@vercel/node 2.9.14 → 2.10.0

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.
@@ -12,6 +12,7 @@ const node_fetch_1 = __importDefault(require("node-fetch"));
12
12
  const edge_wasm_plugin_1 = require("./edge-wasm-plugin");
13
13
  const utils_1 = require("../utils");
14
14
  const fs_1 = require("fs");
15
+ const edge_node_compat_plugin_1 = require("./edge-node-compat-plugin");
15
16
  const NODE_VERSION_MAJOR = process.version.match(/^v(\d+)\.\d+/)?.[1];
16
17
  const NODE_VERSION_IDENTIFIER = `node${NODE_VERSION_MAJOR}`;
17
18
  if (!NODE_VERSION_MAJOR) {
@@ -30,6 +31,7 @@ async function serializeRequest(message) {
30
31
  }
31
32
  async function compileUserCode(entrypointFullPath, entrypointRelativePath, isMiddleware) {
32
33
  const { wasmAssets, plugin: edgeWasmPlugin } = edge_wasm_plugin_1.createEdgeWasmPlugin();
34
+ const nodeCompatPlugin = edge_node_compat_plugin_1.createNodeCompatPlugin();
33
35
  try {
34
36
  const result = await esbuild_1.default.build({
35
37
  // bundling behavior: use globals (like "browser") instead
@@ -41,7 +43,7 @@ async function compileUserCode(entrypointFullPath, entrypointRelativePath, isMid
41
43
  sourcemap: 'inline',
42
44
  legalComments: 'none',
43
45
  bundle: true,
44
- plugins: [edgeWasmPlugin],
46
+ plugins: [edgeWasmPlugin, nodeCompatPlugin.plugin],
45
47
  entryPoints: [entrypointFullPath],
46
48
  write: false,
47
49
  format: 'cjs',
@@ -79,7 +81,11 @@ async function compileUserCode(entrypointFullPath, entrypointRelativePath, isMid
79
81
  };
80
82
  registerFetchListener(userEdgeHandler, options, dependencies);
81
83
  `;
82
- return { userCode, wasmAssets };
84
+ return {
85
+ userCode,
86
+ wasmAssets,
87
+ nodeCompatBindings: nodeCompatPlugin.bindings,
88
+ };
83
89
  }
84
90
  catch (error) {
85
91
  // We can't easily show a meaningful stack trace from ncc -> edge-runtime.
@@ -95,6 +101,7 @@ async function createEdgeRuntime(params) {
95
101
  return undefined;
96
102
  }
97
103
  const wasmBindings = await params.wasmAssets.getContext();
104
+ const nodeCompatBindings = params.nodeCompatBindings.getContext();
98
105
  const edgeRuntime = new edge_runtime_1.EdgeRuntime({
99
106
  initialCode: params.userCode,
100
107
  extend: (context) => {
@@ -107,6 +114,8 @@ async function createEdgeRuntime(params) {
107
114
  process: {
108
115
  env: process.env,
109
116
  },
117
+ // These are the global bindings for Node.js compatibility
118
+ ...nodeCompatBindings,
110
119
  // These are the global bindings for WebAssembly module
111
120
  ...wasmBindings,
112
121
  });
@@ -0,0 +1,15 @@
1
+ import type { Plugin } from 'esbuild';
2
+ export declare class NodeCompatBindings {
3
+ private bindings;
4
+ use(modulePath: `node:${string}`): string;
5
+ getContext(): Record<string, unknown>;
6
+ }
7
+ /**
8
+ * Allows to enable Node.js compatibility by detecting namespaced `node:`
9
+ * imports and producing metadata to bind global variables for each.
10
+ * It requires from the consumer to add the imports.
11
+ */
12
+ export declare function createNodeCompatPlugin(): {
13
+ plugin: Plugin;
14
+ bindings: NodeCompatBindings;
15
+ };
@@ -0,0 +1,148 @@
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.createNodeCompatPlugin = exports.NodeCompatBindings = void 0;
7
+ const buffer_1 = __importDefault(require("buffer"));
8
+ const events_1 = __importDefault(require("events"));
9
+ const async_hooks_1 = __importDefault(require("async_hooks"));
10
+ const assert_1 = __importDefault(require("assert"));
11
+ const util_1 = __importDefault(require("util"));
12
+ const SUPPORTED_NODE_MODULES = [
13
+ 'buffer',
14
+ 'events',
15
+ 'assert',
16
+ 'util',
17
+ 'async_hooks',
18
+ ];
19
+ const getSupportedNodeModuleRegex = () => new RegExp(`^(?:node:)?(?:${SUPPORTED_NODE_MODULES.join('|')})$`);
20
+ function pick(obj, keys) {
21
+ const res = {};
22
+ for (const key of keys) {
23
+ res[key] = obj[key];
24
+ }
25
+ return res;
26
+ }
27
+ const NativeModuleMap = () => {
28
+ const mods = {
29
+ buffer: pick(buffer_1.default, [
30
+ 'constants',
31
+ 'kMaxLength',
32
+ 'kStringMaxLength',
33
+ 'Buffer',
34
+ 'SlowBuffer',
35
+ ]),
36
+ events: pick(events_1.default, [
37
+ 'EventEmitter',
38
+ 'captureRejectionSymbol',
39
+ 'defaultMaxListeners',
40
+ 'errorMonitor',
41
+ 'listenerCount',
42
+ 'on',
43
+ 'once',
44
+ ]),
45
+ async_hooks: pick(async_hooks_1.default, [
46
+ 'AsyncLocalStorage',
47
+ 'AsyncResource',
48
+ ]),
49
+ assert: pick(assert_1.default, [
50
+ 'AssertionError',
51
+ 'deepEqual',
52
+ 'deepStrictEqual',
53
+ 'doesNotMatch',
54
+ 'doesNotReject',
55
+ 'doesNotThrow',
56
+ 'equal',
57
+ 'fail',
58
+ 'ifError',
59
+ 'match',
60
+ 'notDeepEqual',
61
+ 'notDeepStrictEqual',
62
+ 'notEqual',
63
+ 'notStrictEqual',
64
+ 'ok',
65
+ 'rejects',
66
+ 'strict',
67
+ 'strictEqual',
68
+ 'throws',
69
+ ]),
70
+ util: pick(util_1.default, [
71
+ '_extend',
72
+ 'callbackify',
73
+ 'format',
74
+ 'inherits',
75
+ 'promisify',
76
+ 'types',
77
+ ]),
78
+ };
79
+ return new Map(Object.entries(mods));
80
+ };
81
+ const NODE_COMPAT_NAMESPACE = 'vercel-node-compat';
82
+ class NodeCompatBindings {
83
+ constructor() {
84
+ this.bindings = new Map();
85
+ }
86
+ use(modulePath) {
87
+ const stripped = modulePath.replace(/^node:/, '');
88
+ const name = `__vc_node_${stripped}__`;
89
+ if (!this.bindings.has(modulePath)) {
90
+ const value = NativeModuleMap().get(stripped);
91
+ if (value === undefined) {
92
+ throw new Error(`Could not find module ${modulePath}`);
93
+ }
94
+ this.bindings.set(modulePath, {
95
+ modulePath: modulePath,
96
+ name,
97
+ value,
98
+ });
99
+ }
100
+ return name;
101
+ }
102
+ getContext() {
103
+ const context = {};
104
+ for (const binding of this.bindings.values()) {
105
+ context[binding.name] = binding.value;
106
+ }
107
+ return context;
108
+ }
109
+ }
110
+ exports.NodeCompatBindings = NodeCompatBindings;
111
+ /**
112
+ * Allows to enable Node.js compatibility by detecting namespaced `node:`
113
+ * imports and producing metadata to bind global variables for each.
114
+ * It requires from the consumer to add the imports.
115
+ */
116
+ function createNodeCompatPlugin() {
117
+ const bindings = new NodeCompatBindings();
118
+ const plugin = {
119
+ name: 'vc-node-compat',
120
+ setup(b) {
121
+ b.onResolve({ filter: getSupportedNodeModuleRegex() }, async (args) => {
122
+ const importee = args.path.replace('node:', '');
123
+ if (!SUPPORTED_NODE_MODULES.includes(importee)) {
124
+ return;
125
+ }
126
+ return {
127
+ namespace: NODE_COMPAT_NAMESPACE,
128
+ path: args.path,
129
+ };
130
+ });
131
+ b.onLoad({ filter: /.+/, namespace: NODE_COMPAT_NAMESPACE }, async (args) => {
132
+ const fullName = args.path.startsWith('node:')
133
+ ? args.path
134
+ : `node:${args.path}`;
135
+ const globalName = bindings.use(fullName);
136
+ return {
137
+ contents: `module.exports = ${globalName};`,
138
+ loader: 'js',
139
+ };
140
+ });
141
+ },
142
+ };
143
+ return {
144
+ plugin,
145
+ bindings,
146
+ };
147
+ }
148
+ exports.createNodeCompatPlugin = createNodeCompatPlugin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/node",
3
- "version": "2.9.14",
3
+ "version": "2.10.0",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -64,5 +64,5 @@
64
64
  "test-listen": "1.1.0",
65
65
  "ts-morph": "12.0.0"
66
66
  },
67
- "gitHead": "ab9915af32e54338845f6ff32340dd0189474c55"
67
+ "gitHead": "6a7fa1526c6652c24350ef4797664a945775cf52"
68
68
  }