@netlify/edge-bundler 7.1.0 → 8.1.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/config.ts +2 -12
- package/dist/node/bundler.js +1 -0
- package/dist/node/bundler.test.js +24 -3
- package/dist/node/config.d.ts +1 -0
- package/dist/node/config.js +4 -9
- package/dist/node/config.test.js +13 -36
- package/dist/node/declaration.js +4 -5
- package/dist/node/manifest.d.ts +16 -16
- package/dist/node/manifest.js +22 -4
- package/dist/node/manifest.test.js +6 -2
- package/dist/node/npm_import_error.js +6 -1
- package/dist/node/validation/manifest/schema.d.ts +17 -0
- package/dist/node/validation/manifest/schema.js +15 -0
- package/package.json +1 -1
package/deno/config.ts
CHANGED
|
@@ -19,22 +19,12 @@ if (func.config === undefined) {
|
|
|
19
19
|
Deno.exit(exitCodes.NoConfig)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
if (typeof func.config !== '
|
|
22
|
+
if (typeof func.config !== 'object') {
|
|
23
23
|
Deno.exit(exitCodes.InvalidExport)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
let config
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
config = await func.config()
|
|
30
|
-
} catch (error) {
|
|
31
|
-
console.error(error)
|
|
32
|
-
|
|
33
|
-
Deno.exit(exitCodes.RuntimeError)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
26
|
try {
|
|
37
|
-
const result = JSON.stringify(config)
|
|
27
|
+
const result = JSON.stringify(func.config)
|
|
38
28
|
|
|
39
29
|
await Deno.writeTextFile(new URL(collectorURL), result)
|
|
40
30
|
} catch (error) {
|
package/dist/node/bundler.js
CHANGED
|
@@ -110,7 +110,28 @@ test('Prints a nice error message when user tries importing NPM module', async (
|
|
|
110
110
|
}
|
|
111
111
|
catch (error) {
|
|
112
112
|
expect(error).toBeInstanceOf(BundleError);
|
|
113
|
-
expect(error.message).toEqual(`It seems like you're trying to import an npm module. This is only supported
|
|
113
|
+
expect(error.message).toEqual(`It seems like you're trying to import an npm module. This is only supported via CDNs like esm.sh. Have you tried 'import mod from "https://esm.sh/p-retry"'?`);
|
|
114
|
+
}
|
|
115
|
+
finally {
|
|
116
|
+
await cleanup();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
test('Prints a nice error message when user tries importing NPM module with npm: scheme', async () => {
|
|
120
|
+
expect.assertions(2);
|
|
121
|
+
const { basePath, cleanup, distPath } = await useFixture('imports_npm_module_scheme');
|
|
122
|
+
const sourceDirectory = join(basePath, 'functions');
|
|
123
|
+
const declarations = [
|
|
124
|
+
{
|
|
125
|
+
function: 'func1',
|
|
126
|
+
path: '/func1',
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
try {
|
|
130
|
+
await bundle([sourceDirectory], distPath, declarations, { basePath });
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
expect(error).toBeInstanceOf(BundleError);
|
|
134
|
+
expect(error.message).toEqual(`It seems like you're trying to import an npm module. This is only supported via CDNs like esm.sh. Have you tried 'import mod from "https://esm.sh/p-retry"'?`);
|
|
114
135
|
}
|
|
115
136
|
finally {
|
|
116
137
|
await cleanup();
|
|
@@ -278,12 +299,12 @@ test('Loads declarations and import maps from the deploy configuration', async (
|
|
|
278
299
|
expect(generatedFiles.length).toBe(2);
|
|
279
300
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
280
301
|
const manifest = JSON.parse(manifestFile);
|
|
281
|
-
const { bundles,
|
|
302
|
+
const { bundles, function_config: functionConfig } = manifest;
|
|
282
303
|
expect(bundles.length).toBe(1);
|
|
283
304
|
expect(bundles[0].format).toBe('eszip2');
|
|
284
305
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
285
306
|
// respects excludedPath from deploy config
|
|
286
|
-
expect(
|
|
307
|
+
expect(functionConfig.func2).toEqual({ excluded_patterns: ['^/func2/skip/?$'] });
|
|
287
308
|
await cleanup();
|
|
288
309
|
});
|
|
289
310
|
test("Ignores entries in `importMapPaths` that don't point to an existing import map file", async () => {
|
package/dist/node/config.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export declare const enum Cache {
|
|
|
9
9
|
export interface FunctionConfig {
|
|
10
10
|
cache?: Cache;
|
|
11
11
|
path?: string | string[];
|
|
12
|
+
excludedPath?: string | string[];
|
|
12
13
|
}
|
|
13
14
|
export declare const getFunctionConfig: (func: EdgeFunction, importMap: ImportMap, deno: DenoBridge, log: Logger) => Promise<FunctionConfig>;
|
package/dist/node/config.js
CHANGED
|
@@ -11,9 +11,8 @@ var ConfigExitCode;
|
|
|
11
11
|
ConfigExitCode[ConfigExitCode["ImportError"] = 2] = "ImportError";
|
|
12
12
|
ConfigExitCode[ConfigExitCode["NoConfig"] = 3] = "NoConfig";
|
|
13
13
|
ConfigExitCode[ConfigExitCode["InvalidExport"] = 4] = "InvalidExport";
|
|
14
|
-
ConfigExitCode[ConfigExitCode["
|
|
15
|
-
ConfigExitCode[ConfigExitCode["
|
|
16
|
-
ConfigExitCode[ConfigExitCode["InvalidDefaultExport"] = 7] = "InvalidDefaultExport";
|
|
14
|
+
ConfigExitCode[ConfigExitCode["SerializationError"] = 5] = "SerializationError";
|
|
15
|
+
ConfigExitCode[ConfigExitCode["InvalidDefaultExport"] = 6] = "InvalidDefaultExport";
|
|
17
16
|
})(ConfigExitCode || (ConfigExitCode = {}));
|
|
18
17
|
const getConfigExtractor = () => {
|
|
19
18
|
const packagePath = getPackagePath();
|
|
@@ -75,14 +74,10 @@ const logConfigError = (func, exitCode, stderr, log) => {
|
|
|
75
74
|
log.system(`No in-source config found for edge function at '${func.path}'`);
|
|
76
75
|
break;
|
|
77
76
|
case ConfigExitCode.InvalidExport:
|
|
78
|
-
log.user(`'config' export in edge function at '${func.path}' must be
|
|
79
|
-
break;
|
|
80
|
-
case ConfigExitCode.RuntimeError:
|
|
81
|
-
log.user(`Error while running 'config' function in edge function at '${func.path}'`);
|
|
82
|
-
log.user(stderr);
|
|
77
|
+
log.user(`'config' export in edge function at '${func.path}' must be an object`);
|
|
83
78
|
break;
|
|
84
79
|
case ConfigExitCode.SerializationError:
|
|
85
|
-
log.user(`'config'
|
|
80
|
+
log.user(`'config' object in edge function at '${func.path}' must contain primitive values only`);
|
|
86
81
|
break;
|
|
87
82
|
case ConfigExitCode.InvalidDefaultExport:
|
|
88
83
|
throw new BundleError(new Error(`Default export in '${func.path}' must be a function. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
package/dist/node/config.test.js
CHANGED
|
@@ -35,7 +35,7 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
35
35
|
source: `
|
|
36
36
|
export default async () => new Response("Hello from function two")
|
|
37
37
|
|
|
38
|
-
export const config =
|
|
38
|
+
export const config = {}
|
|
39
39
|
`,
|
|
40
40
|
},
|
|
41
41
|
// Config with the wrong type
|
|
@@ -45,9 +45,9 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
45
45
|
source: `
|
|
46
46
|
export default async () => new Response("Hello from function two")
|
|
47
47
|
|
|
48
|
-
export const config = {}
|
|
48
|
+
export const config = () => ({})
|
|
49
49
|
`,
|
|
50
|
-
userLog: /^'config' export in edge function at '(.*)' must be
|
|
50
|
+
userLog: /^'config' export in edge function at '(.*)' must be an object$/,
|
|
51
51
|
},
|
|
52
52
|
// Config with a syntax error
|
|
53
53
|
{
|
|
@@ -60,19 +60,6 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
60
60
|
`,
|
|
61
61
|
userLog: /^Could not load edge function at '(.*)'$/,
|
|
62
62
|
},
|
|
63
|
-
// Config that throws
|
|
64
|
-
{
|
|
65
|
-
expectedConfig: {},
|
|
66
|
-
name: 'func5',
|
|
67
|
-
source: `
|
|
68
|
-
export default async () => new Response("Hello from function two")
|
|
69
|
-
|
|
70
|
-
export const config = () => {
|
|
71
|
-
throw new Error('uh-oh')
|
|
72
|
-
}
|
|
73
|
-
`,
|
|
74
|
-
userLog: /^Error while running 'config' function in edge function at '(.*)'$/,
|
|
75
|
-
},
|
|
76
63
|
// Config with `path`
|
|
77
64
|
{
|
|
78
65
|
expectedConfig: { path: '/home' },
|
|
@@ -80,24 +67,9 @@ test('`getFunctionConfig` extracts configuration properties from function file',
|
|
|
80
67
|
source: `
|
|
81
68
|
export default async () => new Response("Hello from function three")
|
|
82
69
|
|
|
83
|
-
export const config =
|
|
70
|
+
export const config = { path: "/home" }
|
|
84
71
|
`,
|
|
85
72
|
},
|
|
86
|
-
// Config that prints to stdout
|
|
87
|
-
{
|
|
88
|
-
expectedConfig: { path: '/home' },
|
|
89
|
-
name: 'func7',
|
|
90
|
-
source: `
|
|
91
|
-
export default async () => new Response("Hello from function three")
|
|
92
|
-
|
|
93
|
-
export const config = () => {
|
|
94
|
-
console.log("Hello from config!")
|
|
95
|
-
|
|
96
|
-
return { path: "/home" }
|
|
97
|
-
}
|
|
98
|
-
`,
|
|
99
|
-
userLog: /^Hello from config!$/,
|
|
100
|
-
},
|
|
101
73
|
];
|
|
102
74
|
for (const func of functions) {
|
|
103
75
|
const logger = {
|
|
@@ -130,7 +102,7 @@ test('Ignores function paths from the in-source `config` function if the feature
|
|
|
130
102
|
configPath: join(internalDirectory, 'config.json'),
|
|
131
103
|
});
|
|
132
104
|
const generatedFiles = await fs.readdir(distPath);
|
|
133
|
-
expect(result.functions.length).toBe(
|
|
105
|
+
expect(result.functions.length).toBe(7);
|
|
134
106
|
expect(generatedFiles.length).toBe(2);
|
|
135
107
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
136
108
|
const manifest = JSON.parse(manifestFile);
|
|
@@ -163,22 +135,27 @@ test('Loads function paths from the in-source `config` function', async () => {
|
|
|
163
135
|
},
|
|
164
136
|
});
|
|
165
137
|
const generatedFiles = await fs.readdir(distPath);
|
|
166
|
-
expect(result.functions.length).toBe(
|
|
138
|
+
expect(result.functions.length).toBe(7);
|
|
167
139
|
expect(generatedFiles.length).toBe(2);
|
|
168
140
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
169
141
|
const manifest = JSON.parse(manifestFile);
|
|
170
|
-
const { bundles, routes, post_cache_routes: postCacheRoutes } = manifest;
|
|
142
|
+
const { bundles, routes, post_cache_routes: postCacheRoutes, function_config: functionConfig } = manifest;
|
|
171
143
|
expect(bundles.length).toBe(1);
|
|
172
144
|
expect(bundles[0].format).toBe('eszip2');
|
|
173
145
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
174
|
-
expect(routes.length).toBe(
|
|
146
|
+
expect(routes.length).toBe(6);
|
|
175
147
|
expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$' });
|
|
176
148
|
expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$' });
|
|
177
149
|
expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$' });
|
|
178
150
|
expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$' });
|
|
179
151
|
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$' });
|
|
152
|
+
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$' });
|
|
180
153
|
expect(postCacheRoutes.length).toBe(1);
|
|
181
154
|
expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$' });
|
|
155
|
+
expect(Object.keys(functionConfig)).toHaveLength(1);
|
|
156
|
+
expect(functionConfig['user-func5']).toEqual({
|
|
157
|
+
excluded_patterns: ['^/user-func5/excluded/?$'],
|
|
158
|
+
});
|
|
182
159
|
await cleanup();
|
|
183
160
|
});
|
|
184
161
|
test('Passes validation if default export exists and is a function', async () => {
|
package/dist/node/declaration.js
CHANGED
|
@@ -17,13 +17,13 @@ export const getDeclarationsFromConfig = (tomlDeclarations, functionsConfig, dep
|
|
|
17
17
|
else if ((_a = config.path) === null || _a === void 0 ? void 0 : _a.length) {
|
|
18
18
|
const paths = Array.isArray(config.path) ? config.path : [config.path];
|
|
19
19
|
paths.forEach((path) => {
|
|
20
|
-
declarations.push({ ...declaration,
|
|
20
|
+
declarations.push({ ...declaration, cache: config.cache, path });
|
|
21
21
|
});
|
|
22
22
|
// With an in-source config without a path, add the config to the declaration
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
-
const { path, ...rest } = config;
|
|
26
|
+
const { path, excludedPath, ...rest } = config;
|
|
27
27
|
declarations.push({ ...declaration, ...rest });
|
|
28
28
|
}
|
|
29
29
|
functionsVisited.add(declaration.function);
|
|
@@ -31,13 +31,12 @@ export const getDeclarationsFromConfig = (tomlDeclarations, functionsConfig, dep
|
|
|
31
31
|
// Finally, we must create declarations for functions that are not declared
|
|
32
32
|
// in the TOML at all.
|
|
33
33
|
for (const name in functionsConfig) {
|
|
34
|
-
const {
|
|
35
|
-
const { path } = functionsConfig[name];
|
|
34
|
+
const { cache, path } = functionsConfig[name];
|
|
36
35
|
// If we have path specified create a declaration for each path
|
|
37
36
|
if (!functionsVisited.has(name) && path) {
|
|
38
37
|
const paths = Array.isArray(path) ? path : [path];
|
|
39
38
|
paths.forEach((singlePath) => {
|
|
40
|
-
declarations.push({
|
|
39
|
+
declarations.push({ cache, function: name, path: singlePath });
|
|
41
40
|
});
|
|
42
41
|
}
|
|
43
42
|
}
|
package/dist/node/manifest.d.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import type { Bundle } from './bundle.js';
|
|
2
|
+
import { FunctionConfig } from './config.js';
|
|
2
3
|
import type { Declaration } from './declaration.js';
|
|
3
4
|
import { EdgeFunction } from './edge_function.js';
|
|
4
5
|
import { Layer } from './layer.js';
|
|
5
|
-
interface GenerateManifestOptions {
|
|
6
|
-
bundles?: Bundle[];
|
|
7
|
-
declarations?: Declaration[];
|
|
8
|
-
functions: EdgeFunction[];
|
|
9
|
-
importMap?: string;
|
|
10
|
-
layers?: Layer[];
|
|
11
|
-
}
|
|
12
6
|
interface Route {
|
|
13
7
|
function: string;
|
|
14
8
|
name?: string;
|
|
15
9
|
pattern: string;
|
|
16
|
-
|
|
10
|
+
}
|
|
11
|
+
interface EdgeFunctionConfig {
|
|
12
|
+
excluded_patterns: string[];
|
|
17
13
|
}
|
|
18
14
|
interface Manifest {
|
|
19
15
|
bundler_version: string;
|
|
@@ -28,20 +24,24 @@ interface Manifest {
|
|
|
28
24
|
}[];
|
|
29
25
|
routes: Route[];
|
|
30
26
|
post_cache_routes: Route[];
|
|
27
|
+
function_config: Record<string, EdgeFunctionConfig>;
|
|
28
|
+
}
|
|
29
|
+
interface GenerateManifestOptions {
|
|
30
|
+
bundles?: Bundle[];
|
|
31
|
+
declarations?: Declaration[];
|
|
32
|
+
functions: EdgeFunction[];
|
|
33
|
+
functionConfig?: Record<string, FunctionConfig>;
|
|
34
|
+
importMap?: string;
|
|
35
|
+
layers?: Layer[];
|
|
31
36
|
}
|
|
32
37
|
interface Route {
|
|
33
38
|
function: string;
|
|
34
39
|
name?: string;
|
|
35
40
|
pattern: string;
|
|
36
41
|
}
|
|
37
|
-
declare const generateManifest: ({ bundles, declarations, functions, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
38
|
-
interface WriteManifestOptions {
|
|
39
|
-
bundles: Bundle[];
|
|
40
|
-
declarations: Declaration[];
|
|
42
|
+
declare const generateManifest: ({ bundles, declarations, functions, functionConfig, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
43
|
+
interface WriteManifestOptions extends GenerateManifestOptions {
|
|
41
44
|
distDirectory: string;
|
|
42
|
-
functions: EdgeFunction[];
|
|
43
|
-
importMap?: string;
|
|
44
|
-
layers?: Layer[];
|
|
45
45
|
}
|
|
46
|
-
declare const writeManifest: ({
|
|
46
|
+
declare const writeManifest: ({ distDirectory, ...rest }: WriteManifestOptions) => Promise<Manifest>;
|
|
47
47
|
export { generateManifest, Manifest, writeManifest };
|
package/dist/node/manifest.js
CHANGED
|
@@ -4,9 +4,26 @@ import globToRegExp from 'glob-to-regexp';
|
|
|
4
4
|
import { getPackageVersion } from './package_json.js';
|
|
5
5
|
import { nonNullable } from './utils/non_nullable.js';
|
|
6
6
|
const serializePattern = (regex) => regex.source.replace(/\\\//g, '/');
|
|
7
|
-
const
|
|
7
|
+
const sanitizeEdgeFunctionConfig = (config) => {
|
|
8
|
+
const newConfig = {};
|
|
9
|
+
for (const [name, functionConfig] of Object.entries(config)) {
|
|
10
|
+
if (functionConfig.excluded_patterns.length !== 0) {
|
|
11
|
+
newConfig[name] = functionConfig;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return newConfig;
|
|
15
|
+
};
|
|
16
|
+
const generateManifest = ({ bundles = [], declarations = [], functions, functionConfig = {}, importMap, layers = [], }) => {
|
|
8
17
|
const preCacheRoutes = [];
|
|
9
18
|
const postCacheRoutes = [];
|
|
19
|
+
const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
|
|
20
|
+
for (const [name, { excludedPath }] of Object.entries(functionConfig)) {
|
|
21
|
+
if (excludedPath) {
|
|
22
|
+
const paths = Array.isArray(excludedPath) ? excludedPath : [excludedPath];
|
|
23
|
+
const excludedPatterns = paths.map(pathToRegularExpression).map(serializePattern);
|
|
24
|
+
manifestFunctionConfig[name].excluded_patterns.push(...excludedPatterns);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
10
27
|
declarations.forEach((declaration) => {
|
|
11
28
|
const func = functions.find(({ name }) => declaration.function === name);
|
|
12
29
|
if (func === undefined) {
|
|
@@ -20,7 +37,7 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
|
|
|
20
37
|
};
|
|
21
38
|
const excludedPattern = getExcludedRegularExpression(declaration);
|
|
22
39
|
if (excludedPattern) {
|
|
23
|
-
|
|
40
|
+
manifestFunctionConfig[func.name].excluded_patterns.push(serializePattern(excludedPattern));
|
|
24
41
|
}
|
|
25
42
|
if (declaration.cache === "manual" /* Cache.Manual */) {
|
|
26
43
|
postCacheRoutes.push(route);
|
|
@@ -40,6 +57,7 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
|
|
|
40
57
|
bundler_version: getPackageVersion(),
|
|
41
58
|
layers,
|
|
42
59
|
import_map: importMap,
|
|
60
|
+
function_config: sanitizeEdgeFunctionConfig(manifestFunctionConfig),
|
|
43
61
|
};
|
|
44
62
|
return manifest;
|
|
45
63
|
};
|
|
@@ -67,8 +85,8 @@ const getExcludedRegularExpression = (declaration) => {
|
|
|
67
85
|
return pathToRegularExpression(declaration.excludedPath);
|
|
68
86
|
}
|
|
69
87
|
};
|
|
70
|
-
const writeManifest = async ({
|
|
71
|
-
const manifest = generateManifest(
|
|
88
|
+
const writeManifest = async ({ distDirectory, ...rest }) => {
|
|
89
|
+
const manifest = generateManifest(rest);
|
|
72
90
|
const manifestPath = join(distDirectory, 'manifest.json');
|
|
73
91
|
await fs.writeFile(manifestPath, JSON.stringify(manifest));
|
|
74
92
|
return manifest;
|
|
@@ -53,10 +53,14 @@ test('Generates a manifest with excluded paths and patterns', () => {
|
|
|
53
53
|
];
|
|
54
54
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
55
55
|
const expectedRoutes = [
|
|
56
|
-
{ function: 'func-1', name: 'Display Name', pattern: '^/f1/.*/?$'
|
|
57
|
-
{ function: 'func-2', pattern: '^/f2/.*/?$'
|
|
56
|
+
{ function: 'func-1', name: 'Display Name', pattern: '^/f1/.*/?$' },
|
|
57
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
58
58
|
];
|
|
59
59
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
60
|
+
expect(manifest.function_config).toEqual({
|
|
61
|
+
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
62
|
+
'func-2': { excluded_patterns: ['^/f2/exclude$'] },
|
|
63
|
+
});
|
|
60
64
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
61
65
|
});
|
|
62
66
|
test('Excludes functions for which there are function files but no matching config declarations', () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class NPMImportError extends Error {
|
|
2
2
|
constructor(originalError, moduleName) {
|
|
3
|
-
super(`It seems like you're trying to import an npm module. This is only supported
|
|
3
|
+
super(`It seems like you're trying to import an npm module. This is only supported via CDNs like esm.sh. Have you tried 'import mod from "https://esm.sh/${moduleName}"'?`);
|
|
4
4
|
this.name = 'NPMImportError';
|
|
5
5
|
this.stack = originalError.stack;
|
|
6
6
|
// https://github.com/microsoft/TypeScript-wiki/blob/8a66ecaf77118de456f7cd9c56848a40fe29b9b4/Breaking-Changes.md#implicit-any-error-raised-for-un-annotated-callback-arguments-with-no-matching-overload-arguments
|
|
@@ -14,6 +14,11 @@ const wrapNpmImportError = (input) => {
|
|
|
14
14
|
const [, moduleName] = match;
|
|
15
15
|
return new NPMImportError(input, moduleName);
|
|
16
16
|
}
|
|
17
|
+
const schemeMatch = input.message.match(/Error: Module not found "npm:(.*)"/);
|
|
18
|
+
if (schemeMatch !== null) {
|
|
19
|
+
const [, moduleName] = schemeMatch;
|
|
20
|
+
return new NPMImportError(input, moduleName);
|
|
21
|
+
}
|
|
17
22
|
}
|
|
18
23
|
return input;
|
|
19
24
|
};
|
|
@@ -86,6 +86,23 @@ declare const edgeManifestSchema: {
|
|
|
86
86
|
bundler_version: {
|
|
87
87
|
type: string;
|
|
88
88
|
};
|
|
89
|
+
function_config: {
|
|
90
|
+
type: string;
|
|
91
|
+
items: {
|
|
92
|
+
type: string;
|
|
93
|
+
required: never[];
|
|
94
|
+
properties: {
|
|
95
|
+
excluded_patterns: {
|
|
96
|
+
type: string;
|
|
97
|
+
items: {
|
|
98
|
+
type: string;
|
|
99
|
+
format: string;
|
|
100
|
+
errorMessage: string;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
};
|
|
89
106
|
};
|
|
90
107
|
additionalProperties: boolean;
|
|
91
108
|
};
|
|
@@ -21,6 +21,20 @@ const routesSchema = {
|
|
|
21
21
|
},
|
|
22
22
|
additionalProperties: false,
|
|
23
23
|
};
|
|
24
|
+
const functionConfigSchema = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
required: [],
|
|
27
|
+
properties: {
|
|
28
|
+
excluded_patterns: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
format: 'regexPattern',
|
|
33
|
+
errorMessage: 'excluded_patterns needs to be an array of regex that starts with ^ and ends with $ without any additional slashes before and afterwards',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
24
38
|
const layersSchema = {
|
|
25
39
|
type: 'object',
|
|
26
40
|
required: ['flag', 'name'],
|
|
@@ -53,6 +67,7 @@ const edgeManifestSchema = {
|
|
|
53
67
|
},
|
|
54
68
|
import_map: { type: 'string' },
|
|
55
69
|
bundler_version: { type: 'string' },
|
|
70
|
+
function_config: { type: 'object', items: functionConfigSchema },
|
|
56
71
|
},
|
|
57
72
|
additionalProperties: false,
|
|
58
73
|
};
|