vite-plugin-vercel 8.0.1 → 9.0.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/dist/index.js CHANGED
@@ -1,211 +1,17 @@
1
1
  // src/index.ts
2
- import fs5 from "fs/promises";
3
-
4
- // src/utils.ts
5
- import { normalizePath } from "vite";
6
- import path from "path";
7
- function getRoot(config) {
8
- return normalizePath(config.root || process.cwd());
9
- }
10
- function getOutput(config, suffix) {
11
- return path.join(
12
- config.vercel?.outDir ? "" : getRoot(config),
13
- config.vercel?.outDir ?? ".vercel/output",
14
- suffix ?? ""
15
- );
16
- }
17
- function getPublic(config) {
18
- return path.join(getRoot(config), config.publicDir || "public");
19
- }
20
- function pathRelativeTo(filePath, config, rel) {
21
- const root = getRoot(config);
22
- return normalizePath(
23
- path.relative(normalizePath(path.join(root, rel)), filePath)
24
- );
25
- }
26
-
27
- // src/config.ts
28
- import path2 from "path";
29
-
30
- // src/schemas/config/config.ts
31
- import { z } from "zod";
32
- var HasOrMissing = z.array(
33
- z.union([
34
- z.object({
35
- type: z.literal("host"),
36
- value: z.string()
37
- }).strict(),
38
- z.object({
39
- type: z.literal("header"),
40
- key: z.string(),
41
- value: z.string().optional()
42
- }).strict(),
43
- z.object({
44
- type: z.literal("cookie"),
45
- key: z.string(),
46
- value: z.string().optional()
47
- }).strict(),
48
- z.object({
49
- type: z.literal("query"),
50
- key: z.string(),
51
- value: z.string().optional()
52
- }).strict()
53
- ])
54
- ).optional();
55
- var vercelOutputConfigSchema = z.object({
56
- version: z.literal(3),
57
- routes: z.array(
58
- z.union([
59
- z.object({
60
- src: z.string(),
61
- dest: z.string().optional(),
62
- headers: z.record(z.string()).optional(),
63
- methods: z.array(z.string()).optional(),
64
- status: z.number().int().positive().optional(),
65
- continue: z.boolean().optional(),
66
- check: z.boolean().optional(),
67
- missing: HasOrMissing,
68
- has: HasOrMissing,
69
- locale: z.object({
70
- redirect: z.record(z.string()).optional(),
71
- cookie: z.string().optional()
72
- }).strict().optional(),
73
- middlewarePath: z.string().optional()
74
- }).strict(),
75
- z.object({
76
- handle: z.union([
77
- z.literal("rewrite"),
78
- z.literal("filesystem"),
79
- z.literal("resource"),
80
- z.literal("miss"),
81
- z.literal("hit"),
82
- z.literal("error")
83
- ]),
84
- src: z.string().optional(),
85
- dest: z.string().optional(),
86
- status: z.number().optional()
87
- }).strict()
88
- ])
89
- ).optional(),
90
- images: z.object({
91
- sizes: z.tuple([
92
- z.number().int().positive(),
93
- z.number().int().positive()
94
- ]),
95
- domains: z.array(z.string()).nonempty().optional(),
96
- minimumCacheTTL: z.number().int().positive().optional(),
97
- formats: z.union([z.literal("image/avif"), z.literal("image/webp")]).array().nonempty().optional(),
98
- dangerouslyAllowSVG: z.boolean().optional(),
99
- contentSecurityPolicy: z.string().optional()
100
- }).strict().optional(),
101
- wildcard: z.array(
102
- z.object({
103
- domain: z.string(),
104
- value: z.string()
105
- }).strict()
106
- ).optional(),
107
- overrides: z.record(
108
- z.object({
109
- path: z.string().optional(),
110
- contentType: z.string().optional()
111
- }).strict()
112
- ).optional(),
113
- cache: z.array(z.string()).optional()
114
- }).strict();
115
-
116
- // src/config.ts
117
- import fs from "fs/promises";
118
- import {
119
- getTransformedRoutes,
120
- mergeRoutes,
121
- normalizeRoutes
122
- } from "@vercel/routing-utils";
123
- function reorderEnforce(arr) {
124
- return [
125
- ...arr.filter((r) => r.enforce === "pre"),
126
- ...arr.filter((r) => !r.enforce),
127
- ...arr.filter((r) => r.enforce === "post")
128
- ];
129
- }
130
- function getConfig(resolvedConfig, rewrites, overrides, headers) {
131
- const _rewrites = [
132
- // User provided config always comes first
133
- ...resolvedConfig.vercel?.rewrites ?? [],
134
- ...rewrites ?? []
135
- ];
136
- const { routes, error } = getTransformedRoutes({
137
- cleanUrls: resolvedConfig.vercel?.cleanUrls ?? true,
138
- trailingSlash: resolvedConfig.vercel?.trailingSlash,
139
- rewrites: reorderEnforce(_rewrites),
140
- redirects: resolvedConfig.vercel?.redirects ? reorderEnforce(resolvedConfig.vercel?.redirects) : void 0,
141
- headers
142
- });
143
- if (error) {
144
- throw error;
145
- }
146
- if (resolvedConfig.vercel?.config?.routes && resolvedConfig.vercel.config.routes.length > 0 && !resolvedConfig.vercel.config.routes.every(
147
- (r) => "continue" in r && r.continue
148
- )) {
149
- console.warn(
150
- '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`.'
151
- );
152
- }
153
- let userRoutes = [];
154
- let buildRoutes = [];
155
- if (resolvedConfig.vercel?.config?.routes) {
156
- const norm = normalizeRoutes(resolvedConfig.vercel.config.routes);
157
- if (norm.error) {
158
- throw norm.error;
159
- }
160
- userRoutes = norm.routes ?? [];
161
- }
162
- if (routes) {
163
- const norm = normalizeRoutes(routes);
164
- if (norm.error) {
165
- throw norm.error;
166
- }
167
- buildRoutes = norm.routes ?? [];
168
- }
169
- const cleanRoutes = mergeRoutes({
170
- userRoutes,
171
- builds: [
172
- {
173
- use: "@vercel/node",
174
- entrypoint: "index.js",
175
- routes: buildRoutes
176
- }
177
- ]
178
- });
179
- return vercelOutputConfigSchema.parse({
180
- version: 3,
181
- ...resolvedConfig.vercel?.config,
182
- routes: cleanRoutes,
183
- overrides: {
184
- ...resolvedConfig.vercel?.config?.overrides,
185
- ...overrides
186
- }
187
- });
188
- }
189
- function getConfigDestination(resolvedConfig) {
190
- return path2.join(getOutput(resolvedConfig), "config.json");
191
- }
192
- async function writeConfig(resolvedConfig, rewrites, overrides, headers) {
193
- await fs.writeFile(
194
- getConfigDestination(resolvedConfig),
195
- JSON.stringify(
196
- getConfig(resolvedConfig, rewrites, overrides, headers),
197
- void 0,
198
- 2
199
- ),
200
- "utf-8"
201
- );
202
- }
2
+ import fs5 from "node:fs/promises";
3
+ import path6 from "node:path";
203
4
 
