@netlify/edge-bundler 14.8.2 → 14.8.4
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.d.ts +1 -1
- package/dist/node/bridge.js +3 -3
- package/dist/node/bundler.js +41 -46
- package/dist/node/config.js +6 -1
- package/dist/node/feature_flags.js +1 -1
- package/dist/node/formats/eszip.d.ts +0 -4
- package/dist/node/formats/eszip.js +0 -11
- package/package.json +4 -3
- package/deno/extract.ts +0 -7
- package/dist/node/bridge.test.js +0 -141
- package/dist/node/bundler.test.js +0 -717
- package/dist/node/config.test.js +0 -408
- package/dist/node/declaration.test.js +0 -131
- package/dist/node/deploy_config.test.js +0 -48
- package/dist/node/downloader.test.js +0 -124
- package/dist/node/finder.test.js +0 -17
- package/dist/node/import_map.test.js +0 -212
- package/dist/node/logger.test.js +0 -51
- package/dist/node/main.test.js +0 -46
- package/dist/node/manifest.test.js +0 -597
- package/dist/node/package_json.test.js +0 -7
- package/dist/node/server/server.test.js +0 -144
- package/dist/node/stage_2.test.js +0 -53
- package/dist/node/types.test.js +0 -63
- package/dist/node/validation/manifest/index.test.js +0 -237
|
@@ -1,597 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from 'vitest';
|
|
2
|
-
// @ts-expect-error current tsconfig.json doesn't allow this, but I don't want to change it
|
|
3
|
-
import { version } from '../package.json' assert { type: 'json' };
|
|
4
|
-
import { getRouteMatcher } from '../test/util.js';
|
|
5
|
-
import { BundleFormat } from './bundle.js';
|
|
6
|
-
import { BundleError } from './bundle_error.js';
|
|
7
|
-
import { generateManifest } from './manifest.js';
|
|
8
|
-
import { RateLimitAction, RateLimitAggregator } from './rate_limit.js';
|
|
9
|
-
test('Generates a manifest with different bundles', () => {
|
|
10
|
-
const bundle1 = {
|
|
11
|
-
extension: '.ext1',
|
|
12
|
-
format: BundleFormat.ESZIP2,
|
|
13
|
-
hash: '123456',
|
|
14
|
-
};
|
|
15
|
-
const bundle2 = {
|
|
16
|
-
extension: '.ext2',
|
|
17
|
-
format: BundleFormat.ESZIP2,
|
|
18
|
-
hash: '654321',
|
|
19
|
-
};
|
|
20
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
21
|
-
const declarations = [{ function: 'func-1', path: '/f1' }];
|
|
22
|
-
const { manifest } = generateManifest({ bundles: [bundle1, bundle2], declarations, functions });
|
|
23
|
-
const expectedBundles = [
|
|
24
|
-
{ asset: bundle1.hash + bundle1.extension, format: bundle1.format },
|
|
25
|
-
{ asset: bundle2.hash + bundle2.extension, format: bundle2.format },
|
|
26
|
-
];
|
|
27
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [], path: '/f1' }];
|
|
28
|
-
expect(manifest.bundles).toEqual(expectedBundles);
|
|
29
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
30
|
-
expect(manifest.bundler_version).toBe(version);
|
|
31
|
-
});
|
|
32
|
-
test('Generates a manifest with display names', () => {
|
|
33
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
34
|
-
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
35
|
-
const internalFunctionConfig = {
|
|
36
|
-
'func-1': {
|
|
37
|
-
name: 'Display Name',
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
const { manifest } = generateManifest({
|
|
41
|
-
bundles: [],
|
|
42
|
-
declarations,
|
|
43
|
-
functions,
|
|
44
|
-
internalFunctionConfig,
|
|
45
|
-
});
|
|
46
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' }];
|
|
47
|
-
expect(manifest.function_config).toEqual({
|
|
48
|
-
'func-1': { name: 'Display Name' },
|
|
49
|
-
});
|
|
50
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
51
|
-
expect(manifest.bundler_version).toBe(version);
|
|
52
|
-
});
|
|
53
|
-
test('Generates a manifest with a generator field', () => {
|
|
54
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
55
|
-
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
56
|
-
const internalFunctionConfig = {
|
|
57
|
-
'func-1': {
|
|
58
|
-
generator: '@netlify/fake-plugin@1.0.0',
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
const { manifest } = generateManifest({
|
|
62
|
-
bundles: [],
|
|
63
|
-
declarations,
|
|
64
|
-
functions,
|
|
65
|
-
internalFunctionConfig,
|
|
66
|
-
});
|
|
67
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' }];
|
|
68
|
-
const expectedFunctionConfig = { 'func-1': { generator: '@netlify/fake-plugin@1.0.0' } };
|
|
69
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
70
|
-
expect(manifest.function_config).toEqual(expectedFunctionConfig);
|
|
71
|
-
});
|
|
72
|
-
test('Generates a manifest with excluded paths and patterns', () => {
|
|
73
|
-
const functions = [
|
|
74
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
75
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
76
|
-
{ name: 'func-3', path: '/path/to/func-3.ts' },
|
|
77
|
-
];
|
|
78
|
-
const declarations = [
|
|
79
|
-
{ function: 'func-1', path: '/f1/*', excludedPath: '/f1/exclude' },
|
|
80
|
-
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$', excludedPattern: ['^/f2/exclude$', '^/f2/exclude-as-well$'] },
|
|
81
|
-
{ function: 'func-3', path: '/*', excludedPath: '/**/*.html' },
|
|
82
|
-
];
|
|
83
|
-
const { manifest } = generateManifest({
|
|
84
|
-
bundles: [],
|
|
85
|
-
declarations,
|
|
86
|
-
functions,
|
|
87
|
-
});
|
|
88
|
-
const expectedRoutes = [
|
|
89
|
-
{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: ['^/f1/exclude/?$'], path: '/f1/*' },
|
|
90
|
-
{
|
|
91
|
-
function: 'func-2',
|
|
92
|
-
pattern: '^/f2(?:/(.*))/?$',
|
|
93
|
-
excluded_patterns: ['^/f2/exclude$', '^/f2/exclude-as-well$'],
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
function: 'func-3',
|
|
97
|
-
pattern: '^(?:/(.*))/?$',
|
|
98
|
-
excluded_patterns: ['^(?:/((?:.*)(?:/(?:.*))*))?(?:/(.*))\\.html/?$'],
|
|
99
|
-
path: '/*',
|
|
100
|
-
},
|
|
101
|
-
];
|
|
102
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
103
|
-
expect(manifest.function_config).toEqual({});
|
|
104
|
-
expect(manifest.bundler_version).toBe(version);
|
|
105
|
-
const matcher = getRouteMatcher(manifest);
|
|
106
|
-
expect(matcher('/f1/hello')?.function).toBe('func-1');
|
|
107
|
-
expect(matcher('/grandparent/parent/child/grandchild.html')?.function).toBeUndefined();
|
|
108
|
-
});
|
|
109
|
-
test('TOML-defined paths can be combined with ISC-defined excluded paths', () => {
|
|
110
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
111
|
-
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
112
|
-
const userFunctionConfig = {
|
|
113
|
-
'func-1': { excludedPath: '/f1/exclude' },
|
|
114
|
-
};
|
|
115
|
-
const { manifest } = generateManifest({
|
|
116
|
-
bundles: [],
|
|
117
|
-
declarations,
|
|
118
|
-
functions,
|
|
119
|
-
userFunctionConfig,
|
|
120
|
-
});
|
|
121
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' }];
|
|
122
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
123
|
-
expect(manifest.function_config).toEqual({
|
|
124
|
-
'func-1': { excluded_patterns: ['^/f1/exclude/?$'] },
|
|
125
|
-
});
|
|
126
|
-
expect(manifest.bundler_version).toBe(version);
|
|
127
|
-
});
|
|
128
|
-
test('Filters out internal in-source configurations in user created functions', () => {
|
|
129
|
-
const functions = [
|
|
130
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
131
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
132
|
-
];
|
|
133
|
-
const declarations = [
|
|
134
|
-
{ function: 'func-1', path: '/f1/*' },
|
|
135
|
-
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$' },
|
|
136
|
-
];
|
|
137
|
-
const userFunctionConfig = {
|
|
138
|
-
'func-1': {
|
|
139
|
-
onError: '/custom-error',
|
|
140
|
-
cache: "manual" /* Cache.Manual */,
|
|
141
|
-
excludedPath: '/f1/exclude',
|
|
142
|
-
path: '/path/to/func-1.ts',
|
|
143
|
-
name: 'User function',
|
|
144
|
-
generator: 'fake-generator',
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
const internalFunctionConfig = {
|
|
148
|
-
'func-2': {
|
|
149
|
-
onError: 'bypass',
|
|
150
|
-
cache: "off" /* Cache.Off */,
|
|
151
|
-
excludedPath: '/f2/exclude',
|
|
152
|
-
path: '/path/to/func-2.ts',
|
|
153
|
-
name: 'Internal function',
|
|
154
|
-
generator: 'internal-generator',
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
const { manifest } = generateManifest({
|
|
158
|
-
bundles: [],
|
|
159
|
-
declarations,
|
|
160
|
-
functions,
|
|
161
|
-
userFunctionConfig,
|
|
162
|
-
internalFunctionConfig,
|
|
163
|
-
});
|
|
164
|
-
expect(manifest.function_config).toEqual({
|
|
165
|
-
'func-1': {
|
|
166
|
-
on_error: '/custom-error',
|
|
167
|
-
excluded_patterns: ['^/f1/exclude/?$'],
|
|
168
|
-
},
|
|
169
|
-
'func-2': {
|
|
170
|
-
on_error: 'bypass',
|
|
171
|
-
cache: "off" /* Cache.Off */,
|
|
172
|
-
name: 'Internal function',
|
|
173
|
-
generator: 'internal-generator',
|
|
174
|
-
excluded_patterns: ['^/f2/exclude/?$'],
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
test('excludedPath from ISC goes into function_config, TOML goes into routes', () => {
|
|
179
|
-
const functions = [{ name: 'customisation', path: '/path/to/customisation.ts' }];
|
|
180
|
-
const declarations = [
|
|
181
|
-
{ function: 'customisation', path: '/showcases/*' },
|
|
182
|
-
{ function: 'customisation', path: '/checkout/*', excludedPath: ['/*/terms-and-conditions'] },
|
|
183
|
-
];
|
|
184
|
-
const userFunctionConfig = {
|
|
185
|
-
customisation: {
|
|
186
|
-
excludedPath: ['/*.css', '/*.jpg'],
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
const internalFunctionConfig = {};
|
|
190
|
-
const { manifest } = generateManifest({
|
|
191
|
-
bundles: [],
|
|
192
|
-
declarations,
|
|
193
|
-
functions,
|
|
194
|
-
userFunctionConfig,
|
|
195
|
-
internalFunctionConfig,
|
|
196
|
-
});
|
|
197
|
-
expect(manifest.routes).toEqual([
|
|
198
|
-
{
|
|
199
|
-
function: 'customisation',
|
|
200
|
-
pattern: '^/showcases(?:/(.*))/?$',
|
|
201
|
-
excluded_patterns: [],
|
|
202
|
-
path: '/showcases/*',
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
function: 'customisation',
|
|
206
|
-
pattern: '^/checkout(?:/(.*))/?$',
|
|
207
|
-
excluded_patterns: ['^(?:/(.*))/terms-and-conditions/?$'],
|
|
208
|
-
path: '/checkout/*',
|
|
209
|
-
},
|
|
210
|
-
]);
|
|
211
|
-
expect(manifest.function_config).toEqual({
|
|
212
|
-
customisation: {
|
|
213
|
-
excluded_patterns: ['^(?:/(.*))\\.css/?$', '^(?:/(.*))\\.jpg/?$'],
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
const matcher = getRouteMatcher(manifest);
|
|
217
|
-
expect(matcher('/showcases/boho-matcher')).toBeDefined();
|
|
218
|
-
expect(matcher('/checkout/address')).toBeDefined();
|
|
219
|
-
expect(matcher('/checkout/terms-and-conditions')).toBeUndefined();
|
|
220
|
-
expect(matcher('/checkout/scrooge-mc-duck-animation.css')).toBeUndefined();
|
|
221
|
-
expect(matcher('/showcases/boho-matcher/expensive-chair.jpg')).toBeUndefined();
|
|
222
|
-
});
|
|
223
|
-
test('URLPattern named groups are supported', () => {
|
|
224
|
-
const functions = [{ name: 'customisation', path: '/path/to/customisation.ts' }];
|
|
225
|
-
const declarations = [{ function: 'customisation', path: '/products/:productId' }];
|
|
226
|
-
const userFunctionConfig = {};
|
|
227
|
-
const internalFunctionConfig = {};
|
|
228
|
-
const { manifest } = generateManifest({
|
|
229
|
-
bundles: [],
|
|
230
|
-
declarations,
|
|
231
|
-
functions,
|
|
232
|
-
userFunctionConfig,
|
|
233
|
-
internalFunctionConfig,
|
|
234
|
-
});
|
|
235
|
-
expect(manifest.routes).toEqual([
|
|
236
|
-
{
|
|
237
|
-
function: 'customisation',
|
|
238
|
-
pattern: '^/products(?:/([^/]+?))/?$',
|
|
239
|
-
excluded_patterns: [],
|
|
240
|
-
path: '/products/:productId',
|
|
241
|
-
},
|
|
242
|
-
]);
|
|
243
|
-
const matcher = getRouteMatcher(manifest);
|
|
244
|
-
expect(matcher('/products/jigsaw-doweling-jig')).toBeDefined();
|
|
245
|
-
});
|
|
246
|
-
test('Invalid Path patterns throw bundling errors', () => {
|
|
247
|
-
const functions = [{ name: 'customisation', path: '/path/to/customisation.ts' }];
|
|
248
|
-
const declarations = [{ function: 'customisation', path: '/https://foo.netlify.app/' }];
|
|
249
|
-
const userFunctionConfig = {};
|
|
250
|
-
const internalFunctionConfig = {};
|
|
251
|
-
expect(() => generateManifest({
|
|
252
|
-
bundles: [],
|
|
253
|
-
declarations,
|
|
254
|
-
functions,
|
|
255
|
-
userFunctionConfig,
|
|
256
|
-
internalFunctionConfig,
|
|
257
|
-
})).toThrowError(BundleError);
|
|
258
|
-
});
|
|
259
|
-
test('Includes failure modes in manifest', () => {
|
|
260
|
-
const functions = [
|
|
261
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
262
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
263
|
-
];
|
|
264
|
-
const declarations = [
|
|
265
|
-
{ function: 'func-1', path: '/f1/*' },
|
|
266
|
-
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$' },
|
|
267
|
-
];
|
|
268
|
-
const userFunctionConfig = {
|
|
269
|
-
'func-1': {
|
|
270
|
-
onError: '/custom-error',
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
const { manifest } = generateManifest({ bundles: [], declarations, functions, userFunctionConfig });
|
|
274
|
-
expect(manifest.function_config).toEqual({
|
|
275
|
-
'func-1': { on_error: '/custom-error' },
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
test('Excludes functions for which there are function files but no matching config declarations', () => {
|
|
279
|
-
const bundle1 = {
|
|
280
|
-
extension: '.ext2',
|
|
281
|
-
format: BundleFormat.ESZIP2,
|
|
282
|
-
hash: '123456',
|
|
283
|
-
};
|
|
284
|
-
const functions = [
|
|
285
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
286
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
287
|
-
];
|
|
288
|
-
const declarations = [{ function: 'func-1', path: '/f1' }];
|
|
289
|
-
const { manifest } = generateManifest({ bundles: [bundle1], declarations, functions });
|
|
290
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [], path: '/f1' }];
|
|
291
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
292
|
-
});
|
|
293
|
-
test('Excludes functions for which there are config declarations but no matching function files', () => {
|
|
294
|
-
const bundle1 = {
|
|
295
|
-
extension: '.ext2',
|
|
296
|
-
format: BundleFormat.ESZIP2,
|
|
297
|
-
hash: '123456',
|
|
298
|
-
};
|
|
299
|
-
const functions = [{ name: 'func-2', path: '/path/to/func-2.ts' }];
|
|
300
|
-
const declarations = [
|
|
301
|
-
{ function: 'func-1', path: '/f1' },
|
|
302
|
-
{ function: 'func-2', path: '/f2' },
|
|
303
|
-
];
|
|
304
|
-
const { manifest } = generateManifest({ bundles: [bundle1], declarations, functions });
|
|
305
|
-
const expectedRoutes = [{ function: 'func-2', pattern: '^/f2/?$', excluded_patterns: [], path: '/f2' }];
|
|
306
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
307
|
-
});
|
|
308
|
-
test('Generates a manifest without bundles', () => {
|
|
309
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
310
|
-
const declarations = [{ function: 'func-1', path: '/f1' }];
|
|
311
|
-
const { manifest } = generateManifest({ bundles: [], declarations, functions });
|
|
312
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [], path: '/f1' }];
|
|
313
|
-
expect(manifest.bundles).toEqual([]);
|
|
314
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
315
|
-
expect(manifest.bundler_version).toBe(version);
|
|
316
|
-
});
|
|
317
|
-
test('Generates a manifest with pre and post-cache routes', () => {
|
|
318
|
-
const bundle1 = {
|
|
319
|
-
extension: '.ext1',
|
|
320
|
-
format: BundleFormat.ESZIP2,
|
|
321
|
-
hash: '123456',
|
|
322
|
-
};
|
|
323
|
-
const bundle2 = {
|
|
324
|
-
extension: '.ext2',
|
|
325
|
-
format: BundleFormat.ESZIP2,
|
|
326
|
-
hash: '654321',
|
|
327
|
-
};
|
|
328
|
-
const functions = [
|
|
329
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
330
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
331
|
-
{ name: 'func-3', path: '/path/to/func-3.ts' },
|
|
332
|
-
];
|
|
333
|
-
const declarations = [
|
|
334
|
-
{ function: 'func-1', path: '/f1' },
|
|
335
|
-
{ function: 'func-2', cache: 'not_a_supported_value', path: '/f2' },
|
|
336
|
-
{ function: 'func-3', cache: 'manual', path: '/f3' },
|
|
337
|
-
];
|
|
338
|
-
const { manifest } = generateManifest({ bundles: [bundle1, bundle2], declarations, functions });
|
|
339
|
-
const expectedBundles = [
|
|
340
|
-
{ asset: bundle1.hash + bundle1.extension, format: bundle1.format },
|
|
341
|
-
{ asset: bundle2.hash + bundle2.extension, format: bundle2.format },
|
|
342
|
-
];
|
|
343
|
-
const expectedPreCacheRoutes = [
|
|
344
|
-
{ function: 'func-1', name: undefined, pattern: '^/f1/?$', excluded_patterns: [], path: '/f1' },
|
|
345
|
-
{ function: 'func-2', name: undefined, pattern: '^/f2/?$', excluded_patterns: [], path: '/f2' },
|
|
346
|
-
];
|
|
347
|
-
const expectedPostCacheRoutes = [
|
|
348
|
-
{ function: 'func-3', name: undefined, pattern: '^/f3/?$', excluded_patterns: [], path: '/f3' },
|
|
349
|
-
];
|
|
350
|
-
expect(manifest.bundles).toEqual(expectedBundles);
|
|
351
|
-
expect(manifest.routes).toEqual(expectedPreCacheRoutes);
|
|
352
|
-
expect(manifest.post_cache_routes).toEqual(expectedPostCacheRoutes);
|
|
353
|
-
expect(manifest.bundler_version).toBe(version);
|
|
354
|
-
});
|
|
355
|
-
test('Generates a manifest with layers', () => {
|
|
356
|
-
const functions = [
|
|
357
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
358
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
359
|
-
];
|
|
360
|
-
const declarations = [
|
|
361
|
-
{ function: 'func-1', path: '/f1/*' },
|
|
362
|
-
{ function: 'func-2', path: '/f2/*' },
|
|
363
|
-
];
|
|
364
|
-
const expectedRoutes = [
|
|
365
|
-
{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' },
|
|
366
|
-
{ function: 'func-2', pattern: '^/f2(?:/(.*))/?$', excluded_patterns: [], path: '/f2/*' },
|
|
367
|
-
];
|
|
368
|
-
const layers = [
|
|
369
|
-
{
|
|
370
|
-
name: 'onion',
|
|
371
|
-
flag: 'edge_functions_onion_layer',
|
|
372
|
-
},
|
|
373
|
-
];
|
|
374
|
-
const { manifest: manifest1 } = generateManifest({
|
|
375
|
-
bundles: [],
|
|
376
|
-
declarations,
|
|
377
|
-
functions,
|
|
378
|
-
});
|
|
379
|
-
const { manifest: manifest2 } = generateManifest({
|
|
380
|
-
bundles: [],
|
|
381
|
-
declarations,
|
|
382
|
-
functions,
|
|
383
|
-
layers,
|
|
384
|
-
});
|
|
385
|
-
expect(manifest1.routes).toEqual(expectedRoutes);
|
|
386
|
-
expect(manifest1.layers).toEqual([]);
|
|
387
|
-
expect(manifest2.routes).toEqual(expectedRoutes);
|
|
388
|
-
expect(manifest2.layers).toEqual(layers);
|
|
389
|
-
});
|
|
390
|
-
test('Accepts regular expressions with lookaheads', () => {
|
|
391
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
392
|
-
const declarations = [{ function: 'func-1', pattern: '^\\/((?!api|_next\\/static|_next\\/image|favicon.ico).*)$' }];
|
|
393
|
-
const { manifest } = generateManifest({
|
|
394
|
-
bundles: [],
|
|
395
|
-
declarations,
|
|
396
|
-
functions,
|
|
397
|
-
});
|
|
398
|
-
const [route] = manifest.routes;
|
|
399
|
-
const regexp = new RegExp(route.pattern);
|
|
400
|
-
expect(regexp.test('/foo')).toBeTruthy();
|
|
401
|
-
expect(regexp.test('/_next/static/foo')).toBeFalsy();
|
|
402
|
-
});
|
|
403
|
-
test('Accepts regular expressions with named capture groups', () => {
|
|
404
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
405
|
-
const declarations = [{ function: 'func-1', pattern: '^/(?<name>\\w+)$' }];
|
|
406
|
-
const { manifest } = generateManifest({ bundles: [], declarations, functions });
|
|
407
|
-
expect(manifest.routes).toEqual([{ function: 'func-1', pattern: '^/(?<name>\\w+)$', excluded_patterns: [] }]);
|
|
408
|
-
});
|
|
409
|
-
test('Returns functions without a declaration and unrouted functions', () => {
|
|
410
|
-
const bundle = {
|
|
411
|
-
extension: '.ext1',
|
|
412
|
-
format: BundleFormat.ESZIP2,
|
|
413
|
-
hash: '123456',
|
|
414
|
-
};
|
|
415
|
-
const functions = [
|
|
416
|
-
{ name: 'func-1', path: '/path/to/func-1.ts' },
|
|
417
|
-
{ name: 'func-2', path: '/path/to/func-2.ts' },
|
|
418
|
-
{ name: 'func-4', path: '/path/to/func-4.ts' },
|
|
419
|
-
];
|
|
420
|
-
const declarations = [
|
|
421
|
-
{ function: 'func-1', path: '/f1' },
|
|
422
|
-
{ function: 'func-3', path: '/f3' },
|
|
423
|
-
// @ts-expect-error Error is expected due to neither `path` or `pattern`
|
|
424
|
-
// being present.
|
|
425
|
-
{ function: 'func-4', name: 'Some name' },
|
|
426
|
-
];
|
|
427
|
-
const { declarationsWithoutFunction, manifest, unroutedFunctions } = generateManifest({
|
|
428
|
-
bundles: [bundle],
|
|
429
|
-
declarations,
|
|
430
|
-
functions,
|
|
431
|
-
});
|
|
432
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1/?$', excluded_patterns: [], path: '/f1' }];
|
|
433
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
434
|
-
expect(declarationsWithoutFunction).toEqual(['func-3']);
|
|
435
|
-
expect(unroutedFunctions).toEqual(['func-2', 'func-4']);
|
|
436
|
-
});
|
|
437
|
-
test('Generates a manifest with rate limit config', () => {
|
|
438
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
439
|
-
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
440
|
-
const userFunctionConfig = {
|
|
441
|
-
'func-1': { rateLimit: { windowLimit: 100, windowSize: 60 } },
|
|
442
|
-
};
|
|
443
|
-
const { manifest } = generateManifest({
|
|
444
|
-
bundles: [],
|
|
445
|
-
declarations,
|
|
446
|
-
functions,
|
|
447
|
-
userFunctionConfig,
|
|
448
|
-
});
|
|
449
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' }];
|
|
450
|
-
const expectedFunctionConfig = {
|
|
451
|
-
'func-1': {
|
|
452
|
-
traffic_rules: {
|
|
453
|
-
action: {
|
|
454
|
-
type: 'rate_limit',
|
|
455
|
-
config: {
|
|
456
|
-
rate_limit_config: {
|
|
457
|
-
window_limit: 100,
|
|
458
|
-
window_size: 60,
|
|
459
|
-
algorithm: 'sliding_window',
|
|
460
|
-
},
|
|
461
|
-
aggregate: {
|
|
462
|
-
keys: [{ type: 'domain' }],
|
|
463
|
-
},
|
|
464
|
-
},
|
|
465
|
-
},
|
|
466
|
-
},
|
|
467
|
-
},
|
|
468
|
-
};
|
|
469
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
470
|
-
expect(manifest.function_config).toEqual(expectedFunctionConfig);
|
|
471
|
-
});
|
|
472
|
-
test('Generates a manifest with rewrite config', () => {
|
|
473
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
474
|
-
const declarations = [{ function: 'func-1', path: '/f1/*' }];
|
|
475
|
-
const userFunctionConfig = {
|
|
476
|
-
'func-1': {
|
|
477
|
-
rateLimit: {
|
|
478
|
-
action: RateLimitAction.Rewrite,
|
|
479
|
-
to: '/new_path',
|
|
480
|
-
windowLimit: 100,
|
|
481
|
-
windowSize: 60,
|
|
482
|
-
aggregateBy: [RateLimitAggregator.Domain, RateLimitAggregator.IP],
|
|
483
|
-
},
|
|
484
|
-
},
|
|
485
|
-
};
|
|
486
|
-
const { manifest } = generateManifest({
|
|
487
|
-
bundles: [],
|
|
488
|
-
declarations,
|
|
489
|
-
functions,
|
|
490
|
-
userFunctionConfig,
|
|
491
|
-
});
|
|
492
|
-
const expectedRoutes = [{ function: 'func-1', pattern: '^/f1(?:/(.*))/?$', excluded_patterns: [], path: '/f1/*' }];
|
|
493
|
-
const expectedFunctionConfig = {
|
|
494
|
-
'func-1': {
|
|
495
|
-
traffic_rules: {
|
|
496
|
-
action: {
|
|
497
|
-
type: 'rewrite',
|
|
498
|
-
config: {
|
|
499
|
-
to: '/new_path',
|
|
500
|
-
rate_limit_config: {
|
|
501
|
-
window_limit: 100,
|
|
502
|
-
window_size: 60,
|
|
503
|
-
algorithm: 'sliding_window',
|
|
504
|
-
},
|
|
505
|
-
aggregate: {
|
|
506
|
-
keys: [{ type: 'domain' }, { type: 'ip' }],
|
|
507
|
-
},
|
|
508
|
-
},
|
|
509
|
-
},
|
|
510
|
-
},
|
|
511
|
-
},
|
|
512
|
-
};
|
|
513
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
514
|
-
expect(manifest.function_config).toEqual(expectedFunctionConfig);
|
|
515
|
-
});
|
|
516
|
-
describe('Header matching', () => {
|
|
517
|
-
test('Throws a bundling error if the type is incorrect', () => {
|
|
518
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
519
|
-
expect(() => generateManifest({
|
|
520
|
-
bundles: [],
|
|
521
|
-
// @ts-expect-error Incorrect type
|
|
522
|
-
declarations: [{ function: 'func-1', path: '/f1/*', header: 'foo' }],
|
|
523
|
-
functions,
|
|
524
|
-
})).toThrowError(BundleError);
|
|
525
|
-
expect(() => generateManifest({
|
|
526
|
-
bundles: [],
|
|
527
|
-
declarations: [
|
|
528
|
-
{
|
|
529
|
-
function: 'func-1',
|
|
530
|
-
path: '/f1/*',
|
|
531
|
-
header: {
|
|
532
|
-
'x-correct': true,
|
|
533
|
-
// @ts-expect-error Incorrect type
|
|
534
|
-
'x-not-correct': {
|
|
535
|
-
problem: true,
|
|
536
|
-
},
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
],
|
|
540
|
-
functions,
|
|
541
|
-
})).toThrowError(BundleError);
|
|
542
|
-
});
|
|
543
|
-
test('Writes header matching rules to the manifest', () => {
|
|
544
|
-
const functions = [{ name: 'func-1', path: '/path/to/func-1.ts' }];
|
|
545
|
-
const declarations = [
|
|
546
|
-
{
|
|
547
|
-
function: 'func-1',
|
|
548
|
-
path: '/f1/*',
|
|
549
|
-
header: {
|
|
550
|
-
'x-present': true,
|
|
551
|
-
'x-also-present': true,
|
|
552
|
-
'x-absent': false,
|
|
553
|
-
'x-match-prefix': '^prefix',
|
|
554
|
-
'x-match-exact': '^exact$',
|
|
555
|
-
'x-match-suffix': 'suffix$',
|
|
556
|
-
},
|
|
557
|
-
},
|
|
558
|
-
];
|
|
559
|
-
const { manifest } = generateManifest({
|
|
560
|
-
bundles: [],
|
|
561
|
-
declarations,
|
|
562
|
-
functions,
|
|
563
|
-
});
|
|
564
|
-
const expectedRoutes = [
|
|
565
|
-
{
|
|
566
|
-
function: 'func-1',
|
|
567
|
-
pattern: '^/f1(?:/(.*))/?$',
|
|
568
|
-
excluded_patterns: [],
|
|
569
|
-
path: '/f1/*',
|
|
570
|
-
headers: {
|
|
571
|
-
'x-absent': {
|
|
572
|
-
matcher: 'missing',
|
|
573
|
-
},
|
|
574
|
-
'x-also-present': {
|
|
575
|
-
matcher: 'exists',
|
|
576
|
-
},
|
|
577
|
-
'x-match-exact': {
|
|
578
|
-
pattern: '^exact$',
|
|
579
|
-
matcher: 'regex',
|
|
580
|
-
},
|
|
581
|
-
'x-match-prefix': {
|
|
582
|
-
pattern: '^prefix',
|
|
583
|
-
matcher: 'regex',
|
|
584
|
-
},
|
|
585
|
-
'x-match-suffix': {
|
|
586
|
-
pattern: 'suffix$',
|
|
587
|
-
matcher: 'regex',
|
|
588
|
-
},
|
|
589
|
-
'x-present': {
|
|
590
|
-
matcher: 'exists',
|
|
591
|
-
},
|
|
592
|
-
},
|
|
593
|
-
},
|
|
594
|
-
];
|
|
595
|
-
expect(manifest.routes).toEqual(expectedRoutes);
|
|
596
|
-
});
|
|
597
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import semver from 'semver';
|
|
2
|
-
import { test, expect } from 'vitest';
|
|
3
|
-
import { getPackageVersion } from './package_json.js';
|
|
4
|
-
test('`getPackageVersion` returns the package version`', () => {
|
|
5
|
-
const version = getPackageVersion();
|
|
6
|
-
expect(semver.valid(version)).not.toBeNull();
|
|
7
|
-
});
|