@netlify/edge-bundler 8.14.2 → 8.16.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.
@@ -75,7 +75,7 @@ const stage2Loader = (basePath: string, functions: InputFunction[], externals: S
75
75
  return inlineModule(specifier, importMapData)
76
76
  }
77
77
 
78
- if (specifier === PUBLIC_SPECIFIER || externals.has(specifier)) {
78
+ if (specifier === PUBLIC_SPECIFIER || externals.has(specifier) || specifier.startsWith('node:')) {
79
79
  return {
80
80
  kind: 'external',
81
81
  specifier,
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  import { ExecaChildProcess } from 'execa';
3
3
  import { Logger } from './logger.js';
4
- declare const DENO_VERSION_RANGE = "^1.22.0";
4
+ declare const DENO_VERSION_RANGE = "^1.30.0";
5
5
  type OnBeforeDownloadHook = () => void | Promise<void>;
6
6
  type OnAfterDownloadHook = (error?: Error) => void | Promise<void>;
7
7
  interface DenoOptions {
@@ -9,7 +9,7 @@ import { getPathInHome } from './home_path.js';
9
9
  import { getLogger } from './logger.js';
10
10
  import { getBinaryExtension } from './platform.js';
11
11
  const DENO_VERSION_FILE = 'version.txt';
12
- const DENO_VERSION_RANGE = '^1.22.0';
12
+ const DENO_VERSION_RANGE = '^1.30.0';
13
13
  class DenoBridge {
14
14
  constructor(options) {
15
15
  var _a, _b, _c, _d, _e;
@@ -283,13 +283,13 @@ test('Loads declarations and import maps from the deploy configuration and in-so
283
283
  expect(generatedFiles.length).toBe(2);
284
284
  const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
285
285
  const manifest = JSON.parse(manifestFile);
286
- const { bundles, function_config: functionConfig } = manifest;
286
+ const { bundles, function_config: functionConfig, routes } = manifest;
287
287
  expect(bundles.length).toBe(1);
288
288
  expect(bundles[0].format).toBe('eszip2');
289
289
  expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
290
290
  // respects excludedPath from deploy config
291
+ expect(routes[0].excluded_patterns).toEqual(['^/func2/skip/?$']);
291
292
  expect(functionConfig.func2).toEqual({
292
- excluded_patterns: ['^/func2/skip/?$'],
293
293
  name: 'Function two',
294
294
  generator: '@netlify/fake-plugin@1.0.0',
295
295
  });
@@ -336,3 +336,29 @@ test("Ignores entries in `importMapPaths` that don't point to an existing import
336
336
  await cleanup();
337
337
  await importMap.cleanup();
338
338
  });
339
+ test('Handles imports with the `node:` prefix', async () => {
340
+ const { basePath, cleanup, distPath } = await useFixture('imports_node_specifier');
341
+ const userDirectory = join(basePath, 'netlify', 'edge-functions');
342
+ const result = await bundle([userDirectory], distPath, [], {
343
+ basePath,
344
+ importMapPaths: [join(userDirectory, 'import_map.json')],
345
+ });
346
+ const generatedFiles = await readdir(distPath);
347
+ expect(result.functions.length).toBe(1);
348
+ expect(generatedFiles.length).toBe(2);
349
+ const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
350
+ const manifest = JSON.parse(manifestFile);
351
+ expect(() => validateManifest(manifest)).not.toThrowError();
352
+ const { bundles, import_map: importMapURL, routes } = manifest;
353
+ expect(bundles.length).toBe(1);
354
+ expect(bundles[0].format).toBe('eszip2');
355
+ expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
356
+ expect(importMapURL).toBe(importMapSpecifier);
357
+ expect(routes.length).toBe(1);
358
+ expect(routes[0].function).toBe('func1');
359
+ expect(routes[0].pattern).toBe('^/func1/?$');
360
+ const bundlePath = join(distPath, bundles[0].asset);
361
+ const { func1 } = await runESZIP(bundlePath);
362
+ expect(func1).toBe('ok');
363
+ await cleanup();
364
+ });
@@ -160,14 +160,14 @@ test('Loads function paths from the in-source `config` function', async () => {
160
160
  expect(bundles[0].format).toBe('eszip2');
161
161
  expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
162
162
  expect(routes.length).toBe(6);
163
- expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$' });
164
- expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$' });
165
- expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$' });
166
- expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$' });
167
- expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$' });
168
- expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$' });
163
+ expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$', excluded_patterns: [] });
164
+ expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$', excluded_patterns: [] });
165
+ expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$', excluded_patterns: [] });
166
+ expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$', excluded_patterns: [] });
167
+ expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$', excluded_patterns: [] });
168
+ expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$', excluded_patterns: [] });
169
169
  expect(postCacheRoutes.length).toBe(1);
170
- expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$' });
170
+ expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$', excluded_patterns: [] });
171
171
  expect(Object.keys(functionConfig)).toHaveLength(1);
172
172
  expect(functionConfig['user-func5']).toEqual({
173
173
  excluded_patterns: ['^/user-func5/excluded/?$'],
@@ -8,11 +8,11 @@ interface BaseDeclaration {
8
8
  }
9
9
  type DeclarationWithPath = BaseDeclaration & {
10
10
  path: Path;
11
- excludedPath?: Path;
11
+ excludedPath?: Path | Path[];
12
12
  };
13
13
  type DeclarationWithPattern = BaseDeclaration & {
14
14
  pattern: string;
15
- excludedPattern?: string;
15
+ excludedPattern?: string | string[];
16
16
  };
17
17
  export type Declaration = DeclarationWithPath | DeclarationWithPattern;
18
18
  export declare const mergeDeclarations: (tomlDeclarations: Declaration[], userFunctionsConfig: Record<string, FunctionConfig>, internalFunctionsConfig: Record<string, FunctionConfig>, deployConfigDeclarations: Declaration[], _featureFlags?: FeatureFlags) => Declaration[];
@@ -7,6 +7,7 @@ import { Layer } from './layer.js';
7
7
  interface Route {
8
8
  function: string;
9
9
  pattern: string;
10
+ excluded_patterns: string[];
10
11
  }
11
12
  interface EdgeFunctionConfig {
12
13
  excluded_patterns: string[];
@@ -58,14 +58,12 @@ const generateManifest = ({ bundles = [], declarations = [], featureFlags, funct
58
58
  return;
59
59
  }
60
60
  const pattern = getRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
61
+ const excludedPattern = getExcludedRegularExpressions(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
61
62
  const route = {
62
63
  function: func.name,
63
64
  pattern: serializePattern(pattern),
65
+ excluded_patterns: excludedPattern.map(serializePattern),
64
66
  };
65
- const excludedPattern = getExcludedRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
66
- if (excludedPattern) {
67
- manifestFunctionConfig[func.name].excluded_patterns.push(serializePattern(excludedPattern));
68
- }
69
67
  if (declaration.cache === "manual" /* Cache.Manual */) {
70
68
  postCacheRoutes.push(route);
71
69
  }
@@ -114,23 +112,29 @@ const getRegularExpression = (declaration, failUnsupportedRegex = false) => {
114
112
  }
115
113
  return pathToRegularExpression(declaration.path);
116
114
  };
117
- const getExcludedRegularExpression = (declaration, failUnsupportedRegex = false) => {
115
+ const getExcludedRegularExpressions = (declaration, failUnsupportedRegex = false) => {
118
116
  if ('excludedPattern' in declaration && declaration.excludedPattern) {
119
- try {
120
- return parsePattern(declaration.excludedPattern);
121
- }
122
- catch (error) {
123
- // eslint-disable-next-line max-depth
124
- if (failUnsupportedRegex) {
125
- throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
117
+ const excludedPatterns = Array.isArray(declaration.excludedPattern)
118
+ ? declaration.excludedPattern
119
+ : [declaration.excludedPattern];
120
+ return excludedPatterns.map((excludedPattern) => {
121
+ try {
122
+ return parsePattern(excludedPattern);
126
123
  }
127
- console.warn(`Function '${declaration.function}' uses an unsupported regular expression and will therefore not be invoked: ${error.message}`);
128
- return declaration.excludedPattern;
129
- }
124
+ catch (error) {
125
+ if (failUnsupportedRegex) {
126
+ throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
127
+ }
128
+ console.warn(`Function '${declaration.function}' uses an unsupported regular expression and will therefore not be invoked: ${error.message}`);
129
+ return excludedPattern;
130
+ }
131
+ });
130
132
  }
131
133
  if ('path' in declaration && declaration.excludedPath) {
132
- return pathToRegularExpression(declaration.excludedPath);
134
+ const paths = Array.isArray(declaration.excludedPath) ? declaration.excludedPath : [declaration.excludedPath];
135
+ return paths.map(pathToRegularExpression);
133
136
  }
137
+ return [];
134
138
  };
135
139
  const writeManifest = async ({ distDirectory, ...rest }) => {
136
140
  const manifest = generateManifest(rest);
@@ -21,7 +21,7 @@ test('Generates a manifest with different bundles', () => {
21
21
  { asset: bundle1.hash + bundle1.extension, format: bundle1.format },
22
22
  { asset: bundle2.hash + bundle2.extension, format: bundle2.format },
23
23
  ];
24
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
24
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
25
25
  expect(manifest.bundles).toEqual(expectedBundles);
26
26
  expect(manifest.routes).toEqual(expectedRoutes);
27
27
  expect(manifest.bundler_version).toBe(env.npm_package_version);
@@ -35,7 +35,7 @@ test('Generates a manifest with display names', () => {
35
35
  },
36
36
  };
37
37
  const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig });
38
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
38
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
39
39
  expect(manifest.function_config).toEqual({
40
40
  'func-1': { name: 'Display Name' },
41
41
  });
@@ -51,7 +51,7 @@ test('Generates a manifest with a generator field', () => {
51
51
  },
52
52
  };
53
53
  const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig });
54
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
54
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
55
55
  const expectedFunctionConfig = { 'func-1': { generator: '@netlify/fake-plugin@1.0.0' } };
56
56
  expect(manifest.routes).toEqual(expectedRoutes);
57
57
  expect(manifest.function_config).toEqual(expectedFunctionConfig);
@@ -65,21 +65,17 @@ test('Generates a manifest with excluded paths and patterns', () => {
65
65
  ];
66
66
  const declarations = [
67
67
  { function: 'func-1', path: '/f1/*', excludedPath: '/f1/exclude' },
68
- { function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: '^/f2/exclude$' },
68
+ { function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: ['^/f2/exclude$', '^/f2/exclude-as-well$'] },
69
69
  { function: 'func-3', path: '/*', excludedPath: '/**/*.html' },
70
70
  ];
71
71
  const manifest = generateManifest({ bundles: [], declarations, functions });
72
72
  const expectedRoutes = [
73
- { function: 'func-1', pattern: '^/f1/.*/?$' },
74
- { function: 'func-2', pattern: '^/f2/.*/?$' },
75
- { function: 'func-3', pattern: '^/.*/?$' },
73
+ { function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: ['^/f1/exclude/?$'] },
74
+ { function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: ['^/f2/exclude$', '^/f2/exclude-as-well$'] },
75
+ { function: 'func-3', pattern: '^/.*/?$', excluded_patterns: ['^/.*/.*\\.html/?$'] },
76
76
  ];
77
77
  expect(manifest.routes).toEqual(expectedRoutes);
78
- expect(manifest.function_config).toEqual({
79
- 'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
80
- 'func-2': { excluded_patterns: ['^/f2/exclude$'] },
81
- 'func-3': { excluded_patterns: ['^/.*/.*\\.html/?$'] },
82
- });
78
+ expect(manifest.function_config).toEqual({});
83
79
  expect(manifest.bundler_version).toBe(env.npm_package_version);
84
80
  const matcher = getRouteMatcher(manifest);
85
81
  expect((_a = matcher('/f1/hello')) === null || _a === void 0 ? void 0 : _a.function).toBe('func-1');
@@ -92,7 +88,7 @@ test('TOML-defined paths can be combined with ISC-defined excluded paths', () =>
92
88
  'func-1': { excludedPath: '/f1/exclude' },
93
89
  };
94
90
  const manifest = generateManifest({ bundles: [], declarations, functions, userFunctionConfig });
95
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
91
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
96
92
  expect(manifest.routes).toEqual(expectedRoutes);
97
93
  expect(manifest.function_config).toEqual({
98
94
  'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
@@ -149,6 +145,49 @@ test('Filters out internal in-source configurations in user created functions',
149
145
  },
150
146
  });
151
147
  });
148
+ test('excludedPath from ISC goes into function_config, TOML goes into routes', () => {
149
+ const functions = [{ name: 'customisation', path: '/path/to/customisation.ts' }];
150
+ const declarations = [
151
+ { function: 'customisation', path: '/showcases/*' },
152
+ { function: 'customisation', path: '/checkout/*', excludedPath: ['/*/terms-and-conditions'] },
153
+ ];
154
+ const userFunctionConfig = {
155
+ customisation: {
156
+ excludedPath: ['/*.css', '/*.jpg'],
157
+ },
158
+ };
159
+ const internalFunctionConfig = {};
160
+ const manifest = generateManifest({
161
+ bundles: [],
162
+ declarations,
163
+ functions,
164
+ userFunctionConfig,
165
+ internalFunctionConfig,
166
+ });
167
+ expect(manifest.routes).toEqual([
168
+ {
169
+ function: 'customisation',
170
+ pattern: '^/showcases/.*/?$',
171
+ excluded_patterns: [],
172
+ },
173
+ {
174
+ function: 'customisation',
175
+ pattern: '^/checkout/.*/?$',
176
+ excluded_patterns: ['^/.*/terms-and-conditions/?$'],
177
+ },
178
+ ]);
179
+ expect(manifest.function_config).toEqual({
180
+ customisation: {
181
+ excluded_patterns: ['^/.*\\.css/?$', '^/.*\\.jpg/?$'],
182
+ },
183
+ });
184
+ const matcher = getRouteMatcher(manifest);
185
+ expect(matcher('/showcases/boho-style')).toBeDefined();
186
+ expect(matcher('/checkout/address')).toBeDefined();
187
+ expect(matcher('/checkout/terms-and-conditions')).toBeUndefined();
188
+ expect(matcher('/checkout/scrooge-mc-duck-animation.css')).toBeUndefined();
189
+ expect(matcher('/showcases/boho-style/expensive-chair.jpg')).toBeUndefined();
190
+ });
152
191
  test('Includes failure modes in manifest', () => {
153
192
  const functions = [
154
193
  { name: 'func-1', path: '/path/to/func-1.ts' },
@@ -180,7 +219,7 @@ test('Excludes functions for which there are function files but no matching conf
180
219
  ];
181
220
  const declarations = [{ function: 'func-1', path: '/f1' }];
182
221
  const manifest = generateManifest({ bundles: [bundle1], declarations, functions });
183
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
222
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
184
223
  expect(manifest.routes).toEqual(expectedRoutes);
185
224
  });
186
225
  test('Excludes functions for which there are config declarations but no matching function files', () => {
@@ -195,14 +234,14 @@ test('Excludes functions for which there are config declarations but no matching
195
234
  { function: 'func-2', path: '/f2' },
196
235
  ];
197
236
  const manifest = generateManifest({ bundles: [bundle1], declarations, functions });
198
- const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$' }];
237
+ const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$', excluded_patterns: [] }];
199
238
  expect(manifest.routes).toEqual(expectedRoutes);
200
239
  });
201
240
  test('Generates a manifest without bundles', () => {
202
241
  const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
203
242
  const declarations = [{ function: 'func-1', path: '/f1' }];
204
243
  const manifest = generateManifest({ bundles: [], declarations, functions });
205
- const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
244
+ const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
206
245
  expect(manifest.bundles).toEqual([]);
207
246
  expect(manifest.routes).toEqual(expectedRoutes);
208
247
  expect(manifest.bundler_version).toBe(env.npm_package_version);
@@ -234,10 +273,10 @@ test('Generates a manifest with pre and post-cache routes', () => {
234
273
  { asset: bundle2.hash + bundle2.extension, format: bundle2.format },
235
274
  ];
236
275
  const expectedPreCacheRoutes = [
237
- { function: 'func-1', name: undefined, pattern: '^/f1/?$' },
238
- { function: 'func-2', name: undefined, pattern: '^/f2/?$' },
276
+ { function: 'func-1', name: undefined, pattern: '^/f1/?$', excluded_patterns: [] },
277
+ { function: 'func-2', name: undefined, pattern: '^/f2/?$', excluded_patterns: [] },
239
278
  ];
240
- const expectedPostCacheRoutes = [{ function: 'func-3', name: undefined, pattern: '^/f3/?$' }];
279
+ const expectedPostCacheRoutes = [{ function: 'func-3', name: undefined, pattern: '^/f3/?$', excluded_patterns: [] }];
241
280
  expect(manifest.bundles).toEqual(expectedBundles);
242
281
  expect(manifest.routes).toEqual(expectedPreCacheRoutes);
243
282
  expect(manifest.post_cache_routes).toEqual(expectedPostCacheRoutes);
@@ -253,8 +292,8 @@ test('Generates a manifest with layers', () => {
253
292
  { function: 'func-2', path: '/f2/*' },
254
293
  ];
255
294
  const expectedRoutes = [
256
- { function: 'func-1', pattern: '^/f1/.*/?$' },
257
- { function: 'func-2', pattern: '^/f2/.*/?$' },
295
+ { function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] },
296
+ { function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: [] },
258
297
  ];
259
298
  const layers = [
260
299
  {
@@ -281,7 +320,7 @@ test('Shows a warning if the regular expression contains a negative lookahead',
281
320
  functions,
282
321
  });
283
322
  console.warn = consoleWarn;
284
- expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/\\w+(?=\\d)$' }]);
323
+ expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/\\w+(?=\\d)$', excluded_patterns: [] }]);
285
324
  expect(mockConsoleWarn).toHaveBeenCalledOnce();
286
325
  expect(mockConsoleWarn).toHaveBeenCalledWith("Function 'func-1' uses an unsupported regular expression and will not be invoked: Regular expressions with lookaheads are not supported");
287
326
  });
@@ -299,5 +338,5 @@ test('Converts named capture groups to unnamed capture groups in regular express
299
338
  const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
300
339
  const declarations = [{ function: 'func-1', pattern: '^/(?<name>\\w+)$' }];
301
340
  const manifest = generateManifest({ bundles: [], declarations, functions });
302
- expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(\\w+)$' }]);
341
+ expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(\\w+)$', excluded_patterns: [] }]);
303
342
  });
@@ -36,6 +36,14 @@ declare const edgeManifestSchema: {
36
36
  format: string;
37
37
  errorMessage: string;
38
38
  };
39
+ excluded_patterns: {
40
+ type: string;
41
+ items: {
42
+ type: string;
43
+ format: string;
44
+ errorMessage: string;
45
+ };
46
+ };
39
47
  generator: {
40
48
  type: string;
41
49
  };
@@ -60,6 +68,14 @@ declare const edgeManifestSchema: {
60
68
  format: string;
61
69
  errorMessage: string;
62
70
  };
71
+ excluded_patterns: {
72
+ type: string;
73
+ items: {
74
+ type: string;
75
+ format: string;
76
+ errorMessage: string;
77
+ };
78
+ };
63
79
  generator: {
64
80
  type: string;
65
81
  };
@@ -7,6 +7,14 @@ const bundlesSchema = {
7
7
  },
8
8
  additionalProperties: false,
9
9
  };
10
+ const excludedPatternsSchema = {
11
+ type: 'array',
12
+ items: {
13
+ type: 'string',
14
+ format: 'regexPattern',
15
+ errorMessage: 'excluded_patterns must be an array of regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
16
+ },
17
+ };
10
18
  const routesSchema = {
11
19
  type: 'object',
12
20
  required: ['function', 'pattern'],
@@ -18,6 +26,7 @@ const routesSchema = {
18
26
  format: 'regexPattern',
19
27
  errorMessage: 'pattern must be a regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
20
28
  },
29
+ excluded_patterns: excludedPatternsSchema,
21
30
  generator: { type: 'string' },
22
31
  },
23
32
  additionalProperties: false,
@@ -26,14 +35,7 @@ const functionConfigSchema = {
26
35
  type: 'object',
27
36
  required: [],
28
37
  properties: {
29
- excluded_patterns: {
30
- type: 'array',
31
- items: {
32
- type: 'string',
33
- format: 'regexPattern',
34
- errorMessage: 'excluded_patterns must be an array of regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
35
- },
36
- },
38
+ excluded_patterns: excludedPatternsSchema,
37
39
  on_error: { type: 'string' },
38
40
  },
39
41
  };
package/dist/test/util.js CHANGED
@@ -36,12 +36,16 @@ const inspectFunction = (path) => `
36
36
  console.log(JSON.stringify(responses));
37
37
  `;
38
38
  const getRouteMatcher = (manifest) => (candidate) => manifest.routes.find((route) => {
39
+ var _a, _b;
39
40
  const regex = new RegExp(route.pattern);
40
41
  if (!regex.test(candidate)) {
41
42
  return false;
42
43
  }
43
- const excludedPattern = manifest.function_config[route.function].excluded_patterns;
44
- const isExcluded = excludedPattern.some((pattern) => new RegExp(pattern).test(candidate));
44
+ if (route.excluded_patterns.some((pattern) => new RegExp(pattern).test(candidate))) {
45
+ return false;
46
+ }
47
+ const excludedPatterns = (_b = (_a = manifest.function_config[route.function]) === null || _a === void 0 ? void 0 : _a.excluded_patterns) !== null && _b !== void 0 ? _b : [];
48
+ const isExcluded = excludedPatterns.some((pattern) => new RegExp(pattern).test(candidate));
45
49
  return !isExcluded;
46
50
  });
47
51
  const runESZIP = async (eszipPath) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/edge-bundler",
3
- "version": "8.14.2",
3
+ "version": "8.16.0",
4
4
  "description": "Intelligently prepare Netlify Edge Functions for deployment",
5
5
  "type": "module",
6
6
  "main": "./dist/node/index.js",