@netlify/edge-bundler 11.3.0 → 11.4.1
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/README.md +2 -49
- package/dist/node/bridge.d.ts +0 -2
- package/dist/node/config.d.ts +2 -0
- package/dist/node/config.test.js +62 -4
- package/dist/node/manifest.d.ts +19 -0
- package/dist/node/manifest.js +37 -4
- package/dist/node/manifest.test.js +80 -0
- package/dist/node/npm_dependencies.d.ts +0 -1
- package/dist/node/rate_limit.d.ts +25 -0
- package/dist/node/rate_limit.js +14 -0
- package/dist/node/server/server.d.ts +0 -6
- package/dist/node/utils/error.d.ts +0 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,51 +1,4 @@
|
|
|
1
|
-
[](https://github.com/netlify/edge-bundler/actions)
|
|
2
|
-
[](https://www.npmjs.com/package/@netlify/edge-bundler)
|
|
3
|
-
|
|
4
1
|
# Edge Bundler
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
## Usage
|
|
9
|
-
|
|
10
|
-
1. Install this module as a dependency in your project
|
|
11
|
-
|
|
12
|
-
```
|
|
13
|
-
npm install @netlify/edge-bundler --save
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
2. Import it and create a bundle from a directory of Edge Functions and a list of declarations.
|
|
17
|
-
|
|
18
|
-
```js
|
|
19
|
-
import { bundle } from '@netlify/edge-bundler'
|
|
20
|
-
|
|
21
|
-
// List of directories to search for Edge Functions.
|
|
22
|
-
const sourceDirectories = ['/repo/netlify/edge-functions', '/repo/.netlify/edge-functions']
|
|
23
|
-
|
|
24
|
-
// Directory where bundle should be placed.
|
|
25
|
-
const distDirectory = '/repo/.netlify/edge-functions-dist'
|
|
26
|
-
|
|
27
|
-
// List of Edge Functions declarations.
|
|
28
|
-
const declarations = [
|
|
29
|
-
{ function: 'user-1', path: '/blog/*' },
|
|
30
|
-
{ function: 'internal-2', path: '/' },
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
await bundle(sourceDirectories, distDirectory, declarations)
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Vendored modules
|
|
37
|
-
|
|
38
|
-
To avoid pulling in additional dependencies at runtime, this package vendors some Deno modules in the `deno/vendor`
|
|
39
|
-
directory.
|
|
40
|
-
|
|
41
|
-
You can recreate this directory by running `npm run vendor`.
|
|
42
|
-
|
|
43
|
-
> [!WARNING]
|
|
44
|
-
> At the time of writing, the underlying Deno CLI command doesn't correctly pull the WASM binary required by the ESZIP
|
|
45
|
-
> module. If you run the command to update the list of vendores modules, please ensure you're not deleting
|
|
46
|
-
> `eszip_wasm_bg.wasm`.
|
|
47
|
-
|
|
48
|
-
## Contributors
|
|
49
|
-
|
|
50
|
-
Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for instructions on how to set up and work on this repository. Thanks
|
|
51
|
-
for contributing!
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> This project was moved into the [Netlify Build monorepo](https://github.com/netlify/build/tree/main/packages/edge-bundler).
|
package/dist/node/bridge.d.ts
CHANGED
package/dist/node/config.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { DenoBridge } from './bridge.js';
|
|
|
2
2
|
import { EdgeFunction } from './edge_function.js';
|
|
3
3
|
import { ImportMap } from './import_map.js';
|
|
4
4
|
import { Logger } from './logger.js';
|
|
5
|
+
import { RateLimit } from './rate_limit.js';
|
|
5
6
|
export declare const enum Cache {
|
|
6
7
|
Off = "off",
|
|
7
8
|
Manual = "manual"
|
|
@@ -18,6 +19,7 @@ export interface FunctionConfig {
|
|
|
18
19
|
name?: string;
|
|
19
20
|
generator?: string;
|
|
20
21
|
method?: HTTPMethod | HTTPMethod[];
|
|
22
|
+
rateLimit?: RateLimit;
|
|
21
23
|
}
|
|
22
24
|
export declare const getFunctionConfig: ({ func, importMap, deno, log, }: {
|
|
23
25
|
func: EdgeFunction;
|
package/dist/node/config.test.js
CHANGED
|
@@ -9,6 +9,7 @@ import { DenoBridge } from './bridge.js';
|
|
|
9
9
|
import { bundle } from './bundler.js';
|
|
10
10
|
import { getFunctionConfig } from './config.js';
|
|
11
11
|
import { ImportMap } from './import_map.js';
|
|
12
|
+
import { RateLimitAction, RateLimitAggregator } from './rate_limit.js';
|
|
12
13
|
const importMapFile = {
|
|
13
14
|
baseURL: new URL('file:///some/path/import-map.json'),
|
|
14
15
|
imports: {
|
|
@@ -64,7 +65,7 @@ const functions = [
|
|
|
64
65
|
},
|
|
65
66
|
{
|
|
66
67
|
testName: 'config with wrong onError',
|
|
67
|
-
name: '
|
|
68
|
+
name: 'func6',
|
|
68
69
|
source: `
|
|
69
70
|
export default async () => new Response("Hello from function two")
|
|
70
71
|
export const config = { onError: "foo" }
|
|
@@ -74,7 +75,7 @@ const functions = [
|
|
|
74
75
|
{
|
|
75
76
|
testName: 'config with `path`',
|
|
76
77
|
expectedConfig: { path: '/home' },
|
|
77
|
-
name: '
|
|
78
|
+
name: 'func7',
|
|
78
79
|
source: `
|
|
79
80
|
export default async () => new Response("Hello from function three")
|
|
80
81
|
|
|
@@ -89,17 +90,74 @@ const functions = [
|
|
|
89
90
|
name: 'a displayName',
|
|
90
91
|
onError: 'bypass',
|
|
91
92
|
},
|
|
92
|
-
name: '
|
|
93
|
+
name: 'func8',
|
|
93
94
|
source: `
|
|
94
95
|
export default async () => new Response("Hello from function three")
|
|
95
96
|
|
|
96
|
-
export const config = {
|
|
97
|
+
export const config = {
|
|
98
|
+
path: "/home",
|
|
97
99
|
generator: '@netlify/fake-plugin@1.0.0',
|
|
98
100
|
name: 'a displayName',
|
|
99
101
|
onError: 'bypass',
|
|
100
102
|
}
|
|
101
103
|
`,
|
|
102
104
|
},
|
|
105
|
+
{
|
|
106
|
+
testName: 'config with ratelimit',
|
|
107
|
+
expectedConfig: {
|
|
108
|
+
path: '/ratelimit',
|
|
109
|
+
name: 'a limit rate',
|
|
110
|
+
rateLimit: {
|
|
111
|
+
windowSize: 10,
|
|
112
|
+
windowLimit: 100,
|
|
113
|
+
aggregateBy: [RateLimitAggregator.IP, RateLimitAggregator.Domain],
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
name: 'func9',
|
|
117
|
+
source: `
|
|
118
|
+
export default async () => new Response("Rate my limits")
|
|
119
|
+
|
|
120
|
+
export const config = {
|
|
121
|
+
path: "/ratelimit",
|
|
122
|
+
rateLimit: {
|
|
123
|
+
windowSize: 10,
|
|
124
|
+
windowLimit: 100,
|
|
125
|
+
aggregateBy: ["ip", "domain"],
|
|
126
|
+
},
|
|
127
|
+
name: 'a limit rate',
|
|
128
|
+
}
|
|
129
|
+
`,
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
testName: 'config with rewrite',
|
|
133
|
+
expectedConfig: {
|
|
134
|
+
path: '/rewrite',
|
|
135
|
+
name: 'a limit rewrite',
|
|
136
|
+
rateLimit: {
|
|
137
|
+
action: RateLimitAction.Rewrite,
|
|
138
|
+
to: '/rewritten',
|
|
139
|
+
windowSize: 20,
|
|
140
|
+
windowLimit: 200,
|
|
141
|
+
aggregateBy: [RateLimitAggregator.IP, RateLimitAggregator.Domain],
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
name: 'func9',
|
|
145
|
+
source: `
|
|
146
|
+
export default async () => new Response("Rate my limits")
|
|
147
|
+
|
|
148
|
+
export const config = {
|
|
149
|
+
path: "/rewrite",
|
|
150
|
+
rateLimit: {
|
|
151
|
+
action: "rewrite",
|
|
152
|
+
to: "/rewritten",
|
|
153
|
+
windowSize: 20,
|
|
154
|
+
windowLimit: 200,
|
|
155
|
+
aggregateBy: ["ip", "domain"],
|
|
156
|
+
},
|
|
157
|
+
name: 'a limit rewrite',
|
|
158
|
+
}
|
|
159
|
+
`,
|
|
160
|
+
},
|
|
103
161
|
];
|
|
104
162
|
describe('`getFunctionConfig` extracts configuration properties from function file', () => {
|
|
105
163
|
test.each(functions)('$testName', async (func) => {
|
package/dist/node/manifest.d.ts
CHANGED
|
@@ -11,11 +11,30 @@ interface Route {
|
|
|
11
11
|
path?: string;
|
|
12
12
|
methods?: string[];
|
|
13
13
|
}
|
|
14
|
+
interface TrafficRules {
|
|
15
|
+
action: {
|
|
16
|
+
type: string;
|
|
17
|
+
config: {
|
|
18
|
+
rate_limit_config: {
|
|
19
|
+
algorithm: string;
|
|
20
|
+
window_size: number;
|
|
21
|
+
window_limit: number;
|
|
22
|
+
};
|
|
23
|
+
aggregate: {
|
|
24
|
+
keys: {
|
|
25
|
+
type: string;
|
|
26
|
+
}[];
|
|
27
|
+
};
|
|
28
|
+
to?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
}
|
|
14
32
|
export interface EdgeFunctionConfig {
|
|
15
33
|
excluded_patterns: string[];
|
|
16
34
|
on_error?: string;
|
|
17
35
|
generator?: string;
|
|
18
36
|
name?: string;
|
|
37
|
+
traffic_rules?: TrafficRules;
|
|
19
38
|
}
|
|
20
39
|
interface Manifest {
|
|
21
40
|
bundler_version: string;
|
package/dist/node/manifest.js
CHANGED
|
@@ -3,6 +3,7 @@ import { join } from 'path';
|
|
|
3
3
|
import { wrapBundleError } from './bundle_error.js';
|
|
4
4
|
import { normalizePattern } from './declaration.js';
|
|
5
5
|
import { getPackageVersion } from './package_json.js';
|
|
6
|
+
import { RateLimitAction, RateLimitAlgorithm, RateLimitAggregator } from './rate_limit.js';
|
|
6
7
|
import { nonNullable } from './utils/non_nullable.js';
|
|
7
8
|
import { ExtendedURLPattern } from './utils/urlpattern.js';
|
|
8
9
|
const removeEmptyConfigValues = (functionConfig) => Object.entries(functionConfig).reduce((acc, [key, value]) => {
|
|
@@ -52,21 +53,30 @@ const generateManifest = ({ bundles = [], declarations = [], functions, userFunc
|
|
|
52
53
|
const manifestFunctionConfig = Object.fromEntries(functions.map(({ name }) => [name, { excluded_patterns: [] }]));
|
|
53
54
|
const routedFunctions = new Set();
|
|
54
55
|
const declarationsWithoutFunction = new Set();
|
|
55
|
-
for (const [name, { excludedPath, onError }] of Object.entries(userFunctionConfig)) {
|
|
56
|
+
for (const [name, { excludedPath, onError, rateLimit }] of Object.entries(userFunctionConfig)) {
|
|
56
57
|
// If the config block is for a function that is not defined, discard it.
|
|
57
58
|
if (manifestFunctionConfig[name] === undefined) {
|
|
58
59
|
continue;
|
|
59
60
|
}
|
|
60
61
|
addExcludedPatterns(name, manifestFunctionConfig, excludedPath);
|
|
61
|
-
manifestFunctionConfig[name] = {
|
|
62
|
+
manifestFunctionConfig[name] = {
|
|
63
|
+
...manifestFunctionConfig[name],
|
|
64
|
+
on_error: onError,
|
|
65
|
+
traffic_rules: getTrafficRulesConfig(rateLimit),
|
|
66
|
+
};
|
|
62
67
|
}
|
|
63
|
-
for (const [name, { excludedPath, path, onError, ...rest }] of Object.entries(internalFunctionConfig)) {
|
|
68
|
+
for (const [name, { excludedPath, path, onError, rateLimit, ...rest }] of Object.entries(internalFunctionConfig)) {
|
|
64
69
|
// If the config block is for a function that is not defined, discard it.
|
|
65
70
|
if (manifestFunctionConfig[name] === undefined) {
|
|
66
71
|
continue;
|
|
67
72
|
}
|
|
68
73
|
addExcludedPatterns(name, manifestFunctionConfig, excludedPath);
|
|
69
|
-
manifestFunctionConfig[name] = {
|
|
74
|
+
manifestFunctionConfig[name] = {
|
|
75
|
+
...manifestFunctionConfig[name],
|
|
76
|
+
on_error: onError,
|
|
77
|
+
traffic_rules: getTrafficRulesConfig(rateLimit),
|
|
78
|
+
...rest,
|
|
79
|
+
};
|
|
70
80
|
}
|
|
71
81
|
declarations.forEach((declaration) => {
|
|
72
82
|
const func = functions.find(({ name }) => declaration.function === name);
|
|
@@ -116,6 +126,29 @@ const generateManifest = ({ bundles = [], declarations = [], functions, userFunc
|
|
|
116
126
|
const unroutedFunctions = functions.filter(({ name }) => !routedFunctions.has(name)).map(({ name }) => name);
|
|
117
127
|
return { declarationsWithoutFunction: [...declarationsWithoutFunction], manifest, unroutedFunctions };
|
|
118
128
|
};
|
|
129
|
+
const getTrafficRulesConfig = (rl) => {
|
|
130
|
+
if (rl === undefined) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const rateLimitAgg = Array.isArray(rl.aggregateBy) ? rl.aggregateBy : [RateLimitAggregator.Domain];
|
|
134
|
+
const rewriteConfig = 'to' in rl && typeof rl.to === 'string' ? { to: rl.to } : undefined;
|
|
135
|
+
return {
|
|
136
|
+
action: {
|
|
137
|
+
type: rl.action || RateLimitAction.Limit,
|
|
138
|
+
config: {
|
|
139
|
+
...rewriteConfig,
|
|
140
|
+
rate_limit_config: {
|
|
141
|
+
window_limit: rl.windowLimit,
|
|
142
|
+
window_size: rl.windowSize,
|
|
143
|
+
algorithm: RateLimitAlgorithm.SlidingWindow,
|
|
144
|
+
},
|
|
145
|
+
aggregate: {
|
|
146
|
+
keys: rateLimitAgg.map((agg) => ({ type: agg })),
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
};
|
|
119
152
|
const pathToRegularExpression = (path) => {
|
|
120
153
|
if (!path) {
|
|
121
154
|
return null;
|
|
@@ -4,6 +4,7 @@ import { getRouteMatcher } from '../test/util.js';
|
|
|
4
4
|
import { BundleFormat } from './bundle.js';
|
|
5
5
|
import { BundleError } from './bundle_error.js';
|
|
6
6
|
import { generateManifest } from './manifest.js';
|
|
7
|
+
import { RateLimitAction, RateLimitAggregator } from './rate_limit.js';
|
|
7
8
|
test('Generates a manifest with different bundles', () => {
|
|
8
9
|
const bundle1 = {
|
|
9
10
|
extension: '.ext1',
|
|
@@ -433,3 +434,82 @@ test('Returns functions without a declaration and unrouted functions', () => {
|
|
|
433
434
|
expect(declarationsWithoutFunction).toEqual(['func-3']);
|
|
434
435
|
expect(unroutedFunctions).toEqual(['func-2', 'func-4']);
|
|
435
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
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare enum RateLimitAlgorithm {
|
|
2
|
+
SlidingWindow = "sliding_window"
|
|
3
|
+
}
|
|
4
|
+
export declare enum RateLimitAggregator {
|
|
5
|
+
Domain = "domain",
|
|
6
|
+
IP = "ip"
|
|
7
|
+
}
|
|
8
|
+
export declare enum RateLimitAction {
|
|
9
|
+
Limit = "rate_limit",
|
|
10
|
+
Rewrite = "rewrite"
|
|
11
|
+
}
|
|
12
|
+
interface SlidingWindow {
|
|
13
|
+
windowLimit: number;
|
|
14
|
+
windowSize: number;
|
|
15
|
+
}
|
|
16
|
+
export type RewriteActionConfig = SlidingWindow & {
|
|
17
|
+
to: string;
|
|
18
|
+
};
|
|
19
|
+
interface RateLimitConfig {
|
|
20
|
+
action?: RateLimitAction;
|
|
21
|
+
aggregateBy?: RateLimitAggregator | RateLimitAggregator[];
|
|
22
|
+
algorithm?: RateLimitAlgorithm;
|
|
23
|
+
}
|
|
24
|
+
export type RateLimit = RateLimitConfig & (SlidingWindow | RewriteActionConfig);
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export var RateLimitAlgorithm;
|
|
2
|
+
(function (RateLimitAlgorithm) {
|
|
3
|
+
RateLimitAlgorithm["SlidingWindow"] = "sliding_window";
|
|
4
|
+
})(RateLimitAlgorithm || (RateLimitAlgorithm = {}));
|
|
5
|
+
export var RateLimitAggregator;
|
|
6
|
+
(function (RateLimitAggregator) {
|
|
7
|
+
RateLimitAggregator["Domain"] = "domain";
|
|
8
|
+
RateLimitAggregator["IP"] = "ip";
|
|
9
|
+
})(RateLimitAggregator || (RateLimitAggregator = {}));
|
|
10
|
+
export var RateLimitAction;
|
|
11
|
+
(function (RateLimitAction) {
|
|
12
|
+
RateLimitAction["Limit"] = "rate_limit";
|
|
13
|
+
RateLimitAction["Rewrite"] = "rewrite";
|
|
14
|
+
})(RateLimitAction || (RateLimitAction = {}));
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
/// <reference types="node" />
|
|
4
|
-
/// <reference types="node" />
|
|
5
|
-
/// <reference types="node" />
|
|
6
|
-
/// <reference types="node" />
|
|
7
1
|
import type { WriteStream } from 'fs';
|
|
8
2
|
import { OnAfterDownloadHook, OnBeforeDownloadHook } from '../bridge.js';
|
|
9
3
|
import { FunctionConfig } from '../config.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/edge-bundler",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.1",
|
|
4
4
|
"description": "Intelligently prepare Netlify Edge Functions for deployment",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/node/index.js",
|
|
@@ -75,13 +75,13 @@
|
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
77
|
"@import-maps/resolve": "^1.0.1",
|
|
78
|
-
"@vercel/nft": "^0.
|
|
78
|
+
"@vercel/nft": "^0.29.0",
|
|
79
79
|
"ajv": "^8.11.2",
|
|
80
80
|
"ajv-errors": "^3.0.0",
|
|
81
81
|
"better-ajv-errors": "^1.2.0",
|
|
82
82
|
"common-path-prefix": "^3.0.0",
|
|
83
83
|
"env-paths": "^3.0.0",
|
|
84
|
-
"esbuild": "0.
|
|
84
|
+
"esbuild": "0.25.1",
|
|
85
85
|
"execa": "^6.0.0",
|
|
86
86
|
"find-up": "^6.3.0",
|
|
87
87
|
"get-package-name": "^2.2.0",
|