@netlify/edge-bundler 8.14.1 → 8.15.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/bridge.test.js +3 -3
- package/dist/node/bundler.test.js +22 -22
- package/dist/node/config.test.js +12 -12
- package/dist/node/declaration.d.ts +2 -2
- package/dist/node/downloader.js +0 -1
- package/dist/node/downloader.test.js +1 -1
- package/dist/node/formats/javascript.js +4 -5
- package/dist/node/main.test.js +1 -1
- package/dist/node/manifest.d.ts +1 -0
- package/dist/node/manifest.js +20 -16
- package/dist/node/manifest.test.js +62 -23
- package/dist/node/stage_2.test.js +5 -6
- package/dist/node/types.test.js +3 -3
- package/dist/node/validation/manifest/schema.d.ts +16 -0
- package/dist/node/validation/manifest/schema.js +10 -8
- package/dist/test/util.js +6 -2
- package/package.json +1 -2
package/dist/node/bridge.test.js
CHANGED
|
@@ -53,7 +53,7 @@ test('Does not inherit environment variables if `extendEnv` is false', async ()
|
|
|
53
53
|
});
|
|
54
54
|
output = output.trim().replace(/\n+/g, '\n');
|
|
55
55
|
expect(output).toBe('LULU=LALA');
|
|
56
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
56
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
57
57
|
});
|
|
58
58
|
test('Does inherit environment variables if `extendEnv` is true', async () => {
|
|
59
59
|
var _a;
|
|
@@ -78,7 +78,7 @@ test('Does inherit environment variables if `extendEnv` is true', async () => {
|
|
|
78
78
|
// lets remove holes, split lines and sort lines by name, as different OSes might order them different
|
|
79
79
|
const environmentVariables = output.trim().replace(/\n+/g, '\n').split('\n').sort();
|
|
80
80
|
expect(environmentVariables).toEqual(['LULU=LALA', 'TADA=TUDU']);
|
|
81
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
81
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
82
82
|
});
|
|
83
83
|
test('Does inherit environment variables if `extendEnv` is not set', async () => {
|
|
84
84
|
var _a;
|
|
@@ -103,5 +103,5 @@ test('Does inherit environment variables if `extendEnv` is not set', async () =>
|
|
|
103
103
|
// lets remove holes, split lines and sort lines by name, as different OSes might order them different
|
|
104
104
|
const environmentVariables = output.trim().replace(/\n+/g, '\n').split('\n').sort();
|
|
105
105
|
expect(environmentVariables).toEqual(['LULU=LALA', 'TADA=TUDU']);
|
|
106
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
106
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
107
107
|
});
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { access, readdir, readFile, rm, writeFile } from 'fs/promises';
|
|
2
2
|
import { join, resolve } from 'path';
|
|
3
3
|
import process from 'process';
|
|
4
4
|
import { pathToFileURL } from 'url';
|
|
5
|
-
import { deleteAsync } from 'del';
|
|
6
5
|
import tmp from 'tmp-promise';
|
|
7
6
|
import { test, expect, vi } from 'vitest';
|
|
8
7
|
import { importMapSpecifier } from '../shared/consts.js';
|
|
@@ -26,10 +25,10 @@ test('Produces an ESZIP bundle', async () => {
|
|
|
26
25
|
configPath: join(internalDirectory, 'config.json'),
|
|
27
26
|
importMapPaths: [join(userDirectory, 'import_map.json')],
|
|
28
27
|
});
|
|
29
|
-
const generatedFiles = await
|
|
28
|
+
const generatedFiles = await readdir(distPath);
|
|
30
29
|
expect(result.functions.length).toBe(3);
|
|
31
30
|
expect(generatedFiles.length).toBe(2);
|
|
32
|
-
const manifestFile = await
|
|
31
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
33
32
|
const manifest = JSON.parse(manifestFile);
|
|
34
33
|
expect(() => validateManifest(manifest)).not.toThrowError();
|
|
35
34
|
const { bundles, import_map: importMapURL } = manifest;
|
|
@@ -57,10 +56,10 @@ test('Uses the vendored eszip module instead of fetching it from deno.land', asy
|
|
|
57
56
|
basePath,
|
|
58
57
|
configPath: join(sourceDirectory, 'config.json'),
|
|
59
58
|
});
|
|
60
|
-
const generatedFiles = await
|
|
59
|
+
const generatedFiles = await readdir(distPath);
|
|
61
60
|
expect(result.functions.length).toBe(1);
|
|
62
61
|
expect(generatedFiles.length).toBe(2);
|
|
63
|
-
const manifestFile = await
|
|
62
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
64
63
|
const manifest = JSON.parse(manifestFile);
|
|
65
64
|
const { bundles } = manifest;
|
|
66
65
|
expect(bundles.length).toBe(1);
|
|
@@ -164,10 +163,10 @@ test('Uses the cache directory as the `DENO_DIR` value', async () => {
|
|
|
164
163
|
configPath: join(sourceDirectory, 'config.json'),
|
|
165
164
|
};
|
|
166
165
|
const result = await bundle([sourceDirectory], distPath, declarations, options);
|
|
167
|
-
const outFiles = await
|
|
166
|
+
const outFiles = await readdir(distPath);
|
|
168
167
|
expect(result.functions.length).toBe(1);
|
|
169
168
|
expect(outFiles.length).toBe(2);
|
|
170
|
-
const denoDir = await
|
|
169
|
+
const denoDir = await readdir(join(cacheDir.path, 'deno_dir'));
|
|
171
170
|
expect(denoDir.includes('gen')).toBe(true);
|
|
172
171
|
await cleanup();
|
|
173
172
|
});
|
|
@@ -184,10 +183,10 @@ test('Supports import maps with relative paths', async () => {
|
|
|
184
183
|
basePath,
|
|
185
184
|
configPath: join(sourceDirectory, 'config.json'),
|
|
186
185
|
});
|
|
187
|
-
const generatedFiles = await
|
|
186
|
+
const generatedFiles = await readdir(distPath);
|
|
188
187
|
expect(result.functions.length).toBe(1);
|
|
189
188
|
expect(generatedFiles.length).toBe(2);
|
|
190
|
-
const manifestFile = await
|
|
189
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
191
190
|
const manifest = JSON.parse(manifestFile);
|
|
192
191
|
const { bundles } = manifest;
|
|
193
192
|
expect(bundles.length).toBe(1);
|
|
@@ -212,7 +211,7 @@ test('Ignores any user-defined `deno.json` files', async () => {
|
|
|
212
211
|
'https://deno.land/': 'https://black.hole/',
|
|
213
212
|
},
|
|
214
213
|
};
|
|
215
|
-
await
|
|
214
|
+
await writeFile(importMapFile.path, JSON.stringify(importMap));
|
|
216
215
|
// Deno configuration files need to be in the current working directory.
|
|
217
216
|
// There's not a great way for us to set the working directory of the `deno`
|
|
218
217
|
// process that we'll run, so our best bet is to write the file to whatever
|
|
@@ -222,7 +221,7 @@ test('Ignores any user-defined `deno.json` files', async () => {
|
|
|
222
221
|
importMap: importMapFile.path,
|
|
223
222
|
};
|
|
224
223
|
try {
|
|
225
|
-
await
|
|
224
|
+
await access(denoConfigPath);
|
|
226
225
|
throw new Error(`The file at '${denoConfigPath} would be overwritten by this test. Please move the file to a different location and try again.'`);
|
|
227
226
|
}
|
|
228
227
|
catch (error) {
|
|
@@ -230,13 +229,14 @@ test('Ignores any user-defined `deno.json` files', async () => {
|
|
|
230
229
|
throw error;
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
|
-
await
|
|
232
|
+
await writeFile(denoConfigPath, JSON.stringify(denoConfig));
|
|
234
233
|
expect(() => bundle([sourceDirectory], distPath, declarations, {
|
|
235
234
|
basePath,
|
|
236
235
|
configPath: join(sourceDirectory, 'config.json'),
|
|
237
236
|
})).not.toThrow();
|
|
238
237
|
await cleanup();
|
|
239
|
-
await
|
|
238
|
+
await rm(denoConfigPath, { force: true, recursive: true, maxRetries: 10 });
|
|
239
|
+
await rm(importMapFile.path, { force: true, recursive: true, maxRetries: 10 });
|
|
240
240
|
});
|
|
241
241
|
test('Processes a function that imports a custom layer', async () => {
|
|
242
242
|
const { basePath, cleanup, distPath } = await useFixture('with_layers');
|
|
@@ -252,10 +252,10 @@ test('Processes a function that imports a custom layer', async () => {
|
|
|
252
252
|
basePath,
|
|
253
253
|
configPath: join(sourceDirectory, 'config.json'),
|
|
254
254
|
});
|
|
255
|
-
const generatedFiles = await
|
|
255
|
+
const generatedFiles = await readdir(distPath);
|
|
256
256
|
expect(result.functions.length).toBe(1);
|
|
257
257
|
expect(generatedFiles.length).toBe(2);
|
|
258
|
-
const manifestFile = await
|
|
258
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
259
259
|
const manifest = JSON.parse(manifestFile);
|
|
260
260
|
const { bundles, layers } = manifest;
|
|
261
261
|
expect(bundles.length).toBe(1);
|
|
@@ -278,18 +278,18 @@ test('Loads declarations and import maps from the deploy configuration and in-so
|
|
|
278
278
|
configPath: join(basePath, '.netlify', 'edge-functions', 'manifest.json'),
|
|
279
279
|
internalSrcFolder: directories[1],
|
|
280
280
|
});
|
|
281
|
-
const generatedFiles = await
|
|
281
|
+
const generatedFiles = await readdir(distPath);
|
|
282
282
|
expect(result.functions.length).toBe(3);
|
|
283
283
|
expect(generatedFiles.length).toBe(2);
|
|
284
|
-
const manifestFile = await
|
|
284
|
+
const manifestFile = await readFile(resolve(distPath, 'manifest.json'), 'utf8');
|
|
285
285
|
const manifest = JSON.parse(manifestFile);
|
|
286
|
-
const { bundles, function_config: functionConfig } = manifest;
|
|
286
|
+
const { bundles, function_config: functionConfig, routes } = manifest;
|
|
287
287
|
expect(bundles.length).toBe(1);
|
|
288
288
|
expect(bundles[0].format).toBe('eszip2');
|
|
289
289
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
290
290
|
// respects excludedPath from deploy config
|
|
291
|
+
expect(routes[0].excluded_patterns).toEqual(['^/func2/skip/?$']);
|
|
291
292
|
expect(functionConfig.func2).toEqual({
|
|
292
|
-
excluded_patterns: ['^/func2/skip/?$'],
|
|
293
293
|
name: 'Function two',
|
|
294
294
|
generator: '@netlify/fake-plugin@1.0.0',
|
|
295
295
|
});
|
|
@@ -317,7 +317,7 @@ test("Ignores entries in `importMapPaths` that don't point to an existing import
|
|
|
317
317
|
},
|
|
318
318
|
},
|
|
319
319
|
};
|
|
320
|
-
await
|
|
320
|
+
await writeFile(importMap.path, JSON.stringify(importMapContents));
|
|
321
321
|
const nonExistingImportMapPath = join(distPath, 'some-file-that-does-not-exist.json');
|
|
322
322
|
const result = await bundle([sourceDirectory], distPath, [
|
|
323
323
|
{
|
|
@@ -329,7 +329,7 @@ test("Ignores entries in `importMapPaths` that don't point to an existing import
|
|
|
329
329
|
importMapPaths: [nonExistingImportMapPath, importMap.path],
|
|
330
330
|
systemLogger,
|
|
331
331
|
});
|
|
332
|
-
const generatedFiles = await
|
|
332
|
+
const generatedFiles = await readdir(distPath);
|
|
333
333
|
expect(result.functions.length).toBe(2);
|
|
334
334
|
expect(generatedFiles.length).toBe(2);
|
|
335
335
|
expect(systemLogger).toHaveBeenCalledWith(`Did not find an import map file at '${nonExistingImportMapPath}'.`);
|
package/dist/node/config.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
|
+
import { rm } from 'fs/promises';
|
|
2
3
|
import { join, resolve } from 'path';
|
|
3
4
|
import { pathToFileURL } from 'url';
|
|
4
|
-
import { deleteAsync } from 'del';
|
|
5
5
|
import tmp from 'tmp-promise';
|
|
6
6
|
import { test, expect, vi, describe } from 'vitest';
|
|
7
7
|
import { fixturesDir, useFixture } from '../test/util.js';
|
|
@@ -129,7 +129,7 @@ describe('`getFunctionConfig` extracts configuration properties from function fi
|
|
|
129
129
|
expect(config).toEqual(func.expectedConfig);
|
|
130
130
|
expect(logger.user).not.toHaveBeenCalled();
|
|
131
131
|
}
|
|
132
|
-
await
|
|
132
|
+
await rm(tmpDir, { force: true, recursive: true, maxRetries: 10 });
|
|
133
133
|
});
|
|
134
134
|
});
|
|
135
135
|
test('Loads function paths from the in-source `config` function', async () => {
|
|
@@ -160,14 +160,14 @@ test('Loads function paths from the in-source `config` function', async () => {
|
|
|
160
160
|
expect(bundles[0].format).toBe('eszip2');
|
|
161
161
|
expect(generatedFiles.includes(bundles[0].asset)).toBe(true);
|
|
162
162
|
expect(routes.length).toBe(6);
|
|
163
|
-
expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$' });
|
|
164
|
-
expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$' });
|
|
165
|
-
expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$' });
|
|
166
|
-
expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$' });
|
|
167
|
-
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$' });
|
|
168
|
-
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$' });
|
|
163
|
+
expect(routes[0]).toEqual({ function: 'framework-func2', pattern: '^/framework-func2/?$', excluded_patterns: [] });
|
|
164
|
+
expect(routes[1]).toEqual({ function: 'user-func2', pattern: '^/user-func2/?$', excluded_patterns: [] });
|
|
165
|
+
expect(routes[2]).toEqual({ function: 'framework-func1', pattern: '^/framework-func1/?$', excluded_patterns: [] });
|
|
166
|
+
expect(routes[3]).toEqual({ function: 'user-func1', pattern: '^/user-func1/?$', excluded_patterns: [] });
|
|
167
|
+
expect(routes[4]).toEqual({ function: 'user-func3', pattern: '^/user-func3/?$', excluded_patterns: [] });
|
|
168
|
+
expect(routes[5]).toEqual({ function: 'user-func5', pattern: '^/user-func5/.*/?$', excluded_patterns: [] });
|
|
169
169
|
expect(postCacheRoutes.length).toBe(1);
|
|
170
|
-
expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$' });
|
|
170
|
+
expect(postCacheRoutes[0]).toEqual({ function: 'user-func4', pattern: '^/user-func4/?$', excluded_patterns: [] });
|
|
171
171
|
expect(Object.keys(functionConfig)).toHaveLength(1);
|
|
172
172
|
expect(functionConfig['user-func5']).toEqual({
|
|
173
173
|
excluded_patterns: ['^/user-func5/excluded/?$'],
|
|
@@ -196,7 +196,7 @@ test('Passes validation if default export exists and is a function', async () =>
|
|
|
196
196
|
name: func.name,
|
|
197
197
|
path,
|
|
198
198
|
}, new ImportMap([importMapFile]), deno, logger)).resolves.not.toThrow();
|
|
199
|
-
await
|
|
199
|
+
await rm(tmpDir, { force: true, recursive: true, maxRetries: 10 });
|
|
200
200
|
});
|
|
201
201
|
test('Fails validation if default export is not function', async () => {
|
|
202
202
|
const { path: tmpDir } = await tmp.dir();
|
|
@@ -221,7 +221,7 @@ test('Fails validation if default export is not function', async () => {
|
|
|
221
221
|
path,
|
|
222
222
|
}, new ImportMap([importMapFile]), deno, logger);
|
|
223
223
|
await expect(config).rejects.toThrowError(invalidDefaultExportErr(path));
|
|
224
|
-
await
|
|
224
|
+
await rm(tmpDir, { force: true, recursive: true, maxRetries: 10 });
|
|
225
225
|
});
|
|
226
226
|
test('Fails validation if default export is not present', async () => {
|
|
227
227
|
const { path: tmpDir } = await tmp.dir();
|
|
@@ -245,5 +245,5 @@ test('Fails validation if default export is not present', async () => {
|
|
|
245
245
|
path,
|
|
246
246
|
}, new ImportMap([importMapFile]), deno, logger);
|
|
247
247
|
await expect(config).rejects.toThrowError(invalidDefaultExportErr(path));
|
|
248
|
-
await
|
|
248
|
+
await rm(tmpDir, { force: true, recursive: true, maxRetries: 10 });
|
|
249
249
|
});
|
|
@@ -8,11 +8,11 @@ interface BaseDeclaration {
|
|
|
8
8
|
}
|
|
9
9
|
type DeclarationWithPath = BaseDeclaration & {
|
|
10
10
|
path: Path;
|
|
11
|
-
excludedPath?: Path;
|
|
11
|
+
excludedPath?: Path | Path[];
|
|
12
12
|
};
|
|
13
13
|
type DeclarationWithPattern = BaseDeclaration & {
|
|
14
14
|
pattern: string;
|
|
15
|
-
excludedPattern?: string;
|
|
15
|
+
excludedPattern?: string | string[];
|
|
16
16
|
};
|
|
17
17
|
export type Declaration = DeclarationWithPath | DeclarationWithPattern;
|
|
18
18
|
export declare const mergeDeclarations: (tomlDeclarations: Declaration[], userFunctionsConfig: Record<string, FunctionConfig>, internalFunctionsConfig: Record<string, FunctionConfig>, deployConfigDeclarations: Declaration[], _featureFlags?: FeatureFlags) => Declaration[];
|
package/dist/node/downloader.js
CHANGED
|
@@ -42,7 +42,6 @@ const downloadVersion = async (versionRange) => {
|
|
|
42
42
|
const version = await getLatestVersionForRange(versionRange);
|
|
43
43
|
const url = getReleaseURL(version);
|
|
44
44
|
const res = await fetch(url);
|
|
45
|
-
// eslint-disable-next-line no-magic-numbers
|
|
46
45
|
if (res.body === null || res.status < 200 || res.status > 299) {
|
|
47
46
|
throw new Error(`Download failed with status code ${res.status}`);
|
|
48
47
|
}
|
|
@@ -30,7 +30,7 @@ beforeEach(async (ctx) => {
|
|
|
30
30
|
ctx.tmpDir = tmpDir.path;
|
|
31
31
|
});
|
|
32
32
|
afterEach(async (ctx) => {
|
|
33
|
-
await rm(ctx.tmpDir, { force: true, recursive: true });
|
|
33
|
+
await rm(ctx.tmpDir, { force: true, recursive: true, maxRetries: 10 });
|
|
34
34
|
});
|
|
35
35
|
test('tries downloading binary up to 4 times', async (ctx) => {
|
|
36
36
|
nock.disableNetConnect();
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdir, rm, writeFile } from 'fs/promises';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
|
-
import { deleteAsync } from 'del';
|
|
5
4
|
const defaultFormatExportTypeError = (name) => `The Edge Function "${name}" has failed to load. Does it have a function as the default export?`;
|
|
6
5
|
const defaultFormatImportError = (name) => `There was an error with Edge Function "${name}".`;
|
|
7
6
|
const generateStage2 = async ({ bootstrapURL, distDirectory, fileName, formatExportTypeError, formatImportError, functions, }) => {
|
|
8
|
-
await
|
|
9
|
-
await
|
|
7
|
+
await rm(distDirectory, { force: true, recursive: true, maxRetries: 3 });
|
|
8
|
+
await mkdir(distDirectory, { recursive: true });
|
|
10
9
|
const entryPoint = getLocalEntryPoint(functions, { bootstrapURL, formatExportTypeError, formatImportError });
|
|
11
10
|
const stage2Path = join(distDirectory, fileName);
|
|
12
|
-
await
|
|
11
|
+
await writeFile(stage2Path, entryPoint);
|
|
13
12
|
return stage2Path;
|
|
14
13
|
};
|
|
15
14
|
// For the local development environment, we import the user functions with
|
package/dist/node/main.test.js
CHANGED
|
@@ -43,5 +43,5 @@ test('Downloads the Deno CLI on demand and caches it for subsequent calls', asyn
|
|
|
43
43
|
expect((_d = output2 === null || output2 === void 0 ? void 0 : output2.stdout) !== null && _d !== void 0 ? _d : '').toMatch(expectedOutput);
|
|
44
44
|
expect(beforeDownload).toHaveBeenCalledTimes(1);
|
|
45
45
|
expect(afterDownload).toHaveBeenCalledTimes(1);
|
|
46
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
46
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
47
47
|
});
|
package/dist/node/manifest.d.ts
CHANGED
package/dist/node/manifest.js
CHANGED
|
@@ -58,14 +58,12 @@ const generateManifest = ({ bundles = [], declarations = [], featureFlags, funct
|
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
60
|
const pattern = getRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
|
|
61
|
+
const excludedPattern = getExcludedRegularExpressions(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
|
|
61
62
|
const route = {
|
|
62
63
|
function: func.name,
|
|
63
64
|
pattern: serializePattern(pattern),
|
|
65
|
+
excluded_patterns: excludedPattern.map(serializePattern),
|
|
64
66
|
};
|
|
65
|
-
const excludedPattern = getExcludedRegularExpression(declaration, featureFlags === null || featureFlags === void 0 ? void 0 : featureFlags.edge_functions_fail_unsupported_regex);
|
|
66
|
-
if (excludedPattern) {
|
|
67
|
-
manifestFunctionConfig[func.name].excluded_patterns.push(serializePattern(excludedPattern));
|
|
68
|
-
}
|
|
69
67
|
if (declaration.cache === "manual" /* Cache.Manual */) {
|
|
70
68
|
postCacheRoutes.push(route);
|
|
71
69
|
}
|
|
@@ -114,23 +112,29 @@ const getRegularExpression = (declaration, failUnsupportedRegex = false) => {
|
|
|
114
112
|
}
|
|
115
113
|
return pathToRegularExpression(declaration.path);
|
|
116
114
|
};
|
|
117
|
-
const
|
|
115
|
+
const getExcludedRegularExpressions = (declaration, failUnsupportedRegex = false) => {
|
|
118
116
|
if ('excludedPattern' in declaration && declaration.excludedPattern) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
|
|
117
|
+
const excludedPatterns = Array.isArray(declaration.excludedPattern)
|
|
118
|
+
? declaration.excludedPattern
|
|
119
|
+
: [declaration.excludedPattern];
|
|
120
|
+
return excludedPatterns.map((excludedPattern) => {
|
|
121
|
+
try {
|
|
122
|
+
return parsePattern(excludedPattern);
|
|
126
123
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (failUnsupportedRegex) {
|
|
126
|
+
throw new Error(`Could not parse path declaration of function '${declaration.function}': ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
console.warn(`Function '${declaration.function}' uses an unsupported regular expression and will therefore not be invoked: ${error.message}`);
|
|
129
|
+
return excludedPattern;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
130
132
|
}
|
|
131
133
|
if ('path' in declaration && declaration.excludedPath) {
|
|
132
|
-
|
|
134
|
+
const paths = Array.isArray(declaration.excludedPath) ? declaration.excludedPath : [declaration.excludedPath];
|
|
135
|
+
return paths.map(pathToRegularExpression);
|
|
133
136
|
}
|
|
137
|
+
return [];
|
|
134
138
|
};
|
|
135
139
|
const writeManifest = async ({ distDirectory, ...rest }) => {
|
|
136
140
|
const manifest = generateManifest(rest);
|
|
@@ -21,7 +21,7 @@ test('Generates a manifest with different bundles', () => {
|
|
|
21
21
|
{ asset: bundle1.hash + bundle1.extension, format: bundle1.format },
|
|
22
22
|
{ asset: bundle2.hash + bundle2.extension, format: bundle2.format },
|
|
23
23
|
];
|
|
24
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
|
|
24
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
|
|
25
25
|
expect(manifest.bundles).toEqual(expectedBundles);
|
|
26
26
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
27
27
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
@@ -35,7 +35,7 @@ test('Generates a manifest with display names', () => {
|
|
|
35
35
|
},
|
|
36
36
|
};
|
|
37
37
|
const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig });
|
|
38
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
|
|
38
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
|
|
39
39
|
expect(manifest.function_config).toEqual({
|
|
40
40
|
'func-1': { name: 'Display Name' },
|
|
41
41
|
});
|
|
@@ -51,7 +51,7 @@ test('Generates a manifest with a generator field', () => {
|
|
|
51
51
|
},
|
|
52
52
|
};
|
|
53
53
|
const manifest = generateManifest({ bundles: [], declarations, functions, internalFunctionConfig });
|
|
54
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
|
|
54
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
|
|
55
55
|
const expectedFunctionConfig = { 'func-1': { generator: '@netlify/fake-plugin@1.0.0' } };
|
|
56
56
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
57
57
|
expect(manifest.function_config).toEqual(expectedFunctionConfig);
|
|
@@ -65,21 +65,17 @@ test('Generates a manifest with excluded paths and patterns', () => {
|
|
|
65
65
|
];
|
|
66
66
|
const declarations = [
|
|
67
67
|
{ function: 'func-1', path: '/f1/*', excludedPath: '/f1/exclude' },
|
|
68
|
-
{ function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: '^/f2/exclude$' },
|
|
68
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$', excludedPattern: ['^/f2/exclude$', '^/f2/exclude-as-well$'] },
|
|
69
69
|
{ function: 'func-3', path: '/*', excludedPath: '/**/*.html' },
|
|
70
70
|
];
|
|
71
71
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
72
72
|
const expectedRoutes = [
|
|
73
|
-
{ function: 'func-1', pattern: '^/f1/.*/?$' },
|
|
74
|
-
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
75
|
-
{ function: 'func-3', pattern: '^/.*/?$' },
|
|
73
|
+
{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: ['^/f1/exclude/?$'] },
|
|
74
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: ['^/f2/exclude$', '^/f2/exclude-as-well$'] },
|
|
75
|
+
{ function: 'func-3', pattern: '^/.*/?$', excluded_patterns: ['^/.*/.*\\.html/?$'] },
|
|
76
76
|
];
|
|
77
77
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
78
|
-
expect(manifest.function_config).toEqual({
|
|
79
|
-
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
80
|
-
'func-2': { excluded_patterns: ['^/f2/exclude$'] },
|
|
81
|
-
'func-3': { excluded_patterns: ['^/.*/.*\\.html/?$'] },
|
|
82
|
-
});
|
|
78
|
+
expect(manifest.function_config).toEqual({});
|
|
83
79
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
84
80
|
const matcher = getRouteMatcher(manifest);
|
|
85
81
|
expect((_a = matcher('/f1/hello')) === null || _a === void 0 ? void 0 : _a.function).toBe('func-1');
|
|
@@ -92,7 +88,7 @@ test('TOML-defined paths can be combined with ISC-defined excluded paths', () =>
|
|
|
92
88
|
'func-1': { excludedPath: '/f1/exclude' },
|
|
93
89
|
};
|
|
94
90
|
const manifest = generateManifest({ bundles: [], declarations, functions, userFunctionConfig });
|
|
95
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$' }];
|
|
91
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] }];
|
|
96
92
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
97
93
|
expect(manifest.function_config).toEqual({
|
|
98
94
|
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
@@ -149,6 +145,49 @@ test('Filters out internal in-source configurations in user created functions',
|
|
|
149
145
|
},
|
|
150
146
|
});
|
|
151
147
|
});
|
|
148
|
+
test('excludedPath from ISC goes into function_config, TOML goes into routes', () => {
|
|
149
|
+
const functions = [{ name: 'customisation', path: '/path/to/customisation.ts' }];
|
|
150
|
+
const declarations = [
|
|
151
|
+
{ function: 'customisation', path: '/showcases/*' },
|
|
152
|
+
{ function: 'customisation', path: '/checkout/*', excludedPath: ['/*/terms-and-conditions'] },
|
|
153
|
+
];
|
|
154
|
+
const userFunctionConfig = {
|
|
155
|
+
customisation: {
|
|
156
|
+
excludedPath: ['/*.css', '/*.jpg'],
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const internalFunctionConfig = {};
|
|
160
|
+
const manifest = generateManifest({
|
|
161
|
+
bundles: [],
|
|
162
|
+
declarations,
|
|
163
|
+
functions,
|
|
164
|
+
userFunctionConfig,
|
|
165
|
+
internalFunctionConfig,
|
|
166
|
+
});
|
|
167
|
+
expect(manifest.routes).toEqual([
|
|
168
|
+
{
|
|
169
|
+
function: 'customisation',
|
|
170
|
+
pattern: '^/showcases/.*/?$',
|
|
171
|
+
excluded_patterns: [],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
function: 'customisation',
|
|
175
|
+
pattern: '^/checkout/.*/?$',
|
|
176
|
+
excluded_patterns: ['^/.*/terms-and-conditions/?$'],
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
expect(manifest.function_config).toEqual({
|
|
180
|
+
customisation: {
|
|
181
|
+
excluded_patterns: ['^/.*\\.css/?$', '^/.*\\.jpg/?$'],
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
const matcher = getRouteMatcher(manifest);
|
|
185
|
+
expect(matcher('/showcases/boho-style')).toBeDefined();
|
|
186
|
+
expect(matcher('/checkout/address')).toBeDefined();
|
|
187
|
+
expect(matcher('/checkout/terms-and-conditions')).toBeUndefined();
|
|
188
|
+
expect(matcher('/checkout/scrooge-mc-duck-animation.css')).toBeUndefined();
|
|
189
|
+
expect(matcher('/showcases/boho-style/expensive-chair.jpg')).toBeUndefined();
|
|
190
|
+
});
|
|
152
191
|
test('Includes failure modes in manifest', () => {
|
|
153
192
|
const functions = [
|
|
154
193
|
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
@@ -180,7 +219,7 @@ test('Excludes functions for which there are function files but no matching conf
|
|
|
180
219
|
];
|
|
181
220
|
const declarations = [{ function: 'func-1', path: '/f1' }];
|
|
182
221
|
const manifest = generateManifest({ bundles: [bundle1], declarations, functions });
|
|
183
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
|
|
222
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
|
|
184
223
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
185
224
|
});
|
|
186
225
|
test('Excludes functions for which there are config declarations but no matching function files', () => {
|
|
@@ -195,14 +234,14 @@ test('Excludes functions for which there are config declarations but no matching
|
|
|
195
234
|
{ function: 'func-2', path: '/f2' },
|
|
196
235
|
];
|
|
197
236
|
const manifest = generateManifest({ bundles: [bundle1], declarations, functions });
|
|
198
|
-
const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$' }];
|
|
237
|
+
const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$', excluded_patterns: [] }];
|
|
199
238
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
200
239
|
});
|
|
201
240
|
test('Generates a manifest without bundles', () => {
|
|
202
241
|
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
203
242
|
const declarations = [{ function: 'func-1', path: '/f1' }];
|
|
204
243
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
205
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$' }];
|
|
244
|
+
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [] }];
|
|
206
245
|
expect(manifest.bundles).toEqual([]);
|
|
207
246
|
expect(manifest.routes).toEqual(expectedRoutes);
|
|
208
247
|
expect(manifest.bundler_version).toBe(env.npm_package_version);
|
|
@@ -234,10 +273,10 @@ test('Generates a manifest with pre and post-cache routes', () => {
|
|
|
234
273
|
{ asset: bundle2.hash + bundle2.extension, format: bundle2.format },
|
|
235
274
|
];
|
|
236
275
|
const expectedPreCacheRoutes = [
|
|
237
|
-
{ function: 'func-1', name: undefined, pattern: '^/f1/?$' },
|
|
238
|
-
{ function: 'func-2', name: undefined, pattern: '^/f2/?$' },
|
|
276
|
+
{ function: 'func-1', name: undefined, pattern: '^/f1/?$', excluded_patterns: [] },
|
|
277
|
+
{ function: 'func-2', name: undefined, pattern: '^/f2/?$', excluded_patterns: [] },
|
|
239
278
|
];
|
|
240
|
-
const expectedPostCacheRoutes = [{ function: 'func-3', name: undefined, pattern: '^/f3/?$' }];
|
|
279
|
+
const expectedPostCacheRoutes = [{ function: 'func-3', name: undefined, pattern: '^/f3/?$', excluded_patterns: [] }];
|
|
241
280
|
expect(manifest.bundles).toEqual(expectedBundles);
|
|
242
281
|
expect(manifest.routes).toEqual(expectedPreCacheRoutes);
|
|
243
282
|
expect(manifest.post_cache_routes).toEqual(expectedPostCacheRoutes);
|
|
@@ -253,8 +292,8 @@ test('Generates a manifest with layers', () => {
|
|
|
253
292
|
{ function: 'func-2', path: '/f2/*' },
|
|
254
293
|
];
|
|
255
294
|
const expectedRoutes = [
|
|
256
|
-
{ function: 'func-1', pattern: '^/f1/.*/?$' },
|
|
257
|
-
{ function: 'func-2', pattern: '^/f2/.*/?$' },
|
|
295
|
+
{ function: 'func-1', pattern: '^/f1/.*/?$', excluded_patterns: [] },
|
|
296
|
+
{ function: 'func-2', pattern: '^/f2/.*/?$', excluded_patterns: [] },
|
|
258
297
|
];
|
|
259
298
|
const layers = [
|
|
260
299
|
{
|
|
@@ -281,7 +320,7 @@ test('Shows a warning if the regular expression contains a negative lookahead',
|
|
|
281
320
|
functions,
|
|
282
321
|
});
|
|
283
322
|
console.warn = consoleWarn;
|
|
284
|
-
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/\\w+(?=\\d)$' }]);
|
|
323
|
+
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/\\w+(?=\\d)$', excluded_patterns: [] }]);
|
|
285
324
|
expect(mockConsoleWarn).toHaveBeenCalledOnce();
|
|
286
325
|
expect(mockConsoleWarn).toHaveBeenCalledWith("Function 'func-1' uses an unsupported regular expression and will not be invoked: Regular expressions with lookaheads are not supported");
|
|
287
326
|
});
|
|
@@ -299,5 +338,5 @@ test('Converts named capture groups to unnamed capture groups in regular express
|
|
|
299
338
|
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
300
339
|
const declarations = [{ function: 'func-1', pattern: '^/(?<name>\\w+)$' }];
|
|
301
340
|
const manifest = generateManifest({ bundles: [], declarations, functions });
|
|
302
|
-
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(\\w+)$' }]);
|
|
341
|
+
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(\\w+)$', excluded_patterns: [] }]);
|
|
303
342
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rm, writeFile } from 'fs/promises';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { pathToFileURL } from 'url';
|
|
4
|
-
import { deleteAsync } from 'del';
|
|
5
4
|
import { execa } from 'execa';
|
|
6
5
|
import tmp from 'tmp-promise';
|
|
7
6
|
import { test, expect } from 'vitest';
|
|
@@ -23,18 +22,18 @@ test('`getLocalEntryPoint` returns a valid stage 2 file for local development',
|
|
|
23
22
|
`;
|
|
24
23
|
const printerPath = join(tmpDir, 'printer.mjs');
|
|
25
24
|
const bootstrapURL = pathToFileURL(printerPath).toString();
|
|
26
|
-
await
|
|
25
|
+
await writeFile(printerPath, printer);
|
|
27
26
|
const functions = [
|
|
28
27
|
{ name: 'func1', path: join(tmpDir, 'func1.mjs'), response: 'Hello from function 1' },
|
|
29
28
|
{ name: 'func2', path: join(tmpDir, 'func2.mjs'), response: 'Hello from function 2' },
|
|
30
29
|
];
|
|
31
30
|
for (const func of functions) {
|
|
32
31
|
const contents = `export default () => ${JSON.stringify(func.response)}`;
|
|
33
|
-
await
|
|
32
|
+
await writeFile(func.path, contents);
|
|
34
33
|
}
|
|
35
34
|
const stage2 = getLocalEntryPoint(functions.map(({ name, path }) => ({ name, path })), { bootstrapURL });
|
|
36
35
|
const stage2Path = join(tmpDir, 'stage2.mjs');
|
|
37
|
-
await
|
|
36
|
+
await writeFile(stage2Path, stage2);
|
|
38
37
|
const { stdout, stderr } = await execa('deno', ['run', '--allow-all', stage2Path]);
|
|
39
38
|
expect(stderr).toBe('');
|
|
40
39
|
const { metadata, responses } = JSON.parse(stdout);
|
|
@@ -42,5 +41,5 @@ test('`getLocalEntryPoint` returns a valid stage 2 file for local development',
|
|
|
42
41
|
expect(responses[func.name]).toBe(func.response);
|
|
43
42
|
expect(metadata.functions[func.name].url).toBe(pathToFileURL(func.path).toString());
|
|
44
43
|
}
|
|
45
|
-
await
|
|
44
|
+
await rm(tmpDir, { force: true, recursive: true });
|
|
46
45
|
});
|
package/dist/node/types.test.js
CHANGED
|
@@ -24,7 +24,7 @@ test('`ensureLatestTypes` updates the Deno CLI cache if the local version of typ
|
|
|
24
24
|
expect(mock).toHaveBeenCalledWith(['cache', '-r', mockURL]);
|
|
25
25
|
expect(versionFile).toBe(mockVersion);
|
|
26
26
|
mock.mockRestore();
|
|
27
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
27
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
28
28
|
});
|
|
29
29
|
test('`ensureLatestTypes` does not update the Deno CLI cache if the local version of types is up-to-date', async () => {
|
|
30
30
|
const mockURL = 'https://edge.netlify';
|
|
@@ -43,7 +43,7 @@ test('`ensureLatestTypes` does not update the Deno CLI cache if the local versio
|
|
|
43
43
|
expect(latestVersionMock.isDone()).toBe(true);
|
|
44
44
|
expect(mock).not.toHaveBeenCalled();
|
|
45
45
|
mock.mockRestore();
|
|
46
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
46
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
47
47
|
});
|
|
48
48
|
test('`ensureLatestTypes` does not throw if the types URL is not available', async () => {
|
|
49
49
|
const mockURL = 'https://edge.netlify';
|
|
@@ -59,5 +59,5 @@ test('`ensureLatestTypes` does not throw if the types URL is not available', asy
|
|
|
59
59
|
expect(latestVersionMock.isDone()).toBe(true);
|
|
60
60
|
expect(mock).not.toHaveBeenCalled();
|
|
61
61
|
mock.mockRestore();
|
|
62
|
-
await rm(tmpDir.path, { force: true, recursive: true });
|
|
62
|
+
await rm(tmpDir.path, { force: true, recursive: true, maxRetries: 10 });
|
|
63
63
|
});
|
|
@@ -36,6 +36,14 @@ declare const edgeManifestSchema: {
|
|
|
36
36
|
format: string;
|
|
37
37
|
errorMessage: string;
|
|
38
38
|
};
|
|
39
|
+
excluded_patterns: {
|
|
40
|
+
type: string;
|
|
41
|
+
items: {
|
|
42
|
+
type: string;
|
|
43
|
+
format: string;
|
|
44
|
+
errorMessage: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
39
47
|
generator: {
|
|
40
48
|
type: string;
|
|
41
49
|
};
|
|
@@ -60,6 +68,14 @@ declare const edgeManifestSchema: {
|
|
|
60
68
|
format: string;
|
|
61
69
|
errorMessage: string;
|
|
62
70
|
};
|
|
71
|
+
excluded_patterns: {
|
|
72
|
+
type: string;
|
|
73
|
+
items: {
|
|
74
|
+
type: string;
|
|
75
|
+
format: string;
|
|
76
|
+
errorMessage: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
63
79
|
generator: {
|
|
64
80
|
type: string;
|
|
65
81
|
};
|
|
@@ -7,6 +7,14 @@ const bundlesSchema = {
|
|
|
7
7
|
},
|
|
8
8
|
additionalProperties: false,
|
|
9
9
|
};
|
|
10
|
+
const excludedPatternsSchema = {
|
|
11
|
+
type: 'array',
|
|
12
|
+
items: {
|
|
13
|
+
type: 'string',
|
|
14
|
+
format: 'regexPattern',
|
|
15
|
+
errorMessage: 'excluded_patterns must be an array of regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
10
18
|
const routesSchema = {
|
|
11
19
|
type: 'object',
|
|
12
20
|
required: ['function', 'pattern'],
|
|
@@ -18,6 +26,7 @@ const routesSchema = {
|
|
|
18
26
|
format: 'regexPattern',
|
|
19
27
|
errorMessage: 'pattern must be a regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
|
|
20
28
|
},
|
|
29
|
+
excluded_patterns: excludedPatternsSchema,
|
|
21
30
|
generator: { type: 'string' },
|
|
22
31
|
},
|
|
23
32
|
additionalProperties: false,
|
|
@@ -26,14 +35,7 @@ const functionConfigSchema = {
|
|
|
26
35
|
type: 'object',
|
|
27
36
|
required: [],
|
|
28
37
|
properties: {
|
|
29
|
-
excluded_patterns:
|
|
30
|
-
type: 'array',
|
|
31
|
-
items: {
|
|
32
|
-
type: 'string',
|
|
33
|
-
format: 'regexPattern',
|
|
34
|
-
errorMessage: 'excluded_patterns must be an array of regex that starts with ^ and ends with $ (e.g. ^/blog/[d]{4}$)',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
38
|
+
excluded_patterns: excludedPatternsSchema,
|
|
37
39
|
on_error: { type: 'string' },
|
|
38
40
|
},
|
|
39
41
|
};
|
package/dist/test/util.js
CHANGED
|
@@ -36,12 +36,16 @@ const inspectFunction = (path) => `
|
|
|
36
36
|
console.log(JSON.stringify(responses));
|
|
37
37
|
`;
|
|
38
38
|
const getRouteMatcher = (manifest) => (candidate) => manifest.routes.find((route) => {
|
|
39
|
+
var _a, _b;
|
|
39
40
|
const regex = new RegExp(route.pattern);
|
|
40
41
|
if (!regex.test(candidate)) {
|
|
41
42
|
return false;
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
if (route.excluded_patterns.some((pattern) => new RegExp(pattern).test(candidate))) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const excludedPatterns = (_b = (_a = manifest.function_config[route.function]) === null || _a === void 0 ? void 0 : _a.excluded_patterns) !== null && _b !== void 0 ? _b : [];
|
|
48
|
+
const isExcluded = excludedPatterns.some((pattern) => new RegExp(pattern).test(candidate));
|
|
45
49
|
return !isExcluded;
|
|
46
50
|
});
|
|
47
51
|
const runESZIP = async (eszipPath) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.15.0",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -78,7 +78,6 @@
|
|
|
78
78
|
"ajv-errors": "^3.0.0",
|
|
79
79
|
"better-ajv-errors": "^1.2.0",
|
|
80
80
|
"common-path-prefix": "^3.0.0",
|
|
81
|
-
"del": "^7.0.0",
|
|
82
81
|
"env-paths": "^3.0.0",
|
|
83
82
|
"execa": "^6.0.0",
|
|
84
83
|
"find-up": "^6.3.0",
|