@vercel/node 3.0.5 → 3.0.7

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/node",
3
- "version": "3.0.5",
3
+ "version": "3.0.7",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -17,13 +17,14 @@
17
17
  "@edge-runtime/primitives": "3.1.1",
18
18
  "@edge-runtime/vm": "3.1.1",
19
19
  "@types/node": "14.18.33",
20
- "@vercel/build-utils": "7.2.0",
20
+ "@vercel/build-utils": "7.2.2",
21
21
  "@vercel/error-utils": "2.0.1",
22
+ "@vercel/nft": "0.24.2",
22
23
  "@vercel/static-config": "3.0.0",
23
24
  "async-listen": "3.0.0",
24
- "content-type": "1.0.5",
25
25
  "edge-runtime": "2.5.1",
26
26
  "esbuild": "0.14.47",
27
+ "etag": "1.8.1",
27
28
  "exit-hook": "2.2.1",
28
29
  "node-fetch": "2.6.9",
29
30
  "path-to-regexp": "6.2.1",
@@ -41,20 +42,16 @@
41
42
  "@types/cookie": "0.3.3",
42
43
  "@types/etag": "1.8.0",
43
44
  "@types/jest": "29.5.0",
44
- "@types/test-listen": "1.1.0",
45
- "@vercel/ncc": "0.24.0",
46
- "@vercel/nft": "0.22.5",
45
+ "content-type": "1.0.5",
47
46
  "cookie": "0.4.0",
48
47
  "cross-env": "7.0.3",
49
- "etag": "1.8.1",
50
48
  "execa": "3.2.0",
51
49
  "fs-extra": "11.1.0",
52
50
  "jest-junit": "16.0.0",
53
- "source-map-support": "0.5.12",
54
- "test-listen": "1.1.0"
51
+ "source-map-support": "0.5.12"
55
52
  },
56
53
  "scripts": {
57
- "build": "node build",
54
+ "build": "node build.mjs",
58
55
  "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --env node --verbose --bail --runInBand",
59
56
  "test-unit": "pnpm test test/unit",
60
57
  "test-e2e": "pnpm test test/integration"
package/dist/babel.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compile = void 0;
4
- const babel = require('@babel/core'); // eslint-disable-line @typescript-eslint/no-var-requires
5
- // eslint-disable-next-line @typescript-eslint/no-var-requires
6
- const pluginTransformModulesCommonJs = require('@babel/plugin-transform-modules-commonjs');
7
- function compile(filename, source) {
8
- return babel.transform(source, {
9
- filename,
10
- configFile: false,
11
- babelrc: false,
12
- highlightCode: false,
13
- compact: false,
14
- sourceType: 'module',
15
- sourceMaps: true,
16
- parserOpts: {
17
- plugins: [
18
- 'asyncGenerators',
19
- 'classProperties',
20
- 'classPrivateProperties',
21
- 'classPrivateMethods',
22
- 'optionalCatchBinding',
23
- 'objectRestSpread',
24
- 'numericSeparator',
25
- 'dynamicImport',
26
- 'importMeta',
27
- ],
28
- },
29
- plugins: [pluginTransformModulesCommonJs],
30
- });
31
- }
32
- exports.compile = compile;
@@ -1,175 +0,0 @@
1
- import { createEdgeWasmPlugin } from './edge-wasm-plugin.mjs';
2
- import { createNodeCompatPlugin, } from './edge-node-compat-plugin.mjs';
3
- import { EdgeRuntime, runServer } from 'edge-runtime';
4
- import { fetch, Headers } from 'undici';
5
- import { isError } from '@vercel/error-utils';
6
- import { readFileSync } from 'fs';
7
- import { serializeBody, entrypointToOutputPath, logError } from '../utils.js';
8
- import esbuild from 'esbuild';
9
- import exitHook from 'exit-hook';
10
- import { fileURLToPath } from 'url';
11
- const NODE_VERSION_MAJOR = process.version.match(/^v(\d+)\.\d+/)?.[1];
12
- const NODE_VERSION_IDENTIFIER = `node${NODE_VERSION_MAJOR}`;
13
- if (!NODE_VERSION_MAJOR) {
14
- throw new Error(`Unable to determine current node version: process.version=${process.version}`);
15
- }
16
- const __dirname = fileURLToPath(new URL('.', import.meta.url));
17
- const edgeHandlerTemplate = readFileSync(`${__dirname}/edge-handler-template.js`);
18
- async function compileUserCode(entrypointFullPath, entrypointRelativePath, isMiddleware) {
19
- const { wasmAssets, plugin: edgeWasmPlugin } = createEdgeWasmPlugin();
20
- const nodeCompatPlugin = createNodeCompatPlugin();
21
- try {
22
- const result = await esbuild.build({
23
- // bundling behavior: use globals (like "browser") instead
24
- // of "require" statements for core libraries (like "node")
25
- platform: 'browser',
26
- conditions: ['edge-light', 'development'],
27
- // target syntax: only use syntax available on the current
28
- // version of node
29
- target: NODE_VERSION_IDENTIFIER,
30
- sourcemap: 'inline',
31
- legalComments: 'none',
32
- bundle: true,
33
- plugins: [
34
- edgeWasmPlugin,
35
- nodeCompatPlugin.plugin,
36
- {
37
- name: 'import.meta.url',
38
- setup({ onLoad }) {
39
- onLoad({ filter: /\.[cm]?js$/, namespace: 'file' }, args => {
40
- let code = readFileSync(args.path, 'utf8');
41
- code = code.replace(/\bimport\.meta\.url\b/g, JSON.stringify(import.meta.url));
42
- return { contents: code };
43
- });
44
- },
45
- },
46
- ],
47
- entryPoints: [entrypointFullPath],
48
- write: false,
49
- format: 'cjs',
50
- });
51
- const compiledFile = result.outputFiles?.[0];
52
- if (!compiledFile) {
53
- throw new Error(`Compilation of ${entrypointRelativePath} produced no output files.`);
54
- }
55
- const userCode = `
56
- // strict mode
57
- "use strict";var regeneratorRuntime;
58
-
59
- // user code
60
- (() => {
61
- ${compiledFile.text};
62
- })();
63
-
64
- const userModule = module.exports;
65
-
66
- // request metadata
67
- const isMiddleware = ${isMiddleware};
68
- const entrypointLabel = '${entrypointRelativePath}';
69
-
70
- // edge handler
71
- ${edgeHandlerTemplate};
72
- const dependencies = { Request, Response };
73
- const options = { isMiddleware, entrypointLabel };
74
- registerFetchListener(userModule, options, dependencies);
75
- `;
76
- return {
77
- userCode,
78
- wasmAssets,
79
- nodeCompatBindings: nodeCompatPlugin.bindings,
80
- };
81
- }
82
- catch (error) {
83
- // We can't easily show a meaningful stack trace from ncc -> edge-runtime.
84
- // So, stick with just the message for now.
85
- console.error(`Failed to compile user code for edge runtime.`);
86
- if (isError(error))
87
- logError(error);
88
- return undefined;
89
- }
90
- }
91
- async function createEdgeRuntimeServer(params) {
92
- try {
93
- if (!params) {
94
- return undefined;
95
- }
96
- const wasmBindings = await params.wasmAssets.getContext();
97
- const nodeCompatBindings = params.nodeCompatBindings.getContext();
98
- const runtime = new EdgeRuntime({
99
- initialCode: params.userCode,
100
- extend: context => {
101
- Object.assign(context, {
102
- // This is required for esbuild wrapping logic to resolve
103
- module: {},
104
- // This is required for environment variable access.
105
- // In production, env var access is provided by static analysis
106
- // so that only the used values are available.
107
- process: {
108
- env: process.env,
109
- },
110
- // These are the global bindings for Node.js compatibility
111
- ...nodeCompatBindings,
112
- // These are the global bindings for WebAssembly module
113
- ...wasmBindings,
114
- });
115
- return context;
116
- },
117
- });
118
- const server = await runServer({ runtime });
119
- exitHook(() => server.close());
120
- return server;
121
- }
122
- catch (error) {
123
- // We can't easily show a meaningful stack trace from ncc -> edge-runtime.
124
- // So, stick with just the message for now.
125
- console.error('Failed to instantiate edge runtime.');
126
- logError(error);
127
- return undefined;
128
- }
129
- }
130
- export async function createEdgeEventHandler(entrypointFullPath, entrypointRelativePath, isMiddleware, isZeroConfig) {
131
- const userCode = await compileUserCode(entrypointFullPath, entrypointRelativePath, isMiddleware);
132
- const server = await createEdgeRuntimeServer(userCode);
133
- return async function (request) {
134
- if (!server) {
135
- // this error state is already logged, but we have to wait until here to exit the process
136
- // this matches the serverless function bridge launcher's behavior when
137
- // an error is thrown in the function
138
- process.exit(1);
139
- }
140
- const headers = new Headers(request.headers);
141
- const body = await serializeBody(request);
142
- if (body !== undefined)
143
- headers.set('content-length', String(body.length));
144
- const url = new URL(request.url ?? '/', server.url);
145
- const response = await fetch(url, {
146
- body,
147
- headers,
148
- method: request.method,
149
- redirect: 'manual',
150
- });
151
- const isUserError = response.headers.get('x-vercel-failed') === 'edge-wrapper';
152
- if (isUserError && response.status >= 500) {
153
- const body = await response.text();
154
- // We can't currently get a real stack trace from the Edge Function error,
155
- // but we can fake a basic one that is still usefult to the user.
156
- const fakeStackTrace = ` at (${entrypointRelativePath})`;
157
- const requestPath = entrypointToRequestPath(entrypointRelativePath, isZeroConfig);
158
- console.log(`Error from API Route ${requestPath}: ${body}\n${fakeStackTrace}`);
159
- // this matches the serverless function bridge launcher's behavior when
160
- // an error is thrown in the function
161
- process.exit(1);
162
- }
163
- return {
164
- status: response.status,
165
- headers: response.headers,
166
- body: response.body,
167
- encoding: 'utf8',
168
- };
169
- };
170
- }
171
- function entrypointToRequestPath(entrypointRelativePath, isZeroConfig) {
172
- // ensure the path starts with a slash to match conventions used elsewhere,
173
- // notably when rendering serverless function paths in error messages
174
- return '/' + entrypointToOutputPath(entrypointRelativePath, isZeroConfig);
175
- }
@@ -1,140 +0,0 @@
1
- import BufferImplementation from 'buffer';
2
- import EventsImplementation from 'events';
3
- import AsyncHooksImplementation from 'async_hooks';
4
- import AssertImplementation from 'assert';
5
- import UtilImplementation from 'util';
6
- const SUPPORTED_NODE_MODULES = [
7
- 'buffer',
8
- 'events',
9
- 'assert',
10
- 'util',
11
- 'async_hooks',
12
- ];
13
- const getSupportedNodeModuleRegex = () => new RegExp(`^(?:node:)?(?:${SUPPORTED_NODE_MODULES.join('|')})$`);
14
- function pick(obj, keys) {
15
- const res = {};
16
- for (const key of keys) {
17
- res[key] = obj[key];
18
- }
19
- return res;
20
- }
21
- const NativeModuleMap = () => {
22
- const mods = {
23
- buffer: pick(BufferImplementation, [
24
- 'constants',
25
- 'kMaxLength',
26
- 'kStringMaxLength',
27
- 'Buffer',
28
- 'SlowBuffer',
29
- ]),
30
- events: pick(EventsImplementation, [
31
- 'EventEmitter',
32
- 'captureRejectionSymbol',
33
- 'defaultMaxListeners',
34
- 'errorMonitor',
35
- 'listenerCount',
36
- 'on',
37
- 'once',
38
- ]),
39
- async_hooks: pick(AsyncHooksImplementation, [
40
- 'AsyncLocalStorage',
41
- 'AsyncResource',
42
- ]),
43
- assert: pick(AssertImplementation, [
44
- 'AssertionError',
45
- 'deepEqual',
46
- 'deepStrictEqual',
47
- 'doesNotMatch',
48
- 'doesNotReject',
49
- 'doesNotThrow',
50
- 'equal',
51
- 'fail',
52
- 'ifError',
53
- 'match',
54
- 'notDeepEqual',
55
- 'notDeepStrictEqual',
56
- 'notEqual',
57
- 'notStrictEqual',
58
- 'ok',
59
- 'rejects',
60
- 'strict',
61
- 'strictEqual',
62
- 'throws',
63
- ]),
64
- util: pick(UtilImplementation, [
65
- '_extend',
66
- 'callbackify',
67
- 'format',
68
- 'inherits',
69
- 'promisify',
70
- 'types',
71
- ]),
72
- };
73
- return new Map(Object.entries(mods));
74
- };
75
- const NODE_COMPAT_NAMESPACE = 'vercel-node-compat';
76
- export class NodeCompatBindings {
77
- constructor() {
78
- this.bindings = new Map();
79
- }
80
- use(modulePath) {
81
- const stripped = modulePath.replace(/^node:/, '');
82
- const name = `__vc_node_${stripped}__`;
83
- if (!this.bindings.has(modulePath)) {
84
- const value = NativeModuleMap().get(stripped);
85
- if (value === undefined) {
86
- throw new Error(`Could not find module ${modulePath}`);
87
- }
88
- this.bindings.set(modulePath, {
89
- modulePath: modulePath,
90
- name,
91
- value,
92
- });
93
- }
94
- return name;
95
- }
96
- getContext() {
97
- const context = {};
98
- for (const binding of this.bindings.values()) {
99
- context[binding.name] = binding.value;
100
- }
101
- return context;
102
- }
103
- }
104
- /**
105
- * Allows to enable Node.js compatibility by detecting namespaced `node:`
106
- * imports and producing metadata to bind global variables for each.
107
- * It requires from the consumer to add the imports.
108
- */
109
- export function createNodeCompatPlugin() {
110
- const bindings = new NodeCompatBindings();
111
- const plugin = {
112
- name: 'vc-node-compat',
113
- setup(b) {
114
- b.onResolve({ filter: getSupportedNodeModuleRegex() }, async (args) => {
115
- const importee = args.path.replace('node:', '');
116
- if (!SUPPORTED_NODE_MODULES.includes(importee)) {
117
- return;
118
- }
119
- return {
120
- namespace: NODE_COMPAT_NAMESPACE,
121
- path: args.path,
122
- };
123
- });
124
- b.onLoad({ filter: /.+/, namespace: NODE_COMPAT_NAMESPACE }, async (args) => {
125
- const fullName = args.path.startsWith('node:')
126
- ? args.path
127
- : `node:${args.path}`;
128
- const globalName = bindings.use(fullName);
129
- return {
130
- contents: `module.exports = ${globalName};`,
131
- loader: 'js',
132
- };
133
- });
134
- },
135
- };
136
- return {
137
- plugin,
138
- bindings,
139
- };
140
- }
@@ -1,77 +0,0 @@
1
- // copied from `edge-functions-bridge`:
2
- // https://github.com/vercel/runtimes/blob/c076db9e3ce5635f7c2690396e3d9f791a0fd808/packages/edge-functions-bridge/src/get-edge-function-source.ts#L282-L317
3
- import { createHash } from 'crypto';
4
- import { promises as fs } from 'fs';
5
- export class WasmAssets {
6
- constructor() {
7
- this.assets = new Map();
8
- }
9
- /**
10
- * Declare a WebAssembly binding
11
- */
12
- async declare(filePath) {
13
- const hash = sha1(await fs.readFile(filePath));
14
- const name = `wasm_${hash}`;
15
- this.assets.set(name, filePath);
16
- return name;
17
- }
18
- /**
19
- * Get an object with the context needed to execute the code
20
- * built with the plugin
21
- */
22
- async getContext() {
23
- const promises = [];
24
- const context = {};
25
- for (const [name, filePath] of this.assets) {
26
- promises.push((async () => {
27
- const bytes = await fs.readFile(filePath);
28
- context[name] = await WebAssembly.compile(bytes);
29
- })());
30
- }
31
- await Promise.all(promises);
32
- return context;
33
- }
34
- /**
35
- * Allow to iterate easily
36
- */
37
- [Symbol.iterator]() {
38
- return this.assets[Symbol.iterator]();
39
- }
40
- }
41
- export function createEdgeWasmPlugin() {
42
- const wasmAssets = new WasmAssets();
43
- const plugin = {
44
- name: 'vercel-wasm',
45
- setup(b) {
46
- b.onResolve({ filter: /\.wasm\?module/i }, async (data) => {
47
- const wasmFile = data.path.replace(/\?module$/, '');
48
- const resolvedPath = await b.resolve(wasmFile, {
49
- importer: data.importer,
50
- resolveDir: data.resolveDir,
51
- });
52
- if (!resolvedPath.path) {
53
- return {
54
- errors: [
55
- { text: `WebAssembly file could not be located: ${wasmFile}` },
56
- ],
57
- };
58
- }
59
- const name = await wasmAssets.declare(resolvedPath.path);
60
- return {
61
- path: name,
62
- namespace: 'vercel-wasm',
63
- };
64
- });
65
- b.onLoad({ namespace: 'vercel-wasm', filter: /.+/ }, args => {
66
- return {
67
- loader: 'js',
68
- contents: `export default globalThis[${JSON.stringify(args.path)}]`,
69
- };
70
- });
71
- },
72
- };
73
- return { plugin, wasmAssets };
74
- }
75
- function sha1(data) {
76
- return createHash('sha1').update(data).digest('hex');
77
- }
@@ -1,78 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.readMessage = exports.forkDevServer = void 0;
7
- const once_1 = __importDefault(require("@tootallnate/once"));
8
- const build_utils_1 = require("@vercel/build-utils");
9
- const child_process_1 = require("child_process");
10
- const url_1 = require("url");
11
- const path_1 = require("path");
12
- function forkDevServer(options) {
13
- let nodeOptions = process.env.NODE_OPTIONS || '';
14
- if (!nodeOptions.includes('--no-warnings')) {
15
- nodeOptions += ' --no-warnings';
16
- }
17
- const tsNodePath = options.require_.resolve('ts-node');
18
- const esmLoader = (0, url_1.pathToFileURL)((0, path_1.join)(tsNodePath, '..', '..', 'esm.mjs'));
19
- const cjsLoader = (0, path_1.join)(tsNodePath, '..', '..', 'register', 'index.js');
20
- const devServerPath = options.devServerPath || (0, path_1.join)(__dirname, 'dev-server.mjs');
21
- if (options.maybeTranspile) {
22
- if (options.isTypeScript) {
23
- nodeOptions = `--loader ${esmLoader} ${nodeOptions || ''}`;
24
- }
25
- else {
26
- if (options.isEsm) {
27
- // no transform needed because Node.js supports ESM natively
28
- }
29
- else {
30
- nodeOptions = `--require ${cjsLoader} ${nodeOptions || ''}`;
31
- }
32
- }
33
- }
34
- const forkOptions = {
35
- cwd: options.workPath,
36
- execArgv: [],
37
- env: (0, build_utils_1.cloneEnv)(process.env, options.meta.env, {
38
- VERCEL_DEV_ENTRYPOINT: options.entrypoint,
39
- VERCEL_DEV_CONFIG: JSON.stringify(options.config),
40
- VERCEL_DEV_BUILD_ENV: JSON.stringify(options.meta.buildEnv || {}),
41
- TS_NODE_TRANSPILE_ONLY: '1',
42
- TS_NODE_COMPILER_OPTIONS: options.tsConfig?.compilerOptions
43
- ? JSON.stringify(options.tsConfig.compilerOptions)
44
- : undefined,
45
- NODE_OPTIONS: nodeOptions,
46
- }),
47
- };
48
- const child = (0, child_process_1.fork)(devServerPath, [], forkOptions);
49
- checkForPid(devServerPath, child);
50
- return child;
51
- }
52
- exports.forkDevServer = forkDevServer;
53
- function checkForPid(path, process) {
54
- if (!process.pid) {
55
- throw new Error(`Child Process has no "pid" when forking: "${path}"`);
56
- }
57
- }
58
- /**
59
- * When launching a dev-server, we want to know its state.
60
- * This function will be used to know whether it was exited (due to some error),
61
- * or it is listening to new requests, and we can start proxying requests.
62
- */
63
- async function readMessage(child) {
64
- const onMessage = (0, once_1.default)(child, 'message');
65
- const onExit = once_1.default.spread(child, 'close');
66
- const result = await Promise.race([
67
- onMessage.then(x => {
68
- return { state: 'message', value: x };
69
- }),
70
- onExit.then(v => {
71
- return { state: 'exit', value: v };
72
- }),
73
- ]);
74
- onExit.cancel();
75
- onMessage.cancel();
76
- return result;
77
- }
78
- exports.readMessage = readMessage;
@@ -1,7 +0,0 @@
1
- import type { ServerResponse, IncomingMessage } from 'http';
2
- /**
3
- * When users export at least one HTTP handler, we will generate
4
- * a generic handler routing to the right method. If there is no
5
- * handler function exported returns null.
6
- */
7
- export declare function getWebExportsHandler(listener: any, methods: string[]): (req: IncomingMessage, res: ServerResponse) => void;
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getWebExportsHandler = void 0;
4
- const node_utils_1 = require("@edge-runtime/node-utils");
5
- class FetchEvent {
6
- constructor(request) {
7
- this.request = request;
8
- this.response = null;
9
- this.awaiting = new Set();
10
- }
11
- respondWith(response) {
12
- this.response = response;
13
- }
14
- waitUntil() {
15
- throw new Error('waitUntil is not implemented yet for Node.js');
16
- }
17
- }
18
- const webHandlerToNodeHandler = (0, node_utils_1.buildToNodeHandler)({
19
- Headers,
20
- ReadableStream,
21
- // @ts-expect-error Property 'duplex' is missing in type 'Request'
22
- Request: class extends Request {
23
- constructor(input, init) {
24
- super(input, addDuplexToInit(init));
25
- }
26
- },
27
- Uint8Array: Uint8Array,
28
- FetchEvent: FetchEvent,
29
- }, { defaultOrigin: 'https://vercel.com' });
30
- /**
31
- * When users export at least one HTTP handler, we will generate
32
- * a generic handler routing to the right method. If there is no
33
- * handler function exported returns null.
34
- */
35
- function getWebExportsHandler(listener, methods) {
36
- const handlerByMethod = {};
37
- for (const key of methods) {
38
- handlerByMethod[key] =
39
- typeof listener[key] !== 'undefined'
40
- ? webHandlerToNodeHandler(listener[key])
41
- : defaultHttpHandler;
42
- }
43
- return (req, res) => {
44
- const method = req.method ?? 'GET';
45
- handlerByMethod[method](req, res);
46
- };
47
- }
48
- exports.getWebExportsHandler = getWebExportsHandler;
49
- /**
50
- * Add `duplex: 'half'` by default to all requests
51
- * https://github.com/vercel/edge-runtime/blob/bf167c418247a79d3941bfce4a5d43c37f512502/packages/primitives/src/primitives/fetch.js#L22-L26
52
- * https://developer.chrome.com/articles/fetch-streaming-requests/#streaming-request-bodies
53
- */
54
- function addDuplexToInit(init) {
55
- if (typeof init === 'undefined' || typeof init === 'object') {
56
- return { duplex: 'half', ...init };
57
- }
58
- return init;
59
- }
60
- function defaultHttpHandler(_, res) {
61
- res.statusCode = 405;
62
- res.end();
63
- }