@netlify/edge-bundler 8.5.0 → 8.7.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/dist/node/bundler.js +1 -0
- package/dist/node/declaration.d.ts +1 -0
- package/dist/node/feature_flags.js +1 -0
- package/dist/node/manifest.d.ts +5 -1
- package/dist/node/manifest.js +18 -7
- package/dist/node/manifest.test.js +45 -3
- package/dist/node/validation/manifest/index.test.js +2 -0
- package/dist/node/validation/manifest/schema.d.ts +6 -0
- package/dist/node/validation/manifest/schema.js +1 -0
- package/package.json +1 -1
package/dist/node/bundler.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const defaultFlags = {
|
|
2
2
|
edge_functions_cache_deno_dir: false,
|
|
3
3
|
edge_functions_config_export: false,
|
|
4
|
+
edge_functions_fail_unsupported_regex: false,
|
|
4
5
|
};
|
|
5
6
|
const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
|
|
6
7
|
...result,
|
package/dist/node/manifest.d.ts
CHANGED
|
@@ -2,11 +2,13 @@ import type { Bundle } from './bundle.js';
|
|
|
2
2
|
import { FunctionConfig } from './config.js';
|
|
3
3
|
import { Declaration } from './declaration.js';
|
|
4
4
|
import { EdgeFunction } from './edge_function.js';
|
|
5
|
+
import { FeatureFlags } from './feature_flags.js';
|
|
5
6
|
import { Layer } from './layer.js';
|
|
6
7
|
interface Route {
|
|
7
8
|
function: string;
|
|
8
9
|
name?: string;
|
|
9
10
|
pattern: string;
|
|
11
|
+
generator?: string;
|
|
10
12
|
}
|
|
11
13
|
interface EdgeFunctionConfig {
|
|
12
14
|
excluded_patterns: string[];
|
|
@@ -29,6 +31,7 @@ interface Manifest {
|
|
|
29
31
|
interface GenerateManifestOptions {
|
|
30
32
|
bundles?: Bundle[];
|
|
31
33
|
declarations?: Declaration[];
|
|
34
|
+
featureFlags?: FeatureFlags;
|
|
32
35
|
functions: EdgeFunction[];
|
|
33
36
|
functionConfig?: Record<string, FunctionConfig>;
|
|
34
37
|
importMap?: string;
|
|
@@ -38,8 +41,9 @@ interface Route {
|
|
|
38
41
|
function: string;
|
|
39
42
|
name?: string;
|
|
40
43
|
pattern: string;
|
|
44
|
+
generator?: string;
|
|
41
45
|
}
|
|
42
|
-
declare const generateManifest: ({ bundles, declarations, functions, functionConfig, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
46
|
+
declare const generateManifest: ({ bundles, declarations, featureFlags, functions, functionConfig, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
43
47
|
interface WriteManifestOptions extends GenerateManifestOptions {
|
|
44
48
|
distDirectory: string;
|
|
45
49
|
}
|
package/dist/node/manifest.js
CHANGED
|
@@ -18,7 +18,7 @@ const sanitizeEdgeFunctionConfig = (config) => {
|
|
|
18
18
|
}
|
|
19
19
|
return newConfig;
|
|
20
20
|
};
|
|
21
|
-
const generateManifest = ({ bundles = [], declarations = [], functions, functionConfig = {}, importMap, layers = [], }) => {
|
|
21
|
+
const generateManifest = ({ bundles = [], declarations = [], featureFlags, functions, functionConfig = {}, importMap, layers = [], }) => {
|
|
22
22
|
const preCacheRoutes = [];
|
|
23
23
|
const postCacheRoutes = [];
|
|
24
24
|
const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
|
|
@@ -34,13 +34,14 @@ const generateManifest = ({ bundles = [], declarations = [], functions, function
|
|
|
34
34
|
if (func === undefined) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
|
-
const pattern = getRegularExpression(declaration);
|
|
37
|
+
const pattern = getRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
|
|
38
38
|
const route = {
|
|
39
39
|
function: func.name,
|
|
40
40
|
name: declaration.name,
|
|
41
41
|
pattern: serializePattern(pattern),
|
|
42
|
+
generator: declaration.generator,
|
|
42
43
|
};
|
|
43
|
-
const excludedPattern = getExcludedRegularExpression(declaration);
|
|
44
|
+
const excludedPattern = getExcludedRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
|
|
44
45
|
if (excludedPattern) {
|
|
45
46
|
manifestFunctionConfig[func.name].excluded_patterns.push(serializePattern(excludedPattern));
|
|
46
47
|
}
|
|
@@ -76,24 +77,34 @@ const pathToRegularExpression = (path) => {
|
|
|
76
77
|
const normalizedSource = `^${regularExpression.source}\\/?$`;
|
|
77
78
|
return normalizedSource;
|
|
78
79
|
};
|
|
79
|
-
const getRegularExpression = (declaration) => {
|
|
80
|
+
const getRegularExpression = (declaration, failUnsupportedRegex = false) => {
|
|
80
81
|
if ('pattern' in declaration) {
|
|
81
82
|
try {
|
|
82
83
|
return parsePattern(declaration.pattern);
|
|
83
84
|
}
|
|
84
85
|
catch (error) {
|
|
85
|
-
|
|
86
|
+
// eslint-disable-next-line max-depth
|
|
87
|
+
if (failUnsupportedRegex) {
|
|
88
|
+
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
|
|
89
|
+
}
|
|
90
|
+
console.warn(`Function '${declaration.function}' uses an unsupported regular expression and will not be invoked: ${error.message}`);
|
|
91
|
+
return declaration.pattern;
|
|
86
92
|
}
|
|
87
93
|
}
|
|
88
94
|
return pathToRegularExpression(declaration.path);
|
|
89
95
|
};
|
|
90
|
-
const getExcludedRegularExpression = (declaration) => {
|
|
96
|
+
const getExcludedRegularExpression = (declaration, failUnsupportedRegex = false) => {
|
|
91
97
|
if ('excludedPattern' in declaration && declaration.excludedPattern) {
|
|
92
98
|
try {
|
|
93
99
|
return parsePattern(declaration.excludedPattern);
|
|
94
100
|
}
|
|
95
101
|
catch (error) {
|
|
96
|
-
|
|
102
|
+
// eslint-disable-next-line max-depth
|
|
103
|
+
if (failUnsupportedRegex) {
|
|
104
|
+
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
|
|
105
|
+
}
|
|
106
|
+
console.warn(`Function '${declaration.function}' uses an unsupported regular expression and will therefore not be invoked: ${error.message}`);
|
|
107
|
+
return declaration.excludedPattern;
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
if ('path' in declaration && declaration.excludedPath) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { env } from 'process';
|
|
2
|
-
import { test, expect } from 'vitest';
|
|
2
|
+
import { test, expect, vi } from 'vitest';
|
|
3
3
|
import { BundleFormat } from './bundle.js';
|
|
4
4
|
import { generateManifest } from './manifest.js';
|
|
5
5
|
test('Generates a manifest with different bundles', () => {
|
|
@@ -42,6 +42,27 @@ test('Generates a manifest with display names', () => {
|
|
|
42
42
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
43
43
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
44
44
|
});
|
|
45
|
+
test('Generates a manifest with a generator field', () => {
|
|
46
|
+
const functions = [
|
|
47
|
+
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
48
|
+
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
49
|
+
{ name: 'func-3', path: '/path/to/func-3.ts' },
|
|
50
|
+
];
|
|
51
|
+
const declarations = [
|
|
52
|
+
{ function: 'func-1', generator: '@netlify/fake-plugin@1.0.0', path: '/f1/*' },
|
|
53
|
+
{ function: 'func-2', path: '/f2/*' },
|
|
54
|
+
{ function: 'func-3', generator: '@netlify/fake-plugin@1.0.0', cache: 'manual', path: '/f3' },
|
|
55
|
+
];
|
|
56
|
+
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
57
|
+
const expectedRoutes = [
|
|
58
|
+
{ function: 'func-1', generator: '@netlify/fake-plugin@1.0.0', pattern: '^/f1/.*/?$' },
|
|
59
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
60
|
+
];
|
|
61
|
+
const expectedPostCacheRoutes = [{ function: 'func-3', generator: '@netlify/fake-plugin@1.0.0', pattern: '^/f3/?$' }];
|
|
62
|
+
expect(manifest.routes).toEqual(expectedRoutes);
|
|
63
|
+
expect(manifest.post_cache_routes).toEqual(expectedPostCacheRoutes);
|
|
64
|
+
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
65
|
+
});
|
|
45
66
|
test('Generates a manifest with excluded paths and patterns', () => {
|
|
46
67
|
const functions = [
|
|
47
68
|
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
@@ -164,10 +185,31 @@ test('Generates a manifest with layers', () => {
|
|
|
164
185
|
expect(manifest2.routes).toEqual(expectedRoutes);
|
|
165
186
|
expect(manifest2.layers).toEqual(layers);
|
|
166
187
|
});
|
|
167
|
-
test('
|
|
188
|
+
test('Shows a warning if the regular expression contains a negative lookahead', () => {
|
|
189
|
+
const mockConsoleWarn = vi.fn();
|
|
190
|
+
const consoleWarn = console.warn;
|
|
191
|
+
console.warn = mockConsoleWarn;
|
|
192
|
+
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
193
|
+
const declarations = [{ function: 'func-1', pattern: '^/\\w+(?=\\d)$' }];
|
|
194
|
+
const manifest = generateManifest({
|
|
195
|
+
bundles: [],
|
|
196
|
+
declarations,
|
|
197
|
+
functions,
|
|
198
|
+
});
|
|
199
|
+
console.warn = consoleWarn;
|
|
200
|
+
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/\\w+(?=\\d)$' }]);
|
|
201
|
+
expect(mockConsoleWarn).toHaveBeenCalledOnce();
|
|
202
|
+
expect(mockConsoleWarn).toHaveBeenCalledWith("Function 'func-1' uses an unsupported regular expression and will not be invoked: Regular expressions with lookaheads are not supported");
|
|
203
|
+
});
|
|
204
|
+
test('Throws an error if the regular expression contains a negative lookahead and the `edge_functions_fail_unsupported_regex` flag is set', () => {
|
|
168
205
|
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
169
206
|
const declarations = [{ function: 'func-1', pattern: '^/\\w+(?=\\d)$' }];
|
|
170
|
-
expect(() => generateManifest({
|
|
207
|
+
expect(() => generateManifest({
|
|
208
|
+
bundles: [],
|
|
209
|
+
declarations,
|
|
210
|
+
featureFlags: { edge_functions_fail_unsupported_regex: true },
|
|
211
|
+
functions,
|
|
212
|
+
})).toThrowError(/^Could not parse path declaration of function 'func-1': Regular expressions with lookaheads are not supported$/);
|
|
171
213
|
});
|
|
172
214
|
test('Converts named capture groups to unnamed capture groups in regular expressions', () => {
|
|
173
215
|
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
@@ -14,6 +14,7 @@ const getBaseManifest = () => ({
|
|
|
14
14
|
name: 'name',
|
|
15
15
|
function: 'hello',
|
|
16
16
|
pattern: '^/hello/?$',
|
|
17
|
+
generator: '@netlify/fake-plugin@1.0.0',
|
|
17
18
|
},
|
|
18
19
|
],
|
|
19
20
|
post_cache_routes: [
|
|
@@ -21,6 +22,7 @@ const getBaseManifest = () => ({
|
|
|
21
22
|
name: 'name',
|
|
22
23
|
function: 'hello',
|
|
23
24
|
pattern: '^/hello/?$',
|
|
25
|
+
generator: '@netlify/fake-plugin@1.0.0',
|
|
24
26
|
},
|
|
25
27
|
],
|
|
26
28
|
layers: [
|
|
@@ -36,6 +36,9 @@ declare const edgeManifestSchema: {
|
|
|
36
36
|
format: string;
|
|
37
37
|
errorMessage: string;
|
|
38
38
|
};
|
|
39
|
+
generator: {
|
|
40
|
+
type: string;
|
|
41
|
+
};
|
|
39
42
|
};
|
|
40
43
|
additionalProperties: boolean;
|
|
41
44
|
};
|
|
@@ -57,6 +60,9 @@ declare const edgeManifestSchema: {
|
|
|
57
60
|
format: string;
|
|
58
61
|
errorMessage: string;
|
|
59
62
|
};
|
|
63
|
+
generator: {
|
|
64
|
+
type: string;
|
|
65
|
+
};
|
|
60
66
|
};
|
|
61
67
|
additionalProperties: boolean;
|
|
62
68
|
};
|
|
@@ -18,6 +18,7 @@ const routesSchema = {
|
|
|
18
18
|
format: 'regexPattern',
|
|
19
19
|
errorMessage: 'pattern needs to be a regex that starts with ^ and ends with $ without any additional slashes before and afterwards',
|
|
20
20
|
},
|
|
21
|
+
generator: { type: 'string' },
|
|
21
22
|
},
|
|
22
23
|
additionalProperties: false,
|
|
23
24
|
};
|