-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
utils.ts
120 lines (107 loc) · 3.21 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import { debug, streamToBuffer } from '@vercel/build-utils';
import { pathToRegexp } from 'path-to-regexp';
import type { IncomingMessage } from 'http';
import { extname } from 'path';
export function getRegExpFromMatchers(matcherOrMatchers: unknown): string {
if (!matcherOrMatchers) {
return '^/.*$';
}
const matchers = Array.isArray(matcherOrMatchers)
? matcherOrMatchers
: [matcherOrMatchers];
const regExps = matchers.flatMap(getRegExpFromMatcher).join('|');
return regExps;
}
function getRegExpFromMatcher(
matcher: unknown,
index: number,
allMatchers: unknown[]
): string[] {
if (typeof matcher !== 'string') {
throw new Error(
"Middleware's `config.matcher` must be a path matcher (string) or an array of path matchers (string[])"
);
}
if (!matcher.startsWith('/')) {
throw new Error(
`Middleware's \`config.matcher\` values must start with "/". Received: ${matcher}`
);
}
const regExps = [pathToRegexp(matcher).source];
if (matcher === '/' && !allMatchers.includes('/index')) {
regExps.push(pathToRegexp('/index').source);
}
return regExps;
}
/**
* If `zeroConfig`:
* "api/foo.js" -> "api/foo.js"
* "api/foo.ts" -> "api/foo.ts"
*
* If *NOT* `zeroConfig`:
* "api/foo.js" -> "api/foo"
* "api/foo.ts" -> "api/foo"
*/
export function entrypointToOutputPath(
entrypoint: string,
zeroConfig?: boolean
): string {
if (zeroConfig) {
const ext = extname(entrypoint);
return entrypoint.slice(0, entrypoint.length - ext.length);
}
return entrypoint;
}
export function logError(error: Error) {
let message = error.message;
if (!message.startsWith('Error:')) {
message = `Error: ${message}`;
}
console.error(message);
if (error.stack) {
// only show the stack trace if debug is enabled
// because it points to internals, not user code
const errorPrefixLength = 'Error: '.length;
const errorMessageLength = errorPrefixLength + error.message.length;
debug(error.stack.substring(errorMessageLength + 1));
}
}
export enum EdgeRuntimes {
Edge = 'edge',
ExperimentalEdge = 'experimental-edge',
}
export function isEdgeRuntime(runtime?: string): runtime is EdgeRuntimes {
return (
runtime !== undefined &&
Object.values(EdgeRuntimes).includes(runtime as EdgeRuntimes)
);
}
const ALLOWED_RUNTIMES: string[] = Object.values(EdgeRuntimes);
export function validateConfiguredRuntime(
runtime: string | undefined,
entrypoint: string
) {
if (runtime) {
if (runtime === 'nodejs') {
throw new Error(
`${entrypoint}: \`config.runtime: "nodejs"\` semantics will evolve soon. Please remove the \`runtime\` key to keep the existing behavior.`
);
}
if (!ALLOWED_RUNTIMES.includes(runtime)) {
throw new Error(
`${entrypoint}: unsupported "runtime" value in \`config\`: ${JSON.stringify(
runtime
)} (must be one of: ${JSON.stringify(
ALLOWED_RUNTIMES
)}). Learn more: https://vercel.link/creating-edge-functions`
);
}
}
}
export async function serializeBody(
request: IncomingMessage
): Promise<Buffer | undefined> {
return request.method !== 'GET' && request.method !== 'HEAD'
? await streamToBuffer(request)
: undefined;
}