@tanstack/react-start-rsc 0.1.11 → 0.1.13

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 +1 @@
1
- {"version":3,"file":"ClientSlot.js","names":[],"sources":["../../src/ClientSlot.tsx"],"sourcesContent":["'use client'\n\nimport { useSlotContext } from './SlotContext'\n\nexport interface ClientSlotProps {\n slot: string\n args: Array<unknown>\n}\n\nexport function ClientSlot({ slot, args }: ClientSlotProps) {\n const ctx = useSlotContext()\n\n if (!ctx) {\n throw new Error('ClientSlot must be rendered within SlotProvider')\n }\n\n const impl = ctx.implementations[slot]\n\n // No implementation provided\n if (impl === undefined) {\n if (ctx.strict) {\n throw new Error(`Missing slot implementation for \"${slot}\"`)\n }\n return null\n }\n\n // For children slot or any non-function value, render directly\n if (typeof impl !== 'function') {\n return <>{impl}</>\n }\n\n // Render function with args\n return <>{impl(...args)}</>\n}\n"],"mappings":";;;;AASA,SAAgB,WAAW,EAAE,MAAM,QAAyB;CAC1D,MAAM,MAAM,gBAAgB;AAE5B,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,kDAAkD;CAGpE,MAAM,OAAO,IAAI,gBAAgB;AAGjC,KAAI,SAAS,KAAA,GAAW;AACtB,MAAI,IAAI,OACN,OAAM,IAAI,MAAM,oCAAoC,KAAK,GAAG;AAE9D,SAAO;;AAIT,KAAI,OAAO,SAAS,WAClB,QAAO,oBAAA,UAAA,EAAA,UAAG,MAAQ,CAAA;AAIpB,QAAO,oBAAA,UAAA,EAAA,UAAG,KAAK,GAAG,KAAK,EAAI,CAAA"}
1
+ {"version":3,"file":"ClientSlot.js","names":[],"sources":["../../src/ClientSlot.tsx"],"sourcesContent":["'use client'\n\nimport { useSlotContext } from './SlotContext'\n\nexport interface ClientSlotProps {\n slot: string\n args: Array<unknown>\n}\n\nexport function ClientSlot({ slot, args }: ClientSlotProps) {\n const ctx = useSlotContext()\n\n if (!ctx) {\n throw new Error('ClientSlot must be rendered within SlotProvider')\n }\n\n const impl = ctx.implementations[slot]\n\n // No implementation provided\n if (impl === undefined) {\n if (ctx.strict) {\n throw new Error(`Missing slot implementation for \"${slot}\"`)\n }\n return null\n }\n\n // For children slot or any non-function value, render directly\n if (typeof impl !== 'function') {\n return <>{impl}</>\n }\n\n // Render function with args\n return <>{impl(...args)}</>\n}\n"],"mappings":";;;;AASA,SAAgB,WAAW,EAAE,MAAM,QAAyB;CAC1D,MAAM,MAAM,eAAe;CAE3B,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,iDAAiD;CAGnE,MAAM,OAAO,IAAI,gBAAgB;CAGjC,IAAI,SAAS,KAAA,GAAW;EACtB,IAAI,IAAI,QACN,MAAM,IAAI,MAAM,oCAAoC,KAAK,EAAE;EAE7D,OAAO;CACT;CAGA,IAAI,OAAO,SAAS,YAClB,OAAO,oBAAA,UAAA,EAAA,UAAG,KAAO,CAAA;CAInB,OAAO,oBAAA,UAAA,EAAA,UAAG,KAAK,GAAG,IAAI,EAAI,CAAA;AAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"CompositeComponent.js","names":[],"sources":["../../src/CompositeComponent.tsx"],"sourcesContent":["'use client'\n\nimport { Suspense } from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { SlotProvider } from './SlotContext'\nimport {\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport type { AnyCompositeComponent } from './ServerComponentTypes'\nimport type { SlotImplementations } from './types'\n\nfunction splitSlotProps(props?: Record<string, unknown>): {\n implementations: SlotImplementations\n strict: boolean\n} {\n const safeProps = props ?? {}\n const { children, strict, ...slotProps } = safeProps as {\n children?: unknown\n strict?: unknown\n [key: string]: unknown\n }\n\n return {\n implementations: { ...slotProps, children },\n strict: strict === true,\n }\n}\n\nfunction EmptyFallback() {\n return null\n}\n\nfunction CompositeRenderInner({\n getTree,\n path,\n slotProps,\n}: {\n getTree: () => unknown\n path: Array<string>\n slotProps?: Record<string, unknown>\n}): React.ReactNode {\n let tree: unknown = getTree()\n\n for (const key of path) {\n if (tree === null || tree === undefined) return null\n if (typeof tree !== 'object') return null\n tree = (tree as Record<string, unknown>)[key]\n }\n\n if (tree === null || tree === undefined) return null\n\n const { implementations, strict } = splitSlotProps(slotProps)\n\n return (\n <SlotProvider implementations={implementations} strict={strict}>\n {tree as React.ReactNode}\n </SlotProvider>\n )\n}\n\nfunction CompositeRenderComponent({\n getTree,\n path,\n slotProps,\n cssHrefs,\n jsPreloads,\n}: {\n getTree: () => unknown\n path: Array<string>\n slotProps?: Record<string, unknown>\n cssHrefs?: ReadonlySet<string>\n jsPreloads?: ReadonlySet<string>\n}): React.ReactNode {\n for (const href of cssHrefs ?? []) {\n ReactDOM.preinit(href, { as: 'style', precedence: 'high' })\n }\n\n if (jsPreloads) {\n for (const href of jsPreloads) {\n ReactDOM.preloadModule(href)\n }\n }\n\n return (\n <>\n <Suspense fallback={<EmptyFallback />}>\n <CompositeRenderInner\n getTree={getTree}\n path={path}\n slotProps={slotProps}\n />\n </Suspense>\n </>\n )\n}\n\n/**\n * Renders composite RSC data with slot support.\n *\n * Use this component to render data from `createCompositeComponent`.\n * Pass slot implementations as props to fill in ClientSlot placeholders.\n *\n * @example\n * ```tsx\n * const src = await createCompositeComponent((props) => (\n * <div>\n * <header>{props.header('Dashboard')}</header>\n * <main>{props.children}</main>\n * </div>\n * ))\n *\n * // In route component\n * return (\n * <CompositeComponent src={src} header={(title) => <h1>{title}</h1>}>\n * <p>Main content</p>\n * </CompositeComponent>\n * )\n * ```\n */\nexport function CompositeComponent<TComp extends AnyCompositeComponent>(\n props: CompositeComponentProps<TComp>,\n): TComp['~types']['return'] {\n const { src, ...slotProps } = props\n\n const stream = src[SERVER_COMPONENT_STREAM]\n\n if (!stream) {\n throw new Error(\n '[tanstack/start] <CompositeComponent> missing RSC stream on src',\n )\n }\n\n const cssHrefs = src[SERVER_COMPONENT_CSS_HREFS]\n const jsPreloads = src[SERVER_COMPONENT_JS_PRELOADS]\n\n const path = src[RSC_PROXY_PATH] ?? []\n\n const getTree = src[RSC_PROXY_GET_TREE]\n\n if (!getTree) {\n throw new Error(\n '[tanstack/start] <CompositeComponent> missing getTree on RSC src. ' +\n 'Make sure src comes from createCompositeComponent().',\n )\n }\n\n return (\n <CompositeRenderComponent\n getTree={getTree}\n path={path}\n slotProps={slotProps}\n cssHrefs={cssHrefs}\n jsPreloads={jsPreloads}\n />\n )\n}\n\nexport type CompositeComponentProps<TComp extends AnyCompositeComponent> = {\n src: TComp\n} & TComp['~types']['props']\n"],"mappings":";;;;;;;AAgBA,SAAS,eAAe,OAGtB;CAEA,MAAM,EAAE,UAAU,QAAQ,GAAG,cADX,SAAS,EAAE;AAO7B,QAAO;EACL,iBAAiB;GAAE,GAAG;GAAW;GAAU;EAC3C,QAAQ,WAAW;EACpB;;AAGH,SAAS,gBAAgB;AACvB,QAAO;;AAGT,SAAS,qBAAqB,EAC5B,SACA,MACA,aAKkB;CAClB,IAAI,OAAgB,SAAS;AAE7B,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,SAAS,QAAQ,SAAS,KAAA,EAAW,QAAO;AAChD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAQ,KAAiC;;AAG3C,KAAI,SAAS,QAAQ,SAAS,KAAA,EAAW,QAAO;CAEhD,MAAM,EAAE,iBAAiB,WAAW,eAAe,UAAU;AAE7D,QACE,oBAAC,cAAD;EAA+B;EAAyB;YACrD;EACY,CAAA;;AAInB,SAAS,yBAAyB,EAChC,SACA,MACA,WACA,UACA,cAOkB;AAClB,MAAK,MAAM,QAAQ,YAAY,EAAE,CAC/B,UAAS,QAAQ,MAAM;EAAE,IAAI;EAAS,YAAY;EAAQ,CAAC;AAG7D,KAAI,WACF,MAAK,MAAM,QAAQ,WACjB,UAAS,cAAc,KAAK;AAIhC,QACE,oBAAA,UAAA,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,eAAD,EAAiB,CAAA;YACnC,oBAAC,sBAAD;GACW;GACH;GACK;GACX,CAAA;EACO,CAAA,EACV,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;AA2BP,SAAgB,mBACd,OAC2B;CAC3B,MAAM,EAAE,KAAK,GAAG,cAAc;AAI9B,KAAI,CAFW,IAAI,yBAGjB,OAAM,IAAI,MACR,kEACD;CAGH,MAAM,WAAW,IAAI;CACrB,MAAM,aAAa,IAAI;CAEvB,MAAM,OAAO,IAAI,mBAAmB,EAAE;CAEtC,MAAM,UAAU,IAAI;AAEpB,KAAI,CAAC,QACH,OAAM,IAAI,MACR,yHAED;AAGH,QACE,oBAAC,0BAAD;EACW;EACH;EACK;EACD;EACE;EACZ,CAAA"}
1
+ {"version":3,"file":"CompositeComponent.js","names":[],"sources":["../../src/CompositeComponent.tsx"],"sourcesContent":["'use client'\n\nimport { Suspense } from 'react'\nimport ReactDOM from 'react-dom'\n\nimport { SlotProvider } from './SlotContext'\nimport {\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport type { AnyCompositeComponent } from './ServerComponentTypes'\nimport type { SlotImplementations } from './types'\n\nfunction splitSlotProps(props?: Record<string, unknown>): {\n implementations: SlotImplementations\n strict: boolean\n} {\n const safeProps = props ?? {}\n const { children, strict, ...slotProps } = safeProps as {\n children?: unknown\n strict?: unknown\n [key: string]: unknown\n }\n\n return {\n implementations: { ...slotProps, children },\n strict: strict === true,\n }\n}\n\nfunction EmptyFallback() {\n return null\n}\n\nfunction CompositeRenderInner({\n getTree,\n path,\n slotProps,\n}: {\n getTree: () => unknown\n path: Array<string>\n slotProps?: Record<string, unknown>\n}): React.ReactNode {\n let tree: unknown = getTree()\n\n for (const key of path) {\n if (tree === null || tree === undefined) return null\n if (typeof tree !== 'object') return null\n tree = (tree as Record<string, unknown>)[key]\n }\n\n if (tree === null || tree === undefined) return null\n\n const { implementations, strict } = splitSlotProps(slotProps)\n\n return (\n <SlotProvider implementations={implementations} strict={strict}>\n {tree as React.ReactNode}\n </SlotProvider>\n )\n}\n\nfunction CompositeRenderComponent({\n getTree,\n path,\n slotProps,\n cssHrefs,\n jsPreloads,\n}: {\n getTree: () => unknown\n path: Array<string>\n slotProps?: Record<string, unknown>\n cssHrefs?: ReadonlySet<string>\n jsPreloads?: ReadonlySet<string>\n}): React.ReactNode {\n for (const href of cssHrefs ?? []) {\n ReactDOM.preinit(href, { as: 'style', precedence: 'high' })\n }\n\n if (jsPreloads) {\n for (const href of jsPreloads) {\n ReactDOM.preloadModule(href)\n }\n }\n\n return (\n <>\n <Suspense fallback={<EmptyFallback />}>\n <CompositeRenderInner\n getTree={getTree}\n path={path}\n slotProps={slotProps}\n />\n </Suspense>\n </>\n )\n}\n\n/**\n * Renders composite RSC data with slot support.\n *\n * Use this component to render data from `createCompositeComponent`.\n * Pass slot implementations as props to fill in ClientSlot placeholders.\n *\n * @example\n * ```tsx\n * const src = await createCompositeComponent((props) => (\n * <div>\n * <header>{props.header('Dashboard')}</header>\n * <main>{props.children}</main>\n * </div>\n * ))\n *\n * // In route component\n * return (\n * <CompositeComponent src={src} header={(title) => <h1>{title}</h1>}>\n * <p>Main content</p>\n * </CompositeComponent>\n * )\n * ```\n */\nexport function CompositeComponent<TComp extends AnyCompositeComponent>(\n props: CompositeComponentProps<TComp>,\n): TComp['~types']['return'] {\n const { src, ...slotProps } = props\n\n const stream = src[SERVER_COMPONENT_STREAM]\n\n if (!stream) {\n throw new Error(\n '[tanstack/start] <CompositeComponent> missing RSC stream on src',\n )\n }\n\n const cssHrefs = src[SERVER_COMPONENT_CSS_HREFS]\n const jsPreloads = src[SERVER_COMPONENT_JS_PRELOADS]\n\n const path = src[RSC_PROXY_PATH] ?? []\n\n const getTree = src[RSC_PROXY_GET_TREE]\n\n if (!getTree) {\n throw new Error(\n '[tanstack/start] <CompositeComponent> missing getTree on RSC src. ' +\n 'Make sure src comes from createCompositeComponent().',\n )\n }\n\n return (\n <CompositeRenderComponent\n getTree={getTree}\n path={path}\n slotProps={slotProps}\n cssHrefs={cssHrefs}\n jsPreloads={jsPreloads}\n />\n )\n}\n\nexport type CompositeComponentProps<TComp extends AnyCompositeComponent> = {\n src: TComp\n} & TComp['~types']['props']\n"],"mappings":";;;;;;;AAgBA,SAAS,eAAe,OAGtB;CAEA,MAAM,EAAE,UAAU,QAAQ,GAAG,cADX,SAAS,CAAC;CAO5B,OAAO;EACL,iBAAiB;GAAE,GAAG;GAAW;EAAS;EAC1C,QAAQ,WAAW;CACrB;AACF;AAEA,SAAS,gBAAgB;CACvB,OAAO;AACT;AAEA,SAAS,qBAAqB,EAC5B,SACA,MACA,aAKkB;CAClB,IAAI,OAAgB,QAAQ;CAE5B,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,SAAS,QAAQ,SAAS,KAAA,GAAW,OAAO;EAChD,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,OAAQ,KAAiC;CAC3C;CAEA,IAAI,SAAS,QAAQ,SAAS,KAAA,GAAW,OAAO;CAEhD,MAAM,EAAE,iBAAiB,WAAW,eAAe,SAAS;CAE5D,OACE,oBAAC,cAAD;EAA+B;EAAyB;YACrD;CACW,CAAA;AAElB;AAEA,SAAS,yBAAyB,EAChC,SACA,MACA,WACA,UACA,cAOkB;CAClB,KAAK,MAAM,QAAQ,YAAY,CAAC,GAC9B,SAAS,QAAQ,MAAM;EAAE,IAAI;EAAS,YAAY;CAAO,CAAC;CAG5D,IAAI,YACF,KAAK,MAAM,QAAQ,YACjB,SAAS,cAAc,IAAI;CAI/B,OACE,oBAAA,UAAA,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,eAAD,CAAgB,CAAA;YAClC,oBAAC,sBAAD;GACW;GACH;GACK;EACZ,CAAA;CACO,CAAA,EACV,CAAA;AAEN;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,mBACd,OAC2B;CAC3B,MAAM,EAAE,KAAK,GAAG,cAAc;CAI9B,IAAI,CAFW,IAAI,0BAGjB,MAAM,IAAI,MACR,iEACF;CAGF,MAAM,WAAW,IAAI;CACrB,MAAM,aAAa,IAAI;CAEvB,MAAM,OAAO,IAAI,mBAAmB,CAAC;CAErC,MAAM,UAAU,IAAI;CAEpB,IAAI,CAAC,SACH,MAAM,IAAI,MACR,wHAEF;CAGF,OACE,oBAAC,0BAAD;EACW;EACH;EACK;EACD;EACE;CACb,CAAA;AAEL"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReplayableStream.js","names":[],"sources":["../../src/ReplayableStream.ts"],"sourcesContent":["/**\n * ReplayableStream is used for React Server Components (RSC) / Flight streams.\n *\n * In this package the same Flight payload may need to be:\n * - decoded for SSR (render path), and/or\n * - serialized for transport to the client for client-side decoding.\n *\n * Call sites:\n * - `src/createServerComponent.ts`: wraps the produced Flight stream once.\n * - `src/serialization.ts`: uses `createReplayStream()` to transport a fresh stream\n * to the client via `RawStream`.\n *\n * Constraints:\n * - Consumption order isn't fixed: SSR decode might start first or transport might\n * start first depending on the request path.\n * - Sometimes only one happens (e.g. when client calls server function directly).\n *\n * Why not just `ReadableStream.tee()`?\n * - tee() must be called up-front before the stream is consumed/locked and only\n * creates two live branches (no late \"replay from byte 0\").\n * - If one branch is slower or never consumed, the runtime may buffer internally\n * to keep branches consistent, which can retain large Flight payloads longer\n * than intended and makes cleanup less explicit.\n *\n * ReplayableStream reads once, buffers explicitly, can mint replay streams on\n * demand, and centralizes cancellation so aborting can stop upstream work and\n * free buffered data deterministically.\n *\n * Memory Management:\n * - Memory is released when the abort signal fires (request cancelled)\n * - Call `release()` to force immediate cleanup if no more replays are needed\n * - No automatic release: replays can be created at unpredictable times (SSR decode\n * finishes before serialization starts), so we can't safely auto-release\n */\n\nexport interface ReplayableStreamOptions {\n signal?: AbortSignal\n}\n\n// Use Symbol.for to ensure the same symbol across different module instances\nexport const REPLAYABLE_STREAM_MARKER = Symbol.for(\n 'tanstack.rsc.ReplayableStream',\n)\n\nexport class ReplayableStream<T = Uint8Array> {\n // Marker for cross-environment instance checking\n readonly [REPLAYABLE_STREAM_MARKER] = true\n\n private chunks: Array<T> = []\n private done = false\n private error: unknown = null\n private waiter: PromiseWithResolvers<void> | null = null\n private aborted = false\n private released = false\n\n private sourceReader: ReadableStreamDefaultReader<T> | null = null\n private abortSignal: AbortSignal | undefined\n private abortListener: (() => void) | null = null\n\n constructor(\n private source: ReadableStream<T>,\n private options: ReplayableStreamOptions = {},\n ) {\n this.abortSignal = options.signal\n this.start()\n }\n\n private start(): void {\n const signal = this.abortSignal\n\n if (signal?.aborted) {\n this.handleAbort()\n return\n }\n\n const onAbort = () => this.handleAbort()\n this.abortListener = onAbort\n signal?.addEventListener('abort', onAbort, { once: true })\n\n const reader = this.source.getReader()\n this.sourceReader = reader\n\n const pump = async () => {\n try {\n // Keep reading until upstream ends or we are stopped.\n while (!this.aborted && !this.released) {\n const { done, value } = await reader.read()\n if (done) break\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.aborted || this.released) break\n this.chunks.push(value)\n this.notify()\n }\n this.done = true\n } catch (err) {\n if (!this.aborted && !this.released) {\n this.error = err\n }\n this.done = true\n } finally {\n this.detachAbortListener()\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n if (this.sourceReader === reader) {\n this.sourceReader = null\n }\n this.notify()\n }\n }\n\n pump()\n }\n\n private detachAbortListener(): void {\n const signal = this.abortSignal\n const listener = this.abortListener\n if (signal && listener) {\n signal.removeEventListener('abort', listener)\n }\n this.abortListener = null\n }\n\n private cancelSource(reason: unknown): void {\n const reader = this.sourceReader\n this.sourceReader = null\n\n try {\n reader?.cancel(reason).catch(() => {})\n } catch {\n // Ignore\n }\n }\n\n private handleAbort(): void {\n if (this.aborted) return\n this.aborted = true\n this.done = true\n\n // Try to stop upstream work immediately.\n // Cancellation during an abort can throw synchronously in some runtimes\n // (eg when the underlying cancel algorithm throws). Never let that escape\n // an AbortSignal event handler.\n const reason =\n this.abortSignal?.reason ?? new Error('ReplayableStream aborted')\n\n this.detachAbortListener()\n this.abortSignal = undefined\n this.cancelSource(reason)\n\n this.chunks = [] // Free memory immediately on abort\n this.released = true\n this.notify()\n }\n\n private notify(): void {\n if (this.waiter) {\n this.waiter.resolve()\n this.waiter = null\n }\n }\n\n private wait(): Promise<void> {\n if (this.done || this.released) return Promise.resolve()\n if (!this.waiter) {\n this.waiter = Promise.withResolvers<void>()\n }\n return this.waiter.promise\n }\n\n /**\n * Explicitly release buffered chunks.\n * Call this when you know no more replay streams will be created.\n * After calling release(), createReplayStream() will return empty streams.\n */\n release(): void {\n if (this.released) return\n\n this.released = true\n this.chunks = []\n\n // Release should also stop upstream work and wake any waiters.\n // This is important when a Flight payload is never consumed again\n // (eg. cached loader data that evicts) to avoid retaining upstream resources.\n this.detachAbortListener()\n this.abortSignal = undefined\n this.cancelSource(new Error('ReplayableStream released'))\n this.notify()\n }\n\n /**\n * Check if the stream data has been released\n */\n isReleased(): boolean {\n return this.released\n }\n\n /**\n * Create an independent replay stream. Each call returns a fresh reader\n * that starts from the beginning of the buffered data.\n *\n * If the stream has been released, returns a stream that closes immediately.\n */\n createReplayStream(): ReadableStream<T> {\n if (this.released) {\n return new ReadableStream<T>({\n start(controller) {\n controller.close()\n },\n })\n }\n\n let index = 0\n\n return new ReadableStream<T>({\n pull: async (controller) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n if (this.released) {\n controller.close()\n return\n }\n\n if (index < this.chunks.length) {\n controller.enqueue(this.chunks[index++] as T)\n return\n }\n\n if (this.done) {\n if (this.error && !this.aborted) {\n controller.error(this.error)\n } else {\n controller.close()\n }\n return\n }\n\n await this.wait()\n }\n },\n cancel: () => {\n // No-op: consumers canceling a replay should not cancel upstream.\n // Upstream cancellation is controlled by abort/release.\n },\n })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReplayableStream.js","names":[],"sources":["../../src/ReplayableStream.ts"],"sourcesContent":["/**\n * ReplayableStream is used for React Server Components (RSC) / Flight streams.\n *\n * In this package the same Flight payload may need to be:\n * - decoded for SSR (render path), and/or\n * - serialized for transport to the client for client-side decoding.\n *\n * Call sites:\n * - `src/createServerComponent.ts`: wraps the produced Flight stream once.\n * - `src/serialization.ts`: uses `createReplayStream()` to transport a fresh stream\n * to the client via `RawStream`.\n *\n * Constraints:\n * - Consumption order isn't fixed: SSR decode might start first or transport might\n * start first depending on the request path.\n * - Sometimes only one happens (e.g. when client calls server function directly).\n *\n * Why not just `ReadableStream.tee()`?\n * - tee() must be called up-front before the stream is consumed/locked and only\n * creates two live branches (no late \"replay from byte 0\").\n * - If one branch is slower or never consumed, the runtime may buffer internally\n * to keep branches consistent, which can retain large Flight payloads longer\n * than intended and makes cleanup less explicit.\n *\n * ReplayableStream reads once, buffers explicitly, can mint replay streams on\n * demand, and centralizes cancellation so aborting can stop upstream work and\n * free buffered data deterministically.\n *\n * Memory Management:\n * - Memory is released when the abort signal fires (request cancelled)\n * - Call `release()` to force immediate cleanup if no more replays are needed\n * - No automatic release: replays can be created at unpredictable times (SSR decode\n * finishes before serialization starts), so we can't safely auto-release\n */\n\nexport interface ReplayableStreamOptions {\n signal?: AbortSignal\n}\n\n// Use Symbol.for to ensure the same symbol across different module instances\nexport const REPLAYABLE_STREAM_MARKER = Symbol.for(\n 'tanstack.rsc.ReplayableStream',\n)\n\nexport class ReplayableStream<T = Uint8Array> {\n // Marker for cross-environment instance checking\n readonly [REPLAYABLE_STREAM_MARKER] = true\n\n private chunks: Array<T> = []\n private done = false\n private error: unknown = null\n private waiter: PromiseWithResolvers<void> | null = null\n private aborted = false\n private released = false\n\n private sourceReader: ReadableStreamDefaultReader<T> | null = null\n private abortSignal: AbortSignal | undefined\n private abortListener: (() => void) | null = null\n\n constructor(\n private source: ReadableStream<T>,\n private options: ReplayableStreamOptions = {},\n ) {\n this.abortSignal = options.signal\n this.start()\n }\n\n private start(): void {\n const signal = this.abortSignal\n\n if (signal?.aborted) {\n this.handleAbort()\n return\n }\n\n const onAbort = () => this.handleAbort()\n this.abortListener = onAbort\n signal?.addEventListener('abort', onAbort, { once: true })\n\n const reader = this.source.getReader()\n this.sourceReader = reader\n\n const pump = async () => {\n try {\n // Keep reading until upstream ends or we are stopped.\n while (!this.aborted && !this.released) {\n const { done, value } = await reader.read()\n if (done) break\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.aborted || this.released) break\n this.chunks.push(value)\n this.notify()\n }\n this.done = true\n } catch (err) {\n if (!this.aborted && !this.released) {\n this.error = err\n }\n this.done = true\n } finally {\n this.detachAbortListener()\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n if (this.sourceReader === reader) {\n this.sourceReader = null\n }\n this.notify()\n }\n }\n\n pump()\n }\n\n private detachAbortListener(): void {\n const signal = this.abortSignal\n const listener = this.abortListener\n if (signal && listener) {\n signal.removeEventListener('abort', listener)\n }\n this.abortListener = null\n }\n\n private cancelSource(reason: unknown): void {\n const reader = this.sourceReader\n this.sourceReader = null\n\n try {\n reader?.cancel(reason).catch(() => {})\n } catch {\n // Ignore\n }\n }\n\n private handleAbort(): void {\n if (this.aborted) return\n this.aborted = true\n this.done = true\n\n // Try to stop upstream work immediately.\n // Cancellation during an abort can throw synchronously in some runtimes\n // (eg when the underlying cancel algorithm throws). Never let that escape\n // an AbortSignal event handler.\n const reason =\n this.abortSignal?.reason ?? new Error('ReplayableStream aborted')\n\n this.detachAbortListener()\n this.abortSignal = undefined\n this.cancelSource(reason)\n\n this.chunks = [] // Free memory immediately on abort\n this.released = true\n this.notify()\n }\n\n private notify(): void {\n if (this.waiter) {\n this.waiter.resolve()\n this.waiter = null\n }\n }\n\n private wait(): Promise<void> {\n if (this.done || this.released) return Promise.resolve()\n if (!this.waiter) {\n this.waiter = Promise.withResolvers<void>()\n }\n return this.waiter.promise\n }\n\n /**\n * Explicitly release buffered chunks.\n * Call this when you know no more replay streams will be created.\n * After calling release(), createReplayStream() will return empty streams.\n */\n release(): void {\n if (this.released) return\n\n this.released = true\n this.chunks = []\n\n // Release should also stop upstream work and wake any waiters.\n // This is important when a Flight payload is never consumed again\n // (eg. cached loader data that evicts) to avoid retaining upstream resources.\n this.detachAbortListener()\n this.abortSignal = undefined\n this.cancelSource(new Error('ReplayableStream released'))\n this.notify()\n }\n\n /**\n * Check if the stream data has been released\n */\n isReleased(): boolean {\n return this.released\n }\n\n /**\n * Create an independent replay stream. Each call returns a fresh reader\n * that starts from the beginning of the buffered data.\n *\n * If the stream has been released, returns a stream that closes immediately.\n */\n createReplayStream(): ReadableStream<T> {\n if (this.released) {\n return new ReadableStream<T>({\n start(controller) {\n controller.close()\n },\n })\n }\n\n let index = 0\n\n return new ReadableStream<T>({\n pull: async (controller) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n if (this.released) {\n controller.close()\n return\n }\n\n if (index < this.chunks.length) {\n controller.enqueue(this.chunks[index++] as T)\n return\n }\n\n if (this.done) {\n if (this.error && !this.aborted) {\n controller.error(this.error)\n } else {\n controller.close()\n }\n return\n }\n\n await this.wait()\n }\n },\n cancel: () => {\n // No-op: consumers canceling a replay should not cancel upstream.\n // Upstream cancellation is controlled by abort/release.\n },\n })\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"RscNodeRenderer.js","names":[],"sources":["../../src/RscNodeRenderer.tsx"],"sourcesContent":["'use client'\n\nimport { Suspense } from 'react'\nimport ReactDOM from 'react-dom'\n\nimport {\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n} from './ServerComponentTypes'\n\nfunction EmptyFallback() {\n return null\n}\n\nfunction RscNodeRenderInner({\n getTree,\n path,\n}: {\n getTree: () => unknown\n path: Array<string>\n}): React.ReactNode {\n let tree: unknown = getTree()\n\n for (const key of path) {\n if (tree === null || tree === undefined) return null\n if (typeof tree !== 'object') return null\n tree = (tree as Record<string, unknown>)[key]\n }\n\n if (tree === null || tree === undefined) return null\n\n // No SlotProvider - just return the tree directly\n return tree as React.ReactNode\n}\n\n/**\n * Renders a renderable RSC proxy without slot support.\n * Used internally by the renderable proxy's $$typeof/type masquerade.\n */\nexport function RscNodeRenderer({ data }: { data: any }): React.ReactNode {\n const cssHrefs = data[SERVER_COMPONENT_CSS_HREFS] as\n | ReadonlySet<string>\n | undefined\n const jsPreloads = data[SERVER_COMPONENT_JS_PRELOADS] as\n | ReadonlySet<string>\n | undefined\n\n const path = (data[RSC_PROXY_PATH] as Array<string> | undefined) ?? []\n\n const getTree = data[RSC_PROXY_GET_TREE] as (() => unknown) | undefined\n if (!getTree) {\n throw new Error(\n '[tanstack/start] RscNodeRenderer missing getTree on RSC data.',\n )\n }\n\n for (const href of cssHrefs ?? []) {\n ReactDOM.preinit(href, { as: 'style', precedence: 'high' })\n }\n\n if (jsPreloads) {\n for (const href of jsPreloads) {\n ReactDOM.preloadModule(href)\n }\n }\n\n return (\n <>\n <Suspense fallback={<EmptyFallback />}>\n <RscNodeRenderInner getTree={getTree} path={path} />\n </Suspense>\n </>\n )\n}\n"],"mappings":";;;;;;AAYA,SAAS,gBAAgB;AACvB,QAAO;;AAGT,SAAS,mBAAmB,EAC1B,SACA,QAIkB;CAClB,IAAI,OAAgB,SAAS;AAE7B,MAAK,MAAM,OAAO,MAAM;AACtB,MAAI,SAAS,QAAQ,SAAS,KAAA,EAAW,QAAO;AAChD,MAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAQ,KAAiC;;AAG3C,KAAI,SAAS,QAAQ,SAAS,KAAA,EAAW,QAAO;AAGhD,QAAO;;;;;;AAOT,SAAgB,gBAAgB,EAAE,QAAwC;CACxE,MAAM,WAAW,KAAK;CAGtB,MAAM,aAAa,KAAK;CAIxB,MAAM,OAAQ,KAAK,mBAAiD,EAAE;CAEtE,MAAM,UAAU,KAAK;AACrB,KAAI,CAAC,QACH,OAAM,IAAI,MACR,gEACD;AAGH,MAAK,MAAM,QAAQ,YAAY,EAAE,CAC/B,UAAS,QAAQ,MAAM;EAAE,IAAI;EAAS,YAAY;EAAQ,CAAC;AAG7D,KAAI,WACF,MAAK,MAAM,QAAQ,WACjB,UAAS,cAAc,KAAK;AAIhC,QACE,oBAAA,UAAA,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,eAAD,EAAiB,CAAA;YACnC,oBAAC,oBAAD;GAA6B;GAAe;GAAQ,CAAA;EAC3C,CAAA,EACV,CAAA"}
1
+ {"version":3,"file":"RscNodeRenderer.js","names":[],"sources":["../../src/RscNodeRenderer.tsx"],"sourcesContent":["'use client'\n\nimport { Suspense } from 'react'\nimport ReactDOM from 'react-dom'\n\nimport {\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n} from './ServerComponentTypes'\n\nfunction EmptyFallback() {\n return null\n}\n\nfunction RscNodeRenderInner({\n getTree,\n path,\n}: {\n getTree: () => unknown\n path: Array<string>\n}): React.ReactNode {\n let tree: unknown = getTree()\n\n for (const key of path) {\n if (tree === null || tree === undefined) return null\n if (typeof tree !== 'object') return null\n tree = (tree as Record<string, unknown>)[key]\n }\n\n if (tree === null || tree === undefined) return null\n\n // No SlotProvider - just return the tree directly\n return tree as React.ReactNode\n}\n\n/**\n * Renders a renderable RSC proxy without slot support.\n * Used internally by the renderable proxy's $$typeof/type masquerade.\n */\nexport function RscNodeRenderer({ data }: { data: any }): React.ReactNode {\n const cssHrefs = data[SERVER_COMPONENT_CSS_HREFS] as\n | ReadonlySet<string>\n | undefined\n const jsPreloads = data[SERVER_COMPONENT_JS_PRELOADS] as\n | ReadonlySet<string>\n | undefined\n\n const path = (data[RSC_PROXY_PATH] as Array<string> | undefined) ?? []\n\n const getTree = data[RSC_PROXY_GET_TREE] as (() => unknown) | undefined\n if (!getTree) {\n throw new Error(\n '[tanstack/start] RscNodeRenderer missing getTree on RSC data.',\n )\n }\n\n for (const href of cssHrefs ?? []) {\n ReactDOM.preinit(href, { as: 'style', precedence: 'high' })\n }\n\n if (jsPreloads) {\n for (const href of jsPreloads) {\n ReactDOM.preloadModule(href)\n }\n }\n\n return (\n <>\n <Suspense fallback={<EmptyFallback />}>\n <RscNodeRenderInner getTree={getTree} path={path} />\n </Suspense>\n </>\n )\n}\n"],"mappings":";;;;;;AAYA,SAAS,gBAAgB;CACvB,OAAO;AACT;AAEA,SAAS,mBAAmB,EAC1B,SACA,QAIkB;CAClB,IAAI,OAAgB,QAAQ;CAE5B,KAAK,MAAM,OAAO,MAAM;EACtB,IAAI,SAAS,QAAQ,SAAS,KAAA,GAAW,OAAO;EAChD,IAAI,OAAO,SAAS,UAAU,OAAO;EACrC,OAAQ,KAAiC;CAC3C;CAEA,IAAI,SAAS,QAAQ,SAAS,KAAA,GAAW,OAAO;CAGhD,OAAO;AACT;;;;;AAMA,SAAgB,gBAAgB,EAAE,QAAwC;CACxE,MAAM,WAAW,KAAK;CAGtB,MAAM,aAAa,KAAK;CAIxB,MAAM,OAAQ,KAAK,mBAAiD,CAAC;CAErE,MAAM,UAAU,KAAK;CACrB,IAAI,CAAC,SACH,MAAM,IAAI,MACR,+DACF;CAGF,KAAK,MAAM,QAAQ,YAAY,CAAC,GAC9B,SAAS,QAAQ,MAAM;EAAE,IAAI;EAAS,YAAY;CAAO,CAAC;CAG5D,IAAI,YACF,KAAK,MAAM,QAAQ,YACjB,SAAS,cAAc,IAAI;CAI/B,OACE,oBAAA,UAAA,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU,oBAAC,eAAD,CAAgB,CAAA;YAClC,oBAAC,oBAAD;GAA6B;GAAe;EAAO,CAAA;CAC3C,CAAA,EACV,CAAA;AAEN"}
@@ -1 +1 @@
1
- {"version":3,"file":"ServerComponentTypes.js","names":[],"sources":["../../src/ServerComponentTypes.ts"],"sourcesContent":["import type {\n Constrain,\n LooseAsyncReturnType,\n LooseReturnType,\n ValidateSerializable,\n} from '@tanstack/router-core'\nimport type { ComponentProps, ComponentType } from 'react'\n\nexport interface ServerComponentStream {\n createReplayStream: () => ReadableStream<Uint8Array>\n}\n\n// Symbol to attach stream to component for serialization\nexport const SERVER_COMPONENT_STREAM = Symbol.for('tanstack.rsc.stream')\n\n// Symbol to attach collected CSS hrefs to component\nexport const SERVER_COMPONENT_CSS_HREFS = Symbol.for('tanstack.rsc.cssHrefs')\n\n// Symbol to attach collected JS modulepreload hrefs to component\nexport const SERVER_COMPONENT_JS_PRELOADS = Symbol.for(\n 'tanstack.rsc.jsPreloads',\n)\n\n// Symbol to attach a nested selection path to the RSC data proxy\nexport const RSC_PROXY_PATH = Symbol.for('tanstack.rsc.path')\n\n// Symbol to attach the root tree getter to every nested proxy\nexport const RSC_PROXY_GET_TREE = Symbol.for('tanstack.rsc.getTree')\n\n// Symbol to mark a proxy as \"renderable\" (for renderServerComponent output)\n// When true: from renderServerComponent (directly renderable)\n// When false/undefined: from createCompositeComponent (needs <CompositeComponent src={...} />)\nexport const RENDERABLE_RSC = Symbol.for('tanstack.rsc.renderable')\n\n// Dev-only: collected slot usage data for devtools (client-side cache)\nexport const RSC_SLOT_USAGES = Symbol.for('tanstack.rsc.slotUsages')\n\n// Dev-only: stream of slot usage preview events for devtools\nexport const RSC_SLOT_USAGES_STREAM = Symbol.for(\n 'tanstack.rsc.slotUsages.stream',\n)\n\nexport type RscSlotUsageEvent = {\n slot: string\n // Raw args passed to the slot call (must be serializable by the transport)\n args?: Array<any>\n}\n\n/**\n * Type guard to check if a value is a ServerComponent (Proxy with attached stream).\n * The value can be either an object (proxy target) or a function (stub for server functions).\n */\nexport function isServerComponent(\n value: unknown,\n): value is AnyCompositeComponent {\n if (value === null || value === undefined) return false\n if (typeof value !== 'object' && typeof value !== 'function') return false\n return (\n SERVER_COMPONENT_STREAM in value &&\n (value as any)[SERVER_COMPONENT_STREAM] !== undefined\n )\n}\n\nexport type ValidateCompositeComponent<TComp> = Constrain<\n TComp,\n (\n props: ValidateCompositeComponentProps<TComp>,\n ) => ValidateCompositeComponentReturnType<TComp>\n>\n\nexport type ValidateCompositeComponentProps<TComp> = unknown extends TComp\n ? TComp\n : ValidateCompositeComponentPropsObject<CompositeComponentProps<TComp>>\n\nexport type ValidateCompositeComponentPropsObject<TProps> =\n unknown extends TProps\n ? TProps\n : {\n [TKey in keyof TProps]: ValidateCompositeComponentProp<TProps[TKey]>\n }\n\nexport type CompositeComponentProps<TComp> = TComp extends (\n props: infer TProps,\n) => any\n ? TProps\n : unknown\n\nexport type ValidateCompositeComponentProp<TProp> = TProp extends (\n ...args: Array<any>\n) => any\n ? (...args: ValidateReactSerializable<Parameters<TProp>>) => React.ReactNode\n : TProp extends ComponentType<any>\n ? ComponentType<ValidateReactSerializable<ComponentProps<TProp>>>\n : TProp extends React.ReactNode\n ? TProp\n : React.ReactNode\n\nexport type ValidateReactSerializable<T> = ValidateSerializable<\n T,\n ReactSerializable\n>\n\nexport type ReactSerializable =\n | number\n | string\n | bigint\n | boolean\n | null\n | undefined\n | React.ReactNode\n\nexport type ValidateCompositeComponentReturnType<TComp> = unknown extends TComp\n ? React.ReactNode\n : ValidateCompositeComponentResult<LooseReturnType<TComp>>\n\nexport type ValidateCompositeComponentResult<TNode> =\n ValidateServerComponentResult<TNode>\n\nexport type ValidateServerComponentResult<TNode> =\n TNode extends Promise<any>\n ? ValidateCompositeComponentPromiseResult<TNode>\n : TNode extends React.ReactNode\n ? TNode\n : TNode extends (...args: Array<any>) => any\n ? React.ReactNode\n : TNode extends object\n ? ValidateCompositeComponentObjectResult<TNode>\n : React.ReactNode\n\nexport type ValidateCompositeComponentPromiseResult<TPromise> =\n TPromise extends Promise<infer T>\n ? Promise<ValidateCompositeComponentResult<T>>\n : never\n\nexport type ValidateCompositeComponentObjectResult<TObject> = {\n [TKey in keyof TObject]: ValidateCompositeComponentResult<TObject[TKey]>\n}\n\nexport type CompositeComponentResult<TComp> = CompositeComponentBuilder<\n TComp,\n LooseAsyncReturnType<TComp>\n>\n\nexport type CompositeComponentBuilder<TComp, TReturn> =\n TReturn extends React.ReactNode\n ? CompositeComponent<TComp, TReturn>\n : {\n [TKey in keyof TReturn]: CompositeComponentBuilder<TComp, TReturn[TKey]>\n }\n\nexport interface CompositeComponent<in out TComp, in out TReturn> {\n '~types': {\n props: CompositeComponentProps<TComp>\n return: TReturn\n }\n\n [SERVER_COMPONENT_STREAM]?: ServerComponentStream\n\n /**\n * Root decoded tree getter.\n */\n [RSC_PROXY_GET_TREE]?: () => unknown\n /**\n * Nested selection path (eg ['content','Stats']).\n * Used by <CompositeComponent/> to render a sub-tree.\n */\n [RSC_PROXY_PATH]?: Array<string>\n /**\n * CSS hrefs collected from the RSC stream.\n * Can be used for preloading in <head> or emitting 103 Early Hints.\n */\n [SERVER_COMPONENT_CSS_HREFS]?: ReadonlySet<string>\n\n /**\n * JS hrefs collected from the RSC stream.\n * Emitted as modulepreload links only if the decoded tree is rendered in SSR.\n */\n [SERVER_COMPONENT_JS_PRELOADS]?: ReadonlySet<string>\n\n /**\n * Dev-only: async stream of slot usage preview events.\n * Used by devtools to show slot names and previewed call args without\n * buffering/draining the Flight stream.\n */\n [RSC_SLOT_USAGES_STREAM]?: ReadableStream<RscSlotUsageEvent>\n}\n\nexport type ValidateRenderableServerComponent<TNode> =\n ValidateServerComponentResult<TNode>\n\nexport type RenderableServerComponentBuilder<T> = T extends React.ReactNode\n ? RenderableServerComponent<T>\n : { [TKey in keyof T]: RenderableServerComponentBuilder<T[TKey]> }\n\nexport type RenderableServerComponent<TNode extends React.ReactNode> = TNode &\n RenderableServerComponentAttributes<TNode>\n\nexport interface RenderableServerComponentAttributes<TNode> {\n '~types': {\n node: TNode\n }\n [SERVER_COMPONENT_STREAM]: ServerComponentStream\n [RENDERABLE_RSC]: true\n}\n\ndeclare module '@tanstack/router-core' {\n export interface SerializableExtensions {\n CompositeComponent: AnyCompositeComponent\n RenderableServerComponent: AnyRenderableServerComponent\n }\n}\n\nexport type AnyCompositeComponent = CompositeComponent<any, any>\n\nexport type AnyRenderableServerComponent =\n RenderableServerComponentAttributes<any>\n"],"mappings":";AAaA,IAAa,0BAA0B,OAAO,IAAI,sBAAsB;AAGxE,IAAa,6BAA6B,OAAO,IAAI,wBAAwB;AAG7E,IAAa,+BAA+B,OAAO,IACjD,0BACD;AAGD,IAAa,iBAAiB,OAAO,IAAI,oBAAoB;AAG7D,IAAa,qBAAqB,OAAO,IAAI,uBAAuB;AAKpE,IAAa,iBAAiB,OAAO,IAAI,0BAA0B;AAGnE,IAAa,kBAAkB,OAAO,IAAI,0BAA0B;AAGpE,IAAa,yBAAyB,OAAO,IAC3C,iCACD;;;;;AAYD,SAAgB,kBACd,OACgC;AAChC,KAAI,UAAU,QAAQ,UAAU,KAAA,EAAW,QAAO;AAClD,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAY,QAAO;AACrE,QACE,2BAA2B,SAC1B,MAAc,6BAA6B,KAAA"}
1
+ {"version":3,"file":"ServerComponentTypes.js","names":[],"sources":["../../src/ServerComponentTypes.ts"],"sourcesContent":["import type {\n Constrain,\n LooseAsyncReturnType,\n LooseReturnType,\n ValidateSerializable,\n} from '@tanstack/router-core'\nimport type { ComponentProps, ComponentType } from 'react'\n\nexport interface ServerComponentStream {\n createReplayStream: () => ReadableStream<Uint8Array>\n}\n\n// Symbol to attach stream to component for serialization\nexport const SERVER_COMPONENT_STREAM = Symbol.for('tanstack.rsc.stream')\n\n// Symbol to attach collected CSS hrefs to component\nexport const SERVER_COMPONENT_CSS_HREFS = Symbol.for('tanstack.rsc.cssHrefs')\n\n// Symbol to attach collected JS modulepreload hrefs to component\nexport const SERVER_COMPONENT_JS_PRELOADS = Symbol.for(\n 'tanstack.rsc.jsPreloads',\n)\n\n// Symbol to attach a nested selection path to the RSC data proxy\nexport const RSC_PROXY_PATH = Symbol.for('tanstack.rsc.path')\n\n// Symbol to attach the root tree getter to every nested proxy\nexport const RSC_PROXY_GET_TREE = Symbol.for('tanstack.rsc.getTree')\n\n// Symbol to mark a proxy as \"renderable\" (for renderServerComponent output)\n// When true: from renderServerComponent (directly renderable)\n// When false/undefined: from createCompositeComponent (needs <CompositeComponent src={...} />)\nexport const RENDERABLE_RSC = Symbol.for('tanstack.rsc.renderable')\n\n// Dev-only: collected slot usage data for devtools (client-side cache)\nexport const RSC_SLOT_USAGES = Symbol.for('tanstack.rsc.slotUsages')\n\n// Dev-only: stream of slot usage preview events for devtools\nexport const RSC_SLOT_USAGES_STREAM = Symbol.for(\n 'tanstack.rsc.slotUsages.stream',\n)\n\nexport type RscSlotUsageEvent = {\n slot: string\n // Raw args passed to the slot call (must be serializable by the transport)\n args?: Array<any>\n}\n\n/**\n * Type guard to check if a value is a ServerComponent (Proxy with attached stream).\n * The value can be either an object (proxy target) or a function (stub for server functions).\n */\nexport function isServerComponent(\n value: unknown,\n): value is AnyCompositeComponent {\n if (value === null || value === undefined) return false\n if (typeof value !== 'object' && typeof value !== 'function') return false\n return (\n SERVER_COMPONENT_STREAM in value &&\n (value as any)[SERVER_COMPONENT_STREAM] !== undefined\n )\n}\n\nexport type ValidateCompositeComponent<TComp> = Constrain<\n TComp,\n (\n props: ValidateCompositeComponentProps<TComp>,\n ) => ValidateCompositeComponentReturnType<TComp>\n>\n\nexport type ValidateCompositeComponentProps<TComp> = unknown extends TComp\n ? TComp\n : ValidateCompositeComponentPropsObject<CompositeComponentProps<TComp>>\n\nexport type ValidateCompositeComponentPropsObject<TProps> =\n unknown extends TProps\n ? TProps\n : {\n [TKey in keyof TProps]: ValidateCompositeComponentProp<TProps[TKey]>\n }\n\nexport type CompositeComponentProps<TComp> = TComp extends (\n props: infer TProps,\n) => any\n ? TProps\n : unknown\n\nexport type ValidateCompositeComponentProp<TProp> = TProp extends (\n ...args: Array<any>\n) => any\n ? (...args: ValidateReactSerializable<Parameters<TProp>>) => React.ReactNode\n : TProp extends ComponentType<any>\n ? ComponentType<ValidateReactSerializable<ComponentProps<TProp>>>\n : TProp extends React.ReactNode\n ? TProp\n : React.ReactNode\n\nexport type ValidateReactSerializable<T> = ValidateSerializable<\n T,\n ReactSerializable\n>\n\nexport type ReactSerializable =\n | number\n | string\n | bigint\n | boolean\n | null\n | undefined\n | React.ReactNode\n\nexport type ValidateCompositeComponentReturnType<TComp> = unknown extends TComp\n ? React.ReactNode\n : ValidateCompositeComponentResult<LooseReturnType<TComp>>\n\nexport type ValidateCompositeComponentResult<TNode> =\n ValidateServerComponentResult<TNode>\n\nexport type ValidateServerComponentResult<TNode> =\n TNode extends Promise<any>\n ? ValidateCompositeComponentPromiseResult<TNode>\n : TNode extends React.ReactNode\n ? TNode\n : TNode extends (...args: Array<any>) => any\n ? React.ReactNode\n : TNode extends object\n ? ValidateCompositeComponentObjectResult<TNode>\n : React.ReactNode\n\nexport type ValidateCompositeComponentPromiseResult<TPromise> =\n TPromise extends Promise<infer T>\n ? Promise<ValidateCompositeComponentResult<T>>\n : never\n\nexport type ValidateCompositeComponentObjectResult<TObject> = {\n [TKey in keyof TObject]: ValidateCompositeComponentResult<TObject[TKey]>\n}\n\nexport type CompositeComponentResult<TComp> = CompositeComponentBuilder<\n TComp,\n LooseAsyncReturnType<TComp>\n>\n\nexport type CompositeComponentBuilder<TComp, TReturn> =\n TReturn extends React.ReactNode\n ? CompositeComponent<TComp, TReturn>\n : {\n [TKey in keyof TReturn]: CompositeComponentBuilder<TComp, TReturn[TKey]>\n }\n\nexport interface CompositeComponent<in out TComp, in out TReturn> {\n '~types': {\n props: CompositeComponentProps<TComp>\n return: TReturn\n }\n\n [SERVER_COMPONENT_STREAM]?: ServerComponentStream\n\n /**\n * Root decoded tree getter.\n */\n [RSC_PROXY_GET_TREE]?: () => unknown\n /**\n * Nested selection path (eg ['content','Stats']).\n * Used by <CompositeComponent/> to render a sub-tree.\n */\n [RSC_PROXY_PATH]?: Array<string>\n /**\n * CSS hrefs collected from the RSC stream.\n * Can be used for preloading in <head> or emitting 103 Early Hints.\n */\n [SERVER_COMPONENT_CSS_HREFS]?: ReadonlySet<string>\n\n /**\n * JS hrefs collected from the RSC stream.\n * Emitted as modulepreload links only if the decoded tree is rendered in SSR.\n */\n [SERVER_COMPONENT_JS_PRELOADS]?: ReadonlySet<string>\n\n /**\n * Dev-only: async stream of slot usage preview events.\n * Used by devtools to show slot names and previewed call args without\n * buffering/draining the Flight stream.\n */\n [RSC_SLOT_USAGES_STREAM]?: ReadableStream<RscSlotUsageEvent>\n}\n\nexport type ValidateRenderableServerComponent<TNode> =\n ValidateServerComponentResult<TNode>\n\nexport type RenderableServerComponentBuilder<T> = T extends React.ReactNode\n ? RenderableServerComponent<T>\n : { [TKey in keyof T]: RenderableServerComponentBuilder<T[TKey]> }\n\nexport type RenderableServerComponent<TNode extends React.ReactNode> = TNode &\n RenderableServerComponentAttributes<TNode>\n\nexport interface RenderableServerComponentAttributes<TNode> {\n '~types': {\n node: TNode\n }\n [SERVER_COMPONENT_STREAM]: ServerComponentStream\n [RENDERABLE_RSC]: true\n}\n\ndeclare module '@tanstack/router-core' {\n export interface SerializableExtensions {\n CompositeComponent: AnyCompositeComponent\n RenderableServerComponent: AnyRenderableServerComponent\n }\n}\n\nexport type AnyCompositeComponent = CompositeComponent<any, any>\n\nexport type AnyRenderableServerComponent =\n RenderableServerComponentAttributes<any>\n"],"mappings":";AAaA,IAAa,0BAA0B,OAAO,IAAI,qBAAqB;AAGvE,IAAa,6BAA6B,OAAO,IAAI,uBAAuB;AAG5E,IAAa,+BAA+B,OAAO,IACjD,yBACF;AAGA,IAAa,iBAAiB,OAAO,IAAI,mBAAmB;AAG5D,IAAa,qBAAqB,OAAO,IAAI,sBAAsB;AAKnE,IAAa,iBAAiB,OAAO,IAAI,yBAAyB;AAGlE,IAAa,kBAAkB,OAAO,IAAI,yBAAyB;AAGnE,IAAa,yBAAyB,OAAO,IAC3C,gCACF;;;;;AAYA,SAAgB,kBACd,OACgC;CAChC,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;CAClD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAAY,OAAO;CACrE,OACE,2BAA2B,SAC1B,MAAc,6BAA6B,KAAA;AAEhD"}
@@ -1 +1 @@
1
- {"version":3,"file":"SlotContext.js","names":[],"sources":["../../src/SlotContext.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, use } from 'react'\nimport type { SlotImplementations } from './types'\n\nexport interface SlotContextValue {\n implementations: SlotImplementations\n strict: boolean\n}\n\nconst SlotContext = createContext<SlotContextValue | null>(null)\n\n/**\n * Hook to access slot implementations from within ClientSlot.\n */\nexport function useSlotContext(): SlotContextValue | null {\n return use(SlotContext)\n}\n\nexport interface SlotProviderProps {\n implementations: SlotImplementations\n strict?: boolean\n children?: React.ReactNode\n}\n\n/**\n * SlotProvider - makes slot implementations available to ClientSlot components.\n *\n * Must wrap the decoded RSC content so that ClientSlot components can\n * access their slot implementations via React Context.\n */\nexport function SlotProvider({\n implementations,\n strict,\n children,\n}: SlotProviderProps) {\n return (\n <SlotContext value={{ implementations, strict: strict ?? false }}>\n {children}\n </SlotContext>\n )\n}\n"],"mappings":";;;;AAUA,IAAM,cAAc,cAAuC,KAAK;;;;AAKhE,SAAgB,iBAA0C;AACxD,QAAO,IAAI,YAAY;;;;;;;;AAezB,SAAgB,aAAa,EAC3B,iBACA,QACA,YACoB;AACpB,QACE,oBAAC,aAAD;EAAa,OAAO;GAAE;GAAiB,QAAQ,UAAU;GAAO;EAC7D;EACW,CAAA"}
1
+ {"version":3,"file":"SlotContext.js","names":[],"sources":["../../src/SlotContext.tsx"],"sourcesContent":["'use client'\n\nimport { createContext, use } from 'react'\nimport type { SlotImplementations } from './types'\n\nexport interface SlotContextValue {\n implementations: SlotImplementations\n strict: boolean\n}\n\nconst SlotContext = createContext<SlotContextValue | null>(null)\n\n/**\n * Hook to access slot implementations from within ClientSlot.\n */\nexport function useSlotContext(): SlotContextValue | null {\n return use(SlotContext)\n}\n\nexport interface SlotProviderProps {\n implementations: SlotImplementations\n strict?: boolean\n children?: React.ReactNode\n}\n\n/**\n * SlotProvider - makes slot implementations available to ClientSlot components.\n *\n * Must wrap the decoded RSC content so that ClientSlot components can\n * access their slot implementations via React Context.\n */\nexport function SlotProvider({\n implementations,\n strict,\n children,\n}: SlotProviderProps) {\n return (\n <SlotContext value={{ implementations, strict: strict ?? false }}>\n {children}\n </SlotContext>\n )\n}\n"],"mappings":";;;;AAUA,IAAM,cAAc,cAAuC,IAAI;;;;AAK/D,SAAgB,iBAA0C;CACxD,OAAO,IAAI,WAAW;AACxB;;;;;;;AAcA,SAAgB,aAAa,EAC3B,iBACA,QACA,YACoB;CACpB,OACE,oBAAC,aAAD;EAAa,OAAO;GAAE;GAAiB,QAAQ,UAAU;EAAM;EAC5D;CACU,CAAA;AAEjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"awaitLazyElements.js","names":[],"sources":["../../src/awaitLazyElements.ts"],"sourcesContent":["import { ReactElement, ReactLazy, ReactSuspense } from './reactSymbols'\n\n/**\n * Optional callback for collecting CSS hrefs during tree traversal.\n * Only called server-side when processing <link rel=\"stylesheet\" data-rsc-css-href>\n */\nexport type CssHrefCollector = (href: string) => void\n\n/**\n * Yields pending lazy element payloads from a tree, stopping at Suspense boundaries.\n * Also collects CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href> elements.\n */\nfunction* findPendingLazyPayloads(\n obj: unknown,\n seen = new Set(),\n cssCollector?: CssHrefCollector,\n): Generator<PromiseLike<unknown>> {\n if (!obj || typeof obj !== 'object') return\n if (seen.has(obj)) return\n seen.add(obj)\n\n const el = obj as any\n\n // Stop at Suspense boundaries - lazy elements inside are intentionally deferred\n if (el.$$typeof === ReactElement && el.type === ReactSuspense) {\n return\n }\n\n // Collect CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href>\n // The active RSC bundler adapter injects these for CSS module imports\n if (\n el.$$typeof === ReactElement &&\n el.type === 'link' &&\n el.props?.rel === 'stylesheet'\n ) {\n const cssHref = el.props['data-rsc-css-href'] as string | undefined\n if (cssHref && cssCollector) {\n cssCollector(cssHref)\n }\n }\n\n // Yield pending lazy element payload\n if (el.$$typeof === ReactLazy) {\n const payload = el._payload\n if (\n payload &&\n typeof payload === 'object' &&\n (payload.status === 'pending' || payload.status === 'blocked') &&\n typeof payload.then === 'function'\n ) {\n yield payload\n }\n }\n\n // Recurse into children\n if (Array.isArray(obj)) {\n for (const item of obj) {\n yield* findPendingLazyPayloads(item, seen, cssCollector)\n }\n } else {\n for (const key of Object.keys(obj)) {\n if (key !== '_owner' && key !== '_store') {\n yield* findPendingLazyPayloads(el[key], seen, cssCollector)\n }\n }\n }\n}\n\n/**\n * Wait for all lazy elements in a tree to be resolved.\n * This ensures client component chunks are fully loaded before rendering,\n * preventing Suspense boundaries from flashing during SWR navigation.\n *\n * Also collects CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href>\n * elements for preloading in <head>.\n *\n * @param tree - The tree to process\n * @param cssCollector - Optional callback to collect CSS hrefs (server-only)\n */\nexport async function awaitLazyElements(\n tree: unknown,\n cssCollector?: CssHrefCollector,\n): Promise<void> {\n for (const payload of findPendingLazyPayloads(\n tree,\n new Set(),\n cssCollector,\n )) {\n await Promise.resolve(payload).catch(() => {})\n }\n}\n"],"mappings":";;;;;;AAYA,UAAU,wBACR,KACA,uBAAO,IAAI,KAAK,EAChB,cACiC;AACjC,KAAI,CAAC,OAAO,OAAO,QAAQ,SAAU;AACrC,KAAI,KAAK,IAAI,IAAI,CAAE;AACnB,MAAK,IAAI,IAAI;CAEb,MAAM,KAAK;AAGX,KAAI,GAAG,aAAa,gBAAgB,GAAG,SAAS,cAC9C;AAKF,KACE,GAAG,aAAa,gBAChB,GAAG,SAAS,UACZ,GAAG,OAAO,QAAQ,cAClB;EACA,MAAM,UAAU,GAAG,MAAM;AACzB,MAAI,WAAW,aACb,cAAa,QAAQ;;AAKzB,KAAI,GAAG,aAAa,WAAW;EAC7B,MAAM,UAAU,GAAG;AACnB,MACE,WACA,OAAO,YAAY,aAClB,QAAQ,WAAW,aAAa,QAAQ,WAAW,cACpD,OAAO,QAAQ,SAAS,WAExB,OAAM;;AAKV,KAAI,MAAM,QAAQ,IAAI,CACpB,MAAK,MAAM,QAAQ,IACjB,QAAO,wBAAwB,MAAM,MAAM,aAAa;KAG1D,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,KAAI,QAAQ,YAAY,QAAQ,SAC9B,QAAO,wBAAwB,GAAG,MAAM,MAAM,aAAa;;;;;;;;;;;;;AAiBnE,eAAsB,kBACpB,MACA,cACe;AACf,MAAK,MAAM,WAAW,wBACpB,sBACA,IAAI,KAAK,EACT,aACD,CACC,OAAM,QAAQ,QAAQ,QAAQ,CAAC,YAAY,GAAG"}
1
+ {"version":3,"file":"awaitLazyElements.js","names":[],"sources":["../../src/awaitLazyElements.ts"],"sourcesContent":["import { ReactElement, ReactLazy, ReactSuspense } from './reactSymbols'\n\n/**\n * Optional callback for collecting CSS hrefs during tree traversal.\n * Only called server-side when processing <link rel=\"stylesheet\" data-rsc-css-href>\n */\nexport type CssHrefCollector = (href: string) => void\n\n/**\n * Yields pending lazy element payloads from a tree, stopping at Suspense boundaries.\n * Also collects CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href> elements.\n */\nfunction* findPendingLazyPayloads(\n obj: unknown,\n seen = new Set(),\n cssCollector?: CssHrefCollector,\n): Generator<PromiseLike<unknown>> {\n if (!obj || typeof obj !== 'object') return\n if (seen.has(obj)) return\n seen.add(obj)\n\n const el = obj as any\n\n // Stop at Suspense boundaries - lazy elements inside are intentionally deferred\n if (el.$$typeof === ReactElement && el.type === ReactSuspense) {\n return\n }\n\n // Collect CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href>\n // The active RSC bundler adapter injects these for CSS module imports\n if (\n el.$$typeof === ReactElement &&\n el.type === 'link' &&\n el.props?.rel === 'stylesheet'\n ) {\n const cssHref = el.props['data-rsc-css-href'] as string | undefined\n if (cssHref && cssCollector) {\n cssCollector(cssHref)\n }\n }\n\n // Yield pending lazy element payload\n if (el.$$typeof === ReactLazy) {\n const payload = el._payload\n if (\n payload &&\n typeof payload === 'object' &&\n (payload.status === 'pending' || payload.status === 'blocked') &&\n typeof payload.then === 'function'\n ) {\n yield payload\n }\n }\n\n // Recurse into children\n if (Array.isArray(obj)) {\n for (const item of obj) {\n yield* findPendingLazyPayloads(item, seen, cssCollector)\n }\n } else {\n for (const key of Object.keys(obj)) {\n if (key !== '_owner' && key !== '_store') {\n yield* findPendingLazyPayloads(el[key], seen, cssCollector)\n }\n }\n }\n}\n\n/**\n * Wait for all lazy elements in a tree to be resolved.\n * This ensures client component chunks are fully loaded before rendering,\n * preventing Suspense boundaries from flashing during SWR navigation.\n *\n * Also collects CSS hrefs from <link rel=\"stylesheet\" data-rsc-css-href>\n * elements for preloading in <head>.\n *\n * @param tree - The tree to process\n * @param cssCollector - Optional callback to collect CSS hrefs (server-only)\n */\nexport async function awaitLazyElements(\n tree: unknown,\n cssCollector?: CssHrefCollector,\n): Promise<void> {\n for (const payload of findPendingLazyPayloads(\n tree,\n new Set(),\n cssCollector,\n )) {\n await Promise.resolve(payload).catch(() => {})\n }\n}\n"],"mappings":";;;;;;AAYA,UAAU,wBACR,KACA,uBAAO,IAAI,IAAI,GACf,cACiC;CACjC,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;CACrC,IAAI,KAAK,IAAI,GAAG,GAAG;CACnB,KAAK,IAAI,GAAG;CAEZ,MAAM,KAAK;CAGX,IAAI,GAAG,aAAa,gBAAgB,GAAG,SAAS,eAC9C;CAKF,IACE,GAAG,aAAa,gBAChB,GAAG,SAAS,UACZ,GAAG,OAAO,QAAQ,cAClB;EACA,MAAM,UAAU,GAAG,MAAM;EACzB,IAAI,WAAW,cACb,aAAa,OAAO;CAExB;CAGA,IAAI,GAAG,aAAa,WAAW;EAC7B,MAAM,UAAU,GAAG;EACnB,IACE,WACA,OAAO,YAAY,aAClB,QAAQ,WAAW,aAAa,QAAQ,WAAW,cACpD,OAAO,QAAQ,SAAS,YAExB,MAAM;CAEV;CAGA,IAAI,MAAM,QAAQ,GAAG,GACnB,KAAK,MAAM,QAAQ,KACjB,OAAO,wBAAwB,MAAM,MAAM,YAAY;MAGzD,KAAK,MAAM,OAAO,OAAO,KAAK,GAAG,GAC/B,IAAI,QAAQ,YAAY,QAAQ,UAC9B,OAAO,wBAAwB,GAAG,MAAM,MAAM,YAAY;AAIlE;;;;;;;;;;;;AAaA,eAAsB,kBACpB,MACA,cACe;CACf,KAAK,MAAM,WAAW,wBACpB,sBACA,IAAI,IAAI,GACR,YACF,GACE,MAAM,QAAQ,QAAQ,OAAO,EAAE,YAAY,CAAC,CAAC;AAEjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"createCompositeComponent.js","names":[],"sources":["../../src/createCompositeComponent.ts"],"sourcesContent":["import { createElement } from 'react'\nimport { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport { getRequest } from '@tanstack/start-server-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport { sanitizeSlotArgs } from './slotUsageSanitizer'\nimport { ReplayableStream } from './ReplayableStream'\nimport { ClientSlot } from './ClientSlot'\nimport {\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport { createRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n CompositeComponentResult,\n RscSlotUsageEvent,\n ServerComponentStream,\n ValidateCompositeComponent,\n} from './ServerComponentTypes'\nimport type { RscCssEnvelopeOptions } from './rscCssEnvelope'\n\nimport './rscSsrHandler' // Import for global declaration side effect\n\n/**\n * Creates a composite server component with slot support.\n *\n * Supports returning:\n * - A ReactNode directly\n * - An object structure with ReactNodes: accessed as `src.Foo`\n * - Nested structures: accessed as `src.x.Bar`\n *\n * Props that are functions become slots - they render as ClientSlot placeholders\n * in the RSC output, filled in by the consumer with actual implementations.\n *\n * The returned value is NOT directly renderable. Use `<CompositeComponent src={...} />`.\n *\n * @example\n * ```tsx\n * const src = await createCompositeComponent((props) => (\n * <div>\n * <header>{props.header('Dashboard')}</header>\n * <main>{props.children}</main>\n * </div>\n * ))\n *\n * // In route component\n * return (\n * <CompositeComponent src={src} header={(title) => <h1>{title}</h1>}>\n * <p>Main content</p>\n * </CompositeComponent>\n * )\n * ```\n */\nexport async function createCompositeComponent<TComp>(\n component: ValidateCompositeComponent<TComp>,\n options?: RscCssEnvelopeOptions,\n): Promise<CompositeComponentResult<TComp>> {\n const isDev = process.env.NODE_ENV === 'development'\n\n // Dev-only: stream slot usage events (slot + raw args)\n const slotUsagesEmitter = isDev\n ? createReadableStreamEmitter<RscSlotUsageEvent>()\n : null\n\n // Create a wrapper component that will be rendered inside React's Flight context.\n // This ensures React.cache works properly since the component is called during\n // renderToReadableStream's render phase, not before it.\n const { proxy: proxyProps } = createSlotProxy<{}>({\n onSlotCall: slotUsagesEmitter\n ? (name, args) => {\n const sanitizedArgs = sanitizeSlotArgs(args)\n slotUsagesEmitter.emit({\n slot: name,\n args: sanitizedArgs.length ? sanitizedArgs : undefined,\n })\n }\n : undefined,\n })\n\n // Wrapper that renders the user's component inside Flight render context\n async function ServerComponentWrapper() {\n return createRscCssEnvelope(\n await (component as React.FC)(proxyProps),\n options,\n )\n }\n\n // Render using createElement so React calls our component during Flight rendering\n // This is critical for React.cache to work - the component must be invoked\n // during renderToReadableStream's execution, not before\n const flightStream = renderToReadableStream(\n createElement(ServerComponentWrapper as any),\n )\n\n // Check if this is an SSR request (router) or a direct server function call\n const ctx = getStartContext({ throwIfNotFound: false })\n const isRouterRequest = ctx?.handlerType === 'router'\n const ssrHandler = globalThis.__RSC_SSR__\n\n // SSR path: buffer stream for replay, pre-decode for synchronous rendering\n if (isRouterRequest && ssrHandler) {\n const signal = getRequest().signal\n const stream = new ReplayableStream(flightStream, { signal })\n\n // Pre-decode during loader phase for synchronous SSR rendering\n const decoded = await ssrHandler.decode(stream)\n\n // For SSR we know decode fully consumed the Flight stream.\n slotUsagesEmitter?.close()\n\n return ssrHandler.createCompositeProxy(\n stream,\n decoded,\n slotUsagesEmitter?.stream,\n ) as CompositeComponentResult<TComp>\n }\n\n // Server function call path:\n // The serialization adapter will stream to the client.\n const monitoredFlightStream =\n isDev && slotUsagesEmitter\n ? wrapReadableStream(flightStream, {\n onDone: () => {\n slotUsagesEmitter.close()\n },\n onCancel: () => {\n slotUsagesEmitter.close()\n },\n onError: () => {\n slotUsagesEmitter.close()\n },\n })\n : flightStream\n\n return createCompositeHandle(monitoredFlightStream, {\n slotUsagesStream: slotUsagesEmitter?.stream,\n }) as CompositeComponentResult<TComp>\n}\n\n/**\n * Creates a composite handle for server function responses.\n * No proxy needed - the client will decode and create its own proxy.\n */\nfunction createCompositeHandle(\n flightStream: ReadableStream<Uint8Array>,\n options?: {\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n },\n): AnyCompositeComponent {\n // Simple single-use stream wrapper. For server function calls, the stream\n // is consumed exactly once by the serialization adapter for transport.\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => flightStream,\n }\n\n // Create a stub function with the stream attached for serialization.\n // This will never be rendered directly - it goes through serialization\n // which extracts the stream and sends it to the client.\n const stub = function CompositeComponentStub(): never {\n throw new Error(\n 'CompositeComponent from server function cannot be rendered on server. ' +\n 'It should be serialized and sent to the client.',\n )\n }\n\n ;(stub as any)[SERVER_COMPONENT_STREAM] = streamWrapper\n // Note: RENDERABLE_RSC is not set (or implicitly false), indicating this is a composite component\n\n if (options?.slotUsagesStream) {\n ;(stub as any)[RSC_SLOT_USAGES_STREAM] = options.slotUsagesStream\n }\n\n return stub as unknown as AnyCompositeComponent\n}\n\n/**\n * Base slot props type - functions that become ClientSlot placeholders\n */\ninterface SlotPropsBase {\n [key: string]:\n | ((...args: Array<any>) => React.ReactNode)\n | React.ReactNode\n | undefined\n children?: React.ReactNode\n}\n\ninterface SlotProxyResult<TSlotProps extends object> {\n proxy: TSlotProps & SlotPropsBase\n}\n\n/**\n * Proxy that turns property access into ClientSlot renders.\n * Also tracks accessed slot names for devtools.\n */\nfunction createSlotProxy<TSlotProps extends object>(options?: {\n onSlotCall?: (name: string, args: Array<any>) => void\n}): SlotProxyResult<TSlotProps> {\n const cache = new Map<string, (...args: Array<any>) => React.ReactNode>()\n\n const proxy = new Proxy({} as TSlotProps & SlotPropsBase, {\n get(_target, prop) {\n if (prop === 'then' || typeof prop !== 'string') return undefined\n\n if (prop === 'children') {\n options?.onSlotCall?.('children', [])\n return createElement(ClientSlot, { slot: 'children', args: [] })\n }\n\n let fn = cache.get(prop)\n if (!fn) {\n fn = (...args: Array<any>) => {\n options?.onSlotCall?.(prop, args)\n return createElement(ClientSlot, { slot: prop, args })\n }\n cache.set(prop, fn)\n }\n return fn\n },\n })\n\n return {\n proxy,\n }\n}\n\nfunction createReadableStreamEmitter<T>(): {\n stream: ReadableStream<T>\n emit: (value: T) => void\n close: () => void\n} {\n let closed = false\n const queue: Array<T> = []\n let controller: ReadableStreamDefaultController<T> | null = null\n\n const stream = new ReadableStream<T>({\n start(ctrl) {\n controller = ctrl\n for (const value of queue) {\n try {\n ctrl.enqueue(value)\n } catch {\n // Ignore\n }\n }\n queue.length = 0\n if (closed) {\n try {\n ctrl.close()\n } catch {\n // Ignore\n }\n }\n },\n cancel() {\n closed = true\n controller = null\n queue.length = 0\n },\n })\n\n const emit = (value: T) => {\n if (closed) return\n if (!controller) {\n queue.push(value)\n return\n }\n try {\n controller.enqueue(value)\n } catch {\n // Ignore\n }\n }\n\n const close = () => {\n if (closed) return\n closed = true\n if (controller) {\n try {\n controller.close()\n } catch {\n // Ignore\n }\n controller = null\n }\n }\n\n return { stream, emit, close }\n}\n\nfunction wrapReadableStream<T>(\n source: ReadableStream<T>,\n handlers: {\n onDone?: () => void\n onCancel?: () => void\n onError?: () => void\n },\n): ReadableStream<T> {\n const reader = source.getReader()\n let finished = false\n\n const finish = () => {\n if (finished) return\n finished = true\n handlers.onDone?.()\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n }\n\n return new ReadableStream<T>({\n async pull(controller) {\n try {\n const { value, done } = await reader.read()\n if (done) {\n controller.close()\n finish()\n return\n }\n controller.enqueue(value)\n } catch (err) {\n try {\n controller.error(err)\n } catch {\n // Ignore\n }\n handlers.onError?.()\n finish()\n }\n },\n async cancel(reason) {\n handlers.onCancel?.()\n try {\n await reader.cancel(reason)\n } catch {\n // Ignore\n }\n finish()\n },\n })\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createCompositeComponent.js","names":[],"sources":["../../src/createCompositeComponent.ts"],"sourcesContent":["import { createElement } from 'react'\nimport { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport { getRequest } from '@tanstack/start-server-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport { sanitizeSlotArgs } from './slotUsageSanitizer'\nimport { ReplayableStream } from './ReplayableStream'\nimport { ClientSlot } from './ClientSlot'\nimport {\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport { createRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n CompositeComponentResult,\n RscSlotUsageEvent,\n ServerComponentStream,\n ValidateCompositeComponent,\n} from './ServerComponentTypes'\nimport type { RscCssEnvelopeOptions } from './rscCssEnvelope'\n\nimport './rscSsrHandler' // Import for global declaration side effect\n\n/**\n * Creates a composite server component with slot support.\n *\n * Supports returning:\n * - A ReactNode directly\n * - An object structure with ReactNodes: accessed as `src.Foo`\n * - Nested structures: accessed as `src.x.Bar`\n *\n * Props that are functions become slots - they render as ClientSlot placeholders\n * in the RSC output, filled in by the consumer with actual implementations.\n *\n * The returned value is NOT directly renderable. Use `<CompositeComponent src={...} />`.\n *\n * @example\n * ```tsx\n * const src = await createCompositeComponent((props) => (\n * <div>\n * <header>{props.header('Dashboard')}</header>\n * <main>{props.children}</main>\n * </div>\n * ))\n *\n * // In route component\n * return (\n * <CompositeComponent src={src} header={(title) => <h1>{title}</h1>}>\n * <p>Main content</p>\n * </CompositeComponent>\n * )\n * ```\n */\nexport async function createCompositeComponent<TComp>(\n component: ValidateCompositeComponent<TComp>,\n options?: RscCssEnvelopeOptions,\n): Promise<CompositeComponentResult<TComp>> {\n const isDev = process.env.NODE_ENV === 'development'\n\n // Dev-only: stream slot usage events (slot + raw args)\n const slotUsagesEmitter = isDev\n ? createReadableStreamEmitter<RscSlotUsageEvent>()\n : null\n\n // Create a wrapper component that will be rendered inside React's Flight context.\n // This ensures React.cache works properly since the component is called during\n // renderToReadableStream's render phase, not before it.\n const { proxy: proxyProps } = createSlotProxy<{}>({\n onSlotCall: slotUsagesEmitter\n ? (name, args) => {\n const sanitizedArgs = sanitizeSlotArgs(args)\n slotUsagesEmitter.emit({\n slot: name,\n args: sanitizedArgs.length ? sanitizedArgs : undefined,\n })\n }\n : undefined,\n })\n\n // Wrapper that renders the user's component inside Flight render context\n async function ServerComponentWrapper() {\n return createRscCssEnvelope(\n await (component as React.FC)(proxyProps),\n options,\n )\n }\n\n // Render using createElement so React calls our component during Flight rendering\n // This is critical for React.cache to work - the component must be invoked\n // during renderToReadableStream's execution, not before\n const flightStream = renderToReadableStream(\n createElement(ServerComponentWrapper as any),\n )\n\n // Check if this is an SSR request (router) or a direct server function call\n const ctx = getStartContext({ throwIfNotFound: false })\n const isRouterRequest = ctx?.handlerType === 'router'\n const ssrHandler = globalThis.__RSC_SSR__\n\n // SSR path: buffer stream for replay, pre-decode for synchronous rendering\n if (isRouterRequest && ssrHandler) {\n const signal = getRequest().signal\n const stream = new ReplayableStream(flightStream, { signal })\n\n // Pre-decode during loader phase for synchronous SSR rendering\n const decoded = await ssrHandler.decode(stream)\n\n // For SSR we know decode fully consumed the Flight stream.\n slotUsagesEmitter?.close()\n\n return ssrHandler.createCompositeProxy(\n stream,\n decoded,\n slotUsagesEmitter?.stream,\n ) as CompositeComponentResult<TComp>\n }\n\n // Server function call path:\n // The serialization adapter will stream to the client.\n const monitoredFlightStream =\n isDev && slotUsagesEmitter\n ? wrapReadableStream(flightStream, {\n onDone: () => {\n slotUsagesEmitter.close()\n },\n onCancel: () => {\n slotUsagesEmitter.close()\n },\n onError: () => {\n slotUsagesEmitter.close()\n },\n })\n : flightStream\n\n return createCompositeHandle(monitoredFlightStream, {\n slotUsagesStream: slotUsagesEmitter?.stream,\n }) as CompositeComponentResult<TComp>\n}\n\n/**\n * Creates a composite handle for server function responses.\n * No proxy needed - the client will decode and create its own proxy.\n */\nfunction createCompositeHandle(\n flightStream: ReadableStream<Uint8Array>,\n options?: {\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n },\n): AnyCompositeComponent {\n // Simple single-use stream wrapper. For server function calls, the stream\n // is consumed exactly once by the serialization adapter for transport.\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => flightStream,\n }\n\n // Create a stub function with the stream attached for serialization.\n // This will never be rendered directly - it goes through serialization\n // which extracts the stream and sends it to the client.\n const stub = function CompositeComponentStub(): never {\n throw new Error(\n 'CompositeComponent from server function cannot be rendered on server. ' +\n 'It should be serialized and sent to the client.',\n )\n }\n\n ;(stub as any)[SERVER_COMPONENT_STREAM] = streamWrapper\n // Note: RENDERABLE_RSC is not set (or implicitly false), indicating this is a composite component\n\n if (options?.slotUsagesStream) {\n ;(stub as any)[RSC_SLOT_USAGES_STREAM] = options.slotUsagesStream\n }\n\n return stub as unknown as AnyCompositeComponent\n}\n\n/**\n * Base slot props type - functions that become ClientSlot placeholders\n */\ninterface SlotPropsBase {\n [key: string]:\n | ((...args: Array<any>) => React.ReactNode)\n | React.ReactNode\n | undefined\n children?: React.ReactNode\n}\n\ninterface SlotProxyResult<TSlotProps extends object> {\n proxy: TSlotProps & SlotPropsBase\n}\n\n/**\n * Proxy that turns property access into ClientSlot renders.\n * Also tracks accessed slot names for devtools.\n */\nfunction createSlotProxy<TSlotProps extends object>(options?: {\n onSlotCall?: (name: string, args: Array<any>) => void\n}): SlotProxyResult<TSlotProps> {\n const cache = new Map<string, (...args: Array<any>) => React.ReactNode>()\n\n const proxy = new Proxy({} as TSlotProps & SlotPropsBase, {\n get(_target, prop) {\n if (prop === 'then' || typeof prop !== 'string') return undefined\n\n if (prop === 'children') {\n options?.onSlotCall?.('children', [])\n return createElement(ClientSlot, { slot: 'children', args: [] })\n }\n\n let fn = cache.get(prop)\n if (!fn) {\n fn = (...args: Array<any>) => {\n options?.onSlotCall?.(prop, args)\n return createElement(ClientSlot, { slot: prop, args })\n }\n cache.set(prop, fn)\n }\n return fn\n },\n })\n\n return {\n proxy,\n }\n}\n\nfunction createReadableStreamEmitter<T>(): {\n stream: ReadableStream<T>\n emit: (value: T) => void\n close: () => void\n} {\n let closed = false\n const queue: Array<T> = []\n let controller: ReadableStreamDefaultController<T> | null = null\n\n const stream = new ReadableStream<T>({\n start(ctrl) {\n controller = ctrl\n for (const value of queue) {\n try {\n ctrl.enqueue(value)\n } catch {\n // Ignore\n }\n }\n queue.length = 0\n if (closed) {\n try {\n ctrl.close()\n } catch {\n // Ignore\n }\n }\n },\n cancel() {\n closed = true\n controller = null\n queue.length = 0\n },\n })\n\n const emit = (value: T) => {\n if (closed) return\n if (!controller) {\n queue.push(value)\n return\n }\n try {\n controller.enqueue(value)\n } catch {\n // Ignore\n }\n }\n\n const close = () => {\n if (closed) return\n closed = true\n if (controller) {\n try {\n controller.close()\n } catch {\n // Ignore\n }\n controller = null\n }\n }\n\n return { stream, emit, close }\n}\n\nfunction wrapReadableStream<T>(\n source: ReadableStream<T>,\n handlers: {\n onDone?: () => void\n onCancel?: () => void\n onError?: () => void\n },\n): ReadableStream<T> {\n const reader = source.getReader()\n let finished = false\n\n const finish = () => {\n if (finished) return\n finished = true\n handlers.onDone?.()\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n }\n\n return new ReadableStream<T>({\n async pull(controller) {\n try {\n const { value, done } = await reader.read()\n if (done) {\n controller.close()\n finish()\n return\n }\n controller.enqueue(value)\n } catch (err) {\n try {\n controller.error(err)\n } catch {\n // Ignore\n }\n handlers.onError?.()\n finish()\n }\n },\n async cancel(reason) {\n handlers.onCancel?.()\n try {\n await reader.cancel(reason)\n } catch {\n // Ignore\n }\n finish()\n },\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,eAAsB,yBACpB,WACA,SAC0C;CAC1C,MAAM,QAAA,QAAA,IAAA,aAAiC;CAGvC,MAAM,oBAAoB,QACtB,4BAA+C,IAC/C;CAKJ,MAAM,EAAE,OAAO,eAAe,gBAAoB,EAChD,YAAY,qBACP,MAAM,SAAS;EACd,MAAM,gBAAgB,iBAAiB,IAAI;EAC3C,kBAAkB,KAAK;GACrB,MAAM;GACN,MAAM,cAAc,SAAS,gBAAgB,KAAA;EAC/C,CAAC;CACH,IACA,KAAA,EACN,CAAC;CAGD,eAAe,yBAAyB;EACtC,OAAO,qBACL,MAAO,UAAuB,UAAU,GACxC,OACF;CACF;CAKA,MAAM,eAAe,uBACnB,cAAc,sBAA6B,CAC7C;CAIA,MAAM,kBADM,gBAAgB,EAAE,iBAAiB,MAAM,CAC7B,GAAK,gBAAgB;CAC7C,MAAM,aAAa,WAAW;CAG9B,IAAI,mBAAmB,YAAY;EACjC,MAAM,SAAS,WAAW,EAAE;EAC5B,MAAM,SAAS,IAAI,iBAAiB,cAAc,EAAE,OAAO,CAAC;EAG5D,MAAM,UAAU,MAAM,WAAW,OAAO,MAAM;EAG9C,mBAAmB,MAAM;EAEzB,OAAO,WAAW,qBAChB,QACA,SACA,mBAAmB,MACrB;CACF;CAmBA,OAAO,sBAdL,SAAS,oBACL,mBAAmB,cAAc;EAC/B,cAAc;GACZ,kBAAkB,MAAM;EAC1B;EACA,gBAAgB;GACd,kBAAkB,MAAM;EAC1B;EACA,eAAe;GACb,kBAAkB,MAAM;EAC1B;CACF,CAAC,IACD,cAE8C,EAClD,kBAAkB,mBAAmB,OACvC,CAAC;AACH;;;;;AAMA,SAAS,sBACP,cACA,SAGuB;CAGvB,MAAM,gBAAuC,EAC3C,0BAA0B,aAC5B;CAKA,MAAM,OAAO,SAAS,yBAAgC;EACpD,MAAM,IAAI,MACR,uHAEF;CACF;CAEC,KAAc,2BAA2B;CAG1C,IAAI,SAAS,kBACV,KAAc,0BAA0B,QAAQ;CAGnD,OAAO;AACT;;;;;AAqBA,SAAS,gBAA2C,SAEpB;CAC9B,MAAM,wBAAQ,IAAI,IAAsD;CAuBxE,OAAO,EACL,OAAA,IAtBgB,MAAM,CAAC,GAAiC,EACxD,IAAI,SAAS,MAAM;EACjB,IAAI,SAAS,UAAU,OAAO,SAAS,UAAU,OAAO,KAAA;EAExD,IAAI,SAAS,YAAY;GACvB,SAAS,aAAa,YAAY,CAAC,CAAC;GACpC,OAAO,cAAc,YAAY;IAAE,MAAM;IAAY,MAAM,CAAC;GAAE,CAAC;EACjE;EAEA,IAAI,KAAK,MAAM,IAAI,IAAI;EACvB,IAAI,CAAC,IAAI;GACP,MAAM,GAAG,SAAqB;IAC5B,SAAS,aAAa,MAAM,IAAI;IAChC,OAAO,cAAc,YAAY;KAAE,MAAM;KAAM;IAAK,CAAC;GACvD;GACA,MAAM,IAAI,MAAM,EAAE;EACpB;EACA,OAAO;CACT,EACF,CAGE,EACF;AACF;AAEA,SAAS,8BAIP;CACA,IAAI,SAAS;CACb,MAAM,QAAkB,CAAC;CACzB,IAAI,aAAwD;CAE5D,MAAM,SAAS,IAAI,eAAkB;EACnC,MAAM,MAAM;GACV,aAAa;GACb,KAAK,MAAM,SAAS,OAClB,IAAI;IACF,KAAK,QAAQ,KAAK;GACpB,QAAQ,CAER;GAEF,MAAM,SAAS;GACf,IAAI,QACF,IAAI;IACF,KAAK,MAAM;GACb,QAAQ,CAER;EAEJ;EACA,SAAS;GACP,SAAS;GACT,aAAa;GACb,MAAM,SAAS;EACjB;CACF,CAAC;CAED,MAAM,QAAQ,UAAa;EACzB,IAAI,QAAQ;EACZ,IAAI,CAAC,YAAY;GACf,MAAM,KAAK,KAAK;GAChB;EACF;EACA,IAAI;GACF,WAAW,QAAQ,KAAK;EAC1B,QAAQ,CAER;CACF;CAEA,MAAM,cAAc;EAClB,IAAI,QAAQ;EACZ,SAAS;EACT,IAAI,YAAY;GACd,IAAI;IACF,WAAW,MAAM;GACnB,QAAQ,CAER;GACA,aAAa;EACf;CACF;CAEA,OAAO;EAAE;EAAQ;EAAM;CAAM;AAC/B;AAEA,SAAS,mBACP,QACA,UAKmB;CACnB,MAAM,SAAS,OAAO,UAAU;CAChC,IAAI,WAAW;CAEf,MAAM,eAAe;EACnB,IAAI,UAAU;EACd,WAAW;EACX,SAAS,SAAS;EAClB,IAAI;GACF,OAAO,YAAY;EACrB,QAAQ,CAER;CACF;CAEA,OAAO,IAAI,eAAkB;EAC3B,MAAM,KAAK,YAAY;GACrB,IAAI;IACF,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;IAC1C,IAAI,MAAM;KACR,WAAW,MAAM;KACjB,OAAO;KACP;IACF;IACA,WAAW,QAAQ,KAAK;GAC1B,SAAS,KAAK;IACZ,IAAI;KACF,WAAW,MAAM,GAAG;IACtB,QAAQ,CAER;IACA,SAAS,UAAU;IACnB,OAAO;GACT;EACF;EACA,MAAM,OAAO,QAAQ;GACnB,SAAS,WAAW;GACpB,IAAI;IACF,MAAM,OAAO,OAAO,MAAM;GAC5B,QAAQ,CAER;GACA,OAAO;EACT;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"createCompositeComponent.stub.js","names":[],"sources":["../../src/createCompositeComponent.stub.ts"],"sourcesContent":["import type {\n CompositeComponentResult,\n ValidateCompositeComponent,\n} from './ServerComponentTypes'\n\n/**\n * Client stub for createCompositeComponent.\n *\n * This function should never be called at runtime on the client.\n * It exists only to satisfy bundler imports in client bundles.\n * The real implementation only runs inside server functions.\n */\nexport function createCompositeComponent<TComp>(\n _component: ValidateCompositeComponent<TComp>,\n): Promise<CompositeComponentResult<TComp>> {\n throw new Error(\n 'createCompositeComponent cannot be called on the client. ' +\n 'This function should only be called inside a server function or route loader.',\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,yBACd,YAC0C;AAC1C,OAAM,IAAI,MACR,yIAED"}
1
+ {"version":3,"file":"createCompositeComponent.stub.js","names":[],"sources":["../../src/createCompositeComponent.stub.ts"],"sourcesContent":["import type {\n CompositeComponentResult,\n ValidateCompositeComponent,\n} from './ServerComponentTypes'\n\n/**\n * Client stub for createCompositeComponent.\n *\n * This function should never be called at runtime on the client.\n * It exists only to satisfy bundler imports in client bundles.\n * The real implementation only runs inside server functions.\n */\nexport function createCompositeComponent<TComp>(\n _component: ValidateCompositeComponent<TComp>,\n): Promise<CompositeComponentResult<TComp>> {\n throw new Error(\n 'createCompositeComponent cannot be called on the client. ' +\n 'This function should only be called inside a server function or route loader.',\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,yBACd,YAC0C;CAC1C,MAAM,IAAI,MACR,wIAEF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"createRscProxy.js","names":[],"sources":["../../src/createRscProxy.tsx"],"sourcesContent":["'use client'\n\nimport { createElement } from 'react'\nimport { RscNodeRenderer } from './RscNodeRenderer'\nimport {\n RENDERABLE_RSC,\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n RSC_SLOT_USAGES,\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport type { RscSlotUsageEvent } from './ServerComponentTypes'\n\nexport interface RscProxyOptions {\n stream?: unknown // The stream to attach for serialization\n cssHrefs?: ReadonlySet<string> // CSS hrefs collected from the RSC stream\n jsPreloads?: ReadonlySet<string> // JS hrefs collected from the RSC stream\n renderable?: boolean // If true, proxy masquerades as React element\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent> // Dev only: slot usage event stream\n}\n\n/**\n * Creates a recursive Proxy for RSC data.\n *\n * If `renderable: true`, returns a React element that can be rendered as `{data}`.\n * The element also has proxy-like behavior for nested access like `data.foo.bar`.\n *\n * If `renderable: false` (default), the proxy is NOT directly renderable and\n * must be used with `<CompositeComponent src={...} />`.\n */\nexport function createRscProxy<T>(\n getTree: () => T,\n options: RscProxyOptions = {},\n): any {\n if (options.renderable) {\n // For renderable mode, create a real React element with proxy access\n return createRenderableElement(\n getTree,\n [],\n options.stream,\n options.cssHrefs,\n options.jsPreloads,\n )\n }\n let slotUsages: Array<RscSlotUsageEvent> | undefined = undefined\n\n if (\n process.env.NODE_ENV === 'development' &&\n typeof window !== 'undefined' &&\n options.slotUsagesStream\n ) {\n slotUsages = []\n void consumeSlotUsages(options.slotUsagesStream, slotUsages)\n }\n\n // Non-renderable mode: plain proxy\n return createRscProxyWithPath(\n getTree,\n [],\n options.stream,\n options.cssHrefs,\n options.jsPreloads,\n slotUsages,\n options.slotUsagesStream,\n )\n}\n\n/**\n * Creates a React element that's also a Proxy for nested access.\n * This is used by renderable RSCs so they work as both {data} and {data.foo.bar}.\n */\ntype CreateProxyOptions = {\n getTree: () => unknown\n path: Array<string>\n stream: unknown | undefined\n cssHrefs: ReadonlySet<string> | undefined\n jsPreloads: ReadonlySet<string> | undefined\n renderable: boolean\n slotUsages: Array<RscSlotUsageEvent> | undefined\n slotUsagesStream: ReadableStream<RscSlotUsageEvent> | undefined\n}\n\nconst UNHANDLED = Symbol('tanstack.rsc.proxy.unhandled')\n\nfunction handleProxyTrap(\n kind: 'get' | 'has',\n prop: PropertyKey,\n options: CreateProxyOptions,\n): unknown | boolean | typeof UNHANDLED {\n switch (prop) {\n // Seroval (>=1.5) uses string sentinels and `in` checks for internal types.\n // These proxies must never look like streams/sequences.\n case '__SEROVAL_STREAM__':\n case '__SEROVAL_SEQUENCE__':\n return kind === 'get' ? undefined : false\n\n // Seroval >=1.5 also checks iterability via `Symbol.iterator in value`.\n case Symbol.iterator:\n case Symbol.asyncIterator:\n return kind === 'get' ? undefined : false\n\n // Our proxy branding/properties\n case SERVER_COMPONENT_STREAM:\n return kind === 'get' ? options.stream : options.stream !== undefined\n case SERVER_COMPONENT_CSS_HREFS:\n return kind === 'get' ? options.cssHrefs : options.cssHrefs !== undefined\n case SERVER_COMPONENT_JS_PRELOADS:\n return kind === 'get'\n ? options.jsPreloads\n : options.jsPreloads !== undefined\n case RSC_PROXY_GET_TREE:\n return kind === 'get' ? options.getTree : true\n case RSC_PROXY_PATH:\n return kind === 'get' ? options.path : true\n case RENDERABLE_RSC:\n return kind === 'get' ? options.renderable : true\n case RSC_SLOT_USAGES:\n return kind === 'get'\n ? options.slotUsages\n : options.slotUsages !== undefined\n\n case RSC_SLOT_USAGES_STREAM:\n return kind === 'get'\n ? options.slotUsagesStream\n : options.slotUsagesStream !== undefined\n\n // Avoid promise-like checks\n case 'then':\n return kind === 'get' ? undefined : UNHANDLED\n\n // Avoid breaking primitive coercion (eg String(proxy)).\n // Without these, nested-selection proxies can shadow these keys and\n // cause `Cannot convert object to primitive value` errors.\n case 'toString':\n return kind === 'get' ? Object.prototype.toString : UNHANDLED\n case 'valueOf':\n return kind === 'get' ? Object.prototype.valueOf : UNHANDLED\n case 'constructor':\n return kind === 'get' ? Object : UNHANDLED\n }\n\n // Non-renderable proxies claim all string keys exist for nested selection,\n // but symbol presence checks should be accurate.\n if (typeof prop === 'symbol') {\n return kind === 'get' ? undefined : false\n }\n\n return UNHANDLED\n}\n\nfunction createRscProxyInternal(options: CreateProxyOptions): any {\n // Per-proxy cache so repeated property access is referentially stable.\n const childCache = new Map<string, any>()\n\n const getChild = (key: string) => {\n const cached = childCache.get(key)\n if (cached) return cached\n\n const next = createRscProxyInternal({\n ...options,\n path: [...options.path, key],\n })\n childCache.set(key, next)\n return next\n }\n\n const dataProxy = options.renderable\n ? createRscProxyInternal({ ...options, renderable: false })\n : undefined\n\n // Use a React element (renderable) or plain object (non-renderable) as Proxy target.\n const proxyTarget = options.renderable\n ? createElement(RscNodeRenderer, { data: dataProxy })\n : ({} as any)\n\n return new Proxy(proxyTarget, {\n get(target, prop) {\n const handled = handleProxyTrap('get', prop, options)\n if (handled !== UNHANDLED) return handled\n\n if (options.renderable) {\n // Proxy invariants: if target has a non-configurable, read-only property,\n // we must return the *exact* value for that property.\n if (prop === 'props') {\n return target.props\n }\n\n if (prop === 'data') {\n return dataProxy\n }\n\n if (prop in target) {\n return target[prop]\n }\n }\n\n return getChild(String(prop))\n },\n\n has(target, prop) {\n const handled = handleProxyTrap('has', prop, options)\n if (handled !== UNHANDLED) return handled as boolean\n\n if (options.renderable) {\n if (prop in target) return true\n if (typeof prop === 'string') return true\n return false\n }\n\n // Allow any property access for nested selection.\n return true\n },\n\n getPrototypeOf(target) {\n return options.renderable\n ? Object.getPrototypeOf(target)\n : Object.prototype\n },\n\n getOwnPropertyDescriptor(target, prop) {\n return options.renderable\n ? Object.getOwnPropertyDescriptor(target, prop)\n : undefined\n },\n\n ownKeys(target) {\n return options.renderable ? Reflect.ownKeys(target) : []\n },\n })\n}\n\n/**\n * Creates a React element that's also a Proxy for nested access.\n * This is used by renderable RSCs so they work as both {data} and {data.foo.bar}.\n */\nfunction createRenderableElement(\n getTree: () => unknown,\n path: Array<string>,\n stream: unknown | undefined,\n cssHrefs: ReadonlySet<string> | undefined,\n jsPreloads: ReadonlySet<string> | undefined,\n): any {\n return createRscProxyInternal({\n getTree,\n path,\n stream,\n cssHrefs,\n jsPreloads,\n renderable: true,\n slotUsages: undefined,\n slotUsagesStream: undefined,\n })\n}\n\nfunction createRscProxyWithPath(\n getTree: () => unknown,\n path: Array<string>,\n stream: unknown | undefined,\n cssHrefs: ReadonlySet<string> | undefined,\n jsPreloads: ReadonlySet<string> | undefined,\n slotUsages: Array<RscSlotUsageEvent> | undefined,\n slotUsagesStream: ReadableStream<RscSlotUsageEvent> | undefined,\n): any {\n return createRscProxyInternal({\n getTree,\n path,\n stream,\n cssHrefs,\n jsPreloads,\n renderable: false,\n slotUsages,\n slotUsagesStream,\n })\n}\n\nasync function consumeSlotUsages(\n stream: ReadableStream<RscSlotUsageEvent>,\n slotUsages: Array<RscSlotUsageEvent>,\n): Promise<void> {\n try {\n const reader = stream.getReader()\n for (;;) {\n const { value, done } = await reader.read()\n if (done) break\n if (!value.slot) continue\n slotUsages.push(value)\n }\n } catch {\n // Ignore - dev-only best effort\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createRscProxy.js","names":[],"sources":["../../src/createRscProxy.tsx"],"sourcesContent":["'use client'\n\nimport { createElement } from 'react'\nimport { RscNodeRenderer } from './RscNodeRenderer'\nimport {\n RENDERABLE_RSC,\n RSC_PROXY_GET_TREE,\n RSC_PROXY_PATH,\n RSC_SLOT_USAGES,\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_CSS_HREFS,\n SERVER_COMPONENT_JS_PRELOADS,\n SERVER_COMPONENT_STREAM,\n} from './ServerComponentTypes'\nimport type { RscSlotUsageEvent } from './ServerComponentTypes'\n\nexport interface RscProxyOptions {\n stream?: unknown // The stream to attach for serialization\n cssHrefs?: ReadonlySet<string> // CSS hrefs collected from the RSC stream\n jsPreloads?: ReadonlySet<string> // JS hrefs collected from the RSC stream\n renderable?: boolean // If true, proxy masquerades as React element\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent> // Dev only: slot usage event stream\n}\n\n/**\n * Creates a recursive Proxy for RSC data.\n *\n * If `renderable: true`, returns a React element that can be rendered as `{data}`.\n * The element also has proxy-like behavior for nested access like `data.foo.bar`.\n *\n * If `renderable: false` (default), the proxy is NOT directly renderable and\n * must be used with `<CompositeComponent src={...} />`.\n */\nexport function createRscProxy<T>(\n getTree: () => T,\n options: RscProxyOptions = {},\n): any {\n if (options.renderable) {\n // For renderable mode, create a real React element with proxy access\n return createRenderableElement(\n getTree,\n [],\n options.stream,\n options.cssHrefs,\n options.jsPreloads,\n )\n }\n let slotUsages: Array<RscSlotUsageEvent> | undefined = undefined\n\n if (\n process.env.NODE_ENV === 'development' &&\n typeof window !== 'undefined' &&\n options.slotUsagesStream\n ) {\n slotUsages = []\n void consumeSlotUsages(options.slotUsagesStream, slotUsages)\n }\n\n // Non-renderable mode: plain proxy\n return createRscProxyWithPath(\n getTree,\n [],\n options.stream,\n options.cssHrefs,\n options.jsPreloads,\n slotUsages,\n options.slotUsagesStream,\n )\n}\n\n/**\n * Creates a React element that's also a Proxy for nested access.\n * This is used by renderable RSCs so they work as both {data} and {data.foo.bar}.\n */\ntype CreateProxyOptions = {\n getTree: () => unknown\n path: Array<string>\n stream: unknown | undefined\n cssHrefs: ReadonlySet<string> | undefined\n jsPreloads: ReadonlySet<string> | undefined\n renderable: boolean\n slotUsages: Array<RscSlotUsageEvent> | undefined\n slotUsagesStream: ReadableStream<RscSlotUsageEvent> | undefined\n}\n\nconst UNHANDLED = Symbol('tanstack.rsc.proxy.unhandled')\n\nfunction handleProxyTrap(\n kind: 'get' | 'has',\n prop: PropertyKey,\n options: CreateProxyOptions,\n): unknown | boolean | typeof UNHANDLED {\n switch (prop) {\n // Seroval (>=1.5) uses string sentinels and `in` checks for internal types.\n // These proxies must never look like streams/sequences.\n case '__SEROVAL_STREAM__':\n case '__SEROVAL_SEQUENCE__':\n return kind === 'get' ? undefined : false\n\n // Seroval >=1.5 also checks iterability via `Symbol.iterator in value`.\n case Symbol.iterator:\n case Symbol.asyncIterator:\n return kind === 'get' ? undefined : false\n\n // Our proxy branding/properties\n case SERVER_COMPONENT_STREAM:\n return kind === 'get' ? options.stream : options.stream !== undefined\n case SERVER_COMPONENT_CSS_HREFS:\n return kind === 'get' ? options.cssHrefs : options.cssHrefs !== undefined\n case SERVER_COMPONENT_JS_PRELOADS:\n return kind === 'get'\n ? options.jsPreloads\n : options.jsPreloads !== undefined\n case RSC_PROXY_GET_TREE:\n return kind === 'get' ? options.getTree : true\n case RSC_PROXY_PATH:\n return kind === 'get' ? options.path : true\n case RENDERABLE_RSC:\n return kind === 'get' ? options.renderable : true\n case RSC_SLOT_USAGES:\n return kind === 'get'\n ? options.slotUsages\n : options.slotUsages !== undefined\n\n case RSC_SLOT_USAGES_STREAM:\n return kind === 'get'\n ? options.slotUsagesStream\n : options.slotUsagesStream !== undefined\n\n // Avoid promise-like checks\n case 'then':\n return kind === 'get' ? undefined : UNHANDLED\n\n // Avoid breaking primitive coercion (eg String(proxy)).\n // Without these, nested-selection proxies can shadow these keys and\n // cause `Cannot convert object to primitive value` errors.\n case 'toString':\n return kind === 'get' ? Object.prototype.toString : UNHANDLED\n case 'valueOf':\n return kind === 'get' ? Object.prototype.valueOf : UNHANDLED\n case 'constructor':\n return kind === 'get' ? Object : UNHANDLED\n }\n\n // Non-renderable proxies claim all string keys exist for nested selection,\n // but symbol presence checks should be accurate.\n if (typeof prop === 'symbol') {\n return kind === 'get' ? undefined : false\n }\n\n return UNHANDLED\n}\n\nfunction createRscProxyInternal(options: CreateProxyOptions): any {\n // Per-proxy cache so repeated property access is referentially stable.\n const childCache = new Map<string, any>()\n\n const getChild = (key: string) => {\n const cached = childCache.get(key)\n if (cached) return cached\n\n const next = createRscProxyInternal({\n ...options,\n path: [...options.path, key],\n })\n childCache.set(key, next)\n return next\n }\n\n const dataProxy = options.renderable\n ? createRscProxyInternal({ ...options, renderable: false })\n : undefined\n\n // Use a React element (renderable) or plain object (non-renderable) as Proxy target.\n const proxyTarget = options.renderable\n ? createElement(RscNodeRenderer, { data: dataProxy })\n : ({} as any)\n\n return new Proxy(proxyTarget, {\n get(target, prop) {\n const handled = handleProxyTrap('get', prop, options)\n if (handled !== UNHANDLED) return handled\n\n if (options.renderable) {\n // Proxy invariants: if target has a non-configurable, read-only property,\n // we must return the *exact* value for that property.\n if (prop === 'props') {\n return target.props\n }\n\n if (prop === 'data') {\n return dataProxy\n }\n\n if (prop in target) {\n return target[prop]\n }\n }\n\n return getChild(String(prop))\n },\n\n has(target, prop) {\n const handled = handleProxyTrap('has', prop, options)\n if (handled !== UNHANDLED) return handled as boolean\n\n if (options.renderable) {\n if (prop in target) return true\n if (typeof prop === 'string') return true\n return false\n }\n\n // Allow any property access for nested selection.\n return true\n },\n\n getPrototypeOf(target) {\n return options.renderable\n ? Object.getPrototypeOf(target)\n : Object.prototype\n },\n\n getOwnPropertyDescriptor(target, prop) {\n return options.renderable\n ? Object.getOwnPropertyDescriptor(target, prop)\n : undefined\n },\n\n ownKeys(target) {\n return options.renderable ? Reflect.ownKeys(target) : []\n },\n })\n}\n\n/**\n * Creates a React element that's also a Proxy for nested access.\n * This is used by renderable RSCs so they work as both {data} and {data.foo.bar}.\n */\nfunction createRenderableElement(\n getTree: () => unknown,\n path: Array<string>,\n stream: unknown | undefined,\n cssHrefs: ReadonlySet<string> | undefined,\n jsPreloads: ReadonlySet<string> | undefined,\n): any {\n return createRscProxyInternal({\n getTree,\n path,\n stream,\n cssHrefs,\n jsPreloads,\n renderable: true,\n slotUsages: undefined,\n slotUsagesStream: undefined,\n })\n}\n\nfunction createRscProxyWithPath(\n getTree: () => unknown,\n path: Array<string>,\n stream: unknown | undefined,\n cssHrefs: ReadonlySet<string> | undefined,\n jsPreloads: ReadonlySet<string> | undefined,\n slotUsages: Array<RscSlotUsageEvent> | undefined,\n slotUsagesStream: ReadableStream<RscSlotUsageEvent> | undefined,\n): any {\n return createRscProxyInternal({\n getTree,\n path,\n stream,\n cssHrefs,\n jsPreloads,\n renderable: false,\n slotUsages,\n slotUsagesStream,\n })\n}\n\nasync function consumeSlotUsages(\n stream: ReadableStream<RscSlotUsageEvent>,\n slotUsages: Array<RscSlotUsageEvent>,\n): Promise<void> {\n try {\n const reader = stream.getReader()\n for (;;) {\n const { value, done } = await reader.read()\n if (done) break\n if (!value.slot) continue\n slotUsages.push(value)\n }\n } catch {\n // Ignore - dev-only best effort\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"createServerComponentFromStream.js","names":[],"sources":["../../src/createServerComponentFromStream.ts"],"sourcesContent":["'use client'\n\nimport { use } from 'react'\nimport { trackPostProcessPromise } from '@tanstack/start-client-core'\nimport { createFromReadableStream as browserDecode } from 'virtual:tanstack-rsc-browser-decode'\n\nimport { awaitLazyElements } from './awaitLazyElements'\nimport { createRscProxy } from './createRscProxy'\nimport { unwrapRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n RscSlotUsageEvent,\n ServerComponentStream,\n} from './ServerComponentTypes'\n\n/**\n * Creates a renderable RSC proxy from a raw Flight stream.\n * Client-side only - used by the client serialization adapter for `renderServerComponent`.\n *\n * Returns a Proxy that:\n * - Can be rendered directly as `{data}` in JSX\n * - Supports nested access: `{data.foo.bar}`\n * - Masquerades as a React element\n */\nexport function createRenderableFromStream(\n stream: ReadableStream<Uint8Array>,\n): any {\n const { getTree, streamWrapper, cssHrefs } = setupStreamDecode(stream)\n\n return createRscProxy(getTree, {\n stream: streamWrapper,\n cssHrefs,\n renderable: true,\n })\n}\n\n/**\n * Creates a composite RSC proxy from a raw Flight stream.\n * Client-side only - used by the client serialization adapter for `createCompositeComponent`.\n *\n * Returns a Proxy that:\n * - NOT directly renderable\n * - Supports nested access: `src.foo.bar`\n * - Must be rendered via `<CompositeComponent src={...} />`\n */\nexport function createCompositeFromStream(\n stream: ReadableStream<Uint8Array>,\n options?: {\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n },\n): AnyCompositeComponent {\n const { getTree, streamWrapper, cssHrefs } = setupStreamDecode(stream)\n\n return createRscProxy(getTree, {\n stream: streamWrapper,\n cssHrefs,\n renderable: false,\n slotUsagesStream: options?.slotUsagesStream,\n })\n}\n\n/**\n * Shared stream decode setup for both renderable and composite.\n */\nfunction setupStreamDecode(stream: ReadableStream<Uint8Array>): {\n getTree: () => unknown\n streamWrapper: ServerComponentStream\n cssHrefs: Set<string> | undefined\n} {\n // Start decoding eagerly during deserialization\n const decodeThenable = browserDecode(stream)\n const cssHrefs = new Set<string>()\n\n // Synchronous cache for the decoded tree.\n let cachedTree: unknown = undefined\n let cacheReady = false\n\n // Promise for the tree with lazy elements awaited.\n const transformedTreePromise = Promise.resolve(decodeThenable).then(\n async (result) => {\n await awaitLazyElements(result, (href) => {\n cssHrefs.add(href)\n })\n cachedTree = unwrapRscCssEnvelope(result)\n cacheReady = true\n return cachedTree\n },\n )\n\n // Track the lazy element loading - prevents flash\n trackPostProcessPromise(transformedTreePromise)\n\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => stream,\n }\n\n const getTree = () => {\n if (cacheReady) return cachedTree\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return use(transformedTreePromise)\n }\n\n return { getTree, streamWrapper, cssHrefs }\n}\n// Legacy export for backwards compatibility during migration\nexport const createServerComponentFromStream = createCompositeFromStream\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,SAAgB,2BACd,QACK;CACL,MAAM,EAAE,SAAS,eAAe,aAAa,kBAAkB,OAAO;AAEtE,QAAO,eAAe,SAAS;EAC7B,QAAQ;EACR;EACA,YAAY;EACb,CAAC;;;;;;;;;;;AAYJ,SAAgB,0BACd,QACA,SAGuB;CACvB,MAAM,EAAE,SAAS,eAAe,aAAa,kBAAkB,OAAO;AAEtE,QAAO,eAAe,SAAS;EAC7B,QAAQ;EACR;EACA,YAAY;EACZ,kBAAkB,SAAS;EAC5B,CAAC;;;;;AAMJ,SAAS,kBAAkB,QAIzB;CAEA,MAAM,iBAAiB,yBAAc,OAAO;CAC5C,MAAM,2BAAW,IAAI,KAAa;CAGlC,IAAI,aAAsB,KAAA;CAC1B,IAAI,aAAa;CAGjB,MAAM,yBAAyB,QAAQ,QAAQ,eAAe,CAAC,KAC7D,OAAO,WAAW;AAChB,QAAM,kBAAkB,SAAS,SAAS;AACxC,YAAS,IAAI,KAAK;IAClB;AACF,eAAa,qBAAqB,OAAO;AACzC,eAAa;AACb,SAAO;GAEV;AAGD,yBAAwB,uBAAuB;CAE/C,MAAM,gBAAuC,EAC3C,0BAA0B,QAC3B;CAED,MAAM,gBAAgB;AACpB,MAAI,WAAY,QAAO;AAEvB,SAAO,IAAI,uBAAuB;;AAGpC,QAAO;EAAE;EAAS;EAAe;EAAU"}
1
+ {"version":3,"file":"createServerComponentFromStream.js","names":[],"sources":["../../src/createServerComponentFromStream.ts"],"sourcesContent":["'use client'\n\nimport { use } from 'react'\nimport { trackPostProcessPromise } from '@tanstack/start-client-core'\nimport { createFromReadableStream as browserDecode } from 'virtual:tanstack-rsc-browser-decode'\n\nimport { awaitLazyElements } from './awaitLazyElements'\nimport { createRscProxy } from './createRscProxy'\nimport { unwrapRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n RscSlotUsageEvent,\n ServerComponentStream,\n} from './ServerComponentTypes'\n\n/**\n * Creates a renderable RSC proxy from a raw Flight stream.\n * Client-side only - used by the client serialization adapter for `renderServerComponent`.\n *\n * Returns a Proxy that:\n * - Can be rendered directly as `{data}` in JSX\n * - Supports nested access: `{data.foo.bar}`\n * - Masquerades as a React element\n */\nexport function createRenderableFromStream(\n stream: ReadableStream<Uint8Array>,\n): any {\n const { getTree, streamWrapper, cssHrefs } = setupStreamDecode(stream)\n\n return createRscProxy(getTree, {\n stream: streamWrapper,\n cssHrefs,\n renderable: true,\n })\n}\n\n/**\n * Creates a composite RSC proxy from a raw Flight stream.\n * Client-side only - used by the client serialization adapter for `createCompositeComponent`.\n *\n * Returns a Proxy that:\n * - NOT directly renderable\n * - Supports nested access: `src.foo.bar`\n * - Must be rendered via `<CompositeComponent src={...} />`\n */\nexport function createCompositeFromStream(\n stream: ReadableStream<Uint8Array>,\n options?: {\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n },\n): AnyCompositeComponent {\n const { getTree, streamWrapper, cssHrefs } = setupStreamDecode(stream)\n\n return createRscProxy(getTree, {\n stream: streamWrapper,\n cssHrefs,\n renderable: false,\n slotUsagesStream: options?.slotUsagesStream,\n })\n}\n\n/**\n * Shared stream decode setup for both renderable and composite.\n */\nfunction setupStreamDecode(stream: ReadableStream<Uint8Array>): {\n getTree: () => unknown\n streamWrapper: ServerComponentStream\n cssHrefs: Set<string> | undefined\n} {\n // Start decoding eagerly during deserialization\n const decodeThenable = browserDecode(stream)\n const cssHrefs = new Set<string>()\n\n // Synchronous cache for the decoded tree.\n let cachedTree: unknown = undefined\n let cacheReady = false\n\n // Promise for the tree with lazy elements awaited.\n const transformedTreePromise = Promise.resolve(decodeThenable).then(\n async (result) => {\n await awaitLazyElements(result, (href) => {\n cssHrefs.add(href)\n })\n cachedTree = unwrapRscCssEnvelope(result)\n cacheReady = true\n return cachedTree\n },\n )\n\n // Track the lazy element loading - prevents flash\n trackPostProcessPromise(transformedTreePromise)\n\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => stream,\n }\n\n const getTree = () => {\n if (cacheReady) return cachedTree\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return use(transformedTreePromise)\n }\n\n return { getTree, streamWrapper, cssHrefs }\n}\n// Legacy export for backwards compatibility during migration\nexport const createServerComponentFromStream = createCompositeFromStream\n"],"mappings":";;;;;;;;;;;;;;;;;AAwBA,SAAgB,2BACd,QACK;CACL,MAAM,EAAE,SAAS,eAAe,aAAa,kBAAkB,MAAM;CAErE,OAAO,eAAe,SAAS;EAC7B,QAAQ;EACR;EACA,YAAY;CACd,CAAC;AACH;;;;;;;;;;AAWA,SAAgB,0BACd,QACA,SAGuB;CACvB,MAAM,EAAE,SAAS,eAAe,aAAa,kBAAkB,MAAM;CAErE,OAAO,eAAe,SAAS;EAC7B,QAAQ;EACR;EACA,YAAY;EACZ,kBAAkB,SAAS;CAC7B,CAAC;AACH;;;;AAKA,SAAS,kBAAkB,QAIzB;CAEA,MAAM,iBAAiB,yBAAc,MAAM;CAC3C,MAAM,2BAAW,IAAI,IAAY;CAGjC,IAAI,aAAsB,KAAA;CAC1B,IAAI,aAAa;CAGjB,MAAM,yBAAyB,QAAQ,QAAQ,cAAc,EAAE,KAC7D,OAAO,WAAW;EAChB,MAAM,kBAAkB,SAAS,SAAS;GACxC,SAAS,IAAI,IAAI;EACnB,CAAC;EACD,aAAa,qBAAqB,MAAM;EACxC,aAAa;EACb,OAAO;CACT,CACF;CAGA,wBAAwB,sBAAsB;CAE9C,MAAM,gBAAuC,EAC3C,0BAA0B,OAC5B;CAEA,MAAM,gBAAgB;EACpB,IAAI,YAAY,OAAO;EAEvB,OAAO,IAAI,sBAAsB;CACnC;CAEA,OAAO;EAAE;EAAS;EAAe;CAAS;AAC5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"rsc.js","names":[],"sources":["../../../src/entry/rsc.tsx"],"sourcesContent":["/**\n * Shared RSC (React Server Components) entry point.\n *\n * This file exports the functions needed for the active RSC environment:\n * - getServerFnById: Resolves server functions by their encoded ID\n * - render: Renders a React node to an RSC Flight stream\n */\n\nimport { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport type React from 'react'\n\n// Re-export getServerFnById from the virtual module which handles both dev and production\n// In dev: dynamic import with base64url-decoded file path\n// In production: manifest-based lookup with bundled chunks\nexport { getServerFnById } from '#tanstack-start-server-fn-resolver'\n\n/**\n * Renders a React node to an RSC Flight stream.\n * Used internally for streaming server component output.\n */\nexport function render(node: React.ReactNode): ReadableStream<Uint8Array> {\n return renderToReadableStream(node)\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,SAAgB,OAAO,MAAmD;AACxE,QAAO,uBAAuB,KAAK"}
1
+ {"version":3,"file":"rsc.js","names":[],"sources":["../../../src/entry/rsc.tsx"],"sourcesContent":["/**\n * Shared RSC (React Server Components) entry point.\n *\n * This file exports the functions needed for the active RSC environment:\n * - getServerFnById: Resolves server functions by their encoded ID\n * - render: Renders a React node to an RSC Flight stream\n */\n\nimport { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport type React from 'react'\n\n// Re-export getServerFnById from the virtual module which handles both dev and production\n// In dev: dynamic import with base64url-decoded file path\n// In production: manifest-based lookup with bundled chunks\nexport { getServerFnById } from '#tanstack-start-server-fn-resolver'\n\n/**\n * Renders a React node to an RSC Flight stream.\n * Used internally for streaming server component output.\n */\nexport function render(node: React.ReactNode): ReadableStream<Uint8Array> {\n return renderToReadableStream(node)\n}\n"],"mappings":";;;;;;;;;;;;;;AAoBA,SAAgB,OAAO,MAAmD;CACxE,OAAO,uBAAuB,IAAI;AACpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"flight.js","names":[],"sources":["../../src/flight.ts"],"sourcesContent":["/**\n * Low-level Flight stream APIs for decoding RSC streams.\n *\n * These functions provide direct access to RSC Flight stream decoding,\n * allowing advanced use cases like:\n * - Server functions returning raw Flight Response\n * - API routes streaming Flight payloads\n * - Custom Flight stream handling via RawStream\n *\n * `createFromReadableStream` works in both SSR and browser contexts.\n * `createFromFetch` is browser-only.\n *\n * NOTE: Dynamic imports keep decode initialisation runtime-specific. The\n * concrete implementation comes from bundler-owned virtual modules.\n */\n\nimport {\n createClientOnlyFn,\n createIsomorphicFn,\n} from '@tanstack/start-fn-stubs'\n\n/**\n * Decode a Flight stream into React elements.\n * Works in both SSR and browser contexts.\n *\n * @example\n * ```tsx\n * const rawStream = await getRscRawStream()\n * const tree = await createFromReadableStream(rawStream)\n * return <>{tree}</>\n * ```\n */\nexport const createFromReadableStream = createIsomorphicFn()\n .server(\n async (stream: ReadableStream<Uint8Array>): Promise<React.ReactNode> => {\n const { createFromReadableStream: decode } =\n await import('virtual:tanstack-rsc-ssr-decode')\n return decode(stream) as React.ReactNode\n },\n )\n .client(\n async (stream: ReadableStream<Uint8Array>): Promise<React.ReactNode> => {\n const { createFromReadableStream: decode } =\n await import('virtual:tanstack-rsc-browser-decode')\n return decode(stream)\n },\n )\n\n/**\n * Decode a Flight stream from a fetch Response.\n * Browser only - will throw if called on the server.\n *\n * @example\n * ```tsx\n * // From server function returning raw Response\n * const tree = await createFromFetch(getFlightResponse())\n *\n * // From API route\n * const tree = await createFromFetch(fetch('/api/rsc-flight'))\n * ```\n */\nexport const createFromFetch = createClientOnlyFn(\n async (fetchPromise: Promise<Response>): Promise<React.ReactNode> => {\n const { createFromFetch: decode } =\n await import('virtual:tanstack-rsc-browser-decode')\n return decode(fetchPromise)\n },\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,2BAA2B,oBAAoB,CACzD,OACC,OAAO,WAAiE;CACtE,MAAM,EAAE,0BAA0B,WAChC,MAAM,OAAO;AACf,QAAO,OAAO,OAAO;EAExB,CACA,OACC,OAAO,WAAiE;CACtE,MAAM,EAAE,0BAA0B,WAChC,MAAM,OAAO;AACf,QAAO,OAAO,OAAO;EAExB;;;;;;;;;;;;;;AAeH,IAAa,kBAAkB,mBAC7B,OAAO,iBAA8D;CACnE,MAAM,EAAE,iBAAiB,WACvB,MAAM,OAAO;AACf,QAAO,OAAO,aAAa;EAE9B"}
1
+ {"version":3,"file":"flight.js","names":[],"sources":["../../src/flight.ts"],"sourcesContent":["/**\n * Low-level Flight stream APIs for decoding RSC streams.\n *\n * These functions provide direct access to RSC Flight stream decoding,\n * allowing advanced use cases like:\n * - Server functions returning raw Flight Response\n * - API routes streaming Flight payloads\n * - Custom Flight stream handling via RawStream\n *\n * `createFromReadableStream` works in both SSR and browser contexts.\n * `createFromFetch` is browser-only.\n *\n * NOTE: Dynamic imports keep decode initialisation runtime-specific. The\n * concrete implementation comes from bundler-owned virtual modules.\n */\n\nimport {\n createClientOnlyFn,\n createIsomorphicFn,\n} from '@tanstack/start-fn-stubs'\n\n/**\n * Decode a Flight stream into React elements.\n * Works in both SSR and browser contexts.\n *\n * @example\n * ```tsx\n * const rawStream = await getRscRawStream()\n * const tree = await createFromReadableStream(rawStream)\n * return <>{tree}</>\n * ```\n */\nexport const createFromReadableStream = createIsomorphicFn()\n .server(\n async (stream: ReadableStream<Uint8Array>): Promise<React.ReactNode> => {\n const { createFromReadableStream: decode } =\n await import('virtual:tanstack-rsc-ssr-decode')\n return decode(stream) as React.ReactNode\n },\n )\n .client(\n async (stream: ReadableStream<Uint8Array>): Promise<React.ReactNode> => {\n const { createFromReadableStream: decode } =\n await import('virtual:tanstack-rsc-browser-decode')\n return decode(stream)\n },\n )\n\n/**\n * Decode a Flight stream from a fetch Response.\n * Browser only - will throw if called on the server.\n *\n * @example\n * ```tsx\n * // From server function returning raw Response\n * const tree = await createFromFetch(getFlightResponse())\n *\n * // From API route\n * const tree = await createFromFetch(fetch('/api/rsc-flight'))\n * ```\n */\nexport const createFromFetch = createClientOnlyFn(\n async (fetchPromise: Promise<Response>): Promise<React.ReactNode> => {\n const { createFromFetch: decode } =\n await import('virtual:tanstack-rsc-browser-decode')\n return decode(fetchPromise)\n },\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,2BAA2B,mBAAmB,EACxD,OACC,OAAO,WAAiE;CACtE,MAAM,EAAE,0BAA0B,WAChC,MAAM,OAAO;CACf,OAAO,OAAO,MAAM;AACtB,CACF,EACC,OACC,OAAO,WAAiE;CACtE,MAAM,EAAE,0BAA0B,WAChC,MAAM,OAAO;CACf,OAAO,OAAO,MAAM;AACtB,CACF;;;;;;;;;;;;;;AAeF,IAAa,kBAAkB,mBAC7B,OAAO,iBAA8D;CACnE,MAAM,EAAE,iBAAiB,WACvB,MAAM,OAAO;CACf,OAAO,OAAO,YAAY;AAC5B,CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"flight.stub.js","names":[],"sources":["../../src/flight.stub.ts"],"sourcesContent":["/**\n * Client stub for renderToReadableStream.\n *\n * This function should never be called at runtime on the client.\n * It exists only to provide types for bundler imports in client bundles.\n * The real implementation only runs inside RSC context (server functions).\n */\nexport function renderToReadableStream(\n _node: React.ReactNode,\n): ReadableStream<Uint8Array> {\n throw new Error(\n 'renderToReadableStream cannot be called on the client. ' +\n 'This function should only be called inside RSC context (server functions).',\n )\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,uBACd,OAC4B;AAC5B,OAAM,IAAI,MACR,oIAED"}
1
+ {"version":3,"file":"flight.stub.js","names":[],"sources":["../../src/flight.stub.ts"],"sourcesContent":["/**\n * Client stub for renderToReadableStream.\n *\n * This function should never be called at runtime on the client.\n * It exists only to provide types for bundler imports in client bundles.\n * The real implementation only runs inside RSC context (server functions).\n */\nexport function renderToReadableStream(\n _node: React.ReactNode,\n): ReadableStream<Uint8Array> {\n throw new Error(\n 'renderToReadableStream cannot be called on the client. ' +\n 'This function should only be called inside RSC context (server functions).',\n )\n}\n"],"mappings":";;;;;;;;AAOA,SAAgB,uBACd,OAC4B;CAC5B,MAAM,IAAI,MACR,mIAEF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"rscCssTransform.js","names":[],"sources":["../../../src/plugin/rscCssTransform.ts"],"sourcesContent":["import type {\n StartCompilerImportTransform,\n StartCompilerTransformContext,\n} from '@tanstack/start-plugin-core'\n\nconst TSS_SERVERFN_SPLIT_PARAM = 'tss-serverfn-split'\nconst RSC_CSS_OPTIONS_KEY = '__tanstackStartRscCss'\n\ntype BabelTypes = StartCompilerTransformContext['types']\ntype BabelExpression = ReturnType<\n StartCompilerTransformContext['parseExpression']\n>\n\ntype RscCssTransformKind =\n | 'renderServerComponent'\n | 'createCompositeComponent'\n | 'renderToReadableStream'\n\nexport function createRscCssCompilerTransforms(opts: {\n loadCssExpression: string\n serverFnProviderOnly?: boolean | undefined\n}): Array<StartCompilerImportTransform> {\n let loadCssExpression: BabelExpression | undefined\n\n const getLoadCssExpression = (context: StartCompilerTransformContext) => {\n loadCssExpression ??= context.parseExpression(opts.loadCssExpression)\n return loadCssExpression\n }\n\n return [\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'renderServerComponent',\n name: 'react-rsc-render-server-component-css',\n }),\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'createCompositeComponent',\n name: 'react-rsc-create-composite-component-css',\n }),\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'renderToReadableStream',\n name: 'react-rsc-render-to-readable-stream-css',\n }),\n ]\n}\n\nfunction createRscCssCompilerTransform(opts: {\n name: string\n kind: RscCssTransformKind\n getLoadCssExpression: (\n context: StartCompilerTransformContext,\n ) => BabelExpression\n serverFnProviderOnly?: boolean | undefined\n}): StartCompilerImportTransform {\n return {\n name: opts.name,\n environment: 'server',\n imports: [\n {\n libName: '@tanstack/react-start/rsc',\n rootExport: opts.kind,\n },\n {\n libName: '@tanstack/react-start-rsc',\n rootExport: opts.kind,\n },\n ],\n detect: new RegExp(`\\\\b${opts.kind}\\\\b`),\n transform: (candidates, context) => {\n if (\n opts.serverFnProviderOnly &&\n !context.id.includes(TSS_SERVERFN_SPLIT_PARAM)\n ) {\n return\n }\n\n const t = context.types\n const loadCssExpression = opts.getLoadCssExpression(context)\n const cloneLoadCssExpression = () => t.cloneNode(loadCssExpression)\n\n for (const candidate of candidates) {\n const args = candidate.path.node.arguments\n if (args.length !== 1) continue\n\n if (opts.kind === 'renderToReadableStream') {\n const firstArg = args[0]\n if (!firstArg || !t.isExpression(firstArg)) continue\n if (!isTopLevelJsx(t, firstArg)) continue\n\n args[0] = createCssFragment(\n t,\n firstArg,\n cloneLoadCssExpression(),\n ) as typeof firstArg\n continue\n }\n\n args.push(\n t.objectExpression([\n t.objectProperty(\n t.identifier(RSC_CSS_OPTIONS_KEY),\n cloneLoadCssExpression(),\n ),\n ]),\n )\n }\n },\n }\n}\n\nfunction isTopLevelJsx(t: BabelTypes, expr: BabelExpression): boolean {\n const unwrapped = unwrapTransparentExpression(t, expr)\n return t.isJSXElement(unwrapped) || t.isJSXFragment(unwrapped)\n}\n\nfunction unwrapTransparentExpression(\n t: BabelTypes,\n expr: BabelExpression,\n): BabelExpression {\n let current = expr\n while (\n t.isParenthesizedExpression(current) ||\n t.isTSAsExpression(current) ||\n t.isTSSatisfiesExpression(current) ||\n t.isTSTypeAssertion(current) ||\n t.isTSNonNullExpression(current)\n ) {\n current = current.expression\n }\n return current\n}\n\nfunction createCssFragment(\n t: BabelTypes,\n original: BabelExpression,\n loadCssExpression: BabelExpression,\n) {\n const unwrapped = unwrapTransparentExpression(t, original)\n return t.jsxFragment(t.jsxOpeningFragment(), t.jsxClosingFragment(), [\n t.jsxExpressionContainer(loadCssExpression),\n t.isJSXElement(unwrapped) || t.isJSXFragment(unwrapped)\n ? unwrapped\n : t.jsxExpressionContainer(original),\n ])\n}\n"],"mappings":";AAKA,IAAM,2BAA2B;AACjC,IAAM,sBAAsB;AAY5B,SAAgB,+BAA+B,MAGP;CACtC,IAAI;CAEJ,MAAM,wBAAwB,YAA2C;AACvE,wBAAsB,QAAQ,gBAAgB,KAAK,kBAAkB;AACrE,SAAO;;AAGT,QAAO;EACL,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;GACP,CAAC;EACF,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;GACP,CAAC;EACF,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;GACP,CAAC;EACH;;AAGH,SAAS,8BAA8B,MAON;AAC/B,QAAO;EACL,MAAM,KAAK;EACX,aAAa;EACb,SAAS,CACP;GACE,SAAS;GACT,YAAY,KAAK;GAClB,EACD;GACE,SAAS;GACT,YAAY,KAAK;GAClB,CACF;EACD,QAAQ,IAAI,OAAO,MAAM,KAAK,KAAK,KAAK;EACxC,YAAY,YAAY,YAAY;AAClC,OACE,KAAK,wBACL,CAAC,QAAQ,GAAG,SAAS,yBAAyB,CAE9C;GAGF,MAAM,IAAI,QAAQ;GAClB,MAAM,oBAAoB,KAAK,qBAAqB,QAAQ;GAC5D,MAAM,+BAA+B,EAAE,UAAU,kBAAkB;AAEnE,QAAK,MAAM,aAAa,YAAY;IAClC,MAAM,OAAO,UAAU,KAAK,KAAK;AACjC,QAAI,KAAK,WAAW,EAAG;AAEvB,QAAI,KAAK,SAAS,0BAA0B;KAC1C,MAAM,WAAW,KAAK;AACtB,SAAI,CAAC,YAAY,CAAC,EAAE,aAAa,SAAS,CAAE;AAC5C,SAAI,CAAC,cAAc,GAAG,SAAS,CAAE;AAEjC,UAAK,KAAK,kBACR,GACA,UACA,wBAAwB,CACzB;AACD;;AAGF,SAAK,KACH,EAAE,iBAAiB,CACjB,EAAE,eACA,EAAE,WAAW,oBAAoB,EACjC,wBAAwB,CACzB,CACF,CAAC,CACH;;;EAGN;;AAGH,SAAS,cAAc,GAAe,MAAgC;CACpE,MAAM,YAAY,4BAA4B,GAAG,KAAK;AACtD,QAAO,EAAE,aAAa,UAAU,IAAI,EAAE,cAAc,UAAU;;AAGhE,SAAS,4BACP,GACA,MACiB;CACjB,IAAI,UAAU;AACd,QACE,EAAE,0BAA0B,QAAQ,IACpC,EAAE,iBAAiB,QAAQ,IAC3B,EAAE,wBAAwB,QAAQ,IAClC,EAAE,kBAAkB,QAAQ,IAC5B,EAAE,sBAAsB,QAAQ,CAEhC,WAAU,QAAQ;AAEpB,QAAO;;AAGT,SAAS,kBACP,GACA,UACA,mBACA;CACA,MAAM,YAAY,4BAA4B,GAAG,SAAS;AAC1D,QAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,EAAE,oBAAoB,EAAE,CACnE,EAAE,uBAAuB,kBAAkB,EAC3C,EAAE,aAAa,UAAU,IAAI,EAAE,cAAc,UAAU,GACnD,YACA,EAAE,uBAAuB,SAAS,CACvC,CAAC"}
1
+ {"version":3,"file":"rscCssTransform.js","names":[],"sources":["../../../src/plugin/rscCssTransform.ts"],"sourcesContent":["import type {\n StartCompilerImportTransform,\n StartCompilerTransformContext,\n} from '@tanstack/start-plugin-core'\n\nconst TSS_SERVERFN_SPLIT_PARAM = 'tss-serverfn-split'\nconst RSC_CSS_OPTIONS_KEY = '__tanstackStartRscCss'\n\ntype BabelTypes = StartCompilerTransformContext['types']\ntype BabelExpression = ReturnType<\n StartCompilerTransformContext['parseExpression']\n>\n\ntype RscCssTransformKind =\n | 'renderServerComponent'\n | 'createCompositeComponent'\n | 'renderToReadableStream'\n\nexport function createRscCssCompilerTransforms(opts: {\n loadCssExpression: string\n serverFnProviderOnly?: boolean | undefined\n}): Array<StartCompilerImportTransform> {\n let loadCssExpression: BabelExpression | undefined\n\n const getLoadCssExpression = (context: StartCompilerTransformContext) => {\n loadCssExpression ??= context.parseExpression(opts.loadCssExpression)\n return loadCssExpression\n }\n\n return [\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'renderServerComponent',\n name: 'react-rsc-render-server-component-css',\n }),\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'createCompositeComponent',\n name: 'react-rsc-create-composite-component-css',\n }),\n createRscCssCompilerTransform({\n serverFnProviderOnly: opts.serverFnProviderOnly,\n getLoadCssExpression,\n kind: 'renderToReadableStream',\n name: 'react-rsc-render-to-readable-stream-css',\n }),\n ]\n}\n\nfunction createRscCssCompilerTransform(opts: {\n name: string\n kind: RscCssTransformKind\n getLoadCssExpression: (\n context: StartCompilerTransformContext,\n ) => BabelExpression\n serverFnProviderOnly?: boolean | undefined\n}): StartCompilerImportTransform {\n return {\n name: opts.name,\n environment: 'server',\n imports: [\n {\n libName: '@tanstack/react-start/rsc',\n rootExport: opts.kind,\n },\n {\n libName: '@tanstack/react-start-rsc',\n rootExport: opts.kind,\n },\n ],\n detect: new RegExp(`\\\\b${opts.kind}\\\\b`),\n transform: (candidates, context) => {\n if (\n opts.serverFnProviderOnly &&\n !context.id.includes(TSS_SERVERFN_SPLIT_PARAM)\n ) {\n return\n }\n\n const t = context.types\n const loadCssExpression = opts.getLoadCssExpression(context)\n const cloneLoadCssExpression = () => t.cloneNode(loadCssExpression)\n\n for (const candidate of candidates) {\n const args = candidate.path.node.arguments\n if (args.length !== 1) continue\n\n if (opts.kind === 'renderToReadableStream') {\n const firstArg = args[0]\n if (!firstArg || !t.isExpression(firstArg)) continue\n if (!isTopLevelJsx(t, firstArg)) continue\n\n args[0] = createCssFragment(\n t,\n firstArg,\n cloneLoadCssExpression(),\n ) as typeof firstArg\n continue\n }\n\n args.push(\n t.objectExpression([\n t.objectProperty(\n t.identifier(RSC_CSS_OPTIONS_KEY),\n cloneLoadCssExpression(),\n ),\n ]),\n )\n }\n },\n }\n}\n\nfunction isTopLevelJsx(t: BabelTypes, expr: BabelExpression): boolean {\n const unwrapped = unwrapTransparentExpression(t, expr)\n return t.isJSXElement(unwrapped) || t.isJSXFragment(unwrapped)\n}\n\nfunction unwrapTransparentExpression(\n t: BabelTypes,\n expr: BabelExpression,\n): BabelExpression {\n let current = expr\n while (\n t.isParenthesizedExpression(current) ||\n t.isTSAsExpression(current) ||\n t.isTSSatisfiesExpression(current) ||\n t.isTSTypeAssertion(current) ||\n t.isTSNonNullExpression(current)\n ) {\n current = current.expression\n }\n return current\n}\n\nfunction createCssFragment(\n t: BabelTypes,\n original: BabelExpression,\n loadCssExpression: BabelExpression,\n) {\n const unwrapped = unwrapTransparentExpression(t, original)\n return t.jsxFragment(t.jsxOpeningFragment(), t.jsxClosingFragment(), [\n t.jsxExpressionContainer(loadCssExpression),\n t.isJSXElement(unwrapped) || t.isJSXFragment(unwrapped)\n ? unwrapped\n : t.jsxExpressionContainer(original),\n ])\n}\n"],"mappings":";AAKA,IAAM,2BAA2B;AACjC,IAAM,sBAAsB;AAY5B,SAAgB,+BAA+B,MAGP;CACtC,IAAI;CAEJ,MAAM,wBAAwB,YAA2C;EACvE,sBAAsB,QAAQ,gBAAgB,KAAK,iBAAiB;EACpE,OAAO;CACT;CAEA,OAAO;EACL,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;EACR,CAAC;EACD,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;EACR,CAAC;EACD,8BAA8B;GAC5B,sBAAsB,KAAK;GAC3B;GACA,MAAM;GACN,MAAM;EACR,CAAC;CACH;AACF;AAEA,SAAS,8BAA8B,MAON;CAC/B,OAAO;EACL,MAAM,KAAK;EACX,aAAa;EACb,SAAS,CACP;GACE,SAAS;GACT,YAAY,KAAK;EACnB,GACA;GACE,SAAS;GACT,YAAY,KAAK;EACnB,CACF;EACA,QAAQ,IAAI,OAAO,MAAM,KAAK,KAAK,IAAI;EACvC,YAAY,YAAY,YAAY;GAClC,IACE,KAAK,wBACL,CAAC,QAAQ,GAAG,SAAS,wBAAwB,GAE7C;GAGF,MAAM,IAAI,QAAQ;GAClB,MAAM,oBAAoB,KAAK,qBAAqB,OAAO;GAC3D,MAAM,+BAA+B,EAAE,UAAU,iBAAiB;GAElE,KAAK,MAAM,aAAa,YAAY;IAClC,MAAM,OAAO,UAAU,KAAK,KAAK;IACjC,IAAI,KAAK,WAAW,GAAG;IAEvB,IAAI,KAAK,SAAS,0BAA0B;KAC1C,MAAM,WAAW,KAAK;KACtB,IAAI,CAAC,YAAY,CAAC,EAAE,aAAa,QAAQ,GAAG;KAC5C,IAAI,CAAC,cAAc,GAAG,QAAQ,GAAG;KAEjC,KAAK,KAAK,kBACR,GACA,UACA,uBAAuB,CACzB;KACA;IACF;IAEA,KAAK,KACH,EAAE,iBAAiB,CACjB,EAAE,eACA,EAAE,WAAW,mBAAmB,GAChC,uBAAuB,CACzB,CACF,CAAC,CACH;GACF;EACF;CACF;AACF;AAEA,SAAS,cAAc,GAAe,MAAgC;CACpE,MAAM,YAAY,4BAA4B,GAAG,IAAI;CACrD,OAAO,EAAE,aAAa,SAAS,KAAK,EAAE,cAAc,SAAS;AAC/D;AAEA,SAAS,4BACP,GACA,MACiB;CACjB,IAAI,UAAU;CACd,OACE,EAAE,0BAA0B,OAAO,KACnC,EAAE,iBAAiB,OAAO,KAC1B,EAAE,wBAAwB,OAAO,KACjC,EAAE,kBAAkB,OAAO,KAC3B,EAAE,sBAAsB,OAAO,GAE/B,UAAU,QAAQ;CAEpB,OAAO;AACT;AAEA,SAAS,kBACP,GACA,UACA,mBACA;CACA,MAAM,YAAY,4BAA4B,GAAG,QAAQ;CACzD,OAAO,EAAE,YAAY,EAAE,mBAAmB,GAAG,EAAE,mBAAmB,GAAG,CACnE,EAAE,uBAAuB,iBAAiB,GAC1C,EAAE,aAAa,SAAS,KAAK,EAAE,cAAc,SAAS,IAClD,YACA,EAAE,uBAAuB,QAAQ,CACvC,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","names":[],"sources":["../../../src/plugin/vite.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\nimport path from 'pathe'\nimport { createVirtualModule } from '@tanstack/start-plugin-core/vite'\nimport { createRscCssCompilerTransforms } from './rscCssTransform'\nimport type {\n TanStackStartVitePluginCoreOptions,\n ViteRscForwardSsrResolverStrategy,\n} from '@tanstack/start-plugin-core/vite'\nimport type { PluginOption, UserConfig } from 'vite'\n\nconst isClientEnvironment = (env: { config: { consumer: string } }) =>\n env.config.consumer === 'client'\n\n// Virtual module ids used by the React Start RSC runtime.\nconst RSC_HMR_VIRTUAL_ID = 'virtual:tanstack-rsc-hmr'\nconst RSC_RUNTIME_VIRTUAL_ID = 'virtual:tanstack-rsc-runtime'\nconst RSC_BROWSER_DECODE_VIRTUAL_ID = 'virtual:tanstack-rsc-browser-decode'\nconst RSC_SSR_DECODE_VIRTUAL_ID = 'virtual:tanstack-rsc-ssr-decode'\nconst RSC_ENV_NAME = 'rsc'\n\nconst currentDir = path.dirname(fileURLToPath(import.meta.url))\nconst entryDir = path.resolve(currentDir, '..', '..', 'plugin', 'entry')\nconst rscEntryPath = path.resolve(entryDir, 'rsc.tsx')\n\nexport function configureRsc(): {\n envName: string\n providerEnvironmentName: TanStackStartVitePluginCoreOptions['providerEnvironmentName']\n ssrResolverStrategy: TanStackStartVitePluginCoreOptions['ssrResolverStrategy']\n serializationAdapters: TanStackStartVitePluginCoreOptions['serializationAdapters']\n compilerTransforms: TanStackStartVitePluginCoreOptions['compilerTransforms']\n} {\n const serializationAdapters: TanStackStartVitePluginCoreOptions['serializationAdapters'] =\n [\n // IMPORTANT: plugin-adapters-plugin only calls the top-level factory once.\n // That factory must return a flat array of adapters (not nested arrays),\n // otherwise router-core ends up with non-adapter entries and Seroval crashes.\n {\n client: {\n module: '@tanstack/react-start/rsc/serialization/client',\n export: 'rscSerializationAdapter',\n isFactory: true,\n },\n server: {\n module: '@tanstack/react-start/rsc/serialization/server',\n export: 'rscSerializationAdapter',\n isFactory: true,\n },\n },\n ]\n const ssrResolverStrategy = {\n type: 'vite-rsc-forward',\n sourceEnvironmentName: RSC_ENV_NAME,\n sourceEntry: 'index',\n exportName: 'getServerFnById',\n } satisfies ViteRscForwardSsrResolverStrategy\n return {\n envName: RSC_ENV_NAME,\n providerEnvironmentName: RSC_ENV_NAME,\n ssrResolverStrategy,\n serializationAdapters,\n compilerTransforms: createRscCssCompilerTransforms({\n loadCssExpression: 'import.meta.viteRsc.loadCss()',\n }),\n }\n}\nexport function reactStartRscVitePlugin(): PluginOption {\n return [\n // When RSC is enabled, SSR needs noExternal: true to ensure single React instance.\n // The RSC decoder's dynamic imports for client components can cause module duplication\n // without this, leading to \"Invalid hook call\" errors.\n // We use the top-level `ssr` config option as `environments.ssr.resolve.noExternal`\n // doesn't have the same effect.\n {\n name: 'tanstack-react-start:rsc-ssr-config',\n config() {\n return {\n ssr: {\n noExternal: true,\n },\n }\n },\n },\n {\n name: 'tanstack-react-start:rsc-env-config',\n config() {\n return {\n rsc: {\n // Disable @vitejs/plugin-rsc's built-in server handler middleware.\n // TanStack Start has its own request handling via the SSR environment.\n serverHandler: false,\n // Disable CSS link precedence to prevent React 19 SSR suspension\n // TanStack Start handles CSS preloading via manifest injection instead\n cssLinkPrecedence: false,\n },\n environments: {\n [RSC_ENV_NAME]: {\n consumer: 'server',\n // Force @tanstack packages to be processed by Vite as source code\n // rather than treated as external modules. This ensures:\n // 1. createIsomorphicFn transforms are applied\n // 2. Imports are resolved within the RSC environment context\n // with proper react-server conditions and pre-bundled deps\n resolve: {\n noExternal: [\n '@tanstack/start**',\n '@tanstack/react-start',\n '@tanstack/react-start-rsc',\n '@tanstack/react-router',\n ],\n },\n build: {\n rollupOptions: {\n input: {\n index: rscEntryPath,\n },\n },\n },\n },\n },\n } satisfies UserConfig & {\n rsc: {\n serverHandler: false\n cssLinkPrecedence?: boolean\n }\n }\n },\n },\n\n {\n name: 'tanstack-react-start:rsc-scan-virtual-fallback',\n apply: 'build',\n applyToEnvironment(env) {\n return env.name === RSC_ENV_NAME\n },\n load: {\n filter: {\n id: /^(virtual:tanstack-rsc-runtime|virtual:vite-rsc\\/encryption-key)$/,\n },\n handler(id) {\n if (this.environment.config.build.write !== false) return\n\n if (id === RSC_RUNTIME_VIRTUAL_ID) {\n return `export { renderToReadableStream, createFromReadableStream, createTemporaryReferenceSet, decodeReply, loadServerAction, decodeAction, decodeFormState } from '@vitejs/plugin-rsc/rsc'`\n }\n\n if (id === 'virtual:vite-rsc/encryption-key') {\n return `export default () => ''`\n }\n\n return undefined\n },\n },\n },\n\n // Runtime bridge into the Vite RSC environment.\n createVirtualModule({\n name: 'tanstack-react-start:rsc-runtime-virtual',\n moduleId: RSC_RUNTIME_VIRTUAL_ID,\n load() {\n const envName = this.environment.name\n if (envName === RSC_ENV_NAME) {\n return `export { renderToReadableStream, createFromReadableStream, createTemporaryReferenceSet, decodeReply, loadServerAction, decodeAction, decodeFormState } from '@vitejs/plugin-rsc/rsc'`\n }\n return `\nexport function renderToReadableStream() { throw new Error('renderToReadableStream can only be used in RSC environment'); }\nexport function createFromReadableStream() { throw new Error('createFromReadableStream can only be used in RSC environment'); }\nexport function createTemporaryReferenceSet() { throw new Error('createTemporaryReferenceSet can only be used in RSC environment'); }\nexport function decodeReply() { throw new Error('decodeReply can only be used in RSC environment'); }\nexport function loadServerAction() { throw new Error('loadServerAction can only be used in RSC environment'); }\nexport function decodeAction() { throw new Error('decodeAction can only be used in RSC environment'); }\nexport function decodeFormState() { throw new Error('decodeFormState can only be used in RSC environment'); }\n`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-browser-decode-virtual',\n moduleId: RSC_BROWSER_DECODE_VIRTUAL_ID,\n load() {\n return `export { createFromReadableStream, createFromFetch } from '@vitejs/plugin-rsc/browser'`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-ssr-decode-virtual',\n moduleId: RSC_SSR_DECODE_VIRTUAL_ID,\n load() {\n return `export { setOnClientReference, createFromReadableStream } from '@vitejs/plugin-rsc/ssr'`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-hmr-virtual:dev',\n moduleId: RSC_HMR_VIRTUAL_ID,\n apply: 'serve',\n applyToEnvironment: isClientEnvironment,\n load() {\n return `\nexport function setupRscHmr() {\nif (!import.meta.hot) {\n return\n}\n\n let __invalidateQueued = false\n\n function __queueInvalidate() {\n if (__invalidateQueued) return\n __invalidateQueued = true\n queueMicrotask(async () => {\n __invalidateQueued = false\n try {\n const router = window.__TSR_ROUTER__\n if (!router) {\n console.warn('[rsc:hmr] No router found on window.__TSR_ROUTER__')\n return\n }\n await router.invalidate()\n } catch (e) {\n console.warn('[rsc:hmr] Failed to invalidate router:', e)\n }\n })\n }\n\n import.meta.hot.on('rsc:update', () => {\n __queueInvalidate()\n })\n}\n`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-hmr-virtual:prod',\n moduleId: RSC_HMR_VIRTUAL_ID,\n applyToEnvironment: isClientEnvironment,\n apply: 'build',\n load() {\n return 'export function setupRscHmr() {} '\n },\n }),\n ]\n}\n"],"mappings":";;;;;AAUA,IAAM,uBAAuB,QAC3B,IAAI,OAAO,aAAa;AAG1B,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,gCAAgC;AACtC,IAAM,4BAA4B;AAClC,IAAM,eAAe;AAErB,IAAM,aAAa,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAC/D,IAAM,WAAW,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,QAAQ;AACxE,IAAM,eAAe,KAAK,QAAQ,UAAU,UAAU;AAEtD,SAAgB,eAMd;AAyBA,QAAO;EACL,SAAS;EACT,yBAAyB;EACzB,qBAT0B;GAC1B,MAAM;GACN,uBAAuB;GACvB,aAAa;GACb,YAAY;GACb;EAKC,uBA3BA,CAIE;GACE,QAAQ;IACN,QAAQ;IACR,QAAQ;IACR,WAAW;IACZ;GACD,QAAQ;IACN,QAAQ;IACR,QAAQ;IACR,WAAW;IACZ;GACF,CACF;EAYD,oBAAoB,+BAA+B,EACjD,mBAAmB,iCACpB,CAAC;EACH;;AAEH,SAAgB,0BAAwC;AACtD,QAAO;EAML;GACE,MAAM;GACN,SAAS;AACP,WAAO,EACL,KAAK,EACH,YAAY,MACb,EACF;;GAEJ;EACD;GACE,MAAM;GACN,SAAS;AACP,WAAO;KACL,KAAK;MAGH,eAAe;MAGf,mBAAmB;MACpB;KACD,cAAc,GACX,eAAe;MACd,UAAU;MAMV,SAAS,EACP,YAAY;OACV;OACA;OACA;OACA;OACD,EACF;MACD,OAAO,EACL,eAAe,EACb,OAAO,EACL,OAAO,cACR,EACF,EACF;MACF,EACF;KACF;;GAOJ;EAED;GACE,MAAM;GACN,OAAO;GACP,mBAAmB,KAAK;AACtB,WAAO,IAAI,SAAS;;GAEtB,MAAM;IACJ,QAAQ,EACN,IAAI,qEACL;IACD,QAAQ,IAAI;AACV,SAAI,KAAK,YAAY,OAAO,MAAM,UAAU,MAAO;AAEnD,SAAI,OAAO,uBACT,QAAO;AAGT,SAAI,OAAO,kCACT,QAAO;;IAKZ;GACF;EAGD,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;AAEL,QADgB,KAAK,YAAY,SACjB,aACd,QAAO;AAET,WAAO;;;;;;;;;;GAUV,CAAC;EACF,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;AACL,WAAO;;GAEV,CAAC;EACF,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;AACL,WAAO;;GAEV,CAAC;EACF,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;GACP,oBAAoB;GACpB,OAAO;AACL,WAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCV,CAAC;EACF,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,oBAAoB;GACpB,OAAO;GACP,OAAO;AACL,WAAO;;GAEV,CAAC;EACH"}
1
+ {"version":3,"file":"vite.js","names":[],"sources":["../../../src/plugin/vite.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\nimport path from 'pathe'\nimport { createVirtualModule } from '@tanstack/start-plugin-core/vite'\nimport { createRscCssCompilerTransforms } from './rscCssTransform'\nimport type {\n TanStackStartVitePluginCoreOptions,\n ViteRscForwardSsrResolverStrategy,\n} from '@tanstack/start-plugin-core/vite'\nimport type { PluginOption, UserConfig } from 'vite'\n\nconst isClientEnvironment = (env: { config: { consumer: string } }) =>\n env.config.consumer === 'client'\n\n// Virtual module ids used by the React Start RSC runtime.\nconst RSC_HMR_VIRTUAL_ID = 'virtual:tanstack-rsc-hmr'\nconst RSC_RUNTIME_VIRTUAL_ID = 'virtual:tanstack-rsc-runtime'\nconst RSC_BROWSER_DECODE_VIRTUAL_ID = 'virtual:tanstack-rsc-browser-decode'\nconst RSC_SSR_DECODE_VIRTUAL_ID = 'virtual:tanstack-rsc-ssr-decode'\nconst RSC_ENV_NAME = 'rsc'\n\nconst currentDir = path.dirname(fileURLToPath(import.meta.url))\nconst entryDir = path.resolve(currentDir, '..', '..', 'plugin', 'entry')\nconst rscEntryPath = path.resolve(entryDir, 'rsc.tsx')\n\nexport function configureRsc(): {\n envName: string\n providerEnvironmentName: TanStackStartVitePluginCoreOptions['providerEnvironmentName']\n ssrResolverStrategy: TanStackStartVitePluginCoreOptions['ssrResolverStrategy']\n serializationAdapters: TanStackStartVitePluginCoreOptions['serializationAdapters']\n compilerTransforms: TanStackStartVitePluginCoreOptions['compilerTransforms']\n} {\n const serializationAdapters: TanStackStartVitePluginCoreOptions['serializationAdapters'] =\n [\n // IMPORTANT: plugin-adapters-plugin only calls the top-level factory once.\n // That factory must return a flat array of adapters (not nested arrays),\n // otherwise router-core ends up with non-adapter entries and Seroval crashes.\n {\n client: {\n module: '@tanstack/react-start/rsc/serialization/client',\n export: 'rscSerializationAdapter',\n isFactory: true,\n },\n server: {\n module: '@tanstack/react-start/rsc/serialization/server',\n export: 'rscSerializationAdapter',\n isFactory: true,\n },\n },\n ]\n const ssrResolverStrategy = {\n type: 'vite-rsc-forward',\n sourceEnvironmentName: RSC_ENV_NAME,\n sourceEntry: 'index',\n exportName: 'getServerFnById',\n } satisfies ViteRscForwardSsrResolverStrategy\n return {\n envName: RSC_ENV_NAME,\n providerEnvironmentName: RSC_ENV_NAME,\n ssrResolverStrategy,\n serializationAdapters,\n compilerTransforms: createRscCssCompilerTransforms({\n loadCssExpression: 'import.meta.viteRsc.loadCss()',\n }),\n }\n}\nexport function reactStartRscVitePlugin(): PluginOption {\n return [\n // When RSC is enabled, SSR needs noExternal: true to ensure single React instance.\n // The RSC decoder's dynamic imports for client components can cause module duplication\n // without this, leading to \"Invalid hook call\" errors.\n // We use the top-level `ssr` config option as `environments.ssr.resolve.noExternal`\n // doesn't have the same effect.\n {\n name: 'tanstack-react-start:rsc-ssr-config',\n config() {\n return {\n ssr: {\n noExternal: true,\n },\n }\n },\n },\n {\n name: 'tanstack-react-start:rsc-env-config',\n config() {\n return {\n rsc: {\n // Disable @vitejs/plugin-rsc's built-in server handler middleware.\n // TanStack Start has its own request handling via the SSR environment.\n serverHandler: false,\n // Disable CSS link precedence to prevent React 19 SSR suspension\n // TanStack Start handles CSS preloading via manifest injection instead\n cssLinkPrecedence: false,\n },\n environments: {\n [RSC_ENV_NAME]: {\n consumer: 'server',\n // Force @tanstack packages to be processed by Vite as source code\n // rather than treated as external modules. This ensures:\n // 1. createIsomorphicFn transforms are applied\n // 2. Imports are resolved within the RSC environment context\n // with proper react-server conditions and pre-bundled deps\n resolve: {\n noExternal: [\n '@tanstack/start**',\n '@tanstack/react-start',\n '@tanstack/react-start-rsc',\n '@tanstack/react-router',\n ],\n },\n build: {\n rollupOptions: {\n input: {\n index: rscEntryPath,\n },\n },\n },\n },\n },\n } satisfies UserConfig & {\n rsc: {\n serverHandler: false\n cssLinkPrecedence?: boolean\n }\n }\n },\n },\n\n {\n name: 'tanstack-react-start:rsc-scan-virtual-fallback',\n apply: 'build',\n applyToEnvironment(env) {\n return env.name === RSC_ENV_NAME\n },\n load: {\n filter: {\n id: /^(virtual:tanstack-rsc-runtime|virtual:vite-rsc\\/encryption-key)$/,\n },\n handler(id) {\n if (this.environment.config.build.write !== false) return\n\n if (id === RSC_RUNTIME_VIRTUAL_ID) {\n return `export { renderToReadableStream, createFromReadableStream, createTemporaryReferenceSet, decodeReply, loadServerAction, decodeAction, decodeFormState } from '@vitejs/plugin-rsc/rsc'`\n }\n\n if (id === 'virtual:vite-rsc/encryption-key') {\n return `export default () => ''`\n }\n\n return undefined\n },\n },\n },\n\n // Runtime bridge into the Vite RSC environment.\n createVirtualModule({\n name: 'tanstack-react-start:rsc-runtime-virtual',\n moduleId: RSC_RUNTIME_VIRTUAL_ID,\n load() {\n const envName = this.environment.name\n if (envName === RSC_ENV_NAME) {\n return `export { renderToReadableStream, createFromReadableStream, createTemporaryReferenceSet, decodeReply, loadServerAction, decodeAction, decodeFormState } from '@vitejs/plugin-rsc/rsc'`\n }\n return `\nexport function renderToReadableStream() { throw new Error('renderToReadableStream can only be used in RSC environment'); }\nexport function createFromReadableStream() { throw new Error('createFromReadableStream can only be used in RSC environment'); }\nexport function createTemporaryReferenceSet() { throw new Error('createTemporaryReferenceSet can only be used in RSC environment'); }\nexport function decodeReply() { throw new Error('decodeReply can only be used in RSC environment'); }\nexport function loadServerAction() { throw new Error('loadServerAction can only be used in RSC environment'); }\nexport function decodeAction() { throw new Error('decodeAction can only be used in RSC environment'); }\nexport function decodeFormState() { throw new Error('decodeFormState can only be used in RSC environment'); }\n`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-browser-decode-virtual',\n moduleId: RSC_BROWSER_DECODE_VIRTUAL_ID,\n load() {\n return `export { createFromReadableStream, createFromFetch } from '@vitejs/plugin-rsc/browser'`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-ssr-decode-virtual',\n moduleId: RSC_SSR_DECODE_VIRTUAL_ID,\n load() {\n return `export { setOnClientReference, createFromReadableStream } from '@vitejs/plugin-rsc/ssr'`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-hmr-virtual:dev',\n moduleId: RSC_HMR_VIRTUAL_ID,\n apply: 'serve',\n applyToEnvironment: isClientEnvironment,\n load() {\n return `\nexport function setupRscHmr() {\nif (!import.meta.hot) {\n return\n}\n\n let __invalidateQueued = false\n\n function __queueInvalidate() {\n if (__invalidateQueued) return\n __invalidateQueued = true\n queueMicrotask(async () => {\n __invalidateQueued = false\n try {\n const router = window.__TSR_ROUTER__\n if (!router) {\n console.warn('[rsc:hmr] No router found on window.__TSR_ROUTER__')\n return\n }\n await router.invalidate()\n } catch (e) {\n console.warn('[rsc:hmr] Failed to invalidate router:', e)\n }\n })\n }\n\n import.meta.hot.on('rsc:update', () => {\n __queueInvalidate()\n })\n}\n`\n },\n }),\n createVirtualModule({\n name: 'tanstack-react-start:rsc-hmr-virtual:prod',\n moduleId: RSC_HMR_VIRTUAL_ID,\n applyToEnvironment: isClientEnvironment,\n apply: 'build',\n load() {\n return 'export function setupRscHmr() {} '\n },\n }),\n ]\n}\n"],"mappings":";;;;;AAUA,IAAM,uBAAuB,QAC3B,IAAI,OAAO,aAAa;AAG1B,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,gCAAgC;AACtC,IAAM,4BAA4B;AAClC,IAAM,eAAe;AAErB,IAAM,aAAa,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;AAC9D,IAAM,WAAW,KAAK,QAAQ,YAAY,MAAM,MAAM,UAAU,OAAO;AACvE,IAAM,eAAe,KAAK,QAAQ,UAAU,SAAS;AAErD,SAAgB,eAMd;CAyBA,OAAO;EACL,SAAS;EACT,yBAAyB;EACzB,qBAAA;GARA,MAAM;GACN,uBAAuB;GACvB,aAAa;GACb,YAAY;EAKZ;EACA,uBAAA,CAvBE;GACE,QAAQ;IACN,QAAQ;IACR,QAAQ;IACR,WAAW;GACb;GACA,QAAQ;IACN,QAAQ;IACR,QAAQ;IACR,WAAW;GACb;EACF,CAYF;EACA,oBAAoB,+BAA+B,EACjD,mBAAmB,gCACrB,CAAC;CACH;AACF;AACA,SAAgB,0BAAwC;CACtD,OAAO;EAML;GACE,MAAM;GACN,SAAS;IACP,OAAO,EACL,KAAK,EACH,YAAY,KACd,EACF;GACF;EACF;EACA;GACE,MAAM;GACN,SAAS;IACP,OAAO;KACL,KAAK;MAGH,eAAe;MAGf,mBAAmB;KACrB;KACA,cAAc,GACX,eAAe;MACd,UAAU;MAMV,SAAS,EACP,YAAY;OACV;OACA;OACA;OACA;MACF,EACF;MACA,OAAO,EACL,eAAe,EACb,OAAO,EACL,OAAO,aACT,EACF,EACF;KACF,EACF;IACF;GAMF;EACF;EAEA;GACE,MAAM;GACN,OAAO;GACP,mBAAmB,KAAK;IACtB,OAAO,IAAI,SAAS;GACtB;GACA,MAAM;IACJ,QAAQ,EACN,IAAI,oEACN;IACA,QAAQ,IAAI;KACV,IAAI,KAAK,YAAY,OAAO,MAAM,UAAU,OAAO;KAEnD,IAAI,OAAO,wBACT,OAAO;KAGT,IAAI,OAAO,mCACT,OAAO;IAIX;GACF;EACF;EAGA,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;IAEL,IADgB,KAAK,YAAY,SACjB,cACd,OAAO;IAET,OAAO;;;;;;;;;GAST;EACF,CAAC;EACD,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;IACL,OAAO;GACT;EACF,CAAC;EACD,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;IACL,OAAO;GACT;EACF,CAAC;EACD,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,OAAO;GACP,oBAAoB;GACpB,OAAO;IACL,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BT;EACF,CAAC;EACD,oBAAoB;GAClB,MAAM;GACN,UAAU;GACV,oBAAoB;GACpB,OAAO;GACP,OAAO;IACL,OAAO;GACT;EACF,CAAC;CACH;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"reactSymbols.js","names":[],"sources":["../../src/reactSymbols.ts"],"sourcesContent":["// Inline React 19 internal $$typeof symbols to avoid depending on `react-is`.\n// `react-is` is CJS-only, causing module resolution failures in strict pnpm\n// setups where it can't be resolved from the consumer's node_modules.\nexport const ReactElement = Symbol.for('react.transitional.element')\nexport const ReactLazy = Symbol.for('react.lazy')\nexport const ReactSuspense = Symbol.for('react.suspense')\n"],"mappings":";AAGA,IAAa,eAAe,OAAO,IAAI,6BAA6B;AACpE,IAAa,YAAY,OAAO,IAAI,aAAa;AACjD,IAAa,gBAAgB,OAAO,IAAI,iBAAiB"}
1
+ {"version":3,"file":"reactSymbols.js","names":[],"sources":["../../src/reactSymbols.ts"],"sourcesContent":["// Inline React 19 internal $$typeof symbols to avoid depending on `react-is`.\n// `react-is` is CJS-only, causing module resolution failures in strict pnpm\n// setups where it can't be resolved from the consumer's node_modules.\nexport const ReactElement = Symbol.for('react.transitional.element')\nexport const ReactLazy = Symbol.for('react.lazy')\nexport const ReactSuspense = Symbol.for('react.suspense')\n"],"mappings":";AAGA,IAAa,eAAe,OAAO,IAAI,4BAA4B;AACnE,IAAa,YAAY,OAAO,IAAI,YAAY;AAChD,IAAa,gBAAgB,OAAO,IAAI,gBAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"renderServerComponent.js","names":[],"sources":["../../src/renderServerComponent.ts"],"sourcesContent":["import { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport { getRequest } from '@tanstack/start-server-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport { ReplayableStream } from './ReplayableStream'\nimport { RENDERABLE_RSC, SERVER_COMPONENT_STREAM } from './ServerComponentTypes'\nimport { createRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyRenderableServerComponent,\n RenderableServerComponentBuilder,\n ServerComponentStream,\n ValidateRenderableServerComponent,\n} from './ServerComponentTypes'\nimport type { RscCssEnvelopeOptions } from './rscCssEnvelope'\n\nimport './rscSsrHandler'\n// Import for global declaration side effect\nexport type { RscSsrHandler, RscDecodeResult } from './rscSsrHandler'\n\n/**\n * Renderable RSC handle type - used for serialization detection.\n */\n\n/**\n * Type guard for renderable RSC handle.\n */\nexport function isRenderableRscHandle(\n value: unknown,\n): value is AnyRenderableServerComponent {\n return (\n typeof value === 'function' &&\n SERVER_COMPONENT_STREAM in value &&\n RENDERABLE_RSC in value &&\n (value as any)[RENDERABLE_RSC] === true\n )\n}\n\n/**\n * Renders a React element to an RSC Flight stream.\n *\n * Returns a \"renderable proxy\" that can be:\n * - Rendered directly as `{data}` in JSX\n * - Accessed for nested selections: `{data.foo.bar.Hello}`\n *\n * No slot support - for slots use `createCompositeComponent`.\n *\n * @example\n * ```tsx\n * // In a loader or server function\n * const data = await renderServerComponent(<MyServerComponent foo=\"bar\" />)\n *\n * // In the route component\n * return (\n * <div>\n * {data}\n * {data.sidebar.Menu}\n * </div>\n * )\n * ```\n */\nexport async function renderServerComponent<TNode>(\n node: ValidateRenderableServerComponent<TNode>,\n options?: RscCssEnvelopeOptions,\n): Promise<RenderableServerComponentBuilder<TNode>> {\n const flightStream = renderToReadableStream(\n createRscCssEnvelope(node, options),\n )\n\n // Check if this is an SSR request (router) or a direct server function call\n const ctx = getStartContext({ throwIfNotFound: false })\n const isRouterRequest = ctx?.handlerType === 'router'\n const ssrHandler = globalThis.__RSC_SSR__\n\n // SSR path: buffer stream for replay, pre-decode for synchronous rendering\n if (isRouterRequest && ssrHandler) {\n const signal = getRequest().signal\n const stream = new ReplayableStream(flightStream, { signal })\n\n // Pre-decode during loader phase for synchronous SSR rendering\n const decoded = await ssrHandler.decode(stream)\n return ssrHandler.createRenderableProxy(\n stream,\n decoded,\n ) as RenderableServerComponentBuilder<TNode>\n }\n\n // Server function call path: return a handle for serialization\n return createRenderableHandle(\n flightStream,\n ) as unknown as RenderableServerComponentBuilder<TNode>\n}\n\n/**\n * Creates a renderable handle for server function responses.\n * Tagged with RENDERABLE_RSC for the serialization adapter.\n */\nfunction createRenderableHandle(\n flightStream: ReadableStream<Uint8Array>,\n): AnyRenderableServerComponent {\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => flightStream,\n }\n\n const stub = function RenderableRscStub(): never {\n throw new Error(\n 'Renderable RSC from server function cannot be rendered on server. ' +\n 'It should be serialized and sent to the client.',\n )\n }\n\n ;(stub as any)[SERVER_COMPONENT_STREAM] = streamWrapper\n ;(stub as any)[RENDERABLE_RSC] = true\n return stub as unknown as AnyRenderableServerComponent\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,eAAsB,sBACpB,MACA,SACkD;CAClD,MAAM,eAAe,uBACnB,qBAAqB,MAAM,QAAQ,CACpC;CAID,MAAM,kBADM,gBAAgB,EAAE,iBAAiB,OAAO,CAAC,EAC1B,gBAAgB;CAC7C,MAAM,aAAa,WAAW;AAG9B,KAAI,mBAAmB,YAAY;EACjC,MAAM,SAAS,YAAY,CAAC;EAC5B,MAAM,SAAS,IAAI,iBAAiB,cAAc,EAAE,QAAQ,CAAC;EAG7D,MAAM,UAAU,MAAM,WAAW,OAAO,OAAO;AAC/C,SAAO,WAAW,sBAChB,QACA,QACD;;AAIH,QAAO,uBACL,aACD;;;;;;AAOH,SAAS,uBACP,cAC8B;CAC9B,MAAM,gBAAuC,EAC3C,0BAA0B,cAC3B;CAED,MAAM,OAAO,SAAS,oBAA2B;AAC/C,QAAM,IAAI,MACR,oHAED;;AAGD,MAAa,2BAA2B;AACxC,MAAa,kBAAkB;AACjC,QAAO"}
1
+ {"version":3,"file":"renderServerComponent.js","names":[],"sources":["../../src/renderServerComponent.ts"],"sourcesContent":["import { renderToReadableStream } from 'virtual:tanstack-rsc-runtime'\nimport { getRequest } from '@tanstack/start-server-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport { ReplayableStream } from './ReplayableStream'\nimport { RENDERABLE_RSC, SERVER_COMPONENT_STREAM } from './ServerComponentTypes'\nimport { createRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyRenderableServerComponent,\n RenderableServerComponentBuilder,\n ServerComponentStream,\n ValidateRenderableServerComponent,\n} from './ServerComponentTypes'\nimport type { RscCssEnvelopeOptions } from './rscCssEnvelope'\n\nimport './rscSsrHandler'\n// Import for global declaration side effect\nexport type { RscSsrHandler, RscDecodeResult } from './rscSsrHandler'\n\n/**\n * Renderable RSC handle type - used for serialization detection.\n */\n\n/**\n * Type guard for renderable RSC handle.\n */\nexport function isRenderableRscHandle(\n value: unknown,\n): value is AnyRenderableServerComponent {\n return (\n typeof value === 'function' &&\n SERVER_COMPONENT_STREAM in value &&\n RENDERABLE_RSC in value &&\n (value as any)[RENDERABLE_RSC] === true\n )\n}\n\n/**\n * Renders a React element to an RSC Flight stream.\n *\n * Returns a \"renderable proxy\" that can be:\n * - Rendered directly as `{data}` in JSX\n * - Accessed for nested selections: `{data.foo.bar.Hello}`\n *\n * No slot support - for slots use `createCompositeComponent`.\n *\n * @example\n * ```tsx\n * // In a loader or server function\n * const data = await renderServerComponent(<MyServerComponent foo=\"bar\" />)\n *\n * // In the route component\n * return (\n * <div>\n * {data}\n * {data.sidebar.Menu}\n * </div>\n * )\n * ```\n */\nexport async function renderServerComponent<TNode>(\n node: ValidateRenderableServerComponent<TNode>,\n options?: RscCssEnvelopeOptions,\n): Promise<RenderableServerComponentBuilder<TNode>> {\n const flightStream = renderToReadableStream(\n createRscCssEnvelope(node, options),\n )\n\n // Check if this is an SSR request (router) or a direct server function call\n const ctx = getStartContext({ throwIfNotFound: false })\n const isRouterRequest = ctx?.handlerType === 'router'\n const ssrHandler = globalThis.__RSC_SSR__\n\n // SSR path: buffer stream for replay, pre-decode for synchronous rendering\n if (isRouterRequest && ssrHandler) {\n const signal = getRequest().signal\n const stream = new ReplayableStream(flightStream, { signal })\n\n // Pre-decode during loader phase for synchronous SSR rendering\n const decoded = await ssrHandler.decode(stream)\n return ssrHandler.createRenderableProxy(\n stream,\n decoded,\n ) as RenderableServerComponentBuilder<TNode>\n }\n\n // Server function call path: return a handle for serialization\n return createRenderableHandle(\n flightStream,\n ) as unknown as RenderableServerComponentBuilder<TNode>\n}\n\n/**\n * Creates a renderable handle for server function responses.\n * Tagged with RENDERABLE_RSC for the serialization adapter.\n */\nfunction createRenderableHandle(\n flightStream: ReadableStream<Uint8Array>,\n): AnyRenderableServerComponent {\n const streamWrapper: ServerComponentStream = {\n createReplayStream: () => flightStream,\n }\n\n const stub = function RenderableRscStub(): never {\n throw new Error(\n 'Renderable RSC from server function cannot be rendered on server. ' +\n 'It should be serialized and sent to the client.',\n )\n }\n\n ;(stub as any)[SERVER_COMPONENT_STREAM] = streamWrapper\n ;(stub as any)[RENDERABLE_RSC] = true\n return stub as unknown as AnyRenderableServerComponent\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DA,eAAsB,sBACpB,MACA,SACkD;CAClD,MAAM,eAAe,uBACnB,qBAAqB,MAAM,OAAO,CACpC;CAIA,MAAM,kBADM,gBAAgB,EAAE,iBAAiB,MAAM,CAC7B,GAAK,gBAAgB;CAC7C,MAAM,aAAa,WAAW;CAG9B,IAAI,mBAAmB,YAAY;EACjC,MAAM,SAAS,WAAW,EAAE;EAC5B,MAAM,SAAS,IAAI,iBAAiB,cAAc,EAAE,OAAO,CAAC;EAG5D,MAAM,UAAU,MAAM,WAAW,OAAO,MAAM;EAC9C,OAAO,WAAW,sBAChB,QACA,OACF;CACF;CAGA,OAAO,uBACL,YACF;AACF;;;;;AAMA,SAAS,uBACP,cAC8B;CAC9B,MAAM,gBAAuC,EAC3C,0BAA0B,aAC5B;CAEA,MAAM,OAAO,SAAS,oBAA2B;EAC/C,MAAM,IAAI,MACR,mHAEF;CACF;CAEC,KAAc,2BAA2B;CACzC,KAAc,kBAAkB;CACjC,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"renderServerComponent.stub.js","names":[],"sources":["../../src/renderServerComponent.stub.ts"],"sourcesContent":["import type {\n RenderableServerComponentBuilder,\n ValidateRenderableServerComponent,\n} from './ServerComponentTypes'\n\n/**\n * Client stub for renderServerComponent.\n *\n * This function should never be called at runtime on the client.\n * It exists only to satisfy bundler imports in client bundles.\n * The real implementation only runs inside server functions.\n */\nexport function renderServerComponent<TNode>(\n _node: ValidateRenderableServerComponent<TNode>,\n): Promise<RenderableServerComponentBuilder<TNode>> {\n // Unit/type tests import this stub directly and call it.\n // Avoid throwing in that environment while keeping a hard runtime guard elsewhere.\n if (process.env.NODE_ENV === 'test') {\n return Promise.resolve(null as any)\n }\n\n throw new Error(\n 'renderServerComponent cannot be called on the client. ' +\n 'This function should only be called inside a server function or route loader.',\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,sBACd,OACkD;AAGlD,KAAA,QAAA,IAAA,aAA6B,OAC3B,QAAO,QAAQ,QAAQ,KAAY;AAGrC,OAAM,IAAI,MACR,sIAED"}
1
+ {"version":3,"file":"renderServerComponent.stub.js","names":[],"sources":["../../src/renderServerComponent.stub.ts"],"sourcesContent":["import type {\n RenderableServerComponentBuilder,\n ValidateRenderableServerComponent,\n} from './ServerComponentTypes'\n\n/**\n * Client stub for renderServerComponent.\n *\n * This function should never be called at runtime on the client.\n * It exists only to satisfy bundler imports in client bundles.\n * The real implementation only runs inside server functions.\n */\nexport function renderServerComponent<TNode>(\n _node: ValidateRenderableServerComponent<TNode>,\n): Promise<RenderableServerComponentBuilder<TNode>> {\n // Unit/type tests import this stub directly and call it.\n // Avoid throwing in that environment while keeping a hard runtime guard elsewhere.\n if (process.env.NODE_ENV === 'test') {\n return Promise.resolve(null as any)\n }\n\n throw new Error(\n 'renderServerComponent cannot be called on the client. ' +\n 'This function should only be called inside a server function or route loader.',\n )\n}\n"],"mappings":";;;;;;;;AAYA,SAAgB,sBACd,OACkD;CAGlD,IAAA,QAAA,IAAA,aAA6B,QAC3B,OAAO,QAAQ,QAAQ,IAAW;CAGpC,MAAM,IAAI,MACR,qIAEF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"rscCssEnvelope.js","names":[],"sources":["../../src/rscCssEnvelope.ts"],"sourcesContent":["import type React from 'react'\n\nconst RSC_CSS_ENVELOPE_MARKER = '__tanstackStartRscCssEnvelope'\nconst RSC_CSS_ENVELOPE_RESOURCES = '__tanstackStartRscCss'\nconst RSC_CSS_ENVELOPE_VALUE = '__tanstackStartRscValue'\n\nexport interface RscCssEnvelopeOptions {\n [RSC_CSS_ENVELOPE_RESOURCES]?: React.ReactNode\n}\n\nexport function createRscCssEnvelope<TValue>(\n value: TValue,\n options?: RscCssEnvelopeOptions,\n): TValue | Record<string, unknown> {\n const resources = options?.[RSC_CSS_ENVELOPE_RESOURCES]\n if (resources === undefined || resources === null || resources === false) {\n return value\n }\n\n return {\n [RSC_CSS_ENVELOPE_MARKER]: true,\n [RSC_CSS_ENVELOPE_RESOURCES]: resources,\n [RSC_CSS_ENVELOPE_VALUE]: value,\n }\n}\n\nexport function unwrapRscCssEnvelope(value: unknown): unknown {\n if (!value || typeof value !== 'object') {\n return value\n }\n\n const maybeEnvelope = value as Record<string, unknown>\n if (maybeEnvelope[RSC_CSS_ENVELOPE_MARKER] !== true) {\n return value\n }\n\n return maybeEnvelope[RSC_CSS_ENVELOPE_VALUE]\n}\n"],"mappings":";AAEA,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAM/B,SAAgB,qBACd,OACA,SACkC;CAClC,MAAM,YAAY,UAAU;AAC5B,KAAI,cAAc,KAAA,KAAa,cAAc,QAAQ,cAAc,MACjE,QAAO;AAGT,QAAO;GACJ,0BAA0B;GAC1B,6BAA6B;GAC7B,yBAAyB;EAC3B;;AAGH,SAAgB,qBAAqB,OAAyB;AAC5D,KAAI,CAAC,SAAS,OAAO,UAAU,SAC7B,QAAO;CAGT,MAAM,gBAAgB;AACtB,KAAI,cAAc,6BAA6B,KAC7C,QAAO;AAGT,QAAO,cAAc"}
1
+ {"version":3,"file":"rscCssEnvelope.js","names":[],"sources":["../../src/rscCssEnvelope.ts"],"sourcesContent":["import type React from 'react'\n\nconst RSC_CSS_ENVELOPE_MARKER = '__tanstackStartRscCssEnvelope'\nconst RSC_CSS_ENVELOPE_RESOURCES = '__tanstackStartRscCss'\nconst RSC_CSS_ENVELOPE_VALUE = '__tanstackStartRscValue'\n\nexport interface RscCssEnvelopeOptions {\n [RSC_CSS_ENVELOPE_RESOURCES]?: React.ReactNode\n}\n\nexport function createRscCssEnvelope<TValue>(\n value: TValue,\n options?: RscCssEnvelopeOptions,\n): TValue | Record<string, unknown> {\n const resources = options?.[RSC_CSS_ENVELOPE_RESOURCES]\n if (resources === undefined || resources === null || resources === false) {\n return value\n }\n\n return {\n [RSC_CSS_ENVELOPE_MARKER]: true,\n [RSC_CSS_ENVELOPE_RESOURCES]: resources,\n [RSC_CSS_ENVELOPE_VALUE]: value,\n }\n}\n\nexport function unwrapRscCssEnvelope(value: unknown): unknown {\n if (!value || typeof value !== 'object') {\n return value\n }\n\n const maybeEnvelope = value as Record<string, unknown>\n if (maybeEnvelope[RSC_CSS_ENVELOPE_MARKER] !== true) {\n return value\n }\n\n return maybeEnvelope[RSC_CSS_ENVELOPE_VALUE]\n}\n"],"mappings":";AAEA,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AACnC,IAAM,yBAAyB;AAM/B,SAAgB,qBACd,OACA,SACkC;CAClC,MAAM,YAAY,UAAU;CAC5B,IAAI,cAAc,KAAA,KAAa,cAAc,QAAQ,cAAc,OACjE,OAAO;CAGT,OAAO;GACJ,0BAA0B;GAC1B,6BAA6B;GAC7B,yBAAyB;CAC5B;AACF;AAEA,SAAgB,qBAAqB,OAAyB;CAC5D,IAAI,CAAC,SAAS,OAAO,UAAU,UAC7B,OAAO;CAGT,MAAM,gBAAgB;CACtB,IAAI,cAAc,6BAA6B,MAC7C,OAAO;CAGT,OAAO,cAAc;AACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"serialization.client.js","names":[],"sources":["../../src/serialization.client.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/react-router'\n// RSC HMR setup (dev-only, provided by the active Start bundler adapter).\nimport { setupRscHmr } from 'virtual:tanstack-rsc-hmr'\nimport {\n createCompositeFromStream,\n createRenderableFromStream,\n} from './createServerComponentFromStream'\nimport type {\n AnyCompositeComponent,\n RscSlotUsageEvent,\n} from './ServerComponentTypes'\n\nif (process.env.NODE_ENV === 'development') {\n setupRscHmr()\n}\n\n/**\n * Client-side serialization adapter for RSC (renderable + composite).\n */\ntype SerializedRsc = {\n kind: 'renderable' | 'composite'\n stream: ReadableStream<Uint8Array>\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n}\n\nconst adapter = createSerializationAdapter({\n key: '$RSC',\n test: (_value: unknown): _value is never => false,\n toSerializable: (): never => {\n throw new Error('RSC cannot be serialized on client')\n },\n fromSerializable: (value: SerializedRsc): AnyCompositeComponent => {\n if (value.kind === 'renderable') {\n return createRenderableFromStream(value.stream)\n }\n\n return createCompositeFromStream(value.stream, {\n slotUsagesStream: value.slotUsagesStream,\n })\n },\n})\n\nexport const rscSerializationAdapter = () => [adapter]\n"],"mappings":";;;;AAYA,IAAA,QAAA,IAAA,aAA6B,cAC3B,cAAa;AAYf,IAAM,UAAU,2BAA2B;CACzC,KAAK;CACL,OAAO,WAAqC;CAC5C,sBAA6B;AAC3B,QAAM,IAAI,MAAM,qCAAqC;;CAEvD,mBAAmB,UAAgD;AACjE,MAAI,MAAM,SAAS,aACjB,QAAO,2BAA2B,MAAM,OAAO;AAGjD,SAAO,0BAA0B,MAAM,QAAQ,EAC7C,kBAAkB,MAAM,kBACzB,CAAC;;CAEL,CAAC;AAEF,IAAa,gCAAgC,CAAC,QAAQ"}
1
+ {"version":3,"file":"serialization.client.js","names":[],"sources":["../../src/serialization.client.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/react-router'\n// RSC HMR setup (dev-only, provided by the active Start bundler adapter).\nimport { setupRscHmr } from 'virtual:tanstack-rsc-hmr'\nimport {\n createCompositeFromStream,\n createRenderableFromStream,\n} from './createServerComponentFromStream'\nimport type {\n AnyCompositeComponent,\n RscSlotUsageEvent,\n} from './ServerComponentTypes'\n\nif (process.env.NODE_ENV === 'development') {\n setupRscHmr()\n}\n\n/**\n * Client-side serialization adapter for RSC (renderable + composite).\n */\ntype SerializedRsc = {\n kind: 'renderable' | 'composite'\n stream: ReadableStream<Uint8Array>\n slotUsagesStream?: ReadableStream<RscSlotUsageEvent>\n}\n\nconst adapter = createSerializationAdapter({\n key: '$RSC',\n test: (_value: unknown): _value is never => false,\n toSerializable: (): never => {\n throw new Error('RSC cannot be serialized on client')\n },\n fromSerializable: (value: SerializedRsc): AnyCompositeComponent => {\n if (value.kind === 'renderable') {\n return createRenderableFromStream(value.stream)\n }\n\n return createCompositeFromStream(value.stream, {\n slotUsagesStream: value.slotUsagesStream,\n })\n },\n})\n\nexport const rscSerializationAdapter = () => [adapter]\n"],"mappings":";;;;AAYA,IAAA,QAAA,IAAA,aAA6B,eAC3B,YAAY;AAYd,IAAM,UAAU,2BAA2B;CACzC,KAAK;CACL,OAAO,WAAqC;CAC5C,sBAA6B;EAC3B,MAAM,IAAI,MAAM,oCAAoC;CACtD;CACA,mBAAmB,UAAgD;EACjE,IAAI,MAAM,SAAS,cACjB,OAAO,2BAA2B,MAAM,MAAM;EAGhD,OAAO,0BAA0B,MAAM,QAAQ,EAC7C,kBAAkB,MAAM,iBAC1B,CAAC;CACH;AACF,CAAC;AAED,IAAa,gCAAgC,CAAC,OAAO"}
@@ -38,7 +38,7 @@ setOnClientReference(({ deps, runtime }) => {
38
38
  }
39
39
  if (nextCss) ctx.requestAssets.css = nextCss;
40
40
  });
41
- var ssrHandler = {
41
+ globalThis.__RSC_SSR__ = {
42
42
  async decode(stream) {
43
43
  const readableStream = stream.createReplayStream();
44
44
  const cssCollector = /* @__PURE__ */ new Set();
@@ -75,7 +75,6 @@ var ssrHandler = {
75
75
  });
76
76
  }
77
77
  };
78
- globalThis.__RSC_SSR__ = ssrHandler;
79
78
  /**
80
79
  * Helper to check if a value is a renderable RSC (from renderServerComponent).
81
80
  * The value can be either an object (proxy target) or a function (stub for server functions).
@@ -1 +1 @@
1
- {"version":3,"file":"serialization.server.js","names":[],"sources":["../../src/serialization.server.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { createSerializationAdapter } from '@tanstack/react-router'\nimport { RawStream } from '@tanstack/router-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport {\n setOnClientReference,\n createFromReadableStream as ssrDecode,\n} from 'virtual:tanstack-rsc-ssr-decode'\nimport {\n RENDERABLE_RSC,\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_STREAM,\n isServerComponent,\n} from './ServerComponentTypes'\nimport { createRscProxy } from './createRscProxy'\nimport { awaitLazyElements } from './awaitLazyElements'\nimport { unwrapRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n ServerComponentStream,\n} from './ServerComponentTypes'\nimport type { RscDecodeResult, RscSsrHandler } from './rscSsrHandler'\n\n// ===== SSR Handler Registration =====\n// This handler is registered on globalThis for the RSC environment to access.\n// The RSC env calls these functions during loader execution to pre-decode streams\n// and create renderable proxies.\n//\n// This MUST happen in a module without 'use client' directive.\n// Modules with 'use client' may be transformed to client references in the\n// SSR environment when RSC is enabled, preventing the side effect from running.\n\n// AsyncLocalStorage for decode-scoped CSS collector.\n// Each decode() runs in its own async context with its own collector.\n// The onClientReference callback reads from this to write CSS hrefs.\nconst decodeCollectorStorage = new AsyncLocalStorage<Set<string>>()\nconst jsCollectorStorage = new AsyncLocalStorage<Set<string>>()\n\nsetOnClientReference(\n ({\n deps,\n runtime,\n }: {\n deps: { js: Array<string>; css: Array<string> }\n runtime?: 'rsbuild'\n }) => {\n const ctx = getStartContext({ throwIfNotFound: false })\n\n const cssCollector = decodeCollectorStorage.getStore()\n if (cssCollector) {\n for (const href of deps.css) {\n cssCollector.add(href)\n }\n }\n\n const jsCollector = jsCollectorStorage.getStore()\n if (jsCollector) {\n for (const href of deps.js) {\n jsCollector.add(href)\n }\n }\n\n if (\n !ctx ||\n runtime === 'rsbuild' ||\n (!deps.js.length && !deps.css.length)\n ) {\n return\n }\n\n if (!ctx.requestAssets) ctx.requestAssets = {}\n const seenHrefs = new Set<string>()\n for (const preload of ctx.requestAssets.preloads ?? []) {\n seenHrefs.add(typeof preload === 'string' ? preload : preload.href)\n }\n for (const stylesheet of ctx.requestAssets.css ?? []) {\n seenHrefs.add(\n typeof stylesheet === 'string' ? stylesheet : stylesheet.href,\n )\n }\n\n let nextPreloads: typeof ctx.requestAssets.preloads | undefined\n for (const href of deps.js) {\n if (seenHrefs.has(href)) continue\n seenHrefs.add(href)\n if (!nextPreloads) {\n nextPreloads = ctx.requestAssets.preloads\n ? ctx.requestAssets.preloads.slice()\n : []\n }\n nextPreloads.push(href)\n }\n if (nextPreloads) {\n ctx.requestAssets.preloads = nextPreloads\n }\n\n let nextCss: typeof ctx.requestAssets.css | undefined\n for (const href of deps.css) {\n if (seenHrefs.has(href)) continue\n seenHrefs.add(href)\n if (!nextCss) {\n nextCss = ctx.requestAssets.css ? ctx.requestAssets.css.slice() : []\n }\n nextCss.push(href)\n }\n if (nextCss) {\n ctx.requestAssets.css = nextCss\n }\n },\n)\n\nconst ssrHandler: RscSsrHandler = {\n async decode(stream: ServerComponentStream): Promise<RscDecodeResult> {\n const readableStream = stream.createReplayStream()\n\n // Create a collector for this decode operation.\n // Run the decode in an AsyncLocalStorage context so the onClientReference\n // callback can write to this specific collector even with parallel decodes.\n const cssCollector = new Set<string>()\n const jsCollector = new Set<string>()\n\n return decodeCollectorStorage.run(cssCollector, async () => {\n return jsCollectorStorage.run(jsCollector, async () => {\n const decodedTree = await ssrDecode(readableStream)\n await awaitLazyElements(decodedTree, (href) => {\n cssCollector.add(href)\n })\n\n return {\n tree: unwrapRscCssEnvelope(decodedTree),\n cssHrefs: cssCollector.size > 0 ? cssCollector : undefined,\n jsPreloads: jsCollector.size > 0 ? jsCollector : undefined,\n }\n })\n })\n },\n\n createRenderableProxy(stream, decoded): any {\n return createRscProxy(() => decoded.tree, {\n stream,\n cssHrefs: decoded.cssHrefs,\n jsPreloads: decoded.jsPreloads,\n renderable: true,\n })\n },\n\n createCompositeProxy(\n stream,\n decoded,\n slotUsagesStream,\n ): AnyCompositeComponent {\n const proxy = createRscProxy(() => decoded.tree, {\n stream,\n cssHrefs: decoded.cssHrefs,\n jsPreloads: decoded.jsPreloads,\n renderable: false,\n slotUsagesStream,\n })\n return proxy\n },\n}\n\n// Register SSR handler on globalThis for RSC environment to access.\nglobalThis.__RSC_SSR__ = ssrHandler\n\n// ===== End SSR Handler Registration =====\n\n/**\n * Helper to check if a value is a renderable RSC (from renderServerComponent).\n * The value can be either an object (proxy target) or a function (stub for server functions).\n */\nfunction isRenderableRsc(value: unknown): boolean {\n if (value === null || value === undefined) return false\n if (typeof value !== 'object' && typeof value !== 'function') return false\n return RENDERABLE_RSC in value && (value as any)[RENDERABLE_RSC] === true\n}\n\n/**\n * Server-side serialization adapter for RSC (renderable + composite).\n */\nconst adapter = createSerializationAdapter({\n key: '$RSC',\n test: (value: unknown): value is AnyCompositeComponent => {\n return isServerComponent(value)\n },\n toSerializable: (component: AnyCompositeComponent) => {\n const stream = component[SERVER_COMPONENT_STREAM]!.createReplayStream()\n\n const kind = isRenderableRsc(component) ? 'renderable' : 'composite'\n\n const slotUsagesStream =\n kind === 'composite' &&\n process.env.NODE_ENV === 'development' &&\n RSC_SLOT_USAGES_STREAM in component\n ? ((component as any)[RSC_SLOT_USAGES_STREAM] as unknown as\n | ReadableStream<any>\n | undefined)\n : undefined\n\n return {\n kind,\n stream: new RawStream(stream, { hint: 'text' }),\n slotUsagesStream,\n }\n },\n fromSerializable: (): never => {\n throw new Error('Server should never deserialize RSC data')\n },\n})\n\n/**\n * Factory function for server-side RSC serialization adapter.\n */\nexport const rscSerializationAdapter = () => [adapter]\n"],"mappings":"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"}
1
+ {"version":3,"file":"serialization.server.js","names":[],"sources":["../../src/serialization.server.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\nimport { createSerializationAdapter } from '@tanstack/react-router'\nimport { RawStream } from '@tanstack/router-core'\nimport { getStartContext } from '@tanstack/start-storage-context'\nimport {\n setOnClientReference,\n createFromReadableStream as ssrDecode,\n} from 'virtual:tanstack-rsc-ssr-decode'\nimport {\n RENDERABLE_RSC,\n RSC_SLOT_USAGES_STREAM,\n SERVER_COMPONENT_STREAM,\n isServerComponent,\n} from './ServerComponentTypes'\nimport { createRscProxy } from './createRscProxy'\nimport { awaitLazyElements } from './awaitLazyElements'\nimport { unwrapRscCssEnvelope } from './rscCssEnvelope'\nimport type {\n AnyCompositeComponent,\n ServerComponentStream,\n} from './ServerComponentTypes'\nimport type { RscDecodeResult, RscSsrHandler } from './rscSsrHandler'\n\n// ===== SSR Handler Registration =====\n// This handler is registered on globalThis for the RSC environment to access.\n// The RSC env calls these functions during loader execution to pre-decode streams\n// and create renderable proxies.\n//\n// This MUST happen in a module without 'use client' directive.\n// Modules with 'use client' may be transformed to client references in the\n// SSR environment when RSC is enabled, preventing the side effect from running.\n\n// AsyncLocalStorage for decode-scoped CSS collector.\n// Each decode() runs in its own async context with its own collector.\n// The onClientReference callback reads from this to write CSS hrefs.\nconst decodeCollectorStorage = new AsyncLocalStorage<Set<string>>()\nconst jsCollectorStorage = new AsyncLocalStorage<Set<string>>()\n\nsetOnClientReference(\n ({\n deps,\n runtime,\n }: {\n deps: { js: Array<string>; css: Array<string> }\n runtime?: 'rsbuild'\n }) => {\n const ctx = getStartContext({ throwIfNotFound: false })\n\n const cssCollector = decodeCollectorStorage.getStore()\n if (cssCollector) {\n for (const href of deps.css) {\n cssCollector.add(href)\n }\n }\n\n const jsCollector = jsCollectorStorage.getStore()\n if (jsCollector) {\n for (const href of deps.js) {\n jsCollector.add(href)\n }\n }\n\n if (\n !ctx ||\n runtime === 'rsbuild' ||\n (!deps.js.length && !deps.css.length)\n ) {\n return\n }\n\n if (!ctx.requestAssets) ctx.requestAssets = {}\n const seenHrefs = new Set<string>()\n for (const preload of ctx.requestAssets.preloads ?? []) {\n seenHrefs.add(typeof preload === 'string' ? preload : preload.href)\n }\n for (const stylesheet of ctx.requestAssets.css ?? []) {\n seenHrefs.add(\n typeof stylesheet === 'string' ? stylesheet : stylesheet.href,\n )\n }\n\n let nextPreloads: typeof ctx.requestAssets.preloads | undefined\n for (const href of deps.js) {\n if (seenHrefs.has(href)) continue\n seenHrefs.add(href)\n if (!nextPreloads) {\n nextPreloads = ctx.requestAssets.preloads\n ? ctx.requestAssets.preloads.slice()\n : []\n }\n nextPreloads.push(href)\n }\n if (nextPreloads) {\n ctx.requestAssets.preloads = nextPreloads\n }\n\n let nextCss: typeof ctx.requestAssets.css | undefined\n for (const href of deps.css) {\n if (seenHrefs.has(href)) continue\n seenHrefs.add(href)\n if (!nextCss) {\n nextCss = ctx.requestAssets.css ? ctx.requestAssets.css.slice() : []\n }\n nextCss.push(href)\n }\n if (nextCss) {\n ctx.requestAssets.css = nextCss\n }\n },\n)\n\nconst ssrHandler: RscSsrHandler = {\n async decode(stream: ServerComponentStream): Promise<RscDecodeResult> {\n const readableStream = stream.createReplayStream()\n\n // Create a collector for this decode operation.\n // Run the decode in an AsyncLocalStorage context so the onClientReference\n // callback can write to this specific collector even with parallel decodes.\n const cssCollector = new Set<string>()\n const jsCollector = new Set<string>()\n\n return decodeCollectorStorage.run(cssCollector, async () => {\n return jsCollectorStorage.run(jsCollector, async () => {\n const decodedTree = await ssrDecode(readableStream)\n await awaitLazyElements(decodedTree, (href) => {\n cssCollector.add(href)\n })\n\n return {\n tree: unwrapRscCssEnvelope(decodedTree),\n cssHrefs: cssCollector.size > 0 ? cssCollector : undefined,\n jsPreloads: jsCollector.size > 0 ? jsCollector : undefined,\n }\n })\n })\n },\n\n createRenderableProxy(stream, decoded): any {\n return createRscProxy(() => decoded.tree, {\n stream,\n cssHrefs: decoded.cssHrefs,\n jsPreloads: decoded.jsPreloads,\n renderable: true,\n })\n },\n\n createCompositeProxy(\n stream,\n decoded,\n slotUsagesStream,\n ): AnyCompositeComponent {\n const proxy = createRscProxy(() => decoded.tree, {\n stream,\n cssHrefs: decoded.cssHrefs,\n jsPreloads: decoded.jsPreloads,\n renderable: false,\n slotUsagesStream,\n })\n return proxy\n },\n}\n\n// Register SSR handler on globalThis for RSC environment to access.\nglobalThis.__RSC_SSR__ = ssrHandler\n\n// ===== End SSR Handler Registration =====\n\n/**\n * Helper to check if a value is a renderable RSC (from renderServerComponent).\n * The value can be either an object (proxy target) or a function (stub for server functions).\n */\nfunction isRenderableRsc(value: unknown): boolean {\n if (value === null || value === undefined) return false\n if (typeof value !== 'object' && typeof value !== 'function') return false\n return RENDERABLE_RSC in value && (value as any)[RENDERABLE_RSC] === true\n}\n\n/**\n * Server-side serialization adapter for RSC (renderable + composite).\n */\nconst adapter = createSerializationAdapter({\n key: '$RSC',\n test: (value: unknown): value is AnyCompositeComponent => {\n return isServerComponent(value)\n },\n toSerializable: (component: AnyCompositeComponent) => {\n const stream = component[SERVER_COMPONENT_STREAM]!.createReplayStream()\n\n const kind = isRenderableRsc(component) ? 'renderable' : 'composite'\n\n const slotUsagesStream =\n kind === 'composite' &&\n process.env.NODE_ENV === 'development' &&\n RSC_SLOT_USAGES_STREAM in component\n ? ((component as any)[RSC_SLOT_USAGES_STREAM] as unknown as\n | ReadableStream<any>\n | undefined)\n : undefined\n\n return {\n kind,\n stream: new RawStream(stream, { hint: 'text' }),\n slotUsagesStream,\n }\n },\n fromSerializable: (): never => {\n throw new Error('Server should never deserialize RSC data')\n },\n})\n\n/**\n * Factory function for server-side RSC serialization adapter.\n */\nexport const rscSerializationAdapter = () => [adapter]\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"slotUsageSanitizer.js","names":[],"sources":["../../src/slotUsageSanitizer.ts"],"sourcesContent":["import { isValidElement } from 'react'\n\nconst REACT_ELEMENT_TYPE = Symbol.for('react.element')\nconst REACT_TRANSITIONAL_ELEMENT_TYPE = Symbol.for('react.transitional.element')\nconst REACT_PORTAL_TYPE = Symbol.for('react.portal')\n\nfunction isReactElementLike(value: unknown): boolean {\n if (!value || (typeof value !== 'object' && typeof value !== 'function')) {\n return false\n }\n\n // Prefer React's own check when available.\n if (isValidElement(value)) return true\n\n // Fallback: direct $$typeof detection (covers React 19 transitional elements).\n const t = (value as any).$$typeof\n return (\n t === REACT_ELEMENT_TYPE ||\n t === REACT_TRANSITIONAL_ELEMENT_TYPE ||\n t === REACT_PORTAL_TYPE\n )\n}\n\nconst REACT_ELEMENT_PLACEHOLDER = 'React element'\n\nfunction sanitizeSlotArg(\n value: unknown,\n seen: WeakSet<object>,\n depth: number,\n): unknown {\n if (isReactElementLike(value)) {\n return REACT_ELEMENT_PLACEHOLDER\n }\n\n if (value === null || value === undefined) {\n return value\n }\n\n if (typeof value !== 'object' && typeof value !== 'function') {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((d) => sanitizeSlotArg(d, seen, depth + 1))\n }\n\n const proto = Object.getPrototypeOf(value)\n if (proto === Object.prototype || proto === null) {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = sanitizeSlotArg(v, seen, depth + 1)\n }\n return out\n }\n\n return value\n}\n\nexport function sanitizeSlotArgs(args: Array<any>): Array<any> {\n const seen = new WeakSet<object>()\n return args.map((d) => sanitizeSlotArg(d, seen, 0))\n}\n"],"mappings":";;AAEA,IAAM,qBAAqB,OAAO,IAAI,gBAAgB;AACtD,IAAM,kCAAkC,OAAO,IAAI,6BAA6B;AAChF,IAAM,oBAAoB,OAAO,IAAI,eAAe;AAEpD,SAAS,mBAAmB,OAAyB;AACnD,KAAI,CAAC,SAAU,OAAO,UAAU,YAAY,OAAO,UAAU,WAC3D,QAAO;AAIT,KAAI,eAAe,MAAM,CAAE,QAAO;CAGlC,MAAM,IAAK,MAAc;AACzB,QACE,MAAM,sBACN,MAAM,mCACN,MAAM;;AAIV,IAAM,4BAA4B;AAElC,SAAS,gBACP,OACA,MACA,OACS;AACT,KAAI,mBAAmB,MAAM,CAC3B,QAAO;AAGT,KAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO;AAGT,KAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAChD,QAAO;AAGT,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,KAAK,MAAM,gBAAgB,GAAG,MAAM,QAAQ,EAAE,CAAC;CAG9D,MAAM,QAAQ,OAAO,eAAe,MAAM;AAC1C,KAAI,UAAU,OAAO,aAAa,UAAU,MAAM;EAChD,MAAM,MAA+B,EAAE;AACvC,OAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAiC,CACnE,KAAI,KAAK,gBAAgB,GAAG,MAAM,QAAQ,EAAE;AAE9C,SAAO;;AAGT,QAAO;;AAGT,SAAgB,iBAAiB,MAA8B;CAC7D,MAAM,uBAAO,IAAI,SAAiB;AAClC,QAAO,KAAK,KAAK,MAAM,gBAAgB,GAAG,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"slotUsageSanitizer.js","names":[],"sources":["../../src/slotUsageSanitizer.ts"],"sourcesContent":["import { isValidElement } from 'react'\n\nconst REACT_ELEMENT_TYPE = Symbol.for('react.element')\nconst REACT_TRANSITIONAL_ELEMENT_TYPE = Symbol.for('react.transitional.element')\nconst REACT_PORTAL_TYPE = Symbol.for('react.portal')\n\nfunction isReactElementLike(value: unknown): boolean {\n if (!value || (typeof value !== 'object' && typeof value !== 'function')) {\n return false\n }\n\n // Prefer React's own check when available.\n if (isValidElement(value)) return true\n\n // Fallback: direct $$typeof detection (covers React 19 transitional elements).\n const t = (value as any).$$typeof\n return (\n t === REACT_ELEMENT_TYPE ||\n t === REACT_TRANSITIONAL_ELEMENT_TYPE ||\n t === REACT_PORTAL_TYPE\n )\n}\n\nconst REACT_ELEMENT_PLACEHOLDER = 'React element'\n\nfunction sanitizeSlotArg(\n value: unknown,\n seen: WeakSet<object>,\n depth: number,\n): unknown {\n if (isReactElementLike(value)) {\n return REACT_ELEMENT_PLACEHOLDER\n }\n\n if (value === null || value === undefined) {\n return value\n }\n\n if (typeof value !== 'object' && typeof value !== 'function') {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map((d) => sanitizeSlotArg(d, seen, depth + 1))\n }\n\n const proto = Object.getPrototypeOf(value)\n if (proto === Object.prototype || proto === null) {\n const out: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = sanitizeSlotArg(v, seen, depth + 1)\n }\n return out\n }\n\n return value\n}\n\nexport function sanitizeSlotArgs(args: Array<any>): Array<any> {\n const seen = new WeakSet<object>()\n return args.map((d) => sanitizeSlotArg(d, seen, 0))\n}\n"],"mappings":";;AAEA,IAAM,qBAAqB,OAAO,IAAI,eAAe;AACrD,IAAM,kCAAkC,OAAO,IAAI,4BAA4B;AAC/E,IAAM,oBAAoB,OAAO,IAAI,cAAc;AAEnD,SAAS,mBAAmB,OAAyB;CACnD,IAAI,CAAC,SAAU,OAAO,UAAU,YAAY,OAAO,UAAU,YAC3D,OAAO;CAIT,IAAI,eAAe,KAAK,GAAG,OAAO;CAGlC,MAAM,IAAK,MAAc;CACzB,OACE,MAAM,sBACN,MAAM,mCACN,MAAM;AAEV;AAEA,IAAM,4BAA4B;AAElC,SAAS,gBACP,OACA,MACA,OACS;CACT,IAAI,mBAAmB,KAAK,GAC1B,OAAO;CAGT,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,OAAO;CAGT,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,YAChD,OAAO;CAGT,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,KAAK,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,CAAC;CAG7D,MAAM,QAAQ,OAAO,eAAe,KAAK;CACzC,IAAI,UAAU,OAAO,aAAa,UAAU,MAAM;EAChD,MAAM,MAA+B,CAAC;EACtC,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,KAAgC,GAClE,IAAI,KAAK,gBAAgB,GAAG,MAAM,QAAQ,CAAC;EAE7C,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAgB,iBAAiB,MAA8B;CAC7D,MAAM,uBAAO,IAAI,QAAgB;CACjC,OAAO,KAAK,KAAK,MAAM,gBAAgB,GAAG,MAAM,CAAC,CAAC;AACpD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-start-rsc",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "React Server Components support for TanStack Start",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -83,13 +83,13 @@
83
83
  "dependencies": {
84
84
  "pathe": "^2.0.3",
85
85
  "@tanstack/react-router": "1.170.8",
86
- "@tanstack/react-start-server": "1.167.8",
86
+ "@tanstack/react-start-server": "1.167.9",
87
87
  "@tanstack/router-core": "1.171.6",
88
88
  "@tanstack/router-utils": "1.162.1",
89
- "@tanstack/start-client-core": "1.170.3",
89
+ "@tanstack/start-client-core": "1.170.4",
90
90
  "@tanstack/start-fn-stubs": "1.162.0",
91
- "@tanstack/start-plugin-core": "1.171.4",
92
- "@tanstack/start-server-core": "1.169.3",
91
+ "@tanstack/start-plugin-core": "1.171.6",
92
+ "@tanstack/start-server-core": "1.169.4",
93
93
  "@tanstack/start-storage-context": "1.167.8"
94
94
  },
95
95
  "devDependencies": {