vite-plugin-vercel 11.0.0-beta.2 → 11.0.0-beta.20

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 CHANGED
@@ -1,15 +1,12 @@
1
1
  # vite-plugin-vercel
2
2
 
3
3
  > [!NOTE]
4
- > You are on the [Vite Environment API](https://vite.dev/guide/api-environment.html#environment-configuration) beta branch (v10). Check out [v9 branch](https://github.com/magne4000/vite-plugin-vercel/tree/v9) for current stable version.
4
+ > You are on the [Vite Environment API](https://vite.dev/guide/api-environment.html#environment-configuration) beta branch (v11). Check out [v9 branch](https://github.com/magne4000/vite-plugin-vercel/tree/v9) for current stable version.
5
5
 
6
6
  Vercel adapter for [Vite](https://vitejs.dev/).
7
7
 
8
8
  Bundle your Vite application as supported by [Vercel Output API (v3)](https://vercel.com/docs/build-output-api/v3).
9
9
 
10
- > [!NOTE]
11
- > This plugin is mostly a re-export of [`@photonjs/vercel`](https://github.com/photon-js/photon/tree/main/packages/adapter-vercel)
12
-
13
10
  ## Install
14
11
 
15
12
  ```bash
@@ -68,7 +65,7 @@ export default defineConfig({
68
65
  ```
69
66
 
70
67
  > [!NOTE]
71
- > `@vercel/build` currently forces the building of files in the _/api_ folder, with no way to disable this behavior.
68
+ > `@vercel/build` forces the building of files in the _/api_ folder, with no way to disable this behavior.
72
69
  > It's recommended to place your files in a different folder.
73
70
 
74
71
  ### Configure endpoints
@@ -165,7 +162,7 @@ export default defineConfig({
165
162
  trailingSlash: true,
166
163
  /**
167
164
  * Use `getVercelEntries` for mapping your filesystem routes to entries.
168
- * If you are interfacing this plugin with a framework, entries can also be added through the Photon API
165
+ * If you are interfacing this plugin with a framework, entries can also be added through the {@link https://github.com/photon-js/universal-deploy | universal-deploy} API
169
166
  */
170
167
  entries: {
171
168
  root: {
@@ -209,7 +206,7 @@ Related documentation: https://vercel.com/docs/edge-network/headers/request-head
209
206
 
210
207
  ## Migrations
211
208
 
212
- - [Migration from v9 to v10](https://github.com/magne4000/vite-plugin-vercel/blob/main/MIGRATION.md)
209
+ - [Migration from v9 to v11](https://github.com/magne4000/vite-plugin-vercel/blob/main/MIGRATION.md)
213
210
 
214
211
  ## Demo
215
212
 
package/dist/api.js CHANGED
@@ -1,3 +1,65 @@
1
- import { n as getVercelAPI, t as createAPI } from "./api-DR2y7JVQ.js";
1
+ import { t as assert } from "./assert-vtiLgQIb.js";
2
2
 
3
+ //#region src/api.ts
4
+ function createAPI(outfiles, pluginConfig) {
5
+ return {
6
+ getOutFiles() {
7
+ return outfiles;
8
+ },
9
+ get config() {
10
+ pluginConfig.config ??= {};
11
+ return pluginConfig.config;
12
+ },
13
+ get defaultMaxDuration() {
14
+ return pluginConfig.defaultMaxDuration;
15
+ },
16
+ set defaultMaxDuration(value) {
17
+ pluginConfig.defaultMaxDuration = value;
18
+ },
19
+ get expiration() {
20
+ return pluginConfig.expiration;
21
+ },
22
+ set expiration(value) {
23
+ pluginConfig.expiration = value;
24
+ },
25
+ get rewrites() {
26
+ pluginConfig.rewrites ??= [];
27
+ return pluginConfig.rewrites;
28
+ },
29
+ get headers() {
30
+ pluginConfig.headers ??= [];
31
+ return pluginConfig.headers;
32
+ },
33
+ get redirects() {
34
+ pluginConfig.redirects ??= [];
35
+ return pluginConfig.redirects;
36
+ },
37
+ get cleanUrls() {
38
+ return pluginConfig.cleanUrls;
39
+ },
40
+ set cleanUrls(value) {
41
+ pluginConfig.cleanUrls = value;
42
+ },
43
+ get trailingSlash() {
44
+ return pluginConfig.trailingSlash;
45
+ },
46
+ set trailingSlash(value) {
47
+ pluginConfig.trailingSlash = value;
48
+ },
49
+ get defaultSupportsResponseStreaming() {
50
+ return pluginConfig.defaultSupportsResponseStreaming;
51
+ },
52
+ set defaultSupportsResponseStreaming(value) {
53
+ pluginConfig.defaultSupportsResponseStreaming = value;
54
+ }
55
+ };
56
+ }
57
+ function getVercelAPI(pluginContextOrServer) {
58
+ const vpv = ("environment" in pluginContextOrServer ? pluginContextOrServer.environment.config : pluginContextOrServer.config).plugins.find((p) => p.name === "vite-plugin-vercel:api");
59
+ assert(vpv, "Could not find vite-plugin-vercel:api plugin");
60
+ assert(vpv.api, "Missing `api`. Make sure vite-plugin-vercel is up-to-date");
61
+ return vpv.api("environment" in pluginContextOrServer ? pluginContextOrServer : void 0);
62
+ }
63
+
64
+ //#endregion
3
65
  export { createAPI, getVercelAPI };
@@ -0,0 +1,8 @@
1
+ //#region src/utils/assert.ts
2
+ function assert(condition, errorMessage) {
3
+ if (condition) return;
4
+ throw new Error(`[vite-plugin-vercel] ${errorMessage}`);
5
+ }
6
+
7
+ //#endregion
8
+ export { assert as t };
package/dist/index.d.ts CHANGED
@@ -1,18 +1,31 @@
1
1
  import { EntryMeta } from "@universal-deploy/store";
2
2
 
3
3
  //#region src/index.d.ts
4
-
4
+ interface GetVercelEntriesOptions {
5
+ /**
6
+ * Map entries to URL patterns
7
+ * @example
8
+ * // When dir: "endpoints/myapi" and destination: "api"
9
+ * // endpoints/myapi/page.ts -> /api/page
10
+ * // endpoints/myapi/name/[name].ts -> /api/name/*
11
+ */
12
+ destination?: string;
13
+ /**
14
+ * If true, parse entries exports for per-file settings.
15
+ * Entries can export `edge`, `isr`, `headers` and `streaming`. See README for more details
16
+ *
17
+ * @default true
18
+ */
19
+ tryParseExports?: boolean;
20
+ }
5
21
  /**
6
22
  * Scans the filesystem for entry points.
7
- * @experimental
23
+ * @beta
8
24
  */
9
25
  declare function getVercelEntries(dir: string, {
10
26
  destination,
11
27
  tryParseExports
12
- }: {
13
- destination?: string | undefined;
14
- tryParseExports?: boolean | undefined;
15
- }): Promise<EntryMeta[]>;
28
+ }: GetVercelEntriesOptions): Promise<EntryMeta[]>;
16
29
  declare function extractExports(filepath: string): Promise<{
17
30
  edge?: boolean | undefined;
18
31
  headers?: Record<string, string> | undefined;
@@ -22,4 +35,4 @@ declare function extractExports(filepath: string): Promise<{
22
35
  } | undefined;
23
36
  } | null>;
24
37
  //#endregion
25
- export { extractExports, getVercelEntries };
38
+ export { GetVercelEntriesOptions, extractExports, getVercelEntries };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as pathRelativeTo } from "./path-B4ThGm96.js";
1
+ import { t as pathRelativeTo } from "./path-DoLvGKnz.js";
2
2
  import path from "node:path";
3
3
  import { vercelEndpointExports } from "@vite-plugin-vercel/schemas";
4
4
  import { fromNextFs } from "convert-route/next-fs";
@@ -10,7 +10,7 @@ import { normalizePath } from "vite";
10
10
  //#region src/index.ts
11
11
  /**
12
12
  * Scans the filesystem for entry points.
13
- * @experimental
13
+ * @beta
14
14
  */
15
15
  async function getVercelEntries(dir, { destination = dir, tryParseExports = true }) {
16
16
  const normalizedDir = normalizePath(dir);
@@ -31,7 +31,7 @@ async function getVercelEntries(dir, { destination = dir, tryParseExports = true
31
31
  if (xports?.isr) entry.vercel.isr = xports.isr;
32
32
  if (xports?.headers) entry.vercel.headers = xports.headers;
33
33
  if (xports?.streaming) entry.vercel.streaming = xports.streaming;
34
- entry.pattern = entryToRou3(key);
34
+ entry.route = entryToRou3(key);
35
35
  if (key.includes("[...")) entry.vercel.enforce = "post";
36
36
  entryPoints.push(entry);
37
37
  }
package/dist/types.d.ts CHANGED
@@ -12,6 +12,20 @@ type ViteVercelRedirect = Redirect & {
12
12
  };
13
13
  type PluginContext = ThisParameterType<Extract<Plugin["resolveId"], (...args: never) => any>>;
14
14
  interface ViteVercelConfig {
15
+ /**
16
+ * @experimental
17
+ * @default basic
18
+ */
19
+ bundleStrategy?: "basic" | "nf3";
20
+ /**
21
+ * Override vite build environments
22
+ * @experimental
23
+ */
24
+ viteEnvNames?: {
25
+ client?: string;
26
+ edge?: string | false;
27
+ node?: string;
28
+ };
15
29
  /**
16
30
  * How long Functions should be allowed to run for every request, in seconds.
17
31
  * If left empty, default value for your plan will be used.
package/dist/vite.js CHANGED
@@ -1,22 +1,36 @@
1
- import { t as pathRelativeTo$1 } from "./path-B4ThGm96.js";
2
- import { r as assert, t as createAPI } from "./api-DR2y7JVQ.js";
1
+ import { t as pathRelativeTo$1 } from "./path-DoLvGKnz.js";
2
+ import { t as assert } from "./assert-vtiLgQIb.js";
3
+ import { createAPI, getVercelAPI } from "./api.js";
4
+ import { builtinModules } from "node:module";
3
5
  import path from "node:path";
4
6
  import { vercelOutputConfigSchema, vercelOutputPrerenderConfigSchema, vercelOutputVcConfigSchema } from "@vite-plugin-vercel/schemas";
5
7
  import { fromRou3 } from "convert-route/rou3";
6
8
  import { BuildEnvironment, createRunnableDevEnvironment, mergeConfig, normalizePath } from "vite";
7
9
  import { catchAll, devServer } from "@universal-deploy/store/vite";
8
- import { store } from "@universal-deploy/store";
9
- import fs from "node:fs";
10
+ import { addEntry, getAllEntries } from "@universal-deploy/store";
11
+ import fs, { existsSync, readFileSync, writeFileSync } from "node:fs";
12
+ import { copyFile, cp, rmdir, unlink } from "node:fs/promises";
13
+ import { findRoot } from "@manypkg/find-root";
14
+ import { nodeFileTrace, resolve } from "@vercel/nft";
15
+ import { transform } from "oxc-transform";
16
+ import { build } from "rolldown";
10
17
  import { cpus } from "node:os";
11
- import { resolve } from "@vercel/nft";
12
18
  import { externals } from "nf3/plugin";
13
19
  import pLimit from "p-limit";
14
- import { build } from "rolldown";
15
20
  import { getNodeVersion } from "@vercel/build-utils";
16
21
  import { toPathToRegexpV6 } from "convert-route/path-to-regexp-v6";
17
- import { cp } from "node:fs/promises";
18
22
  import { getTransformedRoutes, mergeRoutes, normalizeRoutes } from "@vercel/routing-utils";
19
23
 
24
+ //#region src/utils/buildEnvs.ts
25
+ function getBuildEnvNames(pluginConfig) {
26
+ return {
27
+ client: pluginConfig.viteEnvNames?.client ?? "vercel_client",
28
+ edge: pluginConfig.viteEnvNames?.edge ?? "vercel_edge",
29
+ node: pluginConfig.viteEnvNames?.node ?? "vercel_node"
30
+ };
31
+ }
32
+
33
+ //#endregion
20
34
  //#region src/utils/dedupeRoutes.ts
21
35
  /**
22
36
  * When multiple entries point to the same module, we can deploy them as a single function.
@@ -24,20 +38,65 @@ import { getTransformedRoutes, mergeRoutes, normalizeRoutes } from "@vercel/rout
24
38
  */
25
39
  function dedupeRoutes() {
26
40
  const entriesToKeep = [];
27
- const entriesGroupedByModuleId = groupBy(store.entries, (e) => e.id);
41
+ const entriesGroupedByModuleId = groupBy(getAllEntries(), (e) => e.id);
28
42
  for (const entries of entriesGroupedByModuleId.values()) {
29
43
  let groupedEntry;
30
44
  for (const entry of entries) if (entry.vercel && Object.keys(entry.vercel).length > 0) {
31
- if (!Array.isArray(entry.pattern)) entry.pattern = [entry.pattern];
45
+ if (!Array.isArray(entry.route)) entry.route = [entry.route];
32
46
  entriesToKeep.push(entry);
33
47
  } else if (!groupedEntry) {
34
48
  groupedEntry = structuredClone(entry);
35
- if (!Array.isArray(groupedEntry.pattern)) groupedEntry.pattern = [groupedEntry.pattern];
49
+ if (!Array.isArray(groupedEntry.route)) groupedEntry.route = [groupedEntry.route];
36
50
  entriesToKeep.push(groupedEntry);
37
- } else groupedEntry.pattern.push(...[entry.pattern].flat());
51
+ } else groupedEntry.route.push(...[entry.route].flat());
38
52
  }
39
53
  return entriesToKeep;
40
54
  }
55
+ /**
56
+ * Sorts routes by specificity.
57
+ *
58
+ * Specificity rules:
59
+ * 1. Segment type priority at each position: Static > Dynamic/Param > Catch-all.
60
+ * 2. Total route length: Longer routes are generally more specific.
61
+ * 3. Prefix match exception: A shorter static route is more specific than a longer route
62
+ * that only adds a catch-all segment to the same prefix.
63
+ * 4. Alphabetical order: Final tie-breaker for static segments at the same position.
64
+ *
65
+ * @param routes - Array of routes to sort.
66
+ * @returns A new array of routes sorted from most specific to least specific.
67
+ */
68
+ function sortRoutes(routes) {
69
+ return [...routes].sort((a, b) => {
70
+ const lenA = a.pathname.length;
71
+ const lenB = b.pathname.length;
72
+ const commonLen = Math.min(lenA, lenB);
73
+ for (let i = 0; i < commonLen; i++) {
74
+ const segA = a.pathname[i];
75
+ const segB = b.pathname[i];
76
+ if (segA.value && !segB.value) return -1;
77
+ if (!segA.value && segB.value) return 1;
78
+ if (segA.value && segB.value) {
79
+ if (segA.value !== segB.value) {
80
+ if (lenA !== lenB) return lenB - lenA;
81
+ return segA.value.localeCompare(segB.value);
82
+ }
83
+ }
84
+ if (!segA.optional && segB.optional) return -1;
85
+ if (segA.optional && !segB.optional) return 1;
86
+ if (segA.catchAll && segB.catchAll) {
87
+ if (!segA.catchAll.greedy && segB.catchAll.greedy) return -1;
88
+ if (segA.catchAll.greedy && !segB.catchAll.greedy) return 1;
89
+ }
90
+ if (segA.catchAll && !segB.catchAll) return 1;
91
+ if (!segA.catchAll && segB.catchAll) return -1;
92
+ }
93
+ if (lenA !== lenB) {
94
+ if (lenA > lenB) return a.pathname[lenB].catchAll ? 1 : -1;
95
+ return b.pathname[lenA].catchAll ? -1 : 1;
96
+ }
97
+ return 0;
98
+ });
99
+ }
41
100
  function groupBy(list, fn, selector) {
42
101
  return Array.from(list).reduce((acc, curr) => {
43
102
  const key = fn(curr);
@@ -56,8 +115,36 @@ function removeExtension$1(subject) {
56
115
 
57
116
  //#endregion
58
117
  //#region src/utils/destination.ts
118
+ function parseViteId(id) {
119
+ const [path, query] = id.split("?");
120
+ return {
121
+ path: decodeURIComponent(path),
122
+ query
123
+ };
124
+ }
125
+ function extractBestPath({ path, query }) {
126
+ if (!query) return path;
127
+ return query.split("&").map(decodeURIComponent).find((p) => p.includes("/")) || path;
128
+ }
129
+ function shortenPath(path, maxSegments = 2) {
130
+ return removeExtension$1(path.split(/[\\/]/).filter(Boolean).slice(-maxSegments).join("_"));
131
+ }
132
+ function mapPath(path, maxSegments = 2) {
133
+ const nodeModuleMatch = path.match(/node_modules[\\/](.+?)([\\/].*)?$/);
134
+ if (nodeModuleMatch) return `${nodeModuleMatch[1].split(/[\\/]/)[0]}_${removeExtension$1(nodeModuleMatch[2]?.split(/[\\/]/).pop() || "index")}`;
135
+ return shortenPath(path, maxSegments);
136
+ }
137
+ function hashString(str, length = 6) {
138
+ let hash = 5381;
139
+ for (let i = 0; i < str.length; i++) hash = hash * 33 ^ str.charCodeAt(i);
140
+ hash = hash >>> 0;
141
+ return hash.toString(36).slice(0, length);
142
+ }
143
+ function uniqueViteName(id, entry, maxSegments = 2) {
144
+ return removeExtension$1(`${mapPath(extractBestPath(parseViteId(id)), maxSegments)}_${hashString(JSON.stringify(entry))}`.replace(/[^a-zA-Z0-9\-_[\]/]/g, "-"));
145
+ }
59
146
  function entryDestinationDefault(root, entry) {
60
- return `${removeExtension$1(pathRelativeTo$1(entry.id, root)).replace(/[^a-zA-Z0-9\-_[\]/]/g, "-")}`;
147
+ return uniqueViteName(pathRelativeTo$1(entry.id, root), entry);
61
148
  }
62
149
  function entryDestination(root, entry, postfix) {
63
150
  return `${path.posix.join("functions/", entryDestinationDefault(root, entry))}${postfix}`;
@@ -66,6 +153,7 @@ function entryDestination(root, entry, postfix) {
66
153
  //#endregion
67
154
  //#region src/plugins/api.ts
68
155
  function apiPlugin(pluginConfig) {
156
+ const envNames = getBuildEnvNames(pluginConfig);
69
157
  const outfiles = [];
70
158
  return {
71
159
  name: "vite-plugin-vercel:api",
@@ -73,12 +161,12 @@ function apiPlugin(pluginConfig) {
73
161
  return createAPI(outfiles, pluginConfig);
74
162
  },
75
163
  applyToEnvironment({ name }) {
76
- return name === "vercel_edge" || name === "vercel_node";
164
+ return name === envNames.edge || name === envNames.node;
77
165
  },
78
- writeBundle(_opts, bundle$1) {
166
+ writeBundle(_opts, bundle) {
79
167
  const root = this.environment.config.root ?? process.cwd();
80
168
  const entryMapByDestination = new Map(dedupeRoutes().map((e) => [entryDestination(root, e, ".func/index"), e]));
81
- for (const [key, value] of Object.entries(bundle$1)) if (value.type === "chunk" && entryMapByDestination.has(removeExtension$1(key))) outfiles.push({
169
+ for (const [key, value] of Object.entries(bundle)) if (value.type === "chunk" && entryMapByDestination.has(removeExtension$1(key))) outfiles.push({
82
170
  type: "chunk",
83
171
  root: this.environment.config.root,
84
172
  outdir: this.environment.config.build.outDir,
@@ -96,6 +184,17 @@ function apiPlugin(pluginConfig) {
96
184
  };
97
185
  }
98
186
 
187
+ //#endregion
188
+ //#region src/utils/edge.ts
189
+ const edgeConditions = [
190
+ "edge-light",
191
+ "worker",
192
+ "browser",
193
+ "module",
194
+ "import",
195
+ "default"
196
+ ];
197
+
99
198
  //#endregion
100
199
  //#region src/utils/external.ts
101
200
  const _external = [
@@ -108,8 +207,193 @@ const _external = [
108
207
  const edgeExternal = [..._external, ..._external.map((e) => `node:${e}`)];
109
208
 
110
209
  //#endregion
111
- //#region src/plugins/bundle.ts
112
- function bundlePlugin() {
210
+ //#region src/plugins/bundle/basic.ts
211
+ const builtIns = new Set(builtinModules.flatMap((m) => [m, `node:${m}`]));
212
+ const edgeWasmPlugin = {
213
+ name: "edge-wasm-vercel",
214
+ resolveId: {
215
+ filter: { id: [/\.wasm\?module$/] },
216
+ handler(id) {
217
+ return {
218
+ id: id.replace(/\.wasm\?module$/, ".wasm"),
219
+ external: true
220
+ };
221
+ }
222
+ }
223
+ };
224
+ const dynamicNativeImportPlugin = {
225
+ name: "edge-dynamic-import-native",
226
+ resolveDynamicImport(specifier) {
227
+ if (typeof specifier === "string" && builtIns.has(specifier)) return {
228
+ id: specifier,
229
+ external: true
230
+ };
231
+ }
232
+ };
233
+ const reactEdgePlugin$1 = {
234
+ name: "react-edge-plugin",
235
+ resolveId: {
236
+ filter: { id: [/react-dom\/server/] },
237
+ async handler(_id, importer, options) {
238
+ return this.resolve("react-dom/server.edge", importer, options);
239
+ }
240
+ }
241
+ };
242
+ function basicBundlePlugin(pluginConfig) {
243
+ const envNames = getBuildEnvNames(pluginConfig);
244
+ const bundledAssets = /* @__PURE__ */ new Map();
245
+ const bundledChunks = [];
246
+ return [{
247
+ name: "vite-plugin-vercel:bundle",
248
+ enforce: "post",
249
+ apply: "build",
250
+ generateBundle(_opts, bundle) {
251
+ for (const b of Object.values(bundle)) {
252
+ const outFile = joinAbsolute(this.environment, this.environment.config.build.outDir, b.fileName);
253
+ if (b.type === "asset") {
254
+ const originalFileNames = b.originalFileNames.map((relativePath) => path.resolve(this.environment.config.root, relativePath));
255
+ const asset = {
256
+ env: this.environment.name,
257
+ root: this.environment.config.root,
258
+ outDir: this.environment.config.build.outDir,
259
+ outFile,
260
+ fileName: b.fileName
261
+ };
262
+ for (const originalFileName of originalFileNames) bundledAssets.set(originalFileName, asset);
263
+ } else if (this.environment.name === envNames.edge || this.environment.name === envNames.node) bundledChunks.push(outFile);
264
+ }
265
+ },
266
+ closeBundle: {
267
+ order: "post",
268
+ async handler() {
269
+ if (!isVercelLastBuildStep(this.environment, pluginConfig)) return;
270
+ this.environment.logger.info("Creating Vercel bundles...");
271
+ const outfiles = getVercelAPI(this).getOutFiles();
272
+ const filesToKeepP = [];
273
+ for (const outfile of outfiles) if (outfile.type === "chunk") filesToKeepP.push(bundle$1(this, bundledAssets, outfile));
274
+ await cleanup$1((await Promise.all(filesToKeepP)).flat(), bundledChunks);
275
+ }
276
+ },
277
+ sharedDuringBuild: true
278
+ }];
279
+ }
280
+ function getAbsoluteOutFile(outfile) {
281
+ const source = joinAbsolutePosix(outfile.root, outfile.outdir, outfile.filepath);
282
+ return {
283
+ source,
284
+ destination: source.replace(outfile.outdir, outfile.outdir)
285
+ };
286
+ }
287
+ async function bundle$1(pluginContext, bundledAssets, outfile) {
288
+ const output = [];
289
+ const { source, destination } = getAbsoluteOutFile(outfile);
290
+ const isEdge = Boolean(outfile.relatedEntry.vercel?.edge);
291
+ const { environment } = pluginContext;
292
+ const buildOptions = {};
293
+ buildOptions.output = {
294
+ format: "esm",
295
+ legalComments: "none",
296
+ codeSplitting: false
297
+ };
298
+ buildOptions.checks = { pluginTimings: false };
299
+ buildOptions.input = [source];
300
+ buildOptions.treeshake = true;
301
+ buildOptions.resolve ??= {};
302
+ if (isEdge) {
303
+ buildOptions.platform = "browser";
304
+ buildOptions.external = edgeExternal;
305
+ buildOptions.resolve.conditionNames = edgeConditions;
306
+ buildOptions.transform = { define: { "process.env.NODE_ENV": JSON.stringify("production") } };
307
+ buildOptions.output.file = destination.replace(/\.mjs$/, ".js");
308
+ buildOptions.plugins = [
309
+ edgeWasmPlugin,
310
+ dynamicNativeImportPlugin,
311
+ reactEdgePlugin$1
312
+ ];
313
+ } else {
314
+ buildOptions.platform = "node";
315
+ buildOptions.output.file = destination.replace(/\.js$/, ".mjs");
316
+ }
317
+ try {
318
+ await build(buildOptions);
319
+ output.push(buildOptions.output.file);
320
+ } catch (e) {
321
+ throw new Error(`Error while bundling ${destination}`, { cause: e });
322
+ }
323
+ let base = environment.config.root;
324
+ try {
325
+ base = (await findRoot(environment.config.root)).rootDir;
326
+ } catch (_e) {}
327
+ const resolvedEntryP = pluginContext.resolve(outfile.relatedEntry.id);
328
+ const entryFilePath = existsSync(outfile.relatedEntry.id) ? outfile.relatedEntry.id : (await resolvedEntryP)?.id && existsSync((await resolvedEntryP).id) ? (await resolvedEntryP).id : null;
329
+ if (entryFilePath === null) return [];
330
+ const { fileList, reasons } = await nodeFileTrace([entryFilePath], {
331
+ base,
332
+ processCwd: environment.config.root,
333
+ mixedModules: true,
334
+ ignore: [
335
+ "**/node_modules/react{,-dom,-dom-server-turbopack}/**/*.development.js",
336
+ "**/*.d.ts",
337
+ "**/*.map",
338
+ "**/node_modules/webpack5/**/*"
339
+ ],
340
+ async readFile(filepath) {
341
+ const code = readFileSync(filepath, "utf-8");
342
+ if (filepath.endsWith(".ts") || filepath.endsWith(".tsx")) return (await transform(filepath, code, { target: "es2022" })).code;
343
+ return code;
344
+ }
345
+ });
346
+ for (const file of fileList) if (reasons.has(file) && reasons.get(file)?.type.includes("asset") && !file.endsWith(".js") && !file.endsWith(".cjs") && !file.endsWith(".mjs") && !file.endsWith("package.json")) {
347
+ const absolutePath = path.join(base, file);
348
+ const assetRenamedByVite = bundledAssets.get(absolutePath);
349
+ const basename = path.basename(assetRenamedByVite ? assetRenamedByVite.fileName : absolutePath);
350
+ if (assetRenamedByVite) writeFileSync(destination, readFileSync(destination, "utf-8").replaceAll(`/${assetRenamedByVite.fileName}`, `./${path.basename(assetRenamedByVite.fileName)}`));
351
+ const to = path.join(path.dirname(destination), basename);
352
+ output.push(to);
353
+ await copyFile(absolutePath, to);
354
+ }
355
+ return output;
356
+ }
357
+ function joinAbsolute(env_or_p0, p1, ...p) {
358
+ if (path.isAbsolute(p1)) return path.join(p1, ...p);
359
+ return path.join(typeof env_or_p0 === "string" ? env_or_p0 : env_or_p0.config.root, p1, ...p);
360
+ }
361
+ function joinAbsolutePosix(env_or_p0, p1, ...p) {
362
+ if (path.isAbsolute(p1)) return path.posix.join(p1, ...p);
363
+ return path.posix.join(typeof env_or_p0 === "string" ? env_or_p0 : env_or_p0.config.root, p1, ...p);
364
+ }
365
+ function isVercelLastBuildStep(env, pluginConfig) {
366
+ const envNames = getBuildEnvNames(pluginConfig);
367
+ return (typeof env !== "string" ? env.name : env) === envNames.node;
368
+ }
369
+ async function cleanup$1(filesToKeep, bundledChunks) {
370
+ const toKeep = new Set(filesToKeep);
371
+ const removedFiles = [];
372
+ await Promise.all(bundledChunks.map(async (file) => {
373
+ if (!toKeep.has(file)) try {
374
+ await unlink(file);
375
+ removedFiles.push(file);
376
+ } catch {}
377
+ }));
378
+ const dirsToRemove = /* @__PURE__ */ new Set();
379
+ for (const file of removedFiles) {
380
+ let dir = path.dirname(file);
381
+ while (dir && dir !== "." && dir !== "/" && !toKeep.has(dir)) {
382
+ dirsToRemove.add(dir);
383
+ dir = path.dirname(dir);
384
+ }
385
+ }
386
+ const sortedDirs = Array.from(dirsToRemove).sort((a, b) => b.length - a.length);
387
+ for (const dir of sortedDirs) try {
388
+ await rmdir(dir);
389
+ } catch {}
390
+ }
391
+
392
+ //#endregion
393
+ //#region src/plugins/bundle/nf3.ts
394
+ function nf3BundlePlugin(pluginConfig) {
395
+ console.warn("[vite-plugin-vercel] bundleStrategy 'nf3' is highly experimental. Use at your own risk; support is not provided for related issues.");
396
+ const envNames = getBuildEnvNames(pluginConfig);
113
397
  const externalsPlugin = externals({});
114
398
  delete externalsPlugin.buildEnd;
115
399
  let buildOutput;
@@ -125,24 +409,31 @@ function bundlePlugin() {
125
409
  return env.config.consumer !== "client";
126
410
  },
127
411
  async writeBundle(_, output) {
128
- const isEdge = this.environment.name === "vercel_edge";
412
+ const isEdge = this.environment.name === envNames.edge;
129
413
  const config = this.environment.config;
130
- const outDir$1 = normalizePath(path.isAbsolute(config.build.outDir) ? config.build.outDir : path.join(config.root, config.build.outDir));
414
+ const outDir = normalizePath(path.isAbsolute(config.build.outDir) ? config.build.outDir : path.join(config.root, config.build.outDir));
131
415
  const entries = Object.entries(output).filter((e) => "isEntry" in e[1] && e[1].isEntry).map((e) => ({
132
416
  name: e[1].name,
133
417
  fileName: e[1].fileName,
134
- outPath: path.join(outDir$1, e[1].fileName)
418
+ outPath: path.join(outDir, e[1].fileName)
135
419
  }));
136
- assert(entries.length > 0, "No entry files found in build output");
420
+ if (entries.length === 0) return;
137
421
  const outPaths = entries.map((entry) => entry.outPath);
138
- const input = Object.fromEntries(outPaths.map((e) => [removeExtension(pathRelativeTo(e, outDir$1)), e]));
422
+ const input = Object.fromEntries(outPaths.map((e) => [removeExtension(pathRelativeTo(e, outDir)), e]));
139
423
  const limit = pLimit(Math.max(1, Math.ceil(cpus().length / 2)));
424
+ const nonVitePlugins = this.environment.config.plugins.filter((p) => {
425
+ return !p.name.startsWith("vite:") && p.name !== "alias" && p.name !== "commonjs" && p.name !== "nitro:externals";
426
+ }).map((x) => {
427
+ const { buildStart, buildEnd, writeBundle, generateBundle, ...rest } = x;
428
+ return rest;
429
+ });
140
430
  const localOutput = (await Promise.all(Object.values(input).map((entryPath) => limit(async () => {
141
- const outDir$2 = path.dirname(entryPath);
431
+ const outDir = path.dirname(entryPath);
142
432
  return { output: (await bundle({
433
+ plugins: nonVitePlugins,
143
434
  isEdge,
144
435
  input: { index: entryPath },
145
- outDir: outDir$2,
436
+ outDir,
146
437
  externals: {
147
438
  conditions: this.environment.config.resolve.conditions,
148
439
  rootDir: this.environment.config.root,
@@ -155,7 +446,7 @@ function bundlePlugin() {
155
446
  }
156
447
  })).output.map((o) => ({
157
448
  ...o,
158
- fileName: path.join(outDir$2, o.fileName)
449
+ fileName: path.join(outDir, o.fileName)
159
450
  })) };
160
451
  })))).flatMap((r) => r.output);
161
452
  buildOutput = buildOutput ? [...buildOutput, ...localOutput] : localOutput;
@@ -169,7 +460,7 @@ function bundle(options) {
169
460
  platform: options.isEdge ? "browser" : "node",
170
461
  external: options.isEdge ? edgeExternal : [],
171
462
  write: true,
172
- plugins: [externals(options.externals)],
463
+ plugins: [...options.plugins, externals(options.externals)],
173
464
  input: options.input,
174
465
  resolve: { conditionNames: options.externals.conditions },
175
466
  output: {
@@ -208,12 +499,13 @@ function removeExtension(subject) {
208
499
  //#region src/plugins/clean-outdir.ts
209
500
  function vercelCleanupPlugin(pluginConfig) {
210
501
  let alreadyRun = false;
502
+ const envNames = getBuildEnvNames(pluginConfig);
211
503
  return {
212
504
  apply: "build",
213
505
  name: "vite-plugin-vercel:cleanup",
214
506
  enforce: "pre",
215
507
  applyToEnvironment(env) {
216
- return env.name === "vercel_client";
508
+ return env.name === envNames.client;
217
509
  },
218
510
  buildStart: {
219
511
  order: "pre",
@@ -251,10 +543,37 @@ function getVcConfig(pluginConfig, filename, options) {
251
543
  });
252
544
  }
253
545
 
546
+ //#endregion
547
+ //#region src/utils/request.ts
548
+ function getOriginalRequest(request) {
549
+ const xNowRouteMatchesHeader = request.headers.get("x-now-route-matches");
550
+ let newUrl = null;
551
+ let newRequest = request;
552
+ if (typeof xNowRouteMatchesHeader === "string") {
553
+ const originalPathBis = new URLSearchParams(xNowRouteMatchesHeader).get("1");
554
+ if (originalPathBis) newUrl = new URL(originalPathBis, request.url).toString();
555
+ }
556
+ if (newUrl) newRequest = new Request(newUrl, {
557
+ method: request.method,
558
+ headers: request.headers,
559
+ body: request.body,
560
+ mode: request.mode,
561
+ credentials: request.credentials,
562
+ cache: request.cache,
563
+ redirect: request.redirect,
564
+ referrer: request.referrer,
565
+ integrity: request.integrity
566
+ });
567
+ return newRequest;
568
+ }
569
+
254
570
  //#endregion
255
571
  //#region src/plugins/loader.ts
256
- const re_DUMMY = /* @__PURE__ */ new RegExp(`__DUMMY__$`);
572
+ const re_DUMMY = new RegExp(`__DUMMY__$`);
573
+ const re_edge = /[?&]vercel_edge\b/;
574
+ const re_node = /[?&]vercel_node\b/;
257
575
  function loaderPlugin(pluginConfig) {
576
+ const envNames = getBuildEnvNames(pluginConfig);
258
577
  let root;
259
578
  return [
260
579
  {
@@ -277,19 +596,57 @@ function loaderPlugin(pluginConfig) {
277
596
  name: "vite-plugin-vercel:load-edge",
278
597
  apply: "build",
279
598
  resolveId: {
280
- filter: { id: [/\?edge$/] },
599
+ filter: { id: re_edge },
600
+ async handler(id, importer, opts) {
601
+ const resolved = await this.resolve(id.replace(re_edge, ""), importer, opts);
602
+ if (!resolved) return null;
603
+ return `${resolved.id}?vercel_edge`;
604
+ }
605
+ },
606
+ load: {
607
+ filter: { id: re_edge },
608
+ async handler(id) {
609
+ const mod = id.replace(re_edge, "");
610
+ return `import mod from ${JSON.stringify(mod)};
611
+
612
+ ${getOriginalRequest.toString()}
613
+
614
+ const fn = (r) => {
615
+ return mod.fetch(getOriginalRequest(r));
616
+ };
617
+
618
+ export default fn`;
619
+ }
620
+ }
621
+ },
622
+ {
623
+ name: "vite-plugin-vercel:load-node",
624
+ apply: "build",
625
+ resolveId: {
626
+ filter: { id: re_node },
281
627
  async handler(id, importer, opts) {
282
- const resolved = await this.resolve(id.replace(/\?edge$/, ""), importer, opts);
628
+ const resolved = await this.resolve(id.replace(re_node, ""), importer, opts);
283
629
  if (!resolved) return null;
284
- return `${resolved.id}?edge`;
630
+ return `${resolved.id}?vercel_node`;
285
631
  }
286
632
  },
287
633
  load: {
288
- filter: { id: [/\?edge$/] },
634
+ filter: { id: re_node },
289
635
  async handler(id) {
290
- const mod = id.replace(/\?edge$/, "");
636
+ const mod = id.replace(re_node, "");
291
637
  return `import mod from ${JSON.stringify(mod)};
292
- const def = mod.fetch;
638
+
639
+ ${getOriginalRequest.toString()}
640
+
641
+ if (mod?.fetch) {
642
+ const ori = mod.fetch;
643
+ mod.fetch = (r) => {
644
+ return ori(getOriginalRequest(r));
645
+ }
646
+ }
647
+
648
+ const def = mod?.server?.nodeHandler ?? mod;
649
+
293
650
  export default def;`;
294
651
  }
295
652
  }
@@ -298,7 +655,7 @@ export default def;`;
298
655
  name: "vite-plugin-vercel:build-functions",
299
656
  apply: "build",
300
657
  applyToEnvironment(env) {
301
- return env.name === "vercel_node" || env.name === "vercel_edge";
658
+ return env.name === envNames.node || env.name === envNames.edge;
302
659
  },
303
660
  config: {
304
661
  order: "post",
@@ -309,28 +666,30 @@ export default def;`;
309
666
  configEnvironment: {
310
667
  order: "post",
311
668
  handler(name) {
312
- const isEdge = name === "vercel_edge";
313
- if (name === "vercel_node" || isEdge) {
669
+ const isEdge = name === envNames.edge;
670
+ if (name === envNames.node || isEdge) {
314
671
  const entries = dedupeRoutes().filter((e) => (e.vercel?.edge ?? false) === isEdge);
315
672
  return { build: { rollupOptions: {
316
- input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?edge` : e.id])),
317
- output: { hoistTransitiveImports: false }
673
+ input: Object.fromEntries(entries.map((e) => [entryDestination(root ?? process.cwd(), e, ".func/index"), isEdge ? `${e.id}?vercel_edge` : `${e.id}?vercel_node`])),
674
+ output: {
675
+ hoistTransitiveImports: false,
676
+ entryFileNames: "[name].js"
677
+ }
318
678
  } } };
319
679
  }
320
680
  }
321
681
  },
322
682
  async buildStart() {
323
- const isEdge = this.environment.name === "vercel_edge";
683
+ const isEdge = this.environment.name === envNames.edge;
324
684
  const nodeVersion = await getNodeVersion(process.cwd());
325
685
  const entries = dedupeRoutes();
326
686
  for (const entry of entries.filter((e) => (e.vercel?.edge ?? false) === isEdge)) {
327
- const isEdge$1 = this.environment.name === "vercel_edge";
328
687
  this.emitFile({
329
688
  type: "asset",
330
689
  fileName: entryDestination(root ?? process.cwd(), entry, ".func/.vc-config.json"),
331
- source: JSON.stringify(getVcConfig(pluginConfig, isEdge$1 ? "index.js" : "index.mjs", {
690
+ source: JSON.stringify(getVcConfig(pluginConfig, isEdge ? "index.js" : "index.mjs", {
332
691
  nodeVersion,
333
- edge: isEdge$1,
692
+ edge: isEdge,
334
693
  streaming: entry.vercel?.streaming
335
694
  }), void 0, 2)
336
695
  });
@@ -340,8 +699,8 @@ export default def;`;
340
699
  source: JSON.stringify(vercelOutputPrerenderConfigSchema.parse(entry.vercel.isr), void 0, 2)
341
700
  });
342
701
  pluginConfig.rewrites ??= [];
343
- for (const pattern of [entry.pattern].flat()) {
344
- const source = toPathToRegexpV6(fromRou3(pattern));
702
+ for (const ir of sortRoutes([entry.route].flat().map((p) => fromRou3(p)))) {
703
+ const source = toPathToRegexpV6(ir);
345
704
  pluginConfig.rewrites.push({
346
705
  enforce: entry.vercel?.enforce,
347
706
  source,
@@ -367,11 +726,12 @@ export default def;`;
367
726
 
368
727
  //#endregion
369
728
  //#region src/plugins/react-edge.ts
370
- function reactEdgePlugin() {
729
+ function reactEdgePlugin(pluginConfig) {
730
+ const envNames = getBuildEnvNames(pluginConfig);
371
731
  return {
372
732
  name: "vite-plugin-vercel:react-edge",
373
733
  applyToEnvironment(env) {
374
- return env.name === "vercel_edge";
734
+ return env.name === envNames.edge;
375
735
  },
376
736
  resolveId: {
377
737
  order: "pre",
@@ -397,7 +757,10 @@ function getConfig(pluginConfig) {
397
757
  const { routes, error } = getTransformedRoutes({
398
758
  cleanUrls: pluginConfig.cleanUrls ?? true,
399
759
  trailingSlash: pluginConfig.trailingSlash,
400
- rewrites: reorderEnforce(_rewrites),
760
+ rewrites: reorderEnforce(_rewrites.map((r) => {
761
+ if (r.source === "/:_1*") r.source = "(.*)";
762
+ return r;
763
+ })),
401
764
  redirects: pluginConfig.redirects ? reorderEnforce(pluginConfig.redirects) : void 0,
402
765
  headers: pluginConfig.headers
403
766
  });
@@ -423,6 +786,7 @@ function getConfig(pluginConfig) {
423
786
  routes: buildRoutes
424
787
  }]
425
788
  });
789
+ for (const route of cleanRoutes) wrapRouteInParentheses(route);
426
790
  return vercelOutputConfigSchema.parse({
427
791
  version: 3,
428
792
  ...pluginConfig.config,
@@ -430,74 +794,73 @@ function getConfig(pluginConfig) {
430
794
  overrides: { ...pluginConfig.config?.overrides }
431
795
  });
432
796
  }
797
+ function wrapRouteInParentheses(route) {
798
+ if (!route.src || !route.dest || route.src.match(/^\(.*\)$/) || route.src.match(/^\^\(.*\)\$$/)) return;
799
+ route.src = `(${route.src})`;
800
+ }
433
801
 
434
802
  //#endregion
435
803
  //#region src/utils/const.ts
436
804
  const virtualEntry = "virtual:vite-plugin-vercel:entry";
437
805
 
438
- //#endregion
439
- //#region src/utils/edge.ts
440
- const edgeConditions = [
441
- "edge-light",
442
- "worker",
443
- "browser",
444
- "module",
445
- "import",
446
- "default"
447
- ];
448
-
449
806
  //#endregion
450
807
  //#region src/plugins/setupEnvs.ts
451
808
  const outDir = path.posix.join(process.cwd(), ".vercel/output");
452
809
  const DUMMY = "__DUMMY__";
453
810
  let injected = false;
454
811
  function setupEnvs(pluginConfig) {
812
+ const envNames = getBuildEnvNames(pluginConfig);
455
813
  return [
456
814
  {
457
815
  name: "vite-plugin-vercel:setup-envs",
458
816
  buildApp: {
459
817
  order: "post",
460
818
  async handler(builder) {
461
- try {
462
- await builder.build(builder.environments.vercel_client);
819
+ if (!builder.environments[envNames.client].isBuilt) try {
820
+ await builder.build(builder.environments[envNames.client]);
463
821
  } catch (e) {
464
822
  if (e instanceof Error && e.message.includes(`Could not resolve entry module "index.html"`)) {} else throw e;
465
823
  }
466
- await builder.build(builder.environments.vercel_edge);
467
- await builder.build(builder.environments.vercel_node);
824
+ if (envNames.edge !== false && !builder.environments[envNames.edge].isBuilt) await builder.build(builder.environments[envNames.edge]);
825
+ if (!builder.environments[envNames.node].isBuilt) await builder.build(builder.environments[envNames.node]);
468
826
  }
469
827
  },
470
- config() {
471
- if (!injected) {
472
- injected = true;
473
- if (pluginConfig.entries) store.entries.push(...pluginConfig.entries);
828
+ config: {
829
+ order: "post",
830
+ handler() {
831
+ if (!injected) {
832
+ injected = true;
833
+ if (pluginConfig.entries) pluginConfig.entries.forEach((entry) => {
834
+ addEntry(entry);
835
+ });
836
+ }
837
+ const outDirOverride = pluginConfig.outDir ? { build: { outDir: pluginConfig.outDir } } : {};
838
+ const environments = {};
839
+ if (envNames.client) environments[envNames.client] = {
840
+ build: {
841
+ outDir: path.join(pluginConfig.outDir ?? outDir, "static"),
842
+ copyPublicDir: true,
843
+ rollupOptions: { input: getDummyInput() }
844
+ },
845
+ consumer: "client"
846
+ };
847
+ if (envNames.edge) environments[envNames.edge] = createVercelEnvironmentOptions(outDirOverride);
848
+ if (envNames.node) environments[envNames.node] = createVercelEnvironmentOptions(outDirOverride);
849
+ return {
850
+ environments,
851
+ builder: {}
852
+ };
474
853
  }
475
- const outDirOverride = pluginConfig.outDir ? { build: { outDir: pluginConfig.outDir } } : {};
476
- return {
477
- environments: {
478
- vercel_edge: createVercelEnvironmentOptions(outDirOverride),
479
- vercel_node: createVercelEnvironmentOptions(outDirOverride),
480
- vercel_client: {
481
- build: {
482
- outDir: path.join(pluginConfig.outDir ?? outDir, "static"),
483
- copyPublicDir: true,
484
- rollupOptions: { input: getDummyInput() }
485
- },
486
- consumer: "client"
487
- }
488
- },
489
- builder: {}
490
- };
491
854
  },
492
855
  sharedDuringBuild: true
493
856
  },
494
857
  {
495
858
  name: "vite-plugin-vercel:setup-envs:vercel_edge",
496
859
  applyToEnvironment(env) {
497
- return env.name === "vercel_edge";
860
+ return env.name === envNames.edge;
498
861
  },
499
862
  configEnvironment(name, config, env) {
500
- if (name !== "vercel_edge") return;
863
+ if (name !== envNames.edge) return;
501
864
  return {
502
865
  resolve: {
503
866
  external: edgeExternal,
@@ -524,8 +887,8 @@ function setupEnvs(pluginConfig) {
524
887
  },
525
888
  generateBundle: {
526
889
  order: "post",
527
- async handler(_opts, bundle$1) {
528
- cleanupDummy(bundle$1);
890
+ async handler(_opts, bundle) {
891
+ cleanupDummy(bundle);
529
892
  }
530
893
  },
531
894
  sharedDuringBuild: true
@@ -533,16 +896,16 @@ function setupEnvs(pluginConfig) {
533
896
  {
534
897
  name: "vite-plugin-vercel:setup-envs:vercel_node",
535
898
  applyToEnvironment(env) {
536
- return env.name === "vercel_node";
899
+ return env.name === envNames.node;
537
900
  },
538
901
  configEnvironment(name, config) {
539
- if (name !== "vercel_node") return;
902
+ if (name !== envNames.node) return;
540
903
  return { optimizeDeps: { ...config.optimizeDeps } };
541
904
  },
542
905
  generateBundle: {
543
906
  order: "post",
544
- async handler(_opts, bundle$1) {
545
- cleanupDummy(bundle$1);
907
+ async handler(_opts, bundle) {
908
+ cleanupDummy(bundle);
546
909
  this.emitFile({
547
910
  type: "asset",
548
911
  fileName: "config.json",
@@ -555,10 +918,10 @@ function setupEnvs(pluginConfig) {
555
918
  {
556
919
  name: "vite-plugin-vercel:setup-envs:vercel_client",
557
920
  applyToEnvironment(env) {
558
- return env.name === "vercel_client";
921
+ return env.name === envNames.client;
559
922
  },
560
- generateBundle: { async handler(_opts, bundle$1) {
561
- cleanupDummy(bundle$1);
923
+ generateBundle: { async handler(_opts, bundle) {
924
+ cleanupDummy(bundle);
562
925
  const topLevelConfig = this.environment.getTopLevelConfig();
563
926
  const clientEnv = topLevelConfig.environments.client;
564
927
  if (clientEnv) try {
@@ -589,7 +952,9 @@ function createVercelEnvironmentOptions(overrides) {
589
952
  rollupOptions: {
590
953
  input: getDummyInput(),
591
954
  output: {
592
- sanitizeFileName: false,
955
+ sanitizeFileName: (filename) => {
956
+ return filename.replace("\0", "_");
957
+ },
593
958
  sourcemap: false
594
959
  }
595
960
  },
@@ -604,26 +969,25 @@ function createVercelEnvironmentOptions(overrides) {
604
969
  function getDummyInput() {
605
970
  return { [DUMMY]: `${virtualEntry}:${DUMMY}` };
606
971
  }
607
- function cleanupDummy(bundle$1) {
608
- const dummy = Object.keys(bundle$1).find((key) => key.includes("_DUMMY_"));
609
- if (dummy) delete bundle$1[dummy];
972
+ function cleanupDummy(bundle) {
973
+ const dummy = Object.keys(bundle).find((key) => key.includes("_DUMMY_"));
974
+ if (dummy) delete bundle[dummy];
610
975
  }
611
976
 
612
977
  //#endregion
613
978
  //#region src/plugins/index.ts
614
979
  function vercel(pluginConfig = {}) {
615
980
  return [
616
- reactEdgePlugin(),
617
- vercelCleanupPlugin(),
981
+ reactEdgePlugin(pluginConfig),
982
+ vercelCleanupPlugin(pluginConfig),
618
983
  apiPlugin(pluginConfig),
619
984
  ...setupEnvs(pluginConfig),
620
985
  ...loaderPlugin(pluginConfig),
621
- ...bundlePlugin(),
986
+ ...pluginConfig?.bundleStrategy === "nf3" ? nf3BundlePlugin(pluginConfig) : basicBundlePlugin(pluginConfig),
622
987
  catchAll(),
623
988
  devServer()
624
989
  ];
625
990
  }
626
- var plugins_default = vercel;
627
991
 
628
992
  //#endregion
629
- export { plugins_default as default, vercel };
993
+ export { vercel as default, vercel };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-vercel",
3
- "version": "11.0.0-beta.2",
3
+ "version": "11.0.0-beta.20",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -26,29 +26,30 @@
26
26
  "@types/node": "^22.19.3",
27
27
  "@universal-middleware/express": "^0.4.22",
28
28
  "@vercel/node": "^5.5.15",
29
- "tsdown": "^0.18.4",
29
+ "tsdown": "^0.20.3",
30
30
  "typescript": "^5.9.3",
31
31
  "vite": "^7.2.4",
32
32
  "vitest": "^4.0.16"
33
33
  },
34
34
  "dependencies": {
35
35
  "@manypkg/find-root": "^3.1.0",
36
- "@universal-deploy/store": "^0.0.2",
36
+ "@universal-deploy/store": "^0.1.3",
37
37
  "@universal-middleware/core": "^0.4.13",
38
38
  "@universal-middleware/vercel": "^0.4.29",
39
39
  "@vercel/build-utils": "^13.2.3",
40
- "@vercel/nft": "^1.1.1",
40
+ "@vercel/nft": "^1.2.0",
41
41
  "@vercel/routing-utils": "^5.3.1",
42
- "@vite-plugin-vercel/schemas": "latest",
43
42
  "convert-route": "^1.0.0",
44
43
  "fast-glob": "^3.3.3",
45
44
  "magicast": "^0.5.1",
46
- "nf3": "^0.3.1",
45
+ "nf3": "^0.3.4",
46
+ "oxc-transform": "^0.108.0",
47
47
  "p-limit": "^7.2.0",
48
48
  "path-to-regexp": "^8.3.0",
49
- "rolldown": "^1.0.0-beta.58",
49
+ "rolldown": "^1.0.0-rc.4",
50
50
  "strip-ansi": "^7.1.2",
51
- "vite-plugin-wasm": "^3.5.0"
51
+ "vite-plugin-wasm": "^3.5.0",
52
+ "@vite-plugin-vercel/schemas": "^1.0.0"
52
53
  },
53
54
  "scripts": {
54
55
  "dev": "tsdown --watch",
@@ -1,70 +0,0 @@
1
- //#region src/utils/assert.ts
2
- function assert(condition, errorMessage) {
3
- if (condition) return;
4
- throw new Error(`[vite-plugin-vercel] ${errorMessage}`);
5
- }
6
-
7
- //#endregion
8
- //#region src/api.ts
9
- function createAPI(outfiles, pluginConfig) {
10
- return {
11
- getOutFiles() {
12
- return outfiles;
13
- },
14
- get config() {
15
- pluginConfig.config ??= {};
16
- return pluginConfig.config;
17
- },
18
- get defaultMaxDuration() {
19
- return pluginConfig.defaultMaxDuration;
20
- },
21
- set defaultMaxDuration(value) {
22
- pluginConfig.defaultMaxDuration = value;
23
- },
24
- get expiration() {
25
- return pluginConfig.expiration;
26
- },
27
- set expiration(value) {
28
- pluginConfig.expiration = value;
29
- },
30
- get rewrites() {
31
- pluginConfig.rewrites ??= [];
32
- return pluginConfig.rewrites;
33
- },
34
- get headers() {
35
- pluginConfig.headers ??= [];
36
- return pluginConfig.headers;
37
- },
38
- get redirects() {
39
- pluginConfig.redirects ??= [];
40
- return pluginConfig.redirects;
41
- },
42
- get cleanUrls() {
43
- return pluginConfig.cleanUrls;
44
- },
45
- set cleanUrls(value) {
46
- pluginConfig.cleanUrls = value;
47
- },
48
- get trailingSlash() {
49
- return pluginConfig.trailingSlash;
50
- },
51
- set trailingSlash(value) {
52
- pluginConfig.trailingSlash = value;
53
- },
54
- get defaultSupportsResponseStreaming() {
55
- return pluginConfig.defaultSupportsResponseStreaming;
56
- },
57
- set defaultSupportsResponseStreaming(value) {
58
- pluginConfig.defaultSupportsResponseStreaming = value;
59
- }
60
- };
61
- }
62
- function getVercelAPI(pluginContextOrServer) {
63
- const vpv = ("environment" in pluginContextOrServer ? pluginContextOrServer.environment.config : pluginContextOrServer.config).plugins.find((p) => p.name === "vite-plugin-vercel:api");
64
- assert(vpv, "Could not find vite-plugin-vercel:api plugin");
65
- assert(vpv.api, "Missing `api`. Make sure vite-plugin-vercel is up-to-date");
66
- return vpv.api("environment" in pluginContextOrServer ? pluginContextOrServer : void 0);
67
- }
68
-
69
- //#endregion
70
- export { getVercelAPI as n, assert as r, createAPI as t };
File without changes