@netlify/edge-bundler 7.0.1 → 7.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.
@@ -278,10 +278,12 @@ test('Loads declarations and import maps from the deploy configuration', async (
278
278
  expect(generatedFiles.length).toBe(2);
279
279
  const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
280
280
  const manifest = JSON.parse(manifestFile);
281
- const { bundles } = manifest;
281
+ const { bundles, routes } = manifest;
282
282
  expect(bundles.length).toBe(1);
283
283
  expect(bundles[0].format).toBe('eszip2');
284
284
  expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
285
+ // respects excludedPath from deploy config
286
+ expect(routes[1].excluded_pattern).toEqual('^/func2/skip/?$');
285
287
  await cleanup();
286
288
  });
287
289
  test("Ignores entries in `importMapPaths` that don't point to an existing import map file", async () => {
@@ -7,9 +7,11 @@ interface BaseDeclaration {
7
7
  }
8
8
  type DeclarationWithPath = BaseDeclaration & {
9
9
  path: string;
10
+ excludedPath?: string;
10
11
  };
11
12
  type DeclarationWithPattern = BaseDeclaration & {
12
13
  pattern: string;
14
+ excludedPattern?: string;
13
15
  };
14
16
  type Declaration = DeclarationWithPath | DeclarationWithPattern;
15
17
  export declare const getDeclarationsFromConfig: (tomlDeclarations: Declaration[], functionsConfig: Record<string, FunctionConfig>, deployConfig: DeployConfig) => Declaration[];
@@ -92,3 +92,10 @@ test('In-source config works if path property is an empty array with cache value
92
92
  const expectedDeclarations = [{ function: 'json', path: '/json-toml', cache: 'manual' }];
93
93
  expect(getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig)).toEqual(expectedDeclarations);
94
94
  });
95
+ test('netlify.toml-defined excludedPath are respected', () => {
96
+ const tomlConfig = [{ function: 'geolocation', path: '/geo/*', excludedPath: '/geo/exclude' }];
97
+ const funcConfig = {};
98
+ const expectedDeclarations = [{ function: 'geolocation', path: '/geo/*', excludedPath: '/geo/exclude' }];
99
+ const declarations = getDeclarationsFromConfig(tomlConfig, funcConfig, deployConfig);
100
+ expect(declarations).toEqual(expectedDeclarations);
101
+ });
@@ -9,6 +9,12 @@ interface GenerateManifestOptions {
9
9
  importMap?: string;
10
10
  layers?: Layer[];
11
11
  }
12
+ interface Route {
13
+ function: string;
14
+ name?: string;
15
+ pattern: string;
16
+ excluded_pattern?: string;
17
+ }
12
18
  interface Manifest {
13
19
  bundler_version: string;
14
20
  bundles: {
@@ -20,16 +26,13 @@ interface Manifest {
20
26
  name: string;
21
27
  flag: string;
22
28
  }[];
23
- routes: {
24
- function: string;
25
- name?: string;
26
- pattern: string;
27
- }[];
28
- post_cache_routes: {
29
- function: string;
30
- name?: string;
31
- pattern: string;
32
- }[];
29
+ routes: Route[];
30
+ post_cache_routes: Route[];
31
+ }
32
+ interface Route {
33
+ function: string;
34
+ name?: string;
35
+ pattern: string;
33
36
  }
34
37
  declare const generateManifest: ({ bundles, declarations, functions, importMap, layers, }: GenerateManifestOptions) => Manifest;
35
38
  interface WriteManifestOptions {
@@ -3,6 +3,7 @@ import { join } from 'path';
3
3
  import globToRegExp from 'glob-to-regexp';
4
4
  import { getPackageVersion } from './package_json.js';
5
5
  import { nonNullable } from './utils/non_nullable.js';
6
+ const serializePattern = (regex) => regex.source.replace(/\\\//g, '/');
6
7
  const generateManifest = ({ bundles = [], declarations = [], functions, importMap, layers = [], }) => {
7
8
  const preCacheRoutes = [];
8
9
  const postCacheRoutes = [];
@@ -12,12 +13,15 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
12
13
  return;
13
14
  }
14
15
  const pattern = getRegularExpression(declaration);
15
- const serializablePattern = pattern.source.replace(/\\\//g, '/');
16
16
  const route = {
17
17
  function: func.name,
18
18
  name: declaration.name,
19
- pattern: serializablePattern,
19
+ pattern: serializePattern(pattern),
20
20
  };
21
+ const excludedPattern = getExcludedRegularExpression(declaration);
22
+ if (excludedPattern) {
23
+ route.excluded_pattern = serializePattern(excludedPattern);
24
+ }
21
25
  if (declaration.cache === "manual" /* Cache.Manual */) {
22
26
  postCacheRoutes.push(route);
23
27
  }
@@ -39,19 +43,30 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
39
43
  };
40
44
  return manifest;
41
45
  };
42
- const getRegularExpression = (declaration) => {
43
- if ('pattern' in declaration) {
44
- return new RegExp(declaration.pattern);
45
- }
46
+ const pathToRegularExpression = (path) => {
46
47
  // We use the global flag so that `globToRegExp` will not wrap the expression
47
48
  // with `^` and `$`. We'll do that ourselves.
48
- const regularExpression = globToRegExp(declaration.path, { flags: 'g' });
49
+ const regularExpression = globToRegExp(path, { flags: 'g' });
49
50
  // Wrapping the expression source with `^` and `$`. Also, adding an optional
50
51
  // trailing slash, so that a declaration of `path: "/foo"` matches requests
51
52
  // for both `/foo` and `/foo/`.
52
53
  const normalizedSource = `^${regularExpression.source}\\/?$`;
53
54
  return new RegExp(normalizedSource);
54
55
  };
56
+ const getRegularExpression = (declaration) => {
57
+ if ('pattern' in declaration) {
58
+ return new RegExp(declaration.pattern);
59
+ }
60
+ return pathToRegularExpression(declaration.path);
61
+ };
62
+ const getExcludedRegularExpression = (declaration) => {
63
+ if ('pattern' in declaration && declaration.excludedPattern) {
64
+ return new RegExp(declaration.excludedPattern);
65
+ }
66
+ if ('path' in declaration && declaration.excludedPath) {
67
+ return pathToRegularExpression(declaration.excludedPath);
68
+ }
69
+ };
55
70
  const writeManifest = async ({ bundles, declarations = [], distDirectory, functions, importMap, layers, }) => {
56
71
  const manifest = generateManifest({ bundles, declarations, functions, importMap, layers });
57
72
  const manifestPath = join(distDirectory, 'manifest.json');
@@ -42,6 +42,23 @@ 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 excluded paths and patterns', () => {
46
+ const functions = [
47
+ { name: 'func-1', path: '/path/to/func-1.ts' },
48
+ { name: 'func-2', path: '/path/to/func-2.ts' },
49
+ ];
50
+ const declarations = [
51
+ { function: 'func-1', name: 'Display Name', path: '/f1/*', excludedPath: '/f1/exclude' },
52
+ { function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: '^/f2/exclude$' },
53
+ ];
54
+ const manifest = generateManifest({ bundles: [], declarations, functions });
55
+ const expectedRoutes = [
56
+ { function: 'func-1', name: 'Display Name', pattern: '^/f1/.*/?$', excluded_pattern: '^/f1/exclude/?$' },
57
+ { function: 'func-2', pattern: '^/f2/.*/?$', excluded_pattern: '^/f2/exclude$' },
58
+ ];
59
+ expect(manifest.routes).toEqual(expectedRoutes);
60
+ expect(manifest.bundler_version).toBe(env.npm_package_version);
61
+ });
45
62
  test('Excludes functions for which there are function files but no matching config declarations', () => {
46
63
  const bundle1 = {
47
64
  extension: '.ext2',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/edge-bundler",
3
- "version": "7.0.1",
3
+ "version": "7.1.0",
4
4
  "description": "Intelligently prepare Netlify Edge Functions for deployment",
5
5
  "type": "module",
6
6
  "main": "./dist/node/index.js",