@netlify/edge-bundler 8.12.1 → 8.12.3
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/validation/manifest/error.d.ts +3 -0
- package/dist/node/validation/manifest/error.js +3 -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 +35 -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,
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export default class ManifestValidationError extends Error {
|
|
2
2
|
constructor(message) {
|
|
3
3
|
super(`Validation of Edge Functions manifest failed\n${message}`);
|
|
4
|
+
this.customErrorInfo = {
|
|
5
|
+
type: 'functionsBundling',
|
|
6
|
+
};
|
|
4
7
|
this.name = 'ManifestValidationError';
|
|
5
8
|
// https://github.com/microsoft/TypeScript-wiki/blob/0fecbda7263f130c57394d779b8ca13f0a2e9123/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
6
9
|
Object.setPrototypeOf(this, ManifestValidationError.prototype);
|
|
@@ -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
|
|
@@ -45,6 +45,19 @@ test('should throw ManifestValidationError with correct message', () => {
|
|
|
45
45
|
expect(() => validateManifest('manifest')).toThrowError(ManifestValidationError);
|
|
46
46
|
expect(() => validateManifest('manifest')).toThrowError(/^Validation of Edge Functions manifest failed/);
|
|
47
47
|
});
|
|
48
|
+
test('should throw ManifestValidationError with customErrorInfo', () => {
|
|
49
|
+
try {
|
|
50
|
+
validateManifest('manifest');
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
expect(error).toBeInstanceOf(ManifestValidationError);
|
|
54
|
+
const { customErrorInfo } = error;
|
|
55
|
+
expect(customErrorInfo).toBeDefined();
|
|
56
|
+
expect(customErrorInfo.type).toBe('functionsBundling');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
expect.fail('should have thrown');
|
|
60
|
+
});
|
|
48
61
|
test('should throw on additional property on root level', () => {
|
|
49
62
|
const manifest = getBaseManifest();
|
|
50
63
|
manifest.foo = 'bar';
|
|
@@ -79,25 +92,42 @@ describe('bundle', () => {
|
|
|
79
92
|
});
|
|
80
93
|
});
|
|
81
94
|
describe('route', () => {
|
|
95
|
+
let freshValidateManifest;
|
|
96
|
+
beforeEach(async () => {
|
|
97
|
+
// reset all modules, to get a fresh AJV validator for FF changes
|
|
98
|
+
vi.resetModules();
|
|
99
|
+
const indexImport = await import('./index.js');
|
|
100
|
+
freshValidateManifest = indexImport.validateManifest;
|
|
101
|
+
});
|
|
82
102
|
test('should throw on additional property', () => {
|
|
83
103
|
const manifest = getBaseManifest();
|
|
84
104
|
manifest.routes[0].foo = 'bar';
|
|
85
|
-
expect(() =>
|
|
105
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
86
106
|
});
|
|
87
107
|
test('should throw on invalid pattern', () => {
|
|
88
108
|
const manifest = getBaseManifest();
|
|
89
109
|
manifest.routes[0].pattern = '/^/hello/?$/';
|
|
90
|
-
expect(() =>
|
|
110
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
111
|
+
});
|
|
112
|
+
test('should not throw on missing beginning slash without FF', () => {
|
|
113
|
+
const manifest = getBaseManifest();
|
|
114
|
+
manifest.routes[0].pattern = '^hello/?$';
|
|
115
|
+
expect(() => freshValidateManifest(manifest, { edge_functions_manifest_validate_slash: false })).not.toThrowError();
|
|
116
|
+
});
|
|
117
|
+
test('should throw on missing beginning slash with FF', () => {
|
|
118
|
+
const manifest = getBaseManifest();
|
|
119
|
+
manifest.routes[0].pattern = '^hello/?$';
|
|
120
|
+
expect(() => freshValidateManifest(manifest, { edge_functions_manifest_validate_slash: true })).toThrowErrorMatchingSnapshot();
|
|
91
121
|
});
|
|
92
122
|
test('should throw on missing function', () => {
|
|
93
123
|
const manifest = getBaseManifest();
|
|
94
124
|
delete manifest.routes[0].function;
|
|
95
|
-
expect(() =>
|
|
125
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
96
126
|
});
|
|
97
127
|
test('should throw on missing pattern', () => {
|
|
98
128
|
const manifest = getBaseManifest();
|
|
99
129
|
delete manifest.routes[0].pattern;
|
|
100
|
-
expect(() =>
|
|
130
|
+
expect(() => freshValidateManifest(manifest)).toThrowErrorMatchingSnapshot();
|
|
101
131
|
});
|
|
102
132
|
});
|
|
103
133
|
// 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.3",
|
|
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"
|