@netlify/edge-bundler 12.3.3 → 13.0.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.
- package/deno/lib/common.ts +1 -1
- package/dist/node/bridge.d.ts +5 -3
- package/dist/node/bridge.js +8 -4
- package/dist/node/bundler.test.js +27 -10
- package/dist/node/config.js +5 -2
- package/dist/node/npm_dependencies.d.ts +0 -1
- package/dist/node/npm_dependencies.js +84 -84
- package/dist/node/server/server.d.ts +0 -1
- package/dist/node/server/server.js +2 -4
- package/dist/node/server/server.test.js +5 -6
- package/dist/test/util.js +1 -1
- package/package.json +3 -3
package/deno/lib/common.ts
CHANGED
|
@@ -42,7 +42,7 @@ const loadWithRetry = (specifier: string, delay = 1000, maxTry = 3) => {
|
|
|
42
42
|
maxTry,
|
|
43
43
|
});
|
|
44
44
|
} catch (error) {
|
|
45
|
-
if (isTooManyTries(error)) {
|
|
45
|
+
if (isTooManyTries(error as Error)) {
|
|
46
46
|
console.error(`Loading ${specifier} failed after ${maxTry} tries.`);
|
|
47
47
|
}
|
|
48
48
|
throw error;
|
package/dist/node/bridge.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type WriteStream } from 'fs';
|
|
2
2
|
import { ExecaChildProcess } from 'execa';
|
|
3
3
|
import { Logger } from './logger.js';
|
|
4
|
-
declare const DENO_VERSION_RANGE = "1.39.0 -
|
|
4
|
+
declare const DENO_VERSION_RANGE = "1.39.0 - 2.2.4";
|
|
5
5
|
type OnBeforeDownloadHook = () => void | Promise<void>;
|
|
6
6
|
type OnAfterDownloadHook = (error?: Error) => void | Promise<void>;
|
|
7
7
|
interface DenoOptions {
|
|
@@ -37,14 +37,16 @@ declare class DenoBridge {
|
|
|
37
37
|
versionRange: string;
|
|
38
38
|
constructor(options: DenoOptions);
|
|
39
39
|
private downloadBinary;
|
|
40
|
-
|
|
40
|
+
getBinaryVersion(binaryPath: string): Promise<string | undefined>;
|
|
41
41
|
private getCachedBinary;
|
|
42
42
|
private getGlobalBinary;
|
|
43
43
|
private getRemoteBinary;
|
|
44
44
|
private static runWithBinary;
|
|
45
45
|
private writeVersionFile;
|
|
46
46
|
ensureCacheDirectory(): Promise<void>;
|
|
47
|
-
getBinaryPath(
|
|
47
|
+
getBinaryPath(options?: {
|
|
48
|
+
silent?: boolean;
|
|
49
|
+
}): Promise<{
|
|
48
50
|
global: boolean;
|
|
49
51
|
path: string;
|
|
50
52
|
}>;
|
package/dist/node/bridge.js
CHANGED
|
@@ -12,7 +12,7 @@ const DENO_VERSION_FILE = 'version.txt';
|
|
|
12
12
|
// When updating DENO_VERSION_RANGE, ensure that the deno version
|
|
13
13
|
// on the netlify/buildbot build image satisfies this range!
|
|
14
14
|
// https://github.com/netlify/buildbot/blob/f9c03c9dcb091d6570e9d0778381560d469e78ad/build-image/noble/Dockerfile#L410
|
|
15
|
-
const DENO_VERSION_RANGE = '1.39.0 -
|
|
15
|
+
const DENO_VERSION_RANGE = '1.39.0 - 2.2.4';
|
|
16
16
|
class DenoBridge {
|
|
17
17
|
constructor(options) {
|
|
18
18
|
var _a, _b, _c, _d, _e;
|
|
@@ -119,15 +119,19 @@ class DenoBridge {
|
|
|
119
119
|
async ensureCacheDirectory() {
|
|
120
120
|
await fs.mkdir(this.cacheDirectory, { recursive: true });
|
|
121
121
|
}
|
|
122
|
-
async getBinaryPath() {
|
|
122
|
+
async getBinaryPath(options) {
|
|
123
123
|
const globalPath = await this.getGlobalBinary();
|
|
124
124
|
if (globalPath !== undefined) {
|
|
125
|
-
|
|
125
|
+
if (!(options === null || options === void 0 ? void 0 : options.silent)) {
|
|
126
|
+
this.logger.system('Using global installation of Deno CLI');
|
|
127
|
+
}
|
|
126
128
|
return { global: true, path: globalPath };
|
|
127
129
|
}
|
|
128
130
|
const cachedPath = await this.getCachedBinary();
|
|
129
131
|
if (cachedPath !== undefined) {
|
|
130
|
-
|
|
132
|
+
if (!(options === null || options === void 0 ? void 0 : options.silent)) {
|
|
133
|
+
this.logger.system('Using cached Deno CLI from', cachedPath);
|
|
134
|
+
}
|
|
131
135
|
return { global: false, path: cachedPath };
|
|
132
136
|
}
|
|
133
137
|
const downloadedPath = await this.getRemoteBinary();
|
|
@@ -84,16 +84,11 @@ test('Adds a custom error property to user errors during bundling', async () =>
|
|
|
84
84
|
}
|
|
85
85
|
catch (error) {
|
|
86
86
|
expect(error).toBeInstanceOf(BundleError);
|
|
87
|
-
const
|
|
88
|
-
expect(messageBeforeStack
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
~
|
|
93
|
-
const ret = new Error(getStringFromWasm0(arg0, arg1));
|
|
94
|
-
^
|
|
95
|
-
"
|
|
96
|
-
`);
|
|
87
|
+
const messageBeforeStack = error.message;
|
|
88
|
+
expect(messageBeforeStack
|
|
89
|
+
.replace(/file:\/\/\/(.*?\/)(build\/packages\/edge-bundler\/deno\/vendor\/deno\.land\/x\/eszip.*)/, 'file://$2')
|
|
90
|
+
// eslint-disable-next-line no-control-regex
|
|
91
|
+
.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '')).toMatchSnapshot();
|
|
97
92
|
expect(error.customErrorInfo).toEqual({
|
|
98
93
|
location: {
|
|
99
94
|
format: 'eszip',
|
|
@@ -407,6 +402,28 @@ test('Loads npm modules from bare specifiers', async () => {
|
|
|
407
402
|
await cleanup();
|
|
408
403
|
await rm(vendorDirectory.path, { force: true, recursive: true });
|
|
409
404
|
});
|
|
405
|
+
test('Loads npm modules which use package.json.exports', async () => {
|
|
406
|
+
const { basePath, cleanup, distPath } = await useFixture('imports_npm_module_exports');
|
|
407
|
+
const sourceDirectory = join(basePath, 'functions');
|
|
408
|
+
const declarations = [
|
|
409
|
+
{
|
|
410
|
+
function: 'func1',
|
|
411
|
+
path: '/func1',
|
|
412
|
+
},
|
|
413
|
+
];
|
|
414
|
+
const vendorDirectory = await tmp.dir();
|
|
415
|
+
await bundle([sourceDirectory], distPath, declarations, {
|
|
416
|
+
basePath,
|
|
417
|
+
vendorDirectory: vendorDirectory.path,
|
|
418
|
+
});
|
|
419
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
420
|
+
const manifest = JSON.parse(manifestFile);
|
|
421
|
+
const bundlePath = join(distPath, manifest.bundles[0].asset);
|
|
422
|
+
const { func1 } = await runESZIP(bundlePath, vendorDirectory.path);
|
|
423
|
+
expect(func1).toBe('hello');
|
|
424
|
+
await cleanup();
|
|
425
|
+
await rm(vendorDirectory.path, { force: true, recursive: true });
|
|
426
|
+
});
|
|
410
427
|
test('Loads npm modules in a monorepo setup', async () => {
|
|
411
428
|
const systemLogger = vi.fn();
|
|
412
429
|
const { basePath: rootPath, cleanup, distPath } = await useFixture('monorepo_npm_module');
|
package/dist/node/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
|
+
import { SemVer } from 'semver';
|
|
4
5
|
import tmp from 'tmp-promise';
|
|
5
6
|
import { BundleError } from './bundle_error.js';
|
|
6
7
|
import { getPackagePath } from './package_json.js';
|
|
@@ -39,21 +40,23 @@ export const getFunctionConfig = async ({ func, importMap, deno, log, }) => {
|
|
|
39
40
|
// The extractor will use its exit code to signal different error scenarios,
|
|
40
41
|
// based on the list of exit codes we send as an argument. We then capture
|
|
41
42
|
// the exit code to know exactly what happened and guide people accordingly.
|
|
43
|
+
const version = new SemVer((await deno.getBinaryVersion((await deno.getBinaryPath({ silent: true })).path)) || '');
|
|
42
44
|
const { exitCode, stderr, stdout } = await deno.run([
|
|
43
45
|
'run',
|
|
44
46
|
'--allow-env',
|
|
47
|
+
version.major >= 2 ? '--allow-import' : '',
|
|
45
48
|
'--allow-net',
|
|
46
49
|
'--allow-read',
|
|
47
50
|
`--allow-write=${collector.path}`,
|
|
48
|
-
'--quiet',
|
|
49
51
|
`--import-map=${importMap.toDataURL()}`,
|
|
50
52
|
'--no-config',
|
|
51
53
|
'--node-modules-dir=false',
|
|
54
|
+
'--quiet',
|
|
52
55
|
extractorPath,
|
|
53
56
|
pathToFileURL(func.path).href,
|
|
54
57
|
pathToFileURL(collector.path).href,
|
|
55
58
|
JSON.stringify(ConfigExitCode),
|
|
56
|
-
], { rejectOnExitCode: false });
|
|
59
|
+
].filter(Boolean), { rejectOnExitCode: false });
|
|
57
60
|
if (exitCode !== ConfigExitCode.Success) {
|
|
58
61
|
handleConfigError(func, exitCode, stderr, log);
|
|
59
62
|
return {};
|
|
@@ -3,13 +3,15 @@ import { builtinModules } from 'module';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
5
5
|
import { resolve } from '@import-maps/resolve';
|
|
6
|
-
import { nodeFileTrace, resolve as nftResolve } from '@vercel/nft';
|
|
7
6
|
import { build } from 'esbuild';
|
|
8
7
|
import { findUp } from 'find-up';
|
|
9
|
-
import
|
|
8
|
+
import { parseImports } from 'parse-imports';
|
|
10
9
|
import tmp from 'tmp-promise';
|
|
11
10
|
import { pathsBetween } from './utils/fs.js';
|
|
12
11
|
const TYPESCRIPT_EXTENSIONS = new Set(['.ts', '.tsx', '.cts', '.ctsx', '.mts', '.mtsx']);
|
|
12
|
+
const slugifyFileName = (specifier) => {
|
|
13
|
+
return specifier.replace(/\//g, '_');
|
|
14
|
+
};
|
|
13
15
|
const slugifyPackageName = (specifier) => {
|
|
14
16
|
if (!specifier.startsWith('@'))
|
|
15
17
|
return specifier;
|
|
@@ -55,9 +57,20 @@ const getTypesPath = async (packageJsonPath) => {
|
|
|
55
57
|
}
|
|
56
58
|
return await getTypePathFromTypesPackage(name, packageJsonPath);
|
|
57
59
|
};
|
|
58
|
-
|
|
60
|
+
function packageName(specifier) {
|
|
61
|
+
if (!specifier.startsWith('@'))
|
|
62
|
+
return specifier.split('/')[0];
|
|
63
|
+
const [scope, pkg] = specifier.split('/');
|
|
64
|
+
return `${scope}/${pkg}`;
|
|
65
|
+
}
|
|
66
|
+
const safelyDetectTypes = async (pkg, basePath) => {
|
|
59
67
|
try {
|
|
60
|
-
|
|
68
|
+
const json = await findUp(`node_modules/${packageName(pkg)}/package.json`, {
|
|
69
|
+
cwd: basePath,
|
|
70
|
+
});
|
|
71
|
+
if (json) {
|
|
72
|
+
return await getTypesPath(json);
|
|
73
|
+
}
|
|
61
74
|
}
|
|
62
75
|
catch {
|
|
63
76
|
return undefined;
|
|
@@ -81,92 +94,80 @@ const banner = {
|
|
|
81
94
|
globalThis.Buffer = __nfyBuffer;
|
|
82
95
|
`,
|
|
83
96
|
};
|
|
97
|
+
async function compileTypeScript(file) {
|
|
98
|
+
const compiled = await build({
|
|
99
|
+
bundle: false,
|
|
100
|
+
entryPoints: [file],
|
|
101
|
+
logLevel: 'silent',
|
|
102
|
+
platform: 'node',
|
|
103
|
+
write: false,
|
|
104
|
+
});
|
|
105
|
+
return compiled.outputFiles[0].text;
|
|
106
|
+
}
|
|
107
|
+
async function parseImportsForFile(file, rootPath) {
|
|
108
|
+
const source = TYPESCRIPT_EXTENSIONS.has(path.extname(file))
|
|
109
|
+
? await compileTypeScript(file)
|
|
110
|
+
: await fs.readFile(file, 'utf-8');
|
|
111
|
+
return await parseImports(source, {
|
|
112
|
+
resolveFrom: rootPath,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
84
115
|
/**
|
|
85
116
|
* Parses a set of functions and returns a list of specifiers that correspond
|
|
86
117
|
* to npm modules.
|
|
87
118
|
*/
|
|
88
119
|
const getNPMSpecifiers = async ({ basePath, functions, importMap, environment, rootPath }) => {
|
|
120
|
+
var _a;
|
|
89
121
|
const baseURL = pathToFileURL(basePath);
|
|
90
|
-
const { reasons } = await nodeFileTrace(functions, {
|
|
91
|
-
base: rootPath,
|
|
92
|
-
processCwd: basePath,
|
|
93
|
-
readFile: async (filePath) => {
|
|
94
|
-
// If this is a TypeScript file, we need to compile in before we can
|
|
95
|
-
// parse it.
|
|
96
|
-
if (TYPESCRIPT_EXTENSIONS.has(path.extname(filePath))) {
|
|
97
|
-
const compiled = await build({
|
|
98
|
-
bundle: false,
|
|
99
|
-
entryPoints: [filePath],
|
|
100
|
-
logLevel: 'silent',
|
|
101
|
-
platform: 'node',
|
|
102
|
-
write: false,
|
|
103
|
-
});
|
|
104
|
-
return compiled.outputFiles[0].text;
|
|
105
|
-
}
|
|
106
|
-
return fs.readFile(filePath, 'utf8');
|
|
107
|
-
},
|
|
108
|
-
resolve: async (specifier, ...args) => {
|
|
109
|
-
// Start by checking whether the specifier matches any import map defined
|
|
110
|
-
// by the user.
|
|
111
|
-
const { matched, resolvedImport } = resolve(specifier, importMap, baseURL);
|
|
112
|
-
// If it does, the resolved import is the specifier we'll evaluate going
|
|
113
|
-
// forward.
|
|
114
|
-
if (matched && resolvedImport.protocol === 'file:') {
|
|
115
|
-
const newSpecifier = fileURLToPath(resolvedImport).replace(/\\/g, '/');
|
|
116
|
-
return nftResolve(newSpecifier, ...args);
|
|
117
|
-
}
|
|
118
|
-
return nftResolve(specifier, ...args);
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
122
|
const npmSpecifiers = [];
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const specifier = getPackageName(path);
|
|
133
|
-
if (specifier) {
|
|
134
|
-
npmSpecifiersWithExtraneousFiles.add(specifier);
|
|
123
|
+
for (const func of functions) {
|
|
124
|
+
const imports = await parseImportsForFile(func, rootPath);
|
|
125
|
+
for (const i of imports) {
|
|
126
|
+
// The non-null assertion is required because typescript can not infer that `moduleSpecifier.value` can be narrowed to a string.
|
|
127
|
+
// The narrowing is possible because `moduleSpecifier.value` will always be a string when `moduleSpecifier.isConstant` is true.
|
|
128
|
+
const specifier = i.moduleSpecifier.isConstant ? i.moduleSpecifier.value : i.moduleSpecifier.code;
|
|
129
|
+
switch (i.moduleSpecifier.type) {
|
|
130
|
+
case 'absolute': {
|
|
131
|
+
npmSpecifiers.push(...(await getNPMSpecifiers({ basePath, functions: [specifier], importMap, environment, rootPath })));
|
|
132
|
+
break;
|
|
135
133
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
134
|
+
case 'relative': {
|
|
135
|
+
const filePath = path.join(path.dirname(func), specifier);
|
|
136
|
+
npmSpecifiers.push(...(await getNPMSpecifiers({ basePath, functions: [filePath], importMap, environment, rootPath })));
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case 'package': {
|
|
140
|
+
// node: prefixed imports are detected as packages instead of as builtins
|
|
141
|
+
// we don't want to try and bundle builtins so we ignore node: prefixed imports
|
|
142
|
+
if (specifier.startsWith('node:')) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
const { matched, resolvedImport } = resolve(specifier, importMap, baseURL);
|
|
146
|
+
if (matched) {
|
|
147
|
+
if (resolvedImport.protocol === 'file:') {
|
|
148
|
+
const newSpecifier = fileURLToPath(resolvedImport).replace(/\\/g, '/');
|
|
149
|
+
npmSpecifiers.push(...(await getNPMSpecifiers({ basePath, functions: [newSpecifier], importMap, environment, rootPath })));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else if (!((_a = resolvedImport === null || resolvedImport === void 0 ? void 0 : resolvedImport.protocol) === null || _a === void 0 ? void 0 : _a.startsWith('http'))) {
|
|
153
|
+
const t = await safelyDetectTypes(specifier, basePath);
|
|
154
|
+
npmSpecifiers.push({
|
|
155
|
+
specifier: specifier,
|
|
156
|
+
types: t,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case 'builtin':
|
|
162
|
+
case 'invalid':
|
|
163
|
+
case 'unknown': {
|
|
164
|
+
// We don't bundle these types of modules
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
164
168
|
}
|
|
165
169
|
}
|
|
166
|
-
return
|
|
167
|
-
npmSpecifiers,
|
|
168
|
-
npmSpecifiersWithExtraneousFiles: [...npmSpecifiersWithExtraneousFiles],
|
|
169
|
-
};
|
|
170
|
+
return npmSpecifiers;
|
|
170
171
|
};
|
|
171
172
|
export const vendorNPMSpecifiers = async ({ basePath, directory, functions, importMap, environment, rootPath = basePath, }) => {
|
|
172
173
|
// The directories that esbuild will use when resolving Node modules. We must
|
|
@@ -178,7 +179,7 @@ export const vendorNPMSpecifiers = async ({ basePath, directory, functions, impo
|
|
|
178
179
|
// project directory. If a custom directory has been specified, we use it.
|
|
179
180
|
// Otherwise, create a random temporary directory.
|
|
180
181
|
const temporaryDirectory = directory ? { path: directory } : await tmp.dir();
|
|
181
|
-
const
|
|
182
|
+
const npmSpecifiers = await getNPMSpecifiers({
|
|
182
183
|
basePath,
|
|
183
184
|
functions,
|
|
184
185
|
importMap: importMap.getContentsWithURLObjects(),
|
|
@@ -189,8 +190,8 @@ export const vendorNPMSpecifiers = async ({ basePath, directory, functions, impo
|
|
|
189
190
|
// where we re-export everything from that specifier. We do this for every
|
|
190
191
|
// specifier, and each of these files will become entry points to esbuild.
|
|
191
192
|
const ops = await Promise.all(npmSpecifiers.map(async ({ specifier, types }) => {
|
|
192
|
-
const code = `import * as mod from "${specifier}"
|
|
193
|
-
const filePath = path.join(temporaryDirectory.path, `bundled-${
|
|
193
|
+
const code = `import * as mod from "${specifier}";\nexport default mod.default;\nexport * from "${specifier}";`;
|
|
194
|
+
const filePath = path.join(temporaryDirectory.path, `bundled-${slugifyFileName(specifier)}.js`);
|
|
194
195
|
await fs.writeFile(filePath, code);
|
|
195
196
|
return { filePath, specifier, types };
|
|
196
197
|
}));
|
|
@@ -269,7 +270,6 @@ export const vendorNPMSpecifiers = async ({ basePath, directory, functions, impo
|
|
|
269
270
|
cleanup,
|
|
270
271
|
directory: temporaryDirectory.path,
|
|
271
272
|
importMap: newImportMap,
|
|
272
|
-
npmSpecifiersWithExtraneousFiles,
|
|
273
273
|
outputFiles,
|
|
274
274
|
};
|
|
275
275
|
};
|
|
@@ -39,7 +39,6 @@ export declare const serve: ({ basePath, bootstrapURL, certificatePath, debug, d
|
|
|
39
39
|
features: Record<string, boolean>;
|
|
40
40
|
functionsConfig: FunctionConfig[];
|
|
41
41
|
graph: ModuleGraphJson;
|
|
42
|
-
npmSpecifiersWithExtraneousFiles: string[];
|
|
43
42
|
success: boolean;
|
|
44
43
|
}>>;
|
|
45
44
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readdir, unlink } from 'fs/promises';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
+
import { pathToFileURL } from 'url';
|
|
3
4
|
import { DenoBridge } from '../bridge.js';
|
|
4
5
|
import { getFunctionConfig } from '../config.js';
|
|
5
6
|
import { generateStage2 } from '../formats/javascript.js';
|
|
@@ -41,7 +42,6 @@ const prepareServer = ({ basePath, bootstrapURL, deno, distDirectory, distImport
|
|
|
41
42
|
const features = {};
|
|
42
43
|
const importMap = new ImportMap();
|
|
43
44
|
await importMap.addFiles((_a = options.importMapPaths) !== null && _a !== void 0 ? _a : [], logger);
|
|
44
|
-
const npmSpecifiersWithExtraneousFiles = [];
|
|
45
45
|
// we keep track of the files that are relevant to the user's code, so we can clean up leftovers from past executions later
|
|
46
46
|
const relevantFiles = [stage2Path];
|
|
47
47
|
const vendor = await vendorNPMSpecifiers({
|
|
@@ -56,7 +56,6 @@ const prepareServer = ({ basePath, bootstrapURL, deno, distDirectory, distImport
|
|
|
56
56
|
if (vendor) {
|
|
57
57
|
features.npmModules = true;
|
|
58
58
|
importMap.add(vendor.importMap);
|
|
59
|
-
npmSpecifiersWithExtraneousFiles.push(...vendor.npmSpecifiersWithExtraneousFiles);
|
|
60
59
|
relevantFiles.push(...vendor.outputFiles);
|
|
61
60
|
}
|
|
62
61
|
await cleanDirectory(distDirectory, relevantFiles);
|
|
@@ -65,7 +64,7 @@ const prepareServer = ({ basePath, bootstrapURL, deno, distDirectory, distImport
|
|
|
65
64
|
// the `stage2Path` file as well as all of their dependencies.
|
|
66
65
|
// Consumers such as the CLI can use this information to watch all the
|
|
67
66
|
// relevant files and issue an isolate restart when one of them changes.
|
|
68
|
-
const { stdout } = await deno.run(['info', '--json', stage2Path]);
|
|
67
|
+
const { stdout } = await deno.run(['info', '--json', pathToFileURL(stage2Path).href]);
|
|
69
68
|
graph = JSON.parse(stdout);
|
|
70
69
|
}
|
|
71
70
|
catch {
|
|
@@ -95,7 +94,6 @@ const prepareServer = ({ basePath, bootstrapURL, deno, distDirectory, distImport
|
|
|
95
94
|
features,
|
|
96
95
|
functionsConfig,
|
|
97
96
|
graph,
|
|
98
|
-
npmSpecifiersWithExtraneousFiles,
|
|
99
97
|
success,
|
|
100
98
|
};
|
|
101
99
|
};
|
|
@@ -42,15 +42,15 @@ test('Starts a server and serves requests for edge functions', async () => {
|
|
|
42
42
|
getFunctionsConfig: true,
|
|
43
43
|
importMapPaths,
|
|
44
44
|
};
|
|
45
|
-
const { features, functionsConfig, graph, success
|
|
45
|
+
const { features, functionsConfig, graph, success } = await server(functions, {
|
|
46
46
|
very_secret_secret: 'i love netlify',
|
|
47
47
|
}, options);
|
|
48
48
|
expect(features).toEqual({ npmModules: true });
|
|
49
49
|
expect(success).toBe(true);
|
|
50
50
|
expect(functionsConfig).toEqual([{ path: '/my-function' }, {}, { path: '/global-netlify' }]);
|
|
51
|
-
|
|
51
|
+
const modules = graph === null || graph === void 0 ? void 0 : graph.modules.filter(({ kind, mediaType }) => kind === 'esm' && mediaType === 'TypeScript');
|
|
52
52
|
for (const key in functions) {
|
|
53
|
-
const graphEntry =
|
|
53
|
+
const graphEntry = modules === null || modules === void 0 ? void 0 : modules.some(({ local }) => local === functions[key].path);
|
|
54
54
|
expect(graphEntry).toBe(true);
|
|
55
55
|
}
|
|
56
56
|
const response1 = await fetch(`http://0.0.0.0:${port}/foo`, {
|
|
@@ -84,7 +84,7 @@ test('Starts a server and serves requests for edge functions', async () => {
|
|
|
84
84
|
});
|
|
85
85
|
const idBarrelFile = await readFile(join(servePath, 'bundled-id.js'), 'utf-8');
|
|
86
86
|
expect(idBarrelFile).toContain(`/// <reference types="${join('..', '..', 'node_modules', 'id', 'types.d.ts')}" />`);
|
|
87
|
-
const identidadeBarrelFile = await readFile(join(servePath, 'bundled
|
|
87
|
+
const identidadeBarrelFile = await readFile(join(servePath, 'bundled-@pt-committee_identidade.js'), 'utf-8');
|
|
88
88
|
expect(identidadeBarrelFile).toContain(`/// <reference types="${join('..', '..', 'node_modules', '@types', 'pt-committee__identidade', 'index.d.ts')}" />`);
|
|
89
89
|
});
|
|
90
90
|
test('Serves edge functions in a monorepo setup', async () => {
|
|
@@ -116,13 +116,12 @@ test('Serves edge functions in a monorepo setup', async () => {
|
|
|
116
116
|
getFunctionsConfig: true,
|
|
117
117
|
importMapPaths,
|
|
118
118
|
};
|
|
119
|
-
const { features, functionsConfig, graph, success
|
|
119
|
+
const { features, functionsConfig, graph, success } = await server(functions, {
|
|
120
120
|
very_secret_secret: 'i love netlify',
|
|
121
121
|
}, options);
|
|
122
122
|
expect(features).toEqual({ npmModules: true });
|
|
123
123
|
expect(success).toBe(true);
|
|
124
124
|
expect(functionsConfig).toEqual([{ path: '/func1' }]);
|
|
125
|
-
expect(npmSpecifiersWithExtraneousFiles).toEqual(['child-1']);
|
|
126
125
|
for (const key in functions) {
|
|
127
126
|
const graphEntry = graph === null || graph === void 0 ? void 0 : graph.modules.some(({ kind, mediaType, local }) => kind === 'esm' && mediaType === 'TypeScript' && local === functions[key].path);
|
|
128
127
|
expect(graphEntry).toBe(true);
|
package/dist/test/util.js
CHANGED
|
@@ -76,7 +76,7 @@ const runESZIP = async (eszipPath, vendorDirectory) => {
|
|
|
76
76
|
}
|
|
77
77
|
await fs.rename(stage2Path, `${stage2Path}.js`);
|
|
78
78
|
// Run function that imports the extracted stage 2 and invokes each function.
|
|
79
|
-
const evalCommand = execa('deno', ['eval', '--
|
|
79
|
+
const evalCommand = execa('deno', ['eval', '--import-map', importMapPath, inspectFunction(stage2Path)]);
|
|
80
80
|
(_c = evalCommand.stderr) === null || _c === void 0 ? void 0 : _c.pipe(stderr);
|
|
81
81
|
const result = await evalCommand;
|
|
82
82
|
await tmpDir.cleanup();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"@import-maps/resolve": "^1.0.1",
|
|
61
|
-
"@vercel/nft": "0.27.7",
|
|
62
61
|
"ajv": "^8.11.2",
|
|
63
62
|
"ajv-errors": "^3.0.0",
|
|
64
63
|
"better-ajv-errors": "^1.2.0",
|
|
@@ -74,11 +73,12 @@
|
|
|
74
73
|
"node-stream-zip": "^1.15.0",
|
|
75
74
|
"p-retry": "^5.1.1",
|
|
76
75
|
"p-wait-for": "^5.0.0",
|
|
76
|
+
"parse-imports": "^2.2.1",
|
|
77
77
|
"path-key": "^4.0.0",
|
|
78
78
|
"semver": "^7.3.8",
|
|
79
79
|
"tmp-promise": "^3.0.3",
|
|
80
80
|
"urlpattern-polyfill": "8.0.2",
|
|
81
81
|
"uuid": "^9.0.0"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "8d10878db3be9cfefe3162fd155c76595aba045e"
|
|
84
84
|
}
|