@netlify/edge-bundler 8.0.0 → 8.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.
- package/dist/node/bundler.js +1 -0
- package/dist/node/bundler.test.js +2 -2
- package/dist/node/config.d.ts +1 -0
- package/dist/node/config.test.js +9 -4
- package/dist/node/declaration.js +4 -5
- package/dist/node/manifest.d.ts +16 -16
- package/dist/node/manifest.js +22 -4
- package/dist/node/manifest.test.js +6 -2
- package/dist/node/validation/manifest/schema.d.ts +17 -0
- package/dist/node/validation/manifest/schema.js +15 -0
- package/package.json +1 -1
package/dist/node/bundler.js
CHANGED
|
@@ -299,12 +299,12 @@ test('Loads declarations and import maps from the deploy configuration', async (
|
|
|
299
299
|
expect(generatedFiles.length).toBe(2);
|
|
300
300
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
301
301
|
const manifest = JSON.parse(manifestFile);
|
|
302
|
-
const { bundles,
|
|
302
|
+
const { bundles, function_config: functionConfig } = manifest;
|
|
303
303
|
expect(bundles.length).toBe(1);
|
|
304
304
|
expect(bundles[0].format).toBe('eszip2');
|
|
305
305
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
306
306
|
// respects excludedPath from deploy config
|
|
307
|
-
expect(
|
|
307
|
+
expect(functionConfig.func2).toEqual({ excluded_patterns: ['^/func2/skip/?$'] });
|
|
308
308
|
await cleanup();
|
|
309
309
|
});
|
|
310
310
|
test("Ignores entries in `importMapPaths` that don't point to an existing import map file", async () => {
|
package/dist/node/config.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export declare const enum Cache {
|
|
|
9
9
|
export interface FunctionConfig {
|
|
10
10
|
cache?: Cache;
|
|
11
11
|
path?: string | string[];
|
|
12
|
+
excludedPath?: string | string[];
|
|
12
13
|
}
|
|
13
14
|
export declare const getFunctionConfig: (func: EdgeFunction, importMap: ImportMap, deno: DenoBridge, log: Logger) => Promise<FunctionConfig>;
|
package/dist/node/config.test.js
CHANGED
|
@@ -102,7 +102,7 @@ test('Ignores function paths from the in-source `config` function if the feature
|
|
|
102
102
|
configPath: join(internalDirectory, 'config.json'),
|
|
103
103
|
});
|
|
104
104
|
const generatedFiles = await fs.readdir(distPath);
|
|
105
|
-
expect(result.functions.length).toBe(
|
|
105
|
+
expect(result.functions.length).toBe(7);
|
|
106
106
|
expect(generatedFiles.length).toBe(2);
|
|
107
107
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
108
108
|
const manifest = JSON.parse(manifestFile);
|
|
@@ -135,22 +135,27 @@ test('Loads function paths from the in-source `config` function', async () => {
|
|
|
135
135
|
},
|
|
136
136
|
});
|
|
137
137
|
const generatedFiles = await fs.readdir(distPath);
|
|
138
|
-
expect(result.functions.length).toBe(
|
|
138
|
+
expect(result.functions.length).toBe(7);
|
|
139
139
|
expect(generatedFiles.length).toBe(2);
|
|
140
140
|
const manifestFile = await fs.readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
141
141
|
const manifest = JSON.parse(manifestFile);
|
|
142
|
-
const { bundles, routes, post_cache_routes: postCacheRoutes } = manifest;
|
|
142
|
+
const { bundles, routes, post_cache_routes: postCacheRoutes, function_config: functionConfig } = manifest;
|
|
143
143
|
expect(bundles.length).toBe(1);
|
|
144
144
|
expect(bundles[0].format).toBe('eszip2');
|
|
145
145
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
146
|
-
expect(routes.length).toBe(
|
|
146
|
+
expect(routes.length).toBe(6);
|
|
147
147
|
expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$' });
|
|
148
148
|
expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$' });
|
|
149
149
|
expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$' });
|
|
150
150
|
expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$' });
|
|
151
151
|
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$' });
|
|
152
|
+
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$' });
|
|
152
153
|
expect(postCacheRoutes.length).toBe(1);
|
|
153
154
|
expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$' });
|
|
155
|
+
expect(Object.keys(functionConfig)).toHaveLength(1);
|
|
156
|
+
expect(functionConfig['user-func5']).toEqual({
|
|
157
|
+
excluded_patterns: ['^/user-func5/excluded/?$'],
|
|
158
|
+
});
|
|
154
159
|
await cleanup();
|
|
155
160
|
});
|
|
156
161
|
test('Passes validation if default export exists and is a function', async () => {
|
package/dist/node/declaration.js
CHANGED
|
@@ -17,13 +17,13 @@ export const getDeclarationsFromConfig = (tomlDeclarations, functionsConfig, dep
|
|
|
17
17
|
else if ((_a = config.path) === null || _a === void 0 ? void 0 : _a.length) {
|
|
18
18
|
const paths = Array.isArray(config.path) ? config.path : [config.path];
|
|
19
19
|
paths.forEach((path) => {
|
|
20
|
-
declarations.push({ ...declaration,
|
|
20
|
+
declarations.push({ ...declaration, cache: config.cache, path });
|
|
21
21
|
});
|
|
22
22
|
// With an in-source config without a path, add the config to the declaration
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
25
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
26
|
-
const { path, ...rest } = config;
|
|
26
|
+
const { path, excludedPath, ...rest } = config;
|
|
27
27
|
declarations.push({ ...declaration, ...rest });
|
|
28
28
|
}
|
|
29
29
|
functionsVisited.add(declaration.function);
|
|
@@ -31,13 +31,12 @@ export const getDeclarationsFromConfig = (tomlDeclarations, functionsConfig, dep
|
|
|
31
31
|
// Finally, we must create declarations for functions that are not declared
|
|
32
32
|
// in the TOML at all.
|
|
33
33
|
for (const name in functionsConfig) {
|
|
34
|
-
const {
|
|
35
|
-
const { path } = functionsConfig[name];
|
|
34
|
+
const { cache, path } = functionsConfig[name];
|
|
36
35
|
// If we have path specified create a declaration for each path
|
|
37
36
|
if (!functionsVisited.has(name) && path) {
|
|
38
37
|
const paths = Array.isArray(path) ? path : [path];
|
|
39
38
|
paths.forEach((singlePath) => {
|
|
40
|
-
declarations.push({
|
|
39
|
+
declarations.push({ cache, function: name, path: singlePath });
|
|
41
40
|
});
|
|
42
41
|
}
|
|
43
42
|
}
|
package/dist/node/manifest.d.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import type { Bundle } from './bundle.js';
|
|
2
|
+
import { FunctionConfig } from './config.js';
|
|
2
3
|
import type { Declaration } from './declaration.js';
|
|
3
4
|
import { EdgeFunction } from './edge_function.js';
|
|
4
5
|
import { Layer } from './layer.js';
|
|
5
|
-
interface GenerateManifestOptions {
|
|
6
|
-
bundles?: Bundle[];
|
|
7
|
-
declarations?: Declaration[];
|
|
8
|
-
functions: EdgeFunction[];
|
|
9
|
-
importMap?: string;
|
|
10
|
-
layers?: Layer[];
|
|
11
|
-
}
|
|
12
6
|
interface Route {
|
|
13
7
|
function: string;
|
|
14
8
|
name?: string;
|
|
15
9
|
pattern: string;
|
|
16
|
-
|
|
10
|
+
}
|
|
11
|
+
interface EdgeFunctionConfig {
|
|
12
|
+
excluded_patterns: string[];
|
|
17
13
|
}
|
|
18
14
|
interface Manifest {
|
|
19
15
|
bundler_version: string;
|
|
@@ -28,20 +24,24 @@ interface Manifest {
|
|
|
28
24
|
}[];
|
|
29
25
|
routes: Route[];
|
|
30
26
|
post_cache_routes: Route[];
|
|
27
|
+
function_config: Record<string, EdgeFunctionConfig>;
|
|
28
|
+
}
|
|
29
|
+
interface GenerateManifestOptions {
|
|
30
|
+
bundles?: Bundle[];
|
|
31
|
+
declarations?: Declaration[];
|
|
32
|
+
functions: EdgeFunction[];
|
|
33
|
+
functionConfig?: Record<string, FunctionConfig>;
|
|
34
|
+
importMap?: string;
|
|
35
|
+
layers?: Layer[];
|
|
31
36
|
}
|
|
32
37
|
interface Route {
|
|
33
38
|
function: string;
|
|
34
39
|
name?: string;
|
|
35
40
|
pattern: string;
|
|
36
41
|
}
|
|
37
|
-
declare const generateManifest: ({ bundles, declarations, functions, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
38
|
-
interface WriteManifestOptions {
|
|
39
|
-
bundles: Bundle[];
|
|
40
|
-
declarations: Declaration[];
|
|
42
|
+
declare const generateManifest: ({ bundles, declarations, functions, functionConfig, importMap, layers, }: GenerateManifestOptions) => Manifest;
|
|
43
|
+
interface WriteManifestOptions extends GenerateManifestOptions {
|
|
41
44
|
distDirectory: string;
|
|
42
|
-
functions: EdgeFunction[];
|
|
43
|
-
importMap?: string;
|
|
44
|
-
layers?: Layer[];
|
|
45
45
|
}
|
|
46
|
-
declare const writeManifest: ({
|
|
46
|
+
declare const writeManifest: ({ distDirectory, ...rest }: WriteManifestOptions) => Promise<Manifest>;
|
|
47
47
|
export { generateManifest, Manifest, writeManifest };
|
package/dist/node/manifest.js
CHANGED
|
@@ -4,9 +4,26 @@ import globToRegExp from 'glob-to-regexp';
|
|
|
4
4
|
import { getPackageVersion } from './package_json.js';
|
|
5
5
|
import { nonNullable } from './utils/non_nullable.js';
|
|
6
6
|
const serializePattern = (regex) => regex.source.replace(/\\\//g, '/');
|
|
7
|
-
const
|
|
7
|
+
const sanitizeEdgeFunctionConfig = (config) => {
|
|
8
|
+
const newConfig = {};
|
|
9
|
+
for (const [name, functionConfig] of Object.entries(config)) {
|
|
10
|
+
if (functionConfig.excluded_patterns.length !== 0) {
|
|
11
|
+
newConfig[name] = functionConfig;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return newConfig;
|
|
15
|
+
};
|
|
16
|
+
const generateManifest = ({ bundles = [], declarations = [], functions, functionConfig = {}, importMap, layers = [], }) => {
|
|
8
17
|
const preCacheRoutes = [];
|
|
9
18
|
const postCacheRoutes = [];
|
|
19
|
+
const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
|
|
20
|
+
for (const [name, { excludedPath }] of Object.entries(functionConfig)) {
|
|
21
|
+
if (excludedPath) {
|
|
22
|
+
const paths = Array.isArray(excludedPath) ? excludedPath : [excludedPath];
|
|
23
|
+
const excludedPatterns = paths.map(pathToRegularExpression).map(serializePattern);
|
|
24
|
+
manifestFunctionConfig[name].excluded_patterns.push(...excludedPatterns);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
10
27
|
declarations.forEach((declaration) => {
|
|
11
28
|
const func = functions.find(({ name }) => declaration.function === name);
|
|
12
29
|
if (func === undefined) {
|
|
@@ -20,7 +37,7 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
|
|
|
20
37
|
};
|
|
21
38
|
const excludedPattern = getExcludedRegularExpression(declaration);
|
|
22
39
|
if (excludedPattern) {
|
|
23
|
-
|
|
40
|
+
manifestFunctionConfig[func.name].excluded_patterns.push(serializePattern(excludedPattern));
|
|
24
41
|
}
|
|
25
42
|
if (declaration.cache === "manual" /* Cache.Manual */) {
|
|
26
43
|
postCacheRoutes.push(route);
|
|
@@ -40,6 +57,7 @@ const generateManifest = ({ bundles = [], declarations = [], functions, importMa
|
|
|
40
57
|
bundler_version: getPackageVersion(),
|
|
41
58
|
layers,
|
|
42
59
|
import_map: importMap,
|
|
60
|
+
function_config: sanitizeEdgeFunctionConfig(manifestFunctionConfig),
|
|
43
61
|
};
|
|
44
62
|
return manifest;
|
|
45
63
|
};
|
|
@@ -67,8 +85,8 @@ const getExcludedRegularExpression = (declaration) => {
|
|
|
67
85
|
return pathToRegularExpression(declaration.excludedPath);
|
|
68
86
|
}
|
|
69
87
|
};
|
|
70
|
-
const writeManifest = async ({
|
|
71
|
-
const manifest = generateManifest(
|
|
88
|
+
const writeManifest = async ({ distDirectory, ...rest }) => {
|
|
89
|
+
const manifest = generateManifest(rest);
|
|
72
90
|
const manifestPath = join(distDirectory, 'manifest.json');
|
|
73
91
|
await fs.writeFile(manifestPath, JSON.stringify(manifest));
|
|
74
92
|
return manifest;
|
|
@@ -53,10 +53,14 @@ test('Generates a manifest with excluded paths and patterns', () => {
|
|
|
53
53
|
];
|
|
54
54
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
55
55
|
const expectedRoutes = [
|
|
56
|
-
{ function: 'func-1', name: 'Display Name', pattern: '^/f1/.*/?$'
|
|
57
|
-
{ function: 'func-2', pattern: '^/f2/.*/?$'
|
|
56
|
+
{ function: 'func-1', name: 'Display Name', pattern: '^/f1/.*/?$' },
|
|
57
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
58
58
|
];
|
|
59
59
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
60
|
+
expect(manifest.function_config).toEqual({
|
|
61
|
+
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
62
|
+
'func-2': { excluded_patterns: ['^/f2/exclude$'] },
|
|
63
|
+
});
|
|
60
64
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
61
65
|
});
|
|
62
66
|
test('Excludes functions for which there are function files but no matching config declarations', () => {
|
|
@@ -86,6 +86,23 @@ declare const edgeManifestSchema: {
|
|
|
86
86
|
bundler_version: {
|
|
87
87
|
type: string;
|
|
88
88
|
};
|
|
89
|
+
function_config: {
|
|
90
|
+
type: string;
|
|
91
|
+
items: {
|
|
92
|
+
type: string;
|
|
93
|
+
required: never[];
|
|
94
|
+
properties: {
|
|
95
|
+
excluded_patterns: {
|
|
96
|
+
type: string;
|
|
97
|
+
items: {
|
|
98
|
+
type: string;
|
|
99
|
+
format: string;
|
|
100
|
+
errorMessage: string;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
};
|
|
89
106
|
};
|
|
90
107
|
additionalProperties: boolean;
|
|
91
108
|
};
|
|
@@ -21,6 +21,20 @@ const routesSchema = {
|
|
|
21
21
|
},
|
|
22
22
|
additionalProperties: false,
|
|
23
23
|
};
|
|
24
|
+
const functionConfigSchema = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
required: [],
|
|
27
|
+
properties: {
|
|
28
|
+
excluded_patterns: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
format: 'regexPattern',
|
|
33
|
+
errorMessage: 'excluded_patterns needs to be an array of regex that starts with ^ and ends with $ without any additional slashes before and afterwards',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
};
|
|
24
38
|
const layersSchema = {
|
|
25
39
|
type: 'object',
|
|
26
40
|
required: ['flag', 'name'],
|
|
@@ -53,6 +67,7 @@ const edgeManifestSchema = {
|
|
|
53
67
|
},
|
|
54
68
|
import_map: { type: 'string' },
|
|
55
69
|
bundler_version: { type: 'string' },
|
|
70
|
+
function_config: { type: 'object', items: functionConfigSchema },
|
|
56
71
|
},
|
|
57
72
|
additionalProperties: false,
|
|
58
73
|
};
|