waku 1.0.0-beta.7 → 1.0.0-beta.8

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 (88) hide show
  1. package/README.md +1 -1
  2. package/dist/lib/types.d.ts +10 -9
  3. package/dist/lib/types.js.map +1 -1
  4. package/dist/lib/utils/react-debug-channel.js +7 -0
  5. package/dist/lib/utils/react-debug-channel.js.map +1 -1
  6. package/dist/lib/utils/render.d.ts +2 -3
  7. package/dist/lib/utils/render.js +1 -4
  8. package/dist/lib/utils/render.js.map +1 -1
  9. package/dist/lib/utils/request.d.ts +10 -6
  10. package/dist/lib/utils/request.js +24 -19
  11. package/dist/lib/utils/request.js.map +1 -1
  12. package/dist/lib/vite-plugins/patch-rsdw.js +8 -2
  13. package/dist/lib/vite-plugins/patch-rsdw.js.map +1 -1
  14. package/dist/lib/vite-rsc/cmd-dev.js +11 -8
  15. package/dist/lib/vite-rsc/cmd-dev.js.map +1 -1
  16. package/dist/lib/vite-rsc/cmd-start.js +2 -1
  17. package/dist/lib/vite-rsc/cmd-start.js.map +1 -1
  18. package/dist/lib/vite-rsc/handler.js +3 -4
  19. package/dist/lib/vite-rsc/handler.js.map +1 -1
  20. package/dist/minimal/client.d.ts +3 -0
  21. package/dist/minimal/client.js +38 -18
  22. package/dist/minimal/client.js.map +1 -1
  23. package/dist/router/base-types.d.ts +2 -1
  24. package/dist/router/base-types.js.map +1 -1
  25. package/dist/router/client-utils/elements-meta.d.ts +6 -0
  26. package/dist/router/client-utils/elements-meta.js +21 -0
  27. package/dist/router/client-utils/elements-meta.js.map +1 -0
  28. package/dist/router/client-utils/navigate.d.ts +11 -5
  29. package/dist/router/client-utils/navigate.js +29 -12
  30. package/dist/router/client-utils/navigate.js.map +1 -1
  31. package/dist/router/client-utils/prefetch-cache.d.ts +21 -0
  32. package/dist/router/{prefetch-cache.js → client-utils/prefetch-cache.js} +18 -4
  33. package/dist/router/client-utils/prefetch-cache.js.map +1 -0
  34. package/dist/router/client.d.ts +4 -3
  35. package/dist/router/client.js +233 -235
  36. package/dist/router/client.js.map +1 -1
  37. package/dist/router/create-pages-utils/inferred-path-types.d.ts +1 -14
  38. package/dist/router/create-pages-utils/inferred-path-types.js.map +1 -1
  39. package/dist/router/create-pages.d.ts +3 -60
  40. package/dist/router/create-pages.js.map +1 -1
  41. package/dist/router/define-router-utils/build-handler.d.ts +11 -0
  42. package/dist/router/define-router-utils/build-handler.js +234 -0
  43. package/dist/router/define-router-utils/build-handler.js.map +1 -0
  44. package/dist/router/define-router-utils/build-metadata.d.ts +5 -0
  45. package/dist/router/define-router-utils/build-metadata.js +7 -0
  46. package/dist/router/define-router-utils/build-metadata.js.map +1 -0
  47. package/dist/router/define-router-utils/client-code.d.ts +3 -0
  48. package/dist/router/define-router-utils/client-code.js +51 -0
  49. package/dist/router/define-router-utils/client-code.js.map +1 -0
  50. package/dist/router/define-router-utils/config-registry.d.ts +18 -0
  51. package/dist/router/define-router-utils/config-registry.js +100 -0
  52. package/dist/router/define-router-utils/config-registry.js.map +1 -0
  53. package/dist/router/define-router-utils/config-serialization.d.ts +5 -0
  54. package/dist/router/define-router-utils/config-serialization.js +140 -0
  55. package/dist/router/define-router-utils/config-serialization.js.map +1 -0
  56. package/dist/router/define-router-utils/config-types.d.ts +65 -0
  57. package/dist/router/define-router-utils/config-types.js +3 -0
  58. package/dist/router/define-router-utils/config-types.js.map +1 -0
  59. package/dist/router/define-router-utils/element-cache.d.ts +14 -0
  60. package/dist/router/define-router-utils/element-cache.js +42 -0
  61. package/dist/router/define-router-utils/element-cache.js.map +1 -0
  62. package/dist/router/define-router-utils/request-handler.d.ts +10 -0
  63. package/dist/router/define-router-utils/request-handler.js +210 -0
  64. package/dist/router/define-router-utils/request-handler.js.map +1 -0
  65. package/dist/router/define-router-utils/request-store.d.ts +32 -0
  66. package/dist/router/define-router-utils/request-store.js +62 -0
  67. package/dist/router/define-router-utils/request-store.js.map +1 -0
  68. package/dist/router/define-router-utils/route-entries.d.ts +15 -0
  69. package/dist/router/define-router-utils/route-entries.js +130 -0
  70. package/dist/router/define-router-utils/route-entries.js.map +1 -0
  71. package/dist/router/define-router.d.ts +4 -73
  72. package/dist/router/define-router.js +25 -879
  73. package/dist/router/define-router.js.map +1 -1
  74. package/dist/router/fs-router.d.ts +1 -60
  75. package/dist/router/fs-router.js.map +1 -1
  76. package/dist/router/isomorphic-utils/build-route-href.d.ts +2 -1
  77. package/dist/router/isomorphic-utils/build-route-href.js.map +1 -1
  78. package/dist/router/isomorphic-utils/route-path.d.ts +4 -0
  79. package/dist/router/isomorphic-utils/route-path.js +6 -0
  80. package/dist/router/isomorphic-utils/route-path.js.map +1 -1
  81. package/dist/router/isomorphic-utils/search-codec-registry.d.ts +14 -1
  82. package/dist/router/isomorphic-utils/search-codec-registry.js +9 -1
  83. package/dist/router/isomorphic-utils/search-codec-registry.js.map +1 -1
  84. package/dist/server.js +2 -1
  85. package/dist/server.js.map +1 -1
  86. package/package.json +8 -8
  87. package/dist/router/prefetch-cache.d.ts +0 -22
  88. package/dist/router/prefetch-cache.js.map +0 -1
package/README.md CHANGED
@@ -39,7 +39,7 @@ While there's a bit of a learning curve to modern React rendering, it introduces
39
39
 
40
40
  So please don't be intimidated by the `'use client'` directive! Once you get the hang of it, you'll appreciate how awesome it is to flexibly move server-client boundaries with a single line of code as your full-stack React codebase evolves over time. It's way simpler than maintaining separate codebases for your backend and frontend.
41
41
 
42
- And please don't fret about client components! Even if you only lightly optimize towards server components, your client bundle size will be smaller than traditional React frameworks, which are always 100% client components.
42
+ And please don't fret about client components! Even if you only lightly optimize towards server components, your client bundle size will be smaller than that of a fully client-rendered React app.
43
43
 
44
44
  > Future versions of Waku may provide additional opt-in APIs to abstract some of the complexity away for an improved developer experience.
45
45
 
@@ -7,7 +7,6 @@ export type Unstable_RenderRsc = (elements: Elements, options?: {
7
7
  etags?: Etags;
8
8
  unstable_clientModuleCallback?: (ids: string[]) => void;
9
9
  }) => Promise<ReadableStream>;
10
- export type Unstable_ParseRsc = (rscStream: ReadableStream) => Promise<Elements>;
11
10
  export type Unstable_RenderHtml = (elementsStream: ReadableStream, html: ReactNode, options: {
12
11
  rscPath: string;
13
12
  formState?: unknown;
@@ -17,31 +16,33 @@ export type Unstable_RenderHtml = (elementsStream: ReadableStream, html: ReactNo
17
16
  }) => Promise<Response>;
18
17
  export type Unstable_EmitFile = (filePath: string, body: ReadableStream) => Promise<void>;
19
18
  export type Unstable_HandleRequest = (input: ({
20
- type: 'component';
19
+ type: 'rsc';
21
20
  rscPath: string;
22
21
  rscParams: unknown;
23
22
  } | {
24
- type: 'function';
23
+ type: 'call';
25
24
  fn: (...args: unknown[]) => Promise<unknown>;
26
25
  args: unknown[];
27
26
  } | {
28
- type: 'action';
29
- fn: () => Promise<unknown>;
30
- } | {
31
- type: 'custom';
27
+ type: 'http';
28
+ tryAction?: () => Promise<{
29
+ action: true;
30
+ formState: unknown;
31
+ } | {
32
+ action: false;
33
+ formData: FormData;
34
+ }>;
32
35
  }) & {
33
36
  pathname: string;
34
37
  req: Request;
35
38
  etags?: Etags;
36
39
  }, utils: {
37
40
  renderRsc: Unstable_RenderRsc;
38
- parseRsc: Unstable_ParseRsc;
39
41
  renderHtml: Unstable_RenderHtml;
40
42
  loadBuildMetadata: (key: string) => Promise<string | undefined>;
41
43
  }) => Promise<ReadableStream | Response | 'fallback' | null | undefined>;
42
44
  export type Unstable_HandleBuild = (utils: {
43
45
  renderRsc: Unstable_RenderRsc;
44
- parseRsc: Unstable_ParseRsc;
45
46
  renderHtml: Unstable_RenderHtml;
46
47
  rscPath2pathname: (rscPath: string) => string;
47
48
  saveBuildMetadata: (key: string, value: string) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { Config } from '../config.js';\nimport type { Etags } from './utils/etags.js';\n\ntype Elements = Record<string, unknown>;\n\nexport type Unstable_RenderRsc = (\n elements: Elements,\n options?: {\n value?: unknown;\n etags?: Etags;\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 etags?: Etags;\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 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, unknown>>) => 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":"AAyGA,WAa8E"}
1
+ {"version":3,"sources":["../../src/lib/types.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { Config } from '../config.js';\nimport type { Etags } from './utils/etags.js';\n\ntype Elements = Record<string, unknown>;\n\nexport type Unstable_RenderRsc = (\n elements: Elements,\n options?: {\n value?: unknown;\n etags?: Etags;\n unstable_clientModuleCallback?: (ids: string[]) => void;\n },\n) => Promise<ReadableStream>;\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: 'rsc'; rscPath: string; rscParams: unknown }\n | {\n type: 'call';\n fn: (...args: unknown[]) => Promise<unknown>;\n args: unknown[];\n }\n | {\n type: 'http';\n tryAction?: () => Promise<\n | { action: true; formState: unknown }\n | { action: false; formData: FormData }\n >;\n }\n ) & {\n pathname: string;\n req: Request;\n etags?: Etags;\n },\n utils: {\n renderRsc: Unstable_RenderRsc;\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 renderHtml: Unstable_RenderHtml;\n rscPath2pathname: (rscPath: string) => string;\n saveBuildMetadata: (key: string, value: string) => Promise<void>;\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, unknown>>) => 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":"AAqGA,WAa8E"}
@@ -1,4 +1,11 @@
1
1
  // This file should not include Node specific code.
2
+ // TODO: this WS debug channel keeps dev payloads lean by offloading React's
3
+ // Server Components debug info (component stacks, timing, console, async
4
+ // metadata) out of the main Flight stream. Our transport is bespoke: paired
5
+ // HMR events here plus the debug-id header hack in rsc-devtools.ts. Waku is
6
+ // cited as prior art for a shared @vitejs/plugin-rsc debug-channel example
7
+ // (https://github.com/vitejs/vite-plugin-react/issues/1306). Once that lands,
8
+ // consider adopting it so we can delete our own transport and rsc-devtools.ts.
2
9
  import { base64ToBytes, bytesToBase64 } from './base64-web.js';
3
10
  export const DEBUG_ID_HEADER = 'X-Waku-Debug-Id';
4
11
  export const DEBUG_CMD_EVENT = 'waku:debug-cmd';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/react-debug-channel.ts"],"sourcesContent":["// This file should not include Node specific code.\n\nimport { base64ToBytes, bytesToBase64 } from './base64-web.js';\n\nexport const DEBUG_ID_HEADER = 'X-Waku-Debug-Id';\nexport const DEBUG_CMD_EVENT = 'waku:debug-cmd';\nexport const DEBUG_DATA_EVENT = 'waku:debug-data';\n\ntype DebugCmdEventReadyPayload = {\n i: string; // debugId\n};\ntype DebugCmdEventChunkPayload = {\n i: string; // debugId\n b: string; // base64 encoded chunk\n};\ntype DebugCmdEventDonePayload = {\n i: string; // debugId\n d: true; // done flag\n};\ntype DebugDataEventChunkPayload = {\n i: string; // debugId\n b: string; // base64 encoded chunk\n};\ntype DebugDataEventDonePayload = {\n i: string; // debugId\n d: true; // done flag\n};\nexport type DebugEventPayload =\n | DebugCmdEventReadyPayload\n | DebugCmdEventChunkPayload\n | DebugCmdEventDonePayload\n | DebugDataEventChunkPayload\n | DebugDataEventDonePayload;\n\nexport function assertIsDebugEventPayload(\n payload: unknown,\n): asserts payload is DebugEventPayload {\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof (payload as { i?: unknown }).i !== 'string' ||\n ('b' in payload && typeof (payload as { b?: unknown }).b !== 'string') ||\n ('d' in payload && (payload as { d?: unknown }).d !== true)\n ) {\n throw new Error('Invalid debug event payload');\n }\n}\n\nconst createWsDebugChannel = (debugId: string) => {\n const hot = import.meta.hot!;\n let closed = false;\n let onDataEvent: ((payload: unknown) => void) | undefined;\n\n const cleanup = (notify?: boolean) => {\n if (closed) {\n return;\n }\n closed = true;\n if (onDataEvent) {\n hot.off(DEBUG_DATA_EVENT, onDataEvent);\n }\n if (notify) {\n hot.send(DEBUG_CMD_EVENT, {\n i: debugId,\n d: true,\n } satisfies DebugEventPayload);\n }\n };\n\n const readable = new ReadableStream<Uint8Array>({\n start(controller) {\n onDataEvent = (payload: unknown) => {\n assertIsDebugEventPayload(payload);\n if (closed || payload.i !== debugId) {\n return;\n }\n if ('b' in payload) {\n // chunk\n controller.enqueue(base64ToBytes(payload.b));\n }\n if ('d' in payload) {\n // done\n cleanup();\n controller.close();\n }\n };\n hot.on(DEBUG_DATA_EVENT, onDataEvent);\n hot.send(DEBUG_CMD_EVENT, { i: debugId } satisfies DebugEventPayload);\n },\n cancel() {\n cleanup(true);\n },\n });\n\n const writable = new WritableStream<Uint8Array>({\n write(chunk) {\n if (closed) {\n throw new Error('Channel is closed');\n }\n hot.send(DEBUG_CMD_EVENT, {\n i: debugId,\n b: bytesToBase64(chunk),\n } satisfies DebugEventPayload);\n },\n close() {\n cleanup(true);\n },\n abort() {\n cleanup(true);\n },\n });\n\n return { readable, writable };\n};\n\nexport const setupDebugChannel = (\n baseFetchFn: typeof fetch,\n prefetched: boolean,\n debugId?: string,\n) => {\n if (prefetched) {\n if (debugId) {\n const debugChannel = createWsDebugChannel(debugId);\n return { debugChannel };\n }\n return {};\n }\n\n const newDebugId = crypto.randomUUID();\n const debugChannel = createWsDebugChannel(newDebugId);\n const fetchFn = ((input: RequestInfo | URL, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n headers.set(DEBUG_ID_HEADER, newDebugId);\n return baseFetchFn(input, {\n ...init,\n headers,\n });\n }) as typeof fetch;\n return { fetchFn, debugChannel };\n};\n"],"names":["base64ToBytes","bytesToBase64","DEBUG_ID_HEADER","DEBUG_CMD_EVENT","DEBUG_DATA_EVENT","assertIsDebugEventPayload","payload","i","b","d","Error","createWsDebugChannel","debugId","hot","closed","onDataEvent","cleanup","notify","off","send","readable","ReadableStream","start","controller","enqueue","close","on","cancel","writable","WritableStream","write","chunk","abort","setupDebugChannel","baseFetchFn","prefetched","debugChannel","newDebugId","crypto","randomUUID","fetchFn","input","init","headers","Headers","set"],"mappings":"AAAA,mDAAmD;AAEnD,SAASA,aAAa,EAAEC,aAAa,QAAQ,kBAAkB;AAE/D,OAAO,MAAMC,kBAAkB,kBAAkB;AACjD,OAAO,MAAMC,kBAAkB,iBAAiB;AAChD,OAAO,MAAMC,mBAAmB,kBAAkB;AA4BlD,OAAO,SAASC,0BACdC,OAAgB;IAEhB,IACE,CAACA,WACD,OAAOA,YAAY,YACnB,OAAO,AAACA,QAA4BC,CAAC,KAAK,YACzC,OAAOD,WAAW,OAAO,AAACA,QAA4BE,CAAC,KAAK,YAC5D,OAAOF,WAAW,AAACA,QAA4BG,CAAC,KAAK,MACtD;QACA,MAAM,IAAIC,MAAM;IAClB;AACF;AAEA,MAAMC,uBAAuB,CAACC;IAC5B,MAAMC,MAAM,YAAYA,GAAG;IAC3B,IAAIC,SAAS;IACb,IAAIC;IAEJ,MAAMC,UAAU,CAACC;QACf,IAAIH,QAAQ;YACV;QACF;QACAA,SAAS;QACT,IAAIC,aAAa;YACfF,IAAIK,GAAG,CAACd,kBAAkBW;QAC5B;QACA,IAAIE,QAAQ;YACVJ,IAAIM,IAAI,CAAChB,iBAAiB;gBACxBI,GAAGK;gBACHH,GAAG;YACL;QACF;IACF;IAEA,MAAMW,WAAW,IAAIC,eAA2B;QAC9CC,OAAMC,UAAU;YACdR,cAAc,CAACT;gBACbD,0BAA0BC;gBAC1B,IAAIQ,UAAUR,QAAQC,CAAC,KAAKK,SAAS;oBACnC;gBACF;gBACA,IAAI,OAAON,SAAS;oBAClB,QAAQ;oBACRiB,WAAWC,OAAO,CAACxB,cAAcM,QAAQE,CAAC;gBAC5C;gBACA,IAAI,OAAOF,SAAS;oBAClB,OAAO;oBACPU;oBACAO,WAAWE,KAAK;gBAClB;YACF;YACAZ,IAAIa,EAAE,CAACtB,kBAAkBW;YACzBF,IAAIM,IAAI,CAAChB,iBAAiB;gBAAEI,GAAGK;YAAQ;QACzC;QACAe;YACEX,QAAQ;QACV;IACF;IAEA,MAAMY,WAAW,IAAIC,eAA2B;QAC9CC,OAAMC,KAAK;YACT,IAAIjB,QAAQ;gBACV,MAAM,IAAIJ,MAAM;YAClB;YACAG,IAAIM,IAAI,CAAChB,iBAAiB;gBACxBI,GAAGK;gBACHJ,GAAGP,cAAc8B;YACnB;QACF;QACAN;YACET,QAAQ;QACV;QACAgB;YACEhB,QAAQ;QACV;IACF;IAEA,OAAO;QAAEI;QAAUQ;IAAS;AAC9B;AAEA,OAAO,MAAMK,oBAAoB,CAC/BC,aACAC,YACAvB;IAEA,IAAIuB,YAAY;QACd,IAAIvB,SAAS;YACX,MAAMwB,eAAezB,qBAAqBC;YAC1C,OAAO;gBAAEwB;YAAa;QACxB;QACA,OAAO,CAAC;IACV;IAEA,MAAMC,aAAaC,OAAOC,UAAU;IACpC,MAAMH,eAAezB,qBAAqB0B;IAC1C,MAAMG,UAAW,CAACC,OAA0BC;QAC1C,MAAMC,UAAU,IAAIC,QAAQF,MAAMC;QAClCA,QAAQE,GAAG,CAAC3C,iBAAiBmC;QAC7B,OAAOH,YAAYO,OAAO;YACxB,GAAGC,IAAI;YACPC;QACF;IACF;IACA,OAAO;QAAEH;QAASJ;IAAa;AACjC,EAAE"}
1
+ {"version":3,"sources":["../../../src/lib/utils/react-debug-channel.ts"],"sourcesContent":["// This file should not include Node specific code.\n\n// TODO: this WS debug channel keeps dev payloads lean by offloading React's\n// Server Components debug info (component stacks, timing, console, async\n// metadata) out of the main Flight stream. Our transport is bespoke: paired\n// HMR events here plus the debug-id header hack in rsc-devtools.ts. Waku is\n// cited as prior art for a shared @vitejs/plugin-rsc debug-channel example\n// (https://github.com/vitejs/vite-plugin-react/issues/1306). Once that lands,\n// consider adopting it so we can delete our own transport and rsc-devtools.ts.\n\nimport { base64ToBytes, bytesToBase64 } from './base64-web.js';\n\nexport const DEBUG_ID_HEADER = 'X-Waku-Debug-Id';\nexport const DEBUG_CMD_EVENT = 'waku:debug-cmd';\nexport const DEBUG_DATA_EVENT = 'waku:debug-data';\n\ntype DebugCmdEventReadyPayload = {\n i: string; // debugId\n};\ntype DebugCmdEventChunkPayload = {\n i: string; // debugId\n b: string; // base64 encoded chunk\n};\ntype DebugCmdEventDonePayload = {\n i: string; // debugId\n d: true; // done flag\n};\ntype DebugDataEventChunkPayload = {\n i: string; // debugId\n b: string; // base64 encoded chunk\n};\ntype DebugDataEventDonePayload = {\n i: string; // debugId\n d: true; // done flag\n};\nexport type DebugEventPayload =\n | DebugCmdEventReadyPayload\n | DebugCmdEventChunkPayload\n | DebugCmdEventDonePayload\n | DebugDataEventChunkPayload\n | DebugDataEventDonePayload;\n\nexport function assertIsDebugEventPayload(\n payload: unknown,\n): asserts payload is DebugEventPayload {\n if (\n !payload ||\n typeof payload !== 'object' ||\n typeof (payload as { i?: unknown }).i !== 'string' ||\n ('b' in payload && typeof (payload as { b?: unknown }).b !== 'string') ||\n ('d' in payload && (payload as { d?: unknown }).d !== true)\n ) {\n throw new Error('Invalid debug event payload');\n }\n}\n\nconst createWsDebugChannel = (debugId: string) => {\n const hot = import.meta.hot!;\n let closed = false;\n let onDataEvent: ((payload: unknown) => void) | undefined;\n\n const cleanup = (notify?: boolean) => {\n if (closed) {\n return;\n }\n closed = true;\n if (onDataEvent) {\n hot.off(DEBUG_DATA_EVENT, onDataEvent);\n }\n if (notify) {\n hot.send(DEBUG_CMD_EVENT, {\n i: debugId,\n d: true,\n } satisfies DebugEventPayload);\n }\n };\n\n const readable = new ReadableStream<Uint8Array>({\n start(controller) {\n onDataEvent = (payload: unknown) => {\n assertIsDebugEventPayload(payload);\n if (closed || payload.i !== debugId) {\n return;\n }\n if ('b' in payload) {\n // chunk\n controller.enqueue(base64ToBytes(payload.b));\n }\n if ('d' in payload) {\n // done\n cleanup();\n controller.close();\n }\n };\n hot.on(DEBUG_DATA_EVENT, onDataEvent);\n hot.send(DEBUG_CMD_EVENT, { i: debugId } satisfies DebugEventPayload);\n },\n cancel() {\n cleanup(true);\n },\n });\n\n const writable = new WritableStream<Uint8Array>({\n write(chunk) {\n if (closed) {\n throw new Error('Channel is closed');\n }\n hot.send(DEBUG_CMD_EVENT, {\n i: debugId,\n b: bytesToBase64(chunk),\n } satisfies DebugEventPayload);\n },\n close() {\n cleanup(true);\n },\n abort() {\n cleanup(true);\n },\n });\n\n return { readable, writable };\n};\n\nexport const setupDebugChannel = (\n baseFetchFn: typeof fetch,\n prefetched: boolean,\n debugId?: string,\n) => {\n if (prefetched) {\n if (debugId) {\n const debugChannel = createWsDebugChannel(debugId);\n return { debugChannel };\n }\n return {};\n }\n\n const newDebugId = crypto.randomUUID();\n const debugChannel = createWsDebugChannel(newDebugId);\n const fetchFn = ((input: RequestInfo | URL, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n headers.set(DEBUG_ID_HEADER, newDebugId);\n return baseFetchFn(input, {\n ...init,\n headers,\n });\n }) as typeof fetch;\n return { fetchFn, debugChannel };\n};\n"],"names":["base64ToBytes","bytesToBase64","DEBUG_ID_HEADER","DEBUG_CMD_EVENT","DEBUG_DATA_EVENT","assertIsDebugEventPayload","payload","i","b","d","Error","createWsDebugChannel","debugId","hot","closed","onDataEvent","cleanup","notify","off","send","readable","ReadableStream","start","controller","enqueue","close","on","cancel","writable","WritableStream","write","chunk","abort","setupDebugChannel","baseFetchFn","prefetched","debugChannel","newDebugId","crypto","randomUUID","fetchFn","input","init","headers","Headers","set"],"mappings":"AAAA,mDAAmD;AAEnD,4EAA4E;AAC5E,yEAAyE;AACzE,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,8EAA8E;AAC9E,+EAA+E;AAE/E,SAASA,aAAa,EAAEC,aAAa,QAAQ,kBAAkB;AAE/D,OAAO,MAAMC,kBAAkB,kBAAkB;AACjD,OAAO,MAAMC,kBAAkB,iBAAiB;AAChD,OAAO,MAAMC,mBAAmB,kBAAkB;AA4BlD,OAAO,SAASC,0BACdC,OAAgB;IAEhB,IACE,CAACA,WACD,OAAOA,YAAY,YACnB,OAAO,AAACA,QAA4BC,CAAC,KAAK,YACzC,OAAOD,WAAW,OAAO,AAACA,QAA4BE,CAAC,KAAK,YAC5D,OAAOF,WAAW,AAACA,QAA4BG,CAAC,KAAK,MACtD;QACA,MAAM,IAAIC,MAAM;IAClB;AACF;AAEA,MAAMC,uBAAuB,CAACC;IAC5B,MAAMC,MAAM,YAAYA,GAAG;IAC3B,IAAIC,SAAS;IACb,IAAIC;IAEJ,MAAMC,UAAU,CAACC;QACf,IAAIH,QAAQ;YACV;QACF;QACAA,SAAS;QACT,IAAIC,aAAa;YACfF,IAAIK,GAAG,CAACd,kBAAkBW;QAC5B;QACA,IAAIE,QAAQ;YACVJ,IAAIM,IAAI,CAAChB,iBAAiB;gBACxBI,GAAGK;gBACHH,GAAG;YACL;QACF;IACF;IAEA,MAAMW,WAAW,IAAIC,eAA2B;QAC9CC,OAAMC,UAAU;YACdR,cAAc,CAACT;gBACbD,0BAA0BC;gBAC1B,IAAIQ,UAAUR,QAAQC,CAAC,KAAKK,SAAS;oBACnC;gBACF;gBACA,IAAI,OAAON,SAAS;oBAClB,QAAQ;oBACRiB,WAAWC,OAAO,CAACxB,cAAcM,QAAQE,CAAC;gBAC5C;gBACA,IAAI,OAAOF,SAAS;oBAClB,OAAO;oBACPU;oBACAO,WAAWE,KAAK;gBAClB;YACF;YACAZ,IAAIa,EAAE,CAACtB,kBAAkBW;YACzBF,IAAIM,IAAI,CAAChB,iBAAiB;gBAAEI,GAAGK;YAAQ;QACzC;QACAe;YACEX,QAAQ;QACV;IACF;IAEA,MAAMY,WAAW,IAAIC,eAA2B;QAC9CC,OAAMC,KAAK;YACT,IAAIjB,QAAQ;gBACV,MAAM,IAAIJ,MAAM;YAClB;YACAG,IAAIM,IAAI,CAAChB,iBAAiB;gBACxBI,GAAGK;gBACHJ,GAAGP,cAAc8B;YACnB;QACF;QACAN;YACET,QAAQ;QACV;QACAgB;YACEhB,QAAQ;QACV;IACF;IAEA,OAAO;QAAEI;QAAUQ;IAAS;AAC9B;AAEA,OAAO,MAAMK,oBAAoB,CAC/BC,aACAC,YACAvB;IAEA,IAAIuB,YAAY;QACd,IAAIvB,SAAS;YACX,MAAMwB,eAAezB,qBAAqBC;YAC1C,OAAO;gBAAEwB;YAAa;QACxB;QACA,OAAO,CAAC;IACV;IAEA,MAAMC,aAAaC,OAAOC,UAAU;IACpC,MAAMH,eAAezB,qBAAqB0B;IAC1C,MAAMG,UAAW,CAACC,OAA0BC;QAC1C,MAAMC,UAAU,IAAIC,QAAQF,MAAMC;QAClCA,QAAQE,GAAG,CAAC3C,iBAAiBmC;QAC7B,OAAOH,YAAYO,OAAO;YACxB,GAAGC,IAAI;YACPC;QACF;IACF;IACA,OAAO;QAAEH;QAASJ;IAAa;AACjC,EAAE"}
@@ -1,9 +1,8 @@
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?: {
1
+ import type { Unstable_RenderHtml, Unstable_RenderRsc } from '../types.js';
2
+ export declare function createRenderUtils(temporaryReferences: unknown, renderToReadableStream: (data: unknown, options?: object, extraOptions?: object) => ReadableStream, 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
- parseRsc: Unstable_ParseRsc;
8
7
  renderHtml: Unstable_RenderHtml;
9
8
  };
@@ -7,7 +7,7 @@ const validateRscElementIds = (elements)=>{
7
7
  }
8
8
  }
9
9
  };
10
- export function createRenderUtils(temporaryReferences, renderToReadableStream, createFromReadableStream, loadSsrEntryModule, buildId, debugChannel, debugId) {
10
+ export function createRenderUtils(temporaryReferences, renderToReadableStream, loadSsrEntryModule, buildId, debugChannel, debugId) {
11
11
  const onError = (e)=>{
12
12
  if (e && typeof e === 'object' && 'digest' in e && typeof e.digest === 'string') {
13
13
  return e.digest;
@@ -41,9 +41,6 @@ export function createRenderUtils(temporaryReferences, renderToReadableStream, c
41
41
  }
42
42
  });
43
43
  },
44
- async parseRsc (stream) {
45
- return createFromReadableStream(stream, {});
46
- },
47
44
  async renderHtml (elementsStream, html, options) {
48
45
  const { INTERNAL_renderHtmlStream: renderHtmlStream } = await loadSsrEntryModule();
49
46
  const rscHtmlStream = renderToReadableStream(html, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/render.ts"],"sourcesContent":["import type {\n Unstable_ParseRsc,\n Unstable_RenderHtml,\n Unstable_RenderRsc,\n} from '../types.js';\nimport { ETAG_ID_PREFIX } from './etags.js';\nimport { sanitizeLog } from './log.js';\n\nconst validateRscElementIds = (elements: Record<string, unknown>) => {\n for (const id of Object.keys(elements)) {\n if (id.startsWith('_')) {\n throw new Error(\n `RSC element IDs starting with \"_\" are reserved for Waku internals: ${id}`,\n );\n }\n }\n};\n\nexport function createRenderUtils(\n temporaryReferences: unknown,\n renderToReadableStream: (\n data: unknown,\n options?: object,\n extraOptions?: object,\n ) => ReadableStream,\n createFromReadableStream: (\n stream: ReadableStream,\n options?: object,\n ) => Promise<unknown>,\n loadSsrEntryModule: () => Promise<\n typeof import('../vite-entries/entry.ssr.js')\n >,\n buildId: string,\n debugChannel?: { readable?: ReadableStream; writable?: WritableStream },\n debugId?: string,\n): {\n renderRsc: Unstable_RenderRsc;\n parseRsc: Unstable_ParseRsc;\n renderHtml: Unstable_RenderHtml;\n} {\n const onError = (e: unknown) => {\n if (\n e &&\n typeof e === 'object' &&\n 'digest' in e &&\n typeof e.digest === 'string'\n ) {\n return e.digest;\n }\n console.error('Error during rendering:', sanitizeLog(e));\n };\n\n return {\n async renderRsc(elements, options) {\n validateRscElementIds(elements);\n const data: Record<string, unknown> = buildId\n ? { ...elements, _buildId: buildId }\n : { ...elements };\n if (options && 'value' in options) {\n data._value = options.value;\n }\n if (options?.etags) {\n for (const [slotId, etag] of Object.entries(options.etags)) {\n data[ETAG_ID_PREFIX + slotId] = etag;\n }\n }\n return renderToReadableStream(\n data,\n {\n temporaryReferences,\n onError,\n debugChannel,\n },\n {\n onClientReference(metadata: {\n id: string;\n name: string;\n deps: { js: string[]; css: string[] };\n }) {\n options?.unstable_clientModuleCallback?.(metadata.deps.js);\n },\n },\n );\n },\n async parseRsc(stream) {\n return createFromReadableStream(stream, {}) as Promise<\n Record<string, unknown>\n >;\n },\n async renderHtml(elementsStream, html, options) {\n const { INTERNAL_renderHtmlStream: renderHtmlStream } =\n await loadSsrEntryModule();\n\n const rscHtmlStream = renderToReadableStream(html, {\n onError,\n });\n const htmlResult = await renderHtmlStream(elementsStream, rscHtmlStream, {\n rscPath: options.rscPath,\n formState: options.formState as never,\n nonce: options.nonce,\n extraScriptContent: options.unstable_extraScriptContent,\n debugId,\n });\n return new Response(htmlResult.stream, {\n status: htmlResult.status || options.status || 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n });\n },\n };\n}\n"],"names":["ETAG_ID_PREFIX","sanitizeLog","validateRscElementIds","elements","id","Object","keys","startsWith","Error","createRenderUtils","temporaryReferences","renderToReadableStream","createFromReadableStream","loadSsrEntryModule","buildId","debugChannel","debugId","onError","e","digest","console","error","renderRsc","options","data","_buildId","_value","value","etags","slotId","etag","entries","onClientReference","metadata","unstable_clientModuleCallback","deps","js","parseRsc","stream","renderHtml","elementsStream","html","INTERNAL_renderHtmlStream","renderHtmlStream","rscHtmlStream","htmlResult","rscPath","formState","nonce","extraScriptContent","unstable_extraScriptContent","Response","status","headers"],"mappings":"AAKA,SAASA,cAAc,QAAQ,aAAa;AAC5C,SAASC,WAAW,QAAQ,WAAW;AAEvC,MAAMC,wBAAwB,CAACC;IAC7B,KAAK,MAAMC,MAAMC,OAAOC,IAAI,CAACH,UAAW;QACtC,IAAIC,GAAGG,UAAU,CAAC,MAAM;YACtB,MAAM,IAAIC,MACR,CAAC,mEAAmE,EAAEJ,IAAI;QAE9E;IACF;AACF;AAEA,OAAO,SAASK,kBACdC,mBAA4B,EAC5BC,sBAImB,EACnBC,wBAGqB,EACrBC,kBAEC,EACDC,OAAe,EACfC,YAAuE,EACvEC,OAAgB;IAMhB,MAAMC,UAAU,CAACC;QACf,IACEA,KACA,OAAOA,MAAM,YACb,YAAYA,KACZ,OAAOA,EAAEC,MAAM,KAAK,UACpB;YACA,OAAOD,EAAEC,MAAM;QACjB;QACAC,QAAQC,KAAK,CAAC,2BAA2BpB,YAAYiB;IACvD;IAEA,OAAO;QACL,MAAMI,WAAUnB,QAAQ,EAAEoB,OAAO;YAC/BrB,sBAAsBC;YACtB,MAAMqB,OAAgCV,UAClC;gBAAE,GAAGX,QAAQ;gBAAEsB,UAAUX;YAAQ,IACjC;gBAAE,GAAGX,QAAQ;YAAC;YAClB,IAAIoB,WAAW,WAAWA,SAAS;gBACjCC,KAAKE,MAAM,GAAGH,QAAQI,KAAK;YAC7B;YACA,IAAIJ,SAASK,OAAO;gBAClB,KAAK,MAAM,CAACC,QAAQC,KAAK,IAAIzB,OAAO0B,OAAO,CAACR,QAAQK,KAAK,EAAG;oBAC1DJ,IAAI,CAACxB,iBAAiB6B,OAAO,GAAGC;gBAClC;YACF;YACA,OAAOnB,uBACLa,MACA;gBACEd;gBACAO;gBACAF;YACF,GACA;gBACEiB,mBAAkBC,QAIjB;oBACCV,SAASW,gCAAgCD,SAASE,IAAI,CAACC,EAAE;gBAC3D;YACF;QAEJ;QACA,MAAMC,UAASC,MAAM;YACnB,OAAO1B,yBAAyB0B,QAAQ,CAAC;QAG3C;QACA,MAAMC,YAAWC,cAAc,EAAEC,IAAI,EAAElB,OAAO;YAC5C,MAAM,EAAEmB,2BAA2BC,gBAAgB,EAAE,GACnD,MAAM9B;YAER,MAAM+B,gBAAgBjC,uBAAuB8B,MAAM;gBACjDxB;YACF;YACA,MAAM4B,aAAa,MAAMF,iBAAiBH,gBAAgBI,eAAe;gBACvEE,SAASvB,QAAQuB,OAAO;gBACxBC,WAAWxB,QAAQwB,SAAS;gBAC5BC,OAAOzB,QAAQyB,KAAK;gBACpBC,oBAAoB1B,QAAQ2B,2BAA2B;gBACvDlC;YACF;YACA,OAAO,IAAImC,SAASN,WAAWP,MAAM,EAAE;gBACrCc,QAAQP,WAAWO,MAAM,IAAI7B,QAAQ6B,MAAM,IAAI;gBAC/CC,SAAS;oBAAE,gBAAgB;gBAA2B;YACxD;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/lib/utils/render.ts"],"sourcesContent":["import type { Unstable_RenderHtml, Unstable_RenderRsc } from '../types.js';\nimport { ETAG_ID_PREFIX } from './etags.js';\nimport { sanitizeLog } from './log.js';\n\nconst validateRscElementIds = (elements: Record<string, unknown>) => {\n for (const id of Object.keys(elements)) {\n if (id.startsWith('_')) {\n throw new Error(\n `RSC element IDs starting with \"_\" are reserved for Waku internals: ${id}`,\n );\n }\n }\n};\n\nexport function createRenderUtils(\n temporaryReferences: unknown,\n renderToReadableStream: (\n data: unknown,\n options?: object,\n extraOptions?: object,\n ) => ReadableStream,\n loadSsrEntryModule: () => Promise<\n typeof import('../vite-entries/entry.ssr.js')\n >,\n buildId: string,\n debugChannel?: { readable?: ReadableStream; writable?: WritableStream },\n debugId?: string,\n): {\n renderRsc: Unstable_RenderRsc;\n renderHtml: Unstable_RenderHtml;\n} {\n const onError = (e: unknown) => {\n if (\n e &&\n typeof e === 'object' &&\n 'digest' in e &&\n typeof e.digest === 'string'\n ) {\n return e.digest;\n }\n console.error('Error during rendering:', sanitizeLog(e));\n };\n\n return {\n async renderRsc(elements, options) {\n validateRscElementIds(elements);\n const data: Record<string, unknown> = buildId\n ? { ...elements, _buildId: buildId }\n : { ...elements };\n if (options && 'value' in options) {\n data._value = options.value;\n }\n if (options?.etags) {\n for (const [slotId, etag] of Object.entries(options.etags)) {\n data[ETAG_ID_PREFIX + slotId] = etag;\n }\n }\n return renderToReadableStream(\n data,\n {\n temporaryReferences,\n onError,\n debugChannel,\n },\n {\n onClientReference(metadata: {\n id: string;\n name: string;\n deps: { js: string[]; css: string[] };\n }) {\n options?.unstable_clientModuleCallback?.(metadata.deps.js);\n },\n },\n );\n },\n async renderHtml(elementsStream, html, options) {\n const { INTERNAL_renderHtmlStream: renderHtmlStream } =\n await loadSsrEntryModule();\n\n const rscHtmlStream = renderToReadableStream(html, {\n onError,\n });\n const htmlResult = await renderHtmlStream(elementsStream, rscHtmlStream, {\n rscPath: options.rscPath,\n formState: options.formState as never,\n nonce: options.nonce,\n extraScriptContent: options.unstable_extraScriptContent,\n debugId,\n });\n return new Response(htmlResult.stream, {\n status: htmlResult.status || options.status || 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n });\n },\n };\n}\n"],"names":["ETAG_ID_PREFIX","sanitizeLog","validateRscElementIds","elements","id","Object","keys","startsWith","Error","createRenderUtils","temporaryReferences","renderToReadableStream","loadSsrEntryModule","buildId","debugChannel","debugId","onError","e","digest","console","error","renderRsc","options","data","_buildId","_value","value","etags","slotId","etag","entries","onClientReference","metadata","unstable_clientModuleCallback","deps","js","renderHtml","elementsStream","html","INTERNAL_renderHtmlStream","renderHtmlStream","rscHtmlStream","htmlResult","rscPath","formState","nonce","extraScriptContent","unstable_extraScriptContent","Response","stream","status","headers"],"mappings":"AACA,SAASA,cAAc,QAAQ,aAAa;AAC5C,SAASC,WAAW,QAAQ,WAAW;AAEvC,MAAMC,wBAAwB,CAACC;IAC7B,KAAK,MAAMC,MAAMC,OAAOC,IAAI,CAACH,UAAW;QACtC,IAAIC,GAAGG,UAAU,CAAC,MAAM;YACtB,MAAM,IAAIC,MACR,CAAC,mEAAmE,EAAEJ,IAAI;QAE9E;IACF;AACF;AAEA,OAAO,SAASK,kBACdC,mBAA4B,EAC5BC,sBAImB,EACnBC,kBAEC,EACDC,OAAe,EACfC,YAAuE,EACvEC,OAAgB;IAKhB,MAAMC,UAAU,CAACC;QACf,IACEA,KACA,OAAOA,MAAM,YACb,YAAYA,KACZ,OAAOA,EAAEC,MAAM,KAAK,UACpB;YACA,OAAOD,EAAEC,MAAM;QACjB;QACAC,QAAQC,KAAK,CAAC,2BAA2BnB,YAAYgB;IACvD;IAEA,OAAO;QACL,MAAMI,WAAUlB,QAAQ,EAAEmB,OAAO;YAC/BpB,sBAAsBC;YACtB,MAAMoB,OAAgCV,UAClC;gBAAE,GAAGV,QAAQ;gBAAEqB,UAAUX;YAAQ,IACjC;gBAAE,GAAGV,QAAQ;YAAC;YAClB,IAAImB,WAAW,WAAWA,SAAS;gBACjCC,KAAKE,MAAM,GAAGH,QAAQI,KAAK;YAC7B;YACA,IAAIJ,SAASK,OAAO;gBAClB,KAAK,MAAM,CAACC,QAAQC,KAAK,IAAIxB,OAAOyB,OAAO,CAACR,QAAQK,KAAK,EAAG;oBAC1DJ,IAAI,CAACvB,iBAAiB4B,OAAO,GAAGC;gBAClC;YACF;YACA,OAAOlB,uBACLY,MACA;gBACEb;gBACAM;gBACAF;YACF,GACA;gBACEiB,mBAAkBC,QAIjB;oBACCV,SAASW,gCAAgCD,SAASE,IAAI,CAACC,EAAE;gBAC3D;YACF;QAEJ;QACA,MAAMC,YAAWC,cAAc,EAAEC,IAAI,EAAEhB,OAAO;YAC5C,MAAM,EAAEiB,2BAA2BC,gBAAgB,EAAE,GACnD,MAAM5B;YAER,MAAM6B,gBAAgB9B,uBAAuB2B,MAAM;gBACjDtB;YACF;YACA,MAAM0B,aAAa,MAAMF,iBAAiBH,gBAAgBI,eAAe;gBACvEE,SAASrB,QAAQqB,OAAO;gBACxBC,WAAWtB,QAAQsB,SAAS;gBAC5BC,OAAOvB,QAAQuB,KAAK;gBACpBC,oBAAoBxB,QAAQyB,2BAA2B;gBACvDhC;YACF;YACA,OAAO,IAAIiC,SAASN,WAAWO,MAAM,EAAE;gBACrCC,QAAQR,WAAWQ,MAAM,IAAI5B,QAAQ4B,MAAM,IAAI;gBAC/CC,SAAS;oBAAE,gBAAgB;gBAA2B;YACxD;QACF;IACF;AACF"}
@@ -1,18 +1,22 @@
1
1
  import type { ReactFormState } from 'react-dom/client';
2
2
  import type { Config } from '../../config.js';
3
3
  export declare function getInput(req: Request, config: Omit<Required<Config>, 'vite'>, temporaryReferences: unknown, decodeReply: (body: string | FormData, options?: object) => Promise<unknown[]>, decodeAction: (body: FormData) => Promise<() => Promise<void>> | null, decodeFormState: (actionResult: unknown, body: FormData) => Promise<ReactFormState | undefined>, loadServerAction: (id: string) => Promise<unknown>): Promise<({
4
- type: "component";
4
+ type: "rsc";
5
5
  rscPath: string;
6
6
  rscParams: unknown;
7
7
  } | {
8
- type: "function";
8
+ type: "call";
9
9
  fn: (...args: unknown[]) => Promise<unknown>;
10
10
  args: unknown[];
11
11
  } | {
12
- type: "action";
13
- fn: () => Promise<unknown>;
14
- } | {
15
- type: "custom";
12
+ type: "http";
13
+ tryAction?: () => Promise<{
14
+ action: true;
15
+ formState: unknown;
16
+ } | {
17
+ action: false;
18
+ formData: FormData;
19
+ }>;
16
20
  }) & {
17
21
  pathname: string;
18
22
  req: Request;
@@ -21,7 +21,7 @@ export async function getInput(req, config, temporaryReferences, decodeReply, de
21
21
  });
22
22
  const action = await loadServerAction(actionId);
23
23
  input = {
24
- type: 'function',
24
+ type: 'call',
25
25
  fn: action,
26
26
  args,
27
27
  pathname,
@@ -39,7 +39,7 @@ export async function getInput(req, config, temporaryReferences, decodeReply, de
39
39
  });
40
40
  }
41
41
  input = {
42
- type: 'component',
42
+ type: 'rsc',
43
43
  rscPath,
44
44
  rscParams,
45
45
  pathname,
@@ -50,22 +50,27 @@ export async function getInput(req, config, temporaryReferences, decodeReply, de
50
50
  } else if (req.method === 'POST') {
51
51
  const contentType = req.headers.get('content-type');
52
52
  if (typeof contentType === 'string' && contentType.startsWith('multipart/form-data')) {
53
- // server action: no js (progressive enhancement)
54
- validateServerActionRequest(req);
53
+ // possibly a no-js server action submission (progressive enhancement)
54
+ let parsing;
55
55
  input = {
56
- type: 'action',
57
- fn: async ()=>{
58
- const formData = await getActionBody(req);
59
- const decodedAction = await decodeAction(formData);
60
- if (typeof decodedAction !== 'function') {
61
- // multipart/form-data POST without an action reference (e.g. crawlers)
62
- throw createCustomError('Bad Request', {
63
- status: 400
64
- });
65
- }
66
- const result = await decodedAction();
67
- return await decodeFormState(result, formData);
68
- },
56
+ type: 'http',
57
+ tryAction: ()=>parsing ??= (async ()=>{
58
+ const formData = await getActionBody(req);
59
+ const decodedAction = await decodeAction(formData);
60
+ if (typeof decodedAction !== 'function') {
61
+ return {
62
+ action: false,
63
+ formData
64
+ };
65
+ }
66
+ validateServerActionRequest(req);
67
+ const result = await decodedAction();
68
+ const formState = await decodeFormState(result, formData);
69
+ return {
70
+ action: true,
71
+ formState
72
+ };
73
+ })(),
69
74
  pathname,
70
75
  req,
71
76
  etags
@@ -73,7 +78,7 @@ export async function getInput(req, config, temporaryReferences, decodeReply, de
73
78
  } else {
74
79
  // POST API request
75
80
  input = {
76
- type: 'custom',
81
+ type: 'http',
77
82
  pathname,
78
83
  req,
79
84
  etags
@@ -82,7 +87,7 @@ export async function getInput(req, config, temporaryReferences, decodeReply, de
82
87
  } else {
83
88
  // SSR
84
89
  input = {
85
- type: 'custom',
90
+ type: 'http',
86
91
  pathname,
87
92
  req,
88
93
  etags
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/request.ts"],"sourcesContent":["import type { ReactFormState } from 'react-dom/client';\nimport type { Config } from '../../config.js';\nimport type { Unstable_HandleRequest as HandleRequest } from '../types.js';\nimport { decodeFuncId, decodeRscPath } from '../utils/rsc-path.js';\nimport { createCustomError } from './custom-errors.js';\nimport { ETAGS_HEADER, parseClientEtags } from './etags.js';\nimport { removeBase } from './path.js';\n\ntype HandleRequestInput = Parameters<HandleRequest>[0];\n\nexport async function getInput(\n req: Request,\n config: Omit<Required<Config>, 'vite'>,\n temporaryReferences: unknown,\n decodeReply: (\n body: string | FormData,\n options?: object,\n ) => Promise<unknown[]>,\n decodeAction: (body: FormData) => Promise<() => Promise<void>> | null,\n decodeFormState: (\n actionResult: unknown,\n body: FormData,\n ) => Promise<ReactFormState | undefined>,\n loadServerAction: (id: string) => Promise<unknown>,\n) {\n const url = new URL(req.url);\n const pathname = removeBase(url.pathname, config.basePath);\n const rscPathPrefix = '/' + config.rscBase + '/';\n const etags = parseClientEtags(req.headers.get(ETAGS_HEADER));\n let rscPath: string | undefined;\n let input: HandleRequestInput;\n if (pathname.startsWith(rscPathPrefix)) {\n rscPath = decodeRscPath(pathname.slice(rscPathPrefix.length));\n // server action: js\n const actionId = decodeFuncId(rscPath);\n if (actionId) {\n validateServerActionRequest(req);\n const body = await getActionBody(req);\n const args = await decodeReply(body, { temporaryReferences });\n const action = await loadServerAction(actionId);\n input = {\n type: 'function',\n fn: action as never,\n args,\n pathname,\n req,\n etags,\n };\n } else {\n // client RSC request\n let rscParams: unknown = url.searchParams;\n if (req.body) {\n validateServerActionRequest(req);\n const body = await getActionBody(req);\n rscParams = await decodeReply(body, {\n temporaryReferences,\n });\n }\n input = {\n type: 'component',\n rscPath,\n rscParams,\n pathname,\n req,\n etags,\n };\n }\n } else if (req.method === 'POST') {\n const contentType = req.headers.get('content-type');\n if (\n typeof contentType === 'string' &&\n contentType.startsWith('multipart/form-data')\n ) {\n // server action: no js (progressive enhancement)\n validateServerActionRequest(req);\n input = {\n type: 'action',\n fn: async () => {\n const formData = (await getActionBody(req)) as FormData;\n const decodedAction = await decodeAction(formData);\n if (typeof decodedAction !== 'function') {\n // multipart/form-data POST without an action reference (e.g. crawlers)\n throw createCustomError('Bad Request', { status: 400 });\n }\n const result = await decodedAction();\n return await decodeFormState(result, formData);\n },\n pathname,\n req,\n etags,\n };\n } else {\n // POST API request\n input = {\n type: 'custom',\n pathname,\n req,\n etags,\n };\n }\n } else {\n // SSR\n input = {\n type: 'custom',\n pathname,\n req,\n etags,\n };\n }\n return input;\n}\n\nfunction validateServerActionRequest(req: Request) {\n if (req.method !== 'POST') {\n throw createCustomError('Method Not Allowed', { status: 405 });\n }\n const origin = req.headers.get('origin');\n if (origin) {\n if (origin === 'null') {\n throw createCustomError('Forbidden', { status: 403 });\n }\n const requestOrigin = new URL(req.url).origin;\n let originUrl: URL;\n try {\n originUrl = new URL(origin);\n } catch {\n throw createCustomError('Forbidden', { status: 403 });\n }\n if (originUrl.origin !== requestOrigin) {\n throw createCustomError('Forbidden', { status: 403 });\n }\n } else if (req.headers.get('sec-fetch-site') === 'cross-site') {\n throw createCustomError('Forbidden', { status: 403 });\n }\n}\n\nasync function getActionBody(req: Request) {\n if (!req.body) {\n throw new Error('missing request body for server function');\n }\n const contentType = req.headers.get('content-type');\n if (contentType?.startsWith('multipart/form-data')) {\n return req.formData();\n } else {\n return req.text();\n }\n}\n"],"names":["decodeFuncId","decodeRscPath","createCustomError","ETAGS_HEADER","parseClientEtags","removeBase","getInput","req","config","temporaryReferences","decodeReply","decodeAction","decodeFormState","loadServerAction","url","URL","pathname","basePath","rscPathPrefix","rscBase","etags","headers","get","rscPath","input","startsWith","slice","length","actionId","validateServerActionRequest","body","getActionBody","args","action","type","fn","rscParams","searchParams","method","contentType","formData","decodedAction","status","result","origin","requestOrigin","originUrl","Error","text"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lib/utils/request.ts"],"sourcesContent":["import type { ReactFormState } from 'react-dom/client';\nimport type { Config } from '../../config.js';\nimport type { Unstable_HandleRequest as HandleRequest } from '../types.js';\nimport { decodeFuncId, decodeRscPath } from '../utils/rsc-path.js';\nimport { createCustomError } from './custom-errors.js';\nimport { ETAGS_HEADER, parseClientEtags } from './etags.js';\nimport { removeBase } from './path.js';\n\ntype HandleRequestInput = Parameters<HandleRequest>[0];\n\nexport async function getInput(\n req: Request,\n config: Omit<Required<Config>, 'vite'>,\n temporaryReferences: unknown,\n decodeReply: (\n body: string | FormData,\n options?: object,\n ) => Promise<unknown[]>,\n decodeAction: (body: FormData) => Promise<() => Promise<void>> | null,\n decodeFormState: (\n actionResult: unknown,\n body: FormData,\n ) => Promise<ReactFormState | undefined>,\n loadServerAction: (id: string) => Promise<unknown>,\n) {\n const url = new URL(req.url);\n const pathname = removeBase(url.pathname, config.basePath);\n const rscPathPrefix = '/' + config.rscBase + '/';\n const etags = parseClientEtags(req.headers.get(ETAGS_HEADER));\n let rscPath: string | undefined;\n let input: HandleRequestInput;\n if (pathname.startsWith(rscPathPrefix)) {\n rscPath = decodeRscPath(pathname.slice(rscPathPrefix.length));\n // server action: js\n const actionId = decodeFuncId(rscPath);\n if (actionId) {\n validateServerActionRequest(req);\n const body = await getActionBody(req);\n const args = await decodeReply(body, { temporaryReferences });\n const action = await loadServerAction(actionId);\n input = {\n type: 'call',\n fn: action as never,\n args,\n pathname,\n req,\n etags,\n };\n } else {\n // client RSC request\n let rscParams: unknown = url.searchParams;\n if (req.body) {\n validateServerActionRequest(req);\n const body = await getActionBody(req);\n rscParams = await decodeReply(body, {\n temporaryReferences,\n });\n }\n input = {\n type: 'rsc',\n rscPath,\n rscParams,\n pathname,\n req,\n etags,\n };\n }\n } else if (req.method === 'POST') {\n const contentType = req.headers.get('content-type');\n if (\n typeof contentType === 'string' &&\n contentType.startsWith('multipart/form-data')\n ) {\n // possibly a no-js server action submission (progressive enhancement)\n let parsing:\n | Promise<\n | { action: true; formState: unknown }\n | { action: false; formData: FormData }\n >\n | undefined;\n input = {\n type: 'http',\n tryAction: () =>\n (parsing ??= (async () => {\n const formData = (await getActionBody(req)) as FormData;\n const decodedAction = await decodeAction(formData);\n if (typeof decodedAction !== 'function') {\n return { action: false as const, formData };\n }\n validateServerActionRequest(req);\n const result = await decodedAction();\n const formState = await decodeFormState(result, formData);\n return { action: true as const, formState };\n })()),\n pathname,\n req,\n etags,\n };\n } else {\n // POST API request\n input = {\n type: 'http',\n pathname,\n req,\n etags,\n };\n }\n } else {\n // SSR\n input = {\n type: 'http',\n pathname,\n req,\n etags,\n };\n }\n return input;\n}\n\nfunction validateServerActionRequest(req: Request) {\n if (req.method !== 'POST') {\n throw createCustomError('Method Not Allowed', { status: 405 });\n }\n const origin = req.headers.get('origin');\n if (origin) {\n if (origin === 'null') {\n throw createCustomError('Forbidden', { status: 403 });\n }\n const requestOrigin = new URL(req.url).origin;\n let originUrl: URL;\n try {\n originUrl = new URL(origin);\n } catch {\n throw createCustomError('Forbidden', { status: 403 });\n }\n if (originUrl.origin !== requestOrigin) {\n throw createCustomError('Forbidden', { status: 403 });\n }\n } else if (req.headers.get('sec-fetch-site') === 'cross-site') {\n throw createCustomError('Forbidden', { status: 403 });\n }\n}\n\nasync function getActionBody(req: Request) {\n if (!req.body) {\n throw new Error('missing request body for server function');\n }\n const contentType = req.headers.get('content-type');\n if (contentType?.startsWith('multipart/form-data')) {\n return req.formData();\n } else {\n return req.text();\n }\n}\n"],"names":["decodeFuncId","decodeRscPath","createCustomError","ETAGS_HEADER","parseClientEtags","removeBase","getInput","req","config","temporaryReferences","decodeReply","decodeAction","decodeFormState","loadServerAction","url","URL","pathname","basePath","rscPathPrefix","rscBase","etags","headers","get","rscPath","input","startsWith","slice","length","actionId","validateServerActionRequest","body","getActionBody","args","action","type","fn","rscParams","searchParams","method","contentType","parsing","tryAction","formData","decodedAction","result","formState","status","origin","requestOrigin","originUrl","Error","text"],"mappings":"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"}
@@ -6,6 +6,12 @@
6
6
  // objects. This transform relaxes that restriction so _debugInfo is recovered
7
7
  // from any object, which is needed for Waku's plain-object payloads to show
8
8
  // the "Server Components" track in Chrome DevTools Performance tab.
9
+ //
10
+ // TODO(react-19.3): once React 19.3 is the minimum, revisit whether reshaping
11
+ // the RSC payload root into a value React's built-in recovery accepts (array,
12
+ // async iterable, element, or lazy — see above) lets us delete this transform.
13
+ // A thin wrapper like `[elements]` is unverified; confirm against React's
14
+ // recovery logic first. Context: https://github.com/vitejs/vite-plugin-react/pull/1304
9
15
  const SEARCH = 'debugInfo = root._debugInfo;';
10
16
  const REPLACE = `
11
17
  ${SEARCH}
@@ -46,7 +52,7 @@ export function patchRsdwPlugin() {
46
52
  if (id === virtualId(RSDW_CLIENT_EDGE_ID)) {
47
53
  if (this.environment.name === 'rsc') {
48
54
  return `
49
- import { createFromReadableStream as createFromReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc'))};
55
+ import { createFromReadableStream as createFromReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc/client'))};
50
56
  export function createFromReadableStream(stream) {
51
57
  return createFromReadableStreamBase(stream);
52
58
  }
@@ -57,7 +63,7 @@ export function patchRsdwPlugin() {
57
63
  if (id === virtualId(RSDW_SERVER_EDGE_ID)) {
58
64
  if (this.environment.name === 'rsc') {
59
65
  return `
60
- import { renderToReadableStream as renderToReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc'))};
66
+ import { renderToReadableStream as renderToReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc/server'))};
61
67
  export function renderToReadableStream(model, _webpackMap, options) {
62
68
  return renderToReadableStreamBase(model, options);
63
69
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/vite-plugins/patch-rsdw.ts"],"sourcesContent":["import type { Plugin } from 'vite';\n\n// Waku sends RSC payloads as plain objects (Record<string, unknown>).\n// In React's flushComponentPerformance, moveDebugInfoFromChunkToInnerValue\n// uses splice(0) which empties chunk._debugInfo after resolution. React main\n// has a fallback that recovers _debugInfo from the resolved value, but only\n// for arrays, async iterables, React elements, and lazy types — not plain\n// objects. This transform relaxes that restriction so _debugInfo is recovered\n// from any object, which is needed for Waku's plain-object payloads to show\n// the \"Server Components\" track in Chrome DevTools Performance tab.\nconst SEARCH = 'debugInfo = root._debugInfo;';\nconst REPLACE = `\n${SEARCH}\nif (debugInfo && 0 === debugInfo.length && \"fulfilled\" === root.status) {\n var _resolved = typeof resolveLazy === \"function\" ? resolveLazy(root.value) : root.value;\n if (\"object\" === typeof _resolved && null !== _resolved && isArrayImpl(_resolved._debugInfo)) {\n debugInfo = _resolved._debugInfo;\n }\n}\n`;\n\nconst RSDW_CLIENT_ID = 'react-server-dom-webpack/client';\nconst RSDW_CLIENT_EDGE_ID = 'react-server-dom-webpack/client.edge';\nconst RSDW_SERVER_EDGE_ID = 'react-server-dom-webpack/server.edge';\n\nconst virtualId = (source: string) => '\\0' + source;\n\nconst isVitePluginRscImporter = (importer?: string) =>\n /(^|[/\\\\])@vitejs[/\\\\]plugin-rsc[/\\\\]/.test(importer || '');\n\nexport function patchRsdwPlugin(): Plugin {\n return {\n name: 'waku:vite-plugins:patch-rsdw',\n enforce: 'pre',\n resolveId(source, importer, _options) {\n if (source === RSDW_CLIENT_ID) {\n return virtualId(source);\n }\n if (\n (source === RSDW_CLIENT_EDGE_ID || source === RSDW_SERVER_EDGE_ID) &&\n !isVitePluginRscImporter(importer)\n ) {\n return virtualId(source);\n }\n },\n load(id) {\n if (id === virtualId(RSDW_CLIENT_ID)) {\n if (this.environment.name === 'client') {\n return `\n import * as ReactClient from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/browser'))};\n export default ReactClient;\n `;\n }\n return `export default {}`;\n }\n if (id === virtualId(RSDW_CLIENT_EDGE_ID)) {\n if (this.environment.name === 'rsc') {\n return `\n import { createFromReadableStream as createFromReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc'))};\n export function createFromReadableStream(stream) {\n return createFromReadableStreamBase(stream);\n }\n `;\n }\n return `export {}`;\n }\n if (id === virtualId(RSDW_SERVER_EDGE_ID)) {\n if (this.environment.name === 'rsc') {\n return `\n import { renderToReadableStream as renderToReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc'))};\n export function renderToReadableStream(model, _webpackMap, options) {\n return renderToReadableStreamBase(model, options);\n }\n `;\n }\n return `export {}`;\n }\n },\n transform(code, id) {\n const [file] = id.split('?');\n if (\n ![\n '/react-server-dom-webpack-client.browser.development.js',\n '/react-server-dom-webpack_client__browser.js',\n ].some((suffix) => file!.endsWith(suffix))\n ) {\n return;\n }\n const patched = code.replace(SEARCH, REPLACE);\n if (patched === code) {\n return;\n }\n return patched;\n },\n };\n}\n"],"names":["SEARCH","REPLACE","RSDW_CLIENT_ID","RSDW_CLIENT_EDGE_ID","RSDW_SERVER_EDGE_ID","virtualId","source","isVitePluginRscImporter","importer","test","patchRsdwPlugin","name","enforce","resolveId","_options","load","id","environment","JSON","stringify","resolve","transform","code","file","split","some","suffix","endsWith","patched","replace"],"mappings":"AAEA,sEAAsE;AACtE,2EAA2E;AAC3E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,8EAA8E;AAC9E,4EAA4E;AAC5E,oEAAoE;AACpE,MAAMA,SAAS;AACf,MAAMC,UAAU,CAAC;AACjB,EAAED,OAAO;;;;;;;AAOT,CAAC;AAED,MAAME,iBAAiB;AACvB,MAAMC,sBAAsB;AAC5B,MAAMC,sBAAsB;AAE5B,MAAMC,YAAY,CAACC,SAAmB,OAAOA;AAE7C,MAAMC,0BAA0B,CAACC,WAC/B,uCAAuCC,IAAI,CAACD,YAAY;AAE1D,OAAO,SAASE;IACd,OAAO;QACLC,MAAM;QACNC,SAAS;QACTC,WAAUP,MAAM,EAAEE,QAAQ,EAAEM,QAAQ;YAClC,IAAIR,WAAWJ,gBAAgB;gBAC7B,OAAOG,UAAUC;YACnB;YACA,IACE,AAACA,CAAAA,WAAWH,uBAAuBG,WAAWF,mBAAkB,KAChE,CAACG,wBAAwBC,WACzB;gBACA,OAAOH,UAAUC;YACnB;QACF;QACAS,MAAKC,EAAE;YACL,IAAIA,OAAOX,UAAUH,iBAAiB;gBACpC,IAAI,IAAI,CAACe,WAAW,CAACN,IAAI,KAAK,UAAU;oBACtC,OAAO,CAAC;2CACyB,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,+BAA+B;;YAEnG,CAAC;gBACL;gBACA,OAAO,CAAC,iBAAiB,CAAC;YAC5B;YACA,IAAIJ,OAAOX,UAAUF,sBAAsB;gBACzC,IAAI,IAAI,CAACc,WAAW,CAACN,IAAI,KAAK,OAAO;oBACnC,OAAO,CAAC;qFACmE,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,iCAAiC;;;;UAIjJ,CAAC;gBACH;gBACA,OAAO,CAAC,SAAS,CAAC;YACpB;YACA,IAAIJ,OAAOX,UAAUD,sBAAsB;gBACzC,IAAI,IAAI,CAACa,WAAW,CAACN,IAAI,KAAK,OAAO;oBACnC,OAAO,CAAC;iFAC+D,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,iCAAiC;;;;UAI7I,CAAC;gBACH;gBACA,OAAO,CAAC,SAAS,CAAC;YACpB;QACF;QACAC,WAAUC,IAAI,EAAEN,EAAE;YAChB,MAAM,CAACO,KAAK,GAAGP,GAAGQ,KAAK,CAAC;YACxB,IACE,CAAC;gBACC;gBACA;aACD,CAACC,IAAI,CAAC,CAACC,SAAWH,KAAMI,QAAQ,CAACD,UAClC;gBACA;YACF;YACA,MAAME,UAAUN,KAAKO,OAAO,CAAC7B,QAAQC;YACrC,IAAI2B,YAAYN,MAAM;gBACpB;YACF;YACA,OAAOM;QACT;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/lib/vite-plugins/patch-rsdw.ts"],"sourcesContent":["import type { Plugin } from 'vite';\n\n// Waku sends RSC payloads as plain objects (Record<string, unknown>).\n// In React's flushComponentPerformance, moveDebugInfoFromChunkToInnerValue\n// uses splice(0) which empties chunk._debugInfo after resolution. React main\n// has a fallback that recovers _debugInfo from the resolved value, but only\n// for arrays, async iterables, React elements, and lazy types — not plain\n// objects. This transform relaxes that restriction so _debugInfo is recovered\n// from any object, which is needed for Waku's plain-object payloads to show\n// the \"Server Components\" track in Chrome DevTools Performance tab.\n//\n// TODO(react-19.3): once React 19.3 is the minimum, revisit whether reshaping\n// the RSC payload root into a value React's built-in recovery accepts (array,\n// async iterable, element, or lazy — see above) lets us delete this transform.\n// A thin wrapper like `[elements]` is unverified; confirm against React's\n// recovery logic first. Context: https://github.com/vitejs/vite-plugin-react/pull/1304\nconst SEARCH = 'debugInfo = root._debugInfo;';\nconst REPLACE = `\n${SEARCH}\nif (debugInfo && 0 === debugInfo.length && \"fulfilled\" === root.status) {\n var _resolved = typeof resolveLazy === \"function\" ? resolveLazy(root.value) : root.value;\n if (\"object\" === typeof _resolved && null !== _resolved && isArrayImpl(_resolved._debugInfo)) {\n debugInfo = _resolved._debugInfo;\n }\n}\n`;\n\nconst RSDW_CLIENT_ID = 'react-server-dom-webpack/client';\nconst RSDW_CLIENT_EDGE_ID = 'react-server-dom-webpack/client.edge';\nconst RSDW_SERVER_EDGE_ID = 'react-server-dom-webpack/server.edge';\n\nconst virtualId = (source: string) => '\\0' + source;\n\nconst isVitePluginRscImporter = (importer?: string) =>\n /(^|[/\\\\])@vitejs[/\\\\]plugin-rsc[/\\\\]/.test(importer || '');\n\nexport function patchRsdwPlugin(): Plugin {\n return {\n name: 'waku:vite-plugins:patch-rsdw',\n enforce: 'pre',\n resolveId(source, importer, _options) {\n if (source === RSDW_CLIENT_ID) {\n return virtualId(source);\n }\n if (\n (source === RSDW_CLIENT_EDGE_ID || source === RSDW_SERVER_EDGE_ID) &&\n !isVitePluginRscImporter(importer)\n ) {\n return virtualId(source);\n }\n },\n load(id) {\n if (id === virtualId(RSDW_CLIENT_ID)) {\n if (this.environment.name === 'client') {\n return `\n import * as ReactClient from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/browser'))};\n export default ReactClient;\n `;\n }\n return `export default {}`;\n }\n if (id === virtualId(RSDW_CLIENT_EDGE_ID)) {\n if (this.environment.name === 'rsc') {\n return `\n import { createFromReadableStream as createFromReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc/client'))};\n export function createFromReadableStream(stream) {\n return createFromReadableStreamBase(stream);\n }\n `;\n }\n return `export {}`;\n }\n if (id === virtualId(RSDW_SERVER_EDGE_ID)) {\n if (this.environment.name === 'rsc') {\n return `\n import { renderToReadableStream as renderToReadableStreamBase } from ${JSON.stringify(import.meta.resolve('@vitejs/plugin-rsc/react/rsc/server'))};\n export function renderToReadableStream(model, _webpackMap, options) {\n return renderToReadableStreamBase(model, options);\n }\n `;\n }\n return `export {}`;\n }\n },\n transform(code, id) {\n const [file] = id.split('?');\n if (\n ![\n '/react-server-dom-webpack-client.browser.development.js',\n '/react-server-dom-webpack_client__browser.js',\n ].some((suffix) => file!.endsWith(suffix))\n ) {\n return;\n }\n const patched = code.replace(SEARCH, REPLACE);\n if (patched === code) {\n return;\n }\n return patched;\n },\n };\n}\n"],"names":["SEARCH","REPLACE","RSDW_CLIENT_ID","RSDW_CLIENT_EDGE_ID","RSDW_SERVER_EDGE_ID","virtualId","source","isVitePluginRscImporter","importer","test","patchRsdwPlugin","name","enforce","resolveId","_options","load","id","environment","JSON","stringify","resolve","transform","code","file","split","some","suffix","endsWith","patched","replace"],"mappings":"AAEA,sEAAsE;AACtE,2EAA2E;AAC3E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,8EAA8E;AAC9E,4EAA4E;AAC5E,oEAAoE;AACpE,EAAE;AACF,8EAA8E;AAC9E,8EAA8E;AAC9E,+EAA+E;AAC/E,0EAA0E;AAC1E,uFAAuF;AACvF,MAAMA,SAAS;AACf,MAAMC,UAAU,CAAC;AACjB,EAAED,OAAO;;;;;;;AAOT,CAAC;AAED,MAAME,iBAAiB;AACvB,MAAMC,sBAAsB;AAC5B,MAAMC,sBAAsB;AAE5B,MAAMC,YAAY,CAACC,SAAmB,OAAOA;AAE7C,MAAMC,0BAA0B,CAACC,WAC/B,uCAAuCC,IAAI,CAACD,YAAY;AAE1D,OAAO,SAASE;IACd,OAAO;QACLC,MAAM;QACNC,SAAS;QACTC,WAAUP,MAAM,EAAEE,QAAQ,EAAEM,QAAQ;YAClC,IAAIR,WAAWJ,gBAAgB;gBAC7B,OAAOG,UAAUC;YACnB;YACA,IACE,AAACA,CAAAA,WAAWH,uBAAuBG,WAAWF,mBAAkB,KAChE,CAACG,wBAAwBC,WACzB;gBACA,OAAOH,UAAUC;YACnB;QACF;QACAS,MAAKC,EAAE;YACL,IAAIA,OAAOX,UAAUH,iBAAiB;gBACpC,IAAI,IAAI,CAACe,WAAW,CAACN,IAAI,KAAK,UAAU;oBACtC,OAAO,CAAC;2CACyB,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,+BAA+B;;YAEnG,CAAC;gBACL;gBACA,OAAO,CAAC,iBAAiB,CAAC;YAC5B;YACA,IAAIJ,OAAOX,UAAUF,sBAAsB;gBACzC,IAAI,IAAI,CAACc,WAAW,CAACN,IAAI,KAAK,OAAO;oBACnC,OAAO,CAAC;qFACmE,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,wCAAwC;;;;UAIxJ,CAAC;gBACH;gBACA,OAAO,CAAC,SAAS,CAAC;YACpB;YACA,IAAIJ,OAAOX,UAAUD,sBAAsB;gBACzC,IAAI,IAAI,CAACa,WAAW,CAACN,IAAI,KAAK,OAAO;oBACnC,OAAO,CAAC;iFAC+D,EAAEO,KAAKC,SAAS,CAAC,YAAYC,OAAO,CAAC,wCAAwC;;;;UAIpJ,CAAC;gBACH;gBACA,OAAO,CAAC,SAAS,CAAC;YACpB;QACF;QACAC,WAAUC,IAAI,EAAEN,EAAE;YAChB,MAAM,CAACO,KAAK,GAAGP,GAAGQ,KAAK,CAAC;YACxB,IACE,CAAC;gBACC;gBACA;aACD,CAACC,IAAI,CAAC,CAACC,SAAWH,KAAMI,QAAQ,CAACD,UAClC;gBACA;YACF;YACA,MAAME,UAAUN,KAAKO,OAAO,CAAC7B,QAAQC;YACrC,IAAI2B,YAAYN,MAAM;gBACpB;YACF;YACA,OAAOM;QACT;IACF;AACF"}
@@ -3,7 +3,7 @@ import * as vite from 'vite';
3
3
  import { combinedPlugins } from '../vite-plugins/combined-plugins.js';
4
4
  import { loadConfig, loadDotEnv } from './loader.js';
5
5
  loadDotEnv();
6
- function createServerRestartHandler() {
6
+ function createServerRestartHandler(strictPort) {
7
7
  let restartInFlight = false;
8
8
  return async (host, port, server)=>{
9
9
  if (restartInFlight) {
@@ -16,7 +16,7 @@ function createServerRestartHandler() {
16
16
  const previousUrls = server.resolvedUrls;
17
17
  await server.close();
18
18
  const freshConfig = await loadConfig();
19
- const newServer = await startDevServer(host, port, freshConfig, true);
19
+ const newServer = await startDevServer(host, port, freshConfig, strictPort, true);
20
20
  if (previousUrls) {
21
21
  server.resolvedUrls = newServer.resolvedUrls;
22
22
  }
@@ -25,7 +25,7 @@ function createServerRestartHandler() {
25
25
  }
26
26
  };
27
27
  }
28
- async function startDevServer(host, port, config, isRestart) {
28
+ async function startDevServer(host, port, config, strictPort, isRestart) {
29
29
  if (isRestart) {
30
30
  loadDotEnv();
31
31
  }
@@ -36,12 +36,14 @@ async function startDevServer(host, port, config, isRestart) {
36
36
  ],
37
37
  server: host ? {
38
38
  host,
39
- port
39
+ port,
40
+ strictPort
40
41
  } : {
41
- port
42
+ port,
43
+ strictPort
42
44
  }
43
45
  });
44
- const handleServerRestart = createServerRestartHandler();
46
+ const handleServerRestart = createServerRestartHandler(strictPort);
45
47
  // Override Vite's restart to intercept automatic restarts (.env, tsconfig, etc.)
46
48
  server.restart = async ()=>{
47
49
  console.log('Vite server restart intercepted, reloading Waku plugins...');
@@ -69,8 +71,9 @@ export async function runDev(flags) {
69
71
  process.env.NODE_ENV ??= 'development';
70
72
  const config = await loadConfig();
71
73
  const host = flags.host;
72
- const port = parseInt(flags.port || '3000', 10);
73
- await startDevServer(host, port, config);
74
+ const configuredPort = flags.port ?? process.env.PORT;
75
+ const port = parseInt(configuredPort ?? '3000', 10);
76
+ await startDevServer(host, port, config, configuredPort !== undefined);
74
77
  }
75
78
 
76
79
  //# sourceMappingURL=cmd-dev.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/vite-rsc/cmd-dev.ts"],"sourcesContent":["import path from 'node:path';\nimport * as vite from 'vite';\nimport type { Config } from '../../config.js';\nimport { combinedPlugins } from '../vite-plugins/combined-plugins.js';\nimport { loadConfig, loadDotEnv } from './loader.js';\n\nloadDotEnv();\n\nfunction createServerRestartHandler() {\n let restartInFlight = false;\n\n return async (\n host: string | undefined,\n port: number,\n server: vite.ViteDevServer,\n ) => {\n if (restartInFlight) {\n console.log('Server restart already in progress, skipping...');\n return;\n }\n restartInFlight = true;\n try {\n console.log('Restarting server with fresh plugin configuration...');\n const previousUrls = server.resolvedUrls;\n await server.close();\n const freshConfig = await loadConfig();\n const newServer = await startDevServer(host, port, freshConfig, true);\n if (previousUrls) {\n server.resolvedUrls = newServer.resolvedUrls;\n }\n } finally {\n restartInFlight = false;\n }\n };\n}\n\nasync function startDevServer(\n host: string | undefined,\n port: number,\n config: Required<Config>,\n isRestart?: boolean,\n) {\n if (isRestart) {\n loadDotEnv();\n }\n const server = await vite.createServer({\n configFile: false,\n plugins: [combinedPlugins(config)],\n server: host ? { host, port } : { port },\n });\n const handleServerRestart = createServerRestartHandler();\n // Override Vite's restart to intercept automatic restarts (.env, tsconfig, etc.)\n server.restart = async () => {\n console.log('Vite server restart intercepted, reloading Waku plugins...');\n await handleServerRestart(host, port, server);\n };\n await server.listen();\n const url =\n server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0];\n console.log(`ready: Listening on ${url}`);\n const watcher = server.watcher;\n watcher.on('change', handleConfigChange);\n watcher.on('unlink', handleConfigChange);\n watcher.on('add', handleConfigChange);\n\n async function handleConfigChange(changedFile: string) {\n const dirname = path.dirname(changedFile);\n const filename = path.basename(changedFile);\n if (\n dirname === process.cwd() &&\n (filename === 'waku.config.ts' || filename === 'waku.config.js')\n ) {\n console.log(`Waku configuration file changed, restarting server...`);\n await handleServerRestart(host, port, server);\n }\n }\n\n return server;\n}\n\nexport async function runDev(flags: { host?: string; port?: string }) {\n // set NODE_ENV before vite.runnerImport: https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= 'development';\n const config = await loadConfig();\n const host = flags.host;\n const port = parseInt(flags.port || '3000', 10);\n await startDevServer(host, port, config);\n}\n"],"names":["path","vite","combinedPlugins","loadConfig","loadDotEnv","createServerRestartHandler","restartInFlight","host","port","server","console","log","previousUrls","resolvedUrls","close","freshConfig","newServer","startDevServer","config","isRestart","createServer","configFile","plugins","handleServerRestart","restart","listen","url","network","local","watcher","on","handleConfigChange","changedFile","dirname","filename","basename","process","cwd","runDev","flags","env","NODE_ENV","parseInt"],"mappings":"AAAA,OAAOA,UAAU,YAAY;AAC7B,YAAYC,UAAU,OAAO;AAE7B,SAASC,eAAe,QAAQ,sCAAsC;AACtE,SAASC,UAAU,EAAEC,UAAU,QAAQ,cAAc;AAErDA;AAEA,SAASC;IACP,IAAIC,kBAAkB;IAEtB,OAAO,OACLC,MACAC,MACAC;QAEA,IAAIH,iBAAiB;YACnBI,QAAQC,GAAG,CAAC;YACZ;QACF;QACAL,kBAAkB;QAClB,IAAI;YACFI,QAAQC,GAAG,CAAC;YACZ,MAAMC,eAAeH,OAAOI,YAAY;YACxC,MAAMJ,OAAOK,KAAK;YAClB,MAAMC,cAAc,MAAMZ;YAC1B,MAAMa,YAAY,MAAMC,eAAeV,MAAMC,MAAMO,aAAa;YAChE,IAAIH,cAAc;gBAChBH,OAAOI,YAAY,GAAGG,UAAUH,YAAY;YAC9C;QACF,SAAU;YACRP,kBAAkB;QACpB;IACF;AACF;AAEA,eAAeW,eACbV,IAAwB,EACxBC,IAAY,EACZU,MAAwB,EACxBC,SAAmB;IAEnB,IAAIA,WAAW;QACbf;IACF;IACA,MAAMK,SAAS,MAAMR,KAAKmB,YAAY,CAAC;QACrCC,YAAY;QACZC,SAAS;YAACpB,gBAAgBgB;SAAQ;QAClCT,QAAQF,OAAO;YAAEA;YAAMC;QAAK,IAAI;YAAEA;QAAK;IACzC;IACA,MAAMe,sBAAsBlB;IAC5B,iFAAiF;IACjFI,OAAOe,OAAO,GAAG;QACfd,QAAQC,GAAG,CAAC;QACZ,MAAMY,oBAAoBhB,MAAMC,MAAMC;IACxC;IACA,MAAMA,OAAOgB,MAAM;IACnB,MAAMC,MACJjB,OAAOI,YAAY,EAAEc,SAAS,CAAC,EAAE,IAAIlB,OAAOI,YAAY,EAAEe,OAAO,CAAC,EAAE;IACtElB,QAAQC,GAAG,CAAC,CAAC,oBAAoB,EAAEe,KAAK;IACxC,MAAMG,UAAUpB,OAAOoB,OAAO;IAC9BA,QAAQC,EAAE,CAAC,UAAUC;IACrBF,QAAQC,EAAE,CAAC,UAAUC;IACrBF,QAAQC,EAAE,CAAC,OAAOC;IAElB,eAAeA,mBAAmBC,WAAmB;QACnD,MAAMC,UAAUjC,KAAKiC,OAAO,CAACD;QAC7B,MAAME,WAAWlC,KAAKmC,QAAQ,CAACH;QAC/B,IACEC,YAAYG,QAAQC,GAAG,MACtBH,CAAAA,aAAa,oBAAoBA,aAAa,gBAAe,GAC9D;YACAxB,QAAQC,GAAG,CAAC,CAAC,qDAAqD,CAAC;YACnE,MAAMY,oBAAoBhB,MAAMC,MAAMC;QACxC;IACF;IAEA,OAAOA;AACT;AAEA,OAAO,eAAe6B,OAAOC,KAAuC;IAClE,qFAAqF;IACrFH,QAAQI,GAAG,CAACC,QAAQ,KAAK;IACzB,MAAMvB,SAAS,MAAMf;IACrB,MAAMI,OAAOgC,MAAMhC,IAAI;IACvB,MAAMC,OAAOkC,SAASH,MAAM/B,IAAI,IAAI,QAAQ;IAC5C,MAAMS,eAAeV,MAAMC,MAAMU;AACnC"}
1
+ {"version":3,"sources":["../../../src/lib/vite-rsc/cmd-dev.ts"],"sourcesContent":["import path from 'node:path';\nimport * as vite from 'vite';\nimport type { Config } from '../../config.js';\nimport { combinedPlugins } from '../vite-plugins/combined-plugins.js';\nimport { loadConfig, loadDotEnv } from './loader.js';\n\nloadDotEnv();\n\nfunction createServerRestartHandler(strictPort: boolean) {\n let restartInFlight = false;\n\n return async (\n host: string | undefined,\n port: number,\n server: vite.ViteDevServer,\n ) => {\n if (restartInFlight) {\n console.log('Server restart already in progress, skipping...');\n return;\n }\n restartInFlight = true;\n try {\n console.log('Restarting server with fresh plugin configuration...');\n const previousUrls = server.resolvedUrls;\n await server.close();\n const freshConfig = await loadConfig();\n const newServer = await startDevServer(\n host,\n port,\n freshConfig,\n strictPort,\n true,\n );\n if (previousUrls) {\n server.resolvedUrls = newServer.resolvedUrls;\n }\n } finally {\n restartInFlight = false;\n }\n };\n}\n\nasync function startDevServer(\n host: string | undefined,\n port: number,\n config: Required<Config>,\n strictPort: boolean,\n isRestart?: boolean,\n) {\n if (isRestart) {\n loadDotEnv();\n }\n const server = await vite.createServer({\n configFile: false,\n plugins: [combinedPlugins(config)],\n server: host ? { host, port, strictPort } : { port, strictPort },\n });\n const handleServerRestart = createServerRestartHandler(strictPort);\n // Override Vite's restart to intercept automatic restarts (.env, tsconfig, etc.)\n server.restart = async () => {\n console.log('Vite server restart intercepted, reloading Waku plugins...');\n await handleServerRestart(host, port, server);\n };\n await server.listen();\n const url =\n server.resolvedUrls?.network?.[0] ?? server.resolvedUrls?.local?.[0];\n console.log(`ready: Listening on ${url}`);\n const watcher = server.watcher;\n watcher.on('change', handleConfigChange);\n watcher.on('unlink', handleConfigChange);\n watcher.on('add', handleConfigChange);\n\n async function handleConfigChange(changedFile: string) {\n const dirname = path.dirname(changedFile);\n const filename = path.basename(changedFile);\n if (\n dirname === process.cwd() &&\n (filename === 'waku.config.ts' || filename === 'waku.config.js')\n ) {\n console.log(`Waku configuration file changed, restarting server...`);\n await handleServerRestart(host, port, server);\n }\n }\n\n return server;\n}\n\nexport async function runDev(flags: { host?: string; port?: string }) {\n // set NODE_ENV before vite.runnerImport: https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= 'development';\n const config = await loadConfig();\n const host = flags.host;\n const configuredPort = flags.port ?? process.env.PORT;\n const port = parseInt(configuredPort ?? '3000', 10);\n await startDevServer(host, port, config, configuredPort !== undefined);\n}\n"],"names":["path","vite","combinedPlugins","loadConfig","loadDotEnv","createServerRestartHandler","strictPort","restartInFlight","host","port","server","console","log","previousUrls","resolvedUrls","close","freshConfig","newServer","startDevServer","config","isRestart","createServer","configFile","plugins","handleServerRestart","restart","listen","url","network","local","watcher","on","handleConfigChange","changedFile","dirname","filename","basename","process","cwd","runDev","flags","env","NODE_ENV","configuredPort","PORT","parseInt","undefined"],"mappings":"AAAA,OAAOA,UAAU,YAAY;AAC7B,YAAYC,UAAU,OAAO;AAE7B,SAASC,eAAe,QAAQ,sCAAsC;AACtE,SAASC,UAAU,EAAEC,UAAU,QAAQ,cAAc;AAErDA;AAEA,SAASC,2BAA2BC,UAAmB;IACrD,IAAIC,kBAAkB;IAEtB,OAAO,OACLC,MACAC,MACAC;QAEA,IAAIH,iBAAiB;YACnBI,QAAQC,GAAG,CAAC;YACZ;QACF;QACAL,kBAAkB;QAClB,IAAI;YACFI,QAAQC,GAAG,CAAC;YACZ,MAAMC,eAAeH,OAAOI,YAAY;YACxC,MAAMJ,OAAOK,KAAK;YAClB,MAAMC,cAAc,MAAMb;YAC1B,MAAMc,YAAY,MAAMC,eACtBV,MACAC,MACAO,aACAV,YACA;YAEF,IAAIO,cAAc;gBAChBH,OAAOI,YAAY,GAAGG,UAAUH,YAAY;YAC9C;QACF,SAAU;YACRP,kBAAkB;QACpB;IACF;AACF;AAEA,eAAeW,eACbV,IAAwB,EACxBC,IAAY,EACZU,MAAwB,EACxBb,UAAmB,EACnBc,SAAmB;IAEnB,IAAIA,WAAW;QACbhB;IACF;IACA,MAAMM,SAAS,MAAMT,KAAKoB,YAAY,CAAC;QACrCC,YAAY;QACZC,SAAS;YAACrB,gBAAgBiB;SAAQ;QAClCT,QAAQF,OAAO;YAAEA;YAAMC;YAAMH;QAAW,IAAI;YAAEG;YAAMH;QAAW;IACjE;IACA,MAAMkB,sBAAsBnB,2BAA2BC;IACvD,iFAAiF;IACjFI,OAAOe,OAAO,GAAG;QACfd,QAAQC,GAAG,CAAC;QACZ,MAAMY,oBAAoBhB,MAAMC,MAAMC;IACxC;IACA,MAAMA,OAAOgB,MAAM;IACnB,MAAMC,MACJjB,OAAOI,YAAY,EAAEc,SAAS,CAAC,EAAE,IAAIlB,OAAOI,YAAY,EAAEe,OAAO,CAAC,EAAE;IACtElB,QAAQC,GAAG,CAAC,CAAC,oBAAoB,EAAEe,KAAK;IACxC,MAAMG,UAAUpB,OAAOoB,OAAO;IAC9BA,QAAQC,EAAE,CAAC,UAAUC;IACrBF,QAAQC,EAAE,CAAC,UAAUC;IACrBF,QAAQC,EAAE,CAAC,OAAOC;IAElB,eAAeA,mBAAmBC,WAAmB;QACnD,MAAMC,UAAUlC,KAAKkC,OAAO,CAACD;QAC7B,MAAME,WAAWnC,KAAKoC,QAAQ,CAACH;QAC/B,IACEC,YAAYG,QAAQC,GAAG,MACtBH,CAAAA,aAAa,oBAAoBA,aAAa,gBAAe,GAC9D;YACAxB,QAAQC,GAAG,CAAC,CAAC,qDAAqD,CAAC;YACnE,MAAMY,oBAAoBhB,MAAMC,MAAMC;QACxC;IACF;IAEA,OAAOA;AACT;AAEA,OAAO,eAAe6B,OAAOC,KAAuC;IAClE,qFAAqF;IACrFH,QAAQI,GAAG,CAACC,QAAQ,KAAK;IACzB,MAAMvB,SAAS,MAAMhB;IACrB,MAAMK,OAAOgC,MAAMhC,IAAI;IACvB,MAAMmC,iBAAiBH,MAAM/B,IAAI,IAAI4B,QAAQI,GAAG,CAACG,IAAI;IACrD,MAAMnC,OAAOoC,SAASF,kBAAkB,QAAQ;IAChD,MAAMzB,eAAeV,MAAMC,MAAMU,QAAQwB,mBAAmBG;AAC9D"}
@@ -8,7 +8,8 @@ export async function runStart(flags) {
8
8
  process.env.NODE_ENV ??= 'production';
9
9
  const config = await loadConfig();
10
10
  const host = flags.host;
11
- const port = await getFreePort(parseInt(flags.port || '8080', 10));
11
+ const configuredPort = flags.port ?? process.env.PORT;
12
+ const port = configuredPort === undefined ? await getFreePort(8080) : parseInt(configuredPort, 10);
12
13
  const distDir = config?.distDir ?? 'dist';
13
14
  const serveFileUrl = pathToFileURL(path.resolve(distDir, 'serve-node.js')).href;
14
15
  if (host) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/vite-rsc/cmd-start.ts"],"sourcesContent":["import net from 'node:net';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { loadConfig, loadDotEnv } from './loader.js';\n\nloadDotEnv();\n\nexport async function runStart(flags: { host?: string; port?: string }) {\n // set NODE_ENV before vite.runnerImport: https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= 'production';\n const config = await loadConfig();\n const host = flags.host;\n const port = await getFreePort(parseInt(flags.port || '8080', 10));\n const distDir = config?.distDir ?? 'dist';\n const serveFileUrl = pathToFileURL(\n path.resolve(distDir, 'serve-node.js'),\n ).href;\n if (host) {\n process.env.HOST = host;\n } else {\n delete process.env.HOST;\n }\n process.env.PORT = String(port);\n await import(serveFileUrl);\n // Defaulting '0.0.0.0' seems heuristic, and not useful.\n // Ref: https://github.com/wakujs/waku/pull/1987\n console.log(`ready: Listening on http://${host || '0.0.0.0'}:${port}/`);\n}\n\nasync function getFreePort(startPort: number): Promise<number> {\n for (let port = startPort; ; port++) {\n try {\n await new Promise<void>((resolve, reject) => {\n const srv = net\n .createServer()\n .once('error', reject)\n .once('listening', () => srv.close(() => resolve()))\n .listen(port);\n });\n return port;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw err;\n }\n }\n }\n}\n"],"names":["net","path","pathToFileURL","loadConfig","loadDotEnv","runStart","flags","process","env","NODE_ENV","config","host","port","getFreePort","parseInt","distDir","serveFileUrl","resolve","href","HOST","PORT","String","console","log","startPort","Promise","reject","srv","createServer","once","close","listen","err","code"],"mappings":"AAAA,OAAOA,SAAS,WAAW;AAC3B,OAAOC,UAAU,YAAY;AAC7B,SAASC,aAAa,QAAQ,WAAW;AACzC,SAASC,UAAU,EAAEC,UAAU,QAAQ,cAAc;AAErDA;AAEA,OAAO,eAAeC,SAASC,KAAuC;IACpE,qFAAqF;IACrFC,QAAQC,GAAG,CAACC,QAAQ,KAAK;IACzB,MAAMC,SAAS,MAAMP;IACrB,MAAMQ,OAAOL,MAAMK,IAAI;IACvB,MAAMC,OAAO,MAAMC,YAAYC,SAASR,MAAMM,IAAI,IAAI,QAAQ;IAC9D,MAAMG,UAAUL,QAAQK,WAAW;IACnC,MAAMC,eAAed,cACnBD,KAAKgB,OAAO,CAACF,SAAS,kBACtBG,IAAI;IACN,IAAIP,MAAM;QACRJ,QAAQC,GAAG,CAACW,IAAI,GAAGR;IACrB,OAAO;QACL,OAAOJ,QAAQC,GAAG,CAACW,IAAI;IACzB;IACAZ,QAAQC,GAAG,CAACY,IAAI,GAAGC,OAAOT;IAC1B,MAAM,MAAM,CAACI;IACb,wDAAwD;IACxD,gDAAgD;IAChDM,QAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAEZ,QAAQ,UAAU,CAAC,EAAEC,KAAK,CAAC,CAAC;AACxE;AAEA,eAAeC,YAAYW,SAAiB;IAC1C,IAAK,IAAIZ,OAAOY,YAAaZ,OAAQ;QACnC,IAAI;YACF,MAAM,IAAIa,QAAc,CAACR,SAASS;gBAChC,MAAMC,MAAM3B,IACT4B,YAAY,GACZC,IAAI,CAAC,SAASH,QACdG,IAAI,CAAC,aAAa,IAAMF,IAAIG,KAAK,CAAC,IAAMb,YACxCc,MAAM,CAACnB;YACZ;YACA,OAAOA;QACT,EAAE,OAAOoB,KAAK;YACZ,IAAI,AAACA,IAA8BC,IAAI,KAAK,cAAc;gBACxD,MAAMD;YACR;QACF;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/lib/vite-rsc/cmd-start.ts"],"sourcesContent":["import net from 'node:net';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { loadConfig, loadDotEnv } from './loader.js';\n\nloadDotEnv();\n\nexport async function runStart(flags: { host?: string; port?: string }) {\n // set NODE_ENV before vite.runnerImport: https://github.com/vitejs/vite/issues/20299\n process.env.NODE_ENV ??= 'production';\n const config = await loadConfig();\n const host = flags.host;\n const configuredPort = flags.port ?? process.env.PORT;\n const port =\n configuredPort === undefined\n ? await getFreePort(8080)\n : parseInt(configuredPort, 10);\n const distDir = config?.distDir ?? 'dist';\n const serveFileUrl = pathToFileURL(\n path.resolve(distDir, 'serve-node.js'),\n ).href;\n if (host) {\n process.env.HOST = host;\n } else {\n delete process.env.HOST;\n }\n process.env.PORT = String(port);\n await import(serveFileUrl);\n // Defaulting '0.0.0.0' seems heuristic, and not useful.\n // Ref: https://github.com/wakujs/waku/pull/1987\n console.log(`ready: Listening on http://${host || '0.0.0.0'}:${port}/`);\n}\n\nasync function getFreePort(startPort: number): Promise<number> {\n for (let port = startPort; ; port++) {\n try {\n await new Promise<void>((resolve, reject) => {\n const srv = net\n .createServer()\n .once('error', reject)\n .once('listening', () => srv.close(() => resolve()))\n .listen(port);\n });\n return port;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw err;\n }\n }\n }\n}\n"],"names":["net","path","pathToFileURL","loadConfig","loadDotEnv","runStart","flags","process","env","NODE_ENV","config","host","configuredPort","port","PORT","undefined","getFreePort","parseInt","distDir","serveFileUrl","resolve","href","HOST","String","console","log","startPort","Promise","reject","srv","createServer","once","close","listen","err","code"],"mappings":"AAAA,OAAOA,SAAS,WAAW;AAC3B,OAAOC,UAAU,YAAY;AAC7B,SAASC,aAAa,QAAQ,WAAW;AACzC,SAASC,UAAU,EAAEC,UAAU,QAAQ,cAAc;AAErDA;AAEA,OAAO,eAAeC,SAASC,KAAuC;IACpE,qFAAqF;IACrFC,QAAQC,GAAG,CAACC,QAAQ,KAAK;IACzB,MAAMC,SAAS,MAAMP;IACrB,MAAMQ,OAAOL,MAAMK,IAAI;IACvB,MAAMC,iBAAiBN,MAAMO,IAAI,IAAIN,QAAQC,GAAG,CAACM,IAAI;IACrD,MAAMD,OACJD,mBAAmBG,YACf,MAAMC,YAAY,QAClBC,SAASL,gBAAgB;IAC/B,MAAMM,UAAUR,QAAQQ,WAAW;IACnC,MAAMC,eAAejB,cACnBD,KAAKmB,OAAO,CAACF,SAAS,kBACtBG,IAAI;IACN,IAAIV,MAAM;QACRJ,QAAQC,GAAG,CAACc,IAAI,GAAGX;IACrB,OAAO;QACL,OAAOJ,QAAQC,GAAG,CAACc,IAAI;IACzB;IACAf,QAAQC,GAAG,CAACM,IAAI,GAAGS,OAAOV;IAC1B,MAAM,MAAM,CAACM;IACb,wDAAwD;IACxD,gDAAgD;IAChDK,QAAQC,GAAG,CAAC,CAAC,2BAA2B,EAAEd,QAAQ,UAAU,CAAC,EAAEE,KAAK,CAAC,CAAC;AACxE;AAEA,eAAeG,YAAYU,SAAiB;IAC1C,IAAK,IAAIb,OAAOa,YAAab,OAAQ;QACnC,IAAI;YACF,MAAM,IAAIc,QAAc,CAACP,SAASQ;gBAChC,MAAMC,MAAM7B,IACT8B,YAAY,GACZC,IAAI,CAAC,SAASH,QACdG,IAAI,CAAC,aAAa,IAAMF,IAAIG,KAAK,CAAC,IAAMZ,YACxCa,MAAM,CAACpB;YACZ;YACA,OAAOA;QACT,EAAE,OAAOqB,KAAK;YACZ,IAAI,AAACA,IAA8BC,IAAI,KAAK,cAAc;gBACxD,MAAMD;YACR;QACF;IACF;AACF"}
@@ -1,4 +1,4 @@
1
- import { createFromReadableStream, createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction, renderToReadableStream } from '@vitejs/plugin-rsc/rsc';
1
+ import { createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction, renderToReadableStream } from '@vitejs/plugin-rsc/rsc/server';
2
2
  import { buildMetadata } from 'virtual:vite-rsc-waku/build-metadata';
3
3
  import { config, isBuild } from 'virtual:vite-rsc-waku/config';
4
4
  import notFoundHtml from 'virtual:vite-rsc-waku/not-found';
@@ -26,7 +26,7 @@ const toProcessRequest = (handleRequest)=>async (req)=>{
26
26
  if (debugId) {
27
27
  debugChannels?.delete(debugId);
28
28
  }
29
- const renderUtils = createRenderUtils(temporaryReferences, renderToReadableStream, createFromReadableStream, loadSsrEntryModule, import.meta.env.WAKU_BUILD_ID ?? '', debugChannel, debugId);
29
+ const renderUtils = createRenderUtils(temporaryReferences, renderToReadableStream, loadSsrEntryModule, import.meta.env.WAKU_BUILD_ID ?? '', debugChannel, debugId);
30
30
  let res;
31
31
  try {
32
32
  res = await handleRequest(input, {
@@ -73,7 +73,7 @@ const toProcessRequest = (handleRequest)=>async (req)=>{
73
73
  return null;
74
74
  };
75
75
  const toProcessBuild = (handleBuild)=>async ({ emitFile, unstable_registerPrunableFile })=>{
76
- const renderUtils = createRenderUtils(undefined, renderToReadableStream, createFromReadableStream, loadSsrEntryModule, import.meta.env.WAKU_BUILD_ID ?? '');
76
+ const renderUtils = createRenderUtils(undefined, renderToReadableStream, loadSsrEntryModule, import.meta.env.WAKU_BUILD_ID ?? '');
77
77
  let fallbackHtml;
78
78
  const getFallbackHtml = async ()=>{
79
79
  if (!fallbackHtml) {
@@ -91,7 +91,6 @@ const toProcessBuild = (handleBuild)=>async ({ emitFile, unstable_registerPrunab
91
91
  };
92
92
  await handleBuild({
93
93
  renderRsc: renderUtils.renderRsc,
94
- parseRsc: renderUtils.parseRsc,
95
94
  renderHtml: renderUtils.renderHtml,
96
95
  rscPath2pathname: (rscPath)=>joinPath(config.rscBase, encodeRscPath(rscPath)),
97
96
  saveBuildMetadata: async (key, value)=>{