@netlify/edge-bundler 8.12.0 → 8.12.2
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.d.ts +2 -2
- package/dist/node/config.d.ts +3 -2
- package/dist/node/declaration.d.ts +3 -3
- package/dist/node/feature_flags.d.ts +2 -0
- package/dist/node/feature_flags.js +1 -0
- package/dist/node/formats/javascript.js +2 -2
- package/dist/node/manifest.js +4 -0
- package/dist/node/validation/manifest/index.d.ts +2 -1
- package/dist/node/validation/manifest/index.js +4 -4
- package/dist/node/validation/manifest/index.test.js +22 -5
- package/dist/node/validation/manifest/schema.js +2 -2
- package/package.json +3 -5
package/dist/node/bundler.d.ts
CHANGED
|
@@ -25,8 +25,8 @@ export declare const addGeneratorFieldIfMissing: (declaration: Declaration, func
|
|
|
25
25
|
cache?: string | undefined;
|
|
26
26
|
function: string;
|
|
27
27
|
name?: string | undefined;
|
|
28
|
-
path: string
|
|
29
|
-
excludedPath?: string | undefined;
|
|
28
|
+
path: `/${string}`;
|
|
29
|
+
excludedPath?: `/${string}` | undefined;
|
|
30
30
|
} | {
|
|
31
31
|
generator: string | undefined;
|
|
32
32
|
cache?: string | undefined;
|
package/dist/node/config.d.ts
CHANGED
|
@@ -7,12 +7,13 @@ export declare const enum Cache {
|
|
|
7
7
|
Off = "off",
|
|
8
8
|
Manual = "manual"
|
|
9
9
|
}
|
|
10
|
+
export type Path = `/${string}`;
|
|
10
11
|
export type OnError = 'fail' | 'bypass' | `/${string}`;
|
|
11
12
|
export declare const isValidOnError: (value: unknown) => value is OnError;
|
|
12
13
|
export interface FunctionConfig {
|
|
13
14
|
cache?: Cache;
|
|
14
|
-
path?:
|
|
15
|
-
excludedPath?:
|
|
15
|
+
path?: Path | Path[];
|
|
16
|
+
excludedPath?: Path | Path[];
|
|
16
17
|
onError?: OnError;
|
|
17
18
|
}
|
|
18
19
|
export declare const getFunctionConfig: (func: EdgeFunction, importMap: ImportMap, deno: DenoBridge, log: Logger, featureFlags: FeatureFlags) => Promise<FunctionConfig>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FunctionConfig } from './config.js';
|
|
1
|
+
import { FunctionConfig, Path } from './config.js';
|
|
2
2
|
interface BaseDeclaration {
|
|
3
3
|
cache?: string;
|
|
4
4
|
function: string;
|
|
@@ -6,8 +6,8 @@ interface BaseDeclaration {
|
|
|
6
6
|
generator?: string;
|
|
7
7
|
}
|
|
8
8
|
type DeclarationWithPath = BaseDeclaration & {
|
|
9
|
-
path:
|
|
10
|
-
excludedPath?:
|
|
9
|
+
path: Path;
|
|
10
|
+
excludedPath?: Path;
|
|
11
11
|
};
|
|
12
12
|
type DeclarationWithPattern = BaseDeclaration & {
|
|
13
13
|
pattern: string;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
declare const defaultFlags: {
|
|
2
2
|
edge_functions_fail_unsupported_regex: boolean;
|
|
3
3
|
edge_functions_invalid_config_throw: boolean;
|
|
4
|
+
edge_functions_manifest_validate_slash: boolean;
|
|
4
5
|
};
|
|
5
6
|
type FeatureFlag = keyof typeof defaultFlags;
|
|
6
7
|
type FeatureFlags = Partial<Record<FeatureFlag, boolean>>;
|
|
7
8
|
declare const getFlags: (input?: Record<string, boolean>, flags?: {
|
|
8
9
|
edge_functions_fail_unsupported_regex: boolean;
|
|
9
10
|
edge_functions_invalid_config_throw: boolean;
|
|
11
|
+
edge_functions_manifest_validate_slash: boolean;
|
|
10
12
|
}) => FeatureFlags;
|
|
11
13
|
export { defaultFlags, getFlags };
|
|
12
14
|
export type { FeatureFlag, FeatureFlags };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const defaultFlags = {
|
|
2
2
|
edge_functions_fail_unsupported_regex: false,
|
|
3
3
|
edge_functions_invalid_config_throw: false,
|
|
4
|
+
edge_functions_manifest_validate_slash: false,
|
|
4
5
|
};
|
|
5
6
|
const getFlags = (input = {}, flags = defaultFlags) => Object.entries(flags).reduce((result, [key, defaultValue]) => ({
|
|
6
7
|
...result,
|
|
@@ -3,7 +3,7 @@ import { join } from 'path';
|
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
4
|
import { deleteAsync } from 'del';
|
|
5
5
|
const defaultFormatExportTypeError = (name) => `The Edge Function "${name}" has failed to load. Does it have a function as the default export?`;
|
|
6
|
-
const
|
|
6
|
+
const defaultFormatImportError = (name) => `There was an error with Edge Function "${name}".`;
|
|
7
7
|
const generateStage2 = async ({ bootstrapURL, distDirectory, fileName, formatExportTypeError, formatImportError, functions, }) => {
|
|
8
8
|
await deleteAsync(distDirectory, { force: true });
|
|
9
9
|
await fs.mkdir(distDirectory, { recursive: true });
|
|
@@ -15,7 +15,7 @@ const generateStage2 = async ({ bootstrapURL, distDirectory, fileName, formatExp
|
|
|
15
15
|
// For the local development environment, we import the user functions with
|
|
16
16
|
// dynamic imports to gracefully handle the case where the file doesn't have
|
|
17
17
|
// a valid default export.
|
|
18
|
-
const getLocalEntryPoint = (functions, { bootstrapURL, formatExportTypeError = defaultFormatExportTypeError, formatImportError =
|
|
18
|
+
const getLocalEntryPoint = (functions, { bootstrapURL, formatExportTypeError = defaultFormatExportTypeError, formatImportError = defaultFormatImportError, }) => {
|
|
19
19
|
const bootImport = `import { boot } from "${bootstrapURL}";`;
|
|
20
20
|
const declaration = `const functions = {}; const metadata = { functions: {} };`;
|
|
21
21
|
const imports = functions.map((func) => {
|
package/dist/node/manifest.js
CHANGED
|
@@ -23,6 +23,10 @@ const generateManifest = ({ bundles = [], declarations = [], featureFlags, funct
|
|
|
23
23
|
const postCacheRoutes = [];
|
|
24
24
|
const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
|
|
25
25
|
for (const [name, { excludedPath, onError }] of Object.entries(functionConfig)) {
|
|
26
|
+
// If the config block is for a function that is not defined, discard it.
|
|
27
|
+
if (manifestFunctionConfig[name] === undefined) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
26
30
|
if (excludedPath) {
|
|
27
31
|
const paths = Array.isArray(excludedPath) ? excludedPath : [excludedPath];
|
|
28
32
|
const excludedPatterns = paths.map(pathToRegularExpression).map(serializePattern);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FeatureFlags } from '../../feature_flags.js';
|
|
1
2
|
import ManifestValidationError from './error.js';
|
|
2
|
-
export declare const validateManifest: (manifestData: unknown) => void;
|
|
3
|
+
export declare const validateManifest: (manifestData: unknown, featureFlags?: FeatureFlags) => void;
|
|
3
4
|
export { ManifestValidationError };
|
|
@@ -4,13 +4,13 @@ import betterAjvErrors from 'better-ajv-errors';
|
|
|
4
4
|
import ManifestValidationError from './error.js';
|
|
5
5
|
import edgeManifestSchema from './schema.js';
|
|
6
6
|
let manifestValidator;
|
|
7
|
-
const initializeValidator = () => {
|
|
7
|
+
const initializeValidator = (featureFlags) => {
|
|
8
8
|
if (manifestValidator === undefined) {
|
|
9
9
|
const ajv = new Ajv({ allErrors: true });
|
|
10
10
|
ajvErrors(ajv);
|
|
11
11
|
// regex pattern for manifest route pattern
|
|
12
12
|
// checks if the pattern string starts with ^ and ends with $
|
|
13
|
-
const normalizedPatternRegex = /^\^.*\$$/;
|
|
13
|
+
const normalizedPatternRegex = featureFlags.edge_functions_manifest_validate_slash ? /^\^\/.*\$$/ : /^\^.*\$$/;
|
|
14
14
|
ajv.addFormat('regexPattern', {
|
|
15
15
|
validate: (data) => normalizedPatternRegex.test(data),
|
|
16
16
|
});
|
|
@@ -19,8 +19,8 @@ const initializeValidator = () => {
|
|
|
19
19
|
return manifestValidator;
|
|
20
20
|
};
|
|
21
21
|
// throws on validation error
|
|
22
|
-
export const validateManifest = (manifestData) => {
|
|
23
|
-
const validate = initializeValidator();
|
|
22
|
+
export const validateManifest = (manifestData, featureFlags = {}) => {
|
|
23
|
+
const validate = initializeValidator(featureFlags);
|
|
24
24
|
const valid = validate(manifestData);
|
|
25
25
|
if (!valid) {
|
|
26
26
|
let errorOutput;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import { test, expect, describe } from 'vitest';
|
|
2
|
+
import { test, expect, describe, beforeEach, vi } from 'vitest';
|
|
3
3
|
import { validateManifest, ManifestValidationError } from './index.js';
|
|
4
4
|
// We need to disable all color outputs for the tests as they are different on different platforms, CI, etc.
|
|
5
5
|
// This only works if this is the same instance of chalk that better-ajv-errors uses
|
|
@@ -79,25 +79,42 @@ describe('bundle', () => {
|
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
81
|
describe('route', () => {
|
|
82
|
+
let freshValidateManifest;
|
|
83
|
+
beforeEach(async () => {
|
|
84
|
+
// reset all modules, to get a fresh AJV validator for FF changes
|
|
85
|
+
vi.resetModules();
|
|
86
|
+
const indexImport = await import('./index.js');
|
|
87
|
+
freshValidateManifest = indexImport.validateManifest;
|
|
88
|
+
});
|
|
82
89
|
test('should throw on additional property', () => {
|
|
83
90
|
const manifest = getBaseManifest();
|
|
84
91
|
manifest.routes[0].foo = 'bar';
|
|
85
|
-
expect(() =>
|
|
92
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
86
93
|
});
|
|
87
94
|
test('should throw on invalid pattern', () => {
|
|
88
95
|
const manifest = getBaseManifest();
|
|
89
96
|
manifest.routes[0].pattern = '/^/hello/?$/';
|
|
90
|
-
expect(() =>
|
|
97
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
98
|
+
});
|
|
99
|
+
test('should not throw on missing beginning slash without FF', () => {
|
|
100
|
+
const manifest = getBaseManifest();
|
|
101
|
+
manifest.routes[0].pattern = '^hello/?$';
|
|
102
|
+
expect(() => freshValidateManifest(manifest, { edge_functions_manifest_validate_slash: false })).not.toThrowError();
|
|
103
|
+
});
|
|
104
|
+
test('should throw on missing beginning slash with FF', () => {
|
|
105
|
+
const manifest = getBaseManifest();
|
|
106
|
+
manifest.routes[0].pattern = '^hello/?$';
|
|
107
|
+
expect(() => freshValidateManifest(manifest, { edge_functions_manifest_validate_slash: true })).toThrowErrorMatchingSnapshot();
|
|
91
108
|
});
|
|
92
109
|
test('should throw on missing function', () => {
|
|
93
110
|
const manifest = getBaseManifest();
|
|
94
111
|
delete manifest.routes[0].function;
|
|
95
|
-
expect(() =>
|
|
112
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
96
113
|
});
|
|
97
114
|
test('should throw on missing pattern', () => {
|
|
98
115
|
const manifest = getBaseManifest();
|
|
99
116
|
delete manifest.routes[0].pattern;
|
|
100
|
-
expect(() =>
|
|
117
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
101
118
|
});
|
|
102
119
|
});
|
|
103
120
|
// No tests for post_cache_routes as schema shared with routes
|
|
@@ -16,7 +16,7 @@ const routesSchema = {
|
|
|
16
16
|
pattern: {
|
|
17
17
|
type: 'string',
|
|
18
18
|
format: 'regexPattern',
|
|
19
|
-
errorMessage: 'pattern needs to be a regex that starts with ^ and ends with $ without any additional slashes before and afterwards',
|
|
19
|
+
errorMessage: 'pattern needs to be a regex that starts with ^ followed by / and ends with $ without any additional slashes before and afterwards',
|
|
20
20
|
},
|
|
21
21
|
generator: { type: 'string' },
|
|
22
22
|
},
|
|
@@ -31,7 +31,7 @@ const functionConfigSchema = {
|
|
|
31
31
|
items: {
|
|
32
32
|
type: 'string',
|
|
33
33
|
format: 'regexPattern',
|
|
34
|
-
errorMessage: 'excluded_patterns needs to be an array of regex that starts with ^ and ends with $ without any additional slashes before and afterwards',
|
|
34
|
+
errorMessage: 'excluded_patterns needs to be an array of regex that starts with ^ followed by / and ends with $ without any additional slashes before and afterwards',
|
|
35
35
|
},
|
|
36
36
|
},
|
|
37
37
|
on_error: { type: 'string' },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "8.12.
|
|
3
|
+
"version": "8.12.2",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -57,9 +57,8 @@
|
|
|
57
57
|
"@types/glob-to-regexp": "^0.4.1",
|
|
58
58
|
"@types/node": "^14.18.32",
|
|
59
59
|
"@types/semver": "^7.3.9",
|
|
60
|
-
"@types/sinon": "^10.0.8",
|
|
61
60
|
"@types/uuid": "^9.0.0",
|
|
62
|
-
"@vitest/coverage-c8": "^0.
|
|
61
|
+
"@vitest/coverage-c8": "^0.29.2",
|
|
63
62
|
"archiver": "^5.3.1",
|
|
64
63
|
"chalk": "^4.1.2",
|
|
65
64
|
"cpy": "^9.0.1",
|
|
@@ -68,8 +67,7 @@
|
|
|
68
67
|
"nock": "^13.2.4",
|
|
69
68
|
"tar": "^6.1.11",
|
|
70
69
|
"typescript": "^4.5.4",
|
|
71
|
-
"
|
|
72
|
-
"vitest": "^0.25.0"
|
|
70
|
+
"vitest": "^0.29.2"
|
|
73
71
|
},
|
|
74
72
|
"engines": {
|
|
75
73
|
"node": "^14.16.0 || >=16.0.0"
|