waku 1.0.0-beta.6 → 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 (125) hide show
  1. package/README.md +4 -2
  2. package/dist/client.d.ts +1 -1
  3. package/dist/client.js +1 -1
  4. package/dist/client.js.map +1 -1
  5. package/dist/lib/global-types.d.ts +0 -1
  6. package/dist/lib/types.d.ts +13 -9
  7. package/dist/lib/types.js.map +1 -1
  8. package/dist/lib/utils/etags.d.ts +8 -0
  9. package/dist/lib/utils/etags.js +30 -0
  10. package/dist/lib/utils/etags.js.map +1 -0
  11. package/dist/lib/utils/path.d.ts +0 -41
  12. package/dist/lib/utils/path.js +0 -178
  13. package/dist/lib/utils/path.js.map +1 -1
  14. package/dist/lib/utils/react-debug-channel.js +7 -0
  15. package/dist/lib/utils/react-debug-channel.js.map +1 -1
  16. package/dist/lib/utils/render.d.ts +2 -3
  17. package/dist/lib/utils/render.js +7 -4
  18. package/dist/lib/utils/render.js.map +1 -1
  19. package/dist/lib/utils/request.d.ts +12 -7
  20. package/dist/lib/utils/request.js +36 -18
  21. package/dist/lib/utils/request.js.map +1 -1
  22. package/dist/lib/vite-plugins/fs-router-typegen.js +1 -1
  23. package/dist/lib/vite-plugins/fs-router-typegen.js.map +1 -1
  24. package/dist/lib/vite-plugins/patch-rsdw.js +8 -2
  25. package/dist/lib/vite-plugins/patch-rsdw.js.map +1 -1
  26. package/dist/lib/vite-rsc/cmd-dev.js +11 -8
  27. package/dist/lib/vite-rsc/cmd-dev.js.map +1 -1
  28. package/dist/lib/vite-rsc/cmd-start.js +2 -1
  29. package/dist/lib/vite-rsc/cmd-start.js.map +1 -1
  30. package/dist/lib/vite-rsc/handler.js +3 -4
  31. package/dist/lib/vite-rsc/handler.js.map +1 -1
  32. package/dist/minimal/client-utils/fetch-store.d.ts +3 -0
  33. package/dist/minimal/client-utils/fetch-store.js +1 -0
  34. package/dist/minimal/client-utils/fetch-store.js.map +1 -1
  35. package/dist/minimal/client.d.ts +24 -4
  36. package/dist/minimal/client.js +200 -88
  37. package/dist/minimal/client.js.map +1 -1
  38. package/dist/minimal/server.d.ts +16 -0
  39. package/dist/minimal/server.js +30 -0
  40. package/dist/minimal/server.js.map +1 -1
  41. package/dist/router/base-types.d.ts +4 -3
  42. package/dist/router/base-types.js.map +1 -1
  43. package/dist/router/client-utils/elements-meta.d.ts +6 -0
  44. package/dist/router/client-utils/elements-meta.js +21 -0
  45. package/dist/router/client-utils/elements-meta.js.map +1 -0
  46. package/dist/router/client-utils/navigate.d.ts +45 -0
  47. package/dist/router/client-utils/navigate.js +112 -0
  48. package/dist/router/client-utils/navigate.js.map +1 -0
  49. package/dist/router/client-utils/prefetch-cache.d.ts +21 -0
  50. package/dist/router/client-utils/prefetch-cache.js +93 -0
  51. package/dist/router/client-utils/prefetch-cache.js.map +1 -0
  52. package/dist/router/client.d.ts +17 -8
  53. package/dist/router/client.js +378 -391
  54. package/dist/router/client.js.map +1 -1
  55. package/dist/router/create-pages-utils/inferred-path-types.d.ts +1 -14
  56. package/dist/router/create-pages-utils/inferred-path-types.js.map +1 -1
  57. package/dist/router/create-pages-utils/path-spec.d.ts +6 -0
  58. package/dist/router/create-pages-utils/path-spec.js +22 -0
  59. package/dist/router/create-pages-utils/path-spec.js.map +1 -0
  60. package/dist/router/create-pages.d.ts +5 -62
  61. package/dist/router/create-pages.js +4 -4
  62. package/dist/router/create-pages.js.map +1 -1
  63. package/dist/router/define-router-utils/build-handler.d.ts +11 -0
  64. package/dist/router/define-router-utils/build-handler.js +234 -0
  65. package/dist/router/define-router-utils/build-handler.js.map +1 -0
  66. package/dist/router/define-router-utils/build-metadata.d.ts +5 -0
  67. package/dist/router/define-router-utils/build-metadata.js +7 -0
  68. package/dist/router/define-router-utils/build-metadata.js.map +1 -0
  69. package/dist/router/define-router-utils/client-code.d.ts +3 -0
  70. package/dist/router/define-router-utils/client-code.js +51 -0
  71. package/dist/router/define-router-utils/client-code.js.map +1 -0
  72. package/dist/router/define-router-utils/config-registry.d.ts +18 -0
  73. package/dist/router/define-router-utils/config-registry.js +100 -0
  74. package/dist/router/define-router-utils/config-registry.js.map +1 -0
  75. package/dist/router/define-router-utils/config-serialization.d.ts +5 -0
  76. package/dist/router/define-router-utils/config-serialization.js +140 -0
  77. package/dist/router/define-router-utils/config-serialization.js.map +1 -0
  78. package/dist/router/define-router-utils/config-types.d.ts +65 -0
  79. package/dist/router/define-router-utils/config-types.js +3 -0
  80. package/dist/router/define-router-utils/config-types.js.map +1 -0
  81. package/dist/router/define-router-utils/element-cache.d.ts +14 -0
  82. package/dist/router/define-router-utils/element-cache.js +42 -0
  83. package/dist/router/define-router-utils/element-cache.js.map +1 -0
  84. package/dist/router/define-router-utils/path-spec.d.ts +5 -0
  85. package/dist/router/define-router-utils/path-spec.js +19 -0
  86. package/dist/router/define-router-utils/path-spec.js.map +1 -0
  87. package/dist/router/define-router-utils/request-handler.d.ts +10 -0
  88. package/dist/router/define-router-utils/request-handler.js +210 -0
  89. package/dist/router/define-router-utils/request-handler.js.map +1 -0
  90. package/dist/router/define-router-utils/request-store.d.ts +32 -0
  91. package/dist/router/define-router-utils/request-store.js +62 -0
  92. package/dist/router/define-router-utils/request-store.js.map +1 -0
  93. package/dist/router/define-router-utils/route-entries.d.ts +15 -0
  94. package/dist/router/define-router-utils/route-entries.js +130 -0
  95. package/dist/router/define-router-utils/route-entries.js.map +1 -0
  96. package/dist/router/define-router-utils/task-runner.js.map +1 -0
  97. package/dist/router/define-router.d.ts +4 -73
  98. package/dist/router/define-router.js +25 -865
  99. package/dist/router/define-router.js.map +1 -1
  100. package/dist/router/fs-router.d.ts +1 -60
  101. package/dist/router/fs-router.js +1 -1
  102. package/dist/router/fs-router.js.map +1 -1
  103. package/dist/router/isomorphic-utils/build-route-href.d.ts +2 -1
  104. package/dist/router/isomorphic-utils/build-route-href.js +2 -2
  105. package/dist/router/isomorphic-utils/build-route-href.js.map +1 -1
  106. package/dist/router/isomorphic-utils/match-route-params.js +2 -2
  107. package/dist/router/isomorphic-utils/match-route-params.js.map +1 -1
  108. package/dist/router/isomorphic-utils/path-spec.d.ts +32 -0
  109. package/dist/router/isomorphic-utils/path-spec.js +143 -0
  110. package/dist/router/isomorphic-utils/path-spec.js.map +1 -0
  111. package/dist/router/isomorphic-utils/route-path.d.ts +4 -3
  112. package/dist/router/isomorphic-utils/route-path.js +6 -6
  113. package/dist/router/isomorphic-utils/route-path.js.map +1 -1
  114. package/dist/router/isomorphic-utils/search-codec-registry.d.ts +14 -1
  115. package/dist/router/isomorphic-utils/search-codec-registry.js +9 -1
  116. package/dist/router/isomorphic-utils/search-codec-registry.js.map +1 -1
  117. package/dist/server.js +2 -1
  118. package/dist/server.js.map +1 -1
  119. package/package.json +8 -8
  120. package/dist/lib/utils/task-runner.js.map +0 -1
  121. package/dist/minimal/client-utils/prefetch-cache.d.ts +0 -15
  122. package/dist/minimal/client-utils/prefetch-cache.js +0 -37
  123. package/dist/minimal/client-utils/prefetch-cache.js.map +0 -1
  124. /package/dist/{lib/utils → router/define-router-utils}/task-runner.d.ts +0 -0
  125. /package/dist/{lib/utils → router/define-router-utils}/task-runner.js +0 -0
package/README.md CHANGED
@@ -13,7 +13,7 @@ visit [waku.gg](https://waku.gg) or `npm create waku@latest`
13
13
 
14
14
  ## Introduction
15
15
 
16
- **Waku** _(wah-ku)_ or **わく** is the minimal React framework. It's lightweight and designed for a fun developer experience, yet supports all the latest React 19 features like server components and actions. Built for marketing sites, headless commerce, and web apps. For large enterprise applications, you may prefer a heavier framework.
16
+ **Waku** _(wah-ku)_ or **わく** is the minimal React framework. It's lightweight and designed for a fun developer experience, yet supports all the latest React 19 features like server components and actions. Built for marketing sites, headless commerce, and full-stack web apps, small or large. Whether Waku fits is about the architecture you want, not the size of your project: Waku keeps its framework surface minimal and composes with ecosystem libraries, while heavier frameworks own more of those concerns for you.
17
17
 
18
18
  ## Getting started
19
19
 
@@ -31,13 +31,15 @@ npm create waku@latest
31
31
 
32
32
  **Node.js version requirement:** `^26.0.0` or `^24.0.0` or `^22.15.0`
33
33
 
34
+ For a guided path, start with the [Quick Start](https://waku.gg/guides/quick-start) guide and continue with the Learn series on [waku.gg/guides](https://waku.gg/guides), which builds a small app step by step.
35
+
34
36
  ## Rendering
35
37
 
36
38
  While there's a bit of a learning curve to modern React rendering, it introduces powerful new patterns of full-stack composability that are only possible with the advent of [server components](https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md).
37
39
 
38
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.
39
41
 
40
- 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.
41
43
 
42
44
  > Future versions of Waku may provide additional opt-in APIs to abstract some of the complexity away for an improved developer experience.
43
45
 
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Highly experimental, the name might change.
2
+ * Experimental, the name and the behavior might change.
3
3
  */
4
4
  export declare const unstable_allowServer: <T>(x: T) => T;
5
5
  /**
package/dist/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getErrorInfo } from './lib/utils/custom-errors.js';
2
2
  /**
3
- * Highly experimental, the name might change.
3
+ * Experimental, the name and the behavior might change.
4
4
  */ export const unstable_allowServer = (x)=>x;
5
5
  /**
6
6
  * Unsure if this is going to be a public API in the future.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { getErrorInfo } from './lib/utils/custom-errors.js';\n\n/**\n * Highly experimental, the name might change.\n */\nexport const unstable_allowServer = <T>(x: T) => x;\n\n/**\n * Unsure if this is going to be a public API in the future.\n */\nexport const unstable_defaultRootOptions = {\n onCaughtError(error: unknown) {\n if (getErrorInfo(error)) {\n return;\n }\n console.error(error);\n },\n};\n"],"names":["getErrorInfo","unstable_allowServer","x","unstable_defaultRootOptions","onCaughtError","error","console"],"mappings":"AAAA,SAASA,YAAY,QAAQ,+BAA+B;AAE5D;;CAEC,GACD,OAAO,MAAMC,uBAAuB,CAAIC,IAASA,EAAE;AAEnD;;CAEC,GACD,OAAO,MAAMC,8BAA8B;IACzCC,eAAcC,KAAc;QAC1B,IAAIL,aAAaK,QAAQ;YACvB;QACF;QACAC,QAAQD,KAAK,CAACA;IAChB;AACF,EAAE"}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { getErrorInfo } from './lib/utils/custom-errors.js';\n\n/**\n * Experimental, the name and the behavior might change.\n */\nexport const unstable_allowServer = <T>(x: T) => x;\n\n/**\n * Unsure if this is going to be a public API in the future.\n */\nexport const unstable_defaultRootOptions = {\n onCaughtError(error: unknown) {\n if (getErrorInfo(error)) {\n return;\n }\n console.error(error);\n },\n};\n"],"names":["getErrorInfo","unstable_allowServer","x","unstable_defaultRootOptions","onCaughtError","error","console"],"mappings":"AAAA,SAASA,YAAY,QAAQ,+BAA+B;AAE5D;;CAEC,GACD,OAAO,MAAMC,uBAAuB,CAAIC,IAASA,EAAE;AAEnD;;CAEC,GACD,OAAO,MAAMC,8BAA8B;IACzCC,eAAcC,KAAc;QAC1B,IAAIL,aAAaK,QAAQ;YACvB;QACF;QACAC,QAAQD,KAAK,CAACA;IAChB;AACF,EAAE"}
@@ -4,7 +4,6 @@ declare global {
4
4
  var __WAKU_REFETCH_ROUTE__: (() => void) | undefined;
5
5
  var __WAKU_START_PREVIEW_SERVER__: (() => Promise<import('./vite-rsc/preview.js').PreviewServer>) | undefined;
6
6
  var __WAKU_SERVER_ENV__: Readonly<Record<string, string>> | undefined;
7
- var __WAKU_PREFETCHED__: import('../minimal/client-utils/prefetch-cache.js').PrefetchEntry[] | undefined;
8
7
  var __WAKU_INITIAL_RSC__: import('./utils/initial-rsc.js').InitialRscEntry | undefined;
9
8
  var __WAKU_DEBUG_CHANNELS__: Map<string, {
10
9
  readable: ReadableStream;
@@ -1,11 +1,12 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { Config } from '../config.js';
3
+ import type { Etags } from './utils/etags.js';
3
4
  type Elements = Record<string, unknown>;
4
5
  export type Unstable_RenderRsc = (elements: Elements, options?: {
5
6
  value?: unknown;
7
+ etags?: Etags;
6
8
  unstable_clientModuleCallback?: (ids: string[]) => void;
7
9
  }) => Promise<ReadableStream>;
8
- export type Unstable_ParseRsc = (rscStream: ReadableStream) => Promise<Elements>;
9
10
  export type Unstable_RenderHtml = (elementsStream: ReadableStream, html: ReactNode, options: {
10
11
  rscPath: string;
11
12
  formState?: unknown;
@@ -15,30 +16,33 @@ export type Unstable_RenderHtml = (elementsStream: ReadableStream, html: ReactNo
15
16
  }) => Promise<Response>;
16
17
  export type Unstable_EmitFile = (filePath: string, body: ReadableStream) => Promise<void>;
17
18
  export type Unstable_HandleRequest = (input: ({
18
- type: 'component';
19
+ type: 'rsc';
19
20
  rscPath: string;
20
21
  rscParams: unknown;
21
22
  } | {
22
- type: 'function';
23
+ type: 'call';
23
24
  fn: (...args: unknown[]) => Promise<unknown>;
24
25
  args: unknown[];
25
26
  } | {
26
- type: 'action';
27
- fn: () => Promise<unknown>;
28
- } | {
29
- type: 'custom';
27
+ type: 'http';
28
+ tryAction?: () => Promise<{
29
+ action: true;
30
+ formState: unknown;
31
+ } | {
32
+ action: false;
33
+ formData: FormData;
34
+ }>;
30
35
  }) & {
31
36
  pathname: string;
32
37
  req: Request;
38
+ etags?: Etags;
33
39
  }, utils: {
34
40
  renderRsc: Unstable_RenderRsc;
35
- parseRsc: Unstable_ParseRsc;
36
41
  renderHtml: Unstable_RenderHtml;
37
42
  loadBuildMetadata: (key: string) => Promise<string | undefined>;
38
43
  }) => Promise<ReadableStream | Response | 'fallback' | null | undefined>;
39
44
  export type Unstable_HandleBuild = (utils: {
40
45
  renderRsc: Unstable_RenderRsc;
41
- parseRsc: Unstable_ParseRsc;
42
46
  renderHtml: Unstable_RenderHtml;
43
47
  rscPath2pathname: (rscPath: string) => string;
44
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';\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 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":"AAsGA,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"}
@@ -0,0 +1,8 @@
1
+ export declare const ETAG_ID_PREFIX = "_etag:";
2
+ export declare const ETAGS_HEADER = "X-Waku-Etags";
3
+ export declare const IMMUTABLE_ETAG = 1;
4
+ export type Etag = string | typeof IMMUTABLE_ETAG;
5
+ export type Etags = Record<string, Etag>;
6
+ export declare const isValidEtag: (value: unknown) => value is Etag;
7
+ export declare const parseClientEtags: (serialized: string | null) => Etags;
8
+ export declare const serializeClientEtags: (etags: Etags) => string;
@@ -0,0 +1,30 @@
1
+ export const ETAG_ID_PREFIX = '_etag:';
2
+ export const ETAGS_HEADER = 'X-Waku-Etags';
3
+ // Non-string sentinel, so it cannot collide with a (string) content validator.
4
+ export const IMMUTABLE_ETAG = 1;
5
+ // '' clears a tag; only printable Latin-1 (no control chars) is header-safe
6
+ export const isValidEtag = (value)=>value === IMMUTABLE_ETAG || typeof value === 'string' && value !== '' && /^[\x20-\x7e\xa0-\xff]+$/.test(value);
7
+ export const parseClientEtags = (serialized)=>{
8
+ if (!serialized) {
9
+ return {};
10
+ }
11
+ let parsed;
12
+ try {
13
+ parsed = JSON.parse(serialized);
14
+ } catch {
15
+ return {};
16
+ }
17
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
18
+ return {};
19
+ }
20
+ const etags = {};
21
+ for (const [key, value] of Object.entries(parsed)){
22
+ if (isValidEtag(value)) {
23
+ etags[key] = value;
24
+ }
25
+ }
26
+ return etags;
27
+ };
28
+ export const serializeClientEtags = (etags)=>JSON.stringify(etags);
29
+
30
+ //# sourceMappingURL=etags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils/etags.ts"],"sourcesContent":["export const ETAG_ID_PREFIX = '_etag:';\nexport const ETAGS_HEADER = 'X-Waku-Etags';\n\n// Non-string sentinel, so it cannot collide with a (string) content validator.\nexport const IMMUTABLE_ETAG = 1;\n\nexport type Etag = string | typeof IMMUTABLE_ETAG;\nexport type Etags = Record<string, Etag>;\n\n// '' clears a tag; only printable Latin-1 (no control chars) is header-safe\nexport const isValidEtag = (value: unknown): value is Etag =>\n value === IMMUTABLE_ETAG ||\n (typeof value === 'string' &&\n value !== '' &&\n /^[\\x20-\\x7e\\xa0-\\xff]+$/.test(value));\n\nexport const parseClientEtags = (serialized: string | null): Etags => {\n if (!serialized) {\n return {};\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(serialized);\n } catch {\n return {};\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n return {};\n }\n const etags: Etags = {};\n for (const [key, value] of Object.entries(parsed)) {\n if (isValidEtag(value)) {\n etags[key] = value;\n }\n }\n return etags;\n};\n\nexport const serializeClientEtags = (etags: Etags): string =>\n JSON.stringify(etags);\n"],"names":["ETAG_ID_PREFIX","ETAGS_HEADER","IMMUTABLE_ETAG","isValidEtag","value","test","parseClientEtags","serialized","parsed","JSON","parse","Array","isArray","etags","key","Object","entries","serializeClientEtags","stringify"],"mappings":"AAAA,OAAO,MAAMA,iBAAiB,SAAS;AACvC,OAAO,MAAMC,eAAe,eAAe;AAE3C,+EAA+E;AAC/E,OAAO,MAAMC,iBAAiB,EAAE;AAKhC,4EAA4E;AAC5E,OAAO,MAAMC,cAAc,CAACC,QAC1BA,UAAUF,kBACT,OAAOE,UAAU,YAChBA,UAAU,MACV,0BAA0BC,IAAI,CAACD,OAAQ;AAE3C,OAAO,MAAME,mBAAmB,CAACC;IAC/B,IAAI,CAACA,YAAY;QACf,OAAO,CAAC;IACV;IACA,IAAIC;IACJ,IAAI;QACFA,SAASC,KAAKC,KAAK,CAACH;IACtB,EAAE,OAAM;QACN,OAAO,CAAC;IACV;IACA,IAAI,OAAOC,WAAW,YAAYA,WAAW,QAAQG,MAAMC,OAAO,CAACJ,SAAS;QAC1E,OAAO,CAAC;IACV;IACA,MAAMK,QAAe,CAAC;IACtB,KAAK,MAAM,CAACC,KAAKV,MAAM,IAAIW,OAAOC,OAAO,CAACR,QAAS;QACjD,IAAIL,YAAYC,QAAQ;YACtBS,KAAK,CAACC,IAAI,GAAGV;QACf;IACF;IACA,OAAOS;AACT,EAAE;AAEF,OAAO,MAAMI,uBAAuB,CAACJ,QACnCJ,KAAKS,SAAS,CAACL,OAAO"}
@@ -4,46 +4,5 @@ export declare const filePathToFileURL: (filePath: string) => string;
4
4
  export declare const fileURLToFilePath: (fileURL: string) => string;
5
5
  export declare const joinPath: (...paths: string[]) => string;
6
6
  export declare const extname: (filePath: string) => string;
7
- export type PathSpecItem = {
8
- type: 'literal';
9
- name: string;
10
- } | {
11
- type: 'group';
12
- name?: string;
13
- prefix?: string;
14
- suffix?: string;
15
- } | {
16
- type: 'wildcard';
17
- name?: string;
18
- };
19
- export type PathSpec = readonly PathSpecItem[];
20
- export declare const parsePathWithSlug: (path: string) => PathSpec;
21
- export declare const parseExactPath: (path: string) => PathSpec;
22
- /**
23
- * Transform a path spec to a regular expression.
24
- */
25
- export declare const path2regexp: (path: PathSpec) => string;
26
- /** Convert a path spec to a string for the path */
27
- export declare const pathSpecAsString: (path: PathSpec) => string;
28
- /**
29
- * Helper function to get the path mapping from the path spec and the pathname.
30
- *
31
- * @param pathSpec
32
- * @param pathname - route as a string
33
- * @example
34
- * getPathMapping(
35
- * [
36
- * { type: 'literal', name: 'foo' },
37
- * { type: 'group', name: 'a' },
38
- * ],
39
- * '/foo/bar',
40
- * );
41
- * // => { a: 'bar' }
42
- */
43
- export declare const getPathMapping: (pathSpec: PathSpec, pathname: string) => Record<string, string | string[]> | null;
44
7
  export declare function removeBase(url: string, base: string): string;
45
8
  export declare function addBase(url: string, base: string): string;
46
- export declare function countSlugsAndWildcards(pathSpec: PathSpec): {
47
- numSlugs: number;
48
- numWildcards: number;
49
- };
@@ -59,168 +59,6 @@ export const extname = (filePath)=>{
59
59
  }
60
60
  return filePath.slice(index);
61
61
  };
62
- const SLUG_PATTERN = /^(.*?)\[([^\]]+)\](.*)$/;
63
- export const parsePathWithSlug = (path)=>path.split('/').filter(Boolean).map((name)=>{
64
- const match = SLUG_PATTERN.exec(name);
65
- if (!match) {
66
- return {
67
- type: 'literal',
68
- name
69
- };
70
- }
71
- const [, prefix, inner, suffix] = match;
72
- if (inner.startsWith('...')) {
73
- return {
74
- type: 'wildcard',
75
- name: inner.slice(3)
76
- };
77
- }
78
- return {
79
- type: 'group',
80
- name: inner,
81
- ...prefix ? {
82
- prefix
83
- } : {},
84
- ...suffix ? {
85
- suffix
86
- } : {}
87
- };
88
- });
89
- export const parseExactPath = (path)=>path.split('/').filter(Boolean).map((name)=>({
90
- type: 'literal',
91
- name
92
- }));
93
- const escapeRegExp = (s)=>s.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&');
94
- /**
95
- * Transform a path spec to a regular expression.
96
- */ export const path2regexp = (path)=>{
97
- const parts = path.map((item)=>{
98
- if (item.type === 'literal') {
99
- return escapeRegExp(item.name);
100
- } else if (item.type === 'group') {
101
- const prefix = escapeRegExp(item.prefix ?? '');
102
- const suffix = escapeRegExp(item.suffix ?? '');
103
- return `${prefix}([^/]+)${suffix}`;
104
- } else {
105
- return `(.*)`;
106
- }
107
- });
108
- return `^/${parts.join('/')}$`;
109
- };
110
- /** Convert a path spec to a string for the path */ export const pathSpecAsString = (path)=>{
111
- return '/' + path.map((item)=>{
112
- if (item.type === 'literal') {
113
- return item.name;
114
- } else if (item.type === 'group') {
115
- const prefix = item.prefix ?? '';
116
- const suffix = item.suffix ?? '';
117
- return `${prefix}[${item.name}]${suffix}`;
118
- } else {
119
- return `[...${item.name}]`;
120
- }
121
- }).join('/');
122
- };
123
- const matchSpecSegment = (spec, segment, mapping)=>{
124
- if (spec.type === 'literal') {
125
- return spec.name === segment;
126
- }
127
- if (segment === undefined) {
128
- return false;
129
- }
130
- const prefix = spec.prefix ?? '';
131
- const suffix = spec.suffix ?? '';
132
- if (prefix || suffix) {
133
- if (!segment.startsWith(prefix) || !segment.endsWith(suffix)) {
134
- return false;
135
- }
136
- const value = segment.slice(prefix.length, suffix ? -suffix.length : undefined);
137
- if (!value) {
138
- return false;
139
- }
140
- if (spec.name) {
141
- mapping[spec.name] = value;
142
- }
143
- } else if (spec.name) {
144
- mapping[spec.name] = segment;
145
- }
146
- return true;
147
- };
148
- /**
149
- * Helper function to get the path mapping from the path spec and the pathname.
150
- *
151
- * @param pathSpec
152
- * @param pathname - route as a string
153
- * @example
154
- * getPathMapping(
155
- * [
156
- * { type: 'literal', name: 'foo' },
157
- * { type: 'group', name: 'a' },
158
- * ],
159
- * '/foo/bar',
160
- * );
161
- * // => { a: 'bar' }
162
- */ export const getPathMapping = (pathSpec, pathname)=>{
163
- const actual = pathname.split('/').filter(Boolean);
164
- if (pathSpec.length > actual.length) {
165
- const wildcardIndex = pathSpec.findIndex((spec)=>spec.type === 'wildcard');
166
- if (wildcardIndex === -1) {
167
- return null;
168
- }
169
- const isTerminalWildcard = wildcardIndex === pathSpec.length - 1;
170
- if (isTerminalWildcard) {
171
- // Terminal wildcards only pass through with zero actual segments
172
- // (handled by the root-wildcard special case below)
173
- if (actual.length > 0) {
174
- return null;
175
- }
176
- } else if (actual.length < pathSpec.length - 1) {
177
- // Non-terminal wildcards can match zero segments; just need enough
178
- // actual segments for every non-wildcard spec in the pathSpec
179
- return null;
180
- }
181
- }
182
- const mapping = {};
183
- let wildcardStartIndex = -1;
184
- for(let i = 0; i < pathSpec.length; i++){
185
- const spec = pathSpec[i];
186
- if (spec.type === 'wildcard') {
187
- wildcardStartIndex = i;
188
- break;
189
- }
190
- if (!matchSpecSegment(spec, actual[i], mapping)) {
191
- return null;
192
- }
193
- }
194
- if (wildcardStartIndex === -1) {
195
- if (pathSpec.length !== actual.length) {
196
- return null;
197
- }
198
- return mapping;
199
- }
200
- if (wildcardStartIndex === 0 && actual.length === 0) {
201
- const wildcardName = pathSpec[wildcardStartIndex].name;
202
- if (wildcardName) {
203
- mapping[wildcardName] = [];
204
- }
205
- return mapping;
206
- }
207
- let wildcardEndIndex = -1;
208
- for(let i = 0; i < pathSpec.length; i++){
209
- const spec = pathSpec[pathSpec.length - i - 1];
210
- if (spec.type === 'wildcard') {
211
- wildcardEndIndex = actual.length - i - 1;
212
- break;
213
- }
214
- if (!matchSpecSegment(spec, actual[actual.length - i - 1], mapping)) {
215
- return null;
216
- }
217
- }
218
- const wildcardName = pathSpec[wildcardStartIndex].name;
219
- if (wildcardName) {
220
- mapping[wildcardName] = actual.slice(wildcardStartIndex, wildcardEndIndex + 1);
221
- }
222
- return mapping;
223
- };
224
62
  // basePath config is ensured to have trailing slash (see plugin)
225
63
  export function removeBase(url, base) {
226
64
  if (base !== '/') {
@@ -237,21 +75,5 @@ export function addBase(url, base) {
237
75
  }
238
76
  return url;
239
77
  }
240
- export function countSlugsAndWildcards(pathSpec) {
241
- let numSlugs = 0;
242
- let numWildcards = 0;
243
- for (const slug of pathSpec){
244
- if (slug.type !== 'literal') {
245
- numSlugs++;
246
- }
247
- if (slug.type === 'wildcard') {
248
- numWildcards++;
249
- }
250
- }
251
- return {
252
- numSlugs,
253
- numWildcards
254
- };
255
- }
256
78
 
257
79
  //# sourceMappingURL=path.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils/path.ts"],"sourcesContent":["// Terminology:\n// - filePath: posix-like file path, e.g. `/foo/bar.js` or `c:/foo/bar.js`\n// This is used by Vite.\n// - fileURL: file URL, e.g. `file:///foo/bar.js` or `file:///c:/foo/bar.js`\n// This is used by import().\n// - osPath: os dependent path, e.g. `/foo/bar.js` or `c:\\foo\\bar.js`\n// This is used by node:fs.\n\nconst ABSOLUTE_WIN32_PATH_REGEXP = /^\\/[a-zA-Z]:\\//;\n\nexport const encodeFilePathToAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n throw new Error('Unsupported absolute file path: ' + filePath);\n }\n if (filePath.startsWith('/')) {\n return filePath;\n }\n return '/' + filePath;\n};\n\nexport const decodeFilePathFromAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n return filePath.slice(1);\n }\n return filePath;\n};\n\nexport const filePathToFileURL = (filePath: string) =>\n 'file://' + encodeURI(filePath);\n\nexport const fileURLToFilePath = (fileURL: string) => {\n if (!fileURL.startsWith('file://')) {\n throw new Error('Not a file URL');\n }\n return decodeURI(fileURL.slice('file://'.length));\n};\n\n// for filePath\nexport const joinPath = (...paths: string[]) => {\n const isAbsolute = paths[0]?.startsWith('/');\n const items = ([] as string[]).concat(\n ...paths.map((path) => path.split('/')),\n );\n const stack: string[] = [];\n for (const item of items) {\n if (item === '..') {\n if (stack.length && stack[stack.length - 1] !== '..') {\n stack.pop();\n } else if (!isAbsolute) {\n stack.push('..');\n }\n } else if (item && item !== '.') {\n stack.push(item);\n }\n }\n return (isAbsolute ? '/' : '') + stack.join('/') || '.';\n};\n\nexport const extname = (filePath: string) => {\n const index = filePath.lastIndexOf('.');\n if (index <= 0) {\n return '';\n }\n if (['/', '.'].includes(filePath[index - 1]!)) {\n return '';\n }\n return filePath.slice(index);\n};\n\nexport type PathSpecItem =\n | { type: 'literal'; name: string }\n | { type: 'group'; name?: string; prefix?: string; suffix?: string }\n | { type: 'wildcard'; name?: string };\nexport type PathSpec = readonly PathSpecItem[];\n\nconst SLUG_PATTERN = /^(.*?)\\[([^\\]]+)\\](.*)$/;\n\nexport const parsePathWithSlug = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => {\n const match = SLUG_PATTERN.exec(name);\n if (!match) {\n return { type: 'literal' as const, name };\n }\n const [, prefix, inner, suffix] = match;\n if (inner!.startsWith('...')) {\n return {\n type: 'wildcard' as const,\n name: inner!.slice(3),\n };\n }\n return {\n type: 'group' as const,\n name: inner!,\n ...(prefix ? { prefix } : {}),\n ...(suffix ? { suffix } : {}),\n };\n });\n\nexport const parseExactPath = (path: string): PathSpec =>\n path\n .split('/')\n .filter(Boolean)\n .map((name) => ({ type: 'literal', name }));\n\nconst escapeRegExp = (s: string) => s.replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&');\n\n/**\n * Transform a path spec to a regular expression.\n */\nexport const path2regexp = (path: PathSpec) => {\n const parts = path.map((item) => {\n if (item.type === 'literal') {\n return escapeRegExp(item.name);\n } else if (item.type === 'group') {\n const prefix = escapeRegExp(item.prefix ?? '');\n const suffix = escapeRegExp(item.suffix ?? '');\n return `${prefix}([^/]+)${suffix}`;\n } else {\n return `(.*)`;\n }\n });\n return `^/${parts.join('/')}$`;\n};\n\n/** Convert a path spec to a string for the path */\nexport const pathSpecAsString = (path: PathSpec) => {\n return (\n '/' +\n path\n .map((item) => {\n if (item.type === 'literal') {\n return item.name;\n } else if (item.type === 'group') {\n const prefix = item.prefix ?? '';\n const suffix = item.suffix ?? '';\n return `${prefix}[${item.name}]${suffix}`;\n } else {\n return `[...${item.name}]`;\n }\n })\n .join('/')\n );\n};\n\nconst matchSpecSegment = (\n spec: Exclude<PathSpecItem, { type: 'wildcard' }>,\n segment: string | undefined,\n mapping: Record<string, string | string[]>,\n): boolean => {\n if (spec.type === 'literal') {\n return spec.name === segment;\n }\n if (segment === undefined) {\n return false;\n }\n const prefix = spec.prefix ?? '';\n const suffix = spec.suffix ?? '';\n if (prefix || suffix) {\n if (!segment.startsWith(prefix) || !segment.endsWith(suffix)) {\n return false;\n }\n const value = segment.slice(\n prefix.length,\n suffix ? -suffix.length : undefined,\n );\n if (!value) {\n return false;\n }\n if (spec.name) {\n mapping[spec.name] = value;\n }\n } else if (spec.name) {\n mapping[spec.name] = segment;\n }\n return true;\n};\n\n/**\n * Helper function to get the path mapping from the path spec and the pathname.\n *\n * @param pathSpec\n * @param pathname - route as a string\n * @example\n * getPathMapping(\n * [\n * { type: 'literal', name: 'foo' },\n * { type: 'group', name: 'a' },\n * ],\n * '/foo/bar',\n * );\n * // => { a: 'bar' }\n */\nexport const getPathMapping = (\n pathSpec: PathSpec,\n pathname: string,\n): Record<string, string | string[]> | null => {\n const actual = pathname.split('/').filter(Boolean);\n if (pathSpec.length > actual.length) {\n const wildcardIndex = pathSpec.findIndex(\n (spec) => spec.type === 'wildcard',\n );\n if (wildcardIndex === -1) {\n return null;\n }\n const isTerminalWildcard = wildcardIndex === pathSpec.length - 1;\n if (isTerminalWildcard) {\n // Terminal wildcards only pass through with zero actual segments\n // (handled by the root-wildcard special case below)\n if (actual.length > 0) {\n return null;\n }\n } else if (actual.length < pathSpec.length - 1) {\n // Non-terminal wildcards can match zero segments; just need enough\n // actual segments for every non-wildcard spec in the pathSpec\n return null;\n }\n }\n const mapping: Record<string, string | string[]> = {};\n let wildcardStartIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[i]!;\n if (spec.type === 'wildcard') {\n wildcardStartIndex = i;\n break;\n }\n if (!matchSpecSegment(spec, actual[i], mapping)) {\n return null;\n }\n }\n if (wildcardStartIndex === -1) {\n if (pathSpec.length !== actual.length) {\n return null;\n }\n return mapping;\n }\n\n if (wildcardStartIndex === 0 && actual.length === 0) {\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = [];\n }\n return mapping;\n }\n\n let wildcardEndIndex = -1;\n for (let i = 0; i < pathSpec.length; i++) {\n const spec = pathSpec[pathSpec.length - i - 1]!;\n if (spec.type === 'wildcard') {\n wildcardEndIndex = actual.length - i - 1;\n break;\n }\n if (!matchSpecSegment(spec, actual[actual.length - i - 1], mapping)) {\n return null;\n }\n }\n const wildcardName = pathSpec[wildcardStartIndex]!.name;\n if (wildcardName) {\n mapping[wildcardName] = actual.slice(\n wildcardStartIndex,\n wildcardEndIndex + 1,\n );\n }\n return mapping;\n};\n\n// basePath config is ensured to have trailing slash (see plugin)\nexport function removeBase(url: string, base: string) {\n if (base !== '/') {\n if (!url.startsWith(base)) {\n throw new Error('pathname must start with basePath: ' + url);\n }\n return url.slice(base.length - 1);\n }\n return url;\n}\n\nexport function addBase(url: string, base: string) {\n if (base !== '/' && url.startsWith('/')) {\n return base.slice(0, -1) + url;\n }\n return url;\n}\n\nexport function countSlugsAndWildcards(pathSpec: PathSpec) {\n let numSlugs = 0;\n let numWildcards = 0;\n for (const slug of pathSpec) {\n if (slug.type !== 'literal') {\n numSlugs++;\n }\n if (slug.type === 'wildcard') {\n numWildcards++;\n }\n }\n return { numSlugs, numWildcards };\n}\n"],"names":["ABSOLUTE_WIN32_PATH_REGEXP","encodeFilePathToAbsolute","filePath","test","Error","startsWith","decodeFilePathFromAbsolute","slice","filePathToFileURL","encodeURI","fileURLToFilePath","fileURL","decodeURI","length","joinPath","paths","isAbsolute","items","concat","map","path","split","stack","item","pop","push","join","extname","index","lastIndexOf","includes","SLUG_PATTERN","parsePathWithSlug","filter","Boolean","name","match","exec","type","prefix","inner","suffix","parseExactPath","escapeRegExp","s","replace","path2regexp","parts","pathSpecAsString","matchSpecSegment","spec","segment","mapping","undefined","endsWith","value","getPathMapping","pathSpec","pathname","actual","wildcardIndex","findIndex","isTerminalWildcard","wildcardStartIndex","i","wildcardName","wildcardEndIndex","removeBase","url","base","addBase","countSlugsAndWildcards","numSlugs","numWildcards","slug"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/lib/utils/path.ts"],"sourcesContent":["// Terminology:\n// - filePath: posix-like file path, e.g. `/foo/bar.js` or `c:/foo/bar.js`\n// This is used by Vite.\n// - fileURL: file URL, e.g. `file:///foo/bar.js` or `file:///c:/foo/bar.js`\n// This is used by import().\n// - osPath: os dependent path, e.g. `/foo/bar.js` or `c:\\foo\\bar.js`\n// This is used by node:fs.\n\nconst ABSOLUTE_WIN32_PATH_REGEXP = /^\\/[a-zA-Z]:\\//;\n\nexport const encodeFilePathToAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n throw new Error('Unsupported absolute file path: ' + filePath);\n }\n if (filePath.startsWith('/')) {\n return filePath;\n }\n return '/' + filePath;\n};\n\nexport const decodeFilePathFromAbsolute = (filePath: string) => {\n if (ABSOLUTE_WIN32_PATH_REGEXP.test(filePath)) {\n return filePath.slice(1);\n }\n return filePath;\n};\n\nexport const filePathToFileURL = (filePath: string) =>\n 'file://' + encodeURI(filePath);\n\nexport const fileURLToFilePath = (fileURL: string) => {\n if (!fileURL.startsWith('file://')) {\n throw new Error('Not a file URL');\n }\n return decodeURI(fileURL.slice('file://'.length));\n};\n\n// for filePath\nexport const joinPath = (...paths: string[]) => {\n const isAbsolute = paths[0]?.startsWith('/');\n const items = ([] as string[]).concat(\n ...paths.map((path) => path.split('/')),\n );\n const stack: string[] = [];\n for (const item of items) {\n if (item === '..') {\n if (stack.length && stack[stack.length - 1] !== '..') {\n stack.pop();\n } else if (!isAbsolute) {\n stack.push('..');\n }\n } else if (item && item !== '.') {\n stack.push(item);\n }\n }\n return (isAbsolute ? '/' : '') + stack.join('/') || '.';\n};\n\nexport const extname = (filePath: string) => {\n const index = filePath.lastIndexOf('.');\n if (index <= 0) {\n return '';\n }\n if (['/', '.'].includes(filePath[index - 1]!)) {\n return '';\n }\n return filePath.slice(index);\n};\n\n// basePath config is ensured to have trailing slash (see plugin)\nexport function removeBase(url: string, base: string) {\n if (base !== '/') {\n if (!url.startsWith(base)) {\n throw new Error('pathname must start with basePath: ' + url);\n }\n return url.slice(base.length - 1);\n }\n return url;\n}\n\nexport function addBase(url: string, base: string) {\n if (base !== '/' && url.startsWith('/')) {\n return base.slice(0, -1) + url;\n }\n return url;\n}\n"],"names":["ABSOLUTE_WIN32_PATH_REGEXP","encodeFilePathToAbsolute","filePath","test","Error","startsWith","decodeFilePathFromAbsolute","slice","filePathToFileURL","encodeURI","fileURLToFilePath","fileURL","decodeURI","length","joinPath","paths","isAbsolute","items","concat","map","path","split","stack","item","pop","push","join","extname","index","lastIndexOf","includes","removeBase","url","base","addBase"],"mappings":"AAAA,eAAe;AACf,0EAA0E;AAC1E,0BAA0B;AAC1B,4EAA4E;AAC5E,8BAA8B;AAC9B,qEAAqE;AACrE,6BAA6B;AAE7B,MAAMA,6BAA6B;AAEnC,OAAO,MAAMC,2BAA2B,CAACC;IACvC,IAAIF,2BAA2BG,IAAI,CAACD,WAAW;QAC7C,MAAM,IAAIE,MAAM,qCAAqCF;IACvD;IACA,IAAIA,SAASG,UAAU,CAAC,MAAM;QAC5B,OAAOH;IACT;IACA,OAAO,MAAMA;AACf,EAAE;AAEF,OAAO,MAAMI,6BAA6B,CAACJ;IACzC,IAAIF,2BAA2BG,IAAI,CAACD,WAAW;QAC7C,OAAOA,SAASK,KAAK,CAAC;IACxB;IACA,OAAOL;AACT,EAAE;AAEF,OAAO,MAAMM,oBAAoB,CAACN,WAChC,YAAYO,UAAUP,UAAU;AAElC,OAAO,MAAMQ,oBAAoB,CAACC;IAChC,IAAI,CAACA,QAAQN,UAAU,CAAC,YAAY;QAClC,MAAM,IAAID,MAAM;IAClB;IACA,OAAOQ,UAAUD,QAAQJ,KAAK,CAAC,UAAUM,MAAM;AACjD,EAAE;AAEF,eAAe;AACf,OAAO,MAAMC,WAAW,CAAC,GAAGC;IAC1B,MAAMC,aAAaD,KAAK,CAAC,EAAE,EAAEV,WAAW;IACxC,MAAMY,QAAQ,AAAC,EAAE,CAAcC,MAAM,IAChCH,MAAMI,GAAG,CAAC,CAACC,OAASA,KAAKC,KAAK,CAAC;IAEpC,MAAMC,QAAkB,EAAE;IAC1B,KAAK,MAAMC,QAAQN,MAAO;QACxB,IAAIM,SAAS,MAAM;YACjB,IAAID,MAAMT,MAAM,IAAIS,KAAK,CAACA,MAAMT,MAAM,GAAG,EAAE,KAAK,MAAM;gBACpDS,MAAME,GAAG;YACX,OAAO,IAAI,CAACR,YAAY;gBACtBM,MAAMG,IAAI,CAAC;YACb;QACF,OAAO,IAAIF,QAAQA,SAAS,KAAK;YAC/BD,MAAMG,IAAI,CAACF;QACb;IACF;IACA,OAAO,AAACP,CAAAA,aAAa,MAAM,EAAC,IAAKM,MAAMI,IAAI,CAAC,QAAQ;AACtD,EAAE;AAEF,OAAO,MAAMC,UAAU,CAACzB;IACtB,MAAM0B,QAAQ1B,SAAS2B,WAAW,CAAC;IACnC,IAAID,SAAS,GAAG;QACd,OAAO;IACT;IACA,IAAI;QAAC;QAAK;KAAI,CAACE,QAAQ,CAAC5B,QAAQ,CAAC0B,QAAQ,EAAE,GAAI;QAC7C,OAAO;IACT;IACA,OAAO1B,SAASK,KAAK,CAACqB;AACxB,EAAE;AAEF,iEAAiE;AACjE,OAAO,SAASG,WAAWC,GAAW,EAAEC,IAAY;IAClD,IAAIA,SAAS,KAAK;QAChB,IAAI,CAACD,IAAI3B,UAAU,CAAC4B,OAAO;YACzB,MAAM,IAAI7B,MAAM,wCAAwC4B;QAC1D;QACA,OAAOA,IAAIzB,KAAK,CAAC0B,KAAKpB,MAAM,GAAG;IACjC;IACA,OAAOmB;AACT;AAEA,OAAO,SAASE,QAAQF,GAAW,EAAEC,IAAY;IAC/C,IAAIA,SAAS,OAAOD,IAAI3B,UAAU,CAAC,MAAM;QACvC,OAAO4B,KAAK1B,KAAK,CAAC,GAAG,CAAC,KAAKyB;IAC7B;IACA,OAAOA;AACT"}
@@ -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
  };
@@ -1,3 +1,4 @@
1
+ import { ETAG_ID_PREFIX } from './etags.js';
1
2
  import { sanitizeLog } from './log.js';
2
3
  const validateRscElementIds = (elements)=>{
3
4
  for (const id of Object.keys(elements)){
@@ -6,7 +7,7 @@ const validateRscElementIds = (elements)=>{
6
7
  }
7
8
  }
8
9
  };
9
- export function createRenderUtils(temporaryReferences, renderToReadableStream, createFromReadableStream, loadSsrEntryModule, buildId, debugChannel, debugId) {
10
+ export function createRenderUtils(temporaryReferences, renderToReadableStream, loadSsrEntryModule, buildId, debugChannel, debugId) {
10
11
  const onError = (e)=>{
11
12
  if (e && typeof e === 'object' && 'digest' in e && typeof e.digest === 'string') {
12
13
  return e.digest;
@@ -25,6 +26,11 @@ export function createRenderUtils(temporaryReferences, renderToReadableStream, c
25
26
  if (options && 'value' in options) {
26
27
  data._value = options.value;
27
28
  }
29
+ if (options?.etags) {
30
+ for (const [slotId, etag] of Object.entries(options.etags)){
31
+ data[ETAG_ID_PREFIX + slotId] = etag;
32
+ }
33
+ }
28
34
  return renderToReadableStream(data, {
29
35
  temporaryReferences,
30
36
  onError,
@@ -35,9 +41,6 @@ export function createRenderUtils(temporaryReferences, renderToReadableStream, c
35
41
  }
36
42
  });
37
43
  },
38
- async parseRsc (stream) {
39
- return createFromReadableStream(stream, {});
40
- },
41
44
  async renderHtml (elementsStream, html, options) {
42
45
  const { INTERNAL_renderHtmlStream: renderHtmlStream } = await loadSsrEntryModule();
43
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 { 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 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":["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","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,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,OAAOhB,uBACLa,MACA;gBACEd;gBACAO;gBACAF;YACF,GACA;gBACEa,mBAAkBC,QAIjB;oBACCN,SAASO,gCAAgCD,SAASE,IAAI,CAACC,EAAE;gBAC3D;YACF;QAEJ;QACA,MAAMC,UAASC,MAAM;YACnB,OAAOtB,yBAAyBsB,QAAQ,CAAC;QAG3C;QACA,MAAMC,YAAWC,cAAc,EAAEC,IAAI,EAAEd,OAAO;YAC5C,MAAM,EAAEe,2BAA2BC,gBAAgB,EAAE,GACnD,MAAM1B;YAER,MAAM2B,gBAAgB7B,uBAAuB0B,MAAM;gBACjDpB;YACF;YACA,MAAMwB,aAAa,MAAMF,iBAAiBH,gBAAgBI,eAAe;gBACvEE,SAASnB,QAAQmB,OAAO;gBACxBC,WAAWpB,QAAQoB,SAAS;gBAC5BC,OAAOrB,QAAQqB,KAAK;gBACpBC,oBAAoBtB,QAAQuB,2BAA2B;gBACvD9B;YACF;YACA,OAAO,IAAI+B,SAASN,WAAWP,MAAM,EAAE;gBACrCc,QAAQP,WAAWO,MAAM,IAAIzB,QAAQyB,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"}