@netlify/edge-bundler 8.13.2 → 8.14.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/node/bundler.js +2 -2
- package/dist/node/config.d.ts +1 -2
- package/dist/node/config.js +7 -22
- package/dist/node/config.test.js +6 -42
- package/dist/node/declaration.d.ts +1 -1
- package/dist/node/declaration.js +18 -29
- package/dist/node/declaration.test.js +14 -25
- package/dist/node/feature_flags.d.ts +0 -4
- package/dist/node/feature_flags.js +0 -2
- package/dist/node/manifest.d.ts +1 -1
- package/dist/node/manifest.test.js +23 -0
- package/dist/node/server/server.js +1 -1
- package/dist/test/util.d.ts +3 -1
- package/dist/test/util.js +10 -1
- package/package.json +4 -4
package/dist/node/bundler.js
CHANGED
|
@@ -63,8 +63,8 @@ const bundle = async (sourceDirectories, distDirectory, tomlDeclarations = [], {
|
|
|
63
63
|
await createFinalBundles([functionBundle], distDirectory, buildID);
|
|
64
64
|
// Retrieving a configuration object for each function.
|
|
65
65
|
// Run `getFunctionConfig` in parallel as it is a non-trivial operation and spins up deno
|
|
66
|
-
const internalConfigPromises = internalFunctions.map(async (func) => [func.name, await getFunctionConfig(func, importMap, deno, logger
|
|
67
|
-
const userConfigPromises = userFunctions.map(async (func) => [func.name, await getFunctionConfig(func, importMap, deno, logger
|
|
66
|
+
const internalConfigPromises = internalFunctions.map(async (func) => [func.name, await getFunctionConfig(func, importMap, deno, logger)]);
|
|
67
|
+
const userConfigPromises = userFunctions.map(async (func) => [func.name, await getFunctionConfig(func, importMap, deno, logger)]);
|
|
68
68
|
// Creating a hash of function names to configuration objects.
|
|
69
69
|
const internalFunctionsWithConfig = Object.fromEntries(await Promise.all(internalConfigPromises));
|
|
70
70
|
const userFunctionsWithConfig = Object.fromEntries(await Promise.all(userConfigPromises));
|
package/dist/node/config.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DenoBridge } from './bridge.js';
|
|
2
2
|
import { EdgeFunction } from './edge_function.js';
|
|
3
|
-
import { FeatureFlags } from './feature_flags.js';
|
|
4
3
|
import { ImportMap } from './import_map.js';
|
|
5
4
|
import { Logger } from './logger.js';
|
|
6
5
|
export declare const enum Cache {
|
|
@@ -18,4 +17,4 @@ export interface FunctionConfig {
|
|
|
18
17
|
name?: string;
|
|
19
18
|
generator?: string;
|
|
20
19
|
}
|
|
21
|
-
export declare const getFunctionConfig: (func: EdgeFunction, importMap: ImportMap, deno: DenoBridge, log: Logger
|
|
20
|
+
export declare const getFunctionConfig: (func: EdgeFunction, importMap: ImportMap, deno: DenoBridge, log: Logger) => Promise<FunctionConfig>;
|
package/dist/node/config.js
CHANGED
|
@@ -26,7 +26,7 @@ const getConfigExtractor = () => {
|
|
|
26
26
|
const configExtractorPath = join(packagePath, 'deno', 'config.ts');
|
|
27
27
|
return configExtractorPath;
|
|
28
28
|
};
|
|
29
|
-
export const getFunctionConfig = async (func, importMap, deno, log
|
|
29
|
+
export const getFunctionConfig = async (func, importMap, deno, log) => {
|
|
30
30
|
// The extractor is a Deno script that will import the function and run its
|
|
31
31
|
// `config` export, if one exists.
|
|
32
32
|
const extractorPath = getConfigExtractor();
|
|
@@ -53,7 +53,7 @@ export const getFunctionConfig = async (func, importMap, deno, log, featureFlags
|
|
|
53
53
|
JSON.stringify(ConfigExitCode),
|
|
54
54
|
], { rejectOnExitCode: false });
|
|
55
55
|
if (exitCode !== ConfigExitCode.Success) {
|
|
56
|
-
handleConfigError(func, exitCode, stderr, log
|
|
56
|
+
handleConfigError(func, exitCode, stderr, log);
|
|
57
57
|
return {};
|
|
58
58
|
}
|
|
59
59
|
if (stdout !== '') {
|
|
@@ -65,7 +65,7 @@ export const getFunctionConfig = async (func, importMap, deno, log, featureFlags
|
|
|
65
65
|
collectorData = JSON.parse(collectorDataJSON);
|
|
66
66
|
}
|
|
67
67
|
catch {
|
|
68
|
-
handleConfigError(func, ConfigExitCode.UnhandledError, stderr, log
|
|
68
|
+
handleConfigError(func, ConfigExitCode.UnhandledError, stderr, log);
|
|
69
69
|
}
|
|
70
70
|
finally {
|
|
71
71
|
await collector.cleanup();
|
|
@@ -75,35 +75,20 @@ export const getFunctionConfig = async (func, importMap, deno, log, featureFlags
|
|
|
75
75
|
}
|
|
76
76
|
return collectorData;
|
|
77
77
|
};
|
|
78
|
-
const handleConfigError = (func, exitCode, stderr, log
|
|
78
|
+
const handleConfigError = (func, exitCode, stderr, log) => {
|
|
79
79
|
switch (exitCode) {
|
|
80
80
|
case ConfigExitCode.ImportError:
|
|
81
81
|
log.user(stderr);
|
|
82
|
-
|
|
83
|
-
throw new BundleError(new Error(`Could not load edge function at '${func.path}'. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
log.user(`Could not load edge function at '${func.path}'`);
|
|
87
|
-
}
|
|
82
|
+
throw new BundleError(new Error(`Could not load edge function at '${func.path}'. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
88
83
|
break;
|
|
89
84
|
case ConfigExitCode.NoConfig:
|
|
90
85
|
log.system(`No in-source config found for edge function at '${func.path}'`);
|
|
91
86
|
break;
|
|
92
87
|
case ConfigExitCode.InvalidExport:
|
|
93
|
-
|
|
94
|
-
throw new BundleError(new Error(`The 'config' export in edge function at '${func.path}' must be an object. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
log.user(`'config' export in edge function at '${func.path}' must be an object`);
|
|
98
|
-
}
|
|
88
|
+
throw new BundleError(new Error(`The 'config' export in edge function at '${func.path}' must be an object. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
99
89
|
break;
|
|
100
90
|
case ConfigExitCode.SerializationError:
|
|
101
|
-
|
|
102
|
-
throw new BundleError(new Error(`The 'config' object in the edge function at '${func.path}' must contain primitive values only. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
log.user(`'config' object in edge function at '${func.path}' must contain primitive values only`);
|
|
106
|
-
}
|
|
91
|
+
throw new BundleError(new Error(`The 'config' object in the edge function at '${func.path}' must contain primitive values only. More on the Edge Functions API at https://ntl.fyi/edge-api.`));
|
|
107
92
|
break;
|
|
108
93
|
case ConfigExitCode.InvalidDefaultExport:
|
|
109
94
|
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
|
@@ -34,8 +34,7 @@ const functions = [
|
|
|
34
34
|
`,
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
|
-
testName: 'config with wrong type
|
|
38
|
-
expectedConfig: {},
|
|
37
|
+
testName: 'config with wrong type',
|
|
39
38
|
name: 'func3',
|
|
40
39
|
source: `
|
|
41
40
|
export default async () => new Response("Hello from function two")
|
|
@@ -43,27 +42,9 @@ const functions = [
|
|
|
43
42
|
export const config = () => ({})
|
|
44
43
|
`,
|
|
45
44
|
error: /^The 'config' export in edge function at '(.*)' must be an object\. More on the Edge Functions API at https:\/\/ntl\.fyi\/edge-api\.$/,
|
|
46
|
-
featureFlags: {
|
|
47
|
-
edge_functions_invalid_config_throw: true,
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
testName: 'config with wrong type (log)',
|
|
52
|
-
expectedConfig: {},
|
|
53
|
-
name: 'func3',
|
|
54
|
-
source: `
|
|
55
|
-
export default async () => new Response("Hello from function two")
|
|
56
|
-
|
|
57
|
-
export const config = () => ({})
|
|
58
|
-
`,
|
|
59
|
-
userLog: /^'config' export in edge function at '(.*)' must be an object$/,
|
|
60
|
-
featureFlags: {
|
|
61
|
-
edge_functions_invalid_config_throw: false,
|
|
62
|
-
},
|
|
63
45
|
},
|
|
64
46
|
{
|
|
65
|
-
testName: 'config with syntax error
|
|
66
|
-
expectedConfig: {},
|
|
47
|
+
testName: 'config with syntax error',
|
|
67
48
|
name: 'func4',
|
|
68
49
|
source: `
|
|
69
50
|
export default async () => new Response("Hello from function two")
|
|
@@ -71,23 +52,6 @@ const functions = [
|
|
|
71
52
|
export const config
|
|
72
53
|
`,
|
|
73
54
|
error: /^Could not load edge function at '(.*)'\. More on the Edge Functions API at https:\/\/ntl\.fyi\/edge-api\.$/,
|
|
74
|
-
featureFlags: {
|
|
75
|
-
edge_functions_invalid_config_throw: true,
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
testName: 'config with syntax error (log)',
|
|
80
|
-
expectedConfig: {},
|
|
81
|
-
name: 'func4',
|
|
82
|
-
source: `
|
|
83
|
-
export default async () => new Response("Hello from function two")
|
|
84
|
-
|
|
85
|
-
export const config
|
|
86
|
-
`,
|
|
87
|
-
userLog: /^Could not load edge function at '(.*)'$/,
|
|
88
|
-
featureFlags: {
|
|
89
|
-
edge_functions_invalid_config_throw: false,
|
|
90
|
-
},
|
|
91
55
|
},
|
|
92
56
|
{
|
|
93
57
|
testName: 'config with correct onError',
|
|
@@ -152,7 +116,7 @@ describe('`getFunctionConfig` extracts configuration properties from function fi
|
|
|
152
116
|
const funcCall = () => getFunctionConfig({
|
|
153
117
|
name: func.name,
|
|
154
118
|
path,
|
|
155
|
-
}, new ImportMap([importMapFile]), deno, logger
|
|
119
|
+
}, new ImportMap([importMapFile]), deno, logger);
|
|
156
120
|
if (func.error) {
|
|
157
121
|
await expect(funcCall()).rejects.toThrowError(func.error);
|
|
158
122
|
}
|
|
@@ -231,7 +195,7 @@ test('Passes validation if default export exists and is a function', async () =>
|
|
|
231
195
|
await expect(getFunctionConfig({
|
|
232
196
|
name: func.name,
|
|
233
197
|
path,
|
|
234
|
-
}, new ImportMap([importMapFile]), deno, logger
|
|
198
|
+
}, new ImportMap([importMapFile]), deno, logger)).resolves.not.toThrow();
|
|
235
199
|
await deleteAsync(tmpDir, { force: true });
|
|
236
200
|
});
|
|
237
201
|
test('Fails validation if default export is not function', async () => {
|
|
@@ -255,7 +219,7 @@ test('Fails validation if default export is not function', async () => {
|
|
|
255
219
|
const config = getFunctionConfig({
|
|
256
220
|
name: func.name,
|
|
257
221
|
path,
|
|
258
|
-
}, new ImportMap([importMapFile]), deno, logger
|
|
222
|
+
}, new ImportMap([importMapFile]), deno, logger);
|
|
259
223
|
await expect(config).rejects.toThrowError(invalidDefaultExportErr(path));
|
|
260
224
|
await deleteAsync(tmpDir, { force: true });
|
|
261
225
|
});
|
|
@@ -279,7 +243,7 @@ test('Fails validation if default export is not present', async () => {
|
|
|
279
243
|
const config = getFunctionConfig({
|
|
280
244
|
name: func.name,
|
|
281
245
|
path,
|
|
282
|
-
}, new ImportMap([importMapFile]), deno, logger
|
|
246
|
+
}, new ImportMap([importMapFile]), deno, logger);
|
|
283
247
|
await expect(config).rejects.toThrowError(invalidDefaultExportErr(path));
|
|
284
248
|
await deleteAsync(tmpDir, { force: true });
|
|
285
249
|
});
|
|
@@ -15,6 +15,6 @@ type DeclarationWithPattern = BaseDeclaration & {
|
|
|
15
15
|
excludedPattern?: string;
|
|
16
16
|
};
|
|
17
17
|
export type Declaration = DeclarationWithPath | DeclarationWithPattern;
|
|
18
|
-
export declare const mergeDeclarations: (tomlDeclarations: Declaration[], userFunctionsConfig: Record<string, FunctionConfig>, internalFunctionsConfig: Record<string, FunctionConfig>, deployConfigDeclarations: Declaration[],
|
|
18
|
+
export declare const mergeDeclarations: (tomlDeclarations: Declaration[], userFunctionsConfig: Record<string, FunctionConfig>, internalFunctionsConfig: Record<string, FunctionConfig>, deployConfigDeclarations: Declaration[], _featureFlags?: FeatureFlags) => Declaration[];
|
|
19
19
|
export declare const parsePattern: (pattern: string) => string;
|
|
20
20
|
export {};
|
package/dist/node/declaration.js
CHANGED
|
@@ -1,30 +1,20 @@
|
|
|
1
1
|
import regexpAST from 'regexp-tree';
|
|
2
|
-
export const mergeDeclarations = (tomlDeclarations, userFunctionsConfig, internalFunctionsConfig, deployConfigDeclarations,
|
|
2
|
+
export const mergeDeclarations = (tomlDeclarations, userFunctionsConfig, internalFunctionsConfig, deployConfigDeclarations,
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4
|
+
_featureFlags = {}) => {
|
|
3
5
|
const functionsVisited = new Set();
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
// 4. Declarations from the users ISC
|
|
17
|
-
...createDeclarationsFromFunctionConfigs(userFunctionsConfig, functionsVisited),
|
|
18
|
-
];
|
|
19
|
-
}
|
|
20
|
-
else {
|
|
21
|
-
declarations = [
|
|
22
|
-
...getDeclarationsFromInput(tomlDeclarations, userFunctionsConfig, functionsVisited),
|
|
23
|
-
...getDeclarationsFromInput(deployConfigDeclarations, internalFunctionsConfig, functionsVisited),
|
|
24
|
-
...createDeclarationsFromFunctionConfigs(internalFunctionsConfig, functionsVisited),
|
|
25
|
-
...createDeclarationsFromFunctionConfigs(userFunctionsConfig, functionsVisited),
|
|
26
|
-
];
|
|
27
|
-
}
|
|
6
|
+
const declarations = [
|
|
7
|
+
// INTEGRATIONS
|
|
8
|
+
// 1. Declarations from the integrations deploy config
|
|
9
|
+
...getDeclarationsFromInput(deployConfigDeclarations, internalFunctionsConfig, functionsVisited),
|
|
10
|
+
// 2. Declarations from the integrations ISC
|
|
11
|
+
...createDeclarationsFromFunctionConfigs(internalFunctionsConfig, functionsVisited),
|
|
12
|
+
// USER
|
|
13
|
+
// 3. Declarations from the users toml config
|
|
14
|
+
...getDeclarationsFromInput(tomlDeclarations, userFunctionsConfig, functionsVisited),
|
|
15
|
+
// 4. Declarations from the users ISC
|
|
16
|
+
...createDeclarationsFromFunctionConfigs(userFunctionsConfig, functionsVisited),
|
|
17
|
+
];
|
|
28
18
|
return declarations;
|
|
29
19
|
};
|
|
30
20
|
const getDeclarationsFromInput = (inputDeclarations, functionConfigs, functionsVisited) => {
|
|
@@ -76,9 +66,8 @@ const createDeclarationsFromFunctionConfigs = (functionConfigs, functionsVisited
|
|
|
76
66
|
// Validates and normalizes a pattern so that it's a valid regular expression
|
|
77
67
|
// in Go, which is the engine used by our edge nodes.
|
|
78
68
|
export const parsePattern = (pattern) => {
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const regex = regexpAST.transform(`/${normalizedPattern}/`, {
|
|
69
|
+
const regexp = new RegExp(pattern);
|
|
70
|
+
const newRegexp = regexpAST.transform(regexp, {
|
|
82
71
|
Assertion(path) {
|
|
83
72
|
// Lookaheads are not supported. If we find one, throw an error.
|
|
84
73
|
if (path.node.kind === 'Lookahead') {
|
|
@@ -99,5 +88,5 @@ export const parsePattern = (pattern) => {
|
|
|
99
88
|
},
|
|
100
89
|
});
|
|
101
90
|
// Strip leading and forward slashes.
|
|
102
|
-
return
|
|
91
|
+
return newRegexp.toString().slice(1, -1);
|
|
103
92
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { test, expect } from 'vitest';
|
|
2
|
-
import { mergeDeclarations } from './declaration.js';
|
|
2
|
+
import { mergeDeclarations, parsePattern } from './declaration.js';
|
|
3
3
|
const deployConfigDeclarations = [];
|
|
4
4
|
test('Ensure the order of edge functions with FF', () => {
|
|
5
5
|
const deployConfigDeclarations = [
|
|
@@ -18,30 +18,7 @@ test('Ensure the order of edge functions with FF', () => {
|
|
|
18
18
|
const internalFuncConfig = {
|
|
19
19
|
'framework-isc-c': { path: ['/path1', '/path2'] },
|
|
20
20
|
};
|
|
21
|
-
expect(mergeDeclarations(tomlConfig, userFuncConfig, internalFuncConfig, deployConfigDeclarations
|
|
22
|
-
edge_functions_correct_order: true,
|
|
23
|
-
})).toMatchSnapshot();
|
|
24
|
-
});
|
|
25
|
-
test('Ensure the order of edge functions without FF', () => {
|
|
26
|
-
const deployConfigDeclarations = [
|
|
27
|
-
{ function: 'framework-manifest-a', path: '/path1' },
|
|
28
|
-
{ function: 'framework-manifest-c', path: '/path3' },
|
|
29
|
-
{ function: 'framework-manifest-b', path: '/path2' },
|
|
30
|
-
];
|
|
31
|
-
const tomlConfig = [
|
|
32
|
-
{ function: 'user-toml-a', path: '/path1' },
|
|
33
|
-
{ function: 'user-toml-c', path: '/path3' },
|
|
34
|
-
{ function: 'user-toml-b', path: '/path2' },
|
|
35
|
-
];
|
|
36
|
-
const userFuncConfig = {
|
|
37
|
-
'user-isc-c': { path: ['/path1', '/path2'] },
|
|
38
|
-
};
|
|
39
|
-
const internalFuncConfig = {
|
|
40
|
-
'framework-isc-c': { path: ['/path1', '/path2'] },
|
|
41
|
-
};
|
|
42
|
-
expect(mergeDeclarations(tomlConfig, userFuncConfig, internalFuncConfig, deployConfigDeclarations, {
|
|
43
|
-
edge_functions_correct_order: false,
|
|
44
|
-
})).toMatchSnapshot();
|
|
21
|
+
expect(mergeDeclarations(tomlConfig, userFuncConfig, internalFuncConfig, deployConfigDeclarations)).toMatchSnapshot();
|
|
45
22
|
});
|
|
46
23
|
test('In-source config takes precedence over netlify.toml config', () => {
|
|
47
24
|
const tomlConfig = [
|
|
@@ -137,3 +114,15 @@ test('netlify.toml-defined excludedPath are respected', () => {
|
|
|
137
114
|
const declarations = mergeDeclarations(tomlConfig, funcConfig, {}, deployConfigDeclarations);
|
|
138
115
|
expect(declarations).toEqual(expectedDeclarations);
|
|
139
116
|
});
|
|
117
|
+
test('Does not escape front slashes in a regex pattern if they are already escaped', () => {
|
|
118
|
+
const regexPattern = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[\\/#\\?]?$';
|
|
119
|
+
const expected = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[\\/#\\?]?$';
|
|
120
|
+
const actual = parsePattern(regexPattern);
|
|
121
|
+
expect(actual).toEqual(expected);
|
|
122
|
+
});
|
|
123
|
+
test('Escapes front slashes in a regex pattern', () => {
|
|
124
|
+
const regexPattern = '^(?:/(_next/data/[^/]{1,}))?(?:/([^/.]{1,}))/shows(?:/(.*))(.json)?[/#\\?]?$';
|
|
125
|
+
const expected = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[/#\\?]?$';
|
|
126
|
+
const actual = parsePattern(regexPattern);
|
|
127
|
+
expect(actual).toEqual(expected);
|
|
128
|
+
});
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
declare const defaultFlags: {
|
|
2
|
-
edge_functions_correct_order: boolean;
|
|
3
2
|
edge_functions_fail_unsupported_regex: boolean;
|
|
4
|
-
edge_functions_invalid_config_throw: boolean;
|
|
5
3
|
};
|
|
6
4
|
type FeatureFlag = keyof typeof defaultFlags;
|
|
7
5
|
type FeatureFlags = Partial<Record<FeatureFlag, boolean>>;
|
|
8
6
|
declare const getFlags: (input?: Record<string, boolean>, flags?: {
|
|
9
|
-
edge_functions_correct_order: boolean;
|
|
10
7
|
edge_functions_fail_unsupported_regex: boolean;
|
|
11
|
-
edge_functions_invalid_config_throw: boolean;
|
|
12
8
|
}) => FeatureFlags;
|
|
13
9
|
export { defaultFlags, getFlags };
|
|
14
10
|
export type { FeatureFlag, FeatureFlags };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const defaultFlags = {
|
|
2
|
-
edge_functions_correct_order: false,
|
|
3
2
|
edge_functions_fail_unsupported_regex: false,
|
|
4
|
-
edge_functions_invalid_config_throw: false,
|
|
5
3
|
};
|
|
6
4
|
const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
|
|
7
5
|
...result,
|
package/dist/node/manifest.d.ts
CHANGED
|
@@ -44,4 +44,4 @@ interface WriteManifestOptions extends GenerateManifestOptions {
|
|
|
44
44
|
distDirectory: string;
|
|
45
45
|
}
|
|
46
46
|
declare const writeManifest: ({ distDirectory, ...rest }: WriteManifestOptions) => Promise<Manifest>;
|
|
47
|
-
export { generateManifest, Manifest, writeManifest };
|
|
47
|
+
export { generateManifest, Manifest, Route, writeManifest };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { env } from 'process';
|
|
2
2
|
import { test, expect, vi } from 'vitest';
|
|
3
|
+
import { getRouteMatcher } from '../test/util.js';
|
|
3
4
|
import { BundleFormat } from './bundle.js';
|
|
4
5
|
import { generateManifest } from './manifest.js';
|
|
5
6
|
test('Generates a manifest with different bundles', () => {
|
|
@@ -56,23 +57,45 @@ test('Generates a manifest with a generator field', () => {
|
|
|
56
57
|
expect(manifest.function_config).toEqual(expectedFunctionConfig);
|
|
57
58
|
});
|
|
58
59
|
test('Generates a manifest with excluded paths and patterns', () => {
|
|
60
|
+
var _a, _b;
|
|
59
61
|
const functions = [
|
|
60
62
|
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
61
63
|
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
64
|
+
{ name: 'func-3', path: '/path/to/func-3.ts' },
|
|
62
65
|
];
|
|
63
66
|
const declarations = [
|
|
64
67
|
{ function: 'func-1', path: '/f1/*', excludedPath: '/f1/exclude' },
|
|
65
68
|
{ function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: '^/f2/exclude$' },
|
|
69
|
+
{ function: 'func-3', path: '/*', excludedPath: '/**/*.html' },
|
|
66
70
|
];
|
|
67
71
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
68
72
|
const expectedRoutes = [
|
|
69
73
|
{ function: 'func-1', pattern: '^/f1/.*/?$' },
|
|
70
74
|
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
75
|
+
{ function: 'func-3', pattern: '^/.*/?$' },
|
|
71
76
|
];
|
|
72
77
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
73
78
|
expect(manifest.function_config).toEqual({
|
|
74
79
|
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
75
80
|
'func-2': { excluded_patterns: ['^/f2/exclude$'] },
|
|
81
|
+
'func-3': { excluded_patterns: ['^/.*/.*\\.html/?$'] },
|
|
82
|
+
});
|
|
83
|
+
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
84
|
+
const matcher = getRouteMatcher(manifest);
|
|
85
|
+
expect((_a = matcher('/f1/hello')) === null || _a === void 0 ? void 0 : _a.function).toBe('func-1');
|
|
86
|
+
expect((_b = matcher('/grandparent/parent/child/grandchild.html')) === null || _b === void 0 ? void 0 : _b.function).toBeUndefined();
|
|
87
|
+
});
|
|
88
|
+
test('TOML-defined paths can be combined with ISC-defined excluded paths', () => {
|
|
89
|
+
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
90
|
+
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
91
|
+
const userFunctionConfig = {
|
|
92
|
+
'func-1': { excludedPath: '/f1/exclude' },
|
|
93
|
+
};
|
|
94
|
+
const manifest = generateManifest({ bundles: [], declarations, functions, userFunctionConfig });
|
|
95
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
|
|
96
|
+
expect(manifest.routes).toEqual(expectedRoutes);
|
|
97
|
+
expect(manifest.function_config).toEqual({
|
|
98
|
+
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
76
99
|
});
|
|
77
100
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
78
101
|
});
|
|
@@ -43,7 +43,7 @@ const prepareServer = ({ bootstrapURL, deno, distDirectory, flags: denoFlags, fo
|
|
|
43
43
|
});
|
|
44
44
|
let functionsConfig = [];
|
|
45
45
|
if (options.getFunctionsConfig) {
|
|
46
|
-
functionsConfig = await Promise.all(functions.map((func) => getFunctionConfig(func, importMap, deno, logger
|
|
46
|
+
functionsConfig = await Promise.all(functions.map((func) => getFunctionConfig(func, importMap, deno, logger)));
|
|
47
47
|
}
|
|
48
48
|
const success = await waitForServer(port, processRef.ps);
|
|
49
49
|
return {
|
package/dist/test/util.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Manifest } from '../node/manifest.js';
|
|
1
2
|
declare const testLogger: import("../node/logger.js").Logger;
|
|
2
3
|
declare const fixturesDir: string;
|
|
3
4
|
declare const useFixture: (fixtureName: string) => Promise<{
|
|
@@ -5,5 +6,6 @@ declare const useFixture: (fixtureName: string) => Promise<{
|
|
|
5
6
|
cleanup: () => Promise<void>;
|
|
6
7
|
distPath: string;
|
|
7
8
|
}>;
|
|
9
|
+
declare const getRouteMatcher: (manifest: Manifest) => (candidate: string) => import("../node/manifest.js").Route | undefined;
|
|
8
10
|
declare const runESZIP: (eszipPath: string) => Promise<any>;
|
|
9
|
-
export { fixturesDir, testLogger, runESZIP, useFixture };
|
|
11
|
+
export { fixturesDir, getRouteMatcher, testLogger, runESZIP, useFixture };
|
package/dist/test/util.js
CHANGED
|
@@ -35,6 +35,15 @@ const inspectFunction = (path) => `
|
|
|
35
35
|
|
|
36
36
|
console.log(JSON.stringify(responses));
|
|
37
37
|
`;
|
|
38
|
+
const getRouteMatcher = (manifest) => (candidate) => manifest.routes.find((route) => {
|
|
39
|
+
const regex = new RegExp(route.pattern);
|
|
40
|
+
if (!regex.test(candidate)) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const excludedPattern = manifest.function_config[route.function].excluded_patterns;
|
|
44
|
+
const isExcluded = excludedPattern.some((pattern) => new RegExp(pattern).test(candidate));
|
|
45
|
+
return !isExcluded;
|
|
46
|
+
});
|
|
38
47
|
const runESZIP = async (eszipPath) => {
|
|
39
48
|
var _a, _b, _c;
|
|
40
49
|
const tmpDir = await tmp.dir({ unsafeCleanup: true });
|
|
@@ -66,4 +75,4 @@ const runESZIP = async (eszipPath) => {
|
|
|
66
75
|
await tmpDir.cleanup();
|
|
67
76
|
return JSON.parse(result.stdout);
|
|
68
77
|
};
|
|
69
|
-
export { fixturesDir, testLogger, runESZIP, useFixture };
|
|
78
|
+
export { fixturesDir, getRouteMatcher, testLogger, runESZIP, useFixture };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.14.1",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"keywords": [],
|
|
44
44
|
"license": "MIT",
|
|
45
|
-
"repository": "netlify/edge-bundler",
|
|
45
|
+
"repository": "https://github.com/netlify/edge-bundler",
|
|
46
46
|
"bugs": {
|
|
47
47
|
"url": "https://github.com/netlify/edge-bundler/issues"
|
|
48
48
|
},
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@types/node": "^14.18.32",
|
|
59
59
|
"@types/semver": "^7.3.9",
|
|
60
60
|
"@types/uuid": "^9.0.0",
|
|
61
|
-
"@vitest/coverage-c8": "^0.
|
|
61
|
+
"@vitest/coverage-c8": "^0.31.0",
|
|
62
62
|
"archiver": "^5.3.1",
|
|
63
63
|
"chalk": "^4.1.2",
|
|
64
64
|
"cpy": "^9.0.1",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"nock": "^13.2.4",
|
|
68
68
|
"tar": "^6.1.11",
|
|
69
69
|
"typescript": "^5.0.0",
|
|
70
|
-
"vitest": "^0.
|
|
70
|
+
"vitest": "^0.31.0"
|
|
71
71
|
},
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": "^14.16.0 || >=16.0.0"
|