@reckona/mreact-server 0.0.159 → 0.0.161

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.
@@ -1,39 +1,55 @@
1
1
  import type { HtmlSink } from "@reckona/mreact-shared/compiler-contract";
2
+ /** Options shared by async boundaries that render resolved values or caught errors. */
2
3
  export interface AsyncBoundaryOptions {
3
4
  catch?: (sink: HtmlSink, error: unknown) => void | PromiseLike<void>;
4
5
  hydrationAwaitId?: string;
5
6
  }
7
+ /** Options for rendering a boundary whose resolved content can arrive out of order. */
6
8
  export interface OutOfOrderBoundaryOptions extends AsyncBoundaryOptions {
7
9
  hydration?: boolean;
8
10
  placeholder?: (sink: HtmlSink) => void;
9
11
  placeholderTag?: string;
10
12
  }
13
+ /** Options for emitting the out-of-order fragment reorder script. */
11
14
  export interface OutOfOrderReorderScriptOptions {
12
15
  nonce?: string;
13
16
  src?: string;
14
17
  }
18
+ /** Options for script tags that hydrate server-rendered data. */
15
19
  export interface HydrationScriptOptions {
16
20
  nonce?: string;
17
21
  }
22
+ /** Options for scripts that reveal React Suspense segments. */
18
23
  export interface ReactSuspenseScriptOptions {
19
24
  nonce?: string;
20
25
  src?: string;
21
26
  }
27
+ /** Options for React Suspense boundaries rendered with streamed segments. */
22
28
  export interface ReactSuspenseBoundaryOptions extends AsyncBoundaryOptions {
23
29
  fallback?: (sink: HtmlSink) => void | PromiseLike<void>;
24
30
  nonce?: string;
25
31
  }
32
+ /** Error metadata used when forcing a React Suspense boundary to client render. */
26
33
  export interface ReactSuspenseClientRenderOptions {
27
34
  message?: string;
28
35
  stack?: string;
29
36
  }
37
+ /** Renderer invoked with an async boundary's resolved value. */
30
38
  export type AsyncBoundaryRender<T> = (sink: HtmlSink, value: Awaited<T>) => void | PromiseLike<void>;
39
+ /** Renders a value once it resolves, or renders a configured catch branch on error. */
31
40
  export declare function renderAsyncBoundary<T>(sink: HtmlSink, value: T, render: AsyncBoundaryRender<T>, options?: AsyncBoundaryOptions): Promise<void>;
41
+ /** Emits a placeholder immediately and defers resolved HTML as an out-of-order fragment. */
32
42
  export declare function renderOutOfOrderBoundary<T>(sink: HtmlSink, id: string, value: T, render: AsyncBoundaryRender<T>, options?: OutOfOrderBoundaryOptions): void;
43
+ /** Emits the client script that swaps out-of-order fragments into their placeholders. */
33
44
  export declare function renderOutOfOrderReorderScript(sink: HtmlSink, options?: OutOfOrderReorderScriptOptions): void;
45
+ /** Wraps streamed content in React Suspense completion markers. */
34
46
  export declare function renderReactSuspenseBoundary(sink: HtmlSink, render: (sink: HtmlSink) => void | PromiseLike<void>): void | PromiseLike<void>;
47
+ /** Emits a React Suspense fallback and streams the resolved segment out of order. */
35
48
  export declare function renderReactSuspenseOutOfOrderBoundary<T>(sink: HtmlSink, boundaryId: string, segmentId: string, value: T, render: AsyncBoundaryRender<T>, options?: ReactSuspenseBoundaryOptions): void;
49
+ /** Emits a React Suspense boundary that instructs the client to render the fallback. */
36
50
  export declare function renderReactSuspenseClientRenderBoundary(sink: HtmlSink, fallback: (sink: HtmlSink) => void | PromiseLike<void>, options?: ReactSuspenseClientRenderOptions): void | PromiseLike<void>;
51
+ /** Wraps server-rendered HTML in hydration start and end markers. */
37
52
  export declare function renderHydrationBoundary(sink: HtmlSink, id: string, render: (sink: HtmlSink) => void | PromiseLike<void>): void | PromiseLike<void>;
53
+ /** External script body that reveals a React Suspense segment when loaded. */
38
54
  export declare const reactSuspenseRevealExternalScript = "(()=>{(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data===\"$\"||n.data===\"$?\"||n.data===\"$!\")d++;else if(n.data===\"/$\"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data=\"$\";});var s=document.currentScript;if(!s)return;var b=s.getAttribute(\"data-boundary-id\");var seg=s.getAttribute(\"data-segment-id\");if(b!==null&&seg!==null)self.$RC(b,seg);})();";
39
55
  //# sourceMappingURL=boundary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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"}
package/dist/boundary.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { escapeAttribute, isPromiseLikeUnknown, renderNonceAttribute, serializeScriptJson, } from "./html-internals.js";
2
2
  import { createStringSink } from "./sink.js";
3
3
  const outOfOrderBoundaryInstances = new WeakMap();
4
+ /** Renders a value once it resolves, or renders a configured catch branch on error. */
4
5
  export async function renderAsyncBoundary(sink, value, render, options = {}) {
5
6
  try {
6
7
  const resolved = await value;
@@ -128,6 +129,7 @@ function inheritBackpressure(childSink, parentSink) {
128
129
  backpressure: parentSink.backpressure,
129
130
  };
130
131
  }
132
+ /** Emits a placeholder immediately and defers resolved HTML as an out-of-order fragment. */
131
133
  export function renderOutOfOrderBoundary(sink, id, value, render, options = {}) {
132
134
  const boundaryId = nextOutOfOrderBoundaryInstanceId(sink, id);
133
135
  const placeholderSink = createStringSink();
@@ -168,6 +170,7 @@ async function renderOutOfOrderFragment(sink, id, value, render, options) {
168
170
  appendAwaitHydrationData(sink, options.hydrationAwaitId, resolvedValue);
169
171
  }
170
172
  }
173
+ /** Emits the client script that swaps out-of-order fragments into their placeholders. */
171
174
  export function renderOutOfOrderReorderScript(sink, options = {}) {
172
175
  const nonceAttribute = options.nonce === undefined ? "" : ` nonce="${escapeAttribute(options.nonce)}"`;
173
176
  if (options.src !== undefined) {
@@ -180,6 +183,7 @@ function renderOutOfOrderFragmentHtml(id, html) {
180
183
  const escapedId = escapeAttribute(id);
181
184
  return `<template data-mreact-oob-fragment="${escapedId}">${html}</template><mreact-oob-complete hidden data-mreact-oob-complete="${escapedId}"></mreact-oob-complete>`;
182
185
  }
186
+ /** Wraps streamed content in React Suspense completion markers. */
183
187
  export function renderReactSuspenseBoundary(sink, render) {
184
188
  sink.append("<!--$-->");
185
189
  const result = render(sink);
@@ -190,6 +194,7 @@ export function renderReactSuspenseBoundary(sink, render) {
190
194
  }
191
195
  sink.append("<!--/$-->");
192
196
  }
197
+ /** Emits a React Suspense fallback and streams the resolved segment out of order. */
193
198
  export function renderReactSuspenseOutOfOrderBoundary(sink, boundaryId, segmentId, value, render, options = {}) {
194
199
  const actualBoundaryId = nextOutOfOrderBoundaryInstanceId(sink, boundaryId);
195
200
  const suffix = actualBoundaryId.slice(boundaryId.length);
@@ -214,6 +219,7 @@ function nextOutOfOrderBoundaryInstanceId(sink, id) {
214
219
  instances.set(id, count + 1);
215
220
  return count === 0 ? id : `${id}-${count.toString(36)}`;
216
221
  }
222
+ /** Emits a React Suspense boundary that instructs the client to render the fallback. */
217
223
  export function renderReactSuspenseClientRenderBoundary(sink, fallback, options = {}) {
218
224
  sink.append(`<!--$!--><template${renderReactSuspenseErrorAttributes(options)}></template>`);
219
225
  const result = fallback(sink);
@@ -240,6 +246,7 @@ function renderReactSuspenseRevealScript(boundaryId, segmentId, options = {}) {
240
246
  }
241
247
  return `<script${renderNonceAttribute(options.nonce)}>${reactSuspenseRevealScriptBody};$RC(${serializeScriptJson(boundaryId)},${serializeScriptJson(segmentId)})</script>`;
242
248
  }
249
+ /** Wraps server-rendered HTML in hydration start and end markers. */
243
250
  export function renderHydrationBoundary(sink, id, render) {
244
251
  const markerId = encodeURIComponent(id);
245
252
  sink.append(`<!--mreact-h:start:${markerId}-->`);
@@ -256,5 +263,6 @@ function isPromiseLike(value) {
256
263
  }
257
264
  const outOfOrderReorderScript = `(()=>{function apply(root){const fragments=Array.from(root.querySelectorAll("template[data-mreact-oob-fragment]"));for(const fragment of fragments){const id=fragment.getAttribute("data-mreact-oob-fragment");if(id===null)continue;const markers=Array.from(root.querySelectorAll("[data-mreact-oob-complete]"));const marker=markers.find((candidate)=>candidate.getAttribute("data-mreact-oob-complete")===id);if(marker===undefined)continue;const placeholders=Array.from(root.querySelectorAll("[data-mreact-oob-placeholder]"));const placeholder=placeholders.find((candidate)=>candidate.getAttribute("data-mreact-oob-placeholder")===id);if(placeholder===undefined)continue;placeholder.replaceWith(fragment.content.cloneNode(true));fragment.remove();marker.remove();}}apply(document);new MutationObserver(()=>apply(document)).observe(document.documentElement,{childList:true,subtree:true});})();`;
258
265
  const reactSuspenseRevealScriptBody = `(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data==="$"||n.data==="$?"||n.data==="$!")d++;else if(n.data==="/$"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data="$";})`;
266
+ /** External script body that reveals a React Suspense segment when loaded. */
259
267
  export const reactSuspenseRevealExternalScript = `(()=>{${reactSuspenseRevealScriptBody};var s=document.currentScript;if(!s)return;var b=s.getAttribute("data-boundary-id");var seg=s.getAttribute("data-segment-id");if(b!==null&&seg!==null)self.$RC(b,seg);})();`;
260
268
  //# sourceMappingURL=boundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, type StringHtmlSink } from \"./sink.js\";\n\nexport interface AsyncBoundaryOptions {\n catch?: (sink: HtmlSink, error: unknown) => void | PromiseLike<void>;\n hydrationAwaitId?: string;\n}\n\nexport interface OutOfOrderBoundaryOptions extends AsyncBoundaryOptions {\n hydration?: boolean;\n placeholder?: (sink: HtmlSink) => void;\n placeholderTag?: string;\n}\n\nexport interface OutOfOrderReorderScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface HydrationScriptOptions {\n nonce?: string;\n}\n\nexport interface ReactSuspenseScriptOptions {\n nonce?: string;\n src?: string;\n}\n\nexport interface ReactSuspenseBoundaryOptions extends AsyncBoundaryOptions {\n fallback?: (sink: HtmlSink) => void | PromiseLike<void>;\n nonce?: string;\n}\n\nexport interface ReactSuspenseClientRenderOptions {\n message?: string;\n stack?: string;\n}\n\nexport type AsyncBoundaryRender<T> = (\n sink: HtmlSink,\n value: Awaited<T>,\n) => void | PromiseLike<void>;\n\nconst outOfOrderBoundaryInstances = new WeakMap<HtmlSink, Map<string, number>>();\n\nexport async function renderAsyncBoundary<T>(\n sink: HtmlSink,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: AsyncBoundaryOptions = {},\n): Promise<void> {\n try {\n const resolved = await value;\n await sink.backpressure?.();\n await render(sink, resolved);\n if (options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolved);\n }\n } catch (error) {\n if (options.catch === undefined) {\n throw error;\n }\n\n await sink.backpressure?.();\n await options.catch(sink, error);\n }\n}\n\n// Threshold for `<Await>` payload size warnings (UTF-8 byte length of\n// JSON-serialized representation). 100KB warn / 1MB error follow the\n// \"you're sending a lot of data\" hint pattern used by other frameworks.\nconst AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;\nconst AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;\nconst textEncoder = typeof TextEncoder !== \"undefined\" ? new TextEncoder() : undefined;\n\nfunction isProductionMode(): boolean {\n // `process` may not exist in cross-runtime environments (Cloudflare/Deno).\n // The server tsconfig does not include `@types/node`, so we look it up\n // through `globalThis` with a minimal local typing.\n const globalProcess = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process;\n\n try {\n return globalProcess?.env?.[\"NODE_ENV\"] === \"production\";\n } catch {\n return false;\n }\n}\n\nfunction appendAwaitHydrationData(\n sink: HtmlSink,\n awaitId: string,\n resolved: unknown,\n): void {\n const serialized = serializeAwaitHydrationValue(resolved, awaitId);\n\n if (serialized === undefined) {\n return;\n }\n\n const idLiteral = JSON.stringify(awaitId).replaceAll(\"<\", \"\\\\u003c\");\n sink.append(\n `<script data-mreact-await=\"${escapeAttribute(awaitId)}\">(self.__mreactAwaitData||(self.__mreactAwaitData={}))[${idLiteral}]={value:${serialized}}</script>`,\n );\n}\n\n// Emits a single console.warn in dev when `resolved` contains shapes the\n// wire format will silently drop or coerce (Date / Map / Set / RegExp /\n// class instance / function / Symbol / nested non-POJO).\nfunction warnIfNonSerializableAwaitValue(value: unknown, awaitId: string): void {\n if (isProductionMode()) {\n return;\n }\n\n if (!containsNonSerializableSurface(value)) {\n return;\n }\n\n console.warn(\n `[mreact] <Await value={...}> for \"${awaitId}\" includes non-serializable ` +\n `data (Date / Map / Set / RegExp / class instance / function / Symbol). ` +\n `The wire format uses JSON.stringify, so the client-side renderer may ` +\n `receive a different shape after the JSON round-trip. Convert to plain ` +\n `JSON-serializable data before it reaches <Await>. See ` +\n `https://github.com/t-k/mreact#streaming-loading-and-await.`,\n );\n}\n\nfunction containsNonSerializableSurface(value: unknown): boolean {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return false;\n }\n\n if (value instanceof Date || value instanceof Map || value instanceof Set || value instanceof RegExp) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.some((entry) => containsNonSerializableSurface(entry));\n }\n\n const proto = Object.getPrototypeOf(value);\n\n if (proto !== Object.prototype && proto !== null) {\n return true;\n }\n\n for (const entry of Object.values(value as Record<string, unknown>)) {\n if (containsNonSerializableSurface(entry)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction reportAwaitPayloadSize(json: string, awaitId: string): void {\n if (json.length * 3 < AWAIT_PAYLOAD_WARN_BYTES) {\n return;\n }\n\n const byteLength = textEncoder?.encode(json).length ?? json.length;\n\n if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {\n console.error(\n `[mreact] <Await> payload for \"${awaitId}\" is ${(byteLength / 1024 / 1024).toFixed(2)}MB, ` +\n `exceeding the 1MB error threshold. Large payloads inflate HTML response size and ` +\n `client memory pressure. Stream the data via loader or split into smaller boundaries.`,\n );\n return;\n }\n\n if (byteLength > AWAIT_PAYLOAD_WARN_BYTES) {\n console.warn(\n `[mreact] large await payload for \"${awaitId}\": ${(byteLength / 1024).toFixed(1)}KB ` +\n `(over the 100KB warning threshold). Consider streaming the data via loader or ` +\n `splitting into smaller boundaries.`,\n );\n }\n}\n\nfunction serializeAwaitHydrationValue(value: unknown, awaitId: string): string | undefined {\n try {\n const json = JSON.stringify(value);\n if (json === undefined) {\n return undefined;\n }\n\n warnIfNonSerializableAwaitValue(value, awaitId);\n reportAwaitPayloadSize(json, awaitId);\n\n // Defuse `</script>` and runaway control characters so the data can be\n // safely embedded inside a `<script>` element.\n return json\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n } catch {\n return undefined;\n }\n}\n\nfunction inheritBackpressure(childSink: StringHtmlSink, parentSink: HtmlSink): StringHtmlSink {\n if (parentSink.backpressure === undefined) {\n return childSink;\n }\n\n return {\n ...childSink,\n backpressure: parentSink.backpressure,\n };\n}\n\nexport function renderOutOfOrderBoundary<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions = {},\n): void {\n const boundaryId = nextOutOfOrderBoundaryInstanceId(sink, id);\n const placeholderSink = createStringSink();\n const placeholderResult = options.placeholder?.(placeholderSink);\n if (!isProductionMode() && isPromiseLikeUnknown(placeholderResult)) {\n throw new Error(\"renderOutOfOrderBoundary placeholder must be synchronous.\");\n }\n const placeholderTag = normalizeOutOfOrderPlaceholderTag(options.placeholderTag);\n const hydrationStart =\n options.hydration === true ? `<!--mreact-h:start:${encodeURIComponent(boundaryId)}-->` : \"\";\n const hydrationEnd =\n options.hydration === true ? `<!--mreact-h:end:${encodeURIComponent(boundaryId)}-->` : \"\";\n sink.append(\n `${hydrationStart}<${placeholderTag} data-mreact-oob-placeholder=\"${escapeAttribute(boundaryId)}\">${placeholderSink.toString()}</${placeholderTag}>${hydrationEnd}`,\n );\n\n const task = renderOutOfOrderFragment(sink, boundaryId, value, render, options);\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction normalizeOutOfOrderPlaceholderTag(tag: unknown): string {\n if (typeof tag !== \"string\") {\n return \"span\";\n }\n\n const normalized = tag.trim().toLowerCase();\n return /^[a-z][a-z0-9-]*$/.test(normalized) ? normalized : \"span\";\n}\n\nasync function renderOutOfOrderFragment<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions,\n): Promise<void> {\n const fragmentSink = inheritBackpressure(createStringSink(), sink);\n let resolvedValue: unknown;\n let hasResolvedValue = false;\n\n await renderAsyncBoundary(\n fragmentSink,\n value,\n async (childSink, resolved) => {\n resolvedValue = resolved;\n hasResolvedValue = true;\n await render(childSink, resolved);\n },\n options.catch === undefined ? {} : { catch: options.catch },\n );\n await fragmentSink.drain();\n\n sink.append(renderOutOfOrderFragmentHtml(id, fragmentSink.toString()));\n\n if (hasResolvedValue && options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolvedValue);\n }\n}\n\nexport function renderOutOfOrderReorderScript(\n sink: HtmlSink,\n options: OutOfOrderReorderScriptOptions = {},\n): void {\n const nonceAttribute =\n options.nonce === undefined ? \"\" : ` nonce=\"${escapeAttribute(options.nonce)}\"`;\n\n if (options.src !== undefined) {\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute} src=\"${escapeAttribute(options.src)}\"></script>`,\n );\n return;\n }\n\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute}>${outOfOrderReorderScript}</script>`,\n );\n}\n\nfunction renderOutOfOrderFragmentHtml(id: string, html: string): string {\n const escapedId = escapeAttribute(id);\n return `<template data-mreact-oob-fragment=\"${escapedId}\">${html}</template><mreact-oob-complete hidden data-mreact-oob-complete=\"${escapedId}\"></mreact-oob-complete>`;\n}\n\nexport function renderReactSuspenseBoundary(\n sink: HtmlSink,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n sink.append(\"<!--$-->\");\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nexport function renderReactSuspenseOutOfOrderBoundary<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions = {},\n): void {\n const actualBoundaryId = nextOutOfOrderBoundaryInstanceId(sink, boundaryId);\n const suffix = actualBoundaryId.slice(boundaryId.length);\n const actualSegmentId = `${segmentId}${suffix}`;\n const fallbackSink = createStringSink();\n void options.fallback?.(fallbackSink);\n sink.append(\n `<!--$?--><template id=\"${escapeAttribute(actualBoundaryId)}\"></template>${fallbackSink.toString()}<!--/$-->`,\n );\n\n const task = renderReactSuspenseSegment(\n sink,\n actualBoundaryId,\n actualSegmentId,\n value,\n render,\n options,\n );\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction nextOutOfOrderBoundaryInstanceId(sink: HtmlSink, id: string): string {\n let instances = outOfOrderBoundaryInstances.get(sink);\n\n if (instances === undefined) {\n instances = new Map();\n outOfOrderBoundaryInstances.set(sink, instances);\n }\n\n const count = instances.get(id) ?? 0;\n instances.set(id, count + 1);\n\n return count === 0 ? id : `${id}-${count.toString(36)}`;\n}\n\nexport function renderReactSuspenseClientRenderBoundary(\n sink: HtmlSink,\n fallback: (sink: HtmlSink) => void | PromiseLike<void>,\n options: ReactSuspenseClientRenderOptions = {},\n): void | PromiseLike<void> {\n sink.append(`<!--$!--><template${renderReactSuspenseErrorAttributes(options)}></template>`);\n const result = fallback(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nasync function renderReactSuspenseSegment<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions,\n): Promise<void> {\n const segmentSink = inheritBackpressure(createStringSink(), sink);\n\n await renderAsyncBoundary(\n segmentSink,\n value,\n render,\n options.catch === undefined ? {} : { catch: options.catch },\n );\n\n sink.append(\n `<div hidden id=\"${escapeAttribute(segmentId)}\">${segmentSink.toString()}</div>${renderReactSuspenseRevealScript(boundaryId, segmentId, options)}`,\n );\n}\n\nfunction renderReactSuspenseErrorAttributes(options: ReactSuspenseClientRenderOptions): string {\n const message =\n options.message === undefined ? \"\" : ` data-msg=\"${escapeAttribute(options.message)}\"`;\n const stack = options.stack === undefined ? \"\" : ` data-stck=\"${escapeAttribute(options.stack)}\"`;\n\n return `${message}${stack}`;\n}\n\nfunction renderReactSuspenseRevealScript(\n boundaryId: string,\n segmentId: string,\n options: ReactSuspenseScriptOptions = {},\n): string {\n if (options.src !== undefined) {\n return `<script data-mreact-react-suspense-reveal${renderNonceAttribute(options.nonce)} src=\"${escapeAttribute(options.src)}\" data-boundary-id=\"${escapeAttribute(boundaryId)}\" data-segment-id=\"${escapeAttribute(segmentId)}\"></script>`;\n }\n\n return `<script${renderNonceAttribute(options.nonce)}>${reactSuspenseRevealScriptBody};$RC(${serializeScriptJson(boundaryId)},${serializeScriptJson(segmentId)})</script>`;\n}\n\nexport function renderHydrationBoundary(\n sink: HtmlSink,\n id: string,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n const markerId = encodeURIComponent(id);\n sink.append(`<!--mreact-h:start:${markerId}-->`);\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n });\n }\n\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n\nconst outOfOrderReorderScript = `(()=>{function apply(root){const fragments=Array.from(root.querySelectorAll(\"template[data-mreact-oob-fragment]\"));for(const fragment of fragments){const id=fragment.getAttribute(\"data-mreact-oob-fragment\");if(id===null)continue;const markers=Array.from(root.querySelectorAll(\"[data-mreact-oob-complete]\"));const marker=markers.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-complete\")===id);if(marker===undefined)continue;const placeholders=Array.from(root.querySelectorAll(\"[data-mreact-oob-placeholder]\"));const placeholder=placeholders.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-placeholder\")===id);if(placeholder===undefined)continue;placeholder.replaceWith(fragment.content.cloneNode(true));fragment.remove();marker.remove();}}apply(document);new MutationObserver(()=>apply(document)).observe(document.documentElement,{childList:true,subtree:true});})();`;\n\nconst reactSuspenseRevealScriptBody = `(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data===\"$\"||n.data===\"$?\"||n.data===\"$!\")d++;else if(n.data===\"/$\"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data=\"$\";})`;\n\nexport const reactSuspenseRevealExternalScript = `(()=>{${reactSuspenseRevealScriptBody};var s=document.currentScript;if(!s)return;var b=s.getAttribute(\"data-boundary-id\");var seg=s.getAttribute(\"data-segment-id\");if(b!==null&&seg!==null)self.$RC(b,seg);})();`;\n"]}
1
+ {"version":3,"file":"boundary.js","sourceRoot":"","sources":["../src/boundary.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAuB,MAAM,WAAW,CAAC;AAkDlE,MAAM,2BAA2B,GAAG,IAAI,OAAO,EAAiC,CAAC;AAEjF,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAc,EACd,KAAQ,EACR,MAA8B,EAC9B,UAAgC,EAAE;IAElC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC;QAC7B,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAC5B,MAAM,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC7B,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC3C,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,KAAK,CAAC;QACd,CAAC;QAED,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;QAC5B,MAAM,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,qEAAqE;AACrE,wEAAwE;AACxE,MAAM,wBAAwB,GAAG,GAAG,GAAG,IAAI,CAAC;AAC5C,MAAM,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAAC;AAC9C,MAAM,WAAW,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAEvF,SAAS,gBAAgB;IACvB,2EAA2E;IAC3E,uEAAuE;IACvE,oDAAoD;IACpD,MAAM,aAAa,GAAI,UAAyE;SAC7F,OAAO,CAAC;IAEX,IAAI,CAAC;QACH,OAAO,aAAa,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,YAAY,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAC/B,IAAc,EACd,OAAe,EACf,QAAiB;IAEjB,MAAM,UAAU,GAAG,4BAA4B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEnE,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CACT,8BAA8B,eAAe,CAAC,OAAO,CAAC,2DAA2D,SAAS,YAAY,UAAU,YAAY,CAC7J,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,wEAAwE;AACxE,yDAAyD;AACzD,SAAS,+BAA+B,CAAC,KAAc,EAAE,OAAe;IACtE,IAAI,gBAAgB,EAAE,EAAE,CAAC;QACvB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,8BAA8B,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,OAAO,CAAC,IAAI,CACV,qCAAqC,OAAO,8BAA8B;QACxE,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,wDAAwD;QACxD,4DAA4D,CAC/D,CAAC;AACJ,CAAC;AAED,SAAS,8BAA8B,CAAC,KAAc;IACpD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,YAAY,GAAG,IAAI,KAAK,YAAY,GAAG,IAAI,KAAK,YAAY,MAAM,EAAE,CAAC;QACrG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAE3C,IAAI,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAgC,CAAC,EAAE,CAAC;QACpE,IAAI,8BAA8B,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAY,EAAE,OAAe;IAC3D,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,wBAAwB,EAAE,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAEnE,IAAI,UAAU,GAAG,yBAAyB,EAAE,CAAC;QAC3C,OAAO,CAAC,KAAK,CACX,iCAAiC,OAAO,QAAQ,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YACzF,mFAAmF;YACnF,sFAAsF,CACzF,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,UAAU,GAAG,wBAAwB,EAAE,CAAC;QAC1C,OAAO,CAAC,IAAI,CACV,qCAAqC,OAAO,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;YACnF,gFAAgF;YAChF,oCAAoC,CACvC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,KAAc,EAAE,OAAe;IACnE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,+BAA+B,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,sBAAsB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAEtC,uEAAuE;QACvE,+CAA+C;QAC/C,OAAO,IAAI;aACR,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;aAC1B,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC;aAC/B,UAAU,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAyB,EAAE,UAAoB;IAC1E,IAAI,UAAU,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,SAAS;QACZ,YAAY,EAAE,UAAU,CAAC,YAAY;KACtC,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,wBAAwB,CACtC,IAAc,EACd,EAAU,EACV,KAAQ,EACR,MAA8B,EAC9B,UAAqC,EAAE;IAEvC,MAAM,UAAU,GAAG,gCAAgC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;IAC3C,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,eAAe,CAAC,CAAC;IACjE,IAAI,CAAC,gBAAgB,EAAE,IAAI,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,cAAc,GAAG,iCAAiC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IACjF,MAAM,cAAc,GAClB,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,sBAAsB,kBAAkB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9F,MAAM,YAAY,GAChB,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,oBAAoB,kBAAkB,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,IAAI,CAAC,MAAM,CACT,GAAG,cAAc,IAAI,cAAc,iCAAiC,eAAe,CAAC,UAAU,CAAC,KAAK,eAAe,CAAC,QAAQ,EAAE,KAAK,cAAc,IAAI,YAAY,EAAE,CACpK,CAAC;IAEF,MAAM,IAAI,GAAG,wBAAwB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAEhF,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,iCAAiC,CAAC,GAAY;IACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;AACpE,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,IAAc,EACd,EAAU,EACV,KAAQ,EACR,MAA8B,EAC9B,OAAkC;IAElC,MAAM,YAAY,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC,CAAC;IACnE,IAAI,aAAsB,CAAC;IAC3B,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAE7B,MAAM,mBAAmB,CACvB,YAAY,EACZ,KAAK,EACL,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;QAC5B,aAAa,GAAG,QAAQ,CAAC;QACzB,gBAAgB,GAAG,IAAI,CAAC;QACxB,MAAM,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC,EACD,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAC5D,CAAC;IACF,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;IAE3B,IAAI,CAAC,MAAM,CAAC,4BAA4B,CAAC,EAAE,EAAE,YAAY,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAEvE,IAAI,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC/D,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,6BAA6B,CAC3C,IAAc,EACd,UAA0C,EAAE;IAE5C,MAAM,cAAc,GAClB,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;IAElF,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CACT,kCAAkC,cAAc,SAAS,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CACnG,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,CACT,kCAAkC,cAAc,IAAI,uBAAuB,WAAW,CACvF,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CAAC,EAAU,EAAE,IAAY;IAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IACtC,OAAO,uCAAuC,SAAS,KAAK,IAAI,oEAAoE,SAAS,0BAA0B,CAAC;AAC1K,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,2BAA2B,CACzC,IAAc,EACd,MAAoD;IAEpD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE5B,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC3B,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qCAAqC,CACnD,IAAc,EACd,UAAkB,EAClB,SAAiB,EACjB,KAAQ,EACR,MAA8B,EAC9B,UAAwC,EAAE;IAE1C,MAAM,gBAAgB,GAAG,gCAAgC,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,eAAe,GAAG,GAAG,SAAS,GAAG,MAAM,EAAE,CAAC;IAChD,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;IACxC,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,CACT,0BAA0B,eAAe,CAAC,gBAAgB,CAAC,gBAAgB,YAAY,CAAC,QAAQ,EAAE,WAAW,CAC9G,CAAC;IAEF,MAAM,IAAI,GAAG,0BAA0B,CACrC,IAAI,EACJ,gBAAgB,EAChB,eAAe,EACf,KAAK,EACL,MAAM,EACN,OAAO,CACR,CAAC;IAEF,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC7B,KAAK,IAAI,CAAC;QACV,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,gCAAgC,CAAC,IAAc,EAAE,EAAU;IAClE,IAAI,SAAS,GAAG,2BAA2B,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEtD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,2BAA2B,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACrC,SAAS,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IAE7B,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,uCAAuC,CACrD,IAAc,EACd,QAAsD,EACtD,UAA4C,EAAE;IAE9C,IAAI,CAAC,MAAM,CAAC,qBAAqB,kCAAkC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAC5F,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE9B,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,IAAc,EACd,UAAkB,EAClB,SAAiB,EACjB,KAAQ,EACR,MAA8B,EAC9B,OAAqC;IAErC,MAAM,WAAW,GAAG,mBAAmB,CAAC,gBAAgB,EAAE,EAAE,IAAI,CAAC,CAAC;IAElE,MAAM,mBAAmB,CACvB,WAAW,EACX,KAAK,EACL,MAAM,EACN,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAC5D,CAAC;IAEF,IAAI,CAAC,MAAM,CACT,mBAAmB,eAAe,CAAC,SAAS,CAAC,KAAK,WAAW,CAAC,QAAQ,EAAE,SAAS,+BAA+B,CAAC,UAAU,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,CACnJ,CAAC;AACJ,CAAC;AAED,SAAS,kCAAkC,CAAC,OAAyC;IACnF,MAAM,OAAO,GACX,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,cAAc,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC;IACzF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;IAElG,OAAO,GAAG,OAAO,GAAG,KAAK,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,+BAA+B,CACtC,UAAkB,EAClB,SAAiB,EACjB,UAAsC,EAAE;IAExC,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,4CAA4C,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,eAAe,CAAC,UAAU,CAAC,sBAAsB,eAAe,CAAC,SAAS,CAAC,aAAa,CAAC;IAC7O,CAAC;IAED,OAAO,UAAU,oBAAoB,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,6BAA6B,QAAQ,mBAAmB,CAAC,UAAU,CAAC,IAAI,mBAAmB,CAAC,SAAS,CAAC,YAAY,CAAC;AAC7K,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,uBAAuB,CACrC,IAAc,EACd,EAAU,EACV,MAAoD;IAEpD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,MAAM,CAAC,sBAAsB,QAAQ,KAAK,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE5B,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,MAAM,CAAC,oBAAoB,QAAQ,KAAK,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,oBAAoB,QAAQ,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,oBAAoB,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,uBAAuB,GAAG,w3BAAw3B,CAAC;AAEz5B,MAAM,6BAA6B,GAAG,2cAA2c,CAAC;AAElf,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iCAAiC,GAAG,SAAS,6BAA6B,6KAA6K,CAAC","sourcesContent":["import type { HtmlSink } from \"@reckona/mreact-shared/compiler-contract\";\nimport {\n escapeAttribute,\n isPromiseLikeUnknown,\n renderNonceAttribute,\n serializeScriptJson,\n} from \"./html-internals.js\";\nimport { createStringSink, type StringHtmlSink } from \"./sink.js\";\n\n/** Options shared by async boundaries that render resolved values or caught errors. */\nexport interface AsyncBoundaryOptions {\n catch?: (sink: HtmlSink, error: unknown) => void | PromiseLike<void>;\n hydrationAwaitId?: string;\n}\n\n/** Options for rendering a boundary whose resolved content can arrive out of order. */\nexport interface OutOfOrderBoundaryOptions extends AsyncBoundaryOptions {\n hydration?: boolean;\n placeholder?: (sink: HtmlSink) => void;\n placeholderTag?: string;\n}\n\n/** Options for emitting the out-of-order fragment reorder script. */\nexport interface OutOfOrderReorderScriptOptions {\n nonce?: string;\n src?: string;\n}\n\n/** Options for script tags that hydrate server-rendered data. */\nexport interface HydrationScriptOptions {\n nonce?: string;\n}\n\n/** Options for scripts that reveal React Suspense segments. */\nexport interface ReactSuspenseScriptOptions {\n nonce?: string;\n src?: string;\n}\n\n/** Options for React Suspense boundaries rendered with streamed segments. */\nexport interface ReactSuspenseBoundaryOptions extends AsyncBoundaryOptions {\n fallback?: (sink: HtmlSink) => void | PromiseLike<void>;\n nonce?: string;\n}\n\n/** Error metadata used when forcing a React Suspense boundary to client render. */\nexport interface ReactSuspenseClientRenderOptions {\n message?: string;\n stack?: string;\n}\n\n/** Renderer invoked with an async boundary's resolved value. */\nexport type AsyncBoundaryRender<T> = (\n sink: HtmlSink,\n value: Awaited<T>,\n) => void | PromiseLike<void>;\n\nconst outOfOrderBoundaryInstances = new WeakMap<HtmlSink, Map<string, number>>();\n\n/** Renders a value once it resolves, or renders a configured catch branch on error. */\nexport async function renderAsyncBoundary<T>(\n sink: HtmlSink,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: AsyncBoundaryOptions = {},\n): Promise<void> {\n try {\n const resolved = await value;\n await sink.backpressure?.();\n await render(sink, resolved);\n if (options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolved);\n }\n } catch (error) {\n if (options.catch === undefined) {\n throw error;\n }\n\n await sink.backpressure?.();\n await options.catch(sink, error);\n }\n}\n\n// Threshold for `<Await>` payload size warnings (UTF-8 byte length of\n// JSON-serialized representation). 100KB warn / 1MB error follow the\n// \"you're sending a lot of data\" hint pattern used by other frameworks.\nconst AWAIT_PAYLOAD_WARN_BYTES = 100 * 1024;\nconst AWAIT_PAYLOAD_ERROR_BYTES = 1024 * 1024;\nconst textEncoder = typeof TextEncoder !== \"undefined\" ? new TextEncoder() : undefined;\n\nfunction isProductionMode(): boolean {\n // `process` may not exist in cross-runtime environments (Cloudflare/Deno).\n // The server tsconfig does not include `@types/node`, so we look it up\n // through `globalThis` with a minimal local typing.\n const globalProcess = (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process;\n\n try {\n return globalProcess?.env?.[\"NODE_ENV\"] === \"production\";\n } catch {\n return false;\n }\n}\n\nfunction appendAwaitHydrationData(\n sink: HtmlSink,\n awaitId: string,\n resolved: unknown,\n): void {\n const serialized = serializeAwaitHydrationValue(resolved, awaitId);\n\n if (serialized === undefined) {\n return;\n }\n\n const idLiteral = JSON.stringify(awaitId).replaceAll(\"<\", \"\\\\u003c\");\n sink.append(\n `<script data-mreact-await=\"${escapeAttribute(awaitId)}\">(self.__mreactAwaitData||(self.__mreactAwaitData={}))[${idLiteral}]={value:${serialized}}</script>`,\n );\n}\n\n// Emits a single console.warn in dev when `resolved` contains shapes the\n// wire format will silently drop or coerce (Date / Map / Set / RegExp /\n// class instance / function / Symbol / nested non-POJO).\nfunction warnIfNonSerializableAwaitValue(value: unknown, awaitId: string): void {\n if (isProductionMode()) {\n return;\n }\n\n if (!containsNonSerializableSurface(value)) {\n return;\n }\n\n console.warn(\n `[mreact] <Await value={...}> for \"${awaitId}\" includes non-serializable ` +\n `data (Date / Map / Set / RegExp / class instance / function / Symbol). ` +\n `The wire format uses JSON.stringify, so the client-side renderer may ` +\n `receive a different shape after the JSON round-trip. Convert to plain ` +\n `JSON-serializable data before it reaches <Await>. See ` +\n `https://github.com/t-k/mreact#streaming-loading-and-await.`,\n );\n}\n\nfunction containsNonSerializableSurface(value: unknown): boolean {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return false;\n }\n\n if (value instanceof Date || value instanceof Map || value instanceof Set || value instanceof RegExp) {\n return true;\n }\n\n if (Array.isArray(value)) {\n return value.some((entry) => containsNonSerializableSurface(entry));\n }\n\n const proto = Object.getPrototypeOf(value);\n\n if (proto !== Object.prototype && proto !== null) {\n return true;\n }\n\n for (const entry of Object.values(value as Record<string, unknown>)) {\n if (containsNonSerializableSurface(entry)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction reportAwaitPayloadSize(json: string, awaitId: string): void {\n if (json.length * 3 < AWAIT_PAYLOAD_WARN_BYTES) {\n return;\n }\n\n const byteLength = textEncoder?.encode(json).length ?? json.length;\n\n if (byteLength > AWAIT_PAYLOAD_ERROR_BYTES) {\n console.error(\n `[mreact] <Await> payload for \"${awaitId}\" is ${(byteLength / 1024 / 1024).toFixed(2)}MB, ` +\n `exceeding the 1MB error threshold. Large payloads inflate HTML response size and ` +\n `client memory pressure. Stream the data via loader or split into smaller boundaries.`,\n );\n return;\n }\n\n if (byteLength > AWAIT_PAYLOAD_WARN_BYTES) {\n console.warn(\n `[mreact] large await payload for \"${awaitId}\": ${(byteLength / 1024).toFixed(1)}KB ` +\n `(over the 100KB warning threshold). Consider streaming the data via loader or ` +\n `splitting into smaller boundaries.`,\n );\n }\n}\n\nfunction serializeAwaitHydrationValue(value: unknown, awaitId: string): string | undefined {\n try {\n const json = JSON.stringify(value);\n if (json === undefined) {\n return undefined;\n }\n\n warnIfNonSerializableAwaitValue(value, awaitId);\n reportAwaitPayloadSize(json, awaitId);\n\n // Defuse `</script>` and runaway control characters so the data can be\n // safely embedded inside a `<script>` element.\n return json\n .replaceAll(\"<\", \"\\\\u003c\")\n .replaceAll(\"\\u2028\", \"\\\\u2028\")\n .replaceAll(\"\\u2029\", \"\\\\u2029\");\n } catch {\n return undefined;\n }\n}\n\nfunction inheritBackpressure(childSink: StringHtmlSink, parentSink: HtmlSink): StringHtmlSink {\n if (parentSink.backpressure === undefined) {\n return childSink;\n }\n\n return {\n ...childSink,\n backpressure: parentSink.backpressure,\n };\n}\n\n/** Emits a placeholder immediately and defers resolved HTML as an out-of-order fragment. */\nexport function renderOutOfOrderBoundary<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions = {},\n): void {\n const boundaryId = nextOutOfOrderBoundaryInstanceId(sink, id);\n const placeholderSink = createStringSink();\n const placeholderResult = options.placeholder?.(placeholderSink);\n if (!isProductionMode() && isPromiseLikeUnknown(placeholderResult)) {\n throw new Error(\"renderOutOfOrderBoundary placeholder must be synchronous.\");\n }\n const placeholderTag = normalizeOutOfOrderPlaceholderTag(options.placeholderTag);\n const hydrationStart =\n options.hydration === true ? `<!--mreact-h:start:${encodeURIComponent(boundaryId)}-->` : \"\";\n const hydrationEnd =\n options.hydration === true ? `<!--mreact-h:end:${encodeURIComponent(boundaryId)}-->` : \"\";\n sink.append(\n `${hydrationStart}<${placeholderTag} data-mreact-oob-placeholder=\"${escapeAttribute(boundaryId)}\">${placeholderSink.toString()}</${placeholderTag}>${hydrationEnd}`,\n );\n\n const task = renderOutOfOrderFragment(sink, boundaryId, value, render, options);\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction normalizeOutOfOrderPlaceholderTag(tag: unknown): string {\n if (typeof tag !== \"string\") {\n return \"span\";\n }\n\n const normalized = tag.trim().toLowerCase();\n return /^[a-z][a-z0-9-]*$/.test(normalized) ? normalized : \"span\";\n}\n\nasync function renderOutOfOrderFragment<T>(\n sink: HtmlSink,\n id: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: OutOfOrderBoundaryOptions,\n): Promise<void> {\n const fragmentSink = inheritBackpressure(createStringSink(), sink);\n let resolvedValue: unknown;\n let hasResolvedValue = false;\n\n await renderAsyncBoundary(\n fragmentSink,\n value,\n async (childSink, resolved) => {\n resolvedValue = resolved;\n hasResolvedValue = true;\n await render(childSink, resolved);\n },\n options.catch === undefined ? {} : { catch: options.catch },\n );\n await fragmentSink.drain();\n\n sink.append(renderOutOfOrderFragmentHtml(id, fragmentSink.toString()));\n\n if (hasResolvedValue && options.hydrationAwaitId !== undefined) {\n appendAwaitHydrationData(sink, options.hydrationAwaitId, resolvedValue);\n }\n}\n\n/** Emits the client script that swaps out-of-order fragments into their placeholders. */\nexport function renderOutOfOrderReorderScript(\n sink: HtmlSink,\n options: OutOfOrderReorderScriptOptions = {},\n): void {\n const nonceAttribute =\n options.nonce === undefined ? \"\" : ` nonce=\"${escapeAttribute(options.nonce)}\"`;\n\n if (options.src !== undefined) {\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute} src=\"${escapeAttribute(options.src)}\"></script>`,\n );\n return;\n }\n\n sink.append(\n `<script data-mreact-oob-reorder${nonceAttribute}>${outOfOrderReorderScript}</script>`,\n );\n}\n\nfunction renderOutOfOrderFragmentHtml(id: string, html: string): string {\n const escapedId = escapeAttribute(id);\n return `<template data-mreact-oob-fragment=\"${escapedId}\">${html}</template><mreact-oob-complete hidden data-mreact-oob-complete=\"${escapedId}\"></mreact-oob-complete>`;\n}\n\n/** Wraps streamed content in React Suspense completion markers. */\nexport function renderReactSuspenseBoundary(\n sink: HtmlSink,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n sink.append(\"<!--$-->\");\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\n/** Emits a React Suspense fallback and streams the resolved segment out of order. */\nexport function renderReactSuspenseOutOfOrderBoundary<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions = {},\n): void {\n const actualBoundaryId = nextOutOfOrderBoundaryInstanceId(sink, boundaryId);\n const suffix = actualBoundaryId.slice(boundaryId.length);\n const actualSegmentId = `${segmentId}${suffix}`;\n const fallbackSink = createStringSink();\n void options.fallback?.(fallbackSink);\n sink.append(\n `<!--$?--><template id=\"${escapeAttribute(actualBoundaryId)}\"></template>${fallbackSink.toString()}<!--/$-->`,\n );\n\n const task = renderReactSuspenseSegment(\n sink,\n actualBoundaryId,\n actualSegmentId,\n value,\n render,\n options,\n );\n\n if (sink.defer === undefined) {\n void task;\n return;\n }\n\n sink.defer(task);\n}\n\nfunction nextOutOfOrderBoundaryInstanceId(sink: HtmlSink, id: string): string {\n let instances = outOfOrderBoundaryInstances.get(sink);\n\n if (instances === undefined) {\n instances = new Map();\n outOfOrderBoundaryInstances.set(sink, instances);\n }\n\n const count = instances.get(id) ?? 0;\n instances.set(id, count + 1);\n\n return count === 0 ? id : `${id}-${count.toString(36)}`;\n}\n\n/** Emits a React Suspense boundary that instructs the client to render the fallback. */\nexport function renderReactSuspenseClientRenderBoundary(\n sink: HtmlSink,\n fallback: (sink: HtmlSink) => void | PromiseLike<void>,\n options: ReactSuspenseClientRenderOptions = {},\n): void | PromiseLike<void> {\n sink.append(`<!--$!--><template${renderReactSuspenseErrorAttributes(options)}></template>`);\n const result = fallback(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(\"<!--/$-->\");\n });\n }\n\n sink.append(\"<!--/$-->\");\n}\n\nasync function renderReactSuspenseSegment<T>(\n sink: HtmlSink,\n boundaryId: string,\n segmentId: string,\n value: T,\n render: AsyncBoundaryRender<T>,\n options: ReactSuspenseBoundaryOptions,\n): Promise<void> {\n const segmentSink = inheritBackpressure(createStringSink(), sink);\n\n await renderAsyncBoundary(\n segmentSink,\n value,\n render,\n options.catch === undefined ? {} : { catch: options.catch },\n );\n\n sink.append(\n `<div hidden id=\"${escapeAttribute(segmentId)}\">${segmentSink.toString()}</div>${renderReactSuspenseRevealScript(boundaryId, segmentId, options)}`,\n );\n}\n\nfunction renderReactSuspenseErrorAttributes(options: ReactSuspenseClientRenderOptions): string {\n const message =\n options.message === undefined ? \"\" : ` data-msg=\"${escapeAttribute(options.message)}\"`;\n const stack = options.stack === undefined ? \"\" : ` data-stck=\"${escapeAttribute(options.stack)}\"`;\n\n return `${message}${stack}`;\n}\n\nfunction renderReactSuspenseRevealScript(\n boundaryId: string,\n segmentId: string,\n options: ReactSuspenseScriptOptions = {},\n): string {\n if (options.src !== undefined) {\n return `<script data-mreact-react-suspense-reveal${renderNonceAttribute(options.nonce)} src=\"${escapeAttribute(options.src)}\" data-boundary-id=\"${escapeAttribute(boundaryId)}\" data-segment-id=\"${escapeAttribute(segmentId)}\"></script>`;\n }\n\n return `<script${renderNonceAttribute(options.nonce)}>${reactSuspenseRevealScriptBody};$RC(${serializeScriptJson(boundaryId)},${serializeScriptJson(segmentId)})</script>`;\n}\n\n/** Wraps server-rendered HTML in hydration start and end markers. */\nexport function renderHydrationBoundary(\n sink: HtmlSink,\n id: string,\n render: (sink: HtmlSink) => void | PromiseLike<void>,\n): void | PromiseLike<void> {\n const markerId = encodeURIComponent(id);\n sink.append(`<!--mreact-h:start:${markerId}-->`);\n const result = render(sink);\n\n if (isPromiseLike(result)) {\n return result.then(() => {\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n });\n }\n\n sink.append(`<!--mreact-h:end:${markerId}-->`);\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<void> {\n return isPromiseLikeUnknown(value);\n}\n\nconst outOfOrderReorderScript = `(()=>{function apply(root){const fragments=Array.from(root.querySelectorAll(\"template[data-mreact-oob-fragment]\"));for(const fragment of fragments){const id=fragment.getAttribute(\"data-mreact-oob-fragment\");if(id===null)continue;const markers=Array.from(root.querySelectorAll(\"[data-mreact-oob-complete]\"));const marker=markers.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-complete\")===id);if(marker===undefined)continue;const placeholders=Array.from(root.querySelectorAll(\"[data-mreact-oob-placeholder]\"));const placeholder=placeholders.find((candidate)=>candidate.getAttribute(\"data-mreact-oob-placeholder\")===id);if(placeholder===undefined)continue;placeholder.replaceWith(fragment.content.cloneNode(true));fragment.remove();marker.remove();}}apply(document);new MutationObserver(()=>apply(document)).observe(document.documentElement,{childList:true,subtree:true});})();`;\n\nconst reactSuspenseRevealScriptBody = `(self.$RC=self.$RC||function(bid,sid){var b=document.getElementById(bid);var s=document.getElementById(sid);if(!b||!s)return;var p=b.parentNode;var e=b.nextSibling;var d=0;var r=[];for(var n=e;n;n=n.nextSibling){if(n.nodeType===8){if(n.data===\"$\"||n.data===\"$?\"||n.data===\"$!\")d++;else if(n.data===\"/$\"){if(d===0){e=n;break;}d--;}}r.push(n);}for(var i=0;r[i];i++)p.removeChild(r[i]);while(s.firstChild)p.insertBefore(s.firstChild,e);s.remove();b.data=\"$\";})`;\n\n/** External script body that reveals a React Suspense segment when loaded. */\nexport const reactSuspenseRevealExternalScript = `(()=>{${reactSuspenseRevealScriptBody};var s=document.currentScript;if(!s)return;var b=s.getAttribute(\"data-boundary-id\");var seg=s.getAttribute(\"data-segment-id\");if(b!==null&&seg!==null)self.$RC(b,seg);})();`;\n"]}
@@ -4,12 +4,14 @@ interface NodeBuffer extends Uint8Array {
4
4
  copy(target: NodeBuffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
5
5
  subarray(start?: number, end?: number): NodeBuffer;
6
6
  }
7
+ /** Accumulates server-rendered chunks into a Node Buffer. */
7
8
  export interface BufferSink {
8
9
  append(chunk: string | NodeBuffer): void;
9
10
  toBuffer(): NodeBuffer;
10
11
  toString(): string;
11
12
  size(): number;
12
13
  }
14
+ /** Options controlling allocation and growth for a Node buffer sink. */
13
15
  export interface BufferSinkOptions {
14
16
  /**
15
17
  * Initial backing buffer size (UTF-8 bytes). The buffer grows
@@ -22,15 +24,6 @@ export interface BufferSinkOptions {
22
24
  */
23
25
  growthFactor?: number;
24
26
  }
25
- /**
26
- * Creates a Node-only buffer sink with a single pre-allocated growing
27
- * backing `Buffer`. UTF-8 encoding happens in-place at the current write
28
- * offset, avoiding per-chunk Buffer allocation and a final concat.
29
- *
30
- * Compared to `Buffer.concat`-style implementations, this trades a small
31
- * amount of headroom memory for ~5-10x throughput on small chunks
32
- * (see docs/benchmarks/2026-05-12-server-sink-strategy.md).
33
- */
34
27
  /**
35
28
  * A streaming-flavored buffer sink used by
36
29
  * `renderToReadableStream`. Coalesces successive `append(chunk)` calls
@@ -58,6 +51,7 @@ export interface StreamingBufferSink {
58
51
  flush(): void;
59
52
  size(): number;
60
53
  }
54
+ /** Options controlling automatic flush behavior for a streaming buffer sink. */
61
55
  export interface StreamingBufferSinkOptions {
62
56
  /** UTF-8 byte threshold that triggers an automatic flush from inside
63
57
  * `append`. Default 8 KiB (one common TCP segment payload). */
@@ -68,7 +62,12 @@ export interface StreamingBufferSinkOptions {
68
62
  * automatic), and only with a non-empty byte buffer. */
69
63
  onFlush(buffer: Uint8Array): void;
70
64
  }
65
+ /** Creates a streaming sink that coalesces appended text into byte buffers. */
71
66
  export declare function createStreamingBufferSink(options: StreamingBufferSinkOptions): StreamingBufferSink;
67
+ /**
68
+ * Creates a Node-only buffer sink with a single pre-allocated growing
69
+ * backing `Buffer`.
70
+ */
72
71
  export declare function createBufferSink(options?: BufferSinkOptions): BufferSink;
73
72
  export {};
74
73
  //# sourceMappingURL=buffer-sink.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"buffer-sink.d.ts","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"AAcA,UAAU,UAAW,SAAQ,UAAU;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CACpD;AAaD,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,IAAI,UAAU,CAAC;IACvB,QAAQ,IAAI,MAAM,CAAC;IACnB,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,0BAA0B;IACzC;oEACgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6DACyD;IACzD,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA6BrB;AAyDD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA8C5E"}
1
+ {"version":3,"file":"buffer-sink.d.ts","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"AAcA,UAAU,UAAW,SAAQ,UAAU;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAClE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChE,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;CACpD;AAaD,6DAA6D;AAC7D,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC;IACzC,QAAQ,IAAI,UAAU,CAAC;IACvB,QAAQ,IAAI,MAAM,CAAC;IACnB,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,IAAI,IAAI,CAAC;IACd,IAAI,IAAI,MAAM,CAAC;CAChB;AAED,gFAAgF;AAChF,MAAM,WAAW,0BAA0B;IACzC;oEACgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;6DACyD;IACzD,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CACnC;AAED,+EAA+E;AAC/E,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CA6BrB;AAyDD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU,CA8C5E"}
@@ -11,6 +11,7 @@
11
11
  //
12
12
  // tsconfig は `lib: ES2022 + DOM`, `types: []` なので `@types/node` に
13
13
  // 依存しないよう、`Buffer` の最小型を本 file 内で declare する。
14
+ /** Creates a streaming sink that coalesces appended text into byte buffers. */
14
15
  export function createStreamingBufferSink(options) {
15
16
  if (!hasNodeBuffer()) {
16
17
  return createStreamingEncodedSink(options);
@@ -89,6 +90,10 @@ function concatUint8Arrays(chunks, byteLength) {
89
90
  function hasNodeBuffer() {
90
91
  return typeof Buffer !== "undefined" && typeof Buffer.allocUnsafe === "function";
91
92
  }
93
+ /**
94
+ * Creates a Node-only buffer sink with a single pre-allocated growing
95
+ * backing `Buffer`.
96
+ */
92
97
  export function createBufferSink(options = {}) {
93
98
  const initialSize = options.initialSize ?? 8192;
94
99
  const growthFactor = options.growthFactor ?? 2;
@@ -1 +1 @@
1
- {"version":3,"file":"buffer-sink.js","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"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","sourcesContent":["// Node 専用 buffer sink — issue 050 の対応。\n//\n// `createStringSink` (cross-runtime, string accumulator) と並べて、\n// Node の `Buffer` を直接 accumulate する sink を提供する。HTTP response\n// body へ `response.write(buffer)` で直接渡すと string → UTF-8 encode の\n// cost を 1 回にまとめられる利点がある。\n//\n// 注: Cloudflare Workers / Deno など `Buffer` を持たない runtime では\n// import 時に runtime error になる。cross-runtime ポータビリティが必要な\n// callsite は `@reckona/mreact-server` 本体の `createStringSink` を使う。\n//\n// tsconfig は `lib: ES2022 + DOM`, `types: []` なので `@types/node` に\n// 依存しないよう、`Buffer` の最小型を本 file 内で declare する。\n\ninterface NodeBuffer extends Uint8Array {\n toString(encoding?: string, start?: number, end?: number): string;\n write(input: string, offset: number, encoding?: string): number;\n copy(target: NodeBuffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n subarray(start?: number, end?: number): NodeBuffer;\n}\n\ninterface BufferConstructor {\n from(input: string, encoding?: string): NodeBuffer;\n from(input: ArrayBufferLike | ArrayLike<number>): NodeBuffer;\n alloc(size: number): NodeBuffer;\n allocUnsafe(size: number): NodeBuffer;\n byteLength(input: string, encoding?: string): number;\n isBuffer(input: unknown): input is NodeBuffer;\n}\n\ndeclare const Buffer: BufferConstructor;\n\nexport interface BufferSink {\n append(chunk: string | NodeBuffer): void;\n toBuffer(): NodeBuffer;\n toString(): string;\n size(): number;\n}\n\nexport interface BufferSinkOptions {\n /**\n * Initial backing buffer size (UTF-8 bytes). The buffer grows\n * geometrically as needed. Default: 8192.\n */\n initialSize?: number;\n /**\n * Growth multiplier when the backing buffer needs to expand.\n * Default: 2.\n */\n growthFactor?: number;\n}\n\n/**\n * Creates a Node-only buffer sink with a single pre-allocated growing\n * backing `Buffer`. UTF-8 encoding happens in-place at the current write\n * offset, avoiding per-chunk Buffer allocation and a final concat.\n *\n * Compared to `Buffer.concat`-style implementations, this trades a small\n * amount of headroom memory for ~5-10x throughput on small chunks\n * (see docs/benchmarks/2026-05-12-server-sink-strategy.md).\n */\n/**\n * A streaming-flavored buffer sink used by\n * `renderToReadableStream`. Coalesces successive `append(chunk)` calls\n * into a single byte buffer, then hands the buffer to a consumer\n * callback either on demand (`flush()`) or automatically once the\n * accumulated UTF-8 byte length crosses a threshold.\n *\n * The contract:\n * - Each call to `flush()` (or an auto-flush triggered from within\n * `append`) delivers **exactly one** non-empty byte buffer to the\n * consumer. Empty buffers are never delivered — callers do not\n * need to filter them out.\n * - The delivered buffer is exclusively owned by the consumer; the\n * sink will not mutate it afterwards. Internally we allocate a\n * fresh backing buffer per epoch, so handing off a `subarray` view\n * is safe with no copy.\n *\n * Issue 084: motivated by the streaming SSR throughput gap to\n * marko-run (mreact was at 0.66x marko's ops/sec because the previous\n * implementation paid a `TextEncoder.encode` + Web Streams\n * `controller.enqueue` round-trip per `sink.append()` call).\n */\nexport interface StreamingBufferSink {\n append(chunk: string): void;\n flush(): void;\n size(): number;\n}\n\nexport interface StreamingBufferSinkOptions {\n /** UTF-8 byte threshold that triggers an automatic flush from inside\n * `append`. Default 8 KiB (one common TCP segment payload). */\n flushThreshold?: number;\n /** Initial backing buffer size; same semantics as `BufferSinkOptions`. */\n initialSize?: number;\n /** Consumer hook — invoked at most once per `flush()` (manual or\n * automatic), and only with a non-empty byte buffer. */\n onFlush(buffer: Uint8Array): void;\n}\n\nexport function createStreamingBufferSink(\n options: StreamingBufferSinkOptions,\n): StreamingBufferSink {\n if (!hasNodeBuffer()) {\n return createStreamingEncodedSink(options);\n }\n\n const flushThreshold = options.flushThreshold ?? 8192;\n const initialSize = options.initialSize ?? flushThreshold;\n let inner = createBufferSink({ initialSize });\n const emitAndReset = () => {\n const buf = inner.toBuffer();\n inner = createBufferSink({ initialSize });\n options.onFlush(buf);\n };\n return {\n append(chunk) {\n if (chunk === \"\") return;\n inner.append(chunk);\n if (inner.size() >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (inner.size() === 0) return;\n emitAndReset();\n },\n size() {\n return inner.size();\n },\n };\n}\n\nfunction createStreamingEncodedSink(options: StreamingBufferSinkOptions): StreamingBufferSink {\n const flushThreshold = options.flushThreshold ?? 8192;\n const encoder = new TextEncoder();\n let chunks: Uint8Array[] = [];\n let byteLength = 0;\n\n const emitAndReset = () => {\n const output = concatUint8Arrays(chunks, byteLength);\n chunks = [];\n byteLength = 0;\n options.onFlush(output);\n };\n\n return {\n append(chunk) {\n if (chunk === \"\") return;\n\n const bytes = encoder.encode(chunk);\n chunks.push(bytes);\n byteLength += bytes.byteLength;\n\n if (byteLength >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (byteLength === 0) return;\n emitAndReset();\n },\n size() {\n return byteLength;\n },\n };\n}\n\nfunction concatUint8Arrays(chunks: Uint8Array[], byteLength: number): Uint8Array {\n if (chunks.length === 1) {\n return chunks[0] ?? new Uint8Array();\n }\n\n const output = new Uint8Array(byteLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n output.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return output;\n}\n\nfunction hasNodeBuffer(): boolean {\n return typeof Buffer !== \"undefined\" && typeof Buffer.allocUnsafe === \"function\";\n}\n\nexport function createBufferSink(options: BufferSinkOptions = {}): BufferSink {\n const initialSize = options.initialSize ?? 8192;\n const growthFactor = options.growthFactor ?? 2;\n let buffer = Buffer.allocUnsafe(initialSize);\n let offset = 0;\n\n function ensure(requiredBytes: number): void {\n const required = offset + requiredBytes;\n\n if (required <= buffer.length) {\n return;\n }\n\n let newCapacity = buffer.length === 0 ? initialSize : buffer.length;\n\n while (newCapacity < required) {\n newCapacity = Math.ceil(newCapacity * growthFactor);\n }\n\n const grown = Buffer.allocUnsafe(newCapacity);\n buffer.copy(grown, 0, 0, offset);\n buffer = grown;\n }\n\n return {\n append(chunk) {\n if (typeof chunk === \"string\") {\n ensure(Buffer.byteLength(chunk, \"utf8\"));\n offset += buffer.write(chunk, offset, \"utf8\");\n return;\n }\n\n ensure(chunk.length);\n chunk.copy(buffer, offset);\n offset += chunk.length;\n },\n toBuffer() {\n return buffer.subarray(0, offset);\n },\n toString() {\n return buffer.toString(\"utf8\", 0, offset);\n },\n size() {\n return offset;\n },\n };\n}\n"]}
1
+ {"version":3,"file":"buffer-sink.js","sourceRoot":"","sources":["../src/buffer-sink.ts"],"names":[],"mappings":"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","sourcesContent":["// Node 専用 buffer sink — issue 050 の対応。\n//\n// `createStringSink` (cross-runtime, string accumulator) と並べて、\n// Node の `Buffer` を直接 accumulate する sink を提供する。HTTP response\n// body へ `response.write(buffer)` で直接渡すと string → UTF-8 encode の\n// cost を 1 回にまとめられる利点がある。\n//\n// 注: Cloudflare Workers / Deno など `Buffer` を持たない runtime では\n// import 時に runtime error になる。cross-runtime ポータビリティが必要な\n// callsite は `@reckona/mreact-server` 本体の `createStringSink` を使う。\n//\n// tsconfig は `lib: ES2022 + DOM`, `types: []` なので `@types/node` に\n// 依存しないよう、`Buffer` の最小型を本 file 内で declare する。\n\ninterface NodeBuffer extends Uint8Array {\n toString(encoding?: string, start?: number, end?: number): string;\n write(input: string, offset: number, encoding?: string): number;\n copy(target: NodeBuffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;\n subarray(start?: number, end?: number): NodeBuffer;\n}\n\ninterface BufferConstructor {\n from(input: string, encoding?: string): NodeBuffer;\n from(input: ArrayBufferLike | ArrayLike<number>): NodeBuffer;\n alloc(size: number): NodeBuffer;\n allocUnsafe(size: number): NodeBuffer;\n byteLength(input: string, encoding?: string): number;\n isBuffer(input: unknown): input is NodeBuffer;\n}\n\ndeclare const Buffer: BufferConstructor;\n\n/** Accumulates server-rendered chunks into a Node Buffer. */\nexport interface BufferSink {\n append(chunk: string | NodeBuffer): void;\n toBuffer(): NodeBuffer;\n toString(): string;\n size(): number;\n}\n\n/** Options controlling allocation and growth for a Node buffer sink. */\nexport interface BufferSinkOptions {\n /**\n * Initial backing buffer size (UTF-8 bytes). The buffer grows\n * geometrically as needed. Default: 8192.\n */\n initialSize?: number;\n /**\n * Growth multiplier when the backing buffer needs to expand.\n * Default: 2.\n */\n growthFactor?: number;\n}\n\n/**\n * A streaming-flavored buffer sink used by\n * `renderToReadableStream`. Coalesces successive `append(chunk)` calls\n * into a single byte buffer, then hands the buffer to a consumer\n * callback either on demand (`flush()`) or automatically once the\n * accumulated UTF-8 byte length crosses a threshold.\n *\n * The contract:\n * - Each call to `flush()` (or an auto-flush triggered from within\n * `append`) delivers **exactly one** non-empty byte buffer to the\n * consumer. Empty buffers are never delivered — callers do not\n * need to filter them out.\n * - The delivered buffer is exclusively owned by the consumer; the\n * sink will not mutate it afterwards. Internally we allocate a\n * fresh backing buffer per epoch, so handing off a `subarray` view\n * is safe with no copy.\n *\n * Issue 084: motivated by the streaming SSR throughput gap to\n * marko-run (mreact was at 0.66x marko's ops/sec because the previous\n * implementation paid a `TextEncoder.encode` + Web Streams\n * `controller.enqueue` round-trip per `sink.append()` call).\n */\nexport interface StreamingBufferSink {\n append(chunk: string): void;\n flush(): void;\n size(): number;\n}\n\n/** Options controlling automatic flush behavior for a streaming buffer sink. */\nexport interface StreamingBufferSinkOptions {\n /** UTF-8 byte threshold that triggers an automatic flush from inside\n * `append`. Default 8 KiB (one common TCP segment payload). */\n flushThreshold?: number;\n /** Initial backing buffer size; same semantics as `BufferSinkOptions`. */\n initialSize?: number;\n /** Consumer hook — invoked at most once per `flush()` (manual or\n * automatic), and only with a non-empty byte buffer. */\n onFlush(buffer: Uint8Array): void;\n}\n\n/** Creates a streaming sink that coalesces appended text into byte buffers. */\nexport function createStreamingBufferSink(\n options: StreamingBufferSinkOptions,\n): StreamingBufferSink {\n if (!hasNodeBuffer()) {\n return createStreamingEncodedSink(options);\n }\n\n const flushThreshold = options.flushThreshold ?? 8192;\n const initialSize = options.initialSize ?? flushThreshold;\n let inner = createBufferSink({ initialSize });\n const emitAndReset = () => {\n const buf = inner.toBuffer();\n inner = createBufferSink({ initialSize });\n options.onFlush(buf);\n };\n return {\n append(chunk) {\n if (chunk === \"\") return;\n inner.append(chunk);\n if (inner.size() >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (inner.size() === 0) return;\n emitAndReset();\n },\n size() {\n return inner.size();\n },\n };\n}\n\nfunction createStreamingEncodedSink(options: StreamingBufferSinkOptions): StreamingBufferSink {\n const flushThreshold = options.flushThreshold ?? 8192;\n const encoder = new TextEncoder();\n let chunks: Uint8Array[] = [];\n let byteLength = 0;\n\n const emitAndReset = () => {\n const output = concatUint8Arrays(chunks, byteLength);\n chunks = [];\n byteLength = 0;\n options.onFlush(output);\n };\n\n return {\n append(chunk) {\n if (chunk === \"\") return;\n\n const bytes = encoder.encode(chunk);\n chunks.push(bytes);\n byteLength += bytes.byteLength;\n\n if (byteLength >= flushThreshold) {\n emitAndReset();\n }\n },\n flush() {\n if (byteLength === 0) return;\n emitAndReset();\n },\n size() {\n return byteLength;\n },\n };\n}\n\nfunction concatUint8Arrays(chunks: Uint8Array[], byteLength: number): Uint8Array {\n if (chunks.length === 1) {\n return chunks[0] ?? new Uint8Array();\n }\n\n const output = new Uint8Array(byteLength);\n let offset = 0;\n\n for (const chunk of chunks) {\n output.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return output;\n}\n\nfunction hasNodeBuffer(): boolean {\n return typeof Buffer !== \"undefined\" && typeof Buffer.allocUnsafe === \"function\";\n}\n\n/**\n * Creates a Node-only buffer sink with a single pre-allocated growing\n * backing `Buffer`.\n */\nexport function createBufferSink(options: BufferSinkOptions = {}): BufferSink {\n const initialSize = options.initialSize ?? 8192;\n const growthFactor = options.growthFactor ?? 2;\n let buffer = Buffer.allocUnsafe(initialSize);\n let offset = 0;\n\n function ensure(requiredBytes: number): void {\n const required = offset + requiredBytes;\n\n if (required <= buffer.length) {\n return;\n }\n\n let newCapacity = buffer.length === 0 ? initialSize : buffer.length;\n\n while (newCapacity < required) {\n newCapacity = Math.ceil(newCapacity * growthFactor);\n }\n\n const grown = Buffer.allocUnsafe(newCapacity);\n buffer.copy(grown, 0, 0, offset);\n buffer = grown;\n }\n\n return {\n append(chunk) {\n if (typeof chunk === \"string\") {\n ensure(Buffer.byteLength(chunk, \"utf8\"));\n offset += buffer.write(chunk, offset, \"utf8\");\n return;\n }\n\n ensure(chunk.length);\n chunk.copy(buffer, offset);\n offset += chunk.length;\n },\n toBuffer() {\n return buffer.subarray(0, offset);\n },\n toString() {\n return buffer.toString(\"utf8\", 0, offset);\n },\n size() {\n return offset;\n },\n };\n}\n"]}
package/dist/flight.d.ts CHANGED
@@ -1,34 +1,46 @@
1
+ /** Symbol tag used to identify client references in serialized Flight values. */
1
2
  export declare const CLIENT_REFERENCE_TYPE: unique symbol;
3
+ /** Symbol tag used to identify server references in serialized Flight values. */
2
4
  export declare const SERVER_REFERENCE_TYPE: unique symbol;
5
+ /** Registered client reference included in a Flight response. */
3
6
  export interface FlightClientReference {
4
7
  id: number;
5
8
  moduleId: string;
6
9
  exportName: string;
7
10
  chunks?: string[];
8
11
  }
12
+ /** Input used to register a client reference before assigning a Flight id. */
9
13
  export interface FlightClientReferenceInput {
10
14
  name: string;
11
15
  moduleId: string;
12
16
  exportName: string;
13
17
  }
18
+ /** Client manifest entry with resolved module chunks. */
14
19
  export interface FlightClientManifestEntry extends FlightClientReferenceInput {
15
20
  chunks: string[];
16
21
  }
22
+ /** Function that can be invoked through a server action request. */
17
23
  export type ServerAction = (...args: unknown[]) => unknown | Promise<unknown>;
24
+ /** Validation result returned by server action guards. */
18
25
  export type ServerActionValidationResult = boolean | string;
26
+ /** Server action entry with optional argument validation. */
19
27
  export interface ServerActionDescriptor {
20
28
  action: ServerAction;
21
29
  validateArgs?: (args: unknown[]) => ServerActionValidationResult;
22
30
  }
31
+ /** Registry mapping server action keys to handlers. */
23
32
  export type ServerActionRegistry = Record<string, ServerAction | ServerActionDescriptor>;
33
+ /** Store used to reject replayed server action nonces. */
24
34
  export interface ServerActionReplayStore {
25
35
  has(value: string): boolean;
26
36
  add(value: string): void;
27
37
  }
38
+ /** Module export reference requested by a server action request. */
28
39
  export interface ServerActionRequestReference {
29
40
  moduleId: string;
30
41
  exportName: string;
31
42
  }
43
+ /** Security and validation options for createServerActionHandler. */
32
44
  export interface ServerActionHandlerOptions {
33
45
  allowedOrigins?: readonly string[] | "any";
34
46
  authorize?: (request: Request, reference: ServerActionRequestReference, args: unknown[]) => ServerActionValidationResult | Promise<ServerActionValidationResult>;
@@ -43,41 +55,49 @@ export interface ServerActionHandlerOptions {
43
55
  };
44
56
  maxBodyBytes?: number;
45
57
  }
58
+ /** Options for embedding a serialized Flight response in a script tag. */
46
59
  export interface FlightScriptOptions {
47
60
  id?: string;
48
61
  nonce?: string;
49
62
  }
63
+ /** Registered server reference included in a Flight response. */
50
64
  export interface FlightServerReference {
51
65
  id: number;
52
66
  moduleId: string;
53
67
  exportName: string;
54
68
  bound?: FlightModel[];
55
69
  }
70
+ /** Runtime marker object representing a client module export. */
56
71
  export interface ClientReference {
57
72
  $$typeof: typeof CLIENT_REFERENCE_TYPE;
58
73
  moduleId: string;
59
74
  exportName: string;
60
75
  chunks?: string[];
61
76
  }
77
+ /** Runtime marker object representing a server module export. */
62
78
  export interface ServerReference {
63
79
  $$typeof: typeof SERVER_REFERENCE_TYPE;
64
80
  moduleId: string;
65
81
  exportName: string;
66
82
  bound?: unknown[];
67
83
  }
84
+ /** Serializable Flight payload with root model and module references. */
68
85
  export interface FlightResponse {
69
86
  version: 1;
70
87
  root: FlightModel;
71
88
  clientReferences: FlightClientReference[];
72
89
  serverReferences: FlightServerReference[];
73
90
  }
91
+ /** Recursive value model supported by the mreact Flight serializer. */
74
92
  export type FlightModel = null | string | number | boolean | FlightModel[] | FlightObjectModel | FlightElementModel | FlightClientReferenceModel | FlightServerReferenceModel | FlightDateModel | FlightBigIntModel | FlightNumberModel | FlightSymbolModel | FlightMapModel | FlightSetModel | FlightFormDataModel | FlightIterableModel | FlightErrorModel | FlightPromiseModel | FlightArrayBufferModel | FlightTypedArrayModel | FlightDataViewModel | {
75
93
  kind: "undefined";
76
94
  };
95
+ /** Plain object shape inside a Flight model. */
77
96
  export interface FlightObjectModel {
78
97
  kind?: never;
79
98
  [key: string]: FlightModel | undefined;
80
99
  }
100
+ /** Serialized React-compatible element inside a Flight model. */
81
101
  export interface FlightElementModel {
82
102
  kind: "element";
83
103
  type: string | FlightClientReferenceModel | {
@@ -86,88 +106,119 @@ export interface FlightElementModel {
86
106
  key: string | null;
87
107
  props: Record<string, FlightModel>;
88
108
  }
109
+ /** Reference to a client module export inside a Flight model. */
89
110
  export interface FlightClientReferenceModel {
90
111
  kind: "client-reference";
91
112
  id: number;
92
113
  }
114
+ /** Reference to a server module export inside a Flight model. */
93
115
  export interface FlightServerReferenceModel {
94
116
  kind: "server-reference";
95
117
  id: number;
96
118
  }
119
+ /** Serialized Date value inside a Flight model. */
97
120
  export interface FlightDateModel {
98
121
  kind: "date";
99
122
  value: string;
100
123
  }
124
+ /** Serialized bigint value inside a Flight model. */
101
125
  export interface FlightBigIntModel {
102
126
  kind: "bigint";
103
127
  value: string;
104
128
  }
129
+ /** Serialized non-finite or negative-zero number inside a Flight model. */
105
130
  export interface FlightNumberModel {
106
131
  kind: "number";
107
132
  value: "Infinity" | "-Infinity" | "NaN" | "-0";
108
133
  }
134
+ /** Serialized global symbol reference inside a Flight model. */
109
135
  export interface FlightSymbolModel {
110
136
  kind: "symbol";
111
137
  name: string;
112
138
  }
139
+ /** Serialized Map value inside a Flight model. */
113
140
  export interface FlightMapModel {
114
141
  kind: "map";
115
142
  entries: [FlightModel, FlightModel][];
116
143
  }
144
+ /** Serialized Set value inside a Flight model. */
117
145
  export interface FlightSetModel {
118
146
  kind: "set";
119
147
  values: FlightModel[];
120
148
  }
149
+ /** Serialized FormData value inside a Flight model. */
121
150
  export interface FlightFormDataModel {
122
151
  kind: "form-data";
123
152
  entries: [string, FlightModel][];
124
153
  }
154
+ /** Serialized iterable value inside a Flight model. */
125
155
  export interface FlightIterableModel {
126
156
  kind: "iterable";
127
157
  values: FlightModel[];
128
158
  }
159
+ /** Serialized Error value inside a Flight model. */
129
160
  export interface FlightErrorModel {
130
161
  kind: "error";
131
162
  name: string;
132
163
  message: string;
133
164
  digest?: string;
134
165
  }
166
+ /** Reference to an outlined promise chunk inside a Flight model. */
135
167
  export interface FlightPromiseModel {
136
168
  kind: "promise";
137
169
  id: number;
138
170
  }
171
+ /** Serialized ArrayBuffer value inside a Flight model. */
139
172
  export interface FlightArrayBufferModel {
140
173
  kind: "array-buffer";
141
174
  bytes: number[];
142
175
  }
176
+ /** Serialized typed array value inside a Flight model. */
143
177
  export interface FlightTypedArrayModel {
144
178
  kind: "typed-array";
145
179
  arrayType: FlightTypedArrayName;
146
180
  bytes: number[];
147
181
  }
182
+ /** Serialized DataView value inside a Flight model. */
148
183
  export interface FlightDataViewModel {
149
184
  kind: "data-view";
150
185
  bytes: number[];
151
186
  }
187
+ /** Typed array constructor names supported by the Flight serializer. */
152
188
  export type FlightTypedArrayName = "Int8Array" | "Uint8Array" | "Uint8ClampedArray" | "Int16Array" | "Uint16Array" | "Int32Array" | "Uint32Array" | "Float32Array" | "Float64Array" | "BigInt64Array" | "BigUint64Array";
189
+ /** Lists the React Flight row tags and model tokens covered by the serializer. */
153
190
  export interface ReactFlightProtocolCoverage {
154
191
  binaryRowTags: string[];
155
192
  modelTokens: string[];
156
193
  rowTags: string[];
157
194
  }
195
+ /** Returns the React Flight protocol tags and tokens supported by this package. */
158
196
  export declare function getReactFlightProtocolCoverage(): ReactFlightProtocolCoverage;
197
+ /** Creates a runtime client reference marker for a module export. */
159
198
  export declare function createClientReference(moduleId: string, exportName?: string, chunks?: string[]): ClientReference;
199
+ /** Creates a runtime server reference marker for a module export. */
160
200
  export declare function createServerReference(moduleId: string, exportName?: string, bound?: unknown[]): ServerReference;
201
+ /** Returns true when a value is a runtime client reference marker. */
161
202
  export declare function isClientReference(value: unknown): value is ClientReference;
203
+ /** Returns true when a value is a runtime server reference marker. */
162
204
  export declare function isServerReference(value: unknown): value is ServerReference;
205
+ /** Serializes a renderable value into a structured Flight response. */
163
206
  export declare function renderToFlightResponse<P extends Record<string, unknown>>(renderable: ((props: P) => unknown) | unknown, props?: P): Promise<FlightResponse>;
207
+ /** Serializes a Flight response to JSON text. */
164
208
  export declare function stringifyFlightResponse(response: FlightResponse): string;
209
+ /** Renders a Flight response as an HTML script tag. */
165
210
  export declare function renderFlightResponseScript(response: FlightResponse, options?: FlightScriptOptions): string;
211
+ /** Creates a request handler that validates and invokes registered server actions. */
166
212
  export declare function createServerActionHandler(actions: ServerActionRegistry, options?: ServerActionHandlerOptions): (request: Request) => Promise<Response>;
213
+ /** Encodes a structured Flight response into React Flight row text. */
167
214
  export declare function toReactFlightRows(response: FlightResponse): string;
215
+ /** Decodes React Flight row text into a structured Flight response. */
168
216
  export declare function fromReactFlightRows(rows: string): FlightResponse;
217
+ /** Merges additional React Flight row text into an existing Flight response. */
169
218
  export declare function mergeReactFlightRows(response: FlightResponse, rows: string): FlightResponse;
219
+ /** Builds a Flight client manifest from client references and chunk resolution. */
170
220
  export declare function createFlightClientManifest(references: readonly FlightClientReferenceInput[], resolveChunks: (reference: FlightClientReferenceInput) => string[]): FlightClientManifestEntry[];
221
+ /** Renders modulepreload links for client chunks referenced by a Flight response. */
171
222
  export declare function renderFlightPreloadLinks(response: FlightResponse, options?: {
172
223
  nonce?: string;
173
224
  }): string;