@vercel/node 2.4.4 → 2.5.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.
- package/dist/dev-server.js +31 -20
- package/dist/edge-wasm-plugin.d.ts +21 -0
- package/dist/edge-wasm-plugin.js +82 -0
- package/dist/index.js +3183 -2965
- package/package.json +7 -7
package/dist/dev-server.js
CHANGED
@@ -70,7 +70,7 @@ const static_config_1 = require("@vercel/static-config");
|
|
70
70
|
const ts_morph_1 = require("ts-morph");
|
71
71
|
const esbuild_1 = __importDefault(require("esbuild"));
|
72
72
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
73
|
-
const
|
73
|
+
const edge_wasm_plugin_1 = require("./edge-wasm-plugin");
|
74
74
|
function logError(error) {
|
75
75
|
console.error(error.message);
|
76
76
|
if (error.stack) {
|
@@ -126,24 +126,25 @@ async function serializeRequest(message) {
|
|
126
126
|
body,
|
127
127
|
});
|
128
128
|
}
|
129
|
-
async function compileUserCode(
|
129
|
+
async function compileUserCode(entrypointPath, entrypointLabel) {
|
130
|
+
const { wasmAssets, plugin: edgeWasmPlugin } = edge_wasm_plugin_1.createEdgeWasmPlugin();
|
130
131
|
try {
|
131
132
|
const result = await esbuild_1.default.build({
|
132
133
|
platform: 'node',
|
133
134
|
target: 'node14',
|
134
135
|
sourcemap: 'inline',
|
135
136
|
bundle: true,
|
136
|
-
|
137
|
+
plugins: [edgeWasmPlugin],
|
138
|
+
entryPoints: [entrypointPath],
|
137
139
|
write: false,
|
138
140
|
format: 'cjs',
|
139
141
|
});
|
140
142
|
const compiledFile = result.outputFiles?.[0];
|
141
143
|
if (!compiledFile) {
|
142
|
-
throw new Error(`Compilation of ${
|
144
|
+
throw new Error(`Compilation of ${entrypointLabel} produced no output files.`);
|
143
145
|
}
|
144
|
-
const userCode =
|
145
|
-
|
146
|
-
${userCode};
|
146
|
+
const userCode = `
|
147
|
+
${compiledFile.text};
|
147
148
|
|
148
149
|
addEventListener('fetch', async (event) => {
|
149
150
|
try {
|
@@ -173,6 +174,10 @@ async function compileUserCode(entrypoint) {
|
|
173
174
|
|
174
175
|
let response = await edgeHandler(event.request, event);
|
175
176
|
|
177
|
+
if (!response) {
|
178
|
+
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
|
179
|
+
}
|
180
|
+
|
176
181
|
return event.respondWith(response);
|
177
182
|
} catch (error) {
|
178
183
|
// we can't easily show a meaningful stack trace
|
@@ -185,6 +190,7 @@ async function compileUserCode(entrypoint) {
|
|
185
190
|
}));
|
186
191
|
}
|
187
192
|
})`;
|
193
|
+
return { userCode, wasmAssets };
|
188
194
|
}
|
189
195
|
catch (error) {
|
190
196
|
// We can't easily show a meaningful stack trace from ncc -> edge-runtime.
|
@@ -194,20 +200,25 @@ async function compileUserCode(entrypoint) {
|
|
194
200
|
return undefined;
|
195
201
|
}
|
196
202
|
}
|
197
|
-
async function createEdgeRuntime(
|
203
|
+
async function createEdgeRuntime(params) {
|
198
204
|
try {
|
199
|
-
if (!
|
205
|
+
if (!params) {
|
200
206
|
return undefined;
|
201
207
|
}
|
208
|
+
const wasmBindings = await params.wasmAssets.getContext();
|
202
209
|
const edgeRuntime = new edge_runtime_1.EdgeRuntime({
|
203
|
-
initialCode: userCode,
|
210
|
+
initialCode: params.userCode,
|
204
211
|
extend: (context) => {
|
205
212
|
Object.assign(context, {
|
206
|
-
|
207
|
-
module: {
|
208
|
-
|
213
|
+
// This is required for esbuild wrapping logic to resolve
|
214
|
+
module: {},
|
215
|
+
// This is required for environment variable access.
|
216
|
+
// In production, env var access is provided by static analysis
|
217
|
+
// so that only the used values are available.
|
218
|
+
process: {
|
219
|
+
env: process.env,
|
209
220
|
},
|
210
|
-
});
|
221
|
+
}, wasmBindings);
|
211
222
|
return context;
|
212
223
|
},
|
213
224
|
});
|
@@ -223,8 +234,8 @@ async function createEdgeRuntime(userCode) {
|
|
223
234
|
return undefined;
|
224
235
|
}
|
225
236
|
}
|
226
|
-
async function createEdgeEventHandler(
|
227
|
-
const userCode = await compileUserCode(
|
237
|
+
async function createEdgeEventHandler(entrypointPath, entrypointLabel) {
|
238
|
+
const userCode = await compileUserCode(entrypointPath, entrypointLabel);
|
228
239
|
const server = await createEdgeRuntime(userCode);
|
229
240
|
return async function (request) {
|
230
241
|
if (!server) {
|
@@ -266,15 +277,15 @@ function parseRuntime(entrypoint, entryPointPath) {
|
|
266
277
|
return runtime;
|
267
278
|
}
|
268
279
|
async function createEventHandler(entrypoint, config, options) {
|
269
|
-
const
|
270
|
-
const runtime = parseRuntime(entrypoint,
|
280
|
+
const entrypointPath = path_1.join(process.cwd(), entrypoint);
|
281
|
+
const runtime = parseRuntime(entrypoint, entrypointPath);
|
271
282
|
// `middleware.js`/`middleware.ts` file is always run as
|
272
283
|
// an Edge Function, otherwise needs to be opted-in via
|
273
284
|
// `export const config = { runtime: 'experimental-edge' }`
|
274
285
|
if (config.middleware === true || runtime === 'experimental-edge') {
|
275
|
-
return createEdgeEventHandler(
|
286
|
+
return createEdgeEventHandler(entrypointPath, entrypoint);
|
276
287
|
}
|
277
|
-
return createServerlessEventHandler(
|
288
|
+
return createServerlessEventHandler(entrypointPath, options);
|
278
289
|
}
|
279
290
|
let handleEvent;
|
280
291
|
let handlerEventError;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import type { Plugin } from 'esbuild';
|
2
|
+
export declare class WasmAssets {
|
3
|
+
private readonly assets;
|
4
|
+
/**
|
5
|
+
* Declare a WebAssembly binding
|
6
|
+
*/
|
7
|
+
declare(filePath: string): Promise<string>;
|
8
|
+
/**
|
9
|
+
* Get an object with the context needed to execute the code
|
10
|
+
* built with the plugin
|
11
|
+
*/
|
12
|
+
getContext(): Promise<Record<string, WebAssembly.Module>>;
|
13
|
+
/**
|
14
|
+
* Allow to iterate easily
|
15
|
+
*/
|
16
|
+
[Symbol.iterator](): IterableIterator<[string, string]>;
|
17
|
+
}
|
18
|
+
export declare function createEdgeWasmPlugin(): {
|
19
|
+
plugin: Plugin;
|
20
|
+
wasmAssets: WasmAssets;
|
21
|
+
};
|
@@ -0,0 +1,82 @@
|
|
1
|
+
"use strict";
|
2
|
+
// copied from `edge-functions-bridge`:
|
3
|
+
// https://github.com/vercel/runtimes/blob/c076db9e3ce5635f7c2690396e3d9f791a0fd808/packages/edge-functions-bridge/src/get-edge-function-source.ts#L282-L317
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
5
|
+
exports.createEdgeWasmPlugin = exports.WasmAssets = void 0;
|
6
|
+
const crypto_1 = require("crypto");
|
7
|
+
const fs_1 = require("fs");
|
8
|
+
class WasmAssets {
|
9
|
+
constructor() {
|
10
|
+
this.assets = new Map();
|
11
|
+
}
|
12
|
+
/**
|
13
|
+
* Declare a WebAssembly binding
|
14
|
+
*/
|
15
|
+
async declare(filePath) {
|
16
|
+
const hash = sha1(await fs_1.promises.readFile(filePath));
|
17
|
+
const name = `wasm_${hash}`;
|
18
|
+
this.assets.set(name, filePath);
|
19
|
+
return name;
|
20
|
+
}
|
21
|
+
/**
|
22
|
+
* Get an object with the context needed to execute the code
|
23
|
+
* built with the plugin
|
24
|
+
*/
|
25
|
+
async getContext() {
|
26
|
+
const promises = [];
|
27
|
+
const context = {};
|
28
|
+
for (const [name, filePath] of this.assets) {
|
29
|
+
promises.push((async () => {
|
30
|
+
const bytes = await fs_1.promises.readFile(filePath);
|
31
|
+
context[name] = await WebAssembly.compile(bytes);
|
32
|
+
})());
|
33
|
+
}
|
34
|
+
await Promise.all(promises);
|
35
|
+
return context;
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Allow to iterate easily
|
39
|
+
*/
|
40
|
+
[Symbol.iterator]() {
|
41
|
+
return this.assets[Symbol.iterator]();
|
42
|
+
}
|
43
|
+
}
|
44
|
+
exports.WasmAssets = WasmAssets;
|
45
|
+
function createEdgeWasmPlugin() {
|
46
|
+
const wasmAssets = new WasmAssets();
|
47
|
+
const plugin = {
|
48
|
+
name: 'vercel-wasm',
|
49
|
+
setup(b) {
|
50
|
+
b.onResolve({ filter: /\.wasm\?module/i }, async (data) => {
|
51
|
+
const wasmFile = data.path.replace(/\?module$/, '');
|
52
|
+
const resolvedPath = await b.resolve(wasmFile, {
|
53
|
+
importer: data.importer,
|
54
|
+
resolveDir: data.resolveDir,
|
55
|
+
});
|
56
|
+
if (!resolvedPath.path) {
|
57
|
+
return {
|
58
|
+
errors: [
|
59
|
+
{ text: `WebAssembly file could not be located: ${wasmFile}` },
|
60
|
+
],
|
61
|
+
};
|
62
|
+
}
|
63
|
+
const name = await wasmAssets.declare(resolvedPath.path);
|
64
|
+
return {
|
65
|
+
path: name,
|
66
|
+
namespace: 'vercel-wasm',
|
67
|
+
};
|
68
|
+
});
|
69
|
+
b.onLoad({ namespace: 'vercel-wasm', filter: /.+/ }, args => {
|
70
|
+
return {
|
71
|
+
loader: 'js',
|
72
|
+
contents: `export default globalThis[${JSON.stringify(args.path)}]`,
|
73
|
+
};
|
74
|
+
});
|
75
|
+
},
|
76
|
+
};
|
77
|
+
return { plugin, wasmAssets };
|
78
|
+
}
|
79
|
+
exports.createEdgeWasmPlugin = createEdgeWasmPlugin;
|
80
|
+
function sha1(data) {
|
81
|
+
return crypto_1.createHash('sha1').update(data).digest('hex');
|
82
|
+
}
|