vite-plugin-vercel 0.1.0 → 0.1.3

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
@@ -2,9 +2,29 @@
2
2
 
3
3
  This is a **Work In Progress** Vercel adapter for [`vite`](https://vitejs.dev/).
4
4
 
5
+ Its purpose is to help you bundle your application in `.vercel` folder as supported by
6
+ [Vercel API v3](https://vercel.com/docs/build-output-api/v3).
7
+
8
+ ## Features
9
+
10
+ - [x] [SSG/Static files support](https://vercel.com/docs/build-output-api/v3#vercel-primitives/static-files)
11
+ - see [`prerender` config](/packages/vercel/src/types.ts#L33)
12
+ - [x] [SSR/Serverless functions support](https://vercel.com/docs/build-output-api/v3#vercel-primitives/serverless-functions)
13
+ - `.[jt]s` files under the `<root>/api` folder of your project are automatically bundled as Serverless functions under `.vercel/output/functions/api/*.func`
14
+ - see [`additionalEndpoints` config](/packages/vercel/src/types.ts#L54)
15
+ - [x] [ISR/Prerender functions support](https://vercel.com/docs/build-output-api/v3#vercel-primitives/prerender-functions)
16
+ - see [`isr` config](/packages/vercel/src/types.ts#L81). Also see implementation of [vite-plugin-ssr](/packages/vite-plugin-ssr/vite-plugin-ssr.ts) for example
17
+ - [ ] [Edge functions support](https://vercel.com/docs/build-output-api/v3#vercel-primitives/edge-functions)
18
+ - [ ] [Images optimization support](https://vercel.com/docs/build-output-api/v3#build-output-configuration/supported-properties/images)
19
+ - [ ] [Preview mode support](https://vercel.com/docs/build-output-api/v3#features/preview-mode)
20
+ - [x] [Advanced config override](/packages/vercel/src/types.ts#L15)
21
+ - [ ] Complete config override
22
+
5
23
  ## Usage
6
24
 
7
- Install as a dev dependency and add it to your Vite config like this:
25
+ First, make sure `ENABLE_VC_BUILD=1` is declared as an Environment Variable in your deployment configuration.
26
+
27
+ Then, install this package as a dev dependency and add it to your Vite config like this:
8
28
 
9
29
  ```ts
10
30
  import { defineConfig } from 'vite';
@@ -21,30 +41,18 @@ export default defineConfig({
21
41
  [vite-plugin-ssr](https://vite-plugin-ssr.com/) will support this plugin when stable.
22
42
  In the meantime, you can add experimental support yourself.
23
43
 
24
- First copy [prerender](../../prerender) folder to the root of your project.
25
- Then, update your vercel config:
44
+ Install `@magne4000/vite-plugin-vercel-ssr` package, and update your vite config:
26
45
 
27
46
  ```ts
28
- // vercel.config.ts
29
- // A TS config is prefered if your project is of { type: "module" }
30
-
31
- import module from 'module';
47
+ // vite.config.ts
32
48
  import { defineConfig } from 'vite';
33
49
  import ssr from 'vite-plugin-ssr/plugin';
34
50
  import vercel from 'vite-plugin-vercel';
35
-
36
- // FIX esbuild bug https://github.com/evanw/esbuild/pull/2067
37
- // probably not necessary when `./prerender/vite-plugin-ssr` will be included in `vite-plugin-ssr`
38
- // eslint-disable-next-line no-undef
39
- globalThis.require = module.createRequire(import.meta.url);
51
+ import vercelSsr from '@magne4000/vite-plugin-vercel-ssr';
40
52
 
41
53
  export default defineConfig(async ({ command, mode }) => {
42
- // Dynamic import to bypass esbuild compilation issue.
43
- // If you are not using ESM, could me move as a top synchronous import
44
- const vitePluginSsrVercelPlugin = await import('./prerender/vite-plugin-ssr');
45
-
46
54
  return {
47
- plugins: [ssr(), vercel(), vitePluginSsrVercelPlugin.default()],
55
+ plugins: [ssr(), vercel(), vercelSsr()],
48
56
  build: {
49
57
  polyfillDynamicImport: false,
50
58
  },
@@ -54,3 +62,11 @@ export default defineConfig(async ({ command, mode }) => {
54
62
  };
55
63
  });
56
64
  ```
65
+
66
+ ### Config
67
+
68
+ See [TS types](/packages/vercel/src/types.ts#L15) for details.
69
+
70
+ ## Demo
71
+
72
+ https://test-vite-vercel-plugin.vercel.app/
package/dist/index.cjs CHANGED
@@ -1,38 +1,10 @@
1
+ "use strict";
1
2
  var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
- var __defProps = Object.defineProperties;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
6
  var __getProtoOf = Object.getPrototypeOf;
9
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
11
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
12
- var __spreadValues = (a, b) => {
13
- for (var prop in b || (b = {}))
14
- if (__hasOwnProp.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- if (__getOwnPropSymbols)
17
- for (var prop of __getOwnPropSymbols(b)) {
18
- if (__propIsEnum.call(b, prop))
19
- __defNormalProp(a, prop, b[prop]);
20
- }
21
- return a;
22
- };
23
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
24
- var __objRest = (source, exclude) => {
25
- var target = {};
26
- for (var prop in source)
27
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
28
- target[prop] = source[prop];
29
- if (source != null && __getOwnPropSymbols)
30
- for (var prop of __getOwnPropSymbols(source)) {
31
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
32
- target[prop] = source[prop];
33
- }
34
- return target;
35
- };
36
8
  var __export = (target, all) => {
37
9
  for (var name in all)
38
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -73,9 +45,9 @@ function getOutput(config, suffix) {
73
45
  var _a, _b;
74
46
  return import_path.default.join(((_a = config.vercel) == null ? void 0 : _a.outDir) ? "" : getRoot(config), ((_b = config.vercel) == null ? void 0 : _b.outDir) ?? ".vercel/output", suffix ?? "");
75
47
  }
76
- function pathRelativeToApi(filePath, config) {
48
+ function pathRelativeTo(filePath, config, rel) {
77
49
  const root = getRoot(config);
78
- return (0, import_vite.normalizePath)(import_path.default.relative(import_path.default.join(root, "api"), filePath));
50
+ return (0, import_vite.normalizePath)(import_path.default.relative(import_path.default.join(root, rel), filePath));
79
51
  }
80
52
  async function copyDir(src, dest) {
81
53
  await import_promises.default.mkdir(dest, { recursive: true });
@@ -171,29 +143,51 @@ var vercelOutputConfigSchema = import_zod.z.object({
171
143
  // src/config.ts
172
144
  var import_promises2 = __toESM(require("fs/promises"), 1);
173
145
  var import_routing_utils = require("@vercel/routing-utils");
174
- function getConfig(resolvedConfig, config) {
175
- var _a, _b, _c, _d, _e;
176
- const { routes } = (0, import_routing_utils.getTransformedRoutes)({
146
+ function reorderEnforce(arr) {
147
+ return [
148
+ ...arr.filter((r) => r.enforce === "pre"),
149
+ ...arr.filter((r) => !r.enforce),
150
+ ...arr.filter((r) => r.enforce === "post")
151
+ ];
152
+ }
153
+ function getConfig(resolvedConfig, rewrites, overrides) {
154
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
155
+ const _rewrites = [
156
+ ...((_a = resolvedConfig.vercel) == null ? void 0 : _a.rewrites) ?? [],
157
+ ...rewrites ?? []
158
+ ];
159
+ const { routes, error } = (0, import_routing_utils.getTransformedRoutes)({
177
160
  nowConfig: {
178
- cleanUrls: true
161
+ cleanUrls: ((_b = resolvedConfig.vercel) == null ? void 0 : _b.cleanUrls) ?? true,
162
+ trailingSlash: (_c = resolvedConfig.vercel) == null ? void 0 : _c.trailingSlash,
163
+ rewrites: reorderEnforce(_rewrites),
164
+ redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0
179
165
  }
180
166
  });
181
- return vercelOutputConfigSchema.parse(__spreadProps(__spreadValues({
182
- version: 3
183
- }, (_a = resolvedConfig.vercel) == null ? void 0 : _a.config), {
167
+ if (error) {
168
+ throw error;
169
+ }
170
+ if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0) {
171
+ console.warn("It is discouraged to use `vercel.config.routes` to override routes. Prefer using `vercel.rewrites` and `vercel.redirects`.");
172
+ }
173
+ return vercelOutputConfigSchema.parse({
174
+ version: 3,
175
+ ...(_h = resolvedConfig.vercel) == null ? void 0 : _h.config,
184
176
  routes: [
185
177
  ...routes ?? [],
186
- ...(config == null ? void 0 : config.routes) ?? [],
187
- ...((_c = (_b = resolvedConfig.vercel) == null ? void 0 : _b.config) == null ? void 0 : _c.routes) ?? []
178
+ ...((_j = (_i = resolvedConfig.vercel) == null ? void 0 : _i.config) == null ? void 0 : _j.routes) ?? []
188
179
  ],
189
- overrides: __spreadValues(__spreadValues({}, (_e = (_d = resolvedConfig.vercel) == null ? void 0 : _d.config) == null ? void 0 : _e.overrides), config == null ? void 0 : config.overrides)
190
- }));
180
+ overrides: {
181
+ ...(_l = (_k = resolvedConfig.vercel) == null ? void 0 : _k.config) == null ? void 0 : _l.overrides,
182
+ ...overrides
183
+ }
184
+ });
191
185
  }
192
186
  function getConfigDestination(resolvedConfig) {
193
187
  return import_path2.default.join(getOutput(resolvedConfig), "config.json");
194
188
  }
195
- async function writeConfig(resolvedConfig, config) {
196
- await import_promises2.default.writeFile(getConfigDestination(resolvedConfig), JSON.stringify(getConfig(resolvedConfig, config), void 0, 2), "utf-8");
189
+ async function writeConfig(resolvedConfig, rewrites, overrides) {
190
+ await import_promises2.default.writeFile(getConfigDestination(resolvedConfig), JSON.stringify(getConfig(resolvedConfig, rewrites, overrides), void 0, 2), "utf-8");
197
191
  }
198
192
 
199
193
  // src/build.ts
@@ -243,20 +237,26 @@ var vercelOutputVcConfigSchema = import_zod2.z.union([
243
237
  var import_promises3 = __toESM(require("fs/promises"), 1);
244
238
  function getAdditionalEndpoints(resolvedConfig) {
245
239
  var _a;
246
- return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => __spreadProps(__spreadValues({}, e), {
247
- destination: e.destination + ".func"
240
+ return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => ({
241
+ ...e,
242
+ addRoute: e.addRoute ?? true,
243
+ destination: import_path3.default.resolve("/", e.destination) + ".func"
248
244
  }));
249
245
  }
250
246
  function getEntries(resolvedConfig) {
251
247
  const apiEntries = import_fast_glob.default.sync(`${getRoot(resolvedConfig)}/api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !import_path3.default.basename(filepath).startsWith("_"));
252
- return apiEntries.reduce((entryPoints, filePath) => {
253
- const outFilePath = pathRelativeToApi(filePath, resolvedConfig);
248
+ if (apiEntries.length > 0) {
249
+ console.warn("@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.");
250
+ }
251
+ const otherApiEntries = import_fast_glob.default.sync(`${getRoot(resolvedConfig)}/_api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !import_path3.default.basename(filepath).startsWith("_"));
252
+ return [...apiEntries, ...otherApiEntries].reduce((entryPoints, filePath) => {
253
+ const outFilePath = pathRelativeTo(filePath, resolvedConfig, filePath.includes("/_api/") ? "_api" : "api");
254
254
  const parsed = import_path3.default.parse(outFilePath);
255
- const entry = {
255
+ entryPoints.push({
256
256
  source: filePath,
257
- destination: `api/${import_path3.default.join(parsed.dir, parsed.name)}.func`
258
- };
259
- entryPoints.push(entry);
257
+ destination: `api/${import_path3.default.posix.join(parsed.dir, parsed.name)}.func`,
258
+ addRoute: true
259
+ });
260
260
  return entryPoints;
261
261
  }, getAdditionalEndpoints(resolvedConfig));
262
262
  }
@@ -298,11 +298,21 @@ async function writeVcConfig(resolvedConfig, destination) {
298
298
  shouldAddHelpers: true
299
299
  }), void 0, 2), "utf-8");
300
300
  }
301
+ function getSourceAndDestination(destination) {
302
+ if (destination.startsWith("api/")) {
303
+ return import_path3.default.posix.resolve("/", destination);
304
+ }
305
+ return import_path3.default.posix.resolve("/", destination, ":match*");
306
+ }
301
307
  async function buildEndpoints(resolvedConfig) {
302
308
  const entries = getEntries(resolvedConfig);
303
309
  for (const entry of entries) {
304
310
  await buildFn(resolvedConfig, entry);
305
311
  }
312
+ return entries.filter((e) => e.addRoute !== false).map((e) => e.destination.replace(/\.func$/, "")).map((destination) => ({
313
+ source: getSourceAndDestination(destination),
314
+ destination: getSourceAndDestination(destination)
315
+ }));
306
316
  }
307
317
 
308
318
  // src/prerender.ts
@@ -333,9 +343,10 @@ async function writePrerenderConfig(resolvedConfig, destination, isr) {
333
343
  const parsed = import_path4.default.parse(destination);
334
344
  const outfile = import_path4.default.join(getOutput(resolvedConfig, "functions"), parsed.dir, parsed.name + ".prerender-config.json");
335
345
  await import_promises4.default.mkdir(import_path4.default.join(getOutput(resolvedConfig, "functions"), parsed.dir), { recursive: true });
336
- await import_promises4.default.writeFile(outfile, JSON.stringify(vercelOutputPrerenderConfigSchema.parse(__spreadValues({
337
- group: group++
338
- }, isr)), void 0, 2), "utf-8");
346
+ await import_promises4.default.writeFile(outfile, JSON.stringify(vercelOutputPrerenderConfigSchema.parse({
347
+ group: group++,
348
+ ...isr
349
+ }), void 0, 2), "utf-8");
339
350
  }
340
351
  function getPrerenderSymlinkInfo(resolvedConfig, destination, target) {
341
352
  const parsed = import_path4.default.parse(destination);
@@ -349,8 +360,7 @@ async function buildPrerenderConfigs(resolvedConfig) {
349
360
  const isr = await getIsrConfig(resolvedConfig);
350
361
  const entries = Object.entries(isr);
351
362
  const rewrites = [];
352
- for (const _a of entries) {
353
- const [destination, _b] = _a, _c = _b, { symlink, route } = _c, isr2 = __objRest(_c, ["symlink", "route"]);
363
+ for (const [destination, { symlink, route, ...isr2 }] of entries) {
354
364
  await writePrerenderConfig(resolvedConfig, destination, isr2);
355
365
  if (symlink) {
356
366
  const info = getPrerenderSymlinkInfo(resolvedConfig, destination, symlink);
@@ -358,8 +368,8 @@ async function buildPrerenderConfigs(resolvedConfig) {
358
368
  }
359
369
  if (route) {
360
370
  rewrites.push({
361
- src: `(${route})`,
362
- dest: `${destination}/?__original_path=$1`
371
+ source: `(${route})`,
372
+ destination: `${destination}/?__original_path=$1`
363
373
  });
364
374
  }
365
375
  }
@@ -375,6 +385,7 @@ async function getIsrConfig(resolvedConfig) {
375
385
  }
376
386
 
377
387
  // src/index.ts
388
+ var import_path5 = __toESM(require("path"), 1);
378
389
  function vercelPlugin() {
379
390
  let resolvedConfig;
380
391
  return {
@@ -398,12 +409,13 @@ function vercelPlugin() {
398
409
  var _a;
399
410
  if (!((_a = resolvedConfig.build) == null ? void 0 : _a.ssr))
400
411
  return;
412
+ const userOverrides = await computeStaticHtmlOverrides(resolvedConfig);
401
413
  const overrides = await execPrerender(resolvedConfig);
402
- await buildEndpoints(resolvedConfig);
403
- const rewrites = await buildPrerenderConfigs(resolvedConfig);
404
- await writeConfig(resolvedConfig, {
405
- routes: [{ handle: "filesystem" }, ...rewrites],
406
- overrides
414
+ const rewrites = await buildEndpoints(resolvedConfig);
415
+ rewrites.push(...await buildPrerenderConfigs(resolvedConfig));
416
+ await writeConfig(resolvedConfig, rewrites, {
417
+ ...userOverrides,
418
+ ...overrides
407
419
  });
408
420
  }
409
421
  };
@@ -417,6 +429,28 @@ async function cleanOutputDirectory(resolvedConfig) {
417
429
  force: true
418
430
  });
419
431
  }
432
+ async function computeStaticHtmlOverrides(resolvedConfig) {
433
+ const staticAbsolutePath = getOutput(resolvedConfig, "static");
434
+ const files = await getStaticHtmlFiles(resolvedConfig, staticAbsolutePath);
435
+ return files.reduce((acc, curr) => {
436
+ const relPath = import_path5.default.relative(staticAbsolutePath, curr);
437
+ const parsed = import_path5.default.parse(relPath);
438
+ const pathJoined = import_path5.default.join(parsed.dir, parsed.name);
439
+ acc[relPath] = {
440
+ path: pathJoined
441
+ };
442
+ return acc;
443
+ }, {});
444
+ }
445
+ async function getStaticHtmlFiles(resolvedConfig, src) {
446
+ const entries = await import_promises5.default.readdir(src, { withFileTypes: true });
447
+ const htmlFiles = [];
448
+ for (const entry of entries) {
449
+ const srcPath = import_path5.default.join(src, entry.name);
450
+ entry.isDirectory() ? htmlFiles.push(...await getStaticHtmlFiles(resolvedConfig, srcPath)) : srcPath.endsWith(".html") ? htmlFiles.push(srcPath) : void 0;
451
+ }
452
+ return htmlFiles;
453
+ }
420
454
  function allPlugins() {
421
455
  return [vercelPlugin()];
422
456
  }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ResolvedConfig, Plugin } from 'vite';
2
2
  import { StdinOptions, BuildOptions } from 'esbuild';
3
3
  import { z } from 'zod';
4
+ import { VercelConfig } from '@vercel/routing-utils';
4
5
 
5
6
  /**
6
7
  * Schema definition for `.vercel/output/config.json`
@@ -513,6 +514,12 @@ declare const vercelOutputPrerenderConfigSchema: z.ZodObject<{
513
514
  }>;
514
515
  declare type VercelOutputPrerenderConfig = z.infer<typeof vercelOutputPrerenderConfigSchema>;
515
516
 
517
+ declare type ViteVercelRewrite = NonNullable<VercelConfig['rewrites']>[number] & {
518
+ enforce?: 'pre' | 'post';
519
+ };
520
+ declare type ViteVercelRedirect = NonNullable<VercelConfig['redirects']>[number] & {
521
+ enforce?: 'pre' | 'post';
522
+ };
516
523
  interface ViteVercelConfig {
517
524
  /**
518
525
  * How long Functions should be allowed to run for every request in seconds.
@@ -552,6 +559,10 @@ interface ViteVercelConfig {
552
559
  * }
553
560
  * ```
554
561
  */
562
+ rewrites?: ViteVercelRewrite[];
563
+ redirects?: ViteVercelRedirect[];
564
+ cleanUrls?: VercelConfig['cleanUrls'];
565
+ trailingSlash?: VercelConfig['trailingSlash'];
555
566
  additionalEndpoints?: ViteVercelApiEntry[];
556
567
  /**
557
568
  * Advanced configuration to override .vercel/output/config.json
@@ -608,8 +619,13 @@ interface ViteVercelApiEntry {
608
619
  * Override esbuild options
609
620
  */
610
621
  buildOptions?: BuildOptions;
622
+ /**
623
+ * Automatically add a route for the function (mimics defaults Vercel behavior)
624
+ * Set to `false` to disable
625
+ */
626
+ addRoute?: boolean;
611
627
  }
612
628
 
613
629
  declare function allPlugins(): Plugin[];
614
630
 
615
- export { VercelOutputConfig, VercelOutputIsr, VercelOutputPrerenderConfig, VercelOutputVcConfig, ViteVercelApiEntry, ViteVercelConfig, ViteVercelPrerenderFn, ViteVercelPrerenderRoute, allPlugins as default };
631
+ export { VercelOutputConfig, VercelOutputIsr, VercelOutputPrerenderConfig, VercelOutputVcConfig, ViteVercelApiEntry, ViteVercelConfig, ViteVercelPrerenderFn, ViteVercelPrerenderRoute, ViteVercelRedirect, ViteVercelRewrite, allPlugins as default };
package/dist/index.js CHANGED
@@ -1,34 +1,4 @@
1
- var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
- var __spreadValues = (a, b) => {
9
- for (var prop in b || (b = {}))
10
- if (__hasOwnProp.call(b, prop))
11
- __defNormalProp(a, prop, b[prop]);
12
- if (__getOwnPropSymbols)
13
- for (var prop of __getOwnPropSymbols(b)) {
14
- if (__propIsEnum.call(b, prop))
15
- __defNormalProp(a, prop, b[prop]);
16
- }
17
- return a;
18
- };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
- var __objRest = (source, exclude) => {
21
- var target = {};
22
- for (var prop in source)
23
- if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
- target[prop] = source[prop];
25
- if (source != null && __getOwnPropSymbols)
26
- for (var prop of __getOwnPropSymbols(source)) {
27
- if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
- target[prop] = source[prop];
29
- }
30
- return target;
31
- };
1
+ "use strict";
32
2
 
33
3
  // src/index.ts
34
4
  import fs5 from "fs/promises";
@@ -50,9 +20,9 @@ function getOutput(config, suffix) {
50
20
  var _a, _b;
51
21
  return path.join(((_a = config.vercel) == null ? void 0 : _a.outDir) ? "" : getRoot(config), ((_b = config.vercel) == null ? void 0 : _b.outDir) ?? ".vercel/output", suffix ?? "");
52
22
  }
53
- function pathRelativeToApi(filePath, config) {
23
+ function pathRelativeTo(filePath, config, rel) {
54
24
  const root = getRoot(config);
55
- return normalizePath(path.relative(path.join(root, "api"), filePath));
25
+ return normalizePath(path.relative(path.join(root, rel), filePath));
56
26
  }
57
27
  async function copyDir(src, dest) {
58
28
  await fs.mkdir(dest, { recursive: true });
@@ -148,29 +118,51 @@ var vercelOutputConfigSchema = z.object({
148
118
  // src/config.ts
149
119
  import fs2 from "fs/promises";
150
120
  import { getTransformedRoutes } from "@vercel/routing-utils";
151
- function getConfig(resolvedConfig, config) {
152
- var _a, _b, _c, _d, _e;
153
- const { routes } = getTransformedRoutes({
121
+ function reorderEnforce(arr) {
122
+ return [
123
+ ...arr.filter((r) => r.enforce === "pre"),
124
+ ...arr.filter((r) => !r.enforce),
125
+ ...arr.filter((r) => r.enforce === "post")
126
+ ];
127
+ }
128
+ function getConfig(resolvedConfig, rewrites, overrides) {
129
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
130
+ const _rewrites = [
131
+ ...((_a = resolvedConfig.vercel) == null ? void 0 : _a.rewrites) ?? [],
132
+ ...rewrites ?? []
133
+ ];
134
+ const { routes, error } = getTransformedRoutes({
154
135
  nowConfig: {
155
- cleanUrls: true
136
+ cleanUrls: ((_b = resolvedConfig.vercel) == null ? void 0 : _b.cleanUrls) ?? true,
137
+ trailingSlash: (_c = resolvedConfig.vercel) == null ? void 0 : _c.trailingSlash,
138
+ rewrites: reorderEnforce(_rewrites),
139
+ redirects: ((_d = resolvedConfig.vercel) == null ? void 0 : _d.redirects) ? reorderEnforce((_e = resolvedConfig.vercel) == null ? void 0 : _e.redirects) : void 0
156
140
  }
157
141
  });
158
- return vercelOutputConfigSchema.parse(__spreadProps(__spreadValues({
159
- version: 3
160
- }, (_a = resolvedConfig.vercel) == null ? void 0 : _a.config), {
142
+ if (error) {
143
+ throw error;
144
+ }
145
+ if (((_g = (_f = resolvedConfig.vercel) == null ? void 0 : _f.config) == null ? void 0 : _g.routes) && resolvedConfig.vercel.config.routes.length > 0) {
146
+ console.warn("It is discouraged to use `vercel.config.routes` to override routes. Prefer using `vercel.rewrites` and `vercel.redirects`.");
147
+ }
148
+ return vercelOutputConfigSchema.parse({
149
+ version: 3,
150
+ ...(_h = resolvedConfig.vercel) == null ? void 0 : _h.config,
161
151
  routes: [
162
152
  ...routes ?? [],
163
- ...(config == null ? void 0 : config.routes) ?? [],
164
- ...((_c = (_b = resolvedConfig.vercel) == null ? void 0 : _b.config) == null ? void 0 : _c.routes) ?? []
153
+ ...((_j = (_i = resolvedConfig.vercel) == null ? void 0 : _i.config) == null ? void 0 : _j.routes) ?? []
165
154
  ],
166
- overrides: __spreadValues(__spreadValues({}, (_e = (_d = resolvedConfig.vercel) == null ? void 0 : _d.config) == null ? void 0 : _e.overrides), config == null ? void 0 : config.overrides)
167
- }));
155
+ overrides: {
156
+ ...(_l = (_k = resolvedConfig.vercel) == null ? void 0 : _k.config) == null ? void 0 : _l.overrides,
157
+ ...overrides
158
+ }
159
+ });
168
160
  }
169
161
  function getConfigDestination(resolvedConfig) {
170
162
  return path2.join(getOutput(resolvedConfig), "config.json");
171
163
  }
172
- async function writeConfig(resolvedConfig, config) {
173
- await fs2.writeFile(getConfigDestination(resolvedConfig), JSON.stringify(getConfig(resolvedConfig, config), void 0, 2), "utf-8");
164
+ async function writeConfig(resolvedConfig, rewrites, overrides) {
165
+ await fs2.writeFile(getConfigDestination(resolvedConfig), JSON.stringify(getConfig(resolvedConfig, rewrites, overrides), void 0, 2), "utf-8");
174
166
  }
175
167
 
176
168
  // src/build.ts
@@ -220,20 +212,26 @@ var vercelOutputVcConfigSchema = z2.union([
220
212
  import fs3 from "fs/promises";
221
213
  function getAdditionalEndpoints(resolvedConfig) {
222
214
  var _a;
223
- return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => __spreadProps(__spreadValues({}, e), {
224
- destination: e.destination + ".func"
215
+ return (((_a = resolvedConfig.vercel) == null ? void 0 : _a.additionalEndpoints) ?? []).map((e) => ({
216
+ ...e,
217
+ addRoute: e.addRoute ?? true,
218
+ destination: path3.resolve("/", e.destination) + ".func"
225
219
  }));
226
220
  }
227
221
  function getEntries(resolvedConfig) {
228
222
  const apiEntries = glob.sync(`${getRoot(resolvedConfig)}/api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path3.basename(filepath).startsWith("_"));
229
- return apiEntries.reduce((entryPoints, filePath) => {
230
- const outFilePath = pathRelativeToApi(filePath, resolvedConfig);
223
+ if (apiEntries.length > 0) {
224
+ console.warn("@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.");
225
+ }
226
+ const otherApiEntries = glob.sync(`${getRoot(resolvedConfig)}/_api/**/*.*([a-zA-Z0-9])`).filter((filepath) => !path3.basename(filepath).startsWith("_"));
227
+ return [...apiEntries, ...otherApiEntries].reduce((entryPoints, filePath) => {
228
+ const outFilePath = pathRelativeTo(filePath, resolvedConfig, filePath.includes("/_api/") ? "_api" : "api");
231
229
  const parsed = path3.parse(outFilePath);
232
- const entry = {
230
+ entryPoints.push({
233
231
  source: filePath,
234
- destination: `api/${path3.join(parsed.dir, parsed.name)}.func`
235
- };
236
- entryPoints.push(entry);
232
+ destination: `api/${path3.posix.join(parsed.dir, parsed.name)}.func`,
233
+ addRoute: true
234
+ });
237
235
  return entryPoints;
238
236
  }, getAdditionalEndpoints(resolvedConfig));
239
237
  }
@@ -275,11 +273,21 @@ async function writeVcConfig(resolvedConfig, destination) {
275
273
  shouldAddHelpers: true
276
274
  }), void 0, 2), "utf-8");
277
275
  }
276
+ function getSourceAndDestination(destination) {
277
+ if (destination.startsWith("api/")) {
278
+ return path3.posix.resolve("/", destination);
279
+ }
280
+ return path3.posix.resolve("/", destination, ":match*");
281
+ }
278
282
  async function buildEndpoints(resolvedConfig) {
279
283
  const entries = getEntries(resolvedConfig);
280
284
  for (const entry of entries) {
281
285
  await buildFn(resolvedConfig, entry);
282
286
  }
287
+ return entries.filter((e) => e.addRoute !== false).map((e) => e.destination.replace(/\.func$/, "")).map((destination) => ({
288
+ source: getSourceAndDestination(destination),
289
+ destination: getSourceAndDestination(destination)
290
+ }));
283
291
  }
284
292
 
285
293
  // src/prerender.ts
@@ -310,9 +318,10 @@ async function writePrerenderConfig(resolvedConfig, destination, isr) {
310
318
  const parsed = path4.parse(destination);
311
319
  const outfile = path4.join(getOutput(resolvedConfig, "functions"), parsed.dir, parsed.name + ".prerender-config.json");
312
320
  await fs4.mkdir(path4.join(getOutput(resolvedConfig, "functions"), parsed.dir), { recursive: true });
313
- await fs4.writeFile(outfile, JSON.stringify(vercelOutputPrerenderConfigSchema.parse(__spreadValues({
314
- group: group++
315
- }, isr)), void 0, 2), "utf-8");
321
+ await fs4.writeFile(outfile, JSON.stringify(vercelOutputPrerenderConfigSchema.parse({
322
+ group: group++,
323
+ ...isr
324
+ }), void 0, 2), "utf-8");
316
325
  }
317
326
  function getPrerenderSymlinkInfo(resolvedConfig, destination, target) {
318
327
  const parsed = path4.parse(destination);
@@ -326,8 +335,7 @@ async function buildPrerenderConfigs(resolvedConfig) {
326
335
  const isr = await getIsrConfig(resolvedConfig);
327
336
  const entries = Object.entries(isr);
328
337
  const rewrites = [];
329
- for (const _a of entries) {
330
- const [destination, _b] = _a, _c = _b, { symlink, route } = _c, isr2 = __objRest(_c, ["symlink", "route"]);
338
+ for (const [destination, { symlink, route, ...isr2 }] of entries) {
331
339
  await writePrerenderConfig(resolvedConfig, destination, isr2);
332
340
  if (symlink) {
333
341
  const info = getPrerenderSymlinkInfo(resolvedConfig, destination, symlink);
@@ -335,8 +343,8 @@ async function buildPrerenderConfigs(resolvedConfig) {
335
343
  }
336
344
  if (route) {
337
345
  rewrites.push({
338
- src: `(${route})`,
339
- dest: `${destination}/?__original_path=$1`
346
+ source: `(${route})`,
347
+ destination: `${destination}/?__original_path=$1`
340
348
  });
341
349
  }
342
350
  }
@@ -352,6 +360,7 @@ async function getIsrConfig(resolvedConfig) {
352
360
  }
353
361
 
354
362
  // src/index.ts
363
+ import path5 from "path";
355
364
  function vercelPlugin() {
356
365
  let resolvedConfig;
357
366
  return {
@@ -375,12 +384,13 @@ function vercelPlugin() {
375
384
  var _a;
376
385
  if (!((_a = resolvedConfig.build) == null ? void 0 : _a.ssr))
377
386
  return;
387
+ const userOverrides = await computeStaticHtmlOverrides(resolvedConfig);
378
388
  const overrides = await execPrerender(resolvedConfig);
379
- await buildEndpoints(resolvedConfig);
380
- const rewrites = await buildPrerenderConfigs(resolvedConfig);
381
- await writeConfig(resolvedConfig, {
382
- routes: [{ handle: "filesystem" }, ...rewrites],
383
- overrides
389
+ const rewrites = await buildEndpoints(resolvedConfig);
390
+ rewrites.push(...await buildPrerenderConfigs(resolvedConfig));
391
+ await writeConfig(resolvedConfig, rewrites, {
392
+ ...userOverrides,
393
+ ...overrides
384
394
  });
385
395
  }
386
396
  };
@@ -394,6 +404,28 @@ async function cleanOutputDirectory(resolvedConfig) {
394
404
  force: true
395
405
  });
396
406
  }
407
+ async function computeStaticHtmlOverrides(resolvedConfig) {
408
+ const staticAbsolutePath = getOutput(resolvedConfig, "static");
409
+ const files = await getStaticHtmlFiles(resolvedConfig, staticAbsolutePath);
410
+ return files.reduce((acc, curr) => {
411
+ const relPath = path5.relative(staticAbsolutePath, curr);
412
+ const parsed = path5.parse(relPath);
413
+ const pathJoined = path5.join(parsed.dir, parsed.name);
414
+ acc[relPath] = {
415
+ path: pathJoined
416
+ };
417
+ return acc;
418
+ }, {});
419
+ }
420
+ async function getStaticHtmlFiles(resolvedConfig, src) {
421
+ const entries = await fs5.readdir(src, { withFileTypes: true });
422
+ const htmlFiles = [];
423
+ for (const entry of entries) {
424
+ const srcPath = path5.join(src, entry.name);
425
+ entry.isDirectory() ? htmlFiles.push(...await getStaticHtmlFiles(resolvedConfig, srcPath)) : srcPath.endsWith(".html") ? htmlFiles.push(srcPath) : void 0;
426
+ }
427
+ return htmlFiles;
428
+ }
397
429
  function allPlugins() {
398
430
  return [vercelPlugin()];
399
431
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-vercel",
3
- "version": "0.1.0",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -23,20 +23,20 @@
23
23
  "vite": "^2.9.9"
24
24
  },
25
25
  "devDependencies": {
26
- "@types/node": "^17.0.34",
27
- "@typescript-eslint/eslint-plugin": "^5.24.0",
28
- "@typescript-eslint/parser": "^5.24.0",
29
- "eslint": "^8.15.0",
30
- "eslint-plugin-solid": "^0.4.7",
31
- "tsup": "^5.12.8",
32
- "typescript": "^4.6.4"
26
+ "@types/node": "^16.11.41",
27
+ "@typescript-eslint/eslint-plugin": "^5.29.0",
28
+ "@typescript-eslint/parser": "^5.29.0",
29
+ "eslint": "^8.18.0",
30
+ "tsup": "^6.1.2",
31
+ "typescript": "^4.7.4",
32
+ "vite": "^2.9.12"
33
33
  },
34
34
  "dependencies": {
35
- "@brillout/libassert": "^0.5.6",
36
- "@vercel/routing-utils": "^1.13.2",
37
- "esbuild": "^0.14.39",
35
+ "@brillout/libassert": "^0.5.8",
36
+ "@vercel/routing-utils": "^1.13.4",
37
+ "esbuild": "^0.14.47",
38
38
  "fast-glob": "^3.2.11",
39
- "zod": "^3.16.0"
39
+ "zod": "^3.17.3"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsup",