@netlify/edge-bundler
Advanced tools
Comparing version 8.16.4 to 8.17.0
@@ -152,2 +152,3 @@ import { promises as fs } from 'fs'; | ||
configPath: join(internalDirectory, 'config.json'), | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
@@ -169,3 +170,3 @@ const generatedFiles = await fs.readdir(distPath); | ||
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$', excluded_patterns: [] }); | ||
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$', excluded_patterns: [] }); | ||
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5(?:/(.*))/?$', excluded_patterns: [] }); | ||
expect(postCacheRoutes.length).toBe(1); | ||
@@ -172,0 +173,0 @@ expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$', excluded_patterns: [] }); |
declare const defaultFlags: { | ||
edge_functions_fail_unsupported_regex: boolean; | ||
edge_functions_path_urlpattern: boolean; | ||
}; | ||
@@ -8,4 +9,5 @@ type FeatureFlag = keyof typeof defaultFlags; | ||
edge_functions_fail_unsupported_regex: boolean; | ||
edge_functions_path_urlpattern: boolean; | ||
}) => FeatureFlags; | ||
export { defaultFlags, getFlags }; | ||
export type { FeatureFlag, FeatureFlags }; |
const defaultFlags = { | ||
edge_functions_fail_unsupported_regex: false, | ||
edge_functions_path_urlpattern: false, | ||
}; | ||
@@ -4,0 +5,0 @@ const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({ |
@@ -7,2 +7,3 @@ import { promises as fs } from 'fs'; | ||
import { nonNullable } from './utils/non_nullable.js'; | ||
import { ExtendedURLPattern } from './utils/urlpattern.js'; | ||
const removeEmptyConfigValues = (functionConfig) => Object.entries(functionConfig).reduce((acc, [key, value]) => { | ||
@@ -29,6 +30,6 @@ if (value && !(Array.isArray(value) && value.length === 0)) { | ||
}; | ||
const addExcludedPatterns = (name, manifestFunctionConfig, excludedPath) => { | ||
const addExcludedPatterns = (name, manifestFunctionConfig, excludedPath, featureFlags) => { | ||
if (excludedPath) { | ||
const paths = Array.isArray(excludedPath) ? excludedPath : [excludedPath]; | ||
const excludedPatterns = paths.map(pathToRegularExpression).map(serializePattern); | ||
const excludedPatterns = paths.map((path) => pathToRegularExpression(path, featureFlags)).map(serializePattern); | ||
manifestFunctionConfig[name].excluded_patterns.push(...excludedPatterns); | ||
@@ -46,3 +47,3 @@ } | ||
} | ||
addExcludedPatterns(name, manifestFunctionConfig, excludedPath); | ||
addExcludedPatterns(name, manifestFunctionConfig, excludedPath, featureFlags); | ||
manifestFunctionConfig[name] = { ...manifestFunctionConfig[name], on_error: onError }; | ||
@@ -55,3 +56,3 @@ } | ||
} | ||
addExcludedPatterns(name, manifestFunctionConfig, excludedPath); | ||
addExcludedPatterns(name, manifestFunctionConfig, excludedPath, featureFlags); | ||
manifestFunctionConfig[name] = { ...manifestFunctionConfig[name], on_error: onError, ...rest }; | ||
@@ -64,4 +65,4 @@ } | ||
} | ||
const pattern = getRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex); | ||
const excludedPattern = getExcludedRegularExpressions(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex); | ||
const pattern = getRegularExpression(declaration, featureFlags); | ||
const excludedPattern = getExcludedRegularExpressions(declaration, featureFlags); | ||
const route = { | ||
@@ -94,3 +95,14 @@ function: func.name, | ||
}; | ||
const pathToRegularExpression = (path) => { | ||
const pathToRegularExpression = (path, featureFlags) => { | ||
if (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_path_urlpattern) { | ||
const pattern = new ExtendedURLPattern({ pathname: path }); | ||
// Removing the `^` and `$` delimiters because we'll need to modify what's | ||
// between them. | ||
const source = pattern.regexp.pathname.source.slice(1, -1); | ||
// Wrapping the expression source with `^` and `$`. Also, adding an optional | ||
// trailing slash, so that a declaration of `path: "/foo"` matches requests | ||
// for both `/foo` and `/foo/`. | ||
const normalizedSource = `^${source}\\/?$`; | ||
return normalizedSource; | ||
} | ||
// We use the global flag so that `globToRegExp` will not wrap the expression | ||
@@ -105,3 +117,3 @@ // with `^` and `$`. We'll do that ourselves. | ||
}; | ||
const getRegularExpression = (declaration, failUnsupportedRegex = false) => { | ||
const getRegularExpression = (declaration, featureFlags) => { | ||
if ('pattern' in declaration) { | ||
@@ -113,3 +125,3 @@ try { | ||
// eslint-disable-next-line max-depth | ||
if (failUnsupportedRegex) { | ||
if (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex) { | ||
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`); | ||
@@ -121,5 +133,5 @@ } | ||
} | ||
return pathToRegularExpression(declaration.path); | ||
return pathToRegularExpression(declaration.path, featureFlags); | ||
}; | ||
const getExcludedRegularExpressions = (declaration, failUnsupportedRegex = false) => { | ||
const getExcludedRegularExpressions = (declaration, featureFlags) => { | ||
if ('excludedPattern' in declaration && declaration.excludedPattern) { | ||
@@ -134,3 +146,3 @@ const excludedPatterns = Array.isArray(declaration.excludedPattern) | ||
catch (error) { | ||
if (failUnsupportedRegex) { | ||
if (featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex) { | ||
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`); | ||
@@ -145,3 +157,3 @@ } | ||
const paths = Array.isArray(declaration.excludedPath) ? declaration.excludedPath : [declaration.excludedPath]; | ||
return paths.map(pathToRegularExpression); | ||
return paths.map((path) => pathToRegularExpression(path, featureFlags)); | ||
} | ||
@@ -148,0 +160,0 @@ return []; |
@@ -37,4 +37,10 @@ import { env } from 'process'; | ||
}; | ||
const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig }); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }]; | ||
const manifest = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
internalFunctionConfig, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [] }]; | ||
expect(manifest.function_config).toEqual({ | ||
@@ -54,4 +60,10 @@ 'func-1': { name: 'Display Name' }, | ||
}; | ||
const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig }); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }]; | ||
const manifest = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
internalFunctionConfig, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [] }]; | ||
const expectedFunctionConfig = { 'func-1': { generator: '@netlify/fake-plugin@1.0.0' } }; | ||
@@ -70,10 +82,19 @@ expect(manifest.routes).toEqual(expectedRoutes); | ||
{ function: 'func-1', path: '/f1/*', excludedPath: '/f1/exclude' }, | ||
{ function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: ['^/f2/exclude$', '^/f2/exclude-as-well$'] }, | ||
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$', excludedPattern: ['^/f2/exclude$', '^/f2/exclude-as-well$'] }, | ||
{ function: 'func-3', path: '/*', excludedPath: '/**/*.html' }, | ||
]; | ||
const manifest = generateManifest({ bundles: [], declarations, functions }); | ||
const manifest = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
const expectedRoutes = [ | ||
{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: ['^/f1/exclude/?$'] }, | ||
{ function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: ['^/f2/exclude$', '^/f2/exclude-as-well$'] }, | ||
{ function: 'func-3', pattern: '^/.*/?$', excluded_patterns: ['^/.*/.*\\.html/?$'] }, | ||
{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: ['^/f1/exclude/?$'] }, | ||
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$', excluded_patterns: ['^/f2/exclude$', '^/f2/exclude-as-well$'] }, | ||
{ | ||
function: 'func-3', | ||
pattern: '^(?:/(.*))/?$', | ||
excluded_patterns: ['^(?:/((?:.*)(?:/(?:.*))*))?(?:/(.*))\\.html/?$'], | ||
}, | ||
]; | ||
@@ -93,4 +114,10 @@ expect(manifest.routes).toEqual(expectedRoutes); | ||
}; | ||
const manifest = generateManifest({ bundles: [], declarations, functions, userFunctionConfig }); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }]; | ||
const manifest = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
userFunctionConfig, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [] }]; | ||
expect(manifest.routes).toEqual(expectedRoutes); | ||
@@ -109,3 +136,3 @@ expect(manifest.function_config).toEqual({ | ||
{ function: 'func-1', path: '/f1/*' }, | ||
{ function: 'func-2', pattern: '^/f2/.*/?$' }, | ||
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$' }, | ||
]; | ||
@@ -171,2 +198,3 @@ const userFunctionConfig = { | ||
internalFunctionConfig, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
@@ -176,3 +204,3 @@ expect(manifest.routes).toEqual([ | ||
function: 'customisation', | ||
pattern: '^/showcases/.*/?$', | ||
pattern: '^/showcases(?:/(.*))/?$', | ||
excluded_patterns: [], | ||
@@ -182,4 +210,4 @@ }, | ||
function: 'customisation', | ||
pattern: '^/checkout/.*/?$', | ||
excluded_patterns: ['^/.*/terms-and-conditions/?$'], | ||
pattern: '^/checkout(?:/(.*))/?$', | ||
excluded_patterns: ['^(?:/(.*))/terms-and-conditions/?$'], | ||
}, | ||
@@ -189,3 +217,3 @@ ]); | ||
customisation: { | ||
excluded_patterns: ['^/.*\\.css/?$', '^/.*\\.jpg/?$'], | ||
excluded_patterns: ['^(?:/(.*))\\.css/?$', '^(?:/(.*))\\.jpg/?$'], | ||
}, | ||
@@ -207,3 +235,3 @@ }); | ||
{ function: 'func-1', path: '/f1/*' }, | ||
{ function: 'func-2', pattern: '^/f2/.*/?$' }, | ||
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$' }, | ||
]; | ||
@@ -305,4 +333,4 @@ const userFunctionConfig = { | ||
const expectedRoutes = [ | ||
{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }, | ||
{ function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: [] }, | ||
{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [] }, | ||
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$', excluded_patterns: [] }, | ||
]; | ||
@@ -315,4 +343,15 @@ const layers = [ | ||
]; | ||
const manifest1 = generateManifest({ bundles: [], declarations, functions }); | ||
const manifest2 = generateManifest({ bundles: [], declarations, functions, layers }); | ||
const manifest1 = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
const manifest2 = generateManifest({ | ||
bundles: [], | ||
declarations, | ||
functions, | ||
layers, | ||
featureFlags: { edge_functions_path_urlpattern: true }, | ||
}); | ||
expect(manifest1.routes).toEqual(expectedRoutes); | ||
@@ -319,0 +358,0 @@ expect(manifest1.layers).toEqual([]); |
{ | ||
"name": "@netlify/edge-bundler", | ||
"version": "8.16.4", | ||
"version": "8.17.0", | ||
"description": "Intelligently prepare Netlify Edge Functions for deployment", | ||
@@ -96,4 +96,5 @@ "type": "module", | ||
"tmp-promise": "^3.0.3", | ||
"urlpattern-polyfill": "8.0.2", | ||
"uuid": "^9.0.0" | ||
} | ||
} |
3103829
153
7924
22
+ Addedurlpattern-polyfill@8.0.2
+ Addedurlpattern-polyfill@8.0.2(transitive)