waku 1.0.0-alpha.9 → 1.0.0-beta.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.
Files changed (92) hide show
  1. package/README.md +35 -24
  2. package/dist/adapters/cloudflare.js +28 -14
  3. package/dist/adapters/cloudflare.js.map +1 -1
  4. package/dist/adapters/netlify-build-enhancer.js +4 -4
  5. package/dist/adapters/netlify-build-enhancer.js.map +1 -1
  6. package/dist/adapters/vercel-build-enhancer.js +3 -2
  7. package/dist/adapters/vercel-build-enhancer.js.map +1 -1
  8. package/dist/lib/types.d.ts +5 -4
  9. package/dist/lib/types.js.map +1 -1
  10. package/dist/lib/utils/managed.js +10 -11
  11. package/dist/lib/utils/managed.js.map +1 -1
  12. package/dist/lib/utils/path.js +4 -3
  13. package/dist/lib/utils/path.js.map +1 -1
  14. package/dist/lib/utils/prefetch.d.ts +23 -0
  15. package/dist/lib/utils/prefetch.js +49 -0
  16. package/dist/lib/utils/prefetch.js.map +1 -0
  17. package/dist/lib/utils/prune-build.d.ts +29 -0
  18. package/dist/lib/utils/prune-build.js +96 -0
  19. package/dist/lib/utils/prune-build.js.map +1 -0
  20. package/dist/lib/utils/react-debug-channel.d.ts +1 -3
  21. package/dist/lib/utils/react-debug-channel.js +6 -7
  22. package/dist/lib/utils/react-debug-channel.js.map +1 -1
  23. package/dist/lib/utils/render.d.ts +1 -1
  24. package/dist/lib/utils/render.js +20 -3
  25. package/dist/lib/utils/render.js.map +1 -1
  26. package/dist/lib/utils/request.js +36 -0
  27. package/dist/lib/utils/request.js.map +1 -1
  28. package/dist/lib/utils/ssr.js +2 -32
  29. package/dist/lib/utils/ssr.js.map +1 -1
  30. package/dist/lib/vite-entries/entry.browser.js +5 -0
  31. package/dist/lib/vite-entries/entry.browser.js.map +1 -1
  32. package/dist/lib/vite-entries/entry.build.d.ts +3 -1
  33. package/dist/lib/vite-entries/entry.build.js +13 -9
  34. package/dist/lib/vite-entries/entry.build.js.map +1 -1
  35. package/dist/lib/vite-plugins/adapter-alias.d.ts +4 -0
  36. package/dist/lib/vite-plugins/{default-adapter.js → adapter-alias.js} +3 -3
  37. package/dist/lib/vite-plugins/adapter-alias.js.map +1 -0
  38. package/dist/lib/vite-plugins/{user-entries.d.ts → app-entries.d.ts} +1 -1
  39. package/dist/lib/vite-plugins/{user-entries.js → app-entries.js} +3 -3
  40. package/dist/lib/vite-plugins/app-entries.js.map +1 -0
  41. package/dist/lib/vite-plugins/build-id.d.ts +2 -0
  42. package/dist/lib/vite-plugins/build-id.js +20 -0
  43. package/dist/lib/vite-plugins/build-id.js.map +1 -0
  44. package/dist/lib/vite-plugins/combined-plugins.js +34 -14
  45. package/dist/lib/vite-plugins/combined-plugins.js.map +1 -1
  46. package/dist/lib/vite-plugins/{main.d.ts → environments.d.ts} +1 -1
  47. package/dist/lib/vite-plugins/{main.js → environments.js} +3 -3
  48. package/dist/lib/vite-plugins/environments.js.map +1 -0
  49. package/dist/lib/vite-plugins/html-shell.d.ts +2 -0
  50. package/dist/lib/vite-plugins/{fallback-html.js → html-shell.js} +5 -5
  51. package/dist/lib/vite-plugins/html-shell.js.map +1 -0
  52. package/dist/lib/vite-plugins/rsc-devtools.d.ts +2 -0
  53. package/dist/lib/vite-plugins/{react-debug.js → rsc-devtools.js} +3 -3
  54. package/dist/lib/vite-plugins/rsc-devtools.js.map +1 -0
  55. package/dist/lib/vite-plugins/static-build.d.ts +5 -0
  56. package/dist/lib/vite-plugins/{build-static-files.js → static-build.js} +23 -5
  57. package/dist/lib/vite-plugins/static-build.js.map +1 -0
  58. package/dist/lib/vite-rsc/handler.js +15 -6
  59. package/dist/lib/vite-rsc/handler.js.map +1 -1
  60. package/dist/lib/vite-rsc/ssr.js +2 -2
  61. package/dist/lib/vite-rsc/ssr.js.map +1 -1
  62. package/dist/minimal/client.d.ts +3 -0
  63. package/dist/minimal/client.js +39 -34
  64. package/dist/minimal/client.js.map +1 -1
  65. package/dist/router/client.d.ts +1 -3
  66. package/dist/router/client.js +45 -48
  67. package/dist/router/client.js.map +1 -1
  68. package/dist/router/create-pages.d.ts +36 -2
  69. package/dist/router/create-pages.js +318 -321
  70. package/dist/router/create-pages.js.map +1 -1
  71. package/dist/router/define-router.d.ts +9 -2
  72. package/dist/router/define-router.js +171 -85
  73. package/dist/router/define-router.js.map +1 -1
  74. package/dist/router/fs-router.d.ts +18 -6
  75. package/dist/router/fs-router.js +28 -25
  76. package/dist/router/fs-router.js.map +1 -1
  77. package/dist/router/server.d.ts +1 -0
  78. package/dist/router/server.js.map +1 -1
  79. package/dist/vite-plugins.d.ts +5 -5
  80. package/dist/vite-plugins.js +5 -5
  81. package/dist/vite-plugins.js.map +1 -1
  82. package/package.json +7 -7
  83. package/dist/lib/vite-plugins/build-static-files.d.ts +0 -4
  84. package/dist/lib/vite-plugins/build-static-files.js.map +0 -1
  85. package/dist/lib/vite-plugins/default-adapter.d.ts +0 -4
  86. package/dist/lib/vite-plugins/default-adapter.js.map +0 -1
  87. package/dist/lib/vite-plugins/fallback-html.d.ts +0 -2
  88. package/dist/lib/vite-plugins/fallback-html.js.map +0 -1
  89. package/dist/lib/vite-plugins/main.js.map +0 -1
  90. package/dist/lib/vite-plugins/react-debug.d.ts +0 -2
  91. package/dist/lib/vite-plugins/react-debug.js.map +0 -1
  92. package/dist/lib/vite-plugins/user-entries.js.map +0 -1
package/README.md CHANGED
@@ -15,8 +15,6 @@ visit [waku.gg](https://waku.gg) or `npm create waku@latest`
15
15
 
16
16
  **Waku** _(wah-ku)_ or **わく** is the minimal React framework. It’s lightweight and designed for a fun developer experience, yet supports all the latest React 19 features like server components and actions. Built for marketing sites, headless commerce, and web apps. For large enterprise applications, you may prefer a heavier framework.
17
17
 
18
- > Please try Waku on non-production projects and report any issues you find. Contributors are welcome.
19
-
20
18
  ## Getting started
21
19
 
22
20
  Start a new Waku project with the `create` command for your preferred package manager. It will scaffold a new project with our default [Waku starter](https://github.com/wakujs/waku/tree/main/examples/01_template).
@@ -31,7 +29,7 @@ npm create waku@latest
31
29
  - `waku build` to generate a production build
32
30
  - `waku start` to serve the production build locally
33
31
 
34
- **Node.js version requirement:** `^24.0.0` or `^22.12.0` or `^20.19.0`
32
+ **Node.js version requirement:** `^26.0.0` or `^24.0.0` or `^22.13.0`
35
33
 
36
34
  ## Rendering
37
35
 
@@ -761,7 +759,7 @@ This allows you to have a `dynamic` slice component while keeping the rest of th
761
759
 
762
760
  ### Link
763
761
 
764
- The `<Link />` component should be used for internal links. It accepts a `to` prop for the destination, which is automatically prefetched ahead of the navigation.
762
+ The `<Link />` component should be used for internal links. It accepts a `to` prop for the destination and handles client-side navigation through Waku's router.
765
763
 
766
764
  ```tsx
767
765
  // ./src/pages/index.tsx
@@ -1027,6 +1025,26 @@ export const getConfig = async () => {
1027
1025
  };
1028
1026
  ```
1029
1027
 
1028
+ ## Middleware
1029
+
1030
+ In the default Waku setup, files in `./src/middleware` are automatically loaded as [Hono middleware](https://hono.dev/docs/guides/middleware). Each file should default export a function that returns a `MiddlewareHandler`.
1031
+
1032
+ ```ts
1033
+ // ./src/middleware/logger.ts
1034
+ import type { MiddlewareHandler } from 'hono';
1035
+
1036
+ const logger = (): MiddlewareHandler => {
1037
+ return async (c, next) => {
1038
+ console.log(c.req.method, c.req.path);
1039
+ await next();
1040
+ };
1041
+ };
1042
+
1043
+ export default logger;
1044
+ ```
1045
+
1046
+ If you provide a custom `./src/waku.server.tsx`, pass middleware through the adapter options with `middlewareModules` or `middlewareFns`.
1047
+
1030
1048
  ## Data fetching
1031
1049
 
1032
1050
  ### Server
@@ -1454,10 +1472,9 @@ For advanced users who want to avoid deploying functions, use the server entry f
1454
1472
  import { fsRouter } from 'waku';
1455
1473
  import adapter from 'waku/adapters/vercel';
1456
1474
 
1457
- export default adapter(
1458
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1459
- { static: true },
1460
- );
1475
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1476
+ static: true,
1477
+ });
1461
1478
  ```
1462
1479
 
1463
1480
  ### Netlify
@@ -1479,10 +1496,9 @@ For advanced users who want to avoid deploying functions, use the server entry f
1479
1496
  import { fsRouter } from 'waku';
1480
1497
  import adapter from 'waku/adapters/netlify';
1481
1498
 
1482
- export default adapter(
1483
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1484
- { static: true },
1485
- );
1499
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1500
+ static: true,
1501
+ });
1486
1502
  ```
1487
1503
 
1488
1504
  ### Cloudflare Workers
@@ -1502,10 +1518,9 @@ wrangler deploy
1502
1518
  import { fsRouter } from 'waku';
1503
1519
  import adapter from 'waku/adapters/cloudflare';
1504
1520
 
1505
- export default adapter(
1506
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1507
- { static: true },
1508
- );
1521
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1522
+ static: true,
1523
+ });
1509
1524
  ```
1510
1525
 
1511
1526
  ### Deno Deploy (experimental)
@@ -1516,9 +1531,7 @@ export default adapter(
1516
1531
  import { fsRouter } from 'waku';
1517
1532
  import adapter from 'waku/adapters/deno';
1518
1533
 
1519
- export default adapter(
1520
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1521
- );
1534
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')));
1522
1535
  ```
1523
1536
 
1524
1537
  ```sh
@@ -1534,9 +1547,7 @@ deployctl deploy --prod dist/serve-deno.js --exclude node_modules
1534
1547
  import { fsRouter } from 'waku';
1535
1548
  import adapter from 'waku/adapters/bun';
1536
1549
 
1537
- export default adapter(
1538
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1539
- );
1550
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')));
1540
1551
  ```
1541
1552
 
1542
1553
  ```sh
@@ -1552,8 +1563,8 @@ import { fsRouter } from 'waku';
1552
1563
  import adapter from 'waku/adapters/aws-lambda';
1553
1564
 
1554
1565
  export default adapter(
1555
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1556
- streaming: false, // optional, default is false
1566
+ fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')),
1567
+ { streaming: false }, // optional, default is false
1557
1568
  );
1558
1569
  ```
1559
1570
 
@@ -4,6 +4,12 @@ import { unstable_constants as constants, unstable_consumeMultiplexedStream as c
4
4
  const { DIST_PUBLIC } = constants;
5
5
  const { contextMiddleware, rscMiddleware, middlewareRunner } = honoMiddleware;
6
6
  const DO_NOT_BUNDLE = '';
7
+ const PRUNABLE_KEY_PREFIX = '\0__prunable__/';
8
+ const emptyStream = ()=>new ReadableStream({
9
+ start (controller) {
10
+ controller.close();
11
+ }
12
+ });
7
13
  function isWranglerDev(req) {
8
14
  // This header seems to only be set for production cloudflare workers
9
15
  return !req.headers.get('cf-visitor');
@@ -44,14 +50,15 @@ export default createServerEntryAdapter(({ processRequest, processBuild, setAllE
44
50
  DIST_PUBLIC,
45
51
  serverless: !options?.static
46
52
  };
53
+ const buildBody = ()=>produceMultiplexedStream(async (emitFile)=>{
54
+ await processBuild({
55
+ emitFile,
56
+ unstable_registerPrunableFile: (srcPath)=>emitFile(PRUNABLE_KEY_PREFIX + srcPath, emptyStream())
57
+ });
58
+ });
47
59
  const fetchFn = async (req)=>{
48
60
  if (new URL(req.url).pathname === `/${internalPathToBuildStaticFiles}`) {
49
- const body = produceMultiplexedStream(async (emitFile)=>{
50
- await processBuild({
51
- emitFile
52
- });
53
- });
54
- return new Response(body);
61
+ return new Response(buildBody());
55
62
  }
56
63
  let cloudflareContext;
57
64
  try {
@@ -88,18 +95,25 @@ export default createServerEntryAdapter(({ processRequest, processBuild, setAllE
88
95
  server.middlewares.use(async (_req, res, next)=>{
89
96
  try {
90
97
  const { Readable } = await import(/* @vite-ignore */ DO_NOT_BUNDLE + 'node:stream');
91
- const body = produceMultiplexedStream(async (emitFile)=>{
92
- await processBuild({
93
- emitFile
94
- });
95
- });
96
- Readable.fromWeb(body).pipe(res);
98
+ Readable.fromWeb(buildBody()).pipe(res);
97
99
  } catch (err) {
98
100
  next(err);
99
101
  }
100
102
  });
101
- const response = await fetch(server.baseUrl + internalPathToBuildStaticFiles);
102
- await consumeMultiplexedStream(response.body, utils.emitFile);
103
+ const response = await fetch(server.baseUrl + internalPathToBuildStaticFiles, {
104
+ headers: {
105
+ connection: 'close'
106
+ }
107
+ });
108
+ await consumeMultiplexedStream(response.body, async (key, stream)=>{
109
+ if (key.startsWith(PRUNABLE_KEY_PREFIX)) {
110
+ utils.unstable_registerPrunableFile(key.slice(PRUNABLE_KEY_PREFIX.length));
111
+ return;
112
+ }
113
+ await utils.emitFile(key, stream);
114
+ });
115
+ // https://github.com/nodejs/node/issues/56645
116
+ await new Promise((resolve)=>setTimeout(resolve, 100));
103
117
  await server.close();
104
118
  },
105
119
  buildOptions,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/cloudflare.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono/tiny';\nimport {\n unstable_createServerEntryAdapter as createServerEntryAdapter,\n unstable_startPreviewServer as startPreviewServer,\n} from 'waku/adapter-builders';\nimport {\n unstable_constants as constants,\n unstable_consumeMultiplexedStream as consumeMultiplexedStream,\n unstable_honoMiddleware as honoMiddleware,\n unstable_produceMultiplexedStream as produceMultiplexedStream,\n} from 'waku/internals';\nimport type { BuildOptions } from './cloudflare-build-enhancer.js';\n\nconst { DIST_PUBLIC } = constants;\nconst { contextMiddleware, rscMiddleware, middlewareRunner } = honoMiddleware;\n\nconst DO_NOT_BUNDLE = '';\n\nfunction isWranglerDev(req: Request): boolean {\n // This header seems to only be set for production cloudflare workers\n return !req.headers.get('cf-visitor');\n}\n\nfunction removeGzipEncoding(res: Response): Response {\n const contentType = res.headers.get('content-type');\n if (\n !contentType ||\n contentType.includes('text/html') ||\n contentType.includes('text/plain')\n ) {\n const headers = new Headers(res.headers);\n headers.set('content-encoding', 'Identity');\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n return res;\n}\n\nexport default createServerEntryAdapter(\n (\n { processRequest, processBuild, setAllEnv, config, notFoundHtml },\n options?: {\n static?: boolean;\n handlers?: Record<string, unknown>;\n assetsDir?: string;\n middlewareFns?: (() => MiddlewareHandler)[];\n middlewareModules?: Record<string, () => Promise<unknown>>;\n internalPathToBuildStaticFiles?: string;\n },\n ) => {\n const {\n middlewareFns = [],\n middlewareModules = {},\n internalPathToBuildStaticFiles = '__waku_internal_build_static_files',\n } = options || {};\n const app = new Hono();\n app.notFound((c) => {\n if (notFoundHtml) {\n return c.html(notFoundHtml, 404);\n }\n return c.text('404 Not Found', 404);\n });\n app.use(contextMiddleware());\n for (const middlewareFn of middlewareFns) {\n app.use(middlewareFn());\n }\n app.use(middlewareRunner(middlewareModules as never));\n app.use(rscMiddleware({ processRequest }));\n const buildOptions: BuildOptions = {\n srcDir: config.srcDir,\n distDir: config.distDir,\n DIST_PUBLIC,\n serverless: !options?.static,\n };\n\n const fetchFn = async (req: Request) => {\n if (new URL(req.url).pathname === `/${internalPathToBuildStaticFiles}`) {\n const body = produceMultiplexedStream(async (emitFile) => {\n await processBuild({ emitFile });\n });\n return new Response(body);\n }\n let cloudflareContext;\n try {\n cloudflareContext = await import(\n /* @vite-ignore */ DO_NOT_BUNDLE + 'cloudflare:workers'\n );\n } catch {\n // Not in a Cloudflare environment\n }\n let res: Response | Promise<Response>;\n if (cloudflareContext) {\n const { env, waitUntil, passThroughOnException } = cloudflareContext;\n res = app.fetch(req, env, {\n waitUntil,\n passThroughOnException,\n props: undefined,\n });\n } else {\n res = app.fetch(req);\n }\n // Workaround https://github.com/cloudflare/workers-sdk/issues/6577\n if (import.meta.env?.PROD && isWranglerDev(req)) {\n if ('then' in res) {\n res = res.then((res) => removeGzipEncoding(res));\n } else {\n res = removeGzipEncoding(res);\n }\n }\n return res;\n };\n\n return {\n fetch: fetchFn,\n build: async (utils) => {\n const server = await startPreviewServer();\n // Fallback middleware for the case without @cloudflare/vite-plugin\n server.middlewares.use(async (_req, res, next) => {\n try {\n const { Readable } = await import(\n /* @vite-ignore */ DO_NOT_BUNDLE + 'node:stream'\n );\n const body = produceMultiplexedStream(async (emitFile) => {\n await processBuild({ emitFile });\n });\n Readable.fromWeb(body as never).pipe(res);\n } catch (err) {\n next(err);\n }\n });\n const response = await fetch(\n server.baseUrl + internalPathToBuildStaticFiles,\n );\n await consumeMultiplexedStream(response.body!, utils.emitFile);\n await server.close();\n },\n buildOptions,\n buildEnhancers: ['waku/adapters/cloudflare-build-enhancer'],\n defaultExport: {\n ...options?.handlers,\n fetch(req: Request, env: Record<string, string>) {\n setAllEnv(env);\n return fetchFn(req);\n },\n },\n };\n },\n);\n"],"names":["Hono","unstable_createServerEntryAdapter","createServerEntryAdapter","unstable_startPreviewServer","startPreviewServer","unstable_constants","constants","unstable_consumeMultiplexedStream","consumeMultiplexedStream","unstable_honoMiddleware","honoMiddleware","unstable_produceMultiplexedStream","produceMultiplexedStream","DIST_PUBLIC","contextMiddleware","rscMiddleware","middlewareRunner","DO_NOT_BUNDLE","isWranglerDev","req","headers","get","removeGzipEncoding","res","contentType","includes","Headers","set","Response","body","status","statusText","processRequest","processBuild","setAllEnv","config","notFoundHtml","options","middlewareFns","middlewareModules","internalPathToBuildStaticFiles","app","notFound","c","html","text","use","middlewareFn","buildOptions","srcDir","distDir","serverless","static","fetchFn","URL","url","pathname","emitFile","cloudflareContext","env","waitUntil","passThroughOnException","fetch","props","undefined","PROD","then","build","utils","server","middlewares","_req","next","Readable","fromWeb","pipe","err","response","baseUrl","close","buildEnhancers","defaultExport","handlers"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/adapters/cloudflare.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'hono';\nimport { Hono } from 'hono/tiny';\nimport {\n unstable_createServerEntryAdapter as createServerEntryAdapter,\n unstable_startPreviewServer as startPreviewServer,\n} from 'waku/adapter-builders';\nimport {\n unstable_constants as constants,\n unstable_consumeMultiplexedStream as consumeMultiplexedStream,\n unstable_honoMiddleware as honoMiddleware,\n unstable_produceMultiplexedStream as produceMultiplexedStream,\n} from 'waku/internals';\nimport type { BuildOptions } from './cloudflare-build-enhancer.js';\n\nconst { DIST_PUBLIC } = constants;\nconst { contextMiddleware, rscMiddleware, middlewareRunner } = honoMiddleware;\n\nconst DO_NOT_BUNDLE = '';\n\nconst PRUNABLE_KEY_PREFIX = '\\0__prunable__/';\n\nconst emptyStream = () =>\n new ReadableStream<Uint8Array>({\n start(controller) {\n controller.close();\n },\n });\n\nfunction isWranglerDev(req: Request): boolean {\n // This header seems to only be set for production cloudflare workers\n return !req.headers.get('cf-visitor');\n}\n\nfunction removeGzipEncoding(res: Response): Response {\n const contentType = res.headers.get('content-type');\n if (\n !contentType ||\n contentType.includes('text/html') ||\n contentType.includes('text/plain')\n ) {\n const headers = new Headers(res.headers);\n headers.set('content-encoding', 'Identity');\n return new Response(res.body, {\n status: res.status,\n statusText: res.statusText,\n headers,\n });\n }\n return res;\n}\n\nexport default createServerEntryAdapter(\n (\n { processRequest, processBuild, setAllEnv, config, notFoundHtml },\n options?: {\n static?: boolean;\n handlers?: Record<string, unknown>;\n assetsDir?: string;\n middlewareFns?: (() => MiddlewareHandler)[];\n middlewareModules?: Record<string, () => Promise<unknown>>;\n internalPathToBuildStaticFiles?: string;\n },\n ) => {\n const {\n middlewareFns = [],\n middlewareModules = {},\n internalPathToBuildStaticFiles = '__waku_internal_build_static_files',\n } = options || {};\n const app = new Hono();\n app.notFound((c) => {\n if (notFoundHtml) {\n return c.html(notFoundHtml, 404);\n }\n return c.text('404 Not Found', 404);\n });\n app.use(contextMiddleware());\n for (const middlewareFn of middlewareFns) {\n app.use(middlewareFn());\n }\n app.use(middlewareRunner(middlewareModules as never));\n app.use(rscMiddleware({ processRequest }));\n const buildOptions: BuildOptions = {\n srcDir: config.srcDir,\n distDir: config.distDir,\n DIST_PUBLIC,\n serverless: !options?.static,\n };\n\n const buildBody = () =>\n produceMultiplexedStream(async (emitFile) => {\n await processBuild({\n emitFile,\n unstable_registerPrunableFile: (srcPath) =>\n emitFile(PRUNABLE_KEY_PREFIX + srcPath, emptyStream()),\n });\n });\n\n const fetchFn = async (req: Request) => {\n if (new URL(req.url).pathname === `/${internalPathToBuildStaticFiles}`) {\n return new Response(buildBody());\n }\n let cloudflareContext;\n try {\n cloudflareContext = await import(\n /* @vite-ignore */ DO_NOT_BUNDLE + 'cloudflare:workers'\n );\n } catch {\n // Not in a Cloudflare environment\n }\n let res: Response | Promise<Response>;\n if (cloudflareContext) {\n const { env, waitUntil, passThroughOnException } = cloudflareContext;\n res = app.fetch(req, env, {\n waitUntil,\n passThroughOnException,\n props: undefined,\n });\n } else {\n res = app.fetch(req);\n }\n // Workaround https://github.com/cloudflare/workers-sdk/issues/6577\n if (import.meta.env?.PROD && isWranglerDev(req)) {\n if ('then' in res) {\n res = res.then((res) => removeGzipEncoding(res));\n } else {\n res = removeGzipEncoding(res);\n }\n }\n return res;\n };\n\n return {\n fetch: fetchFn,\n build: async (utils) => {\n const server = await startPreviewServer();\n // Fallback middleware for the case without @cloudflare/vite-plugin\n server.middlewares.use(async (_req, res, next) => {\n try {\n const { Readable } = await import(\n /* @vite-ignore */ DO_NOT_BUNDLE + 'node:stream'\n );\n Readable.fromWeb(buildBody() as never).pipe(res);\n } catch (err) {\n next(err);\n }\n });\n const response = await fetch(\n server.baseUrl + internalPathToBuildStaticFiles,\n { headers: { connection: 'close' } },\n );\n await consumeMultiplexedStream(response.body!, async (key, stream) => {\n if (key.startsWith(PRUNABLE_KEY_PREFIX)) {\n utils.unstable_registerPrunableFile(\n key.slice(PRUNABLE_KEY_PREFIX.length),\n );\n return;\n }\n await utils.emitFile(key, stream);\n });\n // https://github.com/nodejs/node/issues/56645\n await new Promise((resolve) => setTimeout(resolve, 100));\n await server.close();\n },\n buildOptions,\n buildEnhancers: ['waku/adapters/cloudflare-build-enhancer'],\n defaultExport: {\n ...options?.handlers,\n fetch(req: Request, env: Record<string, string>) {\n setAllEnv(env);\n return fetchFn(req);\n },\n },\n };\n },\n);\n"],"names":["Hono","unstable_createServerEntryAdapter","createServerEntryAdapter","unstable_startPreviewServer","startPreviewServer","unstable_constants","constants","unstable_consumeMultiplexedStream","consumeMultiplexedStream","unstable_honoMiddleware","honoMiddleware","unstable_produceMultiplexedStream","produceMultiplexedStream","DIST_PUBLIC","contextMiddleware","rscMiddleware","middlewareRunner","DO_NOT_BUNDLE","PRUNABLE_KEY_PREFIX","emptyStream","ReadableStream","start","controller","close","isWranglerDev","req","headers","get","removeGzipEncoding","res","contentType","includes","Headers","set","Response","body","status","statusText","processRequest","processBuild","setAllEnv","config","notFoundHtml","options","middlewareFns","middlewareModules","internalPathToBuildStaticFiles","app","notFound","c","html","text","use","middlewareFn","buildOptions","srcDir","distDir","serverless","static","buildBody","emitFile","unstable_registerPrunableFile","srcPath","fetchFn","URL","url","pathname","cloudflareContext","env","waitUntil","passThroughOnException","fetch","props","undefined","PROD","then","build","utils","server","middlewares","_req","next","Readable","fromWeb","pipe","err","response","baseUrl","connection","key","stream","startsWith","slice","length","Promise","resolve","setTimeout","buildEnhancers","defaultExport","handlers"],"mappings":"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"}
@@ -7,14 +7,14 @@ async function postBuild({ distDir, privateDir, rscBase, DIST_PUBLIC, serverless
7
7
  recursive: true
8
8
  });
9
9
  writeFileSync(path.join(functionsDir, 'serve.js'), `\
10
- const { INTERNAL_runFetch } = await import('../${distDir}/server/index.js');
10
+ const { INTERNAL_runFetch } = await import(${JSON.stringify(`../${distDir}/server/index.js`)});
11
11
 
12
12
  export default async (request, context) =>
13
13
  INTERNAL_runFetch(process.env, request, { context });
14
14
 
15
15
  export const config = {
16
16
  preferStatic: true,
17
- path: ['/', '/*', '/${rscBase}/**/*'],
17
+ path: ['/', '/*', ${JSON.stringify(`/${rscBase}/**/*`)}],
18
18
  };
19
19
  `);
20
20
  }
@@ -23,9 +23,9 @@ export const config = {
23
23
  writeFileSync(netlifyTomlFile, `\
24
24
  [build]
25
25
  command = "npm run build"
26
- publish = "${distDir}/${DIST_PUBLIC}"
26
+ publish = ${JSON.stringify(`${distDir}/${DIST_PUBLIC}`)}
27
27
  [functions]
28
- included_files = ["${privateDir}/**"]
28
+ included_files = [${JSON.stringify(`${privateDir}/**`)}]
29
29
  directory = "netlify-functions"
30
30
  `);
31
31
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/netlify-build-enhancer.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nexport type BuildOptions = {\n distDir: string;\n privateDir: string;\n rscBase: string;\n DIST_PUBLIC: string;\n serverless: boolean;\n};\n\nasync function postBuild({\n distDir,\n privateDir,\n rscBase,\n DIST_PUBLIC,\n serverless,\n}: BuildOptions) {\n if (serverless) {\n const functionsDir = path.resolve('netlify-functions');\n mkdirSync(functionsDir, {\n recursive: true,\n });\n writeFileSync(\n path.join(functionsDir, 'serve.js'),\n `\\\nconst { INTERNAL_runFetch } = await import('../${distDir}/server/index.js');\n\nexport default async (request, context) =>\n INTERNAL_runFetch(process.env, request, { context });\n\nexport const config = {\n preferStatic: true,\n path: ['/', '/*', '/${rscBase}/**/*'],\n};\n`,\n );\n }\n const netlifyTomlFile = path.resolve('netlify.toml');\n if (!existsSync(netlifyTomlFile)) {\n writeFileSync(\n netlifyTomlFile,\n `\\\n[build]\n command = \"npm run build\"\n publish = \"${distDir}/${DIST_PUBLIC}\"\n[functions]\n included_files = [\"${privateDir}/**\"]\n directory = \"netlify-functions\"\n`,\n );\n }\n}\n\nexport default async function buildEnhancer(\n build: (utils: unknown, options: BuildOptions) => Promise<void>,\n): Promise<typeof build> {\n return async (utils: unknown, options: BuildOptions) => {\n await build(utils, options);\n await postBuild(options);\n };\n}\n"],"names":["existsSync","mkdirSync","writeFileSync","path","postBuild","distDir","privateDir","rscBase","DIST_PUBLIC","serverless","functionsDir","resolve","recursive","join","netlifyTomlFile","buildEnhancer","build","utils","options"],"mappings":"AAAA,SAASA,UAAU,EAAEC,SAAS,EAAEC,aAAa,QAAQ,UAAU;AAC/D,OAAOC,UAAU,YAAY;AAU7B,eAAeC,UAAU,EACvBC,OAAO,EACPC,UAAU,EACVC,OAAO,EACPC,WAAW,EACXC,UAAU,EACG;IACb,IAAIA,YAAY;QACd,MAAMC,eAAeP,KAAKQ,OAAO,CAAC;QAClCV,UAAUS,cAAc;YACtBE,WAAW;QACb;QACAV,cACEC,KAAKU,IAAI,CAACH,cAAc,aACxB,CAAC;+CACwC,EAAEL,QAAQ;;;;;;;sBAOnC,EAAEE,QAAQ;;AAEhC,CAAC;IAEC;IACA,MAAMO,kBAAkBX,KAAKQ,OAAO,CAAC;IACrC,IAAI,CAACX,WAAWc,kBAAkB;QAChCZ,cACEY,iBACA,CAAC;;;aAGM,EAAET,QAAQ,CAAC,EAAEG,YAAY;;qBAEjB,EAAEF,WAAW;;AAElC,CAAC;IAEC;AACF;AAEA,eAAe,eAAeS,cAC5BC,KAA+D;IAE/D,OAAO,OAAOC,OAAgBC;QAC5B,MAAMF,MAAMC,OAAOC;QACnB,MAAMd,UAAUc;IAClB;AACF"}
1
+ {"version":3,"sources":["../../src/adapters/netlify-build-enhancer.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nexport type BuildOptions = {\n distDir: string;\n privateDir: string;\n rscBase: string;\n DIST_PUBLIC: string;\n serverless: boolean;\n};\n\nasync function postBuild({\n distDir,\n privateDir,\n rscBase,\n DIST_PUBLIC,\n serverless,\n}: BuildOptions) {\n if (serverless) {\n const functionsDir = path.resolve('netlify-functions');\n mkdirSync(functionsDir, {\n recursive: true,\n });\n writeFileSync(\n path.join(functionsDir, 'serve.js'),\n `\\\nconst { INTERNAL_runFetch } = await import(${JSON.stringify(`../${distDir}/server/index.js`)});\n\nexport default async (request, context) =>\n INTERNAL_runFetch(process.env, request, { context });\n\nexport const config = {\n preferStatic: true,\n path: ['/', '/*', ${JSON.stringify(`/${rscBase}/**/*`)}],\n};\n`,\n );\n }\n const netlifyTomlFile = path.resolve('netlify.toml');\n if (!existsSync(netlifyTomlFile)) {\n writeFileSync(\n netlifyTomlFile,\n `\\\n[build]\n command = \"npm run build\"\n publish = ${JSON.stringify(`${distDir}/${DIST_PUBLIC}`)}\n[functions]\n included_files = [${JSON.stringify(`${privateDir}/**`)}]\n directory = \"netlify-functions\"\n`,\n );\n }\n}\n\nexport default async function buildEnhancer(\n build: (utils: unknown, options: BuildOptions) => Promise<void>,\n): Promise<typeof build> {\n return async (utils: unknown, options: BuildOptions) => {\n await build(utils, options);\n await postBuild(options);\n };\n}\n"],"names":["existsSync","mkdirSync","writeFileSync","path","postBuild","distDir","privateDir","rscBase","DIST_PUBLIC","serverless","functionsDir","resolve","recursive","join","JSON","stringify","netlifyTomlFile","buildEnhancer","build","utils","options"],"mappings":"AAAA,SAASA,UAAU,EAAEC,SAAS,EAAEC,aAAa,QAAQ,UAAU;AAC/D,OAAOC,UAAU,YAAY;AAU7B,eAAeC,UAAU,EACvBC,OAAO,EACPC,UAAU,EACVC,OAAO,EACPC,WAAW,EACXC,UAAU,EACG;IACb,IAAIA,YAAY;QACd,MAAMC,eAAeP,KAAKQ,OAAO,CAAC;QAClCV,UAAUS,cAAc;YACtBE,WAAW;QACb;QACAV,cACEC,KAAKU,IAAI,CAACH,cAAc,aACxB,CAAC;2CACoC,EAAEI,KAAKC,SAAS,CAAC,CAAC,GAAG,EAAEV,QAAQ,gBAAgB,CAAC,EAAE;;;;;;;oBAOzE,EAAES,KAAKC,SAAS,CAAC,CAAC,CAAC,EAAER,QAAQ,KAAK,CAAC,EAAE;;AAEzD,CAAC;IAEC;IACA,MAAMS,kBAAkBb,KAAKQ,OAAO,CAAC;IACrC,IAAI,CAACX,WAAWgB,kBAAkB;QAChCd,cACEc,iBACA,CAAC;;;YAGK,EAAEF,KAAKC,SAAS,CAAC,GAAGV,QAAQ,CAAC,EAAEG,aAAa,EAAE;;oBAEtC,EAAEM,KAAKC,SAAS,CAAC,GAAGT,WAAW,GAAG,CAAC,EAAE;;AAEzD,CAAC;IAEC;AACF;AAEA,eAAe,eAAeW,cAC5BC,KAA+D;IAE/D,OAAO,OAAOC,OAAgBC;QAC5B,MAAMF,MAAMC,OAAOC;QACnB,MAAMhB,UAAUgB;IAClB;AACF"}
@@ -1,5 +1,6 @@
1
1
  import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
2
2
  import path from 'node:path';
3
+ const escapeRegExp = (s)=>s.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
3
4
  async function postBuild({ assetsDir, distDir, rscBase, privateDir, basePath, DIST_PUBLIC, serverless }) {
4
5
  const SERVE_JS = 'serve-vercel.js';
5
6
  const serveCode = `
@@ -49,7 +50,7 @@ export default getRequestListener(
49
50
  }
50
51
  const routes = [
51
52
  {
52
- src: `^${basePath}${assetsDir}/(.*)$`,
53
+ src: `^${escapeRegExp(basePath)}${escapeRegExp(assetsDir)}/(.*)$`,
53
54
  headers: {
54
55
  'cache-control': 'public, immutable, max-age=31536000'
55
56
  }
@@ -59,7 +60,7 @@ export default getRequestListener(
59
60
  handle: 'filesystem'
60
61
  },
61
62
  {
62
- src: basePath + '(.*)',
63
+ src: escapeRegExp(basePath) + '(.*)',
63
64
  dest: basePath + rscBase + '/'
64
65
  }
65
66
  ] : []
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/vercel-build-enhancer.ts"],"sourcesContent":["import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nexport type BuildOptions = {\n assetsDir: string;\n distDir: string;\n rscBase: string;\n privateDir: string;\n basePath: string;\n DIST_PUBLIC: string;\n serverless: boolean;\n};\n\nasync function postBuild({\n assetsDir,\n distDir,\n rscBase,\n privateDir,\n basePath,\n DIST_PUBLIC,\n serverless,\n}: BuildOptions) {\n const SERVE_JS = 'serve-vercel.js';\n const serveCode = `\nimport { INTERNAL_runFetch } from './server/index.js';\n\nconst getRequestListener = globalThis.__WAKU_HONO_NODE_SERVER_GET_REQUEST_LISTENER__;\n\nexport default getRequestListener(\n (req, ...args) => INTERNAL_runFetch(process.env, req, ...args)\n);\n`;\n const publicDir = path.resolve(distDir, DIST_PUBLIC);\n const outputDir = path.resolve('.vercel', 'output');\n cpSync(publicDir, path.join(outputDir, 'static'), { recursive: true });\n\n if (serverless) {\n // for serverless function\n // TODO(waku): can use `@vercel/nft` to packaging with native dependencies\n const serverlessDir = path.join(outputDir, 'functions', rscBase + '.func');\n rmSync(serverlessDir, { recursive: true, force: true });\n mkdirSync(path.join(serverlessDir, distDir), {\n recursive: true,\n });\n writeFileSync(path.resolve(distDir, SERVE_JS), serveCode);\n cpSync(path.resolve(distDir), path.join(serverlessDir, distDir), {\n recursive: true,\n });\n if (existsSync(path.resolve(privateDir))) {\n cpSync(path.resolve(privateDir), path.join(serverlessDir, privateDir), {\n recursive: true,\n dereference: true,\n });\n }\n const vcConfigJson = {\n runtime: 'nodejs22.x',\n handler: `${distDir}/${SERVE_JS}`,\n launcherType: 'Nodejs',\n };\n writeFileSync(\n path.join(serverlessDir, '.vc-config.json'),\n JSON.stringify(vcConfigJson, null, 2),\n );\n writeFileSync(\n path.join(serverlessDir, 'package.json'),\n JSON.stringify({ type: 'module' }, null, 2),\n );\n }\n const routes = [\n {\n src: `^${basePath}${assetsDir}/(.*)$`,\n headers: {\n 'cache-control': 'public, immutable, max-age=31536000',\n },\n },\n ...(serverless\n ? [\n { handle: 'filesystem' },\n {\n src: basePath + '(.*)',\n dest: basePath + rscBase + '/',\n },\n ]\n : []),\n ];\n const configJson = { version: 3, routes };\n mkdirSync(outputDir, { recursive: true });\n writeFileSync(\n path.join(outputDir, 'config.json'),\n JSON.stringify(configJson, null, 2),\n );\n}\n\nexport default async function buildEnhancer(\n build: (utils: unknown, options: BuildOptions) => Promise<void>,\n): Promise<typeof build> {\n return async (utils: unknown, options: BuildOptions) => {\n await build(utils, options);\n await postBuild(options);\n };\n}\n"],"names":["cpSync","existsSync","mkdirSync","rmSync","writeFileSync","path","postBuild","assetsDir","distDir","rscBase","privateDir","basePath","DIST_PUBLIC","serverless","SERVE_JS","serveCode","publicDir","resolve","outputDir","join","recursive","serverlessDir","force","dereference","vcConfigJson","runtime","handler","launcherType","JSON","stringify","type","routes","src","headers","handle","dest","configJson","version","buildEnhancer","build","utils","options"],"mappings":"AAAA,SAASA,MAAM,EAAEC,UAAU,EAAEC,SAAS,EAAEC,MAAM,EAAEC,aAAa,QAAQ,UAAU;AAC/E,OAAOC,UAAU,YAAY;AAY7B,eAAeC,UAAU,EACvBC,SAAS,EACTC,OAAO,EACPC,OAAO,EACPC,UAAU,EACVC,QAAQ,EACRC,WAAW,EACXC,UAAU,EACG;IACb,MAAMC,WAAW;IACjB,MAAMC,YAAY,CAAC;;;;;;;;AAQrB,CAAC;IACC,MAAMC,YAAYX,KAAKY,OAAO,CAACT,SAASI;IACxC,MAAMM,YAAYb,KAAKY,OAAO,CAAC,WAAW;IAC1CjB,OAAOgB,WAAWX,KAAKc,IAAI,CAACD,WAAW,WAAW;QAAEE,WAAW;IAAK;IAEpE,IAAIP,YAAY;QACd,0BAA0B;QAC1B,0EAA0E;QAC1E,MAAMQ,gBAAgBhB,KAAKc,IAAI,CAACD,WAAW,aAAaT,UAAU;QAClEN,OAAOkB,eAAe;YAAED,WAAW;YAAME,OAAO;QAAK;QACrDpB,UAAUG,KAAKc,IAAI,CAACE,eAAeb,UAAU;YAC3CY,WAAW;QACb;QACAhB,cAAcC,KAAKY,OAAO,CAACT,SAASM,WAAWC;QAC/Cf,OAAOK,KAAKY,OAAO,CAACT,UAAUH,KAAKc,IAAI,CAACE,eAAeb,UAAU;YAC/DY,WAAW;QACb;QACA,IAAInB,WAAWI,KAAKY,OAAO,CAACP,cAAc;YACxCV,OAAOK,KAAKY,OAAO,CAACP,aAAaL,KAAKc,IAAI,CAACE,eAAeX,aAAa;gBACrEU,WAAW;gBACXG,aAAa;YACf;QACF;QACA,MAAMC,eAAe;YACnBC,SAAS;YACTC,SAAS,GAAGlB,QAAQ,CAAC,EAAEM,UAAU;YACjCa,cAAc;QAChB;QACAvB,cACEC,KAAKc,IAAI,CAACE,eAAe,oBACzBO,KAAKC,SAAS,CAACL,cAAc,MAAM;QAErCpB,cACEC,KAAKc,IAAI,CAACE,eAAe,iBACzBO,KAAKC,SAAS,CAAC;YAAEC,MAAM;QAAS,GAAG,MAAM;IAE7C;IACA,MAAMC,SAAS;QACb;YACEC,KAAK,CAAC,CAAC,EAAErB,WAAWJ,UAAU,MAAM,CAAC;YACrC0B,SAAS;gBACP,iBAAiB;YACnB;QACF;WACIpB,aACA;YACE;gBAAEqB,QAAQ;YAAa;YACvB;gBACEF,KAAKrB,WAAW;gBAChBwB,MAAMxB,WAAWF,UAAU;YAC7B;SACD,GACD,EAAE;KACP;IACD,MAAM2B,aAAa;QAAEC,SAAS;QAAGN;IAAO;IACxC7B,UAAUgB,WAAW;QAAEE,WAAW;IAAK;IACvChB,cACEC,KAAKc,IAAI,CAACD,WAAW,gBACrBU,KAAKC,SAAS,CAACO,YAAY,MAAM;AAErC;AAEA,eAAe,eAAeE,cAC5BC,KAA+D;IAE/D,OAAO,OAAOC,OAAgBC;QAC5B,MAAMF,MAAMC,OAAOC;QACnB,MAAMnC,UAAUmC;IAClB;AACF"}
1
+ {"version":3,"sources":["../../src/adapters/vercel-build-enhancer.ts"],"sourcesContent":["import { cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\nconst escapeRegExp = (s: string) => s.replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&');\n\nexport type BuildOptions = {\n assetsDir: string;\n distDir: string;\n rscBase: string;\n privateDir: string;\n basePath: string;\n DIST_PUBLIC: string;\n serverless: boolean;\n};\n\nasync function postBuild({\n assetsDir,\n distDir,\n rscBase,\n privateDir,\n basePath,\n DIST_PUBLIC,\n serverless,\n}: BuildOptions) {\n const SERVE_JS = 'serve-vercel.js';\n const serveCode = `\nimport { INTERNAL_runFetch } from './server/index.js';\n\nconst getRequestListener = globalThis.__WAKU_HONO_NODE_SERVER_GET_REQUEST_LISTENER__;\n\nexport default getRequestListener(\n (req, ...args) => INTERNAL_runFetch(process.env, req, ...args)\n);\n`;\n const publicDir = path.resolve(distDir, DIST_PUBLIC);\n const outputDir = path.resolve('.vercel', 'output');\n cpSync(publicDir, path.join(outputDir, 'static'), { recursive: true });\n\n if (serverless) {\n // for serverless function\n // TODO(waku): can use `@vercel/nft` to packaging with native dependencies\n const serverlessDir = path.join(outputDir, 'functions', rscBase + '.func');\n rmSync(serverlessDir, { recursive: true, force: true });\n mkdirSync(path.join(serverlessDir, distDir), {\n recursive: true,\n });\n writeFileSync(path.resolve(distDir, SERVE_JS), serveCode);\n cpSync(path.resolve(distDir), path.join(serverlessDir, distDir), {\n recursive: true,\n });\n if (existsSync(path.resolve(privateDir))) {\n cpSync(path.resolve(privateDir), path.join(serverlessDir, privateDir), {\n recursive: true,\n dereference: true,\n });\n }\n const vcConfigJson = {\n runtime: 'nodejs22.x',\n handler: `${distDir}/${SERVE_JS}`,\n launcherType: 'Nodejs',\n };\n writeFileSync(\n path.join(serverlessDir, '.vc-config.json'),\n JSON.stringify(vcConfigJson, null, 2),\n );\n writeFileSync(\n path.join(serverlessDir, 'package.json'),\n JSON.stringify({ type: 'module' }, null, 2),\n );\n }\n const routes = [\n {\n src: `^${escapeRegExp(basePath)}${escapeRegExp(assetsDir)}/(.*)$`,\n headers: {\n 'cache-control': 'public, immutable, max-age=31536000',\n },\n },\n ...(serverless\n ? [\n { handle: 'filesystem' },\n {\n src: escapeRegExp(basePath) + '(.*)',\n dest: basePath + rscBase + '/',\n },\n ]\n : []),\n ];\n const configJson = { version: 3, routes };\n mkdirSync(outputDir, { recursive: true });\n writeFileSync(\n path.join(outputDir, 'config.json'),\n JSON.stringify(configJson, null, 2),\n );\n}\n\nexport default async function buildEnhancer(\n build: (utils: unknown, options: BuildOptions) => Promise<void>,\n): Promise<typeof build> {\n return async (utils: unknown, options: BuildOptions) => {\n await build(utils, options);\n await postBuild(options);\n };\n}\n"],"names":["cpSync","existsSync","mkdirSync","rmSync","writeFileSync","path","escapeRegExp","s","replace","postBuild","assetsDir","distDir","rscBase","privateDir","basePath","DIST_PUBLIC","serverless","SERVE_JS","serveCode","publicDir","resolve","outputDir","join","recursive","serverlessDir","force","dereference","vcConfigJson","runtime","handler","launcherType","JSON","stringify","type","routes","src","headers","handle","dest","configJson","version","buildEnhancer","build","utils","options"],"mappings":"AAAA,SAASA,MAAM,EAAEC,UAAU,EAAEC,SAAS,EAAEC,MAAM,EAAEC,aAAa,QAAQ,UAAU;AAC/E,OAAOC,UAAU,YAAY;AAE7B,MAAMC,eAAe,CAACC,IAAcA,EAAEC,OAAO,CAAC,uBAAuB;AAYrE,eAAeC,UAAU,EACvBC,SAAS,EACTC,OAAO,EACPC,OAAO,EACPC,UAAU,EACVC,QAAQ,EACRC,WAAW,EACXC,UAAU,EACG;IACb,MAAMC,WAAW;IACjB,MAAMC,YAAY,CAAC;;;;;;;;AAQrB,CAAC;IACC,MAAMC,YAAYd,KAAKe,OAAO,CAACT,SAASI;IACxC,MAAMM,YAAYhB,KAAKe,OAAO,CAAC,WAAW;IAC1CpB,OAAOmB,WAAWd,KAAKiB,IAAI,CAACD,WAAW,WAAW;QAAEE,WAAW;IAAK;IAEpE,IAAIP,YAAY;QACd,0BAA0B;QAC1B,0EAA0E;QAC1E,MAAMQ,gBAAgBnB,KAAKiB,IAAI,CAACD,WAAW,aAAaT,UAAU;QAClET,OAAOqB,eAAe;YAAED,WAAW;YAAME,OAAO;QAAK;QACrDvB,UAAUG,KAAKiB,IAAI,CAACE,eAAeb,UAAU;YAC3CY,WAAW;QACb;QACAnB,cAAcC,KAAKe,OAAO,CAACT,SAASM,WAAWC;QAC/ClB,OAAOK,KAAKe,OAAO,CAACT,UAAUN,KAAKiB,IAAI,CAACE,eAAeb,UAAU;YAC/DY,WAAW;QACb;QACA,IAAItB,WAAWI,KAAKe,OAAO,CAACP,cAAc;YACxCb,OAAOK,KAAKe,OAAO,CAACP,aAAaR,KAAKiB,IAAI,CAACE,eAAeX,aAAa;gBACrEU,WAAW;gBACXG,aAAa;YACf;QACF;QACA,MAAMC,eAAe;YACnBC,SAAS;YACTC,SAAS,GAAGlB,QAAQ,CAAC,EAAEM,UAAU;YACjCa,cAAc;QAChB;QACA1B,cACEC,KAAKiB,IAAI,CAACE,eAAe,oBACzBO,KAAKC,SAAS,CAACL,cAAc,MAAM;QAErCvB,cACEC,KAAKiB,IAAI,CAACE,eAAe,iBACzBO,KAAKC,SAAS,CAAC;YAAEC,MAAM;QAAS,GAAG,MAAM;IAE7C;IACA,MAAMC,SAAS;QACb;YACEC,KAAK,CAAC,CAAC,EAAE7B,aAAaQ,YAAYR,aAAaI,WAAW,MAAM,CAAC;YACjE0B,SAAS;gBACP,iBAAiB;YACnB;QACF;WACIpB,aACA;YACE;gBAAEqB,QAAQ;YAAa;YACvB;gBACEF,KAAK7B,aAAaQ,YAAY;gBAC9BwB,MAAMxB,WAAWF,UAAU;YAC7B;SACD,GACD,EAAE;KACP;IACD,MAAM2B,aAAa;QAAEC,SAAS;QAAGN;IAAO;IACxChC,UAAUmB,WAAW;QAAEE,WAAW;IAAK;IACvCnB,cACEC,KAAKiB,IAAI,CAACD,WAAW,gBACrBU,KAAKC,SAAS,CAACO,YAAY,MAAM;AAErC;AAEA,eAAe,eAAeE,cAC5BC,KAA+D;IAE/D,OAAO,OAAOC,OAAgBC;QAC5B,MAAMF,MAAMC,OAAOC;QACnB,MAAMnC,UAAUmC;IAClB;AACF"}
@@ -2,6 +2,7 @@ import type { ReactNode } from 'react';
2
2
  import type { Config } from '../config.js';
3
3
  type Elements = Record<string, unknown>;
4
4
  export type Unstable_RenderRsc = (elements: Elements, options?: {
5
+ value?: unknown;
5
6
  unstable_clientModuleCallback?: (ids: string[]) => void;
6
7
  }) => Promise<ReadableStream>;
7
8
  export type Unstable_ParseRsc = (rscStream: ReadableStream) => Promise<Elements>;
@@ -44,6 +45,7 @@ export type Unstable_HandleBuild = (utils: {
44
45
  withRequest: <T>(req: Request, fn: () => T) => T;
45
46
  generateFile: (fileName: string, body: ReadableStream | string) => Promise<void>;
46
47
  generateDefaultHtml: (fileName: string) => Promise<void>;
48
+ unstable_registerPrunableFile: (srcPath: string) => void;
47
49
  }) => Promise<void>;
48
50
  export type Unstable_Handlers = {
49
51
  handleRequest: Unstable_HandleRequest;
@@ -54,16 +56,15 @@ export type Unstable_ServerEntry = {
54
56
  fetch: (req: Request, ...args: any[]) => Response | Promise<Response>;
55
57
  build: (utils: {
56
58
  emitFile: Unstable_EmitFile;
59
+ unstable_registerPrunableFile: (srcPath: string) => void;
57
60
  }, ...args: any[]) => Promise<void>;
58
61
  buildOptions?: Record<string, unknown>;
59
62
  buildEnhancers?: string[];
60
63
  defaultExport?: unknown;
61
64
  [someOtherProperty: string]: unknown;
62
65
  };
63
- export type Unstable_ProcessRequest = (req: Request) => Promise<Response | null>;
64
- export type Unstable_ProcessBuild = (utils: {
65
- emitFile: Unstable_EmitFile;
66
- }) => Promise<void>;
66
+ export type Unstable_ProcessRequest = (arg: Parameters<Unstable_ServerEntry['fetch']>[0]) => Promise<Response | null>;
67
+ export type Unstable_ProcessBuild = (arg: Parameters<Unstable_ServerEntry['build']>[0]) => Promise<void>;
67
68
  export type Unstable_CreateServerEntryAdapter = <Options>(fn: (args: {
68
69
  handlers: Unstable_Handlers;
69
70
  processRequest: Unstable_ProcessRequest;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { Config } from '../config.js';\n\ntype Elements = Record<string, unknown>;\n\nexport type Unstable_RenderRsc = (\n elements: Elements,\n options?: {\n unstable_clientModuleCallback?: (ids: string[]) => void;\n },\n) => Promise<ReadableStream>;\n\nexport type Unstable_ParseRsc = (\n rscStream: ReadableStream,\n) => Promise<Elements>;\n\nexport type Unstable_RenderHtml = (\n elementsStream: ReadableStream,\n html: ReactNode,\n options: {\n rscPath: string;\n formState?: unknown;\n status?: number;\n nonce?: string;\n unstable_extraScriptContent?: string;\n },\n) => Promise<Response>;\n\nexport type Unstable_EmitFile = (\n filePath: string,\n body: ReadableStream,\n) => Promise<void>;\n\nexport type Unstable_HandleRequest = (\n input: (\n | { type: 'component'; rscPath: string; rscParams: unknown }\n | {\n type: 'function';\n fn: (...args: unknown[]) => Promise<unknown>;\n args: unknown[];\n }\n | {\n type: 'action';\n fn: () => Promise<unknown>;\n }\n | { type: 'custom' }\n ) & {\n pathname: string;\n req: Request;\n },\n utils: {\n renderRsc: Unstable_RenderRsc;\n parseRsc: Unstable_ParseRsc;\n renderHtml: Unstable_RenderHtml;\n loadBuildMetadata: (key: string) => Promise<string | undefined>;\n },\n) => Promise<ReadableStream | Response | 'fallback' | null | undefined>;\n\nexport type Unstable_HandleBuild = (utils: {\n renderRsc: Unstable_RenderRsc;\n parseRsc: Unstable_ParseRsc;\n renderHtml: Unstable_RenderHtml;\n rscPath2pathname: (rscPath: string) => string;\n saveBuildMetadata: (key: string, value: string) => Promise<void>;\n withRequest: <T>(req: Request, fn: () => T) => T;\n generateFile: (\n fileName: string,\n body: ReadableStream | string,\n ) => Promise<void>;\n generateDefaultHtml: (fileName: string) => Promise<void>;\n}) => Promise<void>;\n\nexport type Unstable_Handlers = {\n handleRequest: Unstable_HandleRequest;\n handleBuild: Unstable_HandleBuild;\n [someOtherProperty: string]: unknown;\n};\n\nexport type Unstable_ServerEntry = {\n fetch: (req: Request, ...args: any[]) => Response | Promise<Response>;\n build: (\n utils: {\n emitFile: Unstable_EmitFile;\n },\n ...args: any[]\n ) => Promise<void>;\n buildOptions?: Record<string, unknown>;\n buildEnhancers?: string[]; // enhancer module ids\n defaultExport?: unknown;\n [someOtherProperty: string]: unknown;\n};\n\nexport type Unstable_ProcessRequest = (\n req: Request,\n) => Promise<Response | null>;\n\nexport type Unstable_ProcessBuild = (utils: {\n emitFile: Unstable_EmitFile;\n}) => Promise<void>;\n\nexport type Unstable_CreateServerEntryAdapter = <Options>(\n fn: (\n args: {\n handlers: Unstable_Handlers;\n processRequest: Unstable_ProcessRequest;\n processBuild: Unstable_ProcessBuild;\n setAllEnv: (newEnv: Readonly<Record<string, string>>) => void;\n config: Omit<Required<Config>, 'vite'>;\n isBuild: boolean;\n notFoundHtml: string;\n },\n options?: Options,\n ) => Unstable_ServerEntry,\n) => (handlers: Unstable_Handlers, options?: Options) => Unstable_ServerEntry;\n"],"names":[],"mappings":"AAoGA,WAa8E"}
1
+ {"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { Config } from '../config.js';\n\ntype Elements = Record<string, unknown>;\n\nexport type Unstable_RenderRsc = (\n elements: Elements,\n options?: {\n value?: unknown;\n unstable_clientModuleCallback?: (ids: string[]) => void;\n },\n) => Promise<ReadableStream>;\n\nexport type Unstable_ParseRsc = (\n rscStream: ReadableStream,\n) => Promise<Elements>;\n\nexport type Unstable_RenderHtml = (\n elementsStream: ReadableStream,\n html: ReactNode,\n options: {\n rscPath: string;\n formState?: unknown;\n status?: number;\n nonce?: string;\n unstable_extraScriptContent?: string;\n },\n) => Promise<Response>;\n\nexport type Unstable_EmitFile = (\n filePath: string,\n body: ReadableStream,\n) => Promise<void>;\n\nexport type Unstable_HandleRequest = (\n input: (\n | { type: 'component'; rscPath: string; rscParams: unknown }\n | {\n type: 'function';\n fn: (...args: unknown[]) => Promise<unknown>;\n args: unknown[];\n }\n | {\n type: 'action';\n fn: () => Promise<unknown>;\n }\n | { type: 'custom' }\n ) & {\n pathname: string;\n req: Request;\n },\n utils: {\n renderRsc: Unstable_RenderRsc;\n parseRsc: Unstable_ParseRsc;\n renderHtml: Unstable_RenderHtml;\n loadBuildMetadata: (key: string) => Promise<string | undefined>;\n },\n) => Promise<ReadableStream | Response | 'fallback' | null | undefined>;\n\nexport type Unstable_HandleBuild = (utils: {\n renderRsc: Unstable_RenderRsc;\n parseRsc: Unstable_ParseRsc;\n renderHtml: Unstable_RenderHtml;\n rscPath2pathname: (rscPath: string) => string;\n saveBuildMetadata: (key: string, value: string) => Promise<void>;\n withRequest: <T>(req: Request, fn: () => T) => T;\n generateFile: (\n fileName: string,\n body: ReadableStream | string,\n ) => Promise<void>;\n generateDefaultHtml: (fileName: string) => Promise<void>;\n unstable_registerPrunableFile: (srcPath: string) => void;\n}) => Promise<void>;\n\nexport type Unstable_Handlers = {\n handleRequest: Unstable_HandleRequest;\n handleBuild: Unstable_HandleBuild;\n [someOtherProperty: string]: unknown;\n};\n\nexport type Unstable_ServerEntry = {\n fetch: (req: Request, ...args: any[]) => Response | Promise<Response>;\n build: (\n utils: {\n emitFile: Unstable_EmitFile;\n unstable_registerPrunableFile: (srcPath: string) => void;\n },\n ...args: any[]\n ) => Promise<void>;\n buildOptions?: Record<string, unknown>;\n buildEnhancers?: string[]; // enhancer module ids\n defaultExport?: unknown;\n [someOtherProperty: string]: unknown;\n};\n\nexport type Unstable_ProcessRequest = (\n arg: Parameters<Unstable_ServerEntry['fetch']>[0],\n) => Promise<Response | null>;\n\nexport type Unstable_ProcessBuild = (\n arg: Parameters<Unstable_ServerEntry['build']>[0],\n) => Promise<void>;\n\nexport type Unstable_CreateServerEntryAdapter = <Options>(\n fn: (\n args: {\n handlers: Unstable_Handlers;\n processRequest: Unstable_ProcessRequest;\n processBuild: Unstable_ProcessBuild;\n setAllEnv: (newEnv: Readonly<Record<string, string>>) => void;\n config: Omit<Required<Config>, 'vite'>;\n isBuild: boolean;\n notFoundHtml: string;\n },\n options?: Options,\n ) => Unstable_ServerEntry,\n) => (handlers: Unstable_Handlers, options?: Options) => Unstable_ServerEntry;\n"],"names":[],"mappings":"AAuGA,WAa8E"}
@@ -1,27 +1,26 @@
1
1
  import { EXTENSIONS, SRC_MIDDLEWARE, SRC_PAGES } from '../constants.js';
2
2
  export const getManagedServerEntry = (srcDir)=>{
3
- const globBase = `/${srcDir}/${SRC_PAGES}`;
4
3
  const exts = EXTENSIONS.map((ext)=>ext.slice(1)).join(',');
5
- const globPattern = `${globBase}/**/*.{${exts}}`;
4
+ const globPattern = `/${srcDir}/${SRC_PAGES}/**/*.{${exts}}`;
5
+ const srcDirPrefix = `/${srcDir}/`;
6
6
  const middlewareGlob = [
7
7
  `/${srcDir}/${SRC_MIDDLEWARE}/*.{${exts}}`,
8
8
  `!/${srcDir}/${SRC_MIDDLEWARE}/*.{test,spec}.{${exts}}`
9
9
  ];
10
+ // Strip srcDir prefix from glob keys so fsRouter's default `pagesDir: 'pages'` applies.
10
11
  return `
11
12
  import { fsRouter } from 'waku';
12
13
  import adapter from 'waku/adapters/default';
13
14
 
14
- export default adapter(
15
- fsRouter(
16
- import.meta.glob(
17
- ${JSON.stringify(globPattern)},
18
- { base: ${JSON.stringify(globBase)} }
19
- )
15
+ const modules = Object.fromEntries(
16
+ Object.entries(import.meta.glob(${JSON.stringify(globPattern)})).map(
17
+ ([k, v]) => [k.slice(${srcDirPrefix.length}), v],
20
18
  ),
21
- {
22
- middlewareModules: import.meta.glob(${JSON.stringify(middlewareGlob)}),
23
- },
24
19
  );
20
+
21
+ export default adapter(fsRouter(modules), {
22
+ middlewareModules: import.meta.glob(${JSON.stringify(middlewareGlob)}),
23
+ });
25
24
  `;
26
25
  };
27
26
  export const getManagedClientEntry = ()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/managed.ts"],"sourcesContent":["import { EXTENSIONS, SRC_MIDDLEWARE, SRC_PAGES } from '../constants.js';\n\nexport const getManagedServerEntry = (srcDir: string) => {\n const globBase = `/${srcDir}/${SRC_PAGES}`;\n const exts = EXTENSIONS.map((ext) => ext.slice(1)).join(',');\n const globPattern = `${globBase}/**/*.{${exts}}`;\n const middlewareGlob = [\n `/${srcDir}/${SRC_MIDDLEWARE}/*.{${exts}}`,\n `!/${srcDir}/${SRC_MIDDLEWARE}/*.{test,spec}.{${exts}}`,\n ];\n return `\nimport { fsRouter } from 'waku';\nimport adapter from 'waku/adapters/default';\n\nexport default adapter(\n fsRouter(\n import.meta.glob(\n ${JSON.stringify(globPattern)},\n { base: ${JSON.stringify(globBase)} }\n )\n ),\n {\n middlewareModules: import.meta.glob(${JSON.stringify(middlewareGlob)}),\n },\n);\n`;\n};\n\nexport const getManagedClientEntry = () => {\n return `\nimport { StrictMode, createElement } from 'react';\nimport { createRoot, hydrateRoot } from 'react-dom/client';\nimport { unstable_defaultRootOptions as defaultRootOptions } from 'waku/client';\nimport { Router } from 'waku/router/client';\n\nconst rootElement = createElement(StrictMode, null, createElement(Router));\n\nif (globalThis.__WAKU_HYDRATE__) {\n hydrateRoot(document, rootElement, defaultRootOptions);\n} else {\n createRoot(document, defaultRootOptions).render(rootElement);\n}\n`;\n};\n"],"names":["EXTENSIONS","SRC_MIDDLEWARE","SRC_PAGES","getManagedServerEntry","srcDir","globBase","exts","map","ext","slice","join","globPattern","middlewareGlob","JSON","stringify","getManagedClientEntry"],"mappings":"AAAA,SAASA,UAAU,EAAEC,cAAc,EAAEC,SAAS,QAAQ,kBAAkB;AAExE,OAAO,MAAMC,wBAAwB,CAACC;IACpC,MAAMC,WAAW,CAAC,CAAC,EAAED,OAAO,CAAC,EAAEF,WAAW;IAC1C,MAAMI,OAAON,WAAWO,GAAG,CAAC,CAACC,MAAQA,IAAIC,KAAK,CAAC,IAAIC,IAAI,CAAC;IACxD,MAAMC,cAAc,GAAGN,SAAS,OAAO,EAAEC,KAAK,CAAC,CAAC;IAChD,MAAMM,iBAAiB;QACrB,CAAC,CAAC,EAAER,OAAO,CAAC,EAAEH,eAAe,IAAI,EAAEK,KAAK,CAAC,CAAC;QAC1C,CAAC,EAAE,EAAEF,OAAO,CAAC,EAAEH,eAAe,gBAAgB,EAAEK,KAAK,CAAC,CAAC;KACxD;IACD,OAAO,CAAC;;;;;;;MAOJ,EAAEO,KAAKC,SAAS,CAACH,aAAa;cACtB,EAAEE,KAAKC,SAAS,CAACT,UAAU;;;;wCAID,EAAEQ,KAAKC,SAAS,CAACF,gBAAgB;;;AAGzE,CAAC;AACD,EAAE;AAEF,OAAO,MAAMG,wBAAwB;IACnC,OAAO,CAAC;;;;;;;;;;;;;AAaV,CAAC;AACD,EAAE"}
1
+ {"version":3,"sources":["../../../src/lib/utils/managed.ts"],"sourcesContent":["import { EXTENSIONS, SRC_MIDDLEWARE, SRC_PAGES } from '../constants.js';\n\nexport const getManagedServerEntry = (srcDir: string) => {\n const exts = EXTENSIONS.map((ext) => ext.slice(1)).join(',');\n const globPattern = `/${srcDir}/${SRC_PAGES}/**/*.{${exts}}`;\n const srcDirPrefix = `/${srcDir}/`;\n const middlewareGlob = [\n `/${srcDir}/${SRC_MIDDLEWARE}/*.{${exts}}`,\n `!/${srcDir}/${SRC_MIDDLEWARE}/*.{test,spec}.{${exts}}`,\n ];\n // Strip srcDir prefix from glob keys so fsRouter's default `pagesDir: 'pages'` applies.\n return `\nimport { fsRouter } from 'waku';\nimport adapter from 'waku/adapters/default';\n\nconst modules = Object.fromEntries(\n Object.entries(import.meta.glob(${JSON.stringify(globPattern)})).map(\n ([k, v]) => [k.slice(${srcDirPrefix.length}), v],\n ),\n);\n\nexport default adapter(fsRouter(modules), {\n middlewareModules: import.meta.glob(${JSON.stringify(middlewareGlob)}),\n});\n`;\n};\n\nexport const getManagedClientEntry = () => {\n return `\nimport { StrictMode, createElement } from 'react';\nimport { createRoot, hydrateRoot } from 'react-dom/client';\nimport { unstable_defaultRootOptions as defaultRootOptions } from 'waku/client';\nimport { Router } from 'waku/router/client';\n\nconst rootElement = createElement(StrictMode, null, createElement(Router));\n\nif (globalThis.__WAKU_HYDRATE__) {\n hydrateRoot(document, rootElement, defaultRootOptions);\n} else {\n createRoot(document, defaultRootOptions).render(rootElement);\n}\n`;\n};\n"],"names":["EXTENSIONS","SRC_MIDDLEWARE","SRC_PAGES","getManagedServerEntry","srcDir","exts","map","ext","slice","join","globPattern","srcDirPrefix","middlewareGlob","JSON","stringify","length","getManagedClientEntry"],"mappings":"AAAA,SAASA,UAAU,EAAEC,cAAc,EAAEC,SAAS,QAAQ,kBAAkB;AAExE,OAAO,MAAMC,wBAAwB,CAACC;IACpC,MAAMC,OAAOL,WAAWM,GAAG,CAAC,CAACC,MAAQA,IAAIC,KAAK,CAAC,IAAIC,IAAI,CAAC;IACxD,MAAMC,cAAc,CAAC,CAAC,EAAEN,OAAO,CAAC,EAAEF,UAAU,OAAO,EAAEG,KAAK,CAAC,CAAC;IAC5D,MAAMM,eAAe,CAAC,CAAC,EAAEP,OAAO,CAAC,CAAC;IAClC,MAAMQ,iBAAiB;QACrB,CAAC,CAAC,EAAER,OAAO,CAAC,EAAEH,eAAe,IAAI,EAAEI,KAAK,CAAC,CAAC;QAC1C,CAAC,EAAE,EAAED,OAAO,CAAC,EAAEH,eAAe,gBAAgB,EAAEI,KAAK,CAAC,CAAC;KACxD;IACD,wFAAwF;IACxF,OAAO,CAAC;;;;;kCAKwB,EAAEQ,KAAKC,SAAS,CAACJ,aAAa;yBACvC,EAAEC,aAAaI,MAAM,CAAC;;;;;sCAKT,EAAEF,KAAKC,SAAS,CAACF,gBAAgB;;AAEvE,CAAC;AACD,EAAE;AAEF,OAAO,MAAMI,wBAAwB;IACnC,OAAO,CAAC;;;;;;;;;;;;;AAaV,CAAC;AACD,EAAE"}
@@ -90,15 +90,16 @@ export const parseExactPath = (path)=>path.split('/').filter(Boolean).map((name)
90
90
  type: 'literal',
91
91
  name
92
92
  }));
93
+ const escapeRegExp = (s)=>s.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
93
94
  /**
94
95
  * Transform a path spec to a regular expression.
95
96
  */ export const path2regexp = (path)=>{
96
97
  const parts = path.map((item)=>{
97
98
  if (item.type === 'literal') {
98
- return item.name;
99
+ return escapeRegExp(item.name);
99
100
  } else if (item.type === 'group') {
100
- const prefix = item.prefix ?? '';
101
- const suffix = item.suffix ?? '';
101
+ const prefix = escapeRegExp(item.prefix ?? '');
102
+ const suffix = escapeRegExp(item.suffix ?? '');
102
103
  return `${prefix}([^/]+)${suffix}`;
103
104
  } else {
104
105
  return `(.*)`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/path.ts"],"sourcesContent":["// Terminology:\n// - filePath: posix-like file path, e.g. `/foo/bar.js` or `c:/foo/bar.js`\n// This is used by Vite.\n// - fileURL: file URL, e.g. `file:///foo/bar.js` or `file:///c:/foo/bar.js`\n// This is used by import().\n// - osPath: os dependent path, e.g. `/foo/bar.js` or `c:\\foo\\bar.js`\n// This is used by node:fs.\n\nconst ABSOLUTE_WIN32_PATH_REGEXP = /^\\/[a-zA-Z]:\\//;\n\nexport const encodeFilePathToAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n throw new Error('Unsupported absolute file path: ' + filePath);\n }\n if (filePath.startsWith('/')) {\n return filePath;\n }\n return '/' + filePath;\n};\n\nexport const decodeFilePathFromAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n return filePath.slice(1);\n }\n return filePath;\n};\n\nexport const filePathToFileURL = (filePath: string) =>\n 'file://' + encodeURI(filePath);\n\nexport const fileURLToFilePath = (fileURL: string) => {\n if (!fileURL.startsWith('file://')) {\n throw new Error('Not a file URL');\n }\n return decodeURI(fileURL.slice('file://'.length));\n};\n\n// for filePath\nexport const joinPath = (...paths: string[]) => {\n const isAbsolute = paths[0]?.startsWith('/');\n const items = ([] as string[]).concat(\n ...paths.map((path) => path.split('/')),\n );\n const stack: string[] = [];\n for (const item of items) {\n if (item === '..') {\n if (stack.length && stack[stack.length - 1] !== '..') {\n stack.pop();\n } else if (!isAbsolute) {\n stack.push('..');\n }\n } else if (item && item !== '.') {\n stack.push(item);\n }\n }\n return (isAbsolute ? '/' : '') + stack.join('/') || '.';\n};\n\nexport const extname = (filePath: string) => {\n const index = filePath.lastIndexOf('.');\n if (index <= 0) {\n return '';\n }\n if (['/', '.'].includes(filePath[index - 1]!)) {\n return '';\n }\n return filePath.slice(index);\n};\n\nexport type PathSpecItem =\n | { type: 'literal'; name: string }\n | { type: 'group'; name?: string; prefix?: string; suffix?: string }\n | { type: 'wildcard'; name?: string };\nexport type PathSpec = readonly PathSpecItem[];\n\nconst SLUG_PATTERN = /^(.*?)\\[([^\\]]+)\\](.*)$/;\n\nexport const parsePathWithSlug = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => {\n const match = SLUG_PATTERN.exec(name);\n if (!match) {\n return { type: 'literal' as const, name };\n }\n const [, prefix, inner, suffix] = match;\n if (inner!.startsWith('...')) {\n return {\n type: 'wildcard' as const,\n name: inner!.slice(3),\n };\n }\n return {\n type: 'group' as const,\n name: inner!,\n ...(prefix ? { prefix } : {}),\n ...(suffix ? { suffix } : {}),\n };\n });\n\nexport const parseExactPath = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => ({ type: 'literal', name }));\n\n/**\n * Transform a path spec to a regular expression.\n */\nexport const path2regexp = (path: PathSpec) => {\n const parts = path.map((item) => {\n if (item.type === 'literal') {\n return item.name;\n } else if (item.type === 'group') {\n const prefix = item.prefix ?? '';\n const suffix = item.suffix ?? '';\n return `${prefix}([^/]+)${suffix}`;\n } else {\n return `(.*)`;\n }\n });\n return `^/${parts.join('/')}$`;\n};\n\n/** Convert a path spec to a string for the path */\nexport const pathSpecAsString = (path: PathSpec) => {\n return (\n '/' +\n path\n .map((item) => {\n if (item.type === 'literal') {\n return item.name;\n } else if (item.type === 'group') {\n const prefix = item.prefix ?? '';\n const suffix = item.suffix ?? '';\n return `${prefix}[${item.name}]${suffix}`;\n } else {\n return `[...${item.name}]`;\n }\n })\n .join('/')\n );\n};\n\n/**\n * Helper function to get the path mapping from the path spec and the pathname.\n *\n * @param pathSpec\n * @param pathname - route as a string\n * @example\n * getPathMapping(\n * [\n * { type: 'literal', name: 'foo' },\n * { type: 'group', name: 'a' },\n * ],\n * '/foo/bar',\n * );\n * // => { a: 'bar' }\n */\nexport const getPathMapping = (\n pathSpec: PathSpec,\n pathname: string,\n): Record<string, string | string[]> | null => {\n const actual = pathname.split('/').filter(Boolean);\n if (pathSpec.length > actual.length) {\n const wildcardIndex = pathSpec.findIndex(\n (spec) => spec.type === 'wildcard',\n );\n if (wildcardIndex === -1) {\n return null;\n }\n const isTerminalWildcard = wildcardIndex === pathSpec.length - 1;\n if (isTerminalWildcard) {\n // Terminal wildcards only pass through with zero actual segments\n // (handled by the root-wildcard special case below)\n if (actual.length > 0) {\n return null;\n }\n } else if (actual.length < pathSpec.length - 1) {\n // Non-terminal wildcards can match zero segments; just need enough\n // actual segments for every non-wildcard spec in the pathSpec\n return null;\n }\n }\n const mapping: Record<string, string | string[]> = {};\n let wildcardStartIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[i]!;\n if (spec.type === 'literal') {\n if (spec.name !== actual[i]) {\n return null;\n }\n } else if (spec.type === 'wildcard') {\n wildcardStartIndex = i;\n break;\n } else {\n const segment = actual[i];\n if (segment === undefined) {\n return null;\n }\n const prefix = spec.prefix ?? '';\n const suffix = spec.suffix ?? '';\n if (prefix || suffix) {\n if (!segment.startsWith(prefix) || !segment.endsWith(suffix || '')) {\n return null;\n }\n const value = segment.slice(\n prefix.length,\n suffix ? -suffix.length : undefined,\n );\n if (!value) {\n return null;\n }\n if (spec.name) {\n mapping[spec.name] = value;\n }\n } else if (spec.name) {\n mapping[spec.name] = segment;\n }\n }\n }\n if (wildcardStartIndex === -1) {\n if (pathSpec.length !== actual.length) {\n return null;\n }\n return mapping;\n }\n\n if (wildcardStartIndex === 0 && actual.length === 0) {\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = [];\n }\n return mapping;\n }\n\n let wildcardEndIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[pathSpec.length - i - 1]!;\n if (spec.type === 'literal') {\n if (spec.name !== actual[actual.length - i - 1]) {\n return null;\n }\n } else if (spec.type === 'wildcard') {\n wildcardEndIndex = actual.length - i - 1;\n break;\n } else {\n const segment = actual[actual.length - i - 1];\n if (segment === undefined) {\n return null;\n }\n const prefix = spec.prefix ?? '';\n const suffix = spec.suffix ?? '';\n if (prefix || suffix) {\n if (!segment.startsWith(prefix) || !segment.endsWith(suffix || '')) {\n return null;\n }\n const value = segment.slice(\n prefix.length,\n suffix ? -suffix.length : undefined,\n );\n if (!value) {\n return null;\n }\n if (spec.name) {\n mapping[spec.name] = value;\n }\n } else if (spec.name) {\n mapping[spec.name] = segment;\n }\n }\n }\n if (wildcardStartIndex === -1) {\n throw new Error('Invalid wildcard path');\n }\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = actual.slice(\n wildcardStartIndex,\n wildcardEndIndex + 1,\n );\n }\n return mapping;\n};\n\n// basePath config is ensured to have trailing slash (see plugin)\nexport function removeBase(url: string, base: string) {\n if (base !== '/') {\n if (!url.startsWith(base)) {\n throw new Error('pathname must start with basePath: ' + url);\n }\n return url.slice(base.length - 1);\n }\n return url;\n}\n\nexport function addBase(url: string, base: string) {\n if (base !== '/' && url.startsWith('/')) {\n return base.slice(0, -1) + url;\n }\n return url;\n}\n\nexport function countSlugsAndWildcards(pathSpec: PathSpec) {\n let numSlugs = 0;\n let numWildcards = 0;\n for (const slug of pathSpec) {\n if (slug.type !== 'literal') {\n numSlugs++;\n }\n if (slug.type === 'wildcard') {\n numWildcards++;\n }\n }\n return { numSlugs, numWildcards };\n}\n"],"names":["ABSOLUTE_WIN32_PATH_REGEXP","encodeFilePathToAbsolute","filePath","test","Error","startsWith","decodeFilePathFromAbsolute","slice","filePathToFileURL","encodeURI","fileURLToFilePath","fileURL","decodeURI","length","joinPath","paths","isAbsolute","items","concat","map","path","split","stack","item","pop","push","join","extname","index","lastIndexOf","includes","SLUG_PATTERN","parsePathWithSlug","filter","Boolean","name","match","exec","type","prefix","inner","suffix","parseExactPath","path2regexp","parts","pathSpecAsString","getPathMapping","pathSpec","pathname","actual","wildcardIndex","findIndex","spec","isTerminalWildcard","mapping","wildcardStartIndex","i","segment","undefined","endsWith","value","wildcardName","wildcardEndIndex","removeBase","url","base","addBase","countSlugsAndWildcards","numSlugs","numWildcards","slug"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lib/utils/path.ts"],"sourcesContent":["// Terminology:\n// - filePath: posix-like file path, e.g. `/foo/bar.js` or `c:/foo/bar.js`\n// This is used by Vite.\n// - fileURL: file URL, e.g. `file:///foo/bar.js` or `file:///c:/foo/bar.js`\n// This is used by import().\n// - osPath: os dependent path, e.g. `/foo/bar.js` or `c:\\foo\\bar.js`\n// This is used by node:fs.\n\nconst ABSOLUTE_WIN32_PATH_REGEXP = /^\\/[a-zA-Z]:\\//;\n\nexport const encodeFilePathToAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n throw new Error('Unsupported absolute file path: ' + filePath);\n }\n if (filePath.startsWith('/')) {\n return filePath;\n }\n return '/' + filePath;\n};\n\nexport const decodeFilePathFromAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n return filePath.slice(1);\n }\n return filePath;\n};\n\nexport const filePathToFileURL = (filePath: string) =>\n 'file://' + encodeURI(filePath);\n\nexport const fileURLToFilePath = (fileURL: string) => {\n if (!fileURL.startsWith('file://')) {\n throw new Error('Not a file URL');\n }\n return decodeURI(fileURL.slice('file://'.length));\n};\n\n// for filePath\nexport const joinPath = (...paths: string[]) => {\n const isAbsolute = paths[0]?.startsWith('/');\n const items = ([] as string[]).concat(\n ...paths.map((path) => path.split('/')),\n );\n const stack: string[] = [];\n for (const item of items) {\n if (item === '..') {\n if (stack.length && stack[stack.length - 1] !== '..') {\n stack.pop();\n } else if (!isAbsolute) {\n stack.push('..');\n }\n } else if (item && item !== '.') {\n stack.push(item);\n }\n }\n return (isAbsolute ? '/' : '') + stack.join('/') || '.';\n};\n\nexport const extname = (filePath: string) => {\n const index = filePath.lastIndexOf('.');\n if (index <= 0) {\n return '';\n }\n if (['/', '.'].includes(filePath[index - 1]!)) {\n return '';\n }\n return filePath.slice(index);\n};\n\nexport type PathSpecItem =\n | { type: 'literal'; name: string }\n | { type: 'group'; name?: string; prefix?: string; suffix?: string }\n | { type: 'wildcard'; name?: string };\nexport type PathSpec = readonly PathSpecItem[];\n\nconst SLUG_PATTERN = /^(.*?)\\[([^\\]]+)\\](.*)$/;\n\nexport const parsePathWithSlug = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => {\n const match = SLUG_PATTERN.exec(name);\n if (!match) {\n return { type: 'literal' as const, name };\n }\n const [, prefix, inner, suffix] = match;\n if (inner!.startsWith('...')) {\n return {\n type: 'wildcard' as const,\n name: inner!.slice(3),\n };\n }\n return {\n type: 'group' as const,\n name: inner!,\n ...(prefix ? { prefix } : {}),\n ...(suffix ? { suffix } : {}),\n };\n });\n\nexport const parseExactPath = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => ({ type: 'literal', name }));\n\nconst escapeRegExp = (s: string) => s.replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&');\n\n/**\n * Transform a path spec to a regular expression.\n */\nexport const path2regexp = (path: PathSpec) => {\n const parts = path.map((item) => {\n if (item.type === 'literal') {\n return escapeRegExp(item.name);\n } else if (item.type === 'group') {\n const prefix = escapeRegExp(item.prefix ?? '');\n const suffix = escapeRegExp(item.suffix ?? '');\n return `${prefix}([^/]+)${suffix}`;\n } else {\n return `(.*)`;\n }\n });\n return `^/${parts.join('/')}$`;\n};\n\n/** Convert a path spec to a string for the path */\nexport const pathSpecAsString = (path: PathSpec) => {\n return (\n '/' +\n path\n .map((item) => {\n if (item.type === 'literal') {\n return item.name;\n } else if (item.type === 'group') {\n const prefix = item.prefix ?? '';\n const suffix = item.suffix ?? '';\n return `${prefix}[${item.name}]${suffix}`;\n } else {\n return `[...${item.name}]`;\n }\n })\n .join('/')\n );\n};\n\n/**\n * Helper function to get the path mapping from the path spec and the pathname.\n *\n * @param pathSpec\n * @param pathname - route as a string\n * @example\n * getPathMapping(\n * [\n * { type: 'literal', name: 'foo' },\n * { type: 'group', name: 'a' },\n * ],\n * '/foo/bar',\n * );\n * // => { a: 'bar' }\n */\nexport const getPathMapping = (\n pathSpec: PathSpec,\n pathname: string,\n): Record<string, string | string[]> | null => {\n const actual = pathname.split('/').filter(Boolean);\n if (pathSpec.length > actual.length) {\n const wildcardIndex = pathSpec.findIndex(\n (spec) => spec.type === 'wildcard',\n );\n if (wildcardIndex === -1) {\n return null;\n }\n const isTerminalWildcard = wildcardIndex === pathSpec.length - 1;\n if (isTerminalWildcard) {\n // Terminal wildcards only pass through with zero actual segments\n // (handled by the root-wildcard special case below)\n if (actual.length > 0) {\n return null;\n }\n } else if (actual.length < pathSpec.length - 1) {\n // Non-terminal wildcards can match zero segments; just need enough\n // actual segments for every non-wildcard spec in the pathSpec\n return null;\n }\n }\n const mapping: Record<string, string | string[]> = {};\n let wildcardStartIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[i]!;\n if (spec.type === 'literal') {\n if (spec.name !== actual[i]) {\n return null;\n }\n } else if (spec.type === 'wildcard') {\n wildcardStartIndex = i;\n break;\n } else {\n const segment = actual[i];\n if (segment === undefined) {\n return null;\n }\n const prefix = spec.prefix ?? '';\n const suffix = spec.suffix ?? '';\n if (prefix || suffix) {\n if (!segment.startsWith(prefix) || !segment.endsWith(suffix || '')) {\n return null;\n }\n const value = segment.slice(\n prefix.length,\n suffix ? -suffix.length : undefined,\n );\n if (!value) {\n return null;\n }\n if (spec.name) {\n mapping[spec.name] = value;\n }\n } else if (spec.name) {\n mapping[spec.name] = segment;\n }\n }\n }\n if (wildcardStartIndex === -1) {\n if (pathSpec.length !== actual.length) {\n return null;\n }\n return mapping;\n }\n\n if (wildcardStartIndex === 0 && actual.length === 0) {\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = [];\n }\n return mapping;\n }\n\n let wildcardEndIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[pathSpec.length - i - 1]!;\n if (spec.type === 'literal') {\n if (spec.name !== actual[actual.length - i - 1]) {\n return null;\n }\n } else if (spec.type === 'wildcard') {\n wildcardEndIndex = actual.length - i - 1;\n break;\n } else {\n const segment = actual[actual.length - i - 1];\n if (segment === undefined) {\n return null;\n }\n const prefix = spec.prefix ?? '';\n const suffix = spec.suffix ?? '';\n if (prefix || suffix) {\n if (!segment.startsWith(prefix) || !segment.endsWith(suffix || '')) {\n return null;\n }\n const value = segment.slice(\n prefix.length,\n suffix ? -suffix.length : undefined,\n );\n if (!value) {\n return null;\n }\n if (spec.name) {\n mapping[spec.name] = value;\n }\n } else if (spec.name) {\n mapping[spec.name] = segment;\n }\n }\n }\n if (wildcardStartIndex === -1) {\n throw new Error('Invalid wildcard path');\n }\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = actual.slice(\n wildcardStartIndex,\n wildcardEndIndex + 1,\n );\n }\n return mapping;\n};\n\n// basePath config is ensured to have trailing slash (see plugin)\nexport function removeBase(url: string, base: string) {\n if (base !== '/') {\n if (!url.startsWith(base)) {\n throw new Error('pathname must start with basePath: ' + url);\n }\n return url.slice(base.length - 1);\n }\n return url;\n}\n\nexport function addBase(url: string, base: string) {\n if (base !== '/' && url.startsWith('/')) {\n return base.slice(0, -1) + url;\n }\n return url;\n}\n\nexport function countSlugsAndWildcards(pathSpec: PathSpec) {\n let numSlugs = 0;\n let numWildcards = 0;\n for (const slug of pathSpec) {\n if (slug.type !== 'literal') {\n numSlugs++;\n }\n if (slug.type === 'wildcard') {\n numWildcards++;\n }\n }\n return { numSlugs, numWildcards };\n}\n"],"names":["ABSOLUTE_WIN32_PATH_REGEXP","encodeFilePathToAbsolute","filePath","test","Error","startsWith","decodeFilePathFromAbsolute","slice","filePathToFileURL","encodeURI","fileURLToFilePath","fileURL","decodeURI","length","joinPath","paths","isAbsolute","items","concat","map","path","split","stack","item","pop","push","join","extname","index","lastIndexOf","includes","SLUG_PATTERN","parsePathWithSlug","filter","Boolean","name","match","exec","type","prefix","inner","suffix","parseExactPath","escapeRegExp","s","replace","path2regexp","parts","pathSpecAsString","getPathMapping","pathSpec","pathname","actual","wildcardIndex","findIndex","spec","isTerminalWildcard","mapping","wildcardStartIndex","i","segment","undefined","endsWith","value","wildcardName","wildcardEndIndex","removeBase","url","base","addBase","countSlugsAndWildcards","numSlugs","numWildcards","slug"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ declare const KEY_RSC_PATH = "p";
2
+ declare const KEY_RESPONSE = "r";
3
+ declare const KEY_CLOSE = "x";
4
+ declare const KEY_RSC_PARAMS = "q";
5
+ declare const KEY_TEMPORARY_REFERENCES = "t";
6
+ declare const KEY_DEBUG_ID = "d";
7
+ export type INTERNAL_PrefetchedEntry = {
8
+ [KEY_RSC_PATH]: string;
9
+ [KEY_RESPONSE]: Promise<Response>;
10
+ [KEY_CLOSE]?: () => void;
11
+ [KEY_RSC_PARAMS]?: unknown;
12
+ [KEY_TEMPORARY_REFERENCES]?: unknown;
13
+ [KEY_DEBUG_ID]?: string;
14
+ };
15
+ export declare const createPrefetchedEntry: (rscPath: string, response: Promise<Response>, rscParams?: unknown, temporaryReferences?: unknown) => INTERNAL_PrefetchedEntry;
16
+ export declare const getPrefetchedRscPath: (entry: INTERNAL_PrefetchedEntry) => string;
17
+ export declare const getPrefetchedResponse: (entry: INTERNAL_PrefetchedEntry) => Promise<Response>;
18
+ export declare const getPrefetchedClose: (entry: INTERNAL_PrefetchedEntry) => (() => void) | undefined;
19
+ export declare const getPrefetchedRscParams: (entry: INTERNAL_PrefetchedEntry) => unknown;
20
+ export declare const getPrefetchedTemporaryReferences: <T>(entry: INTERNAL_PrefetchedEntry) => T | undefined;
21
+ export declare const getPrefetchedDebugId: (entry: INTERNAL_PrefetchedEntry) => string | undefined;
22
+ export declare const createInitialPrefetchedEntryCode: (rscPath: string, debugId: string | undefined) => string;
23
+ export {};