@vercel/node 2.2.1-canary.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,8 +68,19 @@ const exit_hook_1 = __importDefault(require("exit-hook"));
68
68
  const edge_runtime_1 = require("edge-runtime");
69
69
  const static_config_1 = require("@vercel/static-config");
70
70
  const ts_morph_1 = require("ts-morph");
71
- const ncc_1 = __importDefault(require("@vercel/ncc"));
71
+ const esbuild_1 = __importDefault(require("esbuild"));
72
72
  const node_fetch_1 = __importDefault(require("node-fetch"));
73
+ const util_1 = require("util");
74
+ function logError(error) {
75
+ console.error(error.message);
76
+ if (error.stack) {
77
+ // only show the stack trace if debug is enabled
78
+ // because it points to internals, not user code
79
+ const errorPrefixLength = 'Error: '.length;
80
+ const errorMessageLength = errorPrefixLength + error.message.length;
81
+ build_utils_1.debug(error.stack.substring(errorMessageLength + 1));
82
+ }
83
+ }
73
84
  function listen(server, port, host) {
74
85
  return new Promise(resolve => {
75
86
  server.listen(port, host, () => {
@@ -115,81 +126,158 @@ async function serializeRequest(message) {
115
126
  body,
116
127
  });
117
128
  }
118
- async function createEdgeEventHandler(entrypoint) {
119
- const buildResult = await ncc_1.default(entrypoint, { target: 'es2022' });
120
- const userCode = buildResult.code;
121
- const initialCode = `
122
- ${userCode};
129
+ async function compileUserCode(entrypoint) {
130
+ try {
131
+ const result = await esbuild_1.default.build({
132
+ platform: 'node',
133
+ target: 'node14',
134
+ sourcemap: 'inline',
135
+ bundle: true,
136
+ entryPoints: [entrypoint],
137
+ write: false,
138
+ format: 'cjs',
139
+ });
140
+ const compiledFile = result.outputFiles?.[0];
141
+ if (!compiledFile) {
142
+ throw new Error(`Compilation of ${entrypoint} produced no output files.`);
143
+ }
144
+ const userCode = new util_1.TextDecoder().decode(compiledFile.contents);
145
+ return `
146
+ ${userCode};
123
147
 
124
- addEventListener('fetch', async (event) => {
125
- let serializedRequest = await event.request.text();
126
- let requestDetails = JSON.parse(serializedRequest);
148
+ addEventListener('fetch', async (event) => {
149
+ try {
150
+ let serializedRequest = await event.request.text();
151
+ let requestDetails = JSON.parse(serializedRequest);
127
152
 
128
- let body;
153
+ let body;
129
154
 
130
- if (requestDetails.method !== 'GET' && requestDetails.method !== 'HEAD') {
131
- body = Uint8Array.from(atob(requestDetails.body), c => c.charCodeAt(0));
132
- }
155
+ if (requestDetails.method !== 'GET' && requestDetails.method !== 'HEAD') {
156
+ body = Uint8Array.from(atob(requestDetails.body), c => c.charCodeAt(0));
157
+ }
133
158
 
134
- let requestUrl = requestDetails.headers['x-forwarded-proto'] + '://' + requestDetails.headers['x-forwarded-host'] + requestDetails.url;
159
+ let requestUrl = requestDetails.headers['x-forwarded-proto'] + '://' + requestDetails.headers['x-forwarded-host'] + requestDetails.url;
135
160
 
136
- let request = new Request(requestUrl, {
137
- headers: requestDetails.headers,
138
- method: requestDetails.method,
139
- body: body
140
- });
161
+ let request = new Request(requestUrl, {
162
+ headers: requestDetails.headers,
163
+ method: requestDetails.method,
164
+ body: body
165
+ });
141
166
 
142
- event.request = request;
167
+ event.request = request;
143
168
 
144
- let edgeHandler = module.exports.default;
145
- let response = edgeHandler(event.request, event);
146
- return event.respondWith(response);
147
- })`;
148
- const edgeRuntime = new edge_runtime_1.EdgeRuntime({
149
- initialCode,
150
- extend: (context) => {
151
- Object.assign(context, {
152
- __dirname: '',
153
- module: {
154
- exports: {},
155
- },
156
- });
157
- return context;
158
- },
159
- });
160
- const server = await edge_runtime_1.runServer({ runtime: edgeRuntime });
161
- exit_hook_1.default(server.close);
169
+ let edgeHandler = module.exports.default;
170
+ if (!edgeHandler) {
171
+ throw new Error('No default export was found. Add a default export to handle requests.');
172
+ }
173
+
174
+ let response = await edgeHandler(event.request, event);
175
+
176
+ return event.respondWith(response);
177
+ } catch (error) {
178
+ // we can't easily show a meaningful stack trace
179
+ // so, stick to just the error message for now
180
+ event.respondWith(new Response(error.message, {
181
+ status: 500,
182
+ headers: {
183
+ 'x-vercel-failed': 'edge-wrapper'
184
+ }
185
+ }));
186
+ }
187
+ })`;
188
+ }
189
+ catch (error) {
190
+ // We can't easily show a meaningful stack trace from ncc -> edge-runtime.
191
+ // So, stick with just the message for now.
192
+ console.error(`Failed to instantiate edge runtime.`);
193
+ logError(error);
194
+ return undefined;
195
+ }
196
+ }
197
+ async function createEdgeRuntime(userCode) {
198
+ try {
199
+ if (!userCode) {
200
+ return undefined;
201
+ }
202
+ const edgeRuntime = new edge_runtime_1.EdgeRuntime({
203
+ initialCode: userCode,
204
+ extend: (context) => {
205
+ Object.assign(context, {
206
+ __dirname: '',
207
+ module: {
208
+ exports: {},
209
+ },
210
+ });
211
+ return context;
212
+ },
213
+ });
214
+ const server = await edge_runtime_1.runServer({ runtime: edgeRuntime });
215
+ exit_hook_1.default(server.close);
216
+ return server;
217
+ }
218
+ catch (error) {
219
+ // We can't easily show a meaningful stack trace from ncc -> edge-runtime.
220
+ // So, stick with just the message for now.
221
+ console.error('Failed to instantiate edge runtime.');
222
+ logError(error);
223
+ return undefined;
224
+ }
225
+ }
226
+ async function createEdgeEventHandler(entrypoint) {
227
+ const userCode = await compileUserCode(entrypoint);
228
+ const server = await createEdgeRuntime(userCode);
162
229
  return async function (request) {
230
+ if (!server) {
231
+ // this error state is already logged, but we have to wait until here to exit the process
232
+ // this matches the serverless function bridge launcher's behavior when
233
+ // an error is thrown in the function
234
+ process.exit(1);
235
+ }
163
236
  const response = await node_fetch_1.default(server.url, {
237
+ redirect: 'manual',
164
238
  method: 'post',
165
239
  body: await serializeRequest(request),
166
240
  });
241
+ const body = await response.text();
242
+ const isUserError = response.headers.get('x-vercel-failed') === 'edge-wrapper';
243
+ if (isUserError && response.status >= 500) {
244
+ // this error was "unhandled" from the user code's perspective
245
+ console.log(`Unhandled rejection: ${body}`);
246
+ // this matches the serverless function bridge launcher's behavior when
247
+ // an error is thrown in the function
248
+ process.exit(1);
249
+ }
167
250
  return {
168
251
  statusCode: response.status,
169
252
  headers: response.headers.raw(),
170
- body: await response.text(),
253
+ body,
171
254
  encoding: 'utf8',
172
255
  };
173
256
  };
174
257
  }
175
258
  const validRuntimes = ['experimental-edge'];
176
- function parseRuntime(entrypoint) {
259
+ function parseRuntime(entrypoint, entryPointPath) {
177
260
  const project = new ts_morph_1.Project();
178
- const staticConfig = static_config_1.getConfig(project, entrypoint);
261
+ const staticConfig = static_config_1.getConfig(project, entryPointPath);
179
262
  const runtime = staticConfig?.runtime;
180
263
  if (runtime && !validRuntimes.includes(runtime)) {
181
- throw new Error(`Invalid function runtime for "${entrypoint}": ${runtime}`);
264
+ throw new Error(`Invalid function runtime "${runtime}" for "${entrypoint}". Valid runtimes are: ${JSON.stringify(validRuntimes)}`);
182
265
  }
183
266
  return runtime;
184
267
  }
185
- async function createEventHandler(entrypoint, options) {
186
- const runtime = parseRuntime(entrypoint);
187
- if (runtime === 'experimental-edge') {
188
- return createEdgeEventHandler(entrypoint);
268
+ async function createEventHandler(entrypoint, config, options) {
269
+ const entryPointPath = path_1.join(process.cwd(), entrypoint);
270
+ const runtime = parseRuntime(entrypoint, entryPointPath);
271
+ // `middleware.js`/`middleware.ts` file is always run as
272
+ // an Edge Function, otherwise needs to be opted-in via
273
+ // `export const config = { runtime: 'experimental-edge' }`
274
+ if (config.middleware === true || runtime === 'experimental-edge') {
275
+ return createEdgeEventHandler(entryPointPath);
189
276
  }
190
- return createServerlessEventHandler(entrypoint, options);
277
+ return createServerlessEventHandler(entryPointPath, options);
191
278
  }
192
279
  let handleEvent;
280
+ let handlerEventError;
193
281
  async function main() {
194
282
  const config = JSON.parse(process.env.VERCEL_DEV_CONFIG || '{}');
195
283
  delete process.env.VERCEL_DEV_CONFIG;
@@ -198,8 +286,15 @@ async function main() {
198
286
  const shouldAddHelpers = !(config.helpers === false || buildEnv.NODEJS_HELPERS === '0');
199
287
  const proxyServer = http_1.createServer(onDevRequest);
200
288
  await listen(proxyServer, 0, '127.0.0.1');
201
- const entryPointPath = path_1.join(process.cwd(), entrypoint);
202
- handleEvent = await createEventHandler(entryPointPath, { shouldAddHelpers });
289
+ try {
290
+ handleEvent = await createEventHandler(entrypoint, config, {
291
+ shouldAddHelpers,
292
+ });
293
+ }
294
+ catch (error) {
295
+ logError(error);
296
+ handlerEventError = error;
297
+ }
203
298
  const address = proxyServer.address();
204
299
  if (typeof process.send === 'function') {
205
300
  process.send(address);
@@ -224,6 +319,12 @@ function rawBody(readable) {
224
319
  }
225
320
  exports.rawBody = rawBody;
226
321
  async function onDevRequest(req, res) {
322
+ if (handlerEventError) {
323
+ // this error state is already logged, but we have to wait until here to exit the process
324
+ // this matches the serverless function bridge launcher's behavior when
325
+ // an error is thrown in the function
326
+ process.exit(1);
327
+ }
227
328
  if (!handleEvent) {
228
329
  res.statusCode = 500;
229
330
  res.end('Bridge is not ready, please try again');
@@ -259,6 +360,6 @@ function fixConfigDev(config) {
259
360
  }
260
361
  exports.fixConfigDev = fixConfigDev;
261
362
  main().catch(err => {
262
- console.error(err);
363
+ logError(err);
263
364
  process.exit(1);
264
365
  });
package/dist/index.js CHANGED
@@ -296058,6 +296058,423 @@ module.exports = {
296058
296058
  }
296059
296059
 
296060
296060
 
296061
+ /***/ }),
296062
+
296063
+ /***/ 91786:
296064
+ /***/ ((__unused_webpack_module, exports) => {
296065
+
296066
+ "use strict";
296067
+
296068
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
296069
+ exports.pathToRegexp = exports.tokensToRegexp = exports.regexpToFunction = exports.match = exports.tokensToFunction = exports.compile = exports.parse = void 0;
296070
+ /**
296071
+ * Tokenize input string.
296072
+ */
296073
+ function lexer(str) {
296074
+ var tokens = [];
296075
+ var i = 0;
296076
+ while (i < str.length) {
296077
+ var char = str[i];
296078
+ if (char === "*" || char === "+" || char === "?") {
296079
+ tokens.push({ type: "MODIFIER", index: i, value: str[i++] });
296080
+ continue;
296081
+ }
296082
+ if (char === "\\") {
296083
+ tokens.push({ type: "ESCAPED_CHAR", index: i++, value: str[i++] });
296084
+ continue;
296085
+ }
296086
+ if (char === "{") {
296087
+ tokens.push({ type: "OPEN", index: i, value: str[i++] });
296088
+ continue;
296089
+ }
296090
+ if (char === "}") {
296091
+ tokens.push({ type: "CLOSE", index: i, value: str[i++] });
296092
+ continue;
296093
+ }
296094
+ if (char === ":") {
296095
+ var name = "";
296096
+ var j = i + 1;
296097
+ while (j < str.length) {
296098
+ var code = str.charCodeAt(j);
296099
+ if (
296100
+ // `0-9`
296101
+ (code >= 48 && code <= 57) ||
296102
+ // `A-Z`
296103
+ (code >= 65 && code <= 90) ||
296104
+ // `a-z`
296105
+ (code >= 97 && code <= 122) ||
296106
+ // `_`
296107
+ code === 95) {
296108
+ name += str[j++];
296109
+ continue;
296110
+ }
296111
+ break;
296112
+ }
296113
+ if (!name)
296114
+ throw new TypeError("Missing parameter name at ".concat(i));
296115
+ tokens.push({ type: "NAME", index: i, value: name });
296116
+ i = j;
296117
+ continue;
296118
+ }
296119
+ if (char === "(") {
296120
+ var count = 1;
296121
+ var pattern = "";
296122
+ var j = i + 1;
296123
+ if (str[j] === "?") {
296124
+ throw new TypeError("Pattern cannot start with \"?\" at ".concat(j));
296125
+ }
296126
+ while (j < str.length) {
296127
+ if (str[j] === "\\") {
296128
+ pattern += str[j++] + str[j++];
296129
+ continue;
296130
+ }
296131
+ if (str[j] === ")") {
296132
+ count--;
296133
+ if (count === 0) {
296134
+ j++;
296135
+ break;
296136
+ }
296137
+ }
296138
+ else if (str[j] === "(") {
296139
+ count++;
296140
+ if (str[j + 1] !== "?") {
296141
+ throw new TypeError("Capturing groups are not allowed at ".concat(j));
296142
+ }
296143
+ }
296144
+ pattern += str[j++];
296145
+ }
296146
+ if (count)
296147
+ throw new TypeError("Unbalanced pattern at ".concat(i));
296148
+ if (!pattern)
296149
+ throw new TypeError("Missing pattern at ".concat(i));
296150
+ tokens.push({ type: "PATTERN", index: i, value: pattern });
296151
+ i = j;
296152
+ continue;
296153
+ }
296154
+ tokens.push({ type: "CHAR", index: i, value: str[i++] });
296155
+ }
296156
+ tokens.push({ type: "END", index: i, value: "" });
296157
+ return tokens;
296158
+ }
296159
+ /**
296160
+ * Parse a string for the raw tokens.
296161
+ */
296162
+ function parse(str, options) {
296163
+ if (options === void 0) { options = {}; }
296164
+ var tokens = lexer(str);
296165
+ var _a = options.prefixes, prefixes = _a === void 0 ? "./" : _a;
296166
+ var defaultPattern = "[^".concat(escapeString(options.delimiter || "/#?"), "]+?");
296167
+ var result = [];
296168
+ var key = 0;
296169
+ var i = 0;
296170
+ var path = "";
296171
+ var tryConsume = function (type) {
296172
+ if (i < tokens.length && tokens[i].type === type)
296173
+ return tokens[i++].value;
296174
+ };
296175
+ var mustConsume = function (type) {
296176
+ var value = tryConsume(type);
296177
+ if (value !== undefined)
296178
+ return value;
296179
+ var _a = tokens[i], nextType = _a.type, index = _a.index;
296180
+ throw new TypeError("Unexpected ".concat(nextType, " at ").concat(index, ", expected ").concat(type));
296181
+ };
296182
+ var consumeText = function () {
296183
+ var result = "";
296184
+ var value;
296185
+ while ((value = tryConsume("CHAR") || tryConsume("ESCAPED_CHAR"))) {
296186
+ result += value;
296187
+ }
296188
+ return result;
296189
+ };
296190
+ while (i < tokens.length) {
296191
+ var char = tryConsume("CHAR");
296192
+ var name = tryConsume("NAME");
296193
+ var pattern = tryConsume("PATTERN");
296194
+ if (name || pattern) {
296195
+ var prefix = char || "";
296196
+ if (prefixes.indexOf(prefix) === -1) {
296197
+ path += prefix;
296198
+ prefix = "";
296199
+ }
296200
+ if (path) {
296201
+ result.push(path);
296202
+ path = "";
296203
+ }
296204
+ result.push({
296205
+ name: name || key++,
296206
+ prefix: prefix,
296207
+ suffix: "",
296208
+ pattern: pattern || defaultPattern,
296209
+ modifier: tryConsume("MODIFIER") || "",
296210
+ });
296211
+ continue;
296212
+ }
296213
+ var value = char || tryConsume("ESCAPED_CHAR");
296214
+ if (value) {
296215
+ path += value;
296216
+ continue;
296217
+ }
296218
+ if (path) {
296219
+ result.push(path);
296220
+ path = "";
296221
+ }
296222
+ var open = tryConsume("OPEN");
296223
+ if (open) {
296224
+ var prefix = consumeText();
296225
+ var name_1 = tryConsume("NAME") || "";
296226
+ var pattern_1 = tryConsume("PATTERN") || "";
296227
+ var suffix = consumeText();
296228
+ mustConsume("CLOSE");
296229
+ result.push({
296230
+ name: name_1 || (pattern_1 ? key++ : ""),
296231
+ pattern: name_1 && !pattern_1 ? defaultPattern : pattern_1,
296232
+ prefix: prefix,
296233
+ suffix: suffix,
296234
+ modifier: tryConsume("MODIFIER") || "",
296235
+ });
296236
+ continue;
296237
+ }
296238
+ mustConsume("END");
296239
+ }
296240
+ return result;
296241
+ }
296242
+ exports.parse = parse;
296243
+ /**
296244
+ * Compile a string to a template function for the path.
296245
+ */
296246
+ function compile(str, options) {
296247
+ return tokensToFunction(parse(str, options), options);
296248
+ }
296249
+ exports.compile = compile;
296250
+ /**
296251
+ * Expose a method for transforming tokens into the path function.
296252
+ */
296253
+ function tokensToFunction(tokens, options) {
296254
+ if (options === void 0) { options = {}; }
296255
+ var reFlags = flags(options);
296256
+ var _a = options.encode, encode = _a === void 0 ? function (x) { return x; } : _a, _b = options.validate, validate = _b === void 0 ? true : _b;
296257
+ // Compile all the tokens into regexps.
296258
+ var matches = tokens.map(function (token) {
296259
+ if (typeof token === "object") {
296260
+ return new RegExp("^(?:".concat(token.pattern, ")$"), reFlags);
296261
+ }
296262
+ });
296263
+ return function (data) {
296264
+ var path = "";
296265
+ for (var i = 0; i < tokens.length; i++) {
296266
+ var token = tokens[i];
296267
+ if (typeof token === "string") {
296268
+ path += token;
296269
+ continue;
296270
+ }
296271
+ var value = data ? data[token.name] : undefined;
296272
+ var optional = token.modifier === "?" || token.modifier === "*";
296273
+ var repeat = token.modifier === "*" || token.modifier === "+";
296274
+ if (Array.isArray(value)) {
296275
+ if (!repeat) {
296276
+ throw new TypeError("Expected \"".concat(token.name, "\" to not repeat, but got an array"));
296277
+ }
296278
+ if (value.length === 0) {
296279
+ if (optional)
296280
+ continue;
296281
+ throw new TypeError("Expected \"".concat(token.name, "\" to not be empty"));
296282
+ }
296283
+ for (var j = 0; j < value.length; j++) {
296284
+ var segment = encode(value[j], token);
296285
+ if (validate && !matches[i].test(segment)) {
296286
+ throw new TypeError("Expected all \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
296287
+ }
296288
+ path += token.prefix + segment + token.suffix;
296289
+ }
296290
+ continue;
296291
+ }
296292
+ if (typeof value === "string" || typeof value === "number") {
296293
+ var segment = encode(String(value), token);
296294
+ if (validate && !matches[i].test(segment)) {
296295
+ throw new TypeError("Expected \"".concat(token.name, "\" to match \"").concat(token.pattern, "\", but got \"").concat(segment, "\""));
296296
+ }
296297
+ path += token.prefix + segment + token.suffix;
296298
+ continue;
296299
+ }
296300
+ if (optional)
296301
+ continue;
296302
+ var typeOfMessage = repeat ? "an array" : "a string";
296303
+ throw new TypeError("Expected \"".concat(token.name, "\" to be ").concat(typeOfMessage));
296304
+ }
296305
+ return path;
296306
+ };
296307
+ }
296308
+ exports.tokensToFunction = tokensToFunction;
296309
+ /**
296310
+ * Create path match function from `path-to-regexp` spec.
296311
+ */
296312
+ function match(str, options) {
296313
+ var keys = [];
296314
+ var re = pathToRegexp(str, keys, options);
296315
+ return regexpToFunction(re, keys, options);
296316
+ }
296317
+ exports.match = match;
296318
+ /**
296319
+ * Create a path match function from `path-to-regexp` output.
296320
+ */
296321
+ function regexpToFunction(re, keys, options) {
296322
+ if (options === void 0) { options = {}; }
296323
+ var _a = options.decode, decode = _a === void 0 ? function (x) { return x; } : _a;
296324
+ return function (pathname) {
296325
+ var m = re.exec(pathname);
296326
+ if (!m)
296327
+ return false;
296328
+ var path = m[0], index = m.index;
296329
+ var params = Object.create(null);
296330
+ var _loop_1 = function (i) {
296331
+ if (m[i] === undefined)
296332
+ return "continue";
296333
+ var key = keys[i - 1];
296334
+ if (key.modifier === "*" || key.modifier === "+") {
296335
+ params[key.name] = m[i].split(key.prefix + key.suffix).map(function (value) {
296336
+ return decode(value, key);
296337
+ });
296338
+ }
296339
+ else {
296340
+ params[key.name] = decode(m[i], key);
296341
+ }
296342
+ };
296343
+ for (var i = 1; i < m.length; i++) {
296344
+ _loop_1(i);
296345
+ }
296346
+ return { path: path, index: index, params: params };
296347
+ };
296348
+ }
296349
+ exports.regexpToFunction = regexpToFunction;
296350
+ /**
296351
+ * Escape a regular expression string.
296352
+ */
296353
+ function escapeString(str) {
296354
+ return str.replace(/([.+*?=^!:${}()[\]|/\\])/g, "\\$1");
296355
+ }
296356
+ /**
296357
+ * Get the flags for a regexp from the options.
296358
+ */
296359
+ function flags(options) {
296360
+ return options && options.sensitive ? "" : "i";
296361
+ }
296362
+ /**
296363
+ * Pull out keys from a regexp.
296364
+ */
296365
+ function regexpToRegexp(path, keys) {
296366
+ if (!keys)
296367
+ return path;
296368
+ var groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
296369
+ var index = 0;
296370
+ var execResult = groupsRegex.exec(path.source);
296371
+ while (execResult) {
296372
+ keys.push({
296373
+ // Use parenthesized substring match if available, index otherwise
296374
+ name: execResult[1] || index++,
296375
+ prefix: "",
296376
+ suffix: "",
296377
+ modifier: "",
296378
+ pattern: "",
296379
+ });
296380
+ execResult = groupsRegex.exec(path.source);
296381
+ }
296382
+ return path;
296383
+ }
296384
+ /**
296385
+ * Transform an array into a regexp.
296386
+ */
296387
+ function arrayToRegexp(paths, keys, options) {
296388
+ var parts = paths.map(function (path) { return pathToRegexp(path, keys, options).source; });
296389
+ return new RegExp("(?:".concat(parts.join("|"), ")"), flags(options));
296390
+ }
296391
+ /**
296392
+ * Create a path regexp from string input.
296393
+ */
296394
+ function stringToRegexp(path, keys, options) {
296395
+ return tokensToRegexp(parse(path, options), keys, options);
296396
+ }
296397
+ /**
296398
+ * Expose a function for taking tokens and returning a RegExp.
296399
+ */
296400
+ function tokensToRegexp(tokens, keys, options) {
296401
+ if (options === void 0) { options = {}; }
296402
+ var _a = options.strict, strict = _a === void 0 ? false : _a, _b = options.start, start = _b === void 0 ? true : _b, _c = options.end, end = _c === void 0 ? true : _c, _d = options.encode, encode = _d === void 0 ? function (x) { return x; } : _d, _e = options.delimiter, delimiter = _e === void 0 ? "/#?" : _e, _f = options.endsWith, endsWith = _f === void 0 ? "" : _f;
296403
+ var endsWithRe = "[".concat(escapeString(endsWith), "]|$");
296404
+ var delimiterRe = "[".concat(escapeString(delimiter), "]");
296405
+ var route = start ? "^" : "";
296406
+ // Iterate over the tokens and create our regexp string.
296407
+ for (var _i = 0, tokens_1 = tokens; _i < tokens_1.length; _i++) {
296408
+ var token = tokens_1[_i];
296409
+ if (typeof token === "string") {
296410
+ route += escapeString(encode(token));
296411
+ }
296412
+ else {
296413
+ var prefix = escapeString(encode(token.prefix));
296414
+ var suffix = escapeString(encode(token.suffix));
296415
+ if (token.pattern) {
296416
+ if (keys)
296417
+ keys.push(token);
296418
+ if (prefix || suffix) {
296419
+ if (token.modifier === "+" || token.modifier === "*") {
296420
+ var mod = token.modifier === "*" ? "?" : "";
296421
+ route += "(?:".concat(prefix, "((?:").concat(token.pattern, ")(?:").concat(suffix).concat(prefix, "(?:").concat(token.pattern, "))*)").concat(suffix, ")").concat(mod);
296422
+ }
296423
+ else {
296424
+ route += "(?:".concat(prefix, "(").concat(token.pattern, ")").concat(suffix, ")").concat(token.modifier);
296425
+ }
296426
+ }
296427
+ else {
296428
+ if (token.modifier === "+" || token.modifier === "*") {
296429
+ route += "((?:".concat(token.pattern, ")").concat(token.modifier, ")");
296430
+ }
296431
+ else {
296432
+ route += "(".concat(token.pattern, ")").concat(token.modifier);
296433
+ }
296434
+ }
296435
+ }
296436
+ else {
296437
+ route += "(?:".concat(prefix).concat(suffix, ")").concat(token.modifier);
296438
+ }
296439
+ }
296440
+ }
296441
+ if (end) {
296442
+ if (!strict)
296443
+ route += "".concat(delimiterRe, "?");
296444
+ route += !options.endsWith ? "$" : "(?=".concat(endsWithRe, ")");
296445
+ }
296446
+ else {
296447
+ var endToken = tokens[tokens.length - 1];
296448
+ var isEndDelimited = typeof endToken === "string"
296449
+ ? delimiterRe.indexOf(endToken[endToken.length - 1]) > -1
296450
+ : endToken === undefined;
296451
+ if (!strict) {
296452
+ route += "(?:".concat(delimiterRe, "(?=").concat(endsWithRe, "))?");
296453
+ }
296454
+ if (!isEndDelimited) {
296455
+ route += "(?=".concat(delimiterRe, "|").concat(endsWithRe, ")");
296456
+ }
296457
+ }
296458
+ return new RegExp(route, flags(options));
296459
+ }
296460
+ exports.tokensToRegexp = tokensToRegexp;
296461
+ /**
296462
+ * Normalize the given path string, returning a regular expression.
296463
+ *
296464
+ * An empty array can be passed in for the keys, which will hold the
296465
+ * placeholder key descriptions. For example, using `/user/:id`, `keys` will
296466
+ * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
296467
+ */
296468
+ function pathToRegexp(path, keys, options) {
296469
+ if (path instanceof RegExp)
296470
+ return regexpToRegexp(path, keys);
296471
+ if (Array.isArray(path))
296472
+ return arrayToRegexp(path, keys, options);
296473
+ return stringToRegexp(path, keys, options);
296474
+ }
296475
+ exports.pathToRegexp = pathToRegexp;
296476
+ //# sourceMappingURL=index.js.map
296477
+
296061
296478
  /***/ }),
296062
296479
 
296063
296480
  /***/ 92879:
@@ -306526,6 +306943,7 @@ const build_utils_1 = __webpack_require__(63445);
306526
306943
  Object.defineProperty(exports, "shouldServe", ({ enumerable: true, get: function () { return build_utils_1.shouldServe; } }));
306527
306944
  const static_config_1 = __webpack_require__(76849);
306528
306945
  const typescript_1 = __webpack_require__(80774);
306946
+ const utils_1 = __webpack_require__(84411);
306529
306947
  function isPortInfo(v) {
306530
306948
  return v && typeof v.port === 'number';
306531
306949
  }
@@ -306754,33 +307172,37 @@ const build = async ({ files, entrypoint, workPath, repoRootPath, config = {}, m
306754
307172
  const outputName = config.zeroConfig
306755
307173
  ? handler.substring(0, handler.length - 3)
306756
307174
  : handler;
307175
+ const isMiddleware = config.middleware === true;
306757
307176
  // Will output an `EdgeFunction` for when `config.middleware = true`
306758
307177
  // (i.e. for root-level "middleware" file) or if source code contains:
306759
307178
  // `export const config = { runtime: 'experimental-edge' }`
306760
- let isEdgeFunction = false;
306761
- // Add a catch-all `route` for Middleware
306762
- if (config.middleware === true) {
307179
+ let isEdgeFunction = isMiddleware;
307180
+ const project = new ts_morph_1.Project();
307181
+ const staticConfig = static_config_1.getConfig(project, entrypointPath);
307182
+ if (staticConfig?.runtime) {
307183
+ if (!ALLOWED_RUNTIMES.includes(staticConfig.runtime)) {
307184
+ throw new Error(`Unsupported "runtime" property in \`config\`: ${JSON.stringify(staticConfig.runtime)} (must be one of: ${JSON.stringify(ALLOWED_RUNTIMES)})`);
307185
+ }
307186
+ isEdgeFunction = staticConfig.runtime === 'experimental-edge';
307187
+ }
307188
+ // Add a `route` for Middleware
307189
+ if (isMiddleware) {
307190
+ if (!isEdgeFunction) {
307191
+ // Root-level middleware file can not have `export const config = { runtime: 'nodejs' }`
307192
+ throw new Error(`Middleware file can not be a Node.js Serverless Function`);
307193
+ }
307194
+ // Middleware is a catch-all for all paths unless a `matcher` property is defined
307195
+ const src = utils_1.getRegExpFromMatchers(staticConfig?.matcher);
306763
307196
  routes = [
306764
307197
  {
306765
- src: '/.*',
307198
+ src,
306766
307199
  middlewarePath: config.zeroConfig
306767
307200
  ? outputName
306768
307201
  : path_1.relative(baseDir, entrypointPath),
306769
307202
  continue: true,
307203
+ override: true,
306770
307204
  },
306771
307205
  ];
306772
- // Middleware is implicitly an Edge Function
306773
- isEdgeFunction = true;
306774
- }
306775
- if (!isEdgeFunction) {
306776
- const project = new ts_morph_1.Project();
306777
- const staticConfig = static_config_1.getConfig(project, entrypointPath);
306778
- if (staticConfig?.runtime) {
306779
- if (!ALLOWED_RUNTIMES.includes(staticConfig.runtime)) {
306780
- throw new Error(`Unsupported "runtime" property in \`config\`: ${JSON.stringify(staticConfig.runtime)} (must be one of: ${JSON.stringify(ALLOWED_RUNTIMES)})`);
306781
- }
306782
- isEdgeFunction = staticConfig.runtime === 'experimental-edge';
306783
- }
306784
307206
  }
306785
307207
  if (isEdgeFunction) {
306786
307208
  output = new build_utils_1.EdgeFunction({
@@ -306812,7 +307234,21 @@ const prepareCache = ({ repoRootPath, workPath }) => {
306812
307234
  exports.prepareCache = prepareCache;
306813
307235
  const startDevServer = async (opts) => {
306814
307236
  const { entrypoint, workPath, config, meta = {} } = opts;
306815
- const entryDir = path_1.join(workPath, path_1.dirname(entrypoint));
307237
+ const entrypointPath = path_1.join(workPath, entrypoint);
307238
+ if (config.middleware === true && typeof meta.requestUrl === 'string') {
307239
+ // TODO: static config is also parsed in `dev-server.ts`.
307240
+ // we should pass in this version as an env var instead.
307241
+ const project = new ts_morph_1.Project();
307242
+ const staticConfig = static_config_1.getConfig(project, entrypointPath);
307243
+ // Middleware is a catch-all for all paths unless a `matcher` property is defined
307244
+ const matchers = new RegExp(utils_1.getRegExpFromMatchers(staticConfig?.matcher));
307245
+ if (!matchers.test(meta.requestUrl)) {
307246
+ // If the "matchers" doesn't say to handle this
307247
+ // path then skip middleware invocation
307248
+ return null;
307249
+ }
307250
+ }
307251
+ const entryDir = path_1.dirname(entrypointPath);
306816
307252
  const projectTsConfig = await build_utils_1.walkParentDirs({
306817
307253
  base: workPath,
306818
307254
  start: entryDir,
@@ -306841,6 +307277,9 @@ const startDevServer = async (opts) => {
306841
307277
  },
306842
307278
  });
306843
307279
  const { pid } = child;
307280
+ if (!pid) {
307281
+ throw new Error(`Child Process has no "pid" when forking: "${devServerPath}"`);
307282
+ }
306844
307283
  const onMessage = once_1.default(child, 'message');
306845
307284
  const onExit = once_1.default.spread(child, 'exit');
306846
307285
  const result = await Promise.race([onMessage, onExit]);
@@ -306862,12 +307301,12 @@ const startDevServer = async (opts) => {
306862
307301
  // Got "exit" event from child process
306863
307302
  const [exitCode, signal] = result;
306864
307303
  const reason = signal ? `"${signal}" signal` : `exit code ${exitCode}`;
306865
- throw new Error(`\`node ${entrypoint}\` failed with ${reason}`);
307304
+ throw new Error(`Function \`${entrypoint}\` failed with ${reason}`);
306866
307305
  }
306867
307306
  };
306868
307307
  exports.startDevServer = startDevServer;
306869
307308
  async function doTypeCheck({ entrypoint, workPath, meta = {} }, projectTsConfig) {
306870
- const { devCacheDir = path_1.join(workPath, '.now', 'cache') } = meta;
307309
+ const { devCacheDir = path_1.join(workPath, '.vercel', 'cache') } = meta;
306871
307310
  const entrypointCacheDir = path_1.join(devCacheDir, 'node', entrypoint);
306872
307311
  // In order to type-check a single file, a standalone tsconfig
306873
307312
  // file needs to be created that inherits from the base one :(
@@ -307283,6 +307722,38 @@ function filterDiagnostics(diagnostics, ignore) {
307283
307722
  }
307284
307723
 
307285
307724
 
307725
+ /***/ }),
307726
+
307727
+ /***/ 84411:
307728
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
307729
+
307730
+ "use strict";
307731
+
307732
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
307733
+ exports.getRegExpFromMatchers = void 0;
307734
+ const path_to_regexp_1 = __webpack_require__(91786);
307735
+ function getRegExpFromMatchers(matcherOrMatchers) {
307736
+ if (!matcherOrMatchers) {
307737
+ return '^/.*$';
307738
+ }
307739
+ const matchers = Array.isArray(matcherOrMatchers)
307740
+ ? matcherOrMatchers
307741
+ : [matcherOrMatchers];
307742
+ return matchers.map(getRegExpFromMatcher).join('|');
307743
+ }
307744
+ exports.getRegExpFromMatchers = getRegExpFromMatchers;
307745
+ function getRegExpFromMatcher(matcher) {
307746
+ if (typeof matcher !== 'string') {
307747
+ throw new Error('`matcher` must be a path matcher or an array of path matchers');
307748
+ }
307749
+ if (!matcher.startsWith('/')) {
307750
+ throw new Error('`matcher`: path matcher must start with /');
307751
+ }
307752
+ const re = path_to_regexp_1.pathToRegexp(matcher);
307753
+ return re.source;
307754
+ }
307755
+
307756
+
307286
307757
  /***/ }),
307287
307758
 
307288
307759
  /***/ 80918:
@@ -0,0 +1 @@
1
+ export declare function getRegExpFromMatchers(matcherOrMatchers: unknown): string;
package/dist/utils.js ADDED
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRegExpFromMatchers = void 0;
4
+ const path_to_regexp_1 = require("path-to-regexp");
5
+ function getRegExpFromMatchers(matcherOrMatchers) {
6
+ if (!matcherOrMatchers) {
7
+ return '^/.*$';
8
+ }
9
+ const matchers = Array.isArray(matcherOrMatchers)
10
+ ? matcherOrMatchers
11
+ : [matcherOrMatchers];
12
+ return matchers.map(getRegExpFromMatcher).join('|');
13
+ }
14
+ exports.getRegExpFromMatchers = getRegExpFromMatchers;
15
+ function getRegExpFromMatcher(matcher) {
16
+ if (typeof matcher !== 'string') {
17
+ throw new Error('`matcher` must be a path matcher or an array of path matchers');
18
+ }
19
+ if (!matcher.startsWith('/')) {
20
+ throw new Error('`matcher`: path matcher must start with /');
21
+ }
22
+ const re = path_to_regexp_1.pathToRegexp(matcher);
23
+ return re.source;
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/node",
3
- "version": "2.2.1-canary.0",
3
+ "version": "2.3.1",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -31,11 +31,11 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@types/node": "*",
34
- "@vercel/build-utils": "4.1.1-canary.1",
35
- "@vercel/ncc": "0.24.0",
34
+ "@vercel/build-utils": "4.2.0",
36
35
  "@vercel/node-bridge": "3.0.0",
37
36
  "@vercel/static-config": "2.0.1",
38
37
  "edge-runtime": "1.0.1",
38
+ "esbuild": "0.14.47",
39
39
  "exit-hook": "2.2.1",
40
40
  "node-fetch": "2.6.1",
41
41
  "ts-node": "8.9.1",
@@ -52,12 +52,14 @@
52
52
  "@types/jest": "27.4.1",
53
53
  "@types/node-fetch": "^2.6.1",
54
54
  "@types/test-listen": "1.1.0",
55
+ "@vercel/ncc": "0.24.0",
55
56
  "@vercel/nft": "0.19.1",
56
57
  "content-type": "1.0.4",
57
58
  "cookie": "0.4.0",
58
59
  "etag": "1.8.1",
60
+ "path-to-regexp": "6.2.1",
59
61
  "source-map-support": "0.5.12",
60
62
  "test-listen": "1.1.0"
61
63
  },
62
- "gitHead": "4f8f3d373f4e42fe1afecd16a4cfc4fe57835be7"
64
+ "gitHead": "b399fe7037eb3e4c42167ba28e82c9ce0332f7a0"
63
65
  }