@netlify/edge-bundler 11.2.1 → 11.3.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.
@@ -52,7 +52,7 @@ declare class DenoBridge {
52
52
  }>;
53
53
  getEnvironmentVariables(inputEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
54
54
  run(args: string[], { env: inputEnv, extendEnv, rejectOnExitCode, stderr, stdout }?: RunOptions): Promise<import("execa").ExecaReturnValue<string>>;
55
- runInBackground(args: string[], ref?: ProcessRef, { env: inputEnv, extendEnv, stderr, stdout }?: RunOptions): Promise<void>;
55
+ runInBackground(args: string[], ref?: ProcessRef, { env: inputEnv, extendEnv, pipeOutput, stderr, stdout }?: RunOptions): Promise<void>;
56
56
  }
57
57
  export { DENO_VERSION_RANGE, DenoBridge };
58
58
  export type { DenoOptions, OnAfterDownloadHook, OnBeforeDownloadHook, ProcessRef };
@@ -151,11 +151,11 @@ class DenoBridge {
151
151
  }
152
152
  // Runs the Deno CLI in the background, assigning a reference of the child
153
153
  // process to a `ps` property in the `ref` argument, if one is supplied.
154
- async runInBackground(args, ref, { env: inputEnv, extendEnv = true, stderr, stdout } = {}) {
154
+ async runInBackground(args, ref, { env: inputEnv, extendEnv = true, pipeOutput, stderr, stdout } = {}) {
155
155
  const { path: binaryPath } = await this.getBinaryPath();
156
156
  const env = this.getEnvironmentVariables(inputEnv);
157
157
  const options = { env, extendEnv };
158
- const ps = DenoBridge.runWithBinary(binaryPath, args, { options, stderr, stdout });
158
+ const ps = DenoBridge.runWithBinary(binaryPath, args, { options, pipeOutput, stderr, stdout });
159
159
  if (ref !== undefined) {
160
160
  // eslint-disable-next-line no-param-reassign
161
161
  ref.ps = ps;
@@ -19,8 +19,7 @@ export type Declaration = DeclarationWithPath | DeclarationWithPattern;
19
19
  export declare const mergeDeclarations: (tomlDeclarations: Declaration[], userFunctionsConfig: Record<string, FunctionConfig>, internalFunctionsConfig: Record<string, FunctionConfig>, deployConfigDeclarations: Declaration[], _featureFlags?: FeatureFlags) => Declaration[];
20
20
  /**
21
21
  * Normalizes a regular expression, ensuring it has a leading `^` and trailing
22
- * `$` characters. It also converts the regular expression from PCRE to RE2 if
23
- * needed.
22
+ * `$` characters.
24
23
  */
25
- export declare const parsePattern: (pattern: string, pcreRegexpEngine: boolean) => string;
24
+ export declare const normalizePattern: (pattern: string) => string;
26
25
  export {};
@@ -1,4 +1,3 @@
1
- import regexpAST from 'regexp-tree';
2
1
  export const mergeDeclarations = (tomlDeclarations, userFunctionsConfig, internalFunctionsConfig, deployConfigDeclarations,
3
2
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
4
3
  _featureFlags = {}) => {
@@ -68,10 +67,9 @@ const createDeclarationsFromFunctionConfigs = (functionConfigs, functionsVisited
68
67
  };
69
68
  /**
70
69
  * Normalizes a regular expression, ensuring it has a leading `^` and trailing
71
- * `$` characters. It also converts the regular expression from PCRE to RE2 if
72
- * needed.
70
+ * `$` characters.
73
71
  */
74
- export const parsePattern = (pattern, pcreRegexpEngine) => {
72
+ export const normalizePattern = (pattern) => {
75
73
  let enclosedPattern = pattern;
76
74
  if (!pattern.startsWith('^')) {
77
75
  enclosedPattern = `^${enclosedPattern}`;
@@ -80,34 +78,6 @@ export const parsePattern = (pattern, pcreRegexpEngine) => {
80
78
  enclosedPattern = `${enclosedPattern}$`;
81
79
  }
82
80
  const regexp = new RegExp(enclosedPattern);
83
- const regexpString = pcreRegexpEngine ? regexp.toString() : transformPCRERegexp(regexp);
84
81
  // Strip leading and forward slashes.
85
- return regexpString.slice(1, -1);
86
- };
87
- /**
88
- * Transforms a PCRE regular expression into a RE2 expression, compatible
89
- * with the Go engine used in our edge nodes.
90
- */
91
- const transformPCRERegexp = (regexp) => {
92
- const newRegexp = regexpAST.transform(regexp, {
93
- Assertion(path) {
94
- // Lookaheads are not supported. If we find one, throw an error.
95
- if (path.node.kind === 'Lookahead') {
96
- throw new Error('Regular expressions with lookaheads are not supported');
97
- }
98
- },
99
- Group(path) {
100
- // Named captured groups in JavaScript use a different syntax than in Go.
101
- // If we find one, convert it to an unnamed capture group, which is valid
102
- // in both engines.
103
- if ('name' in path.node && path.node.name !== undefined) {
104
- path.replace({
105
- ...path.node,
106
- name: undefined,
107
- nameRaw: undefined,
108
- });
109
- }
110
- },
111
- });
112
- return newRegexp.toString();
82
+ return regexp.toString().slice(1, -1);
113
83
  };
@@ -1,5 +1,5 @@
1
1
  import { test, expect } from 'vitest';
2
- import { mergeDeclarations, parsePattern } from './declaration.js';
2
+ import { mergeDeclarations, normalizePattern } from './declaration.js';
3
3
  const deployConfigDeclarations = [];
4
4
  test('Ensure the order of edge functions with FF', () => {
5
5
  const deployConfigDeclarations = [
@@ -117,18 +117,15 @@ test('netlify.toml-defined excludedPath are respected', () => {
117
117
  test('Does not escape front slashes in a regex pattern if they are already escaped', () => {
118
118
  const regexPattern = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[\\/#\\?]?$';
119
119
  const expected = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[\\/#\\?]?$';
120
- expect(parsePattern(regexPattern, false)).toEqual(expected);
121
- expect(parsePattern(regexPattern, true)).toEqual(expected);
120
+ expect(normalizePattern(regexPattern)).toEqual(expected);
122
121
  });
123
122
  test('Escapes front slashes in a regex pattern', () => {
124
123
  const regexPattern = '^(?:/(_next/data/[^/]{1,}))?(?:/([^/.]{1,}))/shows(?:/(.*))(.json)?[/#\\?]?$';
125
124
  const expected = '^(?:\\/(_next\\/data\\/[^/]{1,}))?(?:\\/([^/.]{1,}))\\/shows(?:\\/(.*))(.json)?[/#\\?]?$';
126
- expect(parsePattern(regexPattern, false)).toEqual(expected);
127
- expect(parsePattern(regexPattern, true)).toEqual(expected);
125
+ expect(normalizePattern(regexPattern)).toEqual(expected);
128
126
  });
129
127
  test('Ensures pattern match on the whole path', () => {
130
128
  const regexPattern = '/foo/.*/bar';
131
129
  const expected = '^\\/foo\\/.*\\/bar$';
132
- expect(parsePattern(regexPattern, false)).toEqual(expected);
133
- expect(parsePattern(regexPattern, true)).toEqual(expected);
130
+ expect(normalizePattern(regexPattern)).toEqual(expected);
134
131
  });
@@ -1,10 +1,6 @@
1
- declare const defaultFlags: {
2
- edge_bundler_pcre_regexp: boolean;
3
- };
1
+ declare const defaultFlags: {};
4
2
  type FeatureFlag = keyof typeof defaultFlags;
5
3
  type FeatureFlags = Partial<Record<FeatureFlag, boolean>>;
6
- declare const getFlags: (input?: Record<string, boolean>, flags?: {
7
- edge_bundler_pcre_regexp: boolean;
8
- }) => FeatureFlags;
4
+ declare const getFlags: (input?: Record<string, boolean>, flags?: {}) => FeatureFlags;
9
5
  export { defaultFlags, getFlags };
10
6
  export type { FeatureFlag, FeatureFlags };
@@ -1,6 +1,4 @@
1
- const defaultFlags = {
2
- edge_bundler_pcre_regexp: false,
3
- };
1
+ const defaultFlags = {};
4
2
  const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
5
3
  ...result,
6
4
  [key]: input[key] === undefined ? defaultValue : input[key],
@@ -42,7 +42,7 @@ interface GenerateManifestOptions {
42
42
  layers?: Layer[];
43
43
  userFunctionConfig?: Record<string, FunctionConfig>;
44
44
  }
45
- declare const generateManifest: ({ bundles, declarations, featureFlags, functions, userFunctionConfig, internalFunctionConfig, importMap, layers, }: GenerateManifestOptions) => {
45
+ declare const generateManifest: ({ bundles, declarations, functions, userFunctionConfig, internalFunctionConfig, importMap, layers, }: GenerateManifestOptions) => {
46
46
  declarationsWithoutFunction: string[];
47
47
  manifest: Manifest;
48
48
  unroutedFunctions: string[];
@@ -1,7 +1,7 @@
1
1
  import { promises as fs } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { wrapBundleError } from './bundle_error.js';
4
- import { parsePattern } from './declaration.js';
4
+ import { normalizePattern } from './declaration.js';
5
5
  import { getPackageVersion } from './package_json.js';
6
6
  import { nonNullable } from './utils/non_nullable.js';
7
7
  import { ExtendedURLPattern } from './utils/urlpattern.js';
@@ -46,7 +46,7 @@ const normalizeMethods = (method, name) => {
46
46
  return method.toUpperCase();
47
47
  });
48
48
  };
49
- const generateManifest = ({ bundles = [], declarations = [], featureFlags, functions, userFunctionConfig = {}, internalFunctionConfig = {}, importMap, layers = [], }) => {
49
+ const generateManifest = ({ bundles = [], declarations = [], functions, userFunctionConfig = {}, internalFunctionConfig = {}, importMap, layers = [], }) => {
50
50
  const preCacheRoutes = [];
51
51
  const postCacheRoutes = [];
52
52
  const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
@@ -74,14 +74,14 @@ const generateManifest = ({ bundles = [], declarations = [], featureFlags, funct
74
74
  declarationsWithoutFunction.add(declaration.function);
75
75
  return;
76
76
  }
77
- const pattern = getRegularExpression(declaration, Boolean(featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_bundler_pcre_regexp));
77
+ const pattern = getRegularExpression(declaration);
78
78
  // If there is no `pattern`, the declaration will never be triggered, so we
79
79
  // can discard it.
80
80
  if (!pattern) {
81
81
  return;
82
82
  }
83
83
  routedFunctions.add(declaration.function);
84
- const excludedPattern = getExcludedRegularExpressions(declaration, Boolean(featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_bundler_pcre_regexp));
84
+ const excludedPattern = getExcludedRegularExpressions(declaration);
85
85
  const route = {
86
86
  function: func.name,
87
87
  pattern: serializePattern(pattern),
@@ -135,10 +135,10 @@ const pathToRegularExpression = (path) => {
135
135
  throw wrapBundleError(error);
136
136
  }
137
137
  };
138
- const getRegularExpression = (declaration, pcreRegexpEngine) => {
138
+ const getRegularExpression = (declaration) => {
139
139
  if ('pattern' in declaration) {
140
140
  try {
141
- return parsePattern(declaration.pattern, pcreRegexpEngine);
141
+ return normalizePattern(declaration.pattern);
142
142
  }
143
143
  catch (error) {
144
144
  throw wrapBundleError(new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`));
@@ -146,14 +146,14 @@ const getRegularExpression = (declaration, pcreRegexpEngine) => {
146
146
  }
147
147
  return pathToRegularExpression(declaration.path);
148
148
  };
149
- const getExcludedRegularExpressions = (declaration, pcreRegexpEngine) => {
149
+ const getExcludedRegularExpressions = (declaration) => {
150
150
  if ('excludedPattern' in declaration && declaration.excludedPattern) {
151
151
  const excludedPatterns = Array.isArray(declaration.excludedPattern)
152
152
  ? declaration.excludedPattern
153
153
  : [declaration.excludedPattern];
154
154
  return excludedPatterns.map((excludedPattern) => {
155
155
  try {
156
- return parsePattern(excludedPattern, pcreRegexpEngine);
156
+ return normalizePattern(excludedPattern);
157
157
  }
158
158
  catch (error) {
159
159
  throw wrapBundleError(new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`));
@@ -386,22 +386,12 @@ test('Generates a manifest with layers', () => {
386
386
  expect(manifest2.routes).toEqual(expectedRoutes);
387
387
  expect(manifest2.layers).toEqual(layers);
388
388
  });
389
- test('Throws an error if the regular expression contains a negative lookahead and support for the PCRE engine is disabled', () => {
390
- const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
391
- const declarations = [{ function: 'func-1', pattern: '^\\/((?!api|_next\\/static|_next\\/image|favicon.ico).*)$' }];
392
- expect(() => generateManifest({
393
- bundles: [],
394
- declarations,
395
- functions,
396
- })).toThrowError(/^Could not parse path declaration of function 'func-1': Regular expressions with lookaheads are not supported$/);
397
- });
398
- test('Accepts regular expressions with lookaheads if support for the PCRE engine is enabled', () => {
389
+ test('Accepts regular expressions with lookaheads', () => {
399
390
  const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
400
391
  const declarations = [{ function: 'func-1', pattern: '^\\/((?!api|_next\\/static|_next\\/image|favicon.ico).*)$' }];
401
392
  const { manifest } = generateManifest({
402
393
  bundles: [],
403
394
  declarations,
404
- featureFlags: { edge_bundler_pcre_regexp: true },
405
395
  functions,
406
396
  });
407
397
  const [route] = manifest.routes;
@@ -409,11 +399,11 @@ test('Accepts regular expressions with lookaheads if support for the PCRE engine
409
399
  expect(regexp.test('/foo')).toBeTruthy();
410
400
  expect(regexp.test('/_next/static/foo')).toBeFalsy();
411
401
  });
412
- test('Converts named capture groups to unnamed capture groups in regular expressions', () => {
402
+ test('Accepts regular expressions with named capture groups', () => {
413
403
  const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
414
404
  const declarations = [{ function: 'func-1', pattern: '^/(?<name>\\w+)$' }];
415
405
  const { manifest } = generateManifest({ bundles: [], declarations, functions });
416
- expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(\\w+)$', excluded_patterns: [] }]);
406
+ expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(?<name>\\w+)$', excluded_patterns: [] }]);
417
407
  });
418
408
  test('Returns functions without a declaration and unrouted functions', () => {
419
409
  const bundle = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/edge-bundler",
3
- "version": "11.2.1",
3
+ "version": "11.3.0",
4
4
  "description": "Intelligently prepare Netlify Edge Functions for deployment",
5
5
  "type": "module",
6
6
  "main": "./dist/node/index.js",
@@ -81,7 +81,7 @@
81
81
  "better-ajv-errors": "^1.2.0",
82
82
  "common-path-prefix": "^3.0.0",
83
83
  "env-paths": "^3.0.0",
84
- "esbuild": "0.19.11",
84
+ "esbuild": "0.20.0",
85
85
  "execa": "^6.0.0",
86
86
  "find-up": "^6.3.0",
87
87
  "get-package-name": "^2.2.0",
@@ -93,7 +93,6 @@
93
93
  "p-retry": "^5.1.1",
94
94
  "p-wait-for": "^4.1.0",
95
95
  "path-key": "^4.0.0",
96
- "regexp-tree": "^0.1.24",
97
96
  "semver": "^7.3.8",
98
97
  "tmp-promise": "^3.0.3",
99
98
  "urlpattern-polyfill": "8.0.2",