204
5
  // src/build.ts
205
- import glob from "fast-glob";
206
- import { builtinModules } from "module";
207
- import path3, { basename } from "path";
6
+ import fs, { copyFile } from "node:fs/promises";
7
+ import { builtinModules } from "node:module";
8
+ import path2, { basename } from "node:path";
9
+ import { findRoot } from "@manypkg/find-root";
10
+ import { getNodeVersion } from "@vercel/build-utils";
11
+ import { nodeFileTrace } from "@vercel/nft";
208
12
  import { build } from "esbuild";
13
+ import glob from "fast-glob";
14
+ import { generateCode, loadFile } from "magicast";
209
15
 
210
16
  // src/assert.ts
211
17
  import { newError } from "@brillout/libassert";
@@ -219,83 +25,111 @@ function assert(condition, errorMessage) {
219
25
  }
220
26
 
221
27
  // src/schemas/config/vc-config.ts
222
- import { z as z2 } from "zod";
223
- var vercelOutputEdgeVcConfigSchema = z2.object({
224
- runtime: z2.literal("edge"),
225
- entrypoint: z2.string(),
226
- envVarsInUse: z2.array(z2.string()).optional()
28
+ import { z } from "zod";
29
+ var vercelOutputEdgeVcConfigSchema = z.object({
30
+ runtime: z.literal("edge"),
31
+ entrypoint: z.string(),
32
+ envVarsInUse: z.array(z.string()).optional()
227
33
  }).strict();
228
- var vercelOutputServerlessVcConfigSchema = z2.object({
229
- runtime: z2.string(),
230
- handler: z2.string(),
231
- memory: z2.number().int().min(128).max(3008).optional(),
232
- maxDuration: z2.number().int().positive().optional(),
233
- environment: z2.record(z2.string()).optional(),
234
- regions: z2.array(z2.string()).optional(),
235
- supportsWrapper: z2.boolean().optional(),
236
- supportsResponseStreaming: z2.boolean().optional()
34
+ var vercelOutputServerlessVcConfigSchema = z.object({
35
+ runtime: z.string(),
36
+ handler: z.string(),
37
+ memory: z.number().int().min(128).max(3008).optional(),
38
+ maxDuration: z.number().int().positive().optional(),
39
+ environment: z.record(z.string()).optional(),
40
+ regions: z.array(z.string()).optional(),
41
+ supportsWrapper: z.boolean().optional(),
42
+ supportsResponseStreaming: z.boolean().optional()
237
43
  }).strict();
238
44
  var vercelOutputServerlessNodeVcConfigSchema = vercelOutputServerlessVcConfigSchema.extend({
239
- launcherType: z2.literal("Nodejs"),
240
- shouldAddHelpers: z2.boolean().optional(),
241
- shouldAddSourcemapSupport: z2.boolean().optional(),
242
- awsLambdaHandler: z2.string().optional()
45
+ launcherType: z.literal("Nodejs"),
46
+ shouldAddHelpers: z.boolean().optional(),
47
+ shouldAddSourcemapSupport: z.boolean().optional(),
48
+ awsLambdaHandler: z.string().optional()
243
49
  }).strict();
244
- var vercelOutputVcConfigSchema = z2.union([
50
+ var vercelOutputVcConfigSchema = z.union([
245
51
  vercelOutputEdgeVcConfigSchema,
246
52
  vercelOutputServerlessVcConfigSchema,
247
53
  vercelOutputServerlessNodeVcConfigSchema
248
54
  ]);
249
55
 
250
- // src/build.ts
251
- import fs2, { copyFile } from "fs/promises";
252
-
253
56
  // 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
- streaming: z3.boolean().optional(),
259
- isr: z3.object({
260
- expiration: z3.number().or(z3.literal(false))
57
+ import { z as z2 } from "zod";
58
+ var vercelEndpointExports = z2.object({
59
+ edge: z2.boolean().optional(),
60
+ headers: z2.record(z2.string()).optional(),
61
+ streaming: z2.boolean().optional(),
62
+ isr: z2.object({
63
+ expiration: z2.number().or(z2.literal(false))
261
64
  }).optional()
262
65
  });
263
66
 
67
+ // src/utils.ts
68
+ import { normalizePath } from "vite";
69
+ import path from "node:path";
70
+ function getRoot(config) {
71
+ return normalizePath(config.root || process.cwd());
72
+ }
73
+ function getOutput(config, suffix) {
74
+ return path.join(
75
+ config.vercel?.outDir ? "" : getRoot(config),
76
+ config.vercel?.outDir ?? ".vercel/output",
77
+ suffix ?? ""
78
+ );
79
+ }
80
+ function getPublic(config) {
81
+ return path.join(getRoot(config), config.publicDir || "public");
82
+ }
83
+ function pathRelativeTo(filePath, config, rel) {
84
+ const root = getRoot(config);
85
+ return normalizePath(path.relative(normalizePath(path.join(root, rel)), filePath));
86
+ }
87
+
264
88
  // src/build.ts
265
- import { generateCode, loadFile } from "magicast";
266
- import { getNodeVersion } from "@vercel/build-utils";
267
- import { nodeFileTrace } from "@vercel/nft";
268
- import { findRoot } from "@manypkg/find-root";
269
- function getAdditionalEndpoints(resolvedConfig) {
270
- return (resolvedConfig.vercel?.additionalEndpoints ?? []).map((e) => ({
89
+ async function getAdditionalEndpoints(resolvedConfig) {
90
+ const userEndpoints = [];
91
+ if (Array.isArray(resolvedConfig.vercel?.additionalEndpoints)) {
92
+ for (const endpoint of resolvedConfig.vercel.additionalEndpoints) {
93
+ if (typeof endpoint === "function") {
94
+ const res = await endpoint();
95
+ if (Array.isArray(res)) {
96
+ userEndpoints.push(...res);
97
+ } else {
98
+ userEndpoints.push(res);
99
+ }
100
+ } else {
101
+ userEndpoints.push(endpoint);
102
+ }
103
+ }
104
+ }
105
+ return userEndpoints.map((e) => ({
271
106
  ...e,
272
- addRoute: e.addRoute ?? true,
107
+ route: e.route ?? true,
273
108
  // path.resolve removes the trailing slash if any
274
- destination: path3.posix.resolve("/", e.destination) + ".func"
109
+ destination: `${path2.posix.resolve("/", e.destination)}.func`
275
110
  }));
276
111
  }
277
- function getEntries(resolvedConfig) {
278
- const apiEntries = glob.sync(`${getRoot(resolvedConfig)}/api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path3.basename(filepath).startsWith("_"));
112
+ async function getEntries(resolvedConfig) {
113
+ const apiEntries = glob.sync(`${getRoot(resolvedConfig)}/api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path2.basename(filepath).startsWith("_"));
279
114
  if (apiEntries.length > 0) {
280
115
  console.warn(
281
116
  "@vercel/build is currently force building /api files itself, with no way to disable it. In order to avoid double compilation, you should temporarily rename /api to /_api while using this plugin. /_api functions are compiled under .vercel/output/functions/api/*.func as if they were in /api."
282
117
  );
283
118
  }
284
- const otherApiEntries = glob.sync(`${getRoot(resolvedConfig)}/_api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path3.basename(filepath).startsWith("_"));
285
- return [...apiEntries, ...otherApiEntries].reduce((entryPoints, filePath) => {
286
- const outFilePath = pathRelativeTo(
287
- filePath,
288
- resolvedConfig,
289
- filePath.includes("/_api/") ? "_api" : "api"
290
- );
291
- const parsed = path3.posix.parse(outFilePath);
292
- entryPoints.push({
293
- source: filePath,
294
- destination: `api/${path3.posix.join(parsed.dir, parsed.name)}.func`,
295
- addRoute: true
296
- });
297
- return entryPoints;
298
- }, getAdditionalEndpoints(resolvedConfig));
119
+ const otherApiEntries = glob.sync(`${getRoot(resolvedConfig)}/_api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path2.basename(filepath).startsWith("_"));
120
+ return [...apiEntries, ...otherApiEntries].reduce(
121
+ (entryPoints, filePath) => {
122
+ const outFilePath = pathRelativeTo(filePath, resolvedConfig, filePath.includes("/_api/") ? "_api" : "api");
123
+ const parsed = path2.posix.parse(outFilePath);
124
+ entryPoints.push({
125
+ source: filePath,
126
+ destination: `api/${path2.posix.join(parsed.dir, parsed.name)}.func`,
127
+ route: true
128
+ });
129
+ return entryPoints;
130
+ },
131
+ await getAdditionalEndpoints(resolvedConfig)
132
+ );
299
133
  }
300
134
  var edgeWasmPlugin = {
301
135
  name: "edge-wasm-vercel",
@@ -350,38 +184,21 @@ async function buildFn(resolvedConfig, entry, buildOptions) {
350
184
  Object.assign(options, buildOptions);
351
185
  }
352
186
  const filename = entry.edge || options.format === "cjs" ? "index.js" : "index.mjs";
353
- const outfile = path3.join(
354
- getOutput(resolvedConfig, "functions"),
355
- entry.destination,
356
- filename
357
- );
187
+ const outfile = path2.join(getOutput(resolvedConfig, "functions"), entry.destination, filename);
358
188
  Object.assign(options, { outfile });
359
189
  if (!options.stdin) {
360
190
  if (typeof entry.source === "string") {
361
191
  options.entryPoints = [entry.source];
362
192
  } else {
363
- assert(
364
- typeof entry.source === "object",
365
- `\`{ source }\` must be a string or an object`
366
- );
367
- assert(
368
- typeof entry.source.contents === "string",
369
- `\`{ contents }\` must be a string`
370
- );
193
+ assert(typeof entry.source === "object", "`{ source }` must be a string or an object");
194
+ assert(typeof entry.source.contents === "string", "`{ contents }` must be a string");
371
195
  options.stdin = entry.source;
372
196
  }
373
197
  }
374
198
  if (entry.edge) {
375
- delete options.platform;
199
+ options.platform = void 0;
376
200
  options.external = [...builtinModules, ...builtinModules.map((m) => `node:${m}`)];
377
- options.conditions = [
378
- "edge-light",
379
- "worker",
380
- "browser",
381
- "module",
382
- "import",
383
- "require"
384
- ];
201
+ options.conditions = ["edge-light", "worker", "browser", "module", "import", "require"];
385
202
  options.plugins?.push(edgeWasmPlugin);
386
203
  options.format = "esm";
387
204
  } else if (options.format === "esm") {
@@ -396,9 +213,9 @@ const __dirname = VPV_dirname(__filename);
396
213
  };
397
214
  }
398
215
  const ctx = { found: false, index: "" };
399
- options.plugins.push(vercelOgPlugin(ctx));
216
+ options.plugins?.push(vercelOgPlugin(ctx));
400
217
  const output = await build(options);
401
- if (typeof entry.source == "string") {
218
+ if (typeof entry.source === "string") {
402
219
  let base = resolvedConfig.root;
403
220
  try {
404
221
  const dir = await findRoot(resolvedConfig.root);
@@ -425,18 +242,14 @@ const __dirname = VPV_dirname(__filename);
425
242
  });
426
243
  return result.outputFiles[0].text;
427
244
  }
428
- return fs2.readFile(filepath, "utf-8");
245
+ return fs.readFile(filepath, "utf-8");
429
246
  }
430
247
  });
431
248
  for (const file of fileList) {
432
- if (reasons.has(file) && reasons.get(file).type.includes("asset") && !file.endsWith(".js") && !file.endsWith(".cjs") && !file.endsWith(".mjs") && !file.endsWith("package.json")) {
249
+ if (reasons.has(file) && reasons.get(file)?.type.includes("asset") && !file.endsWith(".js") && !file.endsWith(".cjs") && !file.endsWith(".mjs") && !file.endsWith("package.json")) {
433
250
  await copyFile(
434
- path3.join(base, file),
435
- path3.join(
436
- getOutput(resolvedConfig, "functions"),
437
- entry.destination,
438
- basename(file)
439
- )
251
+ path2.join(base, file),
252
+ path2.join(getOutput(resolvedConfig, "functions"), entry.destination, basename(file))
440
253
  );
441
254
  }
442
255
  }
@@ -448,13 +261,9 @@ const __dirname = VPV_dirname(__filename);
448
261
  return output;
449
262
  }
450
263
  async function writeVcConfig(resolvedConfig, destination, filename, options) {
451
- const vcConfig = path3.join(
452
- getOutput(resolvedConfig, "functions"),
453
- destination,
454
- ".vc-config.json"
455
- );
264
+ const vcConfig = path2.join(getOutput(resolvedConfig, "functions"), destination, ".vc-config.json");
456
265
  const nodeVersion = await getNodeVersion(getOutput(resolvedConfig));
457
- await fs2.writeFile(
266
+ await fs.writeFile(
458
267
  vcConfig,
459
268
  JSON.stringify(
460
269
  vercelOutputVcConfigSchema.parse(
@@ -478,9 +287,9 @@ async function writeVcConfig(resolvedConfig, destination, filename, options) {
478
287
  }
479
288
  function getSourceAndDestination(destination) {
480
289
  if (destination.startsWith("api/")) {
481
- return path3.posix.resolve("/", destination);
290
+ return path2.posix.resolve("/", destination);
482
291
  }
483
- return path3.posix.resolve("/", destination, ":match*");
292
+ return path2.posix.resolve("/", destination, ":match*");
484
293
  }
485
294
  var RE_BRACKETS = /^\[([^/]+)\]$/gm;
486
295
  function replaceBrackets(source) {
@@ -512,8 +321,18 @@ async function extractExports(filepath) {
512
321
  console.warn(`Warning: failed to read exports of '${filepath}'`, e);
513
322
  }
514
323
  }
324
+ async function extractHeaders(resolvedConfig) {
325
+ let headers = [];
326
+ if (typeof resolvedConfig.vercel?.headers === "function") {
327
+ headers = await resolvedConfig.vercel.headers();
328
+ } else if (Array.isArray(resolvedConfig.vercel?.headers)) {
329
+ headers = resolvedConfig.vercel.headers;
330
+ }
331
+ return headers;
332
+ }
515
333
  async function buildEndpoints(resolvedConfig) {
516
- const entries = getEntries(resolvedConfig);
334
+ const entries = await getEntries(resolvedConfig);
335
+ const headers = await extractHeaders(resolvedConfig);
517
336
  for (const entry of entries) {
518
337
  if (typeof entry.source === "string") {
519
338
  const exports = await extractExports(entry.source);
@@ -537,6 +356,9 @@ async function buildEndpoints(resolvedConfig) {
537
356
  `isr configuration should be defined either in the endpoint itself or through Vite config, not both ('${entry.source}')`
538
357
  );
539
358
  }
359
+ if ((entry.isr !== void 0 || exports.isr !== void 0) && (entry.edge !== void 0 || exports.edge !== void 0)) {
360
+ throw new Error(`isr cannot be enabled for edge functions ('${entry.source}')`);
361
+ }
540
362
  if (exports.isr) {
541
363
  entry.isr = exports.isr;
542
364
  }
@@ -547,47 +369,217 @@ async function buildEndpoints(resolvedConfig) {
547
369
  }
548
370
  await buildFn(resolvedConfig, entry);
549
371
  }
550
- const isrEntries = entries.filter((e) => e.isr).map(
551
- (e) => [
552
- e.destination.replace(/\.func$/, ""),
553
- { expiration: e.isr.expiration }
554
- ]
555
- );
372
+ const isrEntries = entries.filter((e) => e.isr).map((e) => [e.destination.replace(/\.func$/, ""), { expiration: e.isr?.expiration }]);
556
373
  return {
557
- rewrites: entries.filter((e) => e.addRoute !== false).map((e) => e.destination.replace(/\.func$/, "")).map((destination) => ({
558
- source: replaceBrackets(getSourceAndDestination(destination)),
559
- destination: getSourceAndDestination(destination)
560
- })),
374
+ rewrites: entries.filter((e) => {
375
+ if (e.addRoute === void 0 && e.route !== void 0) {
376
+ return e.route !== false;
377
+ }
378
+ if (e.addRoute !== void 0 && e.route === void 0) {
379
+ return e.addRoute !== false;
380
+ }
381
+ if (e.addRoute !== void 0 && e.route !== void 0) {
382
+ throw new Error("Cannot use both `route` and `addRoute` in `additionalEndpoints`");
383
+ }
384
+ return true;
385
+ }).map((e) => {
386
+ const destination = e.destination.replace(/\.func$/, "");
387
+ if (typeof e.route === "string") {
388
+ return {
389
+ source: `(${e.route})`,
390
+ destination: `${destination}/?__original_path=$1`
391
+ };
392
+ }
393
+ return {
394
+ source: replaceBrackets(getSourceAndDestination(destination)),
395
+ destination: getSourceAndDestination(destination)
396
+ };
397
+ }),
561
398
  isr: Object.fromEntries(isrEntries),
562
- headers: entries.filter((e) => e.headers).map((e) => ({
563
- source: "/" + e.destination.replace(/\.func$/, ""),
564
- headers: Object.entries(e.headers).map(([key, value]) => ({
565
- key,
566
- value
567
- }))
568
- }))
399
+ headers: [
400
+ ...entries.filter((e) => e.headers).map((e) => ({
401
+ source: `/${e.destination.replace(/\.func$/, "")}`,
402
+ headers: Object.entries(e.headers ?? {}).map(([key, value]) => ({
403
+ key,
404
+ value
405
+ }))
406
+ })),
407
+ ...headers
408
+ ]
569
409
  };
570
410
  }
571
411
 
572
- // src/prerender.ts
573
- import path5 from "path";
412
+ // src/config.ts
413
+ import path3 from "node:path";
574
414
 
575
- // src/schemas/config/prerender-config.ts
576
- import { z as z4 } from "zod";
577
- var vercelOutputPrerenderConfigSchema = z4.object({
578
- expiration: z4.union([z4.number().int().positive(), z4.literal(false)]),
579
- group: z4.number().int().optional(),
580
- bypassToken: z4.string().optional(),
581
- fallback: z4.string().optional(),
582
- allowQuery: z4.array(z4.string()).optional()
415
+ // src/schemas/config/config.ts
416
+ import { z as z3 } from "zod";
417
+ var HasOrMissing = z3.array(
418
+ z3.union([
419
+ z3.object({
420
+ type: z3.literal("host"),
421
+ value: z3.string()
422
+ }).strict(),
423
+ z3.object({
424
+ type: z3.literal("header"),
425
+ key: z3.string(),
426
+ value: z3.string().optional()
427
+ }).strict(),
428
+ z3.object({
429
+ type: z3.literal("cookie"),
430
+ key: z3.string(),
431
+ value: z3.string().optional()
432
+ }).strict(),
433
+ z3.object({
434
+ type: z3.literal("query"),
435
+ key: z3.string(),
436
+ value: z3.string().optional()
437
+ }).strict()
438
+ ])
439
+ ).optional();
440
+ var vercelOutputConfigSchema = z3.object({
441
+ version: z3.literal(3),
442
+ routes: z3.array(
443
+ z3.union([
444
+ z3.object({
445
+ src: z3.string(),
446
+ dest: z3.string().optional(),
447
+ headers: z3.record(z3.string()).optional(),
448
+ methods: z3.array(z3.string()).optional(),
449
+ status: z3.number().int().positive().optional(),
450
+ continue: z3.boolean().optional(),
451
+ check: z3.boolean().optional(),
452
+ missing: HasOrMissing,
453
+ has: HasOrMissing,
454
+ locale: z3.object({
455
+ redirect: z3.record(z3.string()).optional(),
456
+ cookie: z3.string().optional()
457
+ }).strict().optional(),
458
+ middlewarePath: z3.string().optional()
459
+ }).strict(),
460
+ z3.object({
461
+ handle: z3.union([
462
+ z3.literal("rewrite"),
463
+ z3.literal("filesystem"),
464
+ z3.literal("resource"),
465
+ z3.literal("miss"),
466
+ z3.literal("hit"),
467
+ z3.literal("error")
468
+ ]),
469
+ src: z3.string().optional(),
470
+ dest: z3.string().optional(),
471
+ status: z3.number().optional()
472
+ }).strict()
473
+ ])
474
+ ).optional(),
475
+ images: z3.object({
476
+ sizes: z3.tuple([z3.number().int().positive(), z3.number().int().positive()]),
477
+ domains: z3.array(z3.string()).nonempty().optional(),
478
+ minimumCacheTTL: z3.number().int().positive().optional(),
479
+ formats: z3.union([z3.literal("image/avif"), z3.literal("image/webp")]).array().nonempty().optional(),
480
+ dangerouslyAllowSVG: z3.boolean().optional(),
481
+ contentSecurityPolicy: z3.string().optional()
482
+ }).strict().optional(),
483
+ wildcard: z3.array(
484
+ z3.object({
485
+ domain: z3.string(),
486
+ value: z3.string()
487
+ }).strict()
488
+ ).optional(),
489
+ overrides: z3.record(
490
+ z3.object({
491
+ path: z3.string().optional(),
492
+ contentType: z3.string().optional()
493
+ }).strict()
494
+ ).optional(),
495
+ cache: z3.array(z3.string()).optional()
583
496
  }).strict();
584
497
 
585
- // src/prerender.ts
586
- import fs4 from "fs/promises";
498
+ // src/config.ts
499
+ import fs2 from "node:fs/promises";
500
+ import {
501
+ getTransformedRoutes,
502
+ mergeRoutes,
503
+ normalizeRoutes
504
+ } from "@vercel/routing-utils";
505
+ function reorderEnforce(arr) {
506
+ return [
507
+ ...arr.filter((r) => r.enforce === "pre"),
508
+ ...arr.filter((r) => !r.enforce),
509
+ ...arr.filter((r) => r.enforce === "post")
510
+ ];
511
+ }
512
+ function getConfig(resolvedConfig, rewrites, overrides, headers) {
513
+ const _rewrites = [
514
+ // User provided config always comes first
515
+ ...resolvedConfig.vercel?.rewrites ?? [],
516
+ ...rewrites ?? []
517
+ ];
518
+ const { routes, error } = getTransformedRoutes({
519
+ cleanUrls: resolvedConfig.vercel?.cleanUrls ?? true,
520
+ trailingSlash: resolvedConfig.vercel?.trailingSlash,
521
+ rewrites: reorderEnforce(_rewrites),
522
+ redirects: resolvedConfig.vercel?.redirects ? reorderEnforce(resolvedConfig.vercel?.redirects) : void 0,
523
+ headers
524
+ });
525
+ if (error) {
526
+ throw error;
527
+ }
528
+ if (resolvedConfig.vercel?.config?.routes && resolvedConfig.vercel.config.routes.length > 0 && !resolvedConfig.vercel.config.routes.every((r) => "continue" in r && r.continue)) {
529
+ console.warn(
530
+ '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`.'
531
+ );
532
+ }
533
+ let userRoutes = [];
534
+ let buildRoutes = [];
535
+ if (resolvedConfig.vercel?.config?.routes) {
536
+ const norm = normalizeRoutes(resolvedConfig.vercel.config.routes);
537
+ if (norm.error) {
538
+ throw norm.error;
539
+ }
540
+ userRoutes = norm.routes ?? [];
541
+ }
542
+ if (routes) {
543
+ const norm = normalizeRoutes(routes);
544
+ if (norm.error) {
545
+ throw norm.error;
546
+ }
547
+ buildRoutes = norm.routes ?? [];
548
+ }
549
+ const cleanRoutes = mergeRoutes({
550
+ userRoutes,
551
+ builds: [
552
+ {
553
+ use: "@vercel/node",
554
+ entrypoint: "index.js",
555
+ routes: buildRoutes
556
+ }
557
+ ]
558
+ });
559
+ return vercelOutputConfigSchema.parse({
560
+ version: 3,
561
+ ...resolvedConfig.vercel?.config,
562
+ routes: cleanRoutes,
563
+ overrides: {
564
+ ...resolvedConfig.vercel?.config?.overrides,
565
+ ...overrides
566
+ }
567
+ });
568
+ }
569
+ function getConfigDestination(resolvedConfig) {
570
+ return path3.join(getOutput(resolvedConfig), "config.json");
571
+ }
572
+ async function writeConfig(resolvedConfig, rewrites, overrides, headers) {
573
+ await fs2.writeFile(
574
+ getConfigDestination(resolvedConfig),
575
+ JSON.stringify(getConfig(resolvedConfig, rewrites, overrides, headers), void 0, 2),
576
+ "utf-8"
577
+ );
578
+ }
587
579
 
588
580
  // src/helpers.ts
589
- import fs3 from "fs/promises";
590
- import path4 from "path";
581
+ import fs3 from "node:fs/promises";
582
+ import path4 from "node:path";
591
583
  async function copyDir(src, dest) {
592
584
  await fs3.mkdir(dest, { recursive: true });
593
585
  const entries = await fs3.readdir(src, { withFileTypes: true });
@@ -599,6 +591,20 @@ async function copyDir(src, dest) {
599
591
  }
600
592
 
601
593
  // src/prerender.ts
594
+ import path5 from "node:path";
595
+
596
+ // src/schemas/config/prerender-config.ts
597
+ import { z as z4 } from "zod";
598
+ var vercelOutputPrerenderConfigSchema = z4.object({
599
+ expiration: z4.union([z4.number().int().positive(), z4.literal(false)]),
600
+ group: z4.number().int().optional(),
601
+ bypassToken: z4.string().optional(),
602
+ fallback: z4.string().optional(),
603
+ allowQuery: z4.array(z4.string()).optional()
604
+ }).strict();
605
+
606
+ // src/prerender.ts
607
+ import fs4 from "node:fs/promises";
602
608
  function execPrerender(resolvedConfig) {
603
609
  const prerender = resolvedConfig.vercel?.prerender;
604
610
  if (prerender === false) {
@@ -609,15 +615,8 @@ function execPrerender(resolvedConfig) {
609
615
  var group = 1;
610
616
  async function writePrerenderConfig(resolvedConfig, destination, isr) {
611
617
  const parsed = path5.parse(destination);
612
- const outfile = path5.join(
613
- getOutput(resolvedConfig, "functions"),
614
- parsed.dir,
615
- parsed.name + ".prerender-config.json"
616
- );
617
- await fs4.mkdir(
618
- path5.join(getOutput(resolvedConfig, "functions"), parsed.dir),
619
- { recursive: true }
620
- );
618
+ const outfile = path5.join(getOutput(resolvedConfig, "functions"), parsed.dir, `${parsed.name}.prerender-config.json`);
619
+ await fs4.mkdir(path5.join(getOutput(resolvedConfig, "functions"), parsed.dir), { recursive: true });
621
620
  await fs4.writeFile(
622
621
  outfile,
623
622
  JSON.stringify(
@@ -635,34 +634,18 @@ function getPrerenderSymlinkInfo(resolvedConfig, destination, target) {
635
634
  const parsed = path5.parse(destination);
636
635
  const targetParsed = path5.parse(target);
637
636
  return {
638
- target: path5.join(
639
- getOutput(resolvedConfig, "functions"),
640
- targetParsed.dir,
641
- targetParsed.name + ".func"
642
- ),
643
- link: path5.join(
644
- getOutput(resolvedConfig, "functions"),
645
- parsed.dir,
646
- parsed.name + ".func"
647
- )
637
+ target: path5.join(getOutput(resolvedConfig, "functions"), targetParsed.dir, `${targetParsed.name}.func`),
638
+ link: path5.join(getOutput(resolvedConfig, "functions"), parsed.dir, `${parsed.name}.func`)
648
639
  };
649
640
  }
650
641
  async function buildPrerenderConfigs(resolvedConfig, extractedIsr) {
651
- const isr = Object.assign(
652
- {},
653
- extractedIsr,
654
- await getIsrConfig(resolvedConfig)
655
- );
642
+ const isr = Object.assign({}, extractedIsr, await getIsrConfig(resolvedConfig));
656
643
  const entries = Object.entries(isr);
657
644
  const rewrites = [];
658
645
  for (const [destination, { symlink, route, ...isr2 }] of entries) {
659
646
  await writePrerenderConfig(resolvedConfig, destination, isr2);
660
647
  if (symlink) {
661
- const info = getPrerenderSymlinkInfo(
662
- resolvedConfig,
663
- destination,
664
- symlink
665
- );
648
+ const info = getPrerenderSymlinkInfo(resolvedConfig, destination, symlink);
666
649
  await copyDir(info.target, info.link);
667
650
  }
668
651
  if (route) {
@@ -683,7 +666,6 @@ async function getIsrConfig(resolvedConfig) {
683
666
  }
684
667
 
685
668
  // src/index.ts
686
- import path6 from "path";
687
669
  function vercelPluginCleanup() {
688
670
  let resolvedConfig;
689
671
  return {
@@ -713,9 +695,7 @@ function vercelPlugin() {
713
695
  enforce: "post",
714
696
  configResolved(config) {
715
697
  resolvedConfig = config;
716
- vikeFound = resolvedConfig.plugins.some(
717
- (p) => p.name.match("^vite-plugin-ssr:|^vike:")
718
- );
698
+ vikeFound = resolvedConfig.plugins.some((p) => p.name.match("^vite-plugin-ssr:|^vike:"));
719
699
  if (typeof resolvedConfig.vercel?.distContainsOnlyStatic === "undefined") {
720
700
  resolvedConfig.vercel ??= {};
721
701
  resolvedConfig.vercel.distContainsOnlyStatic = !vikeFound;
@@ -757,10 +737,7 @@ async function cleanOutputDirectory(resolvedConfig) {
757
737
  }
758
738
  async function copyDistToStatic(resolvedConfig) {
759
739
  if (resolvedConfig.vercel?.distContainsOnlyStatic) {
760
- await copyDir(
761
- resolvedConfig.build.outDir,
762
- getOutput(resolvedConfig, "static")
763
- );
740
+ await copyDir(resolvedConfig.build.outDir, getOutput(resolvedConfig, "static"));
764
741
  }
765
742
  }
766
743
  async function computeStaticHtmlOverrides(resolvedConfig) {
@@ -768,18 +745,19 @@ async function computeStaticHtmlOverrides(resolvedConfig) {
768
745
  const files = await getStaticHtmlFiles(staticAbsolutePath);
769
746
  const publicDir = getPublic(resolvedConfig);
770
747
  const publicFiles = await getStaticHtmlFiles(publicDir);
771
- files.push(
772
- ...publicFiles.map((f) => f.replace(publicDir, staticAbsolutePath))
748
+ files.push(...publicFiles.map((f) => f.replace(publicDir, staticAbsolutePath)));
749
+ return files.reduce(
750
+ (acc, curr) => {
751
+ const relPath = path6.relative(staticAbsolutePath, curr);
752
+ const parsed = path6.parse(relPath);
753
+ const pathJoined = path6.join(parsed.dir, parsed.name);
754
+ acc[relPath] = {
755
+ path: pathJoined
756
+ };
757
+ return acc;
758
+ },
759
+ {}
773
760
  );
774
- return files.reduce((acc, curr) => {
775
- const relPath = path6.relative(staticAbsolutePath, curr);
776
- const parsed = path6.parse(relPath);
777
- const pathJoined = path6.join(parsed.dir, parsed.name);
778
- acc[relPath] = {
779
- path: pathJoined
780
- };
781
- return acc;
782
- }, {});
783
761
  }
784
762
  async function getStaticHtmlFiles(src) {
785
763
  try {
@@ -812,11 +790,7 @@ async function tryImportVpvv(options) {
812
790
  }
813
791
  function allPlugins(options = {}) {
814
792
  const { smart, ...rest } = options;
815
- return [
816
- vercelPluginCleanup(),
817
- vercelPlugin(),
818
- smart !== false ? tryImportVpvv(rest) : null
819
- ];
793
+ return [vercelPluginCleanup(), vercelPlugin(), smart !== false ? tryImportVpvv(rest) : null];
820
794
  }
821
795
  export {
822
796
  allPlugins as default