@tanstack/router-core
Version:
Modern and scalable routing for React applications
1 lines • 20 kB
Source Map (JSON)
{"version":3,"file":"RawStream.cjs","names":[],"sources":["../../../../src/ssr/serializer/RawStream.ts"],"sourcesContent":["import { createPlugin, createStream } from 'seroval'\nimport type { PluginData, PluginInfo, SerovalNode } from 'seroval'\n\n/**\n * Hint for RawStream encoding strategy during SSR serialization.\n * - 'binary': Always use base64 encoding (best for binary data like files, images)\n * - 'text': Try UTF-8 first, fallback to base64 (best for text-heavy data like RSC payloads)\n */\nexport type RawStreamHint = 'binary' | 'text'\n\n/**\n * Options for RawStream configuration.\n */\nexport interface RawStreamOptions {\n /**\n * Encoding hint for SSR serialization.\n * - 'binary' (default): Always use base64 encoding\n * - 'text': Try UTF-8 first, fallback to base64 for invalid UTF-8 chunks\n */\n hint?: RawStreamHint\n}\n\n/**\n * Marker class for ReadableStream<Uint8Array> that should be serialized\n * with base64 encoding (SSR) or binary framing (server functions).\n *\n * Wrap your binary streams with this to get efficient serialization:\n * ```ts\n * // For binary data (files, images, etc.)\n * return { data: new RawStream(file.stream()) }\n *\n * // For text-heavy data (RSC payloads, etc.)\n * return { data: new RawStream(rscStream, { hint: 'text' }) }\n * ```\n */\nexport class RawStream {\n public readonly hint: RawStreamHint\n\n constructor(\n public readonly stream: ReadableStream<Uint8Array>,\n options?: RawStreamOptions,\n ) {\n this.hint = options?.hint ?? 'binary'\n }\n}\n\n/**\n * Callback type for RPC plugin to register raw streams with multiplexer\n */\nexport type OnRawStreamCallback = (\n streamId: number,\n stream: ReadableStream<Uint8Array>,\n) => void\n\n// Base64 helpers used in both Node and browser.\n// In Node-like runtimes, prefer Buffer for speed and compatibility.\nconst BufferCtor: any = (globalThis as any).Buffer\nconst hasNodeBuffer = !!BufferCtor && typeof BufferCtor.from === 'function'\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n if (bytes.length === 0) return ''\n\n if (hasNodeBuffer) {\n return BufferCtor.from(bytes).toString('base64')\n }\n\n // Browser fallback: chunked String.fromCharCode + btoa\n const CHUNK_SIZE = 0x8000 // 32KB chunks to avoid stack overflow\n const chunks: Array<string> = []\n for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {\n const chunk = bytes.subarray(i, i + CHUNK_SIZE)\n chunks.push(String.fromCharCode.apply(null, chunk as any))\n }\n return btoa(chunks.join(''))\n}\n\nfunction base64ToUint8Array(base64: string): Uint8Array {\n if (base64.length === 0) return new Uint8Array(0)\n\n if (hasNodeBuffer) {\n const buf = BufferCtor.from(base64, 'base64')\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)\n }\n\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes\n}\n\n// Factory sentinels - use null-proto objects to avoid prototype surprises\nconst RAW_STREAM_FACTORY_BINARY: Record<string, never> = Object.create(null)\nconst RAW_STREAM_FACTORY_TEXT: Record<string, never> = Object.create(null)\n\n// Factory constructor for binary mode - converts seroval stream to ReadableStream<Uint8Array>\n// All chunks are base64 encoded strings\nconst RAW_STREAM_FACTORY_CONSTRUCTOR_BINARY = (\n stream: ReturnType<typeof createStream>,\n) =>\n new ReadableStream<Uint8Array>({\n start(controller) {\n stream.on({\n next(base64: string) {\n try {\n controller.enqueue(base64ToUint8Array(base64))\n } catch {\n // Stream may be closed\n }\n },\n throw(error: unknown) {\n controller.error(error)\n },\n return() {\n try {\n controller.close()\n } catch {\n // Stream may already be closed\n }\n },\n })\n },\n })\n\n// Factory constructor for text mode - converts seroval stream to ReadableStream<Uint8Array>\n// Chunks are either strings (UTF-8) or { $b64: string } (base64 fallback)\n// Use module-level TextEncoder to avoid per-factory allocation\nconst textEncoderForFactory = new TextEncoder()\nconst RAW_STREAM_FACTORY_CONSTRUCTOR_TEXT = (\n stream: ReturnType<typeof createStream>,\n) => {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n stream.on({\n next(value: string | { $b64: string }) {\n try {\n if (typeof value === 'string') {\n controller.enqueue(textEncoderForFactory.encode(value))\n } else {\n controller.enqueue(base64ToUint8Array(value.$b64))\n }\n } catch {\n // Stream may be closed\n }\n },\n throw(error: unknown) {\n controller.error(error)\n },\n return() {\n try {\n controller.close()\n } catch {\n // Stream may already be closed\n }\n },\n })\n },\n })\n}\n\n// Minified factory function for binary mode - all chunks are base64 strings\n// This must be self-contained since it's injected into the HTML\nconst FACTORY_BINARY = `(s=>new ReadableStream({start(c){s.on({next(b){try{const d=atob(b),a=new Uint8Array(d.length);for(let i=0;i<d.length;i++)a[i]=d.charCodeAt(i);c.enqueue(a)}catch(_){}},throw(e){c.error(e)},return(){try{c.close()}catch(_){}}})}}))`\n\n// Minified factory function for text mode - chunks are string or {$b64: string}\n// Uses cached TextEncoder for performance\nconst FACTORY_TEXT = `(s=>{const e=new TextEncoder();return new ReadableStream({start(c){s.on({next(v){try{if(typeof v==='string'){c.enqueue(e.encode(v))}else{const d=atob(v.$b64),a=new Uint8Array(d.length);for(let i=0;i<d.length;i++)a[i]=d.charCodeAt(i);c.enqueue(a)}}catch(_){}},throw(x){c.error(x)},return(){try{c.close()}catch(_){}}})}})})`\n\n// Convert ReadableStream<Uint8Array> to seroval stream with base64-encoded chunks (binary mode)\nfunction toBinaryStream(readable: ReadableStream<Uint8Array>) {\n const stream = createStream()\n const reader = readable.getReader()\n\n // Use iterative loop instead of recursive async to avoid stack accumulation\n ;(async () => {\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) {\n stream.return(undefined)\n break\n }\n stream.next(uint8ArrayToBase64(value))\n }\n } catch (error) {\n stream.throw(error)\n } finally {\n reader.releaseLock()\n }\n })()\n\n return stream\n}\n\n// Convert ReadableStream<Uint8Array> to seroval stream with UTF-8 first, base64 fallback (text mode)\nfunction toTextStream(readable: ReadableStream<Uint8Array>) {\n const stream = createStream()\n const reader = readable.getReader()\n const decoder = new TextDecoder('utf-8', { fatal: true })\n\n // Use iterative loop instead of recursive async to avoid stack accumulation\n ;(async () => {\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) {\n // Flush any remaining bytes in the decoder\n try {\n const remaining = decoder.decode()\n if (remaining.length > 0) {\n stream.next(remaining)\n }\n } catch {\n // Ignore decode errors on flush\n }\n stream.return(undefined)\n break\n }\n\n try {\n // Try UTF-8 decode first\n const text = decoder.decode(value, { stream: true })\n if (text.length > 0) {\n stream.next(text)\n }\n } catch {\n // UTF-8 decode failed, fallback to base64\n stream.next({ $b64: uint8ArrayToBase64(value) })\n }\n }\n } catch (error) {\n stream.throw(error)\n } finally {\n reader.releaseLock()\n }\n })()\n\n return stream\n}\n\n// Factory plugin for binary mode\nconst RawStreamFactoryBinaryPlugin = /* @__PURE__ */ createPlugin<\n Record<string, never>,\n PluginInfo\n>({\n tag: 'tss/RawStreamFactory',\n test(value) {\n return value === RAW_STREAM_FACTORY_BINARY\n },\n parse: {\n sync(_value, _ctx, _data) {\n return {}\n },\n async async(_value, _ctx, _data) {\n return {}\n },\n stream(_value, _ctx, _data) {\n return {}\n },\n },\n serialize(_node, _ctx, _data) {\n return FACTORY_BINARY\n },\n deserialize(_node, _ctx, _data) {\n return RAW_STREAM_FACTORY_BINARY\n },\n})\n\n// Factory plugin for text mode\nconst RawStreamFactoryTextPlugin = /* @__PURE__ */ createPlugin<\n Record<string, never>,\n PluginInfo\n>({\n tag: 'tss/RawStreamFactoryText',\n test(value) {\n return value === RAW_STREAM_FACTORY_TEXT\n },\n parse: {\n sync(_value, _ctx, _data) {\n return {}\n },\n async async(_value, _ctx, _data) {\n return {}\n },\n stream(_value, _ctx, _data) {\n return {}\n },\n },\n serialize(_node, _ctx, _data) {\n return FACTORY_TEXT\n },\n deserialize(_node, _ctx, _data) {\n return RAW_STREAM_FACTORY_TEXT\n },\n})\n\nexport interface RawStreamSSRNode extends PluginInfo {\n hint: SerovalNode\n factory: SerovalNode\n stream: SerovalNode\n}\n\nexport interface RawStreamRPCNode extends PluginInfo {\n streamId: SerovalNode\n}\n\n/**\n * SSR Plugin - uses base64 or UTF-8+base64 encoding for chunks, delegates to seroval's stream mechanism.\n * Used during SSR when serializing to JavaScript code for HTML injection.\n *\n * Supports two modes based on RawStream hint:\n * - 'binary': Always base64 encode (default)\n * - 'text': Try UTF-8 first, fallback to base64 for invalid UTF-8\n */\nexport const RawStreamSSRPlugin = /* @__PURE__ */ createPlugin<\n RawStream,\n RawStreamSSRNode\n>({\n tag: 'tss/RawStream',\n extends: [RawStreamFactoryBinaryPlugin, RawStreamFactoryTextPlugin],\n\n test(value: unknown) {\n return value instanceof RawStream\n },\n\n parse: {\n sync(value: RawStream, ctx, _data) {\n // Sync parse not really supported for streams, return empty stream\n const factory =\n value.hint === 'text'\n ? RAW_STREAM_FACTORY_TEXT\n : RAW_STREAM_FACTORY_BINARY\n return {\n hint: ctx.parse(value.hint),\n factory: ctx.parse(factory),\n stream: ctx.parse(createStream()),\n }\n },\n async async(value: RawStream, ctx, _data) {\n const factory =\n value.hint === 'text'\n ? RAW_STREAM_FACTORY_TEXT\n : RAW_STREAM_FACTORY_BINARY\n const encodedStream =\n value.hint === 'text'\n ? toTextStream(value.stream)\n : toBinaryStream(value.stream)\n return {\n hint: await ctx.parse(value.hint),\n factory: await ctx.parse(factory),\n stream: await ctx.parse(encodedStream),\n }\n },\n stream(value: RawStream, ctx, _data) {\n const factory =\n value.hint === 'text'\n ? RAW_STREAM_FACTORY_TEXT\n : RAW_STREAM_FACTORY_BINARY\n const encodedStream =\n value.hint === 'text'\n ? toTextStream(value.stream)\n : toBinaryStream(value.stream)\n return {\n hint: ctx.parse(value.hint),\n factory: ctx.parse(factory),\n stream: ctx.parse(encodedStream),\n }\n },\n },\n\n serialize(node: RawStreamSSRNode, ctx, _data) {\n return (\n '(' +\n ctx.serialize(node.factory) +\n ')(' +\n ctx.serialize(node.stream) +\n ')'\n )\n },\n\n deserialize(node: RawStreamSSRNode, ctx, _data): any {\n const stream: ReturnType<typeof createStream> = ctx.deserialize(node.stream)\n const hint = ctx.deserialize(node.hint)\n return hint === 'text'\n ? RAW_STREAM_FACTORY_CONSTRUCTOR_TEXT(stream)\n : RAW_STREAM_FACTORY_CONSTRUCTOR_BINARY(stream)\n },\n})\n\n/**\n * Creates an RPC plugin instance that registers raw streams with a multiplexer.\n * Used for server function responses where we want binary framing.\n * Note: RPC always uses binary framing regardless of hint.\n *\n * @param onRawStream Callback invoked when a RawStream is encountered during serialization\n */\n/* @__NO_SIDE_EFFECTS__ */\nexport function createRawStreamRPCPlugin(onRawStream: OnRawStreamCallback) {\n // Own stream counter - sequential IDs starting at 1, independent of seroval internals\n let nextStreamId = 1\n\n return /* @__PURE__ */ createPlugin<RawStream, RawStreamRPCNode>({\n tag: 'tss/RawStream',\n\n test(value: unknown) {\n return value instanceof RawStream\n },\n\n parse: {\n async async(value: RawStream, ctx, _data: PluginData) {\n const streamId = nextStreamId++\n onRawStream(streamId, value.stream)\n return { streamId: await ctx.parse(streamId) }\n },\n stream(value: RawStream, ctx, _data: PluginData) {\n const streamId = nextStreamId++\n onRawStream(streamId, value.stream)\n return { streamId: ctx.parse(streamId) }\n },\n },\n\n serialize(): never {\n // RPC uses toCrossJSONStream which produces JSON nodes, not JS code.\n // This method is only called by crossSerialize* which we don't use.\n throw new Error(\n 'RawStreamRPCPlugin.serialize should not be called. RPC uses JSON serialization, not JS code generation.',\n )\n },\n\n deserialize(): never {\n // Client uses createRawStreamDeserializePlugin instead\n throw new Error(\n 'RawStreamRPCPlugin.deserialize should not be called. Use createRawStreamDeserializePlugin on client.',\n )\n },\n })\n}\n\n/**\n * Creates a deserialize-only plugin for client-side stream reconstruction.\n * Used in serverFnFetcher to wire up streams from frame decoder.\n *\n * @param getOrCreateStream Function to get/create a stream by ID from frame decoder\n */\nexport function createRawStreamDeserializePlugin(\n getOrCreateStream: (id: number) => ReadableStream<Uint8Array>,\n) {\n return /* @__PURE__ */ createPlugin<any, RawStreamRPCNode>({\n tag: 'tss/RawStream',\n\n test: () => false, // Client never serializes RawStream\n\n parse: {}, // Client only deserializes, never parses\n\n serialize(): never {\n // Client never serializes RawStream back to server\n throw new Error(\n 'RawStreamDeserializePlugin.serialize should not be called. Client only deserializes.',\n )\n },\n\n deserialize(node, ctx, _data) {\n // In normal seroval usage, ctx.deserialize exists.\n // Some unit tests call plugin.deserialize directly with a minimal ctx.\n const id =\n typeof (ctx as any)?.deserialize === 'function'\n ? (ctx as any).deserialize(node.streamId)\n : (node as any).streamId\n return getOrCreateStream(id as number)\n },\n })\n}\n"],"mappings":"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"}