vite-plugin-vercel 0.3.6 → 2.0.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/README.md +49 -14
- package/dist/index.cjs +158 -32
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +163 -33
- package/package.json +15 -12
package/README.md
CHANGED
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
# vite-plugin-vercel
|
|
2
2
|
|
|
3
|
-
Vercel adapter for [
|
|
3
|
+
Vercel adapter for [Vite](https://vitejs.dev/).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[Vercel API v3](https://vercel.com/docs/build-output-api/v3).
|
|
5
|
+
Bundle your Vite application as supported by [Vercel Output API (v3)](https://vercel.com/docs/build-output-api/v3).
|
|
7
6
|
|
|
8
7
|
## Features
|
|
9
8
|
|
|
10
|
-
- [x] [SSG/Static files
|
|
9
|
+
- [x] [SSG/Static files](https://vercel.com/docs/build-output-api/v3/primitives#static-files)
|
|
11
10
|
- see [`prerender` config](/packages/vercel/src/types.ts#L37)
|
|
12
|
-
- [x] [SSR/Serverless functions
|
|
11
|
+
- [x] [SSR/Serverless functions](https://vercel.com/docs/build-output-api/v3/primitives#serverless-functions)
|
|
13
12
|
- `.[jt]s` files under the `<root>/api` folder of your project are automatically bundled as Serverless functions under `.vercel/output/functions/api/*.func`
|
|
14
13
|
- see [`additionalEndpoints` config](/packages/vercel/src/types.ts#L62)
|
|
15
|
-
- [x] [ISR/Prerender functions
|
|
14
|
+
- [x] [ISR/Prerender functions](https://vercel.com/docs/build-output-api/v3/primitives#prerender-functions)
|
|
16
15
|
- see [`isr` config](/packages/vercel/src/types.ts#L89). Also see implementation of [vike](/packages/vike-integration/vike.ts) for example
|
|
17
|
-
- [x] [Edge functions
|
|
18
|
-
- [ ] [
|
|
19
|
-
- [ ] [
|
|
20
|
-
- [
|
|
21
|
-
|
|
16
|
+
- [x] [Edge functions](https://vercel.com/docs/build-output-api/v3/primitives#edge-functions)
|
|
17
|
+
- [ ] [Edge middleware](https://vercel.com/docs/functions/edge-middleware/middleware-api)
|
|
18
|
+
- [ ] [Images optimization](https://vercel.com/docs/build-output-api/v3/configuration#images)
|
|
19
|
+
- [ ] [Preview mode](https://vercel.com/docs/build-output-api/v3/features#preview-mode)
|
|
20
|
+
- [x] [Advanced config](/packages/vercel/src/types.ts#L19)
|
|
22
21
|
|
|
23
22
|
## Simple usage
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Install this package as a dev dependency and add it to your Vite config:
|
|
26
25
|
|
|
27
26
|
```ts
|
|
28
27
|
// vite.config.ts
|
|
@@ -32,11 +31,47 @@ import vercel from 'vite-plugin-vercel';
|
|
|
32
31
|
export default defineConfig({
|
|
33
32
|
plugins: [vercel()],
|
|
34
33
|
vercel: {
|
|
35
|
-
// optional configuration options, see below for details
|
|
34
|
+
// optional configuration options, see "Advanced usage" below for details
|
|
36
35
|
},
|
|
37
36
|
});
|
|
38
37
|
```
|
|
39
38
|
|
|
39
|
+
> [!NOTE]
|
|
40
|
+
> Files under `/api` or `/_api` directory will automatically be added under `/api/*` route
|
|
41
|
+
> Prefer using `/_api` directory, as `@vercel/build` is currently force building `/api` files,
|
|
42
|
+
> with no way to disable it, thus avoiding double compilation and unexpected behaviour.
|
|
43
|
+
|
|
44
|
+
### Configure endpoints
|
|
45
|
+
|
|
46
|
+
Endpoints under `/api`, `/_api` or added through `additionalEndpoints` can be configured
|
|
47
|
+
by exporting values from the endpoint file:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// file: _api/endpoint.ts
|
|
51
|
+
|
|
52
|
+
// Should run on edge runtime
|
|
53
|
+
export const edge = true;
|
|
54
|
+
|
|
55
|
+
// Always add those header to this endpoint
|
|
56
|
+
export const headers = {
|
|
57
|
+
'Some-Header': 'some value',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Enable Incremental Static Regeneration for this endpoint
|
|
61
|
+
export const isr = {
|
|
62
|
+
expiration: 30,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export default async function handler() {
|
|
66
|
+
return new Response('Edge Function: OK', {
|
|
67
|
+
status: 200,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
> [!NOTE]
|
|
73
|
+
> Please create an issue if you need other per-endpoints configurations
|
|
74
|
+
|
|
40
75
|
## Usage with vike
|
|
41
76
|
|
|
42
77
|
[vike](https://vike.dev/) is supported through [@vite-plugin-vercel/vike](/packages/vike-integration/README.md) plugin.
|
|
@@ -126,7 +161,7 @@ export default defineConfig({
|
|
|
126
161
|
*/
|
|
127
162
|
trailingSlash: true,
|
|
128
163
|
/**
|
|
129
|
-
* By default, all `api/*` endpoints are compiled under `.vercel/output/functions/api/*.func`.
|
|
164
|
+
* By default, all `api/*` and `_api/*` endpoints are compiled under `.vercel/output/functions/api/*.func`.
|
|
130
165
|
* If others serverless functions need to be compiled under `.vercel/output/functions`, they should be added here.
|
|
131
166
|
* For instance, a framework can leverage this to have a generic ssr endpoint
|
|
132
167
|
* without requiring the user to write any code.
|
package/dist/index.cjs
CHANGED
|
@@ -158,7 +158,7 @@ function reorderEnforce(arr) {
|
|
|
158
158
|
...arr.filter((r) => r.enforce === "post")
|
|
159
159
|
];
|
|
160
160
|
}
|
|
161
|
-
function getConfig(resolvedConfig, rewrites, overrides) {
|
|
161
|
+
function getConfig(resolvedConfig, rewrites, overrides, headers) {
|
|
162
162
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
163
163
|
const _rewrites = [
|
|
164
164
|
// User provided config always comes first
|
|
@@ -169,23 +169,49 @@ function getConfig(resolvedConfig, rewrites, overrides) {
|
|
|
169
169
|
cleanUrls: ((_b = resolvedConfig.vercel) == null ? void 0 : _b.cleanUrls) ?? true,
|
|
170
170
|
trailingSlash: (_c = resolvedConfig.vercel) == null ? void 0 : _c.trailingSlash,
|
|
171
171
|
rewrites: reorderEnforce(_rewrites),
|
|
172
|
-
redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0
|
|
172
|
+
redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0,
|
|
173
|
+
headers
|
|
173
174
|
});
|
|
174
175
|
if (error) {
|
|
175
176
|
throw error;
|
|
176
177
|
}
|
|
177
|
-
if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0
|
|
178
|
+
if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0 && !resolvedConfig.vercel.config.routes.every(
|
|
179
|
+
(r) => "continue" in r && r.continue
|
|
180
|
+
)) {
|
|
178
181
|
console.warn(
|
|
179
|
-
"
|
|
182
|
+
'Did you forget to add `"continue": true` to your routes? See https://vercel.com/docs/build-output-api/v3/configuration#source-route\nIf not, it is discouraged to use `vercel.config.routes` to override routes. Prefer using `vercel.rewrites` and `vercel.redirects`.'
|
|
180
183
|
);
|
|
181
184
|
}
|
|
185
|
+
let userRoutes = [];
|
|
186
|
+
let buildRoutes = [];
|
|
187
|
+
if ((_i = (_h = resolvedConfig.vercel) == null ? void 0 : _h.config) == null ? void 0 : _i.routes) {
|
|
188
|
+
const norm = (0, import_routing_utils.normalizeRoutes)(resolvedConfig.vercel.config.routes);
|
|
189
|
+
if (norm.error) {
|
|
190
|
+
throw norm.error;
|
|
191
|
+
}
|
|
192
|
+
userRoutes = norm.routes ?? [];
|
|
193
|
+
}
|
|
194
|
+
if (routes) {
|
|
195
|
+
const norm = (0, import_routing_utils.normalizeRoutes)(routes);
|
|
196
|
+
if (norm.error) {
|
|
197
|
+
throw norm.error;
|
|
198
|
+
}
|
|
199
|
+
buildRoutes = norm.routes ?? [];
|
|
200
|
+
}
|
|
201
|
+
const cleanRoutes = (0, import_routing_utils.mergeRoutes)({
|
|
202
|
+
userRoutes,
|
|
203
|
+
builds: [
|
|
204
|
+
{
|
|
205
|
+
use: "@vercel/node",
|
|
206
|
+
entrypoint: "index.js",
|
|
207
|
+
routes: buildRoutes
|
|
208
|
+
}
|
|
209
|
+
]
|
|
210
|
+
});
|
|
182
211
|
return vercelOutputConfigSchema.parse({
|
|
183
212
|
version: 3,
|
|
184
|
-
...(
|
|
185
|
-
routes:
|
|
186
|
-
...routes ?? [],
|
|
187
|
-
...((_j = (_i = resolvedConfig.vercel) == null ? void 0 : _i.config) == null ? void 0 : _j.routes) ?? []
|
|
188
|
-
],
|
|
213
|
+
...(_j = resolvedConfig.vercel) == null ? void 0 : _j.config,
|
|
214
|
+
routes: cleanRoutes,
|
|
189
215
|
overrides: {
|
|
190
216
|
...(_l = (_k = resolvedConfig.vercel) == null ? void 0 : _k.config) == null ? void 0 : _l.overrides,
|
|
191
217
|
...overrides
|
|
@@ -195,11 +221,11 @@ function getConfig(resolvedConfig, rewrites, overrides) {
|
|
|
195
221
|
function getConfigDestination(resolvedConfig) {
|
|
196
222
|
return import_path2.default.join(getOutput(resolvedConfig), "config.json");
|
|
197
223
|
}
|
|
198
|
-
async function writeConfig(resolvedConfig, rewrites, overrides) {
|
|
224
|
+
async function writeConfig(resolvedConfig, rewrites, overrides, headers) {
|
|
199
225
|
await import_promises.default.writeFile(
|
|
200
226
|
getConfigDestination(resolvedConfig),
|
|
201
227
|
JSON.stringify(
|
|
202
|
-
getConfig(resolvedConfig, rewrites, overrides),
|
|
228
|
+
getConfig(resolvedConfig, rewrites, overrides, headers),
|
|
203
229
|
void 0,
|
|
204
230
|
2
|
|
205
231
|
),
|
|
@@ -252,6 +278,21 @@ var vercelOutputVcConfigSchema = import_zod2.z.union([
|
|
|
252
278
|
|
|
253
279
|
// src/build.ts
|
|
254
280
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
281
|
+
var import_eval = __toESM(require("eval"), 1);
|
|
282
|
+
|
|
283
|
+
// src/schemas/exports.ts
|
|
284
|
+
var import_zod3 = require("zod");
|
|
285
|
+
var vercelEndpointExports = import_zod3.z.object({
|
|
286
|
+
edge: import_zod3.z.boolean().optional(),
|
|
287
|
+
headers: import_zod3.z.record(import_zod3.z.string()).optional(),
|
|
288
|
+
isr: import_zod3.z.object({
|
|
289
|
+
expiration: import_zod3.z.number().or(import_zod3.z.literal(false))
|
|
290
|
+
}).optional()
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// src/build.ts
|
|
294
|
+
var import_magicast = require("magicast");
|
|
295
|
+
var import_build_utils = require("@vercel/build-utils");
|
|
255
296
|
function getAdditionalEndpoints(resolvedConfig) {
|
|
256
297
|
var _a;
|
|
257
298
|
return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => ({
|
|
@@ -364,7 +405,7 @@ async function buildFn(resolvedConfig, entry, buildOptions) {
|
|
|
364
405
|
}
|
|
365
406
|
const ctx = { found: false, index: "" };
|
|
366
407
|
options.plugins.push(vercelOgPlugin(ctx));
|
|
367
|
-
await (0, import_esbuild.build)(options);
|
|
408
|
+
const output = await (0, import_esbuild.build)(options);
|
|
368
409
|
if (ctx.found && ctx.index) {
|
|
369
410
|
const dir = (0, import_path3.dirname)(ctx.index);
|
|
370
411
|
const externalFiles = await (0, import_fast_glob.default)(`${dir}/*.{ttf,wasm}`);
|
|
@@ -380,6 +421,7 @@ async function buildFn(resolvedConfig, entry, buildOptions) {
|
|
|
380
421
|
}
|
|
381
422
|
}
|
|
382
423
|
await writeVcConfig(resolvedConfig, entry.destination, Boolean(entry.edge));
|
|
424
|
+
return output;
|
|
383
425
|
}
|
|
384
426
|
async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
385
427
|
var _a;
|
|
@@ -388,6 +430,7 @@ async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
|
388
430
|
destination,
|
|
389
431
|
".vc-config.json"
|
|
390
432
|
);
|
|
433
|
+
const nodeVersion = await (0, import_build_utils.getNodeVersion)(getOutput(resolvedConfig));
|
|
391
434
|
await import_promises2.default.writeFile(
|
|
392
435
|
vcConfig,
|
|
393
436
|
JSON.stringify(
|
|
@@ -396,7 +439,7 @@ async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
|
396
439
|
runtime: "edge",
|
|
397
440
|
entrypoint: "index.js"
|
|
398
441
|
} : {
|
|
399
|
-
runtime:
|
|
442
|
+
runtime: nodeVersion.runtime,
|
|
400
443
|
handler: "index.js",
|
|
401
444
|
maxDuration: (_a = resolvedConfig.vercel) == null ? void 0 : _a.defaultMaxDuration,
|
|
402
445
|
launcherType: "Nodejs",
|
|
@@ -415,28 +458,102 @@ function getSourceAndDestination(destination) {
|
|
|
415
458
|
}
|
|
416
459
|
return import_path3.default.posix.resolve("/", destination, ":match*");
|
|
417
460
|
}
|
|
461
|
+
async function removeDefaultExport(filepath) {
|
|
462
|
+
const mod = await (0, import_magicast.loadFile)(filepath);
|
|
463
|
+
try {
|
|
464
|
+
delete mod.exports.default;
|
|
465
|
+
} catch (_) {
|
|
466
|
+
}
|
|
467
|
+
return (0, import_magicast.generateCode)(mod).code;
|
|
468
|
+
}
|
|
469
|
+
async function extractExports(filepath) {
|
|
470
|
+
var _a;
|
|
471
|
+
const contents = await removeDefaultExport(filepath);
|
|
472
|
+
const buildOptions = {
|
|
473
|
+
...standardBuildOptions,
|
|
474
|
+
minify: false,
|
|
475
|
+
write: false,
|
|
476
|
+
legalComments: "none"
|
|
477
|
+
};
|
|
478
|
+
buildOptions.stdin = {
|
|
479
|
+
sourcefile: filepath,
|
|
480
|
+
contents,
|
|
481
|
+
loader: filepath.endsWith(".ts") ? "ts" : filepath.endsWith(".tsx") ? "tsx" : filepath.endsWith(".js") ? "js" : filepath.endsWith(".jsx") ? "jsx" : "default",
|
|
482
|
+
resolveDir: (0, import_path3.dirname)(filepath)
|
|
483
|
+
};
|
|
484
|
+
try {
|
|
485
|
+
const output = await (0, import_esbuild.build)(buildOptions);
|
|
486
|
+
const bundle = new TextDecoder().decode((_a = output.outputFiles[0]) == null ? void 0 : _a.contents);
|
|
487
|
+
return vercelEndpointExports.parse((0, import_eval.default)(bundle, filepath, {}, true));
|
|
488
|
+
} catch (e) {
|
|
489
|
+
console.warn(`Warning: failed to read exports of '${filepath}'`, e);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
418
492
|
async function buildEndpoints(resolvedConfig) {
|
|
419
493
|
const entries = getEntries(resolvedConfig);
|
|
420
494
|
for (const entry of entries) {
|
|
495
|
+
if (typeof entry.source === "string") {
|
|
496
|
+
const exports = await extractExports(entry.source);
|
|
497
|
+
if (exports) {
|
|
498
|
+
if (entry.headers || exports.headers) {
|
|
499
|
+
entry.headers = {
|
|
500
|
+
...exports.headers,
|
|
501
|
+
...entry.headers
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
if (entry.edge !== void 0 && exports.edge !== void 0) {
|
|
505
|
+
throw new Error(
|
|
506
|
+
`edge configuration should be defined either in the endpoint itself or through Vite config, not both ('${entry.source}')`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
if (exports.edge !== void 0) {
|
|
510
|
+
entry.edge = exports.edge;
|
|
511
|
+
}
|
|
512
|
+
if (entry.isr !== void 0 && exports.isr !== void 0) {
|
|
513
|
+
throw new Error(
|
|
514
|
+
`isr configuration should be defined either in the endpoint itself or through Vite config, not both ('${entry.source}')`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
if (exports.isr) {
|
|
518
|
+
entry.isr = exports.isr;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
421
522
|
await buildFn(resolvedConfig, entry);
|
|
422
523
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
524
|
+
const isrEntries = entries.filter((e) => e.isr).map(
|
|
525
|
+
(e) => [
|
|
526
|
+
e.destination.replace(/\.func$/, ""),
|
|
527
|
+
{ expiration: e.isr.expiration }
|
|
528
|
+
]
|
|
529
|
+
);
|
|
530
|
+
return {
|
|
531
|
+
rewrites: entries.filter((e) => e.addRoute !== false).map((e) => e.destination.replace(/\.func$/, "")).map((destination) => ({
|
|
532
|
+
source: getSourceAndDestination(destination),
|
|
533
|
+
destination: getSourceAndDestination(destination)
|
|
534
|
+
})),
|
|
535
|
+
isr: Object.fromEntries(isrEntries),
|
|
536
|
+
headers: entries.filter((e) => e.headers).map((e) => ({
|
|
537
|
+
source: "/" + e.destination.replace(/\.func$/, ""),
|
|
538
|
+
headers: Object.entries(e.headers).map(([key, value]) => ({
|
|
539
|
+
key,
|
|
540
|
+
value
|
|
541
|
+
}))
|
|
542
|
+
}))
|
|
543
|
+
};
|
|
427
544
|
}
|
|
428
545
|
|
|
429
546
|
// src/prerender.ts
|
|
430
547
|
var import_path4 = __toESM(require("path"), 1);
|
|
431
548
|
|
|
432
549
|
// src/schemas/config/prerender-config.ts
|
|
433
|
-
var
|
|
434
|
-
var vercelOutputPrerenderConfigSchema =
|
|
435
|
-
expiration:
|
|
436
|
-
group:
|
|
437
|
-
bypassToken:
|
|
438
|
-
fallback:
|
|
439
|
-
allowQuery:
|
|
550
|
+
var import_zod4 = require("zod");
|
|
551
|
+
var vercelOutputPrerenderConfigSchema = import_zod4.z.object({
|
|
552
|
+
expiration: import_zod4.z.union([import_zod4.z.number().int().positive(), import_zod4.z.literal(false)]),
|
|
553
|
+
group: import_zod4.z.number().int().optional(),
|
|
554
|
+
bypassToken: import_zod4.z.string().optional(),
|
|
555
|
+
fallback: import_zod4.z.string().optional(),
|
|
556
|
+
allowQuery: import_zod4.z.array(import_zod4.z.string()).optional()
|
|
440
557
|
}).strict();
|
|
441
558
|
|
|
442
559
|
// src/prerender.ts
|
|
@@ -490,8 +607,12 @@ function getPrerenderSymlinkInfo(resolvedConfig, destination, target) {
|
|
|
490
607
|
)
|
|
491
608
|
};
|
|
492
609
|
}
|
|
493
|
-
async function buildPrerenderConfigs(resolvedConfig) {
|
|
494
|
-
const isr =
|
|
610
|
+
async function buildPrerenderConfigs(resolvedConfig, extractedIsr) {
|
|
611
|
+
const isr = Object.assign(
|
|
612
|
+
{},
|
|
613
|
+
extractedIsr,
|
|
614
|
+
await getIsrConfig(resolvedConfig)
|
|
615
|
+
);
|
|
495
616
|
const entries = Object.entries(isr);
|
|
496
617
|
const rewrites = [];
|
|
497
618
|
for (const [destination, { symlink, route, ...isr2 }] of entries) {
|
|
@@ -556,12 +677,17 @@ function vercelPlugin() {
|
|
|
556
677
|
}
|
|
557
678
|
const overrides = await execPrerender(resolvedConfig);
|
|
558
679
|
const userOverrides = await computeStaticHtmlOverrides(resolvedConfig);
|
|
559
|
-
const rewrites = await buildEndpoints(resolvedConfig);
|
|
560
|
-
rewrites.push(...await buildPrerenderConfigs(resolvedConfig));
|
|
561
|
-
await writeConfig(
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
680
|
+
const { rewrites, isr, headers } = await buildEndpoints(resolvedConfig);
|
|
681
|
+
rewrites.push(...await buildPrerenderConfigs(resolvedConfig, isr));
|
|
682
|
+
await writeConfig(
|
|
683
|
+
resolvedConfig,
|
|
684
|
+
rewrites,
|
|
685
|
+
{
|
|
686
|
+
...userOverrides,
|
|
687
|
+
...overrides
|
|
688
|
+
},
|
|
689
|
+
headers
|
|
690
|
+
);
|
|
565
691
|
}
|
|
566
692
|
};
|
|
567
693
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -639,6 +639,14 @@ interface ViteVercelApiEntry {
|
|
|
639
639
|
* Set to `true` to mark this function as an Edge Function
|
|
640
640
|
*/
|
|
641
641
|
edge?: boolean;
|
|
642
|
+
/**
|
|
643
|
+
* Additional headers
|
|
644
|
+
*/
|
|
645
|
+
headers?: Record<string, string>;
|
|
646
|
+
/**
|
|
647
|
+
* ISR config
|
|
648
|
+
*/
|
|
649
|
+
isr?: VercelOutputIsr;
|
|
642
650
|
}
|
|
643
651
|
|
|
644
652
|
declare function allPlugins(options?: {
|
package/dist/index.d.ts
CHANGED
|
@@ -639,6 +639,14 @@ interface ViteVercelApiEntry {
|
|
|
639
639
|
* Set to `true` to mark this function as an Edge Function
|
|
640
640
|
*/
|
|
641
641
|
edge?: boolean;
|
|
642
|
+
/**
|
|
643
|
+
* Additional headers
|
|
644
|
+
*/
|
|
645
|
+
headers?: Record<string, string>;
|
|
646
|
+
/**
|
|
647
|
+
* ISR config
|
|
648
|
+
*/
|
|
649
|
+
isr?: VercelOutputIsr;
|
|
642
650
|
}
|
|
643
651
|
|
|
644
652
|
declare function allPlugins(options?: {
|
package/dist/index.js
CHANGED
|
@@ -116,7 +116,11 @@ var vercelOutputConfigSchema = z.object({
|
|
|
116
116
|
|
|
117
117
|
// src/config.ts
|
|
118
118
|
import fs from "fs/promises";
|
|
119
|
-
import {
|
|
119
|
+
import {
|
|
120
|
+
getTransformedRoutes,
|
|
121
|
+
mergeRoutes,
|
|
122
|
+
normalizeRoutes
|
|
123
|
+
} from "@vercel/routing-utils";
|
|
120
124
|
function reorderEnforce(arr) {
|
|
121
125
|
return [
|
|
122
126
|
...arr.filter((r) => r.enforce === "pre"),
|
|
@@ -124,7 +128,7 @@ function reorderEnforce(arr) {
|
|
|
124
128
|
...arr.filter((r) => r.enforce === "post")
|
|
125
129
|
];
|
|
126
130
|
}
|
|
127
|
-
function getConfig(resolvedConfig, rewrites, overrides) {
|
|
131
|
+
function getConfig(resolvedConfig, rewrites, overrides, headers) {
|
|
128
132
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
129
133
|
const _rewrites = [
|
|
130
134
|
// User provided config always comes first
|
|
@@ -135,23 +139,49 @@ function getConfig(resolvedConfig, rewrites, overrides) {
|
|
|
135
139
|
cleanUrls: ((_b = resolvedConfig.vercel) == null ? void 0 : _b.cleanUrls) ?? true,
|
|
136
140
|
trailingSlash: (_c = resolvedConfig.vercel) == null ? void 0 : _c.trailingSlash,
|
|
137
141
|
rewrites: reorderEnforce(_rewrites),
|
|
138
|
-
redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0
|
|
142
|
+
redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0,
|
|
143
|
+
headers
|
|
139
144
|
});
|
|
140
145
|
if (error) {
|
|
141
146
|
throw error;
|
|
142
147
|
}
|
|
143
|
-
if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0
|
|
148
|
+
if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0 && !resolvedConfig.vercel.config.routes.every(
|
|
149
|
+
(r) => "continue" in r && r.continue
|
|
150
|
+
)) {
|
|
144
151
|
console.warn(
|
|
145
|
-
"
|
|
152
|
+
'Did you forget to add `"continue": true` to your routes? See https://vercel.com/docs/build-output-api/v3/configuration#source-route\nIf not, it is discouraged to use `vercel.config.routes` to override routes. Prefer using `vercel.rewrites` and `vercel.redirects`.'
|
|
146
153
|
);
|
|
147
154
|
}
|
|
155
|
+
let userRoutes = [];
|
|
156
|
+
let buildRoutes = [];
|
|
157
|
+
if ((_i = (_h = resolvedConfig.vercel) == null ? void 0 : _h.config) == null ? void 0 : _i.routes) {
|
|
158
|
+
const norm = normalizeRoutes(resolvedConfig.vercel.config.routes);
|
|
159
|
+
if (norm.error) {
|
|
160
|
+
throw norm.error;
|
|
161
|
+
}
|
|
162
|
+
userRoutes = norm.routes ?? [];
|
|
163
|
+
}
|
|
164
|
+
if (routes) {
|
|
165
|
+
const norm = normalizeRoutes(routes);
|
|
166
|
+
if (norm.error) {
|
|
167
|
+
throw norm.error;
|
|
168
|
+
}
|
|
169
|
+
buildRoutes = norm.routes ?? [];
|
|
170
|
+
}
|
|
171
|
+
const cleanRoutes = mergeRoutes({
|
|
172
|
+
userRoutes,
|
|
173
|
+
builds: [
|
|
174
|
+
{
|
|
175
|
+
use: "@vercel/node",
|
|
176
|
+
entrypoint: "index.js",
|
|
177
|
+
routes: buildRoutes
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
});
|
|
148
181
|
return vercelOutputConfigSchema.parse({
|
|
149
182
|
version: 3,
|
|
150
|
-
...(
|
|
151
|
-
routes:
|
|
152
|
-
...routes ?? [],
|
|
153
|
-
...((_j = (_i = resolvedConfig.vercel) == null ? void 0 : _i.config) == null ? void 0 : _j.routes) ?? []
|
|
154
|
-
],
|
|
183
|
+
...(_j = resolvedConfig.vercel) == null ? void 0 : _j.config,
|
|
184
|
+
routes: cleanRoutes,
|
|
155
185
|
overrides: {
|
|
156
186
|
...(_l = (_k = resolvedConfig.vercel) == null ? void 0 : _k.config) == null ? void 0 : _l.overrides,
|
|
157
187
|
...overrides
|
|
@@ -161,11 +191,11 @@ function getConfig(resolvedConfig, rewrites, overrides) {
|
|
|
161
191
|
function getConfigDestination(resolvedConfig) {
|
|
162
192
|
return path2.join(getOutput(resolvedConfig), "config.json");
|
|
163
193
|
}
|
|
164
|
-
async function writeConfig(resolvedConfig, rewrites, overrides) {
|
|
194
|
+
async function writeConfig(resolvedConfig, rewrites, overrides, headers) {
|
|
165
195
|
await fs.writeFile(
|
|
166
196
|
getConfigDestination(resolvedConfig),
|
|
167
197
|
JSON.stringify(
|
|
168
|
-
getConfig(resolvedConfig, rewrites, overrides),
|
|
198
|
+
getConfig(resolvedConfig, rewrites, overrides, headers),
|
|
169
199
|
void 0,
|
|
170
200
|
2
|
|
171
201
|
),
|
|
@@ -218,6 +248,21 @@ var vercelOutputVcConfigSchema = z2.union([
|
|
|
218
248
|
|
|
219
249
|
// src/build.ts
|
|
220
250
|
import fs2, { copyFile } from "fs/promises";
|
|
251
|
+
import _eval from "eval";
|
|
252
|
+
|
|
253
|
+
// src/schemas/exports.ts
|
|
254
|
+
import { z as z3 } from "zod";
|
|
255
|
+
var vercelEndpointExports = z3.object({
|
|
256
|
+
edge: z3.boolean().optional(),
|
|
257
|
+
headers: z3.record(z3.string()).optional(),
|
|
258
|
+
isr: z3.object({
|
|
259
|
+
expiration: z3.number().or(z3.literal(false))
|
|
260
|
+
}).optional()
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// src/build.ts
|
|
264
|
+
import { generateCode, loadFile } from "magicast";
|
|
265
|
+
import { getNodeVersion } from "@vercel/build-utils";
|
|
221
266
|
function getAdditionalEndpoints(resolvedConfig) {
|
|
222
267
|
var _a;
|
|
223
268
|
return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => ({
|
|
@@ -330,7 +375,7 @@ async function buildFn(resolvedConfig, entry, buildOptions) {
|
|
|
330
375
|
}
|
|
331
376
|
const ctx = { found: false, index: "" };
|
|
332
377
|
options.plugins.push(vercelOgPlugin(ctx));
|
|
333
|
-
await build(options);
|
|
378
|
+
const output = await build(options);
|
|
334
379
|
if (ctx.found && ctx.index) {
|
|
335
380
|
const dir = dirname(ctx.index);
|
|
336
381
|
const externalFiles = await glob(`${dir}/*.{ttf,wasm}`);
|
|
@@ -346,6 +391,7 @@ async function buildFn(resolvedConfig, entry, buildOptions) {
|
|
|
346
391
|
}
|
|
347
392
|
}
|
|
348
393
|
await writeVcConfig(resolvedConfig, entry.destination, Boolean(entry.edge));
|
|
394
|
+
return output;
|
|
349
395
|
}
|
|
350
396
|
async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
351
397
|
var _a;
|
|
@@ -354,6 +400,7 @@ async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
|
354
400
|
destination,
|
|
355
401
|
".vc-config.json"
|
|
356
402
|
);
|
|
403
|
+
const nodeVersion = await getNodeVersion(getOutput(resolvedConfig));
|
|
357
404
|
await fs2.writeFile(
|
|
358
405
|
vcConfig,
|
|
359
406
|
JSON.stringify(
|
|
@@ -362,7 +409,7 @@ async function writeVcConfig(resolvedConfig, destination, edge) {
|
|
|
362
409
|
runtime: "edge",
|
|
363
410
|
entrypoint: "index.js"
|
|
364
411
|
} : {
|
|
365
|
-
runtime:
|
|
412
|
+
runtime: nodeVersion.runtime,
|
|
366
413
|
handler: "index.js",
|
|
367
414
|
maxDuration: (_a = resolvedConfig.vercel) == null ? void 0 : _a.defaultMaxDuration,
|
|
368
415
|
launcherType: "Nodejs",
|
|
@@ -381,28 +428,102 @@ function getSourceAndDestination(destination) {
|
|
|
381
428
|
}
|
|
382
429
|
return path3.posix.resolve("/", destination, ":match*");
|
|
383
430
|
}
|
|
431
|
+
async function removeDefaultExport(filepath) {
|
|
432
|
+
const mod = await loadFile(filepath);
|
|
433
|
+
try {
|
|
434
|
+
delete mod.exports.default;
|
|
435
|
+
} catch (_) {
|
|
436
|
+
}
|
|
437
|
+
return generateCode(mod).code;
|
|
438
|
+
}
|
|
439
|
+
async function extractExports(filepath) {
|
|
440
|
+
var _a;
|
|
441
|
+
const contents = await removeDefaultExport(filepath);
|
|
442
|
+
const buildOptions = {
|
|
443
|
+
...standardBuildOptions,
|
|
444
|
+
minify: false,
|
|
445
|
+
write: false,
|
|
446
|
+
legalComments: "none"
|
|
447
|
+
};
|
|
448
|
+
buildOptions.stdin = {
|
|
449
|
+
sourcefile: filepath,
|
|
450
|
+
contents,
|
|
451
|
+
loader: filepath.endsWith(".ts") ? "ts" : filepath.endsWith(".tsx") ? "tsx" : filepath.endsWith(".js") ? "js" : filepath.endsWith(".jsx") ? "jsx" : "default",
|
|
452
|
+
resolveDir: dirname(filepath)
|
|
453
|
+
};
|
|
454
|
+
try {
|
|
455
|
+
const output = await build(buildOptions);
|
|
456
|
+
const bundle = new TextDecoder().decode((_a = output.outputFiles[0]) == null ? void 0 : _a.contents);
|
|
457
|
+
return vercelEndpointExports.parse(_eval(bundle, filepath, {}, true));
|
|
458
|
+
} catch (e) {
|
|
459
|
+
console.warn(`Warning: failed to read exports of '${filepath}'`, e);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
384
462
|
async function buildEndpoints(resolvedConfig) {
|
|
385
463
|
const entries = getEntries(resolvedConfig);
|
|
386
464
|
for (const entry of entries) {
|
|
465
|
+
if (typeof entry.source === "string") {
|
|
466
|
+
const exports = await extractExports(entry.source);
|
|
467
|
+
if (exports) {
|
|
468
|
+
if (entry.headers || exports.headers) {
|
|
469
|
+
entry.headers = {
|
|
470
|
+
...exports.headers,
|
|
471
|
+
...entry.headers
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
if (entry.edge !== void 0 && exports.edge !== void 0) {
|
|
475
|
+
throw new Error(
|
|
476
|
+
`edge configuration should be defined either in the endpoint itself or through Vite config, not both ('${entry.source}')`
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
if (exports.edge !== void 0) {
|
|
480
|
+
entry.edge = exports.edge;
|
|
481
|
+
}
|
|
482
|
+
if (entry.isr !== void 0 && exports.isr !== void 0) {
|
|
483
|
+
throw new Error(
|
|
484
|
+
`isr configuration should be defined either in the endpoint itself or through Vite config, not both ('${entry.source}')`
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
if (exports.isr) {
|
|
488
|
+
entry.isr = exports.isr;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
387
492
|
await buildFn(resolvedConfig, entry);
|
|
388
493
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
494
|
+
const isrEntries = entries.filter((e) => e.isr).map(
|
|
495
|
+
(e) => [
|
|
496
|
+
e.destination.replace(/\.func$/, ""),
|
|
497
|
+
{ expiration: e.isr.expiration }
|
|
498
|
+
]
|
|
499
|
+
);
|
|
500
|
+
return {
|
|
501
|
+
rewrites: entries.filter((e) => e.addRoute !== false).map((e) => e.destination.replace(/\.func$/, "")).map((destination) => ({
|
|
502
|
+
source: getSourceAndDestination(destination),
|
|
503
|
+
destination: getSourceAndDestination(destination)
|
|
504
|
+
})),
|
|
505
|
+
isr: Object.fromEntries(isrEntries),
|
|
506
|
+
headers: entries.filter((e) => e.headers).map((e) => ({
|
|
507
|
+
source: "/" + e.destination.replace(/\.func$/, ""),
|
|
508
|
+
headers: Object.entries(e.headers).map(([key, value]) => ({
|
|
509
|
+
key,
|
|
510
|
+
value
|
|
511
|
+
}))
|
|
512
|
+
}))
|
|
513
|
+
};
|
|
393
514
|
}
|
|
394
515
|
|
|
395
516
|
// src/prerender.ts
|
|
396
517
|
import path4 from "path";
|
|
397
518
|
|
|
398
519
|
// src/schemas/config/prerender-config.ts
|
|
399
|
-
import { z as
|
|
400
|
-
var vercelOutputPrerenderConfigSchema =
|
|
401
|
-
expiration:
|
|
402
|
-
group:
|
|
403
|
-
bypassToken:
|
|
404
|
-
fallback:
|
|
405
|
-
allowQuery:
|
|
520
|
+
import { z as z4 } from "zod";
|
|
521
|
+
var vercelOutputPrerenderConfigSchema = z4.object({
|
|
522
|
+
expiration: z4.union([z4.number().int().positive(), z4.literal(false)]),
|
|
523
|
+
group: z4.number().int().optional(),
|
|
524
|
+
bypassToken: z4.string().optional(),
|
|
525
|
+
fallback: z4.string().optional(),
|
|
526
|
+
allowQuery: z4.array(z4.string()).optional()
|
|
406
527
|
}).strict();
|
|
407
528
|
|
|
408
529
|
// src/prerender.ts
|
|
@@ -456,8 +577,12 @@ function getPrerenderSymlinkInfo(resolvedConfig, destination, target) {
|
|
|
456
577
|
)
|
|
457
578
|
};
|
|
458
579
|
}
|
|
459
|
-
async function buildPrerenderConfigs(resolvedConfig) {
|
|
460
|
-
const isr =
|
|
580
|
+
async function buildPrerenderConfigs(resolvedConfig, extractedIsr) {
|
|
581
|
+
const isr = Object.assign(
|
|
582
|
+
{},
|
|
583
|
+
extractedIsr,
|
|
584
|
+
await getIsrConfig(resolvedConfig)
|
|
585
|
+
);
|
|
461
586
|
const entries = Object.entries(isr);
|
|
462
587
|
const rewrites = [];
|
|
463
588
|
for (const [destination, { symlink, route, ...isr2 }] of entries) {
|
|
@@ -522,12 +647,17 @@ function vercelPlugin() {
|
|
|
522
647
|
}
|
|
523
648
|
const overrides = await execPrerender(resolvedConfig);
|
|
524
649
|
const userOverrides = await computeStaticHtmlOverrides(resolvedConfig);
|
|
525
|
-
const rewrites = await buildEndpoints(resolvedConfig);
|
|
526
|
-
rewrites.push(...await buildPrerenderConfigs(resolvedConfig));
|
|
527
|
-
await writeConfig(
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
650
|
+
const { rewrites, isr, headers } = await buildEndpoints(resolvedConfig);
|
|
651
|
+
rewrites.push(...await buildPrerenderConfigs(resolvedConfig, isr));
|
|
652
|
+
await writeConfig(
|
|
653
|
+
resolvedConfig,
|
|
654
|
+
rewrites,
|
|
655
|
+
{
|
|
656
|
+
...userOverrides,
|
|
657
|
+
...overrides
|
|
658
|
+
},
|
|
659
|
+
headers
|
|
660
|
+
);
|
|
531
661
|
}
|
|
532
662
|
};
|
|
533
663
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-vercel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"repository": "https://github.com/magne4000/vite-plugin-vercel",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"vite": "^4.2.0",
|
|
24
23
|
"vike": "*",
|
|
25
|
-
"
|
|
24
|
+
"vite": "^4.2.0",
|
|
25
|
+
"@vite-plugin-vercel/vike": "2.0.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependenciesMeta": {
|
|
28
28
|
"@vite-plugin-vercel/vike": {
|
|
@@ -33,22 +33,25 @@
|
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@types/node": "^16.18.
|
|
37
|
-
"@typescript-eslint/eslint-plugin": "^6.
|
|
38
|
-
"@typescript-eslint/parser": "^6.
|
|
39
|
-
"eslint": "^8.
|
|
36
|
+
"@types/node": "^16.18.58",
|
|
37
|
+
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
|
38
|
+
"@typescript-eslint/parser": "^6.7.5",
|
|
39
|
+
"eslint": "^8.51.0",
|
|
40
40
|
"tsup": "^7.2.0",
|
|
41
41
|
"typescript": "^5.2.2",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"@vite-plugin-vercel/vike": "0.
|
|
42
|
+
"vike": "^0.4.143",
|
|
43
|
+
"vite": "^4.4.11",
|
|
44
|
+
"@vite-plugin-vercel/vike": "2.0.0"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@brillout/libassert": "^0.5.8",
|
|
48
|
+
"@vercel/build-utils": "^7.2.2",
|
|
48
49
|
"@vercel/routing-utils": "^3.0.0",
|
|
49
|
-
"esbuild": "^0.19.
|
|
50
|
+
"esbuild": "^0.19.4",
|
|
51
|
+
"eval": "^0.1.8",
|
|
50
52
|
"fast-glob": "^3.3.1",
|
|
51
|
-
"
|
|
53
|
+
"magicast": "^0.3.0",
|
|
54
|
+
"zod": "^3.22.4"
|
|
52
55
|
},
|
|
53
56
|
"scripts": {
|
|
54
57
|
"build": "tsup",
|