waku 1.0.0-alpha.8 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +41 -28
  2. package/dist/adapters/cloudflare.js +21 -13
  3. package/dist/adapters/cloudflare.js.map +1 -1
  4. package/dist/cli.js +5 -0
  5. package/dist/cli.js.map +1 -1
  6. package/dist/lib/types.d.ts +5 -6
  7. package/dist/lib/types.js.map +1 -1
  8. package/dist/lib/utils/managed.js +10 -11
  9. package/dist/lib/utils/managed.js.map +1 -1
  10. package/dist/lib/utils/prune-build.d.ts +29 -0
  11. package/dist/lib/utils/prune-build.js +96 -0
  12. package/dist/lib/utils/prune-build.js.map +1 -0
  13. package/dist/lib/utils/render.d.ts +2 -3
  14. package/dist/lib/utils/render.js +20 -9
  15. package/dist/lib/utils/render.js.map +1 -1
  16. package/dist/lib/vite-entries/entry.browser.js +5 -0
  17. package/dist/lib/vite-entries/entry.browser.js.map +1 -1
  18. package/dist/lib/vite-entries/entry.build.d.ts +3 -1
  19. package/dist/lib/vite-entries/entry.build.js +15 -4
  20. package/dist/lib/vite-entries/entry.build.js.map +1 -1
  21. package/dist/lib/vite-plugins/adapter-alias.d.ts +4 -0
  22. package/dist/lib/vite-plugins/{default-adapter.js → adapter-alias.js} +3 -3
  23. package/dist/lib/vite-plugins/adapter-alias.js.map +1 -0
  24. package/dist/lib/vite-plugins/{user-entries.d.ts → app-entries.d.ts} +1 -1
  25. package/dist/lib/vite-plugins/{user-entries.js → app-entries.js} +3 -3
  26. package/dist/lib/vite-plugins/app-entries.js.map +1 -0
  27. package/dist/lib/vite-plugins/build-id.d.ts +2 -0
  28. package/dist/lib/vite-plugins/build-id.js +20 -0
  29. package/dist/lib/vite-plugins/build-id.js.map +1 -0
  30. package/dist/lib/vite-plugins/build-metadata.js +3 -3
  31. package/dist/lib/vite-plugins/build-metadata.js.map +1 -1
  32. package/dist/lib/vite-plugins/combined-plugins.js +14 -12
  33. package/dist/lib/vite-plugins/combined-plugins.js.map +1 -1
  34. package/dist/lib/vite-plugins/{main.d.ts → environments.d.ts} +1 -1
  35. package/dist/lib/vite-plugins/{main.js → environments.js} +3 -3
  36. package/dist/lib/vite-plugins/environments.js.map +1 -0
  37. package/dist/lib/vite-plugins/fs-router-typegen.js +3 -0
  38. package/dist/lib/vite-plugins/fs-router-typegen.js.map +1 -1
  39. package/dist/lib/vite-plugins/html-shell.d.ts +2 -0
  40. package/dist/lib/vite-plugins/{fallback-html.js → html-shell.js} +5 -5
  41. package/dist/lib/vite-plugins/html-shell.js.map +1 -0
  42. package/dist/lib/vite-plugins/patch-rsdw.js +34 -5
  43. package/dist/lib/vite-plugins/patch-rsdw.js.map +1 -1
  44. package/dist/lib/vite-plugins/rsc-devtools.d.ts +2 -0
  45. package/dist/lib/vite-plugins/{react-debug.js → rsc-devtools.js} +3 -3
  46. package/dist/lib/vite-plugins/rsc-devtools.js.map +1 -0
  47. package/dist/lib/vite-plugins/static-build.d.ts +5 -0
  48. package/dist/lib/vite-plugins/{build-static-files.js → static-build.js} +21 -4
  49. package/dist/lib/vite-plugins/static-build.js.map +1 -0
  50. package/dist/lib/vite-rsc/cmd-router.d.ts +1 -0
  51. package/dist/lib/vite-rsc/cmd-router.js +48 -0
  52. package/dist/lib/vite-rsc/cmd-router.js.map +1 -0
  53. package/dist/lib/vite-rsc/handler.js +6 -7
  54. package/dist/lib/vite-rsc/handler.js.map +1 -1
  55. package/dist/lib/vite-rsc/ssr.js +2 -2
  56. package/dist/lib/vite-rsc/ssr.js.map +1 -1
  57. package/dist/minimal/client.d.ts +3 -0
  58. package/dist/minimal/client.js +15 -1
  59. package/dist/minimal/client.js.map +1 -1
  60. package/dist/router/client.js +14 -9
  61. package/dist/router/client.js.map +1 -1
  62. package/dist/router/create-pages.d.ts +53 -6
  63. package/dist/router/create-pages.js +349 -347
  64. package/dist/router/create-pages.js.map +1 -1
  65. package/dist/router/define-router.d.ts +7 -2
  66. package/dist/router/define-router.js +314 -114
  67. package/dist/router/define-router.js.map +1 -1
  68. package/dist/router/fs-router.d.ts +18 -6
  69. package/dist/router/fs-router.js +30 -27
  70. package/dist/router/fs-router.js.map +1 -1
  71. package/dist/router/server.d.ts +1 -0
  72. package/dist/router/server.js.map +1 -1
  73. package/dist/server.d.ts +2 -0
  74. package/dist/server.js +9 -0
  75. package/dist/server.js.map +1 -1
  76. package/dist/vite-plugins.d.ts +5 -5
  77. package/dist/vite-plugins.js +5 -5
  78. package/dist/vite-plugins.js.map +1 -1
  79. package/package.json +8 -8
  80. package/dist/lib/vite-plugins/build-static-files.d.ts +0 -4
  81. package/dist/lib/vite-plugins/build-static-files.js.map +0 -1
  82. package/dist/lib/vite-plugins/default-adapter.d.ts +0 -4
  83. package/dist/lib/vite-plugins/default-adapter.js.map +0 -1
  84. package/dist/lib/vite-plugins/fallback-html.d.ts +0 -2
  85. package/dist/lib/vite-plugins/fallback-html.js.map +0 -1
  86. package/dist/lib/vite-plugins/main.js.map +0 -1
  87. package/dist/lib/vite-plugins/react-debug.d.ts +0 -2
  88. package/dist/lib/vite-plugins/react-debug.js.map +0 -1
  89. package/dist/lib/vite-plugins/user-entries.js.map +0 -1
package/README.md CHANGED
@@ -31,7 +31,7 @@ npm create waku@latest
31
31
  - `waku build` to generate a production build
32
32
  - `waku start` to serve the production build locally
33
33
 
34
- **Node.js version requirement:** `^24.0.0` or `^22.12.0` or `^20.19.0`
34
+ **Node.js version requirement:** `^26.0.0` or `^24.0.0` or `^22.12.0`
35
35
 
36
36
  ## Rendering
37
37
 
@@ -761,7 +761,7 @@ This allows you to have a `dynamic` slice component while keeping the rest of th
761
761
 
762
762
  ### Link
763
763
 
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.
764
+ 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
765
 
766
766
  ```tsx
767
767
  // ./src/pages/index.tsx
@@ -1027,6 +1027,26 @@ export const getConfig = async () => {
1027
1027
  };
1028
1028
  ```
1029
1029
 
1030
+ ## Middleware
1031
+
1032
+ 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`.
1033
+
1034
+ ```ts
1035
+ // ./src/middleware/logger.ts
1036
+ import type { MiddlewareHandler } from 'hono';
1037
+
1038
+ const logger = (): MiddlewareHandler => {
1039
+ return async (c, next) => {
1040
+ console.log(c.req.method, c.req.path);
1041
+ await next();
1042
+ };
1043
+ };
1044
+
1045
+ export default logger;
1046
+ ```
1047
+
1048
+ If you provide a custom `./src/waku.server.tsx`, pass middleware through the adapter options with `middlewareModules` or `middlewareFns`.
1049
+
1030
1050
  ## Data fetching
1031
1051
 
1032
1052
  ### Server
@@ -1448,16 +1468,15 @@ vercel
1448
1468
 
1449
1469
  For advanced users who want to avoid deploying functions, use the server entry file with the Vercel adapter and specify the `static` option.
1450
1470
 
1451
- `./src/waku.server.ts`:
1471
+ `./src/waku.server.tsx`:
1452
1472
 
1453
1473
  ```ts
1454
1474
  import { fsRouter } from 'waku';
1455
1475
  import adapter from 'waku/adapters/vercel';
1456
1476
 
1457
- export default adapter(
1458
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1459
- { static: true },
1460
- );
1477
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1478
+ static: true,
1479
+ });
1461
1480
  ```
1462
1481
 
1463
1482
  ### Netlify
@@ -1473,16 +1492,15 @@ netlify deploy
1473
1492
 
1474
1493
  For advanced users who want to avoid deploying functions, use the server entry file with the Netlify adapter and specify the `static` option.
1475
1494
 
1476
- `./src/waku.server.ts`:
1495
+ `./src/waku.server.tsx`:
1477
1496
 
1478
1497
  ```ts
1479
1498
  import { fsRouter } from 'waku';
1480
1499
  import adapter from 'waku/adapters/netlify';
1481
1500
 
1482
- export default adapter(
1483
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1484
- { static: true },
1485
- );
1501
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1502
+ static: true,
1503
+ });
1486
1504
  ```
1487
1505
 
1488
1506
  ### Cloudflare Workers
@@ -1496,29 +1514,26 @@ wrangler deploy
1496
1514
 
1497
1515
  #### Pure SSG with Cloudflare Workers
1498
1516
 
1499
- `./src/waku.server.ts`:
1517
+ `./src/waku.server.tsx`:
1500
1518
 
1501
1519
  ```ts
1502
1520
  import { fsRouter } from 'waku';
1503
1521
  import adapter from 'waku/adapters/cloudflare';
1504
1522
 
1505
- export default adapter(
1506
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1507
- { static: true },
1508
- );
1523
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')), {
1524
+ static: true,
1525
+ });
1509
1526
  ```
1510
1527
 
1511
1528
  ### Deno Deploy (experimental)
1512
1529
 
1513
- `./src/waku.server.ts`:
1530
+ `./src/waku.server.tsx`:
1514
1531
 
1515
1532
  ```ts
1516
1533
  import { fsRouter } from 'waku';
1517
1534
  import adapter from 'waku/adapters/deno';
1518
1535
 
1519
- export default adapter(
1520
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1521
- );
1536
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')));
1522
1537
  ```
1523
1538
 
1524
1539
  ```sh
@@ -1528,15 +1543,13 @@ deployctl deploy --prod dist/serve-deno.js --exclude node_modules
1528
1543
 
1529
1544
  ### Bun (experimental)
1530
1545
 
1531
- `./src/waku.server.ts`:
1546
+ `./src/waku.server.tsx`:
1532
1547
 
1533
1548
  ```ts
1534
1549
  import { fsRouter } from 'waku';
1535
1550
  import adapter from 'waku/adapters/bun';
1536
1551
 
1537
- export default adapter(
1538
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1539
- );
1552
+ export default adapter(fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')));
1540
1553
  ```
1541
1554
 
1542
1555
  ```sh
@@ -1545,15 +1558,15 @@ npm run build
1545
1558
 
1546
1559
  ### AWS Lambda (experimental)
1547
1560
 
1548
- `./src/waku.server.ts`:
1561
+ `./src/waku.server.tsx`:
1549
1562
 
1550
1563
  ```ts
1551
1564
  import { fsRouter } from 'waku';
1552
1565
  import adapter from 'waku/adapters/aws-lambda';
1553
1566
 
1554
1567
  export default adapter(
1555
- fsRouter(import.meta.glob('./**/*.{tsx,ts}', { base: './pages' })),
1556
- streaming: false, // optional, default is false
1568
+ fsRouter(import.meta.glob('./pages/**/*.{tsx,ts}')),
1569
+ { streaming: false }, // optional, default is false
1557
1570
  );
1558
1571
  ```
1559
1572
 
@@ -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,19 @@ 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
103
  const response = await fetch(server.baseUrl + internalPathToBuildStaticFiles);
102
- await consumeMultiplexedStream(response.body, utils.emitFile);
104
+ await consumeMultiplexedStream(response.body, async (key, stream)=>{
105
+ if (key.startsWith(PRUNABLE_KEY_PREFIX)) {
106
+ utils.unstable_registerPrunableFile(key.slice(PRUNABLE_KEY_PREFIX.length));
107
+ return;
108
+ }
109
+ await utils.emitFile(key, stream);
110
+ });
103
111
  await server.close();
104
112
  },
105
113
  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 );\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 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","key","stream","startsWith","slice","length","buildEnhancers","defaultExport","handlers"],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -40,6 +40,10 @@ async function run() {
40
40
  } else if (cmd === 'start') {
41
41
  const { runStart } = await import('./lib/vite-rsc/cmd-start.js');
42
42
  await runStart(values);
43
+ } else if (cmd === 'router') {
44
+ const { runRouter } = await import('./lib/vite-rsc/cmd-router.js');
45
+ await runRouter(positionals[1]);
46
+ process.exit(0);
43
47
  } else {
44
48
  if (cmd) {
45
49
  console.error('Unknown command:', cmd);
@@ -55,6 +59,7 @@ Commands:
55
59
  dev Start the development server
56
60
  build Build the application for production
57
61
  start Start the production server
62
+ router Router subcommands (run 'waku router' for details)
58
63
 
59
64
  Options:
60
65
  -h, --host Hostname to bind (e.g. 0.0.0.0)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport process from 'node:process';\nimport { parseArgs } from 'node:util';\n\nconst require = createRequire(new URL('.', import.meta.url));\n\nconst { values, positionals } = parseArgs({\n args: process.argv.slice(2),\n allowPositionals: true,\n options: {\n host: {\n type: 'string',\n short: 'h',\n },\n port: {\n type: 'string',\n short: 'p',\n },\n version: {\n type: 'boolean',\n short: 'v',\n },\n help: {\n type: 'boolean',\n },\n },\n});\n\nconst cmd = positionals[0];\n\nasync function run() {\n if (values.version) {\n const { version } = require('../package.json');\n console.log(version);\n } else if (values.help) {\n displayUsage();\n } else if (cmd === 'dev') {\n const { runDev } = await import('./lib/vite-rsc/cmd-dev.js');\n await runDev(values);\n } else if (cmd === 'build') {\n const { runBuild } = await import('./lib/vite-rsc/cmd-build.js');\n await runBuild();\n process.exit(0);\n } else if (cmd === 'start') {\n const { runStart } = await import('./lib/vite-rsc/cmd-start.js');\n await runStart(values);\n } else {\n if (cmd) {\n console.error('Unknown command:', cmd);\n }\n displayUsage();\n }\n}\n\nfunction displayUsage() {\n console.log(`\nUsage: waku [options] <command>\n\nCommands:\n dev Start the development server\n build Build the application for production\n start Start the production server\n\nOptions:\n -h, --host Hostname to bind (e.g. 0.0.0.0)\n -p, --port Port number for the server\n -v, --version Display the version number\n --help Display this help message\n`);\n}\n\nrun().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"names":["createRequire","process","parseArgs","require","URL","url","values","positionals","args","argv","slice","allowPositionals","options","host","type","short","port","version","help","cmd","run","console","log","displayUsage","runDev","runBuild","exit","runStart","error","catch"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;AAC5C,OAAOC,aAAa,eAAe;AACnC,SAASC,SAAS,QAAQ,YAAY;AAEtC,MAAMC,UAAUH,cAAc,IAAII,IAAI,KAAK,YAAYC,GAAG;AAE1D,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGL,UAAU;IACxCM,MAAMP,QAAQQ,IAAI,CAACC,KAAK,CAAC;IACzBC,kBAAkB;IAClBC,SAAS;QACPC,MAAM;YACJC,MAAM;YACNC,OAAO;QACT;QACAC,MAAM;YACJF,MAAM;YACNC,OAAO;QACT;QACAE,SAAS;YACPH,MAAM;YACNC,OAAO;QACT;QACAG,MAAM;YACJJ,MAAM;QACR;IACF;AACF;AAEA,MAAMK,MAAMZ,WAAW,CAAC,EAAE;AAE1B,eAAea;IACb,IAAId,OAAOW,OAAO,EAAE;QAClB,MAAM,EAAEA,OAAO,EAAE,GAAGd,QAAQ;QAC5BkB,QAAQC,GAAG,CAACL;IACd,OAAO,IAAIX,OAAOY,IAAI,EAAE;QACtBK;IACF,OAAO,IAAIJ,QAAQ,OAAO;QACxB,MAAM,EAAEK,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC;QAChC,MAAMA,OAAOlB;IACf,OAAO,IAAIa,QAAQ,SAAS;QAC1B,MAAM,EAAEM,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;QAClC,MAAMA;QACNxB,QAAQyB,IAAI,CAAC;IACf,OAAO,IAAIP,QAAQ,SAAS;QAC1B,MAAM,EAAEQ,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;QAClC,MAAMA,SAASrB;IACjB,OAAO;QACL,IAAIa,KAAK;YACPE,QAAQO,KAAK,CAAC,oBAAoBT;QACpC;QACAI;IACF;AACF;AAEA,SAASA;IACPF,QAAQC,GAAG,CAAC,CAAC;;;;;;;;;;;;;AAaf,CAAC;AACD;AAEAF,MAAMS,KAAK,CAAC,CAACD;IACXP,QAAQO,KAAK,CAACA;IACd3B,QAAQyB,IAAI,CAAC;AACf"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport process from 'node:process';\nimport { parseArgs } from 'node:util';\n\nconst require = createRequire(new URL('.', import.meta.url));\n\nconst { values, positionals } = parseArgs({\n args: process.argv.slice(2),\n allowPositionals: true,\n options: {\n host: {\n type: 'string',\n short: 'h',\n },\n port: {\n type: 'string',\n short: 'p',\n },\n version: {\n type: 'boolean',\n short: 'v',\n },\n help: {\n type: 'boolean',\n },\n },\n});\n\nconst cmd = positionals[0];\n\nasync function run() {\n if (values.version) {\n const { version } = require('../package.json');\n console.log(version);\n } else if (values.help) {\n displayUsage();\n } else if (cmd === 'dev') {\n const { runDev } = await import('./lib/vite-rsc/cmd-dev.js');\n await runDev(values);\n } else if (cmd === 'build') {\n const { runBuild } = await import('./lib/vite-rsc/cmd-build.js');\n await runBuild();\n process.exit(0);\n } else if (cmd === 'start') {\n const { runStart } = await import('./lib/vite-rsc/cmd-start.js');\n await runStart(values);\n } else if (cmd === 'router') {\n const { runRouter } = await import('./lib/vite-rsc/cmd-router.js');\n await runRouter(positionals[1]);\n process.exit(0);\n } else {\n if (cmd) {\n console.error('Unknown command:', cmd);\n }\n displayUsage();\n }\n}\n\nfunction displayUsage() {\n console.log(`\nUsage: waku [options] <command>\n\nCommands:\n dev Start the development server\n build Build the application for production\n start Start the production server\n router Router subcommands (run 'waku router' for details)\n\nOptions:\n -h, --host Hostname to bind (e.g. 0.0.0.0)\n -p, --port Port number for the server\n -v, --version Display the version number\n --help Display this help message\n`);\n}\n\nrun().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"names":["createRequire","process","parseArgs","require","URL","url","values","positionals","args","argv","slice","allowPositionals","options","host","type","short","port","version","help","cmd","run","console","log","displayUsage","runDev","runBuild","exit","runStart","runRouter","error","catch"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;AAC5C,OAAOC,aAAa,eAAe;AACnC,SAASC,SAAS,QAAQ,YAAY;AAEtC,MAAMC,UAAUH,cAAc,IAAII,IAAI,KAAK,YAAYC,GAAG;AAE1D,MAAM,EAAEC,MAAM,EAAEC,WAAW,EAAE,GAAGL,UAAU;IACxCM,MAAMP,QAAQQ,IAAI,CAACC,KAAK,CAAC;IACzBC,kBAAkB;IAClBC,SAAS;QACPC,MAAM;YACJC,MAAM;YACNC,OAAO;QACT;QACAC,MAAM;YACJF,MAAM;YACNC,OAAO;QACT;QACAE,SAAS;YACPH,MAAM;YACNC,OAAO;QACT;QACAG,MAAM;YACJJ,MAAM;QACR;IACF;AACF;AAEA,MAAMK,MAAMZ,WAAW,CAAC,EAAE;AAE1B,eAAea;IACb,IAAId,OAAOW,OAAO,EAAE;QAClB,MAAM,EAAEA,OAAO,EAAE,GAAGd,QAAQ;QAC5BkB,QAAQC,GAAG,CAACL;IACd,OAAO,IAAIX,OAAOY,IAAI,EAAE;QACtBK;IACF,OAAO,IAAIJ,QAAQ,OAAO;QACxB,MAAM,EAAEK,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC;QAChC,MAAMA,OAAOlB;IACf,OAAO,IAAIa,QAAQ,SAAS;QAC1B,MAAM,EAAEM,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;QAClC,MAAMA;QACNxB,QAAQyB,IAAI,CAAC;IACf,OAAO,IAAIP,QAAQ,SAAS;QAC1B,MAAM,EAAEQ,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC;QAClC,MAAMA,SAASrB;IACjB,OAAO,IAAIa,QAAQ,UAAU;QAC3B,MAAM,EAAES,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC;QACnC,MAAMA,UAAUrB,WAAW,CAAC,EAAE;QAC9BN,QAAQyB,IAAI,CAAC;IACf,OAAO;QACL,IAAIP,KAAK;YACPE,QAAQQ,KAAK,CAAC,oBAAoBV;QACpC;QACAI;IACF;AACF;AAEA,SAASA;IACPF,QAAQC,GAAG,CAAC,CAAC;;;;;;;;;;;;;;AAcf,CAAC;AACD;AAEAF,MAAMU,KAAK,CAAC,CAACD;IACXR,QAAQQ,KAAK,CAACA;IACd5B,QAAQyB,IAAI,CAAC;AACf"}
@@ -2,9 +2,9 @@ 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
- export type Unstable_RenderRscForParse = (elements: Elements) => Promise<ReadableStream>;
8
8
  export type Unstable_ParseRsc = (rscStream: ReadableStream) => Promise<Elements>;
9
9
  export type Unstable_RenderHtml = (elementsStream: ReadableStream, html: ReactNode, options: {
10
10
  rscPath: string;
@@ -32,7 +32,6 @@ export type Unstable_HandleRequest = (input: ({
32
32
  req: Request;
33
33
  }, utils: {
34
34
  renderRsc: Unstable_RenderRsc;
35
- renderRscForParse: Unstable_RenderRscForParse;
36
35
  parseRsc: Unstable_ParseRsc;
37
36
  renderHtml: Unstable_RenderHtml;
38
37
  loadBuildMetadata: (key: string) => Promise<string | undefined>;
@@ -46,6 +45,7 @@ export type Unstable_HandleBuild = (utils: {
46
45
  withRequest: <T>(req: Request, fn: () => T) => T;
47
46
  generateFile: (fileName: string, body: ReadableStream | string) => Promise<void>;
48
47
  generateDefaultHtml: (fileName: string) => Promise<void>;
48
+ unstable_registerPrunableFile: (srcPath: string) => void;
49
49
  }) => Promise<void>;
50
50
  export type Unstable_Handlers = {
51
51
  handleRequest: Unstable_HandleRequest;
@@ -56,16 +56,15 @@ export type Unstable_ServerEntry = {
56
56
  fetch: (req: Request, ...args: any[]) => Response | Promise<Response>;
57
57
  build: (utils: {
58
58
  emitFile: Unstable_EmitFile;
59
+ unstable_registerPrunableFile: (srcPath: string) => void;
59
60
  }, ...args: any[]) => Promise<void>;
60
61
  buildOptions?: Record<string, unknown>;
61
62
  buildEnhancers?: string[];
62
63
  defaultExport?: unknown;
63
64
  [someOtherProperty: string]: unknown;
64
65
  };
65
- export type Unstable_ProcessRequest = (req: Request) => Promise<Response | null>;
66
- export type Unstable_ProcessBuild = (utils: {
67
- emitFile: Unstable_EmitFile;
68
- }) => 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>;
69
68
  export type Unstable_CreateServerEntryAdapter = <Options>(fn: (args: {
70
69
  handlers: Unstable_Handlers;
71
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\n// Experimental: render RSC only for parse/copy flows without a debug channel.\nexport type Unstable_RenderRscForParse = (\n elements: Elements,\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 renderRscForParse: Unstable_RenderRscForParse;\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":"AA0GA,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"}
@@ -0,0 +1,29 @@
1
+ type Chunk = {
2
+ type: 'chunk';
3
+ fileName: string;
4
+ imports: string[];
5
+ dynamicImports: string[];
6
+ facadeModuleId: string | null;
7
+ isDynamicEntry: boolean;
8
+ isEntry: boolean;
9
+ name: string;
10
+ viteMetadata?: {
11
+ importedAssets?: Set<string>;
12
+ importedCss?: Set<string>;
13
+ };
14
+ };
15
+ type Asset = {
16
+ type: 'asset';
17
+ fileName: string;
18
+ };
19
+ export declare const pruneBuildOutput: ({ rootDir, srcDir, distDir, rscBundle, prunableFiles, }: {
20
+ rootDir: string;
21
+ srcDir: string;
22
+ distDir: string;
23
+ rscBundle: Record<string, Chunk | Asset>;
24
+ prunableFiles: string[];
25
+ }) => Promise<{
26
+ stubbedChunks: string[];
27
+ deletedAssets: string[];
28
+ }>;
29
+ export {};
@@ -0,0 +1,96 @@
1
+ import { rm, writeFile } from 'node:fs/promises';
2
+ import { DIST_SERVER } from '../constants.js';
3
+ import { joinPath } from './path.js';
4
+ // Removes server-bundle files unreachable except via `prunableFiles`:
5
+ // - chunks: stubbed (so dynamic imports still resolve)
6
+ // - emitted assets (CSS, fonts, wasm, ...): deleted
7
+ // Reachability roots are bundle entries plus non-pruned dynamic-entry chunks.
8
+ export const pruneBuildOutput = async ({ rootDir, srcDir, distDir, rscBundle, prunableFiles })=>{
9
+ if (prunableFiles.length === 0) {
10
+ return {
11
+ stubbedChunks: [],
12
+ deletedAssets: []
13
+ };
14
+ }
15
+ const prunableModuleIds = new Set(prunableFiles.map((p)=>joinPath(rootDir, srcDir, p)));
16
+ const chunks = [];
17
+ const assets = [];
18
+ for (const item of Object.values(rscBundle)){
19
+ if (item.type === 'chunk') {
20
+ chunks.push(item);
21
+ } else {
22
+ assets.push(item);
23
+ }
24
+ }
25
+ const chunkMap = new Map(chunks.map((c)=>[
26
+ c.fileName,
27
+ c
28
+ ]));
29
+ const viteAssetsOf = (chunk)=>[
30
+ ...chunk.viteMetadata?.importedAssets ?? [],
31
+ ...chunk.viteMetadata?.importedCss ?? []
32
+ ];
33
+ // Standalone assets (e.g. `wrangler.json` from @cloudflare/vite-plugin)
34
+ // aren't ours to manage.
35
+ const chunkImportedAssets = new Set();
36
+ for (const chunk of chunks){
37
+ for (const a of viteAssetsOf(chunk)){
38
+ chunkImportedAssets.add(a);
39
+ }
40
+ }
41
+ const allDynamicEntryFiles = new Set();
42
+ const keepRoots = [];
43
+ for (const chunk of chunks){
44
+ if (chunk.isDynamicEntry) {
45
+ allDynamicEntryFiles.add(chunk.fileName);
46
+ const isPrunable = chunk.facadeModuleId && prunableModuleIds.has(chunk.facadeModuleId);
47
+ if (!isPrunable) {
48
+ keepRoots.push(chunk.fileName);
49
+ }
50
+ }
51
+ // The 'build' entry is the SSG runner, not part of the runtime bundle.
52
+ if (chunk.isEntry && chunk.name !== 'build') {
53
+ keepRoots.push(chunk.fileName);
54
+ }
55
+ }
56
+ // Each page subtree is evaluated independently - don't follow dynamic
57
+ // imports across other dynamic-entry chunks.
58
+ const keepFiles = new Set();
59
+ const visit = (fileName)=>{
60
+ if (keepFiles.has(fileName)) {
61
+ return;
62
+ }
63
+ keepFiles.add(fileName);
64
+ const chunk = chunkMap.get(fileName);
65
+ if (!chunk) {
66
+ return;
67
+ }
68
+ for (const imp of chunk.imports){
69
+ visit(imp);
70
+ }
71
+ for (const dyn of chunk.dynamicImports){
72
+ if (!allDynamicEntryFiles.has(dyn)) {
73
+ visit(dyn);
74
+ }
75
+ }
76
+ for (const a of viteAssetsOf(chunk)){
77
+ keepFiles.add(a);
78
+ }
79
+ };
80
+ keepRoots.forEach(visit);
81
+ const serverDir = joinPath(rootDir, distDir, DIST_SERVER);
82
+ const stubbedChunks = chunks.map((c)=>c.fileName).filter((f)=>!keepFiles.has(f));
83
+ const deletedAssets = assets.map((a)=>a.fileName).filter((f)=>chunkImportedAssets.has(f) && !keepFiles.has(f));
84
+ await Promise.all([
85
+ ...stubbedChunks.map((f)=>writeFile(joinPath(serverDir, f), '// Pruned by Waku - content cached at build time.\n')),
86
+ ...deletedAssets.map((f)=>rm(joinPath(serverDir, f), {
87
+ force: true
88
+ }))
89
+ ]);
90
+ return {
91
+ stubbedChunks,
92
+ deletedAssets
93
+ };
94
+ };
95
+
96
+ //# sourceMappingURL=prune-build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils/prune-build.ts"],"sourcesContent":["import { rm, writeFile } from 'node:fs/promises';\nimport { DIST_SERVER } from '../constants.js';\nimport { joinPath } from './path.js';\n\ntype Chunk = {\n type: 'chunk';\n fileName: string;\n imports: string[];\n dynamicImports: string[];\n facadeModuleId: string | null;\n isDynamicEntry: boolean;\n isEntry: boolean;\n name: string;\n viteMetadata?: {\n importedAssets?: Set<string>;\n importedCss?: Set<string>;\n };\n};\ntype Asset = {\n type: 'asset';\n fileName: string;\n};\n\n// Removes server-bundle files unreachable except via `prunableFiles`:\n// - chunks: stubbed (so dynamic imports still resolve)\n// - emitted assets (CSS, fonts, wasm, ...): deleted\n// Reachability roots are bundle entries plus non-pruned dynamic-entry chunks.\nexport const pruneBuildOutput = async ({\n rootDir,\n srcDir,\n distDir,\n rscBundle,\n prunableFiles,\n}: {\n rootDir: string;\n srcDir: string;\n distDir: string;\n rscBundle: Record<string, Chunk | Asset>;\n prunableFiles: string[];\n}): Promise<{ stubbedChunks: string[]; deletedAssets: string[] }> => {\n if (prunableFiles.length === 0) {\n return { stubbedChunks: [], deletedAssets: [] };\n }\n const prunableModuleIds = new Set(\n prunableFiles.map((p) => joinPath(rootDir, srcDir, p)),\n );\n\n const chunks: Chunk[] = [];\n const assets: Asset[] = [];\n for (const item of Object.values(rscBundle)) {\n if (item.type === 'chunk') {\n chunks.push(item);\n } else {\n assets.push(item);\n }\n }\n const chunkMap = new Map(chunks.map((c) => [c.fileName, c]));\n\n const viteAssetsOf = (chunk: Chunk) => [\n ...(chunk.viteMetadata?.importedAssets ?? []),\n ...(chunk.viteMetadata?.importedCss ?? []),\n ];\n\n // Standalone assets (e.g. `wrangler.json` from @cloudflare/vite-plugin)\n // aren't ours to manage.\n const chunkImportedAssets = new Set<string>();\n for (const chunk of chunks) {\n for (const a of viteAssetsOf(chunk)) {\n chunkImportedAssets.add(a);\n }\n }\n\n const allDynamicEntryFiles = new Set<string>();\n const keepRoots: string[] = [];\n for (const chunk of chunks) {\n if (chunk.isDynamicEntry) {\n allDynamicEntryFiles.add(chunk.fileName);\n const isPrunable =\n chunk.facadeModuleId && prunableModuleIds.has(chunk.facadeModuleId);\n if (!isPrunable) {\n keepRoots.push(chunk.fileName);\n }\n }\n // The 'build' entry is the SSG runner, not part of the runtime bundle.\n if (chunk.isEntry && chunk.name !== 'build') {\n keepRoots.push(chunk.fileName);\n }\n }\n\n // Each page subtree is evaluated independently - don't follow dynamic\n // imports across other dynamic-entry chunks.\n const keepFiles = new Set<string>();\n const visit = (fileName: string) => {\n if (keepFiles.has(fileName)) {\n return;\n }\n keepFiles.add(fileName);\n const chunk = chunkMap.get(fileName);\n if (!chunk) {\n return;\n }\n for (const imp of chunk.imports) {\n visit(imp);\n }\n for (const dyn of chunk.dynamicImports) {\n if (!allDynamicEntryFiles.has(dyn)) {\n visit(dyn);\n }\n }\n for (const a of viteAssetsOf(chunk)) {\n keepFiles.add(a);\n }\n };\n keepRoots.forEach(visit);\n\n const serverDir = joinPath(rootDir, distDir, DIST_SERVER);\n const stubbedChunks = chunks\n .map((c) => c.fileName)\n .filter((f) => !keepFiles.has(f));\n const deletedAssets = assets\n .map((a) => a.fileName)\n .filter((f) => chunkImportedAssets.has(f) && !keepFiles.has(f));\n\n await Promise.all([\n ...stubbedChunks.map((f) =>\n writeFile(\n joinPath(serverDir, f),\n '// Pruned by Waku - content cached at build time.\\n',\n ),\n ),\n ...deletedAssets.map((f) => rm(joinPath(serverDir, f), { force: true })),\n ]);\n\n return { stubbedChunks, deletedAssets };\n};\n"],"names":["rm","writeFile","DIST_SERVER","joinPath","pruneBuildOutput","rootDir","srcDir","distDir","rscBundle","prunableFiles","length","stubbedChunks","deletedAssets","prunableModuleIds","Set","map","p","chunks","assets","item","Object","values","type","push","chunkMap","Map","c","fileName","viteAssetsOf","chunk","viteMetadata","importedAssets","importedCss","chunkImportedAssets","a","add","allDynamicEntryFiles","keepRoots","isDynamicEntry","isPrunable","facadeModuleId","has","isEntry","name","keepFiles","visit","get","imp","imports","dyn","dynamicImports","forEach","serverDir","filter","f","Promise","all","force"],"mappings":"AAAA,SAASA,EAAE,EAAEC,SAAS,QAAQ,mBAAmB;AACjD,SAASC,WAAW,QAAQ,kBAAkB;AAC9C,SAASC,QAAQ,QAAQ,YAAY;AAqBrC,sEAAsE;AACtE,uDAAuD;AACvD,oDAAoD;AACpD,8EAA8E;AAC9E,OAAO,MAAMC,mBAAmB,OAAO,EACrCC,OAAO,EACPC,MAAM,EACNC,OAAO,EACPC,SAAS,EACTC,aAAa,EAOd;IACC,IAAIA,cAAcC,MAAM,KAAK,GAAG;QAC9B,OAAO;YAAEC,eAAe,EAAE;YAAEC,eAAe,EAAE;QAAC;IAChD;IACA,MAAMC,oBAAoB,IAAIC,IAC5BL,cAAcM,GAAG,CAAC,CAACC,IAAMb,SAASE,SAASC,QAAQU;IAGrD,MAAMC,SAAkB,EAAE;IAC1B,MAAMC,SAAkB,EAAE;IAC1B,KAAK,MAAMC,QAAQC,OAAOC,MAAM,CAACb,WAAY;QAC3C,IAAIW,KAAKG,IAAI,KAAK,SAAS;YACzBL,OAAOM,IAAI,CAACJ;QACd,OAAO;YACLD,OAAOK,IAAI,CAACJ;QACd;IACF;IACA,MAAMK,WAAW,IAAIC,IAAIR,OAAOF,GAAG,CAAC,CAACW,IAAM;YAACA,EAAEC,QAAQ;YAAED;SAAE;IAE1D,MAAME,eAAe,CAACC,QAAiB;eACjCA,MAAMC,YAAY,EAAEC,kBAAkB,EAAE;eACxCF,MAAMC,YAAY,EAAEE,eAAe,EAAE;SAC1C;IAED,wEAAwE;IACxE,yBAAyB;IACzB,MAAMC,sBAAsB,IAAInB;IAChC,KAAK,MAAMe,SAASZ,OAAQ;QAC1B,KAAK,MAAMiB,KAAKN,aAAaC,OAAQ;YACnCI,oBAAoBE,GAAG,CAACD;QAC1B;IACF;IAEA,MAAME,uBAAuB,IAAItB;IACjC,MAAMuB,YAAsB,EAAE;IAC9B,KAAK,MAAMR,SAASZ,OAAQ;QAC1B,IAAIY,MAAMS,cAAc,EAAE;YACxBF,qBAAqBD,GAAG,CAACN,MAAMF,QAAQ;YACvC,MAAMY,aACJV,MAAMW,cAAc,IAAI3B,kBAAkB4B,GAAG,CAACZ,MAAMW,cAAc;YACpE,IAAI,CAACD,YAAY;gBACfF,UAAUd,IAAI,CAACM,MAAMF,QAAQ;YAC/B;QACF;QACA,uEAAuE;QACvE,IAAIE,MAAMa,OAAO,IAAIb,MAAMc,IAAI,KAAK,SAAS;YAC3CN,UAAUd,IAAI,CAACM,MAAMF,QAAQ;QAC/B;IACF;IAEA,sEAAsE;IACtE,6CAA6C;IAC7C,MAAMiB,YAAY,IAAI9B;IACtB,MAAM+B,QAAQ,CAAClB;QACb,IAAIiB,UAAUH,GAAG,CAACd,WAAW;YAC3B;QACF;QACAiB,UAAUT,GAAG,CAACR;QACd,MAAME,QAAQL,SAASsB,GAAG,CAACnB;QAC3B,IAAI,CAACE,OAAO;YACV;QACF;QACA,KAAK,MAAMkB,OAAOlB,MAAMmB,OAAO,CAAE;YAC/BH,MAAME;QACR;QACA,KAAK,MAAME,OAAOpB,MAAMqB,cAAc,CAAE;YACtC,IAAI,CAACd,qBAAqBK,GAAG,CAACQ,MAAM;gBAClCJ,MAAMI;YACR;QACF;QACA,KAAK,MAAMf,KAAKN,aAAaC,OAAQ;YACnCe,UAAUT,GAAG,CAACD;QAChB;IACF;IACAG,UAAUc,OAAO,CAACN;IAElB,MAAMO,YAAYjD,SAASE,SAASE,SAASL;IAC7C,MAAMS,gBAAgBM,OACnBF,GAAG,CAAC,CAACW,IAAMA,EAAEC,QAAQ,EACrB0B,MAAM,CAAC,CAACC,IAAM,CAACV,UAAUH,GAAG,CAACa;IAChC,MAAM1C,gBAAgBM,OACnBH,GAAG,CAAC,CAACmB,IAAMA,EAAEP,QAAQ,EACrB0B,MAAM,CAAC,CAACC,IAAMrB,oBAAoBQ,GAAG,CAACa,MAAM,CAACV,UAAUH,GAAG,CAACa;IAE9D,MAAMC,QAAQC,GAAG,CAAC;WACb7C,cAAcI,GAAG,CAAC,CAACuC,IACpBrD,UACEE,SAASiD,WAAWE,IACpB;WAGD1C,cAAcG,GAAG,CAAC,CAACuC,IAAMtD,GAAGG,SAASiD,WAAWE,IAAI;gBAAEG,OAAO;YAAK;KACtE;IAED,OAAO;QAAE9C;QAAeC;IAAc;AACxC,EAAE"}
@@ -1,10 +1,9 @@
1
- import type { Unstable_ParseRsc, Unstable_RenderHtml, Unstable_RenderRsc, Unstable_RenderRscForParse } from '../types.js';
2
- export declare function createRenderUtils(temporaryReferences: unknown, renderToReadableStream: (data: unknown, options?: object, extraOptions?: object) => ReadableStream, createFromReadableStream: (stream: ReadableStream, options?: object) => Promise<unknown>, loadSsrEntryModule: () => Promise<typeof import('../vite-entries/entry.ssr.js')>, debugChannel?: {
1
+ import type { Unstable_ParseRsc, Unstable_RenderHtml, Unstable_RenderRsc } from '../types.js';
2
+ export declare function createRenderUtils(temporaryReferences: unknown, renderToReadableStream: (data: unknown, options?: object, extraOptions?: object) => ReadableStream, createFromReadableStream: (stream: ReadableStream, options?: object) => Promise<unknown>, loadSsrEntryModule: () => Promise<typeof import('../vite-entries/entry.ssr.js')>, buildId: string, debugChannel?: {
3
3
  readable?: ReadableStream;
4
4
  writable?: WritableStream;
5
5
  }, debugId?: string): {
6
6
  renderRsc: Unstable_RenderRsc;
7
- renderRscForParse: Unstable_RenderRscForParse;
8
7
  parseRsc: Unstable_ParseRsc;
9
8
  renderHtml: Unstable_RenderHtml;
10
9
  };