@tanstack/start-client-core 1.170.2 → 1.170.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/esm/client/ServerFunctionSerializationAdapter.js.map +1 -1
  2. package/dist/esm/client/hydrateStart.js.map +1 -1
  3. package/dist/esm/client-rpc/createClientRpc.js.map +1 -1
  4. package/dist/esm/client-rpc/frame-decoder.js.map +1 -1
  5. package/dist/esm/client-rpc/serverFnFetcher.js.map +1 -1
  6. package/dist/esm/constants.js +4 -0
  7. package/dist/esm/constants.js.map +1 -1
  8. package/dist/esm/createCsrfMiddleware.js.map +1 -1
  9. package/dist/esm/createMiddleware.js.map +1 -1
  10. package/dist/esm/createServerFn.js.map +1 -1
  11. package/dist/esm/createStart.js.map +1 -1
  12. package/dist/esm/{fake-entries/plugin-adapters.js → empty-plugin-adapters.js} +2 -2
  13. package/dist/esm/empty-plugin-adapters.js.map +1 -0
  14. package/dist/esm/fake-entries/router.js.map +1 -1
  15. package/dist/esm/getDefaultSerovalPlugins.js.map +1 -1
  16. package/dist/esm/getGlobalStartContext.js.map +1 -1
  17. package/dist/esm/getRouterInstance.js.map +1 -1
  18. package/dist/esm/getStartContextServerOnly.js.map +1 -1
  19. package/dist/esm/getStartOptions.js.map +1 -1
  20. package/dist/esm/hydration/condition.js.map +1 -1
  21. package/dist/esm/hydration/idle.js.map +1 -1
  22. package/dist/esm/hydration/interaction.js.map +1 -1
  23. package/dist/esm/hydration/load.js.map +1 -1
  24. package/dist/esm/hydration/media.js.map +1 -1
  25. package/dist/esm/hydration/never.js.map +1 -1
  26. package/dist/esm/hydration/renderer.js.map +1 -1
  27. package/dist/esm/hydration/runtime.js.map +1 -1
  28. package/dist/esm/hydration/visible.js.map +1 -1
  29. package/dist/esm/safeObjectMerge.js.map +1 -1
  30. package/package.json +4 -4
  31. package/dist/esm/fake-entries/plugin-adapters.js.map +0 -1
  32. /package/dist/esm/{fake-entries/plugin-adapters.d.ts → empty-plugin-adapters.d.ts} +0 -0
  33. /package/src/{fake-entries/plugin-adapters.ts → empty-plugin-adapters.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"ServerFunctionSerializationAdapter.js","names":[],"sources":["../../../src/client/ServerFunctionSerializationAdapter.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION } from '../constants'\nimport { createClientRpc } from '../client-rpc/createClientRpc'\n\nexport const ServerFunctionSerializationAdapter = createSerializationAdapter({\n key: '$TSS/serverfn',\n test: (v): v is { serverFnMeta: { id: string } } => {\n if (typeof v !== 'function') return false\n\n if (!(TSS_SERVER_FUNCTION in v)) return false\n\n return !!v[TSS_SERVER_FUNCTION]\n },\n toSerializable: ({ serverFnMeta }) => ({ functionId: serverFnMeta.id }),\n fromSerializable: ({ functionId }) => createClientRpc(functionId),\n})\n"],"mappings":";;;;AAIA,IAAa,qCAAqC,2BAA2B;CAC3E,KAAK;CACL,OAAO,MAA6C;AAClD,MAAI,OAAO,MAAM,WAAY,QAAO;AAEpC,MAAI,EAAE,uBAAuB,GAAI,QAAO;AAExC,SAAO,CAAC,CAAC,EAAE;;CAEb,iBAAiB,EAAE,oBAAoB,EAAE,YAAY,aAAa,IAAI;CACtE,mBAAmB,EAAE,iBAAiB,gBAAgB,WAAW;CAClE,CAAC"}
1
+ {"version":3,"file":"ServerFunctionSerializationAdapter.js","names":[],"sources":["../../../src/client/ServerFunctionSerializationAdapter.ts"],"sourcesContent":["import { createSerializationAdapter } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION } from '../constants'\nimport { createClientRpc } from '../client-rpc/createClientRpc'\n\nexport const ServerFunctionSerializationAdapter = createSerializationAdapter({\n key: '$TSS/serverfn',\n test: (v): v is { serverFnMeta: { id: string } } => {\n if (typeof v !== 'function') return false\n\n if (!(TSS_SERVER_FUNCTION in v)) return false\n\n return !!v[TSS_SERVER_FUNCTION]\n },\n toSerializable: ({ serverFnMeta }) => ({ functionId: serverFnMeta.id }),\n fromSerializable: ({ functionId }) => createClientRpc(functionId),\n})\n"],"mappings":";;;;AAIA,IAAa,qCAAqC,2BAA2B;CAC3E,KAAK;CACL,OAAO,MAA6C;EAClD,IAAI,OAAO,MAAM,YAAY,OAAO;EAEpC,IAAI,EAAE,uBAAuB,IAAI,OAAO;EAExC,OAAO,CAAC,CAAC,EAAE;CACb;CACA,iBAAiB,EAAE,oBAAoB,EAAE,YAAY,aAAa,GAAG;CACrE,mBAAmB,EAAE,iBAAiB,gBAAgB,UAAU;AAClE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"hydrateStart.js","names":[],"sources":["../../../src/client/hydrateStart.ts"],"sourcesContent":["import { hydrate } from '@tanstack/router-core/ssr/client'\nimport { startInstance } from '#tanstack-start-entry'\nimport {\n hasPluginAdapters,\n pluginSerializationAdapters,\n} from '#tanstack-start-plugin-adapters'\nimport { getRouter } from '#tanstack-router-entry'\nimport { ServerFunctionSerializationAdapter } from './ServerFunctionSerializationAdapter'\nimport type { AnyRouter, AnySerializationAdapter } from '@tanstack/router-core'\nimport type { AnyStartInstanceOptions } from '../createStart'\n\ntype HotContext = {\n data?: Record<string, unknown>\n dispose?: (cb: (data: Record<string, unknown>) => void) => void\n}\n\ndeclare global {\n interface ImportMeta {\n hot?: HotContext\n webpackHot?: HotContext\n }\n}\n\nasync function hydrateStart(): Promise<AnyRouter> {\n const router = await getRouter()\n\n let serializationAdapters: Array<AnySerializationAdapter>\n if (startInstance) {\n const startOptions = await startInstance.getOptions()\n startOptions.serializationAdapters =\n startOptions.serializationAdapters ?? []\n window.__TSS_START_OPTIONS__ = startOptions as AnyStartInstanceOptions\n serializationAdapters = startOptions.serializationAdapters\n router.options.defaultSsr = startOptions.defaultSsr\n } else {\n serializationAdapters = []\n window.__TSS_START_OPTIONS__ = {\n serializationAdapters,\n } as AnyStartInstanceOptions\n }\n\n // Only spread plugin adapters if any are configured (this will tree-shake away otherwise)\n if (hasPluginAdapters) {\n serializationAdapters.push(...pluginSerializationAdapters)\n }\n serializationAdapters.push(ServerFunctionSerializationAdapter)\n if (router.options.serializationAdapters) {\n serializationAdapters.push(...router.options.serializationAdapters)\n }\n\n router.update({\n basepath: process.env.TSS_ROUTER_BASEPATH,\n ...{ serializationAdapters },\n })\n if (!router.stores.matchesId.get().length) {\n await hydrate(router)\n }\n\n return router\n}\n\nfunction hydrateStartWithHmr(): Promise<AnyRouter> {\n const hot = import.meta.hot ?? import.meta.webpackHot\n\n if (!hot) {\n return hydrateStart()\n }\n\n const key = 'tss-hydrate-start-promise'\n const hotData = (hot.data ??= {})\n let hydrationPromise = hotData[key] as Promise<AnyRouter> | undefined\n\n if (!hydrationPromise) {\n hydrationPromise = hydrateStart().catch((error) => {\n if (hotData[key] === hydrationPromise) {\n hotData[key] = undefined\n }\n\n throw error\n })\n\n hotData[key] = hydrationPromise\n }\n\n hot.dispose?.((data) => {\n data[key] = hotData[key]\n })\n\n return hydrationPromise\n}\n\nconst exportedHydrateStart =\n process.env.NODE_ENV !== 'production' ? hydrateStartWithHmr : hydrateStart\n\nexport { exportedHydrateStart as hydrateStart }\n"],"mappings":";;;;;;AAuBA,eAAe,eAAmC;CAChD,MAAM,SAAS,MAAM,WAAW;CAEhC,IAAI;AACJ,KAAI,eAAe;EACjB,MAAM,eAAe,MAAM,cAAc,YAAY;AACrD,eAAa,wBACX,aAAa,yBAAyB,EAAE;AAC1C,SAAO,wBAAwB;AAC/B,0BAAwB,aAAa;AACrC,SAAO,QAAQ,aAAa,aAAa;QACpC;AACL,0BAAwB,EAAE;AAC1B,SAAO,wBAAwB,EAC7B,uBACD;;AAIH,KAAI,kBACF,uBAAsB,KAAK,GAAG,4BAA4B;AAE5D,uBAAsB,KAAK,mCAAmC;AAC9D,KAAI,OAAO,QAAQ,sBACjB,uBAAsB,KAAK,GAAG,OAAO,QAAQ,sBAAsB;AAGrE,QAAO,OAAO;EACZ,UAAU,QAAQ,IAAI;EACjB;EACN,CAAC;AACF,KAAI,CAAC,OAAO,OAAO,UAAU,KAAK,CAAC,OACjC,OAAM,QAAQ,OAAO;AAGvB,QAAO;;AAGT,SAAS,sBAA0C;CACjD,MAAM,MAAA,OAAA,KAAA,OAAyB,OAAO,KAAK;AAE3C,KAAI,CAAC,IACH,QAAO,cAAc;CAGvB,MAAM,MAAM;CACZ,MAAM,UAAW,IAAI,SAAS,EAAE;CAChC,IAAI,mBAAmB,QAAQ;AAE/B,KAAI,CAAC,kBAAkB;AACrB,qBAAmB,cAAc,CAAC,OAAO,UAAU;AACjD,OAAI,QAAQ,SAAS,iBACnB,SAAQ,OAAO,KAAA;AAGjB,SAAM;IACN;AAEF,UAAQ,OAAO;;AAGjB,KAAI,WAAW,SAAS;AACtB,OAAK,OAAO,QAAQ;GACpB;AAEF,QAAO;;AAGT,IAAM,uBAAA,QAAA,IAAA,aACqB,eAAe,sBAAsB"}
1
+ {"version":3,"file":"hydrateStart.js","names":[],"sources":["../../../src/client/hydrateStart.ts"],"sourcesContent":["import { hydrate } from '@tanstack/router-core/ssr/client'\nimport { startInstance } from '#tanstack-start-entry'\nimport {\n hasPluginAdapters,\n pluginSerializationAdapters,\n} from '#tanstack-start-plugin-adapters'\nimport { getRouter } from '#tanstack-router-entry'\nimport { ServerFunctionSerializationAdapter } from './ServerFunctionSerializationAdapter'\nimport type { AnyRouter, AnySerializationAdapter } from '@tanstack/router-core'\nimport type { AnyStartInstanceOptions } from '../createStart'\n\ntype HotContext = {\n data?: Record<string, unknown>\n dispose?: (cb: (data: Record<string, unknown>) => void) => void\n}\n\ndeclare global {\n interface ImportMeta {\n hot?: HotContext\n webpackHot?: HotContext\n }\n}\n\nasync function hydrateStart(): Promise<AnyRouter> {\n const router = await getRouter()\n\n let serializationAdapters: Array<AnySerializationAdapter>\n if (startInstance) {\n const startOptions = await startInstance.getOptions()\n startOptions.serializationAdapters =\n startOptions.serializationAdapters ?? []\n window.__TSS_START_OPTIONS__ = startOptions as AnyStartInstanceOptions\n serializationAdapters = startOptions.serializationAdapters\n router.options.defaultSsr = startOptions.defaultSsr\n } else {\n serializationAdapters = []\n window.__TSS_START_OPTIONS__ = {\n serializationAdapters,\n } as AnyStartInstanceOptions\n }\n\n // Only spread plugin adapters if any are configured (this will tree-shake away otherwise)\n if (hasPluginAdapters) {\n serializationAdapters.push(...pluginSerializationAdapters)\n }\n serializationAdapters.push(ServerFunctionSerializationAdapter)\n if (router.options.serializationAdapters) {\n serializationAdapters.push(...router.options.serializationAdapters)\n }\n\n router.update({\n basepath: process.env.TSS_ROUTER_BASEPATH,\n ...{ serializationAdapters },\n })\n if (!router.stores.matchesId.get().length) {\n await hydrate(router)\n }\n\n return router\n}\n\nfunction hydrateStartWithHmr(): Promise<AnyRouter> {\n const hot = import.meta.hot ?? import.meta.webpackHot\n\n if (!hot) {\n return hydrateStart()\n }\n\n const key = 'tss-hydrate-start-promise'\n const hotData = (hot.data ??= {})\n let hydrationPromise = hotData[key] as Promise<AnyRouter> | undefined\n\n if (!hydrationPromise) {\n hydrationPromise = hydrateStart().catch((error) => {\n if (hotData[key] === hydrationPromise) {\n hotData[key] = undefined\n }\n\n throw error\n })\n\n hotData[key] = hydrationPromise\n }\n\n hot.dispose?.((data) => {\n data[key] = hotData[key]\n })\n\n return hydrationPromise\n}\n\nconst exportedHydrateStart =\n process.env.NODE_ENV !== 'production' ? hydrateStartWithHmr : hydrateStart\n\nexport { exportedHydrateStart as hydrateStart }\n"],"mappings":";;;;;;AAuBA,eAAe,eAAmC;CAChD,MAAM,SAAS,MAAM,UAAU;CAE/B,IAAI;CACJ,IAAI,eAAe;EACjB,MAAM,eAAe,MAAM,cAAc,WAAW;EACpD,aAAa,wBACX,aAAa,yBAAyB,CAAC;EACzC,OAAO,wBAAwB;EAC/B,wBAAwB,aAAa;EACrC,OAAO,QAAQ,aAAa,aAAa;CAC3C,OAAO;EACL,wBAAwB,CAAC;EACzB,OAAO,wBAAwB,EAC7B,sBACF;CACF;CAGA,IAAI,mBACF,sBAAsB,KAAK,GAAG,2BAA2B;CAE3D,sBAAsB,KAAK,kCAAkC;CAC7D,IAAI,OAAO,QAAQ,uBACjB,sBAAsB,KAAK,GAAG,OAAO,QAAQ,qBAAqB;CAGpE,OAAO,OAAO;EACZ,UAAU,QAAQ,IAAI;EACjB;CACP,CAAC;CACD,IAAI,CAAC,OAAO,OAAO,UAAU,IAAI,EAAE,QACjC,MAAM,QAAQ,MAAM;CAGtB,OAAO;AACT;AAEA,SAAS,sBAA0C;CACjD,MAAM,MAAA,OAAA,KAAA,OAAyB,OAAO,KAAK;CAE3C,IAAI,CAAC,KACH,OAAO,aAAa;CAGtB,MAAM,MAAM;CACZ,MAAM,UAAW,IAAI,SAAS,CAAC;CAC/B,IAAI,mBAAmB,QAAQ;CAE/B,IAAI,CAAC,kBAAkB;EACrB,mBAAmB,aAAa,EAAE,OAAO,UAAU;GACjD,IAAI,QAAQ,SAAS,kBACnB,QAAQ,OAAO,KAAA;GAGjB,MAAM;EACR,CAAC;EAED,QAAQ,OAAO;CACjB;CAEA,IAAI,WAAW,SAAS;EACtB,KAAK,OAAO,QAAQ;CACtB,CAAC;CAED,OAAO;AACT;AAEA,IAAM,uBAAA,QAAA,IAAA,aACqB,eAAe,sBAAsB"}
@@ -1 +1 @@
1
- {"version":3,"file":"createClientRpc.js","names":[],"sources":["../../../src/client-rpc/createClientRpc.ts"],"sourcesContent":["import { TSS_SERVER_FUNCTION } from '../constants'\nimport { getStartOptions } from '../getStartOptions'\nimport { serverFnFetcher } from './serverFnFetcher'\nimport type { ClientFnMeta } from '../constants'\n\nexport function createClientRpc(functionId: string) {\n const url = process.env.TSS_SERVER_FN_BASE + functionId\n const serverFnMeta: ClientFnMeta = { id: functionId }\n\n const clientFn = (...args: Array<any>) => {\n const startFetch = getStartOptions()?.serverFns?.fetch\n return serverFnFetcher(url, args, startFetch ?? fetch)\n }\n\n return Object.assign(clientFn, {\n url,\n serverFnMeta,\n [TSS_SERVER_FUNCTION]: true,\n })\n}\n"],"mappings":";;;;AAKA,SAAgB,gBAAgB,YAAoB;CAClD,MAAM,MAAM,QAAQ,IAAI,qBAAqB;CAC7C,MAAM,eAA6B,EAAE,IAAI,YAAY;CAErD,MAAM,YAAY,GAAG,SAAqB;EACxC,MAAM,aAAa,iBAAiB,EAAE,WAAW;AACjD,SAAO,gBAAgB,KAAK,MAAM,cAAc,MAAM;;AAGxD,QAAO,OAAO,OAAO,UAAU;EAC7B;EACA;GACC,sBAAsB;EACxB,CAAC"}
1
+ {"version":3,"file":"createClientRpc.js","names":[],"sources":["../../../src/client-rpc/createClientRpc.ts"],"sourcesContent":["import { TSS_SERVER_FUNCTION } from '../constants'\nimport { getStartOptions } from '../getStartOptions'\nimport { serverFnFetcher } from './serverFnFetcher'\nimport type { ClientFnMeta } from '../constants'\n\nexport function createClientRpc(functionId: string) {\n const url = process.env.TSS_SERVER_FN_BASE + functionId\n const serverFnMeta: ClientFnMeta = { id: functionId }\n\n const clientFn = (...args: Array<any>) => {\n const startFetch = getStartOptions()?.serverFns?.fetch\n return serverFnFetcher(url, args, startFetch ?? fetch)\n }\n\n return Object.assign(clientFn, {\n url,\n serverFnMeta,\n [TSS_SERVER_FUNCTION]: true,\n })\n}\n"],"mappings":";;;;AAKA,SAAgB,gBAAgB,YAAoB;CAClD,MAAM,MAAM,QAAQ,IAAI,qBAAqB;CAC7C,MAAM,eAA6B,EAAE,IAAI,WAAW;CAEpD,MAAM,YAAY,GAAG,SAAqB;EACxC,MAAM,aAAa,gBAAgB,GAAG,WAAW;EACjD,OAAO,gBAAgB,KAAK,MAAM,cAAc,KAAK;CACvD;CAEA,OAAO,OAAO,OAAO,UAAU;EAC7B;EACA;GACC,sBAAsB;CACzB,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-decoder.js","names":[],"sources":["../../../src/client-rpc/frame-decoder.ts"],"sourcesContent":["/**\n * Client-side frame decoder for multiplexed responses.\n *\n * Decodes binary frame protocol and reconstructs:\n * - JSON stream (NDJSON lines for seroval)\n * - Raw streams (binary data as ReadableStream<Uint8Array>)\n */\n\nimport { FRAME_HEADER_SIZE, FrameType } from '../constants'\n\n/** Cached TextDecoder for frame decoding */\nconst textDecoder = new TextDecoder()\n\n/** Shared empty buffer for empty buffer case - avoids allocation */\nconst EMPTY_BUFFER = new Uint8Array(0)\n\n/** Hardening limits to prevent memory/CPU DoS */\nconst MAX_FRAME_PAYLOAD_SIZE = 16 * 1024 * 1024 // 16MiB\nconst MAX_BUFFERED_BYTES = 32 * 1024 * 1024 // 32MiB\nconst MAX_STREAMS = 1024\nconst MAX_FRAMES = 100_000 // Limit total frames to prevent CPU DoS\n\n/**\n * Result of frame decoding.\n */\nexport interface FrameDecoderResult {\n /** Gets or creates a raw stream by ID (for use by deserialize plugin) */\n getOrCreateStream: (id: number) => ReadableStream<Uint8Array>\n /** Stream of JSON strings (NDJSON lines) */\n jsonChunks: ReadableStream<string>\n}\n\n/**\n * Creates a frame decoder that processes a multiplexed response stream.\n *\n * @param input The raw response body stream\n * @returns Decoded JSON stream and stream getter function\n */\nexport function createFrameDecoder(\n input: ReadableStream<Uint8Array>,\n): FrameDecoderResult {\n const streamControllers = new Map<\n number,\n ReadableStreamDefaultController<Uint8Array>\n >()\n const streams = new Map<number, ReadableStream<Uint8Array>>()\n const cancelledStreamIds = new Set<number>()\n\n let cancelled = false as boolean\n let inputReader: ReadableStreamReader<Uint8Array> | null = null\n let frameCount = 0\n\n let jsonController!: ReadableStreamDefaultController<string>\n const jsonChunks = new ReadableStream<string>({\n start(controller) {\n jsonController = controller\n },\n cancel() {\n cancelled = true\n try {\n inputReader?.cancel()\n } catch {\n // Ignore\n }\n\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.error(new Error('Framed response cancelled'))\n } catch {\n // Ignore\n }\n })\n streamControllers.clear()\n streams.clear()\n cancelledStreamIds.clear()\n },\n })\n\n /**\n * Gets or creates a stream for a given stream ID.\n * Called by deserialize plugin when it encounters a RawStream reference.\n */\n function getOrCreateStream(id: number): ReadableStream<Uint8Array> {\n const existing = streams.get(id)\n if (existing) {\n return existing\n }\n\n // If we already received an END/ERROR for this streamId, returning a fresh stream\n // would hang consumers. Return an already-closed stream instead.\n if (cancelledStreamIds.has(id)) {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.close()\n },\n })\n }\n\n if (streams.size >= MAX_STREAMS) {\n throw new Error(\n `Too many raw streams in framed response (max ${MAX_STREAMS})`,\n )\n }\n\n const stream = new ReadableStream<Uint8Array>({\n start(ctrl) {\n streamControllers.set(id, ctrl)\n },\n cancel() {\n cancelledStreamIds.add(id)\n streamControllers.delete(id)\n streams.delete(id)\n },\n })\n streams.set(id, stream)\n return stream\n }\n\n /**\n * Ensures stream exists and returns its controller for enqueuing data.\n * Used for CHUNK frames where we need to ensure stream is created.\n */\n function ensureController(\n id: number,\n ): ReadableStreamDefaultController<Uint8Array> | undefined {\n getOrCreateStream(id)\n return streamControllers.get(id)\n }\n\n // Process frames asynchronously\n ;(async () => {\n const reader = input.getReader()\n inputReader = reader\n\n const bufferList: Array<Uint8Array> = []\n let totalLength = 0\n\n /**\n * Reads header bytes from buffer chunks without flattening.\n * Returns header data or null if not enough bytes available.\n */\n function readHeader(): {\n type: number\n streamId: number\n length: number\n } | null {\n if (totalLength < FRAME_HEADER_SIZE) return null\n\n const first = bufferList[0]!\n\n // Fast path: header fits entirely in first chunk (common case)\n if (first.length >= FRAME_HEADER_SIZE) {\n const type = first[0]!\n const streamId =\n ((first[1]! << 24) |\n (first[2]! << 16) |\n (first[3]! << 8) |\n first[4]!) >>>\n 0\n const length =\n ((first[5]! << 24) |\n (first[6]! << 16) |\n (first[7]! << 8) |\n first[8]!) >>>\n 0\n return { type, streamId, length }\n }\n\n // Slow path: header spans multiple chunks - flatten header bytes only\n const headerBytes = new Uint8Array(FRAME_HEADER_SIZE)\n let offset = 0\n let remaining = FRAME_HEADER_SIZE\n for (let i = 0; i < bufferList.length && remaining > 0; i++) {\n const chunk = bufferList[i]!\n const toCopy = Math.min(chunk.length, remaining)\n headerBytes.set(chunk.subarray(0, toCopy), offset)\n offset += toCopy\n remaining -= toCopy\n }\n\n const type = headerBytes[0]!\n const streamId =\n ((headerBytes[1]! << 24) |\n (headerBytes[2]! << 16) |\n (headerBytes[3]! << 8) |\n headerBytes[4]!) >>>\n 0\n const length =\n ((headerBytes[5]! << 24) |\n (headerBytes[6]! << 16) |\n (headerBytes[7]! << 8) |\n headerBytes[8]!) >>>\n 0\n\n return { type, streamId, length }\n }\n\n /**\n * Flattens buffer list into single Uint8Array and removes from list.\n */\n function extractFlattened(count: number): Uint8Array {\n if (count === 0) return EMPTY_BUFFER\n\n const result = new Uint8Array(count)\n let offset = 0\n let remaining = count\n\n while (remaining > 0 && bufferList.length > 0) {\n const chunk = bufferList[0]\n if (!chunk) break\n const toCopy = Math.min(chunk.length, remaining)\n result.set(chunk.subarray(0, toCopy), offset)\n\n offset += toCopy\n remaining -= toCopy\n\n if (toCopy === chunk.length) {\n bufferList.shift()\n } else {\n bufferList[0] = chunk.subarray(toCopy)\n }\n }\n\n totalLength -= count\n return result\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const { done, value } = await reader.read()\n if (cancelled) break\n if (done) break\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!value) continue\n\n // Append incoming chunk to buffer list\n if (totalLength + value.length > MAX_BUFFERED_BYTES) {\n throw new Error(\n `Framed response buffer exceeded ${MAX_BUFFERED_BYTES} bytes`,\n )\n }\n bufferList.push(value)\n totalLength += value.length\n\n // Parse complete frames from buffer\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const header = readHeader()\n if (!header) break // Not enough bytes for header\n\n const { type, streamId, length } = header\n\n if (\n type !== FrameType.JSON &&\n type !== FrameType.CHUNK &&\n type !== FrameType.END &&\n type !== FrameType.ERROR\n ) {\n throw new Error(`Unknown frame type: ${type}`)\n }\n\n // Enforce stream id conventions: JSON uses streamId 0, raw streams use non-zero ids\n if (type === FrameType.JSON) {\n if (streamId !== 0) {\n throw new Error('Invalid JSON frame streamId (expected 0)')\n }\n } else {\n if (streamId === 0) {\n throw new Error('Invalid raw frame streamId (expected non-zero)')\n }\n }\n\n if (length > MAX_FRAME_PAYLOAD_SIZE) {\n throw new Error(\n `Frame payload too large: ${length} bytes (max ${MAX_FRAME_PAYLOAD_SIZE})`,\n )\n }\n\n const frameSize = FRAME_HEADER_SIZE + length\n if (totalLength < frameSize) break // Wait for more data\n\n if (++frameCount > MAX_FRAMES) {\n throw new Error(\n `Too many frames in framed response (max ${MAX_FRAMES})`,\n )\n }\n\n // Extract and consume header bytes\n extractFlattened(FRAME_HEADER_SIZE)\n\n // Extract payload\n const payload = extractFlattened(length)\n\n // Process frame by type\n switch (type) {\n case FrameType.JSON: {\n try {\n jsonController.enqueue(textDecoder.decode(payload))\n } catch {\n // JSON stream may be cancelled/closed\n }\n break\n }\n\n case FrameType.CHUNK: {\n const ctrl = ensureController(streamId)\n if (ctrl) {\n ctrl.enqueue(payload)\n }\n break\n }\n\n case FrameType.END: {\n const ctrl = ensureController(streamId)\n cancelledStreamIds.add(streamId)\n if (ctrl) {\n try {\n ctrl.close()\n } catch {\n // Already closed\n }\n streamControllers.delete(streamId)\n }\n break\n }\n\n case FrameType.ERROR: {\n const ctrl = ensureController(streamId)\n cancelledStreamIds.add(streamId)\n if (ctrl) {\n const message = textDecoder.decode(payload)\n ctrl.error(new Error(message))\n streamControllers.delete(streamId)\n }\n break\n }\n }\n }\n }\n\n if (totalLength !== 0) {\n throw new Error('Incomplete frame at end of framed response')\n }\n\n // Close JSON stream when done\n try {\n jsonController.close()\n } catch {\n // JSON stream may be cancelled/closed\n }\n\n // Close any remaining streams (shouldn't happen in normal operation)\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.close()\n } catch {\n // Already closed\n }\n })\n streamControllers.clear()\n } catch (error) {\n // Error reading - propagate to all streams\n try {\n jsonController.error(error)\n } catch {\n // Already errored/closed\n }\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.error(error)\n } catch {\n // Already errored/closed\n }\n })\n streamControllers.clear()\n } finally {\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n inputReader = null\n }\n })()\n\n return { getOrCreateStream, jsonChunks }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"frame-decoder.js","names":[],"sources":["../../../src/client-rpc/frame-decoder.ts"],"sourcesContent":["/**\n * Client-side frame decoder for multiplexed responses.\n *\n * Decodes binary frame protocol and reconstructs:\n * - JSON stream (NDJSON lines for seroval)\n * - Raw streams (binary data as ReadableStream<Uint8Array>)\n */\n\nimport { FRAME_HEADER_SIZE, FrameType } from '../constants'\n\n/** Cached TextDecoder for frame decoding */\nconst textDecoder = new TextDecoder()\n\n/** Shared empty buffer for empty buffer case - avoids allocation */\nconst EMPTY_BUFFER = new Uint8Array(0)\n\n/** Hardening limits to prevent memory/CPU DoS */\nconst MAX_FRAME_PAYLOAD_SIZE = 16 * 1024 * 1024 // 16MiB\nconst MAX_BUFFERED_BYTES = 32 * 1024 * 1024 // 32MiB\nconst MAX_STREAMS = 1024\nconst MAX_FRAMES = 100_000 // Limit total frames to prevent CPU DoS\n\n/**\n * Result of frame decoding.\n */\nexport interface FrameDecoderResult {\n /** Gets or creates a raw stream by ID (for use by deserialize plugin) */\n getOrCreateStream: (id: number) => ReadableStream<Uint8Array>\n /** Stream of JSON strings (NDJSON lines) */\n jsonChunks: ReadableStream<string>\n}\n\n/**\n * Creates a frame decoder that processes a multiplexed response stream.\n *\n * @param input The raw response body stream\n * @returns Decoded JSON stream and stream getter function\n */\nexport function createFrameDecoder(\n input: ReadableStream<Uint8Array>,\n): FrameDecoderResult {\n const streamControllers = new Map<\n number,\n ReadableStreamDefaultController<Uint8Array>\n >()\n const streams = new Map<number, ReadableStream<Uint8Array>>()\n const cancelledStreamIds = new Set<number>()\n\n let cancelled = false as boolean\n let inputReader: ReadableStreamReader<Uint8Array> | null = null\n let frameCount = 0\n\n let jsonController!: ReadableStreamDefaultController<string>\n const jsonChunks = new ReadableStream<string>({\n start(controller) {\n jsonController = controller\n },\n cancel() {\n cancelled = true\n try {\n inputReader?.cancel()\n } catch {\n // Ignore\n }\n\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.error(new Error('Framed response cancelled'))\n } catch {\n // Ignore\n }\n })\n streamControllers.clear()\n streams.clear()\n cancelledStreamIds.clear()\n },\n })\n\n /**\n * Gets or creates a stream for a given stream ID.\n * Called by deserialize plugin when it encounters a RawStream reference.\n */\n function getOrCreateStream(id: number): ReadableStream<Uint8Array> {\n const existing = streams.get(id)\n if (existing) {\n return existing\n }\n\n // If we already received an END/ERROR for this streamId, returning a fresh stream\n // would hang consumers. Return an already-closed stream instead.\n if (cancelledStreamIds.has(id)) {\n return new ReadableStream<Uint8Array>({\n start(controller) {\n controller.close()\n },\n })\n }\n\n if (streams.size >= MAX_STREAMS) {\n throw new Error(\n `Too many raw streams in framed response (max ${MAX_STREAMS})`,\n )\n }\n\n const stream = new ReadableStream<Uint8Array>({\n start(ctrl) {\n streamControllers.set(id, ctrl)\n },\n cancel() {\n cancelledStreamIds.add(id)\n streamControllers.delete(id)\n streams.delete(id)\n },\n })\n streams.set(id, stream)\n return stream\n }\n\n /**\n * Ensures stream exists and returns its controller for enqueuing data.\n * Used for CHUNK frames where we need to ensure stream is created.\n */\n function ensureController(\n id: number,\n ): ReadableStreamDefaultController<Uint8Array> | undefined {\n getOrCreateStream(id)\n return streamControllers.get(id)\n }\n\n // Process frames asynchronously\n ;(async () => {\n const reader = input.getReader()\n inputReader = reader\n\n const bufferList: Array<Uint8Array> = []\n let totalLength = 0\n\n /**\n * Reads header bytes from buffer chunks without flattening.\n * Returns header data or null if not enough bytes available.\n */\n function readHeader(): {\n type: number\n streamId: number\n length: number\n } | null {\n if (totalLength < FRAME_HEADER_SIZE) return null\n\n const first = bufferList[0]!\n\n // Fast path: header fits entirely in first chunk (common case)\n if (first.length >= FRAME_HEADER_SIZE) {\n const type = first[0]!\n const streamId =\n ((first[1]! << 24) |\n (first[2]! << 16) |\n (first[3]! << 8) |\n first[4]!) >>>\n 0\n const length =\n ((first[5]! << 24) |\n (first[6]! << 16) |\n (first[7]! << 8) |\n first[8]!) >>>\n 0\n return { type, streamId, length }\n }\n\n // Slow path: header spans multiple chunks - flatten header bytes only\n const headerBytes = new Uint8Array(FRAME_HEADER_SIZE)\n let offset = 0\n let remaining = FRAME_HEADER_SIZE\n for (let i = 0; i < bufferList.length && remaining > 0; i++) {\n const chunk = bufferList[i]!\n const toCopy = Math.min(chunk.length, remaining)\n headerBytes.set(chunk.subarray(0, toCopy), offset)\n offset += toCopy\n remaining -= toCopy\n }\n\n const type = headerBytes[0]!\n const streamId =\n ((headerBytes[1]! << 24) |\n (headerBytes[2]! << 16) |\n (headerBytes[3]! << 8) |\n headerBytes[4]!) >>>\n 0\n const length =\n ((headerBytes[5]! << 24) |\n (headerBytes[6]! << 16) |\n (headerBytes[7]! << 8) |\n headerBytes[8]!) >>>\n 0\n\n return { type, streamId, length }\n }\n\n /**\n * Flattens buffer list into single Uint8Array and removes from list.\n */\n function extractFlattened(count: number): Uint8Array {\n if (count === 0) return EMPTY_BUFFER\n\n const result = new Uint8Array(count)\n let offset = 0\n let remaining = count\n\n while (remaining > 0 && bufferList.length > 0) {\n const chunk = bufferList[0]\n if (!chunk) break\n const toCopy = Math.min(chunk.length, remaining)\n result.set(chunk.subarray(0, toCopy), offset)\n\n offset += toCopy\n remaining -= toCopy\n\n if (toCopy === chunk.length) {\n bufferList.shift()\n } else {\n bufferList[0] = chunk.subarray(toCopy)\n }\n }\n\n totalLength -= count\n return result\n }\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const { done, value } = await reader.read()\n if (cancelled) break\n if (done) break\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!value) continue\n\n // Append incoming chunk to buffer list\n if (totalLength + value.length > MAX_BUFFERED_BYTES) {\n throw new Error(\n `Framed response buffer exceeded ${MAX_BUFFERED_BYTES} bytes`,\n )\n }\n bufferList.push(value)\n totalLength += value.length\n\n // Parse complete frames from buffer\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const header = readHeader()\n if (!header) break // Not enough bytes for header\n\n const { type, streamId, length } = header\n\n if (\n type !== FrameType.JSON &&\n type !== FrameType.CHUNK &&\n type !== FrameType.END &&\n type !== FrameType.ERROR\n ) {\n throw new Error(`Unknown frame type: ${type}`)\n }\n\n // Enforce stream id conventions: JSON uses streamId 0, raw streams use non-zero ids\n if (type === FrameType.JSON) {\n if (streamId !== 0) {\n throw new Error('Invalid JSON frame streamId (expected 0)')\n }\n } else {\n if (streamId === 0) {\n throw new Error('Invalid raw frame streamId (expected non-zero)')\n }\n }\n\n if (length > MAX_FRAME_PAYLOAD_SIZE) {\n throw new Error(\n `Frame payload too large: ${length} bytes (max ${MAX_FRAME_PAYLOAD_SIZE})`,\n )\n }\n\n const frameSize = FRAME_HEADER_SIZE + length\n if (totalLength < frameSize) break // Wait for more data\n\n if (++frameCount > MAX_FRAMES) {\n throw new Error(\n `Too many frames in framed response (max ${MAX_FRAMES})`,\n )\n }\n\n // Extract and consume header bytes\n extractFlattened(FRAME_HEADER_SIZE)\n\n // Extract payload\n const payload = extractFlattened(length)\n\n // Process frame by type\n switch (type) {\n case FrameType.JSON: {\n try {\n jsonController.enqueue(textDecoder.decode(payload))\n } catch {\n // JSON stream may be cancelled/closed\n }\n break\n }\n\n case FrameType.CHUNK: {\n const ctrl = ensureController(streamId)\n if (ctrl) {\n ctrl.enqueue(payload)\n }\n break\n }\n\n case FrameType.END: {\n const ctrl = ensureController(streamId)\n cancelledStreamIds.add(streamId)\n if (ctrl) {\n try {\n ctrl.close()\n } catch {\n // Already closed\n }\n streamControllers.delete(streamId)\n }\n break\n }\n\n case FrameType.ERROR: {\n const ctrl = ensureController(streamId)\n cancelledStreamIds.add(streamId)\n if (ctrl) {\n const message = textDecoder.decode(payload)\n ctrl.error(new Error(message))\n streamControllers.delete(streamId)\n }\n break\n }\n }\n }\n }\n\n if (totalLength !== 0) {\n throw new Error('Incomplete frame at end of framed response')\n }\n\n // Close JSON stream when done\n try {\n jsonController.close()\n } catch {\n // JSON stream may be cancelled/closed\n }\n\n // Close any remaining streams (shouldn't happen in normal operation)\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.close()\n } catch {\n // Already closed\n }\n })\n streamControllers.clear()\n } catch (error) {\n // Error reading - propagate to all streams\n try {\n jsonController.error(error)\n } catch {\n // Already errored/closed\n }\n streamControllers.forEach((ctrl) => {\n try {\n ctrl.error(error)\n } catch {\n // Already errored/closed\n }\n })\n streamControllers.clear()\n } finally {\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n inputReader = null\n }\n })()\n\n return { getOrCreateStream, jsonChunks }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"serverFnFetcher.js","names":[],"sources":["../../../src/client-rpc/serverFnFetcher.ts"],"sourcesContent":["import {\n createRawStreamDeserializePlugin,\n encode,\n invariant,\n isNotFound,\n parseRedirect,\n} from '@tanstack/router-core'\nimport { fromCrossJSON, toJSONAsync } from 'seroval'\nimport { getDefaultSerovalPlugins } from '../getDefaultSerovalPlugins'\nimport {\n TSS_CONTENT_TYPE_FRAMED,\n TSS_FORMDATA_CONTEXT,\n X_TSS_RAW_RESPONSE,\n X_TSS_SERIALIZED,\n validateFramedProtocolVersion,\n} from '../constants'\nimport { createFrameDecoder } from './frame-decoder'\nimport type { FunctionMiddlewareClientFnOptions } from '../createMiddleware'\nimport type { Plugin as SerovalPlugin } from 'seroval'\n\nlet serovalPlugins: Array<SerovalPlugin<any, any>> | null = null\n\n/**\n * Current async post-processing context for deserialization.\n *\n * Some deserializers need to perform async work after synchronous deserialization\n * (e.g., decoding RSC payloads, fetching remote data). This context allows them\n * to register promises that must complete before the deserialized value is used.\n *\n * This uses a synchronous execution context pattern:\n * - Each call to `fromCrossJSON` is synchronous\n * - Within that synchronous execution, all `fromSerializable` calls happen\n * - We set the context before `fromCrossJSON`, clear it after\n * - For streaming chunks, we set/clear context around each `onMessage` call\n *\n * Even with concurrent server function calls, each individual deserialization\n * is atomic (synchronous), so promises are correctly scoped to their call.\n */\nlet currentPostProcessContext: Array<Promise<unknown>> | null = null\n\n/**\n * Set the current post-processing context for async deserialization work.\n * Called before deserialization starts.\n *\n * @param ctx - Array to collect async work promises, or null to clear\n */\nexport function setPostProcessContext(\n ctx: Array<Promise<unknown>> | null,\n): void {\n currentPostProcessContext = ctx\n}\n\n/**\n * Get the current post-processing context.\n * Returns null if no deserialization is in progress.\n */\nexport function getPostProcessContext(): Array<Promise<unknown>> | null {\n return currentPostProcessContext\n}\n\n/**\n * Track an async post-processing promise in the current deserialization context.\n * Called by deserializers that need to perform async work after sync deserialization.\n *\n * If no context is active (e.g., on server), this is a no-op.\n *\n * @param promise - The async work promise to track\n */\nexport function trackPostProcessPromise(promise: Promise<unknown>): void {\n if (currentPostProcessContext) {\n currentPostProcessContext.push(promise)\n }\n}\n\n/**\n * Helper to await all post-processing promises.\n * Uses Promise.allSettled to ensure all promises complete even if some reject.\n */\nasync function awaitPostProcessPromises(\n promises: Array<Promise<unknown>>,\n): Promise<void> {\n if (promises.length > 0) {\n await Promise.allSettled(promises)\n }\n}\n\n/**\n * Checks if an object has at least one own enumerable property.\n * More efficient than Object.keys(obj).length > 0 as it short-circuits on first property.\n */\nconst hop = Object.prototype.hasOwnProperty\nfunction hasOwnProperties(obj: object): boolean {\n for (const _ in obj) {\n if (hop.call(obj, _)) {\n return true\n }\n }\n return false\n}\n// caller =>\n// serverFnFetcher =>\n// client =>\n// server =>\n// fn =>\n// seroval =>\n// client middleware =>\n// serverFnFetcher =>\n// caller\n\nexport async function serverFnFetcher(\n url: string,\n args: Array<any>,\n handler: (url: string, requestInit: RequestInit) => Promise<Response>,\n) {\n if (!serovalPlugins) {\n serovalPlugins = getDefaultSerovalPlugins()\n }\n const _first = args[0]\n\n const first = _first as FunctionMiddlewareClientFnOptions<any, any, any> & {\n headers?: HeadersInit\n }\n\n // Use custom fetch if provided, otherwise fall back to the passed handler (global fetch)\n const fetchImpl = first.fetch ?? handler\n\n const type = first.data instanceof FormData ? 'formData' : 'payload'\n\n // Arrange the headers\n const headers = first.headers ? new Headers(first.headers) : new Headers()\n headers.set('x-tsr-serverFn', 'true')\n\n if (type === 'payload') {\n headers.set(\n 'accept',\n `${TSS_CONTENT_TYPE_FRAMED}, application/x-ndjson, application/json`,\n )\n }\n\n // If the method is GET, we need to move the payload to the query string\n if (first.method === 'GET') {\n if (type === 'formData') {\n throw new Error('FormData is not supported with GET requests')\n }\n const serializedPayload = await serializePayload(first)\n if (serializedPayload !== undefined) {\n const encodedPayload = encode({\n payload: serializedPayload,\n })\n if (url.includes('?')) {\n url += `&${encodedPayload}`\n } else {\n url += `?${encodedPayload}`\n }\n }\n }\n\n let body = undefined\n if (first.method === 'POST') {\n const fetchBody = await getFetchBody(first)\n if (fetchBody?.contentType) {\n headers.set('content-type', fetchBody.contentType)\n }\n body = fetchBody?.body\n }\n\n return await getResponse(async () =>\n fetchImpl(url, {\n method: first.method,\n headers,\n signal: first.signal,\n body,\n }),\n )\n}\n\nasync function serializePayload(\n opts: FunctionMiddlewareClientFnOptions<any, any, any>,\n): Promise<string | undefined> {\n let payloadAvailable = false\n const payloadToSerialize: any = {}\n if (opts.data !== undefined) {\n payloadAvailable = true\n payloadToSerialize['data'] = opts.data\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (opts.context && hasOwnProperties(opts.context)) {\n payloadAvailable = true\n payloadToSerialize['context'] = opts.context\n }\n\n if (payloadAvailable) {\n return serialize(payloadToSerialize)\n }\n return undefined\n}\n\nasync function serialize(data: any) {\n return JSON.stringify(\n await Promise.resolve(toJSONAsync(data, { plugins: serovalPlugins! })),\n )\n}\n\nasync function getFetchBody(\n opts: FunctionMiddlewareClientFnOptions<any, any, any>,\n): Promise<{ body: FormData | string; contentType?: string } | undefined> {\n if (opts.data instanceof FormData) {\n let serializedContext = undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (opts.context && hasOwnProperties(opts.context)) {\n serializedContext = await serialize(opts.context)\n }\n if (serializedContext !== undefined) {\n opts.data.set(TSS_FORMDATA_CONTEXT, serializedContext)\n }\n return { body: opts.data }\n }\n const serializedBody = await serializePayload(opts)\n if (serializedBody) {\n return { body: serializedBody, contentType: 'application/json' }\n }\n return undefined\n}\n\n/**\n * Retrieves a response from a given function and manages potential errors\n * and special response types including redirects and not found errors.\n *\n * @param fn - The function to execute for obtaining the response.\n * @returns The processed response from the function.\n * @throws If the response is invalid or an error occurs during processing.\n */\nasync function getResponse(fn: () => Promise<Response>) {\n let response: Response\n try {\n response = await fn() // client => server => fn => server => client\n } catch (error) {\n if (error instanceof Response) {\n response = error\n } else {\n console.log(error)\n throw error\n }\n }\n\n if (response.headers.get(X_TSS_RAW_RESPONSE) === 'true') {\n return response\n }\n\n const contentType = response.headers.get('content-type')\n if (!contentType) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n 'Invariant failed: expected content-type header to be set',\n )\n }\n\n invariant()\n }\n const serializedByStart = !!response.headers.get(X_TSS_SERIALIZED)\n\n // If the response is serialized by the start server, we need to process it\n // differently than a normal response.\n if (serializedByStart) {\n let result\n\n // If it's a framed response (contains RawStream), use frame decoder\n if (contentType.includes(TSS_CONTENT_TYPE_FRAMED)) {\n // Validate protocol version compatibility\n validateFramedProtocolVersion(contentType)\n\n if (!response.body) {\n throw new Error('No response body for framed response')\n }\n\n const { getOrCreateStream, jsonChunks } = createFrameDecoder(\n response.body,\n )\n\n // Create deserialize plugin that wires up the raw streams\n const rawStreamPlugin =\n createRawStreamDeserializePlugin(getOrCreateStream)\n const plugins = [rawStreamPlugin, ...(serovalPlugins || [])]\n\n const refs = new Map()\n result = await processFramedResponse({\n jsonStream: jsonChunks,\n onMessage: (msg: any) => fromCrossJSON(msg, { refs, plugins }),\n onError(msg, error) {\n console.error(msg, error)\n },\n })\n }\n // If it's a JSON response, it can be simpler\n else if (contentType.includes('application/json')) {\n const jsonPayload = await response.json()\n // Track async post-processing work for this deserialization\n const postProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(postProcessPromises)\n try {\n result = fromCrossJSON(jsonPayload, { plugins: serovalPlugins! })\n } finally {\n setPostProcessContext(null)\n }\n // Await any async post-processing before returning\n await awaitPostProcessPromises(postProcessPromises)\n }\n\n if (!result) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: expected result to be resolved')\n }\n\n invariant()\n }\n if (result instanceof Error) {\n throw result\n }\n\n return result\n }\n\n // If it wasn't processed by the start serializer, check\n // if it's JSON\n if (contentType.includes('application/json')) {\n const jsonPayload = await response.json()\n const redirect = parseRedirect(jsonPayload)\n if (redirect) {\n throw redirect\n }\n if (isNotFound(jsonPayload)) {\n throw jsonPayload\n }\n return jsonPayload\n }\n\n // Otherwise, if it's not OK, throw the content\n if (!response.ok) {\n throw new Error(await response.text())\n }\n\n // Or return the response itself\n return response\n}\n\n/**\n * Processes a framed response where each JSON chunk is a complete JSON string\n * (already decoded by frame decoder).\n *\n * Uses per-chunk post-processing context to ensure async deserialization work\n * completes before the next chunk is processed. This prevents issues when\n * streaming values require async post-processing (e.g., RSC decoding).\n */\nasync function processFramedResponse({\n jsonStream,\n onMessage,\n onError,\n}: {\n jsonStream: ReadableStream<string>\n onMessage: (msg: any) => any\n onError?: (msg: string, error?: any) => void\n}) {\n const reader = jsonStream.getReader()\n\n // Read first JSON frame - this is the main result\n const { value: firstValue, done: firstDone } = await reader.read()\n if (firstDone || !firstValue) {\n throw new Error('Stream ended before first object')\n }\n\n // Each frame is a complete JSON string\n const firstObject = JSON.parse(firstValue)\n\n // Process remaining frames for streaming refs like RawStream.\n // Keep draining until the server closes the stream.\n // Each chunk gets its own post-processing context to properly scope async work.\n let drainCancelled = false as boolean\n const drain = (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n if (value) {\n try {\n // Set up post-processing context for this chunk\n const chunkPostProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(chunkPostProcessPromises)\n try {\n onMessage(JSON.parse(value))\n } finally {\n setPostProcessContext(null)\n }\n // Await any async post-processing from this chunk before processing next.\n // This ensures values requiring async work are ready before their\n // containing Promise/Stream resolves/emits to consumers.\n await awaitPostProcessPromises(chunkPostProcessPromises)\n } catch (e) {\n onError?.(`Invalid JSON: ${value}`, e)\n }\n }\n }\n } catch (err) {\n if (!drainCancelled) {\n onError?.('Stream processing error:', err)\n }\n }\n })()\n\n // Process first object with its own post-processing context\n let result: any\n const initialPostProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(initialPostProcessPromises)\n try {\n result = onMessage(firstObject)\n } catch (err) {\n setPostProcessContext(null)\n drainCancelled = true\n reader.cancel().catch(() => {})\n throw err\n }\n setPostProcessContext(null)\n\n // Await initial post-processing promises before returning result\n await awaitPostProcessPromises(initialPostProcessPromises)\n\n // If the initial decode fails async, stop draining to avoid holding\n // onto the response body and raw stream buffers unnecessarily.\n Promise.resolve(result).catch(() => {\n drainCancelled = true\n reader.cancel().catch(() => {})\n })\n\n // Detach reader once draining completes.\n drain.finally(() => {\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n })\n\n return result\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"serverFnFetcher.js","names":[],"sources":["../../../src/client-rpc/serverFnFetcher.ts"],"sourcesContent":["import {\n createRawStreamDeserializePlugin,\n encode,\n invariant,\n isNotFound,\n parseRedirect,\n} from '@tanstack/router-core'\nimport { fromCrossJSON, toJSONAsync } from 'seroval'\nimport { getDefaultSerovalPlugins } from '../getDefaultSerovalPlugins'\nimport {\n TSS_CONTENT_TYPE_FRAMED,\n TSS_FORMDATA_CONTEXT,\n X_TSS_RAW_RESPONSE,\n X_TSS_SERIALIZED,\n validateFramedProtocolVersion,\n} from '../constants'\nimport { createFrameDecoder } from './frame-decoder'\nimport type { FunctionMiddlewareClientFnOptions } from '../createMiddleware'\nimport type { Plugin as SerovalPlugin } from 'seroval'\n\nlet serovalPlugins: Array<SerovalPlugin<any, any>> | null = null\n\n/**\n * Current async post-processing context for deserialization.\n *\n * Some deserializers need to perform async work after synchronous deserialization\n * (e.g., decoding RSC payloads, fetching remote data). This context allows them\n * to register promises that must complete before the deserialized value is used.\n *\n * This uses a synchronous execution context pattern:\n * - Each call to `fromCrossJSON` is synchronous\n * - Within that synchronous execution, all `fromSerializable` calls happen\n * - We set the context before `fromCrossJSON`, clear it after\n * - For streaming chunks, we set/clear context around each `onMessage` call\n *\n * Even with concurrent server function calls, each individual deserialization\n * is atomic (synchronous), so promises are correctly scoped to their call.\n */\nlet currentPostProcessContext: Array<Promise<unknown>> | null = null\n\n/**\n * Set the current post-processing context for async deserialization work.\n * Called before deserialization starts.\n *\n * @param ctx - Array to collect async work promises, or null to clear\n */\nexport function setPostProcessContext(\n ctx: Array<Promise<unknown>> | null,\n): void {\n currentPostProcessContext = ctx\n}\n\n/**\n * Get the current post-processing context.\n * Returns null if no deserialization is in progress.\n */\nexport function getPostProcessContext(): Array<Promise<unknown>> | null {\n return currentPostProcessContext\n}\n\n/**\n * Track an async post-processing promise in the current deserialization context.\n * Called by deserializers that need to perform async work after sync deserialization.\n *\n * If no context is active (e.g., on server), this is a no-op.\n *\n * @param promise - The async work promise to track\n */\nexport function trackPostProcessPromise(promise: Promise<unknown>): void {\n if (currentPostProcessContext) {\n currentPostProcessContext.push(promise)\n }\n}\n\n/**\n * Helper to await all post-processing promises.\n * Uses Promise.allSettled to ensure all promises complete even if some reject.\n */\nasync function awaitPostProcessPromises(\n promises: Array<Promise<unknown>>,\n): Promise<void> {\n if (promises.length > 0) {\n await Promise.allSettled(promises)\n }\n}\n\n/**\n * Checks if an object has at least one own enumerable property.\n * More efficient than Object.keys(obj).length > 0 as it short-circuits on first property.\n */\nconst hop = Object.prototype.hasOwnProperty\nfunction hasOwnProperties(obj: object): boolean {\n for (const _ in obj) {\n if (hop.call(obj, _)) {\n return true\n }\n }\n return false\n}\n// caller =>\n// serverFnFetcher =>\n// client =>\n// server =>\n// fn =>\n// seroval =>\n// client middleware =>\n// serverFnFetcher =>\n// caller\n\nexport async function serverFnFetcher(\n url: string,\n args: Array<any>,\n handler: (url: string, requestInit: RequestInit) => Promise<Response>,\n) {\n if (!serovalPlugins) {\n serovalPlugins = getDefaultSerovalPlugins()\n }\n const _first = args[0]\n\n const first = _first as FunctionMiddlewareClientFnOptions<any, any, any> & {\n headers?: HeadersInit\n }\n\n // Use custom fetch if provided, otherwise fall back to the passed handler (global fetch)\n const fetchImpl = first.fetch ?? handler\n\n const type = first.data instanceof FormData ? 'formData' : 'payload'\n\n // Arrange the headers\n const headers = first.headers ? new Headers(first.headers) : new Headers()\n headers.set('x-tsr-serverFn', 'true')\n\n if (type === 'payload') {\n headers.set(\n 'accept',\n `${TSS_CONTENT_TYPE_FRAMED}, application/x-ndjson, application/json`,\n )\n }\n\n // If the method is GET, we need to move the payload to the query string\n if (first.method === 'GET') {\n if (type === 'formData') {\n throw new Error('FormData is not supported with GET requests')\n }\n const serializedPayload = await serializePayload(first)\n if (serializedPayload !== undefined) {\n const encodedPayload = encode({\n payload: serializedPayload,\n })\n if (url.includes('?')) {\n url += `&${encodedPayload}`\n } else {\n url += `?${encodedPayload}`\n }\n }\n }\n\n let body = undefined\n if (first.method === 'POST') {\n const fetchBody = await getFetchBody(first)\n if (fetchBody?.contentType) {\n headers.set('content-type', fetchBody.contentType)\n }\n body = fetchBody?.body\n }\n\n return await getResponse(async () =>\n fetchImpl(url, {\n method: first.method,\n headers,\n signal: first.signal,\n body,\n }),\n )\n}\n\nasync function serializePayload(\n opts: FunctionMiddlewareClientFnOptions<any, any, any>,\n): Promise<string | undefined> {\n let payloadAvailable = false\n const payloadToSerialize: any = {}\n if (opts.data !== undefined) {\n payloadAvailable = true\n payloadToSerialize['data'] = opts.data\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (opts.context && hasOwnProperties(opts.context)) {\n payloadAvailable = true\n payloadToSerialize['context'] = opts.context\n }\n\n if (payloadAvailable) {\n return serialize(payloadToSerialize)\n }\n return undefined\n}\n\nasync function serialize(data: any) {\n return JSON.stringify(\n await Promise.resolve(toJSONAsync(data, { plugins: serovalPlugins! })),\n )\n}\n\nasync function getFetchBody(\n opts: FunctionMiddlewareClientFnOptions<any, any, any>,\n): Promise<{ body: FormData | string; contentType?: string } | undefined> {\n if (opts.data instanceof FormData) {\n let serializedContext = undefined\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (opts.context && hasOwnProperties(opts.context)) {\n serializedContext = await serialize(opts.context)\n }\n if (serializedContext !== undefined) {\n opts.data.set(TSS_FORMDATA_CONTEXT, serializedContext)\n }\n return { body: opts.data }\n }\n const serializedBody = await serializePayload(opts)\n if (serializedBody) {\n return { body: serializedBody, contentType: 'application/json' }\n }\n return undefined\n}\n\n/**\n * Retrieves a response from a given function and manages potential errors\n * and special response types including redirects and not found errors.\n *\n * @param fn - The function to execute for obtaining the response.\n * @returns The processed response from the function.\n * @throws If the response is invalid or an error occurs during processing.\n */\nasync function getResponse(fn: () => Promise<Response>) {\n let response: Response\n try {\n response = await fn() // client => server => fn => server => client\n } catch (error) {\n if (error instanceof Response) {\n response = error\n } else {\n console.log(error)\n throw error\n }\n }\n\n if (response.headers.get(X_TSS_RAW_RESPONSE) === 'true') {\n return response\n }\n\n const contentType = response.headers.get('content-type')\n if (!contentType) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n 'Invariant failed: expected content-type header to be set',\n )\n }\n\n invariant()\n }\n const serializedByStart = !!response.headers.get(X_TSS_SERIALIZED)\n\n // If the response is serialized by the start server, we need to process it\n // differently than a normal response.\n if (serializedByStart) {\n let result\n\n // If it's a framed response (contains RawStream), use frame decoder\n if (contentType.includes(TSS_CONTENT_TYPE_FRAMED)) {\n // Validate protocol version compatibility\n validateFramedProtocolVersion(contentType)\n\n if (!response.body) {\n throw new Error('No response body for framed response')\n }\n\n const { getOrCreateStream, jsonChunks } = createFrameDecoder(\n response.body,\n )\n\n // Create deserialize plugin that wires up the raw streams\n const rawStreamPlugin =\n createRawStreamDeserializePlugin(getOrCreateStream)\n const plugins = [rawStreamPlugin, ...(serovalPlugins || [])]\n\n const refs = new Map()\n result = await processFramedResponse({\n jsonStream: jsonChunks,\n onMessage: (msg: any) => fromCrossJSON(msg, { refs, plugins }),\n onError(msg, error) {\n console.error(msg, error)\n },\n })\n }\n // If it's a JSON response, it can be simpler\n else if (contentType.includes('application/json')) {\n const jsonPayload = await response.json()\n // Track async post-processing work for this deserialization\n const postProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(postProcessPromises)\n try {\n result = fromCrossJSON(jsonPayload, { plugins: serovalPlugins! })\n } finally {\n setPostProcessContext(null)\n }\n // Await any async post-processing before returning\n await awaitPostProcessPromises(postProcessPromises)\n }\n\n if (!result) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error('Invariant failed: expected result to be resolved')\n }\n\n invariant()\n }\n if (result instanceof Error) {\n throw result\n }\n\n return result\n }\n\n // If it wasn't processed by the start serializer, check\n // if it's JSON\n if (contentType.includes('application/json')) {\n const jsonPayload = await response.json()\n const redirect = parseRedirect(jsonPayload)\n if (redirect) {\n throw redirect\n }\n if (isNotFound(jsonPayload)) {\n throw jsonPayload\n }\n return jsonPayload\n }\n\n // Otherwise, if it's not OK, throw the content\n if (!response.ok) {\n throw new Error(await response.text())\n }\n\n // Or return the response itself\n return response\n}\n\n/**\n * Processes a framed response where each JSON chunk is a complete JSON string\n * (already decoded by frame decoder).\n *\n * Uses per-chunk post-processing context to ensure async deserialization work\n * completes before the next chunk is processed. This prevents issues when\n * streaming values require async post-processing (e.g., RSC decoding).\n */\nasync function processFramedResponse({\n jsonStream,\n onMessage,\n onError,\n}: {\n jsonStream: ReadableStream<string>\n onMessage: (msg: any) => any\n onError?: (msg: string, error?: any) => void\n}) {\n const reader = jsonStream.getReader()\n\n // Read first JSON frame - this is the main result\n const { value: firstValue, done: firstDone } = await reader.read()\n if (firstDone || !firstValue) {\n throw new Error('Stream ended before first object')\n }\n\n // Each frame is a complete JSON string\n const firstObject = JSON.parse(firstValue)\n\n // Process remaining frames for streaming refs like RawStream.\n // Keep draining until the server closes the stream.\n // Each chunk gets its own post-processing context to properly scope async work.\n let drainCancelled = false as boolean\n const drain = (async () => {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n while (true) {\n const { value, done } = await reader.read()\n if (done) break\n if (value) {\n try {\n // Set up post-processing context for this chunk\n const chunkPostProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(chunkPostProcessPromises)\n try {\n onMessage(JSON.parse(value))\n } finally {\n setPostProcessContext(null)\n }\n // Await any async post-processing from this chunk before processing next.\n // This ensures values requiring async work are ready before their\n // containing Promise/Stream resolves/emits to consumers.\n await awaitPostProcessPromises(chunkPostProcessPromises)\n } catch (e) {\n onError?.(`Invalid JSON: ${value}`, e)\n }\n }\n }\n } catch (err) {\n if (!drainCancelled) {\n onError?.('Stream processing error:', err)\n }\n }\n })()\n\n // Process first object with its own post-processing context\n let result: any\n const initialPostProcessPromises: Array<Promise<unknown>> = []\n setPostProcessContext(initialPostProcessPromises)\n try {\n result = onMessage(firstObject)\n } catch (err) {\n setPostProcessContext(null)\n drainCancelled = true\n reader.cancel().catch(() => {})\n throw err\n }\n setPostProcessContext(null)\n\n // Await initial post-processing promises before returning result\n await awaitPostProcessPromises(initialPostProcessPromises)\n\n // If the initial decode fails async, stop draining to avoid holding\n // onto the response body and raw stream buffers unnecessarily.\n Promise.resolve(result).catch(() => {\n drainCancelled = true\n reader.cancel().catch(() => {})\n })\n\n // Detach reader once draining completes.\n drain.finally(() => {\n try {\n reader.releaseLock()\n } catch {\n // Ignore\n }\n })\n\n return result\n}\n"],"mappings":"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"}
@@ -11,9 +11,13 @@ var TSS_CONTENT_TYPE_FRAMED = "application/x-tss-framed";
11
11
  * Frame types for binary multiplexing protocol.
12
12
  */
13
13
  var FrameType = {
14
+ /** Seroval JSON chunk (NDJSON line) */
14
15
  JSON: 0,
16
+ /** Raw stream data chunk */
15
17
  CHUNK: 1,
18
+ /** Raw stream end (EOF) */
16
19
  END: 2,
20
+ /** Raw stream error */
17
21
  ERROR: 3
18
22
  };
19
23
  /** Header size in bytes: type(1) + streamId(4) + length(4) */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../../src/constants.ts"],"sourcesContent":["export const TSS_FORMDATA_CONTEXT = '__TSS_CONTEXT'\nexport const TSS_SERVER_FUNCTION = Symbol.for('TSS_SERVER_FUNCTION')\nexport const TSS_SERVER_FUNCTION_FACTORY = Symbol.for(\n 'TSS_SERVER_FUNCTION_FACTORY',\n)\n\nexport const X_TSS_SERIALIZED = 'x-tss-serialized'\nexport const X_TSS_RAW_RESPONSE = 'x-tss-raw'\nexport const X_TSS_CONTEXT = 'x-tss-context'\n\n/** Content-Type for multiplexed framed responses (RawStream support) */\nexport const TSS_CONTENT_TYPE_FRAMED = 'application/x-tss-framed'\n\n/**\n * Frame types for binary multiplexing protocol.\n */\nexport const FrameType = {\n /** Seroval JSON chunk (NDJSON line) */\n JSON: 0,\n /** Raw stream data chunk */\n CHUNK: 1,\n /** Raw stream end (EOF) */\n END: 2,\n /** Raw stream error */\n ERROR: 3,\n} as const\n\nexport type FrameType = (typeof FrameType)[keyof typeof FrameType]\n\n/** Header size in bytes: type(1) + streamId(4) + length(4) */\nexport const FRAME_HEADER_SIZE = 9\n\n/** Current protocol version for framed responses */\nexport const TSS_FRAMED_PROTOCOL_VERSION = 1\n\n/** Full Content-Type header value with version parameter */\nexport const TSS_CONTENT_TYPE_FRAMED_VERSIONED = `${TSS_CONTENT_TYPE_FRAMED}; v=${TSS_FRAMED_PROTOCOL_VERSION}`\n\n/**\n * Parses the version parameter from a framed Content-Type header.\n * Returns undefined if no version parameter is present.\n */\nconst FRAMED_VERSION_REGEX = /;\\s*v=(\\d+)/\nexport function parseFramedProtocolVersion(\n contentType: string,\n): number | undefined {\n // Match \"v=<number>\" in the content-type parameters\n const match = contentType.match(FRAMED_VERSION_REGEX)\n return match ? parseInt(match[1]!, 10) : undefined\n}\n\n/**\n * Validates that the server's protocol version is compatible with this client.\n * Throws an error if versions are incompatible.\n */\nexport function validateFramedProtocolVersion(contentType: string): void {\n const serverVersion = parseFramedProtocolVersion(contentType)\n if (serverVersion === undefined) {\n // No version specified - assume compatible (backwards compat)\n return\n }\n if (serverVersion !== TSS_FRAMED_PROTOCOL_VERSION) {\n throw new Error(\n `Incompatible framed protocol version: server=${serverVersion}, client=${TSS_FRAMED_PROTOCOL_VERSION}. ` +\n `Please ensure client and server are using compatible versions.`,\n )\n }\n}\n\n/**\n * Minimal metadata about a server function, available to client middleware.\n * Only contains the function ID since name/filename may expose server internals.\n */\nexport interface ClientFnMeta {\n /** The unique identifier for this server function */\n id: string\n}\n\n/**\n * Full metadata about a server function, available to server middleware and server functions.\n * This information is embedded at compile time by the TanStack Start compiler.\n */\nexport interface ServerFnMeta extends ClientFnMeta {\n /** The original variable name of the server function (e.g., \"myServerFn\") */\n name: string\n /** The source file path relative to the project root (e.g., \"src/routes/api.ts\") */\n filename: string\n}\n\nexport {}\n"],"mappings":";AAAA,IAAa,uBAAuB;AACpC,IAAa,sBAAsB,OAAO,IAAI,sBAAsB;AACpE,IAAa,8BAA8B,OAAO,IAChD,8BACD;AAED,IAAa,mBAAmB;AAChC,IAAa,qBAAqB;AAClC,IAAa,gBAAgB;;AAG7B,IAAa,0BAA0B;;;;AAKvC,IAAa,YAAY;CAEvB,MAAM;CAEN,OAAO;CAEP,KAAK;CAEL,OAAO;CACR;;AAKD,IAAa,oBAAoB;;AAGjC,IAAa,8BAA8B;;AAG3C,IAAa,oCAAoC,GAAG,wBAAwB;;;;;AAM5E,IAAM,uBAAuB;AAC7B,SAAgB,2BACd,aACoB;CAEpB,MAAM,QAAQ,YAAY,MAAM,qBAAqB;AACrD,QAAO,QAAQ,SAAS,MAAM,IAAK,GAAG,GAAG,KAAA;;;;;;AAO3C,SAAgB,8BAA8B,aAA2B;CACvE,MAAM,gBAAgB,2BAA2B,YAAY;AAC7D,KAAI,kBAAkB,KAAA,EAEpB;AAEF,KAAI,kBAAA,EACF,OAAM,IAAI,MACR,gDAAgD,cAAc,4EAE/D"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../src/constants.ts"],"sourcesContent":["export const TSS_FORMDATA_CONTEXT = '__TSS_CONTEXT'\nexport const TSS_SERVER_FUNCTION = Symbol.for('TSS_SERVER_FUNCTION')\nexport const TSS_SERVER_FUNCTION_FACTORY = Symbol.for(\n 'TSS_SERVER_FUNCTION_FACTORY',\n)\n\nexport const X_TSS_SERIALIZED = 'x-tss-serialized'\nexport const X_TSS_RAW_RESPONSE = 'x-tss-raw'\nexport const X_TSS_CONTEXT = 'x-tss-context'\n\n/** Content-Type for multiplexed framed responses (RawStream support) */\nexport const TSS_CONTENT_TYPE_FRAMED = 'application/x-tss-framed'\n\n/**\n * Frame types for binary multiplexing protocol.\n */\nexport const FrameType = {\n /** Seroval JSON chunk (NDJSON line) */\n JSON: 0,\n /** Raw stream data chunk */\n CHUNK: 1,\n /** Raw stream end (EOF) */\n END: 2,\n /** Raw stream error */\n ERROR: 3,\n} as const\n\nexport type FrameType = (typeof FrameType)[keyof typeof FrameType]\n\n/** Header size in bytes: type(1) + streamId(4) + length(4) */\nexport const FRAME_HEADER_SIZE = 9\n\n/** Current protocol version for framed responses */\nexport const TSS_FRAMED_PROTOCOL_VERSION = 1\n\n/** Full Content-Type header value with version parameter */\nexport const TSS_CONTENT_TYPE_FRAMED_VERSIONED = `${TSS_CONTENT_TYPE_FRAMED}; v=${TSS_FRAMED_PROTOCOL_VERSION}`\n\n/**\n * Parses the version parameter from a framed Content-Type header.\n * Returns undefined if no version parameter is present.\n */\nconst FRAMED_VERSION_REGEX = /;\\s*v=(\\d+)/\nexport function parseFramedProtocolVersion(\n contentType: string,\n): number | undefined {\n // Match \"v=<number>\" in the content-type parameters\n const match = contentType.match(FRAMED_VERSION_REGEX)\n return match ? parseInt(match[1]!, 10) : undefined\n}\n\n/**\n * Validates that the server's protocol version is compatible with this client.\n * Throws an error if versions are incompatible.\n */\nexport function validateFramedProtocolVersion(contentType: string): void {\n const serverVersion = parseFramedProtocolVersion(contentType)\n if (serverVersion === undefined) {\n // No version specified - assume compatible (backwards compat)\n return\n }\n if (serverVersion !== TSS_FRAMED_PROTOCOL_VERSION) {\n throw new Error(\n `Incompatible framed protocol version: server=${serverVersion}, client=${TSS_FRAMED_PROTOCOL_VERSION}. ` +\n `Please ensure client and server are using compatible versions.`,\n )\n }\n}\n\n/**\n * Minimal metadata about a server function, available to client middleware.\n * Only contains the function ID since name/filename may expose server internals.\n */\nexport interface ClientFnMeta {\n /** The unique identifier for this server function */\n id: string\n}\n\n/**\n * Full metadata about a server function, available to server middleware and server functions.\n * This information is embedded at compile time by the TanStack Start compiler.\n */\nexport interface ServerFnMeta extends ClientFnMeta {\n /** The original variable name of the server function (e.g., \"myServerFn\") */\n name: string\n /** The source file path relative to the project root (e.g., \"src/routes/api.ts\") */\n filename: string\n}\n\nexport {}\n"],"mappings":";AAAA,IAAa,uBAAuB;AACpC,IAAa,sBAAsB,OAAO,IAAI,qBAAqB;AACnE,IAAa,8BAA8B,OAAO,IAChD,6BACF;AAEA,IAAa,mBAAmB;AAChC,IAAa,qBAAqB;AAClC,IAAa,gBAAgB;;AAG7B,IAAa,0BAA0B;;;;AAKvC,IAAa,YAAY;;CAEvB,MAAM;;CAEN,OAAO;;CAEP,KAAK;;CAEL,OAAO;AACT;;AAKA,IAAa,oBAAoB;;AAGjC,IAAa,8BAA8B;;AAG3C,IAAa,oCAAoC,GAAG,wBAAwB;;;;;AAM5E,IAAM,uBAAuB;AAC7B,SAAgB,2BACd,aACoB;CAEpB,MAAM,QAAQ,YAAY,MAAM,oBAAoB;CACpD,OAAO,QAAQ,SAAS,MAAM,IAAK,EAAE,IAAI,KAAA;AAC3C;;;;;AAMA,SAAgB,8BAA8B,aAA2B;CACvE,MAAM,gBAAgB,2BAA2B,WAAW;CAC5D,IAAI,kBAAkB,KAAA,GAEpB;CAEF,IAAI,kBAAA,GACF,MAAM,IAAI,MACR,gDAAgD,cAAc,2EAEhE;AAEJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"createCsrfMiddleware.js","names":[],"sources":["../../src/createCsrfMiddleware.ts"],"sourcesContent":["import { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport { createMiddleware } from './createMiddleware'\nimport type {\n RequestMiddlewareAfterServer,\n RequestServerOptions,\n} from './createMiddleware'\nimport type { Register } from '@tanstack/router-core'\n\nexport const csrfSymbol = Symbol.for('tanstack-start:csrf-middleware')\n\nexport type CsrfSecFetchSite =\n | 'same-origin'\n | 'same-site'\n | 'cross-site'\n | 'none'\n\nexport type CsrfMatcher<TValue, TRegister = Register, TMiddlewares = unknown> =\n | TValue\n | Array<TValue>\n | ((\n value: TValue | (string & {}),\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>)\n\nexport interface CsrfMiddlewareOptions<\n TRegister = Register,\n TMiddlewares = unknown,\n> {\n /**\n * Return `true` to validate this request, or `false` to skip validation.\n *\n * @default undefined, which validates every request handled by this middleware.\n */\n filter?: (\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>\n /**\n * Allowed Origin values. Defaults to the trusted request origin.\n */\n origin?: CsrfMatcher<string, TRegister, TMiddlewares>\n /**\n * Allowed Sec-Fetch-Site values.\n *\n * @default 'same-origin'\n */\n secFetchSite?: CsrfMatcher<CsrfSecFetchSite, TRegister, TMiddlewares>\n /**\n * Whether to use Referer as a fallback when Sec-Fetch-Site and Origin are absent.\n *\n * @default true\n */\n referer?:\n | boolean\n | ((\n referer: string,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>)\n /**\n * Allow requests when Sec-Fetch-Site, Origin, and Referer are all missing.\n *\n * @default false\n */\n allowRequestsWithoutOriginCheck?: boolean\n /**\n * Optional response returned when CSRF validation fails.\n *\n * @default new Response('Forbidden', { status: 403 })\n */\n failureResponse?:\n | Response\n | ((\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => Response | Promise<Response>)\n}\n\ntype CreateCsrfMiddleware = <TRegister, TMiddlewares>(\n opts?: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n) => RequestMiddlewareAfterServer<{}, undefined, undefined>\n\nconst innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => {\n const middleware = createMiddleware().server(async (ctx) => {\n const csrfCtx = ctx as RequestServerOptions<any, any>\n\n if (opts.filter && !(await opts.filter(csrfCtx))) {\n return ctx.next()\n }\n\n if (await isCsrfRequestAllowed(opts, csrfCtx)) {\n return ctx.next()\n }\n\n return getFailureResponse(opts, csrfCtx)\n })\n\n if (process.env.NODE_ENV !== 'production') {\n Object.defineProperty(middleware, csrfSymbol, { value: true })\n }\n\n return middleware\n}\n\nexport const createCsrfMiddleware: CreateCsrfMiddleware =\n createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware\n\nexport async function isCsrfRequestAllowed<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean> {\n const result = await getCsrfRequestValidationResult(opts, ctx)\n return (\n result === true ||\n (result === undefined && opts.allowRequestsWithoutOriginCheck === true)\n )\n}\n\nexport async function getCsrfRequestValidationResult<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean | undefined> {\n const fetchSite = ctx.request.headers.get('Sec-Fetch-Site')\n if (fetchSite !== null) {\n return matchValue(opts.secFetchSite ?? 'same-origin', fetchSite, ctx)\n }\n\n const origin = ctx.request.headers.get('Origin')\n if (origin !== null) {\n if (opts.origin) {\n return matchValue(opts.origin, origin, ctx)\n }\n\n return origin === new URL(ctx.request.url).origin\n }\n\n const referer = ctx.request.headers.get('Referer')\n if (referer === null || opts.referer === false) {\n return undefined\n }\n\n if (typeof opts.referer === 'function') {\n return opts.referer(referer, ctx)\n }\n\n if (opts.origin) {\n const refererOrigin = getOriginFromUrl(referer)\n return (\n refererOrigin !== undefined && matchValue(opts.origin, refererOrigin, ctx)\n )\n }\n\n return isRefererSameOrigin(referer, new URL(ctx.request.url).origin)\n}\n\nasync function matchValue<TValue extends string, TRegister, TMiddlewares>(\n matcher: CsrfMatcher<TValue, TRegister, TMiddlewares>,\n value: string,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean> {\n if (typeof matcher === 'function') {\n return matcher(value, ctx)\n }\n\n if (Array.isArray(matcher)) {\n // typescript is dumb for array.includes()\n return matcher.includes(value as TValue)\n }\n\n return value === matcher\n}\n\nfunction getOriginFromUrl(url: string): string | undefined {\n try {\n return new URL(url).origin\n } catch {\n return undefined\n }\n}\n\nfunction isRefererSameOrigin(referer: string, requestOrigin: string): boolean {\n if (referer === requestOrigin) return true\n if (!referer.startsWith(requestOrigin)) return false\n if (referer.length === requestOrigin.length) return true\n const code = referer.charCodeAt(requestOrigin.length)\n return code === 47 /* '/' */ || code === 63 /* '?' */ || code === 35 /* '#' */\n}\n\nasync function getFailureResponse<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<Response> {\n if (typeof opts.failureResponse === 'function') {\n return opts.failureResponse(ctx)\n }\n\n return (\n opts.failureResponse?.clone() ?? new Response('Forbidden', { status: 403 })\n )\n}\n"],"mappings":";;;AAQA,IAAa,aAAa,OAAO,IAAI,iCAAiC;AAuEtE,IAAM,6BAAmD,OAAO,EAAE,KAAK;CACrE,MAAM,aAAa,kBAAkB,CAAC,OAAO,OAAO,QAAQ;EAC1D,MAAM,UAAU;AAEhB,MAAI,KAAK,UAAU,CAAE,MAAM,KAAK,OAAO,QAAQ,CAC7C,QAAO,IAAI,MAAM;AAGnB,MAAI,MAAM,qBAAqB,MAAM,QAAQ,CAC3C,QAAO,IAAI,MAAM;AAGnB,SAAO,mBAAmB,MAAM,QAAQ;GACxC;AAEF,KAAA,QAAA,IAAA,aAA6B,aAC3B,QAAO,eAAe,YAAY,YAAY,EAAE,OAAO,MAAM,CAAC;AAGhE,QAAO;;AAGT,IAAa,uBACX,oBAAoB,CAAC,OAAO,0BAA0B;AAExD,eAAsB,qBACpB,MACA,KACkB;CAClB,MAAM,SAAS,MAAM,+BAA+B,MAAM,IAAI;AAC9D,QACE,WAAW,QACV,WAAW,KAAA,KAAa,KAAK,oCAAoC;;AAItE,eAAsB,+BACpB,MACA,KAC8B;CAC9B,MAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,KAAI,cAAc,KAChB,QAAO,WAAW,KAAK,gBAAgB,eAAe,WAAW,IAAI;CAGvE,MAAM,SAAS,IAAI,QAAQ,QAAQ,IAAI,SAAS;AAChD,KAAI,WAAW,MAAM;AACnB,MAAI,KAAK,OACP,QAAO,WAAW,KAAK,QAAQ,QAAQ,IAAI;AAG7C,SAAO,WAAW,IAAI,IAAI,IAAI,QAAQ,IAAI,CAAC;;CAG7C,MAAM,UAAU,IAAI,QAAQ,QAAQ,IAAI,UAAU;AAClD,KAAI,YAAY,QAAQ,KAAK,YAAY,MACvC;AAGF,KAAI,OAAO,KAAK,YAAY,WAC1B,QAAO,KAAK,QAAQ,SAAS,IAAI;AAGnC,KAAI,KAAK,QAAQ;EACf,MAAM,gBAAgB,iBAAiB,QAAQ;AAC/C,SACE,kBAAkB,KAAA,KAAa,WAAW,KAAK,QAAQ,eAAe,IAAI;;AAI9E,QAAO,oBAAoB,SAAS,IAAI,IAAI,IAAI,QAAQ,IAAI,CAAC,OAAO;;AAGtE,eAAe,WACb,SACA,OACA,KACkB;AAClB,KAAI,OAAO,YAAY,WACrB,QAAO,QAAQ,OAAO,IAAI;AAG5B,KAAI,MAAM,QAAQ,QAAQ,CAExB,QAAO,QAAQ,SAAS,MAAgB;AAG1C,QAAO,UAAU;;AAGnB,SAAS,iBAAiB,KAAiC;AACzD,KAAI;AACF,SAAO,IAAI,IAAI,IAAI,CAAC;SACd;AACN;;;AAIJ,SAAS,oBAAoB,SAAiB,eAAgC;AAC5E,KAAI,YAAY,cAAe,QAAO;AACtC,KAAI,CAAC,QAAQ,WAAW,cAAc,CAAE,QAAO;AAC/C,KAAI,QAAQ,WAAW,cAAc,OAAQ,QAAO;CACpD,MAAM,OAAO,QAAQ,WAAW,cAAc,OAAO;AACrD,QAAO,SAAS,MAAgB,SAAS,MAAgB,SAAS;;AAGpE,eAAe,mBACb,MACA,KACmB;AACnB,KAAI,OAAO,KAAK,oBAAoB,WAClC,QAAO,KAAK,gBAAgB,IAAI;AAGlC,QACE,KAAK,iBAAiB,OAAO,IAAI,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC"}
1
+ {"version":3,"file":"createCsrfMiddleware.js","names":[],"sources":["../../src/createCsrfMiddleware.ts"],"sourcesContent":["import { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport { createMiddleware } from './createMiddleware'\nimport type {\n RequestMiddlewareAfterServer,\n RequestServerOptions,\n} from './createMiddleware'\nimport type { Register } from '@tanstack/router-core'\n\nexport const csrfSymbol = Symbol.for('tanstack-start:csrf-middleware')\n\nexport type CsrfSecFetchSite =\n | 'same-origin'\n | 'same-site'\n | 'cross-site'\n | 'none'\n\nexport type CsrfMatcher<TValue, TRegister = Register, TMiddlewares = unknown> =\n | TValue\n | Array<TValue>\n | ((\n value: TValue | (string & {}),\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>)\n\nexport interface CsrfMiddlewareOptions<\n TRegister = Register,\n TMiddlewares = unknown,\n> {\n /**\n * Return `true` to validate this request, or `false` to skip validation.\n *\n * @default undefined, which validates every request handled by this middleware.\n */\n filter?: (\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>\n /**\n * Allowed Origin values. Defaults to the trusted request origin.\n */\n origin?: CsrfMatcher<string, TRegister, TMiddlewares>\n /**\n * Allowed Sec-Fetch-Site values.\n *\n * @default 'same-origin'\n */\n secFetchSite?: CsrfMatcher<CsrfSecFetchSite, TRegister, TMiddlewares>\n /**\n * Whether to use Referer as a fallback when Sec-Fetch-Site and Origin are absent.\n *\n * @default true\n */\n referer?:\n | boolean\n | ((\n referer: string,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => boolean | Promise<boolean>)\n /**\n * Allow requests when Sec-Fetch-Site, Origin, and Referer are all missing.\n *\n * @default false\n */\n allowRequestsWithoutOriginCheck?: boolean\n /**\n * Optional response returned when CSRF validation fails.\n *\n * @default new Response('Forbidden', { status: 403 })\n */\n failureResponse?:\n | Response\n | ((\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n ) => Response | Promise<Response>)\n}\n\ntype CreateCsrfMiddleware = <TRegister, TMiddlewares>(\n opts?: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n) => RequestMiddlewareAfterServer<{}, undefined, undefined>\n\nconst innerCreateCsrfMiddleware: CreateCsrfMiddleware = (opts = {}) => {\n const middleware = createMiddleware().server(async (ctx) => {\n const csrfCtx = ctx as RequestServerOptions<any, any>\n\n if (opts.filter && !(await opts.filter(csrfCtx))) {\n return ctx.next()\n }\n\n if (await isCsrfRequestAllowed(opts, csrfCtx)) {\n return ctx.next()\n }\n\n return getFailureResponse(opts, csrfCtx)\n })\n\n if (process.env.NODE_ENV !== 'production') {\n Object.defineProperty(middleware, csrfSymbol, { value: true })\n }\n\n return middleware\n}\n\nexport const createCsrfMiddleware: CreateCsrfMiddleware =\n createIsomorphicFn().server(innerCreateCsrfMiddleware) as CreateCsrfMiddleware\n\nexport async function isCsrfRequestAllowed<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean> {\n const result = await getCsrfRequestValidationResult(opts, ctx)\n return (\n result === true ||\n (result === undefined && opts.allowRequestsWithoutOriginCheck === true)\n )\n}\n\nexport async function getCsrfRequestValidationResult<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean | undefined> {\n const fetchSite = ctx.request.headers.get('Sec-Fetch-Site')\n if (fetchSite !== null) {\n return matchValue(opts.secFetchSite ?? 'same-origin', fetchSite, ctx)\n }\n\n const origin = ctx.request.headers.get('Origin')\n if (origin !== null) {\n if (opts.origin) {\n return matchValue(opts.origin, origin, ctx)\n }\n\n return origin === new URL(ctx.request.url).origin\n }\n\n const referer = ctx.request.headers.get('Referer')\n if (referer === null || opts.referer === false) {\n return undefined\n }\n\n if (typeof opts.referer === 'function') {\n return opts.referer(referer, ctx)\n }\n\n if (opts.origin) {\n const refererOrigin = getOriginFromUrl(referer)\n return (\n refererOrigin !== undefined && matchValue(opts.origin, refererOrigin, ctx)\n )\n }\n\n return isRefererSameOrigin(referer, new URL(ctx.request.url).origin)\n}\n\nasync function matchValue<TValue extends string, TRegister, TMiddlewares>(\n matcher: CsrfMatcher<TValue, TRegister, TMiddlewares>,\n value: string,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<boolean> {\n if (typeof matcher === 'function') {\n return matcher(value, ctx)\n }\n\n if (Array.isArray(matcher)) {\n // typescript is dumb for array.includes()\n return matcher.includes(value as TValue)\n }\n\n return value === matcher\n}\n\nfunction getOriginFromUrl(url: string): string | undefined {\n try {\n return new URL(url).origin\n } catch {\n return undefined\n }\n}\n\nfunction isRefererSameOrigin(referer: string, requestOrigin: string): boolean {\n if (referer === requestOrigin) return true\n if (!referer.startsWith(requestOrigin)) return false\n if (referer.length === requestOrigin.length) return true\n const code = referer.charCodeAt(requestOrigin.length)\n return code === 47 /* '/' */ || code === 63 /* '?' */ || code === 35 /* '#' */\n}\n\nasync function getFailureResponse<TRegister, TMiddlewares>(\n opts: CsrfMiddlewareOptions<TRegister, TMiddlewares>,\n ctx: RequestServerOptions<TRegister, TMiddlewares>,\n): Promise<Response> {\n if (typeof opts.failureResponse === 'function') {\n return opts.failureResponse(ctx)\n }\n\n return (\n opts.failureResponse?.clone() ?? new Response('Forbidden', { status: 403 })\n )\n}\n"],"mappings":";;;AAQA,IAAa,aAAa,OAAO,IAAI,gCAAgC;AAuErE,IAAM,6BAAmD,OAAO,CAAC,MAAM;CACrE,MAAM,aAAa,iBAAiB,EAAE,OAAO,OAAO,QAAQ;EAC1D,MAAM,UAAU;EAEhB,IAAI,KAAK,UAAU,CAAE,MAAM,KAAK,OAAO,OAAO,GAC5C,OAAO,IAAI,KAAK;EAGlB,IAAI,MAAM,qBAAqB,MAAM,OAAO,GAC1C,OAAO,IAAI,KAAK;EAGlB,OAAO,mBAAmB,MAAM,OAAO;CACzC,CAAC;CAED,IAAA,QAAA,IAAA,aAA6B,cAC3B,OAAO,eAAe,YAAY,YAAY,EAAE,OAAO,KAAK,CAAC;CAG/D,OAAO;AACT;AAEA,IAAa,uBACX,mBAAmB,EAAE,OAAO,yBAAyB;AAEvD,eAAsB,qBACpB,MACA,KACkB;CAClB,MAAM,SAAS,MAAM,+BAA+B,MAAM,GAAG;CAC7D,OACE,WAAW,QACV,WAAW,KAAA,KAAa,KAAK,oCAAoC;AAEtE;AAEA,eAAsB,+BACpB,MACA,KAC8B;CAC9B,MAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI,gBAAgB;CAC1D,IAAI,cAAc,MAChB,OAAO,WAAW,KAAK,gBAAgB,eAAe,WAAW,GAAG;CAGtE,MAAM,SAAS,IAAI,QAAQ,QAAQ,IAAI,QAAQ;CAC/C,IAAI,WAAW,MAAM;EACnB,IAAI,KAAK,QACP,OAAO,WAAW,KAAK,QAAQ,QAAQ,GAAG;EAG5C,OAAO,WAAW,IAAI,IAAI,IAAI,QAAQ,GAAG,EAAE;CAC7C;CAEA,MAAM,UAAU,IAAI,QAAQ,QAAQ,IAAI,SAAS;CACjD,IAAI,YAAY,QAAQ,KAAK,YAAY,OACvC;CAGF,IAAI,OAAO,KAAK,YAAY,YAC1B,OAAO,KAAK,QAAQ,SAAS,GAAG;CAGlC,IAAI,KAAK,QAAQ;EACf,MAAM,gBAAgB,iBAAiB,OAAO;EAC9C,OACE,kBAAkB,KAAA,KAAa,WAAW,KAAK,QAAQ,eAAe,GAAG;CAE7E;CAEA,OAAO,oBAAoB,SAAS,IAAI,IAAI,IAAI,QAAQ,GAAG,EAAE,MAAM;AACrE;AAEA,eAAe,WACb,SACA,OACA,KACkB;CAClB,IAAI,OAAO,YAAY,YACrB,OAAO,QAAQ,OAAO,GAAG;CAG3B,IAAI,MAAM,QAAQ,OAAO,GAEvB,OAAO,QAAQ,SAAS,KAAe;CAGzC,OAAO,UAAU;AACnB;AAEA,SAAS,iBAAiB,KAAiC;CACzD,IAAI;EACF,OAAO,IAAI,IAAI,GAAG,EAAE;CACtB,QAAQ;EACN;CACF;AACF;AAEA,SAAS,oBAAoB,SAAiB,eAAgC;CAC5E,IAAI,YAAY,eAAe,OAAO;CACtC,IAAI,CAAC,QAAQ,WAAW,aAAa,GAAG,OAAO;CAC/C,IAAI,QAAQ,WAAW,cAAc,QAAQ,OAAO;CACpD,MAAM,OAAO,QAAQ,WAAW,cAAc,MAAM;CACpD,OAAO,SAAS,MAAgB,SAAS,MAAgB,SAAS;AACpE;AAEA,eAAe,mBACb,MACA,KACmB;CACnB,IAAI,OAAO,KAAK,oBAAoB,YAClC,OAAO,KAAK,gBAAgB,GAAG;CAGjC,OACE,KAAK,iBAAiB,MAAM,KAAK,IAAI,SAAS,aAAa,EAAE,QAAQ,IAAI,CAAC;AAE9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"createMiddleware.js","names":[],"sources":["../../src/createMiddleware.ts"],"sourcesContent":["import type { StartInstanceOptions } from './createStart'\nimport type {\n AnyServerFn,\n ConstrainValidator,\n CustomFetch,\n Method,\n} from './createServerFn'\nimport type { ClientFnMeta, ServerFnMeta } from './constants'\nimport type {\n AnyContext,\n Assign,\n Constrain,\n Expand,\n IntersectAssign,\n Register,\n ResolveValidatorInput,\n ResolveValidatorOutput,\n ValidateSerializableInput,\n} from '@tanstack/router-core'\n\nexport type CreateMiddlewareFn<TRegister> = <TType extends MiddlewareType>(\n options?: {\n type?: TType\n },\n __opts?: FunctionMiddlewareOptions<\n TRegister,\n unknown,\n undefined,\n undefined,\n undefined\n >,\n) => CreateMiddlewareResult<TRegister, TType>\n\nexport const createMiddleware: CreateMiddlewareFn<{}> = (options, __opts) => {\n const resolvedOptions = {\n type: 'request',\n ...(__opts || options),\n }\n\n return {\n options: resolvedOptions,\n middleware: (middleware: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { middleware }),\n ) as any\n },\n inputValidator: (inputValidator: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { inputValidator }),\n ) as any\n },\n client: (client: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { client }),\n ) as any\n },\n server: (server: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { server }),\n ) as any\n },\n } as any\n}\n\nexport type MiddlewareType = 'request' | 'function'\n\nexport type CreateMiddlewareResult<\n TRegister,\n TType extends MiddlewareType,\n> = 'request' extends TType\n ? RequestMiddleware<TRegister>\n : FunctionMiddleware<TRegister>\n\nexport interface FunctionMiddleware<\n TRegister,\n> extends FunctionMiddlewareAfterMiddleware<TRegister, unknown> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyRequestMiddleware | AnyFunctionMiddleware>\n >,\n ) => FunctionMiddlewareAfterMiddleware<TRegister, TNewMiddlewares>\n}\n\nexport interface FunctionMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareClient<TRegister, TMiddlewares, undefined>,\n FunctionMiddlewareValidator<TRegister, TMiddlewares> {}\n\nexport interface FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n> {\n '~types': FunctionMiddlewareTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n >\n options: FunctionMiddlewareOptions<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TClientContext\n >\n}\n\nexport interface FunctionMiddlewareTypes<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerContext,\n in out TServerSendContext,\n in out TClientContext,\n in out TClientSendContext,\n> {\n type: 'function'\n middlewares: TMiddlewares\n input: ResolveValidatorInput<TInputValidator>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n output: ResolveValidatorOutput<TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n clientContext: TClientContext\n allClientContextBeforeNext: AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext\n >\n allClientContextAfterNext: AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext,\n TClientSendContext\n >\n serverContext: TServerContext\n serverSendContext: TServerSendContext\n allServerSendContext: AssignAllServerSendContext<\n TMiddlewares,\n TServerSendContext\n >\n allServerContext: AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n clientSendContext: TClientSendContext\n allClientSendContext: AssignAllClientSendContext<\n TMiddlewares,\n TClientSendContext\n >\n inputValidator: TInputValidator\n}\n\n/**\n * Recursively resolve the input type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorInputs<TMiddlewares, TInputValidator> =\n unknown extends TInputValidator\n ? TInputValidator\n : TInputValidator extends undefined\n ? IntersectAllMiddleware<TMiddlewares, 'allInput'>\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allInput'>,\n ResolveValidatorInput<TInputValidator>\n >\n\nexport type IntersectAllMiddleware<\n TMiddlewares,\n TType extends\n | keyof AnyFunctionMiddleware['~types']\n | keyof AnyRequestMiddleware['~types']\n | keyof AnyServerFn['~types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest]\n ? TMiddleware extends\n | AnyFunctionMiddleware\n | AnyRequestMiddleware\n | AnyServerFn\n ? IntersectAllMiddleware<\n TRest,\n TType,\n IntersectAssign<\n TAcc,\n TMiddleware['~types'][TType & keyof TMiddleware['~types']]\n >\n >\n : TAcc\n : TAcc\n\nexport type AnyFunctionMiddleware = FunctionMiddlewareWithTypes<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * Recursively merge the output type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorOutputs<TMiddlewares, TInputValidator> =\n unknown extends TInputValidator\n ? TInputValidator\n : TInputValidator extends undefined\n ? IntersectAllMiddleware<TMiddlewares, 'allOutput'>\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allOutput'>,\n Awaited<ResolveValidatorOutput<TInputValidator>>\n >\n\n/**\n * Recursively resolve the client context type produced by a sequence of middleware\n */\nexport type AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext = undefined,\n> = unknown extends TClientContext\n ? TClientContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>,\n TClientContext\n >\n\nexport type AssignAllMiddleware<\n TMiddlewares,\n TType extends\n | keyof AnyFunctionMiddleware['~types']\n | keyof AnyRequestMiddleware['~types']\n | keyof AnyServerFn['~types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest]\n ? TMiddleware extends\n | AnyFunctionMiddleware\n | AnyRequestMiddleware\n | AnyServerFn\n ? AssignAllMiddleware<\n TRest,\n TType,\n Assign<TAcc, TMiddleware['~types'][TType & keyof TMiddleware['~types']]>\n >\n : TAcc\n : TAcc\n\nexport type AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext = undefined,\n TSendContext = undefined,\n> = unknown extends TClientContext\n ? Assign<TClientContext, TSendContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>,\n Assign<TClientContext, TSendContext>\n >\n\nexport type AssignAllServerSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>,\n TSendContext\n >\n\nexport type AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = Assign<\n // Fetch Request Context\n GlobalFetchRequestContext,\n Assign<\n GlobalServerRequestContext<TRegister>,\n __AssignAllServerRequestContext<TMiddlewares, TSendContext, TServerContext>\n >\n>\n\n// export type GlobalFetchRequestContext<TRegister> = AnyContext\nexport type GlobalFetchRequestContext = Register extends {\n server: { requestContext: infer TRequestContext }\n}\n ? TRequestContext\n : AnyContext\n\nexport type GlobalServerRequestContext<TRegister> = TRegister extends {\n config: StartInstanceOptions<any, any, infer TRequestMiddlewares, any>\n}\n ? AssignAllMiddleware<TRequestMiddlewares, 'allServerContext'>\n : AnyContext\n\ntype __AssignAllServerRequestContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = Assign<\n GlobalFetchRequestContext,\n Assign<\n GlobalServerRequestContext<TRegister>, // TODO: This enabled global middleware\n // type inference, but creates a circular types issue. No idea how to fix this.\n // AnyContext,\n Assign<\n GlobalServerFnContext<TRegister>, // TODO: This enabled global middleware\n // type inference, but creates a circular types issue. No idea how to fix this.\n // AnyContext,/\n __AssignAllServerFnContext<TMiddlewares, TSendContext, TServerContext>\n >\n >\n>\n\ntype GlobalServerFnContext<TRegister> = TRegister extends {\n config: StartInstanceOptions<any, any, any, infer TFunctionMiddlewares>\n}\n ? AssignAllMiddleware<TFunctionMiddlewares, 'allServerContext'>\n : AnyContext\n\ntype __AssignAllServerFnContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllClientSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>,\n TSendContext\n >\n\nexport interface FunctionMiddlewareOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerContext,\n in out TClientContext,\n> {\n middleware?: TMiddlewares\n inputValidator?: ConstrainValidator<TRegister, 'GET', TInputValidator>\n client?: FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TClientContext\n >\n server?: FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n unknown,\n unknown\n >\n}\n\nexport type FunctionMiddlewareClientNextFn<TRegister, TMiddlewares> = <\n TSendContext = undefined,\n TNewClientContext = undefined,\n>(ctx?: {\n context?: TNewClientContext\n sendContext?: ValidateSerializableInput<TRegister, TSendContext>\n headers?: HeadersInit\n fetch?: CustomFetch\n}) => Promise<\n FunctionClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>\n>\n\nexport interface FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext,\n> {\n server: <TNewServerContext = undefined, TSendContext = undefined>(\n server: FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >,\n ) => FunctionMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TNewServerContext,\n TServerSendContext,\n TClientContext,\n TSendContext\n >\n}\n\nexport type FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n> = (\n options: FunctionMiddlewareServerFnOptions<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext\n >,\n) => FunctionMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n>\n\nexport type FunctionMiddlewareServerNextFn<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n> = <TNewServerContext = undefined, TSendContext = undefined>(ctx?: {\n context?: TNewServerContext\n sendContext?: ValidateSerializableInput<TRegister, TSendContext>\n}) => Promise<\n FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >\n>\n\nexport type FunctionServerResultWithContext<\n in out TRegister,\n in out TMiddlewares,\n in out TServerSendContext,\n in out TServerContext,\n in out TSendContext,\n> = {\n 'use functions must return the result of next()': true\n '~types': {\n context: TServerContext\n sendContext: TSendContext\n }\n context: Expand<\n AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n >\n sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>\n}\n\nexport interface FunctionMiddlewareServerFnOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerSendContext,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n context: Expand<\n AssignAllServerFnContext<TRegister, TMiddlewares, TServerSendContext>\n >\n next: FunctionMiddlewareServerNextFn<\n TRegister,\n TMiddlewares,\n TServerSendContext\n >\n method: Method\n serverFnMeta: ServerFnMeta\n signal: AbortSignal\n}\n\nexport type FunctionMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext,\n> =\n | Promise<\n FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n >\n | FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n\nexport interface FunctionMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n> extends FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n> {}\n\nexport interface FunctionMiddlewareClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n> {\n client: <TSendServerContext = undefined, TNewClientContext = undefined>(\n client: FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendServerContext,\n TNewClientContext\n >,\n ) => FunctionMiddlewareAfterClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendServerContext,\n TNewClientContext\n >\n}\n\nexport type FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendContext,\n TClientContext,\n> = (\n options: FunctionMiddlewareClientFnOptions<\n TRegister,\n TMiddlewares,\n TInputValidator\n >,\n) => FunctionMiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext\n>\n\nexport interface FunctionMiddlewareClientFnOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n> {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>\n method: Method\n signal: AbortSignal\n serverFnMeta: ClientFnMeta\n next: FunctionMiddlewareClientNextFn<TRegister, TMiddlewares>\n filename: string\n fetch?: CustomFetch\n}\n\nexport type FunctionMiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext,\n> =\n | Promise<\n FunctionClientResultWithContext<\n TMiddlewares,\n TSendContext,\n TClientContext\n >\n >\n | FunctionClientResultWithContext<TMiddlewares, TSendContext, TClientContext>\n\nexport type FunctionClientResultWithContext<\n in out TMiddlewares,\n in out TSendContext,\n in out TClientContext,\n> = {\n 'use functions must return the result of next()': true\n context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>\n headers: HeadersInit\n fetch?: CustomFetch\n}\n\nexport interface FunctionMiddlewareAfterClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext,\n>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n TServerSendContext,\n TClientContext,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext\n > {}\n\nexport interface FunctionMiddlewareValidator<TRegister, TMiddlewares> {\n inputValidator: <TNewValidator>(\n inputValidator: ConstrainValidator<TRegister, 'GET', TNewValidator>,\n ) => FunctionMiddlewareAfterValidator<TRegister, TMiddlewares, TNewValidator>\n}\n\nexport interface FunctionMiddlewareAfterValidator<\n TRegister,\n TMiddlewares,\n TInputValidator,\n>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n undefined\n >,\n FunctionMiddlewareClient<TRegister, TMiddlewares, TInputValidator> {}\n\nexport interface RequestMiddleware<\n TRegister,\n> extends RequestMiddlewareAfterMiddleware<TRegister, undefined> {\n middleware: <const TMiddlewares = undefined>(\n middlewares: Constrain<TMiddlewares, ReadonlyArray<AnyRequestMiddleware>>,\n ) => RequestMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n}\n\nexport type AnyRequestMiddleware = RequestMiddlewareWithTypes<any, any, any>\n\nexport interface RequestMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TServerContext,\n> {\n '~types': RequestMiddlewareTypes<TRegister, TMiddlewares, TServerContext>\n options: RequestMiddlewareOptions<TRegister, TMiddlewares, TServerContext>\n}\n\nexport interface RequestMiddlewareOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TServerContext,\n> {\n middleware?: TMiddlewares\n server?: RequestServerFn<TRegister, TMiddlewares, TServerContext>\n}\nexport interface RequestMiddlewareTypes<\n TRegister,\n TMiddlewares,\n TServerContext,\n> {\n type: 'request'\n // this only exists so we can use request middlewares in server functions\n allInput: undefined\n // this only exists so we can use request middlewares in server functions\n allOutput: undefined\n middlewares: TMiddlewares\n serverContext: TServerContext\n allServerContext: AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n undefined,\n TServerContext\n >\n}\n\nexport interface RequestMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n extends\n RequestMiddlewareWithTypes<TRegister, TMiddlewares, undefined>,\n RequestMiddlewareServer<TRegister, TMiddlewares> {}\n\nexport interface RequestMiddlewareServer<TRegister, TMiddlewares> {\n server: <TServerContext = undefined>(\n fn: RequestServerFn<TRegister, TMiddlewares, TServerContext>,\n ) => RequestMiddlewareAfterServer<TRegister, TMiddlewares, TServerContext>\n}\n\nexport type RequestServerFn<TRegister, TMiddlewares, TServerContext> = (\n options: RequestServerOptions<TRegister, TMiddlewares>,\n) => RequestMiddlewareServerFnResult<TRegister, TMiddlewares, TServerContext>\n\nexport interface RequestServerOptions<TRegister, TMiddlewares> {\n request: Request\n pathname: string\n context: Expand<AssignAllServerRequestContext<TRegister, TMiddlewares>>\n next: RequestServerNextFn<TRegister, TMiddlewares>\n /**\n * Type of Start handler currently processing this request.\n */\n handlerType: 'serverFn' | 'router'\n /**\n * Metadata about the server function being invoked.\n * This is only present when the request is handling a server function call.\n * For regular page requests, this will be undefined.\n */\n serverFnMeta?: ServerFnMeta\n}\n\nexport type RequestServerNextFn<TRegister, TMiddlewares> = <\n TServerContext = undefined,\n>(\n options?: RequestServerNextFnOptions<TServerContext>,\n) => RequestServerNextFnResult<TRegister, TMiddlewares, TServerContext>\n\nexport interface RequestServerNextFnOptions<TServerContext> {\n context?: TServerContext\n}\n\nexport type RequestServerNextFnResult<TRegister, TMiddlewares, TServerContext> =\n | Promise<RequestServerResult<TRegister, TMiddlewares, TServerContext>>\n | RequestServerResult<TRegister, TMiddlewares, TServerContext>\n\nexport type RequestMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerContext,\n> =\n | Promise<\n RequestServerResult<TRegister, TMiddlewares, TServerContext> | Response\n >\n | RequestServerResult<TRegister, TMiddlewares, TServerContext>\n | Response\n\nexport interface RequestServerResult<TRegister, TMiddlewares, TServerContext> {\n request: Request\n pathname: string\n context: Expand<\n AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n undefined,\n TServerContext\n >\n >\n response: Response\n}\n\nexport interface RequestMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TServerContext,\n> extends RequestMiddlewareWithTypes<TRegister, TMiddlewares, TServerContext> {}\n"],"mappings":";AAiCA,IAAa,oBAA4C,SAAS,WAAW;CAC3E,MAAM,kBAAkB;EACtB,MAAM;EACN,GAAI,UAAU;EACf;AAED,QAAO;EACL,SAAS;EACT,aAAa,eAAoB;AAC/B,UAAO,iBACL,EAAE,EACF,OAAO,OAAO,iBAAiB,EAAE,YAAY,CAAC,CAC/C;;EAEH,iBAAiB,mBAAwB;AACvC,UAAO,iBACL,EAAE,EACF,OAAO,OAAO,iBAAiB,EAAE,gBAAgB,CAAC,CACnD;;EAEH,SAAS,WAAgB;AACvB,UAAO,iBACL,EAAE,EACF,OAAO,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CAC3C;;EAEH,SAAS,WAAgB;AACvB,UAAO,iBACL,EAAE,EACF,OAAO,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CAC3C;;EAEJ"}
1
+ {"version":3,"file":"createMiddleware.js","names":[],"sources":["../../src/createMiddleware.ts"],"sourcesContent":["import type { StartInstanceOptions } from './createStart'\nimport type {\n AnyServerFn,\n ConstrainValidator,\n CustomFetch,\n Method,\n} from './createServerFn'\nimport type { ClientFnMeta, ServerFnMeta } from './constants'\nimport type {\n AnyContext,\n Assign,\n Constrain,\n Expand,\n IntersectAssign,\n Register,\n ResolveValidatorInput,\n ResolveValidatorOutput,\n ValidateSerializableInput,\n} from '@tanstack/router-core'\n\nexport type CreateMiddlewareFn<TRegister> = <TType extends MiddlewareType>(\n options?: {\n type?: TType\n },\n __opts?: FunctionMiddlewareOptions<\n TRegister,\n unknown,\n undefined,\n undefined,\n undefined\n >,\n) => CreateMiddlewareResult<TRegister, TType>\n\nexport const createMiddleware: CreateMiddlewareFn<{}> = (options, __opts) => {\n const resolvedOptions = {\n type: 'request',\n ...(__opts || options),\n }\n\n return {\n options: resolvedOptions,\n middleware: (middleware: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { middleware }),\n ) as any\n },\n inputValidator: (inputValidator: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { inputValidator }),\n ) as any\n },\n client: (client: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { client }),\n ) as any\n },\n server: (server: any) => {\n return createMiddleware(\n {} as any,\n Object.assign(resolvedOptions, { server }),\n ) as any\n },\n } as any\n}\n\nexport type MiddlewareType = 'request' | 'function'\n\nexport type CreateMiddlewareResult<\n TRegister,\n TType extends MiddlewareType,\n> = 'request' extends TType\n ? RequestMiddleware<TRegister>\n : FunctionMiddleware<TRegister>\n\nexport interface FunctionMiddleware<\n TRegister,\n> extends FunctionMiddlewareAfterMiddleware<TRegister, unknown> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyRequestMiddleware | AnyFunctionMiddleware>\n >,\n ) => FunctionMiddlewareAfterMiddleware<TRegister, TNewMiddlewares>\n}\n\nexport interface FunctionMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareClient<TRegister, TMiddlewares, undefined>,\n FunctionMiddlewareValidator<TRegister, TMiddlewares> {}\n\nexport interface FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n> {\n '~types': FunctionMiddlewareTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n >\n options: FunctionMiddlewareOptions<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TClientContext\n >\n}\n\nexport interface FunctionMiddlewareTypes<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerContext,\n in out TServerSendContext,\n in out TClientContext,\n in out TClientSendContext,\n> {\n type: 'function'\n middlewares: TMiddlewares\n input: ResolveValidatorInput<TInputValidator>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n output: ResolveValidatorOutput<TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n clientContext: TClientContext\n allClientContextBeforeNext: AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext\n >\n allClientContextAfterNext: AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext,\n TClientSendContext\n >\n serverContext: TServerContext\n serverSendContext: TServerSendContext\n allServerSendContext: AssignAllServerSendContext<\n TMiddlewares,\n TServerSendContext\n >\n allServerContext: AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n clientSendContext: TClientSendContext\n allClientSendContext: AssignAllClientSendContext<\n TMiddlewares,\n TClientSendContext\n >\n inputValidator: TInputValidator\n}\n\n/**\n * Recursively resolve the input type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorInputs<TMiddlewares, TInputValidator> =\n unknown extends TInputValidator\n ? TInputValidator\n : TInputValidator extends undefined\n ? IntersectAllMiddleware<TMiddlewares, 'allInput'>\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allInput'>,\n ResolveValidatorInput<TInputValidator>\n >\n\nexport type IntersectAllMiddleware<\n TMiddlewares,\n TType extends\n | keyof AnyFunctionMiddleware['~types']\n | keyof AnyRequestMiddleware['~types']\n | keyof AnyServerFn['~types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest]\n ? TMiddleware extends\n | AnyFunctionMiddleware\n | AnyRequestMiddleware\n | AnyServerFn\n ? IntersectAllMiddleware<\n TRest,\n TType,\n IntersectAssign<\n TAcc,\n TMiddleware['~types'][TType & keyof TMiddleware['~types']]\n >\n >\n : TAcc\n : TAcc\n\nexport type AnyFunctionMiddleware = FunctionMiddlewareWithTypes<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * Recursively merge the output type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorOutputs<TMiddlewares, TInputValidator> =\n unknown extends TInputValidator\n ? TInputValidator\n : TInputValidator extends undefined\n ? IntersectAllMiddleware<TMiddlewares, 'allOutput'>\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allOutput'>,\n Awaited<ResolveValidatorOutput<TInputValidator>>\n >\n\n/**\n * Recursively resolve the client context type produced by a sequence of middleware\n */\nexport type AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext = undefined,\n> = unknown extends TClientContext\n ? TClientContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>,\n TClientContext\n >\n\nexport type AssignAllMiddleware<\n TMiddlewares,\n TType extends\n | keyof AnyFunctionMiddleware['~types']\n | keyof AnyRequestMiddleware['~types']\n | keyof AnyServerFn['~types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest]\n ? TMiddleware extends\n | AnyFunctionMiddleware\n | AnyRequestMiddleware\n | AnyServerFn\n ? AssignAllMiddleware<\n TRest,\n TType,\n Assign<TAcc, TMiddleware['~types'][TType & keyof TMiddleware['~types']]>\n >\n : TAcc\n : TAcc\n\nexport type AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext = undefined,\n TSendContext = undefined,\n> = unknown extends TClientContext\n ? Assign<TClientContext, TSendContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>,\n Assign<TClientContext, TSendContext>\n >\n\nexport type AssignAllServerSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>,\n TSendContext\n >\n\nexport type AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = Assign<\n // Fetch Request Context\n GlobalFetchRequestContext,\n Assign<\n GlobalServerRequestContext<TRegister>,\n __AssignAllServerRequestContext<TMiddlewares, TSendContext, TServerContext>\n >\n>\n\n// export type GlobalFetchRequestContext<TRegister> = AnyContext\nexport type GlobalFetchRequestContext = Register extends {\n server: { requestContext: infer TRequestContext }\n}\n ? TRequestContext\n : AnyContext\n\nexport type GlobalServerRequestContext<TRegister> = TRegister extends {\n config: StartInstanceOptions<any, any, infer TRequestMiddlewares, any>\n}\n ? AssignAllMiddleware<TRequestMiddlewares, 'allServerContext'>\n : AnyContext\n\ntype __AssignAllServerRequestContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = Assign<\n GlobalFetchRequestContext,\n Assign<\n GlobalServerRequestContext<TRegister>, // TODO: This enabled global middleware\n // type inference, but creates a circular types issue. No idea how to fix this.\n // AnyContext,\n Assign<\n GlobalServerFnContext<TRegister>, // TODO: This enabled global middleware\n // type inference, but creates a circular types issue. No idea how to fix this.\n // AnyContext,/\n __AssignAllServerFnContext<TMiddlewares, TSendContext, TServerContext>\n >\n >\n>\n\ntype GlobalServerFnContext<TRegister> = TRegister extends {\n config: StartInstanceOptions<any, any, any, infer TFunctionMiddlewares>\n}\n ? AssignAllMiddleware<TFunctionMiddlewares, 'allServerContext'>\n : AnyContext\n\ntype __AssignAllServerFnContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllClientSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>,\n TSendContext\n >\n\nexport interface FunctionMiddlewareOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerContext,\n in out TClientContext,\n> {\n middleware?: TMiddlewares\n inputValidator?: ConstrainValidator<TRegister, 'GET', TInputValidator>\n client?: FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TClientContext\n >\n server?: FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n unknown,\n unknown\n >\n}\n\nexport type FunctionMiddlewareClientNextFn<TRegister, TMiddlewares> = <\n TSendContext = undefined,\n TNewClientContext = undefined,\n>(ctx?: {\n context?: TNewClientContext\n sendContext?: ValidateSerializableInput<TRegister, TSendContext>\n headers?: HeadersInit\n fetch?: CustomFetch\n}) => Promise<\n FunctionClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>\n>\n\nexport interface FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext,\n> {\n server: <TNewServerContext = undefined, TSendContext = undefined>(\n server: FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >,\n ) => FunctionMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TNewServerContext,\n TServerSendContext,\n TClientContext,\n TSendContext\n >\n}\n\nexport type FunctionMiddlewareServerFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n> = (\n options: FunctionMiddlewareServerFnOptions<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext\n >,\n) => FunctionMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n>\n\nexport type FunctionMiddlewareServerNextFn<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n> = <TNewServerContext = undefined, TSendContext = undefined>(ctx?: {\n context?: TNewServerContext\n sendContext?: ValidateSerializableInput<TRegister, TSendContext>\n}) => Promise<\n FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >\n>\n\nexport type FunctionServerResultWithContext<\n in out TRegister,\n in out TMiddlewares,\n in out TServerSendContext,\n in out TServerContext,\n in out TSendContext,\n> = {\n 'use functions must return the result of next()': true\n '~types': {\n context: TServerContext\n sendContext: TSendContext\n }\n context: Expand<\n AssignAllServerFnContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n >\n sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>\n}\n\nexport interface FunctionMiddlewareServerFnOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n in out TServerSendContext,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n context: Expand<\n AssignAllServerFnContext<TRegister, TMiddlewares, TServerSendContext>\n >\n next: FunctionMiddlewareServerNextFn<\n TRegister,\n TMiddlewares,\n TServerSendContext\n >\n method: Method\n serverFnMeta: ServerFnMeta\n signal: AbortSignal\n}\n\nexport type FunctionMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext,\n> =\n | Promise<\n FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n >\n | FunctionServerResultWithContext<\n TRegister,\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n\nexport interface FunctionMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n> extends FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n> {}\n\nexport interface FunctionMiddlewareClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n> {\n client: <TSendServerContext = undefined, TNewClientContext = undefined>(\n client: FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendServerContext,\n TNewClientContext\n >,\n ) => FunctionMiddlewareAfterClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendServerContext,\n TNewClientContext\n >\n}\n\nexport type FunctionMiddlewareClientFn<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TSendContext,\n TClientContext,\n> = (\n options: FunctionMiddlewareClientFnOptions<\n TRegister,\n TMiddlewares,\n TInputValidator\n >,\n) => FunctionMiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext\n>\n\nexport interface FunctionMiddlewareClientFnOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TInputValidator,\n> {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>\n method: Method\n signal: AbortSignal\n serverFnMeta: ClientFnMeta\n next: FunctionMiddlewareClientNextFn<TRegister, TMiddlewares>\n filename: string\n fetch?: CustomFetch\n}\n\nexport type FunctionMiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext,\n> =\n | Promise<\n FunctionClientResultWithContext<\n TMiddlewares,\n TSendContext,\n TClientContext\n >\n >\n | FunctionClientResultWithContext<TMiddlewares, TSendContext, TClientContext>\n\nexport type FunctionClientResultWithContext<\n in out TMiddlewares,\n in out TSendContext,\n in out TClientContext,\n> = {\n 'use functions must return the result of next()': true\n context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>\n headers: HeadersInit\n fetch?: CustomFetch\n}\n\nexport interface FunctionMiddlewareAfterClient<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext,\n>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n TServerSendContext,\n TClientContext,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n TServerSendContext,\n TClientContext\n > {}\n\nexport interface FunctionMiddlewareValidator<TRegister, TMiddlewares> {\n inputValidator: <TNewValidator>(\n inputValidator: ConstrainValidator<TRegister, 'GET', TNewValidator>,\n ) => FunctionMiddlewareAfterValidator<TRegister, TMiddlewares, TNewValidator>\n}\n\nexport interface FunctionMiddlewareAfterValidator<\n TRegister,\n TMiddlewares,\n TInputValidator,\n>\n extends\n FunctionMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n undefined,\n undefined,\n undefined\n >,\n FunctionMiddlewareServer<\n TRegister,\n TMiddlewares,\n TInputValidator,\n undefined,\n undefined\n >,\n FunctionMiddlewareClient<TRegister, TMiddlewares, TInputValidator> {}\n\nexport interface RequestMiddleware<\n TRegister,\n> extends RequestMiddlewareAfterMiddleware<TRegister, undefined> {\n middleware: <const TMiddlewares = undefined>(\n middlewares: Constrain<TMiddlewares, ReadonlyArray<AnyRequestMiddleware>>,\n ) => RequestMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n}\n\nexport type AnyRequestMiddleware = RequestMiddlewareWithTypes<any, any, any>\n\nexport interface RequestMiddlewareWithTypes<\n TRegister,\n TMiddlewares,\n TServerContext,\n> {\n '~types': RequestMiddlewareTypes<TRegister, TMiddlewares, TServerContext>\n options: RequestMiddlewareOptions<TRegister, TMiddlewares, TServerContext>\n}\n\nexport interface RequestMiddlewareOptions<\n in out TRegister,\n in out TMiddlewares,\n in out TServerContext,\n> {\n middleware?: TMiddlewares\n server?: RequestServerFn<TRegister, TMiddlewares, TServerContext>\n}\nexport interface RequestMiddlewareTypes<\n TRegister,\n TMiddlewares,\n TServerContext,\n> {\n type: 'request'\n // this only exists so we can use request middlewares in server functions\n allInput: undefined\n // this only exists so we can use request middlewares in server functions\n allOutput: undefined\n middlewares: TMiddlewares\n serverContext: TServerContext\n allServerContext: AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n undefined,\n TServerContext\n >\n}\n\nexport interface RequestMiddlewareAfterMiddleware<TRegister, TMiddlewares>\n extends\n RequestMiddlewareWithTypes<TRegister, TMiddlewares, undefined>,\n RequestMiddlewareServer<TRegister, TMiddlewares> {}\n\nexport interface RequestMiddlewareServer<TRegister, TMiddlewares> {\n server: <TServerContext = undefined>(\n fn: RequestServerFn<TRegister, TMiddlewares, TServerContext>,\n ) => RequestMiddlewareAfterServer<TRegister, TMiddlewares, TServerContext>\n}\n\nexport type RequestServerFn<TRegister, TMiddlewares, TServerContext> = (\n options: RequestServerOptions<TRegister, TMiddlewares>,\n) => RequestMiddlewareServerFnResult<TRegister, TMiddlewares, TServerContext>\n\nexport interface RequestServerOptions<TRegister, TMiddlewares> {\n request: Request\n pathname: string\n context: Expand<AssignAllServerRequestContext<TRegister, TMiddlewares>>\n next: RequestServerNextFn<TRegister, TMiddlewares>\n /**\n * Type of Start handler currently processing this request.\n */\n handlerType: 'serverFn' | 'router'\n /**\n * Metadata about the server function being invoked.\n * This is only present when the request is handling a server function call.\n * For regular page requests, this will be undefined.\n */\n serverFnMeta?: ServerFnMeta\n}\n\nexport type RequestServerNextFn<TRegister, TMiddlewares> = <\n TServerContext = undefined,\n>(\n options?: RequestServerNextFnOptions<TServerContext>,\n) => RequestServerNextFnResult<TRegister, TMiddlewares, TServerContext>\n\nexport interface RequestServerNextFnOptions<TServerContext> {\n context?: TServerContext\n}\n\nexport type RequestServerNextFnResult<TRegister, TMiddlewares, TServerContext> =\n | Promise<RequestServerResult<TRegister, TMiddlewares, TServerContext>>\n | RequestServerResult<TRegister, TMiddlewares, TServerContext>\n\nexport type RequestMiddlewareServerFnResult<\n TRegister,\n TMiddlewares,\n TServerContext,\n> =\n | Promise<\n RequestServerResult<TRegister, TMiddlewares, TServerContext> | Response\n >\n | RequestServerResult<TRegister, TMiddlewares, TServerContext>\n | Response\n\nexport interface RequestServerResult<TRegister, TMiddlewares, TServerContext> {\n request: Request\n pathname: string\n context: Expand<\n AssignAllServerRequestContext<\n TRegister,\n TMiddlewares,\n undefined,\n TServerContext\n >\n >\n response: Response\n}\n\nexport interface RequestMiddlewareAfterServer<\n TRegister,\n TMiddlewares,\n TServerContext,\n> extends RequestMiddlewareWithTypes<TRegister, TMiddlewares, TServerContext> {}\n"],"mappings":";AAiCA,IAAa,oBAA4C,SAAS,WAAW;CAC3E,MAAM,kBAAkB;EACtB,MAAM;EACN,GAAI,UAAU;CAChB;CAEA,OAAO;EACL,SAAS;EACT,aAAa,eAAoB;GAC/B,OAAO,iBACL,CAAC,GACD,OAAO,OAAO,iBAAiB,EAAE,WAAW,CAAC,CAC/C;EACF;EACA,iBAAiB,mBAAwB;GACvC,OAAO,iBACL,CAAC,GACD,OAAO,OAAO,iBAAiB,EAAE,eAAe,CAAC,CACnD;EACF;EACA,SAAS,WAAgB;GACvB,OAAO,iBACL,CAAC,GACD,OAAO,OAAO,iBAAiB,EAAE,OAAO,CAAC,CAC3C;EACF;EACA,SAAS,WAAgB;GACvB,OAAO,iBACL,CAAC,GACD,OAAO,OAAO,iBAAiB,EAAE,OAAO,CAAC,CAC3C;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"createServerFn.js","names":[],"sources":["../../src/createServerFn.ts"],"sourcesContent":["import { mergeHeaders } from '@tanstack/router-core/ssr/client'\n\nimport { isRedirect, parseRedirect } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION_FACTORY } from './constants'\nimport { getStartOptions } from './getStartOptions'\nimport { getStartContextServerOnly } from './getStartContextServerOnly'\nimport { createNullProtoObject, safeObjectMerge } from './safeObjectMerge'\nimport type {\n ClientFnMeta,\n ServerFnMeta,\n TSS_SERVER_FUNCTION,\n} from './constants'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n Register,\n RegisteredSerializableInput,\n ResolveValidatorInput,\n ValidateSerializable,\n ValidateSerializableInput,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n AssignAllServerFnContext,\n FunctionMiddlewareServerFnResult,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n} from './createMiddleware'\n\ntype TODO = any\n\nexport type ServerFnStrict = boolean | { input?: boolean; output?: boolean }\n\nexport interface ServerFnOptions<\n TMethod extends Method = Method,\n TStrict extends ServerFnStrict = true,\n> {\n method?: TMethod\n strict?: TStrict\n}\n\nexport type ServerFnStrictInput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { input: infer TInput extends boolean }\n ? TInput\n : true\n\nexport type ServerFnStrictOutput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { output: infer TOutput extends boolean }\n ? TOutput\n : true\n\nexport type CreateServerFn<TRegister> = <\n TMethod extends Method,\n TStrict extends ServerFnStrict = true,\n TResponse = unknown,\n TMiddlewares = undefined,\n TInputValidator = undefined,\n>(\n options?: ServerFnOptions<TMethod, TStrict>,\n __opts?: ServerFnBaseOptions<\n TRegister,\n TMethod,\n TResponse,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n) => ServerFnBuilder<TRegister, TMethod, TStrict>\n\nexport const createServerFn: CreateServerFn<Register> = (options, __opts) => {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n any,\n any,\n any,\n any,\n any,\n any\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as Method\n }\n\n const res: ServerFnBuilder<Register, Method, ServerFnStrict> = {\n options: resolvedOptions,\n middleware: (middleware) => {\n // multiple calls to `middleware()` merge the middlewares with the previously supplied ones\n // this is primarily useful for letting users create their own abstractions on top of `createServerFn`\n\n const newMiddleware = [...(resolvedOptions.middleware || [])]\n middleware.map((m) => {\n if (TSS_SERVER_FUNCTION_FACTORY in m) {\n if (m.options.middleware) {\n newMiddleware.push(...m.options.middleware)\n }\n } else {\n newMiddleware.push(m)\n }\n })\n\n const newOptions = {\n ...resolvedOptions,\n middleware: newMiddleware,\n }\n const res = createServerFn(undefined, newOptions) as any\n res[TSS_SERVER_FUNCTION_FACTORY] = true\n return res\n },\n inputValidator: (inputValidator) => {\n const newOptions = { ...resolvedOptions, inputValidator }\n return createServerFn(undefined, newOptions) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<Register, any>,\n ServerFn<Register, Method, any, any, any>,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n const newOptions = { ...resolvedOptions, extractedFn, serverFn }\n\n const resolvedMiddleware = [\n ...(newOptions.middleware || []),\n serverFnBaseToMiddleware(newOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n\n // Propagate the declared HTTP method onto the extracted handler\n // so the manifest-exported symbol (resolved by getServerFnById)\n // carries `method`, enabling the server handler to reject\n // mismatched HTTP methods before parsing request payloads.\n ;(extractedFn as any).method = resolvedOptions.method\n\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n const result = await executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...newOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n fetch: opts?.fetch,\n context: createNullProtoObject(),\n })\n\n const redirect = parseRedirect(result.error)\n if (redirect) {\n throw redirect\n }\n\n if (result.error) throw result.error\n return result.result\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // Expose the declared HTTP method so the server handler\n // can reject mismatched methods before parsing payloads\n method: resolvedOptions.method,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts: any) => {\n const startContext = getStartContextServerOnly()\n const serverContextAfterGlobalMiddlewares =\n startContext.contextAfterGlobalMiddlewares\n const ctx = {\n ...extractedFn,\n ...opts,\n // Ensure we use the full serverFnMeta from the provider file's extractedFn\n // (which has id, name, filename) rather than the partial one from SSR/client\n // callers (which only has id)\n serverFnMeta: extractedFn.serverFnMeta,\n // Merge client context first so trusted server middleware context wins.\n context: safeObjectMerge(\n opts.context,\n serverContextAfterGlobalMiddlewares,\n ),\n request: startContext.request,\n }\n\n const result = await executeMiddleware(\n resolvedMiddleware,\n 'server',\n ctx,\n ).then((d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }))\n\n return result\n },\n },\n ) as any\n },\n } as ServerFnBuilder<Register, Method, ServerFnStrict>\n const fun = (options?: ServerFnOptions<Method, ServerFnStrict>) => {\n const newOptions = {\n ...resolvedOptions,\n ...options,\n }\n return createServerFn(undefined, newOptions) as any\n }\n return Object.assign(fun, res) as any\n}\n\nexport async function executeMiddleware(\n middlewares: Array<AnyFunctionMiddleware | AnyRequestMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const globalMiddlewares = getStartOptions()?.functionMiddleware || []\n let flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddlewares,\n ...middlewares,\n ])\n\n // On server, filter out middlewares that already executed in the request phase\n // to prevent duplicate execution (issue #5239)\n if (env === 'server') {\n const startContext = getStartContextServerOnly({ throwIfNotFound: false })\n if (startContext?.executedRequestMiddlewares) {\n flattenedMiddlewares = flattenedMiddlewares.filter(\n (m) => !startContext.executedRequestMiddlewares.has(m),\n )\n }\n }\n\n const callNextMiddleware: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n // Execute the middleware\n try {\n if (\n 'inputValidator' in nextMiddleware.options &&\n nextMiddleware.options.inputValidator &&\n env === 'server'\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(\n nextMiddleware.options.inputValidator,\n ctx.data,\n )\n }\n\n let middlewareFn: MiddlewareFn | undefined = undefined\n if (env === 'client') {\n if ('client' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.client as\n | MiddlewareFn\n | undefined\n }\n }\n // env === 'server'\n else if ('server' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.server as MiddlewareFn | undefined\n }\n\n if (middlewareFn) {\n const userNext = async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n // Use safeObjectMerge for context objects to prevent prototype pollution\n const nextCtx = {\n ...ctx,\n ...userCtx,\n context: safeObjectMerge(ctx.context, userCtx.context),\n sendContext: safeObjectMerge(ctx.sendContext, userCtx.sendContext),\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n _callSiteFetch: ctx._callSiteFetch,\n fetch: ctx._callSiteFetch ?? userCtx.fetch ?? ctx.fetch,\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : userCtx instanceof Response\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n }\n\n const result = await callNextMiddleware(nextCtx)\n\n if (result.error) {\n throw result.error\n }\n\n return result\n }\n\n // Execute the middleware\n const result = await middlewareFn({\n ...ctx,\n next: userNext,\n })\n\n // If result is NOT a ctx object, we need to return it as\n // the { result }\n if (isRedirect(result)) {\n return {\n ...ctx,\n error: result,\n }\n }\n\n if (result instanceof Response) {\n return {\n ...ctx,\n result,\n }\n }\n\n if (!(result as any)) {\n throw new Error(\n 'User middleware returned undefined. You must call next() or return a result in your middlewares.',\n )\n }\n\n return result\n }\n\n return callNextMiddleware(ctx)\n } catch (error: any) {\n return {\n ...ctx,\n error,\n }\n }\n }\n\n // Start the middleware chain\n return callNextMiddleware({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || createNullProtoObject(),\n _callSiteFetch: opts.fetch,\n })\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n context?: any\n}\n\nexport type Fetcher<TMiddlewares, TInputValidator, TResponse> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n ? OptionalFetcher<TMiddlewares, TInputValidator, TResponse>\n : RequiredFetcher<TMiddlewares, TInputValidator, TResponse>\n\nexport interface FetcherBase {\n [TSS_SERVER_FUNCTION]: true\n url: string\n method: Method\n __executeServer: (opts: {\n method: Method\n data: unknown\n headers?: HeadersInit\n context?: any\n }) => Promise<unknown>\n}\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\n// Ideally, this type should just be `export type CustomFetch = typeof globalThis.fetch`, but that conflicts with the type overrides the `bun-types` package - a dependency of unplugin.\n// Relevant bun issues:\n// - https://github.com/oven-sh/bun/issues/23500\n// - https://github.com/oven-sh/bun/issues/23741\nexport type CustomFetch = typeof fetch extends (...args: infer A) => infer R\n ? (...args: A) => R\n : never\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n}\n\nexport interface OptionalFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\n\nexport type ServerFnReturnType<\n TRegister,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictOutput<TStrict> extends false\n ? TResponse\n : TResponse extends PromiseLike<infer U>\n ? Promise<ServerFnReturnType<TRegister, U, TStrict>>\n : TResponse extends Response\n ? TResponse\n : ValidateSerializableInput<TRegister, TResponse>\n\nexport type ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> = (\n ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>,\n) => ServerFnReturnType<TRegister, TResponse, TStrict>\n\nexport interface ServerFnCtx<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n serverFnMeta: ServerFnMeta\n context: Expand<AssignAllServerFnContext<TRegister, TMiddlewares, {}>>\n method: TMethod\n}\n\nexport type CompiledFetcherFn<TRegister, TResponse> = {\n (\n opts: CompiledFetcherFnOptions & ServerFnBaseOptions<TRegister, Method>,\n ): Promise<TResponse>\n url: string\n serverFnMeta: ServerFnMeta\n}\n\nexport type ServerFnBaseOptions<\n TRegister,\n TMethod extends Method = 'GET',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInputValidator = unknown,\n TStrict extends ServerFnStrict = true,\n> = {\n method: TMethod\n strict?: TStrict\n middleware?: Constrain<\n TMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>\n >\n inputValidator?: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n extractedFn?: CompiledFetcherFn<TRegister, TResponse>\n serverFn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n}\n\nexport type ValidateValidatorInput<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictInput<TStrict> extends false\n ? ResolveValidatorInput<TInputValidator>\n : TMethod extends 'POST'\n ? ResolveValidatorInput<TInputValidator> extends FormData\n ? ResolveValidatorInput<TInputValidator>\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n\nexport type ValidateValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ValidateValidatorInput<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n > extends infer TInput\n ? Validator<TInput, any>\n : never\n\nexport type ConstrainValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n | (unknown extends TInputValidator\n ? TInputValidator\n : ResolveValidatorInput<TInputValidator> extends ValidateValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n ? TInputValidator\n : never)\n | ValidateValidator<TRegister, TMethod, TInputValidator, TStrict>\n\nexport type AppendMiddlewares<TMiddlewares, TNewMiddlewares> =\n TMiddlewares extends ReadonlyArray<any>\n ? TNewMiddlewares extends ReadonlyArray<any>\n ? readonly [...TMiddlewares, ...TNewMiddlewares]\n : TMiddlewares\n : TNewMiddlewares\n\nexport interface ServerFnMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n middleware: <const TNewMiddlewares>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>\n >,\n ) => ServerFnAfterMiddleware<\n TRegister,\n TMethod,\n AppendMiddlewares<TMiddlewares, TNewMiddlewares>,\n TInputValidator,\n TStrict\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, TMiddlewares, TStrict>,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnAfterMiddleware<\n TRegister,\n TNewMethod,\n TMiddlewares,\n TInputValidator,\n TNewStrict\n >\n}\n\nexport type ValidatorFn<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> = <TInputValidator>(\n inputValidator: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >,\n) => ServerFnAfterValidator<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n>\n\nexport interface ServerFnValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> {\n inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares, TStrict>\n}\n\nexport interface ServerFnAfterValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\nexport interface ServerFnAfterTyper<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TNewResponse,\n TStrict\n >,\n ) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>\n}\n\nexport interface ServerFnBuilder<\n TRegister,\n TMethod extends Method = 'GET',\n TStrict extends ServerFnStrict = true,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n undefined,\n undefined,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, undefined, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, undefined, TStrict>,\n ServerFnHandler<TRegister, TMethod, undefined, undefined, TStrict> {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnBuilder<TRegister, TNewMethod, TNewStrict>\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n}\n\nexport interface ServerFnWithTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n '~types': ServerFnTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n [TSS_SERVER_FUNCTION_FACTORY]: true\n}\n\nexport type AnyServerFn = ServerFnWithTypes<any, any, any, any, any, any>\n\nexport interface ServerFnTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n method: TMethod\n strict: TStrict\n middlewares: TMiddlewares\n inputValidator: TInputValidator\n response: TResponse\n allServerContext: AssignAllServerFnContext<TRegister, TMiddlewares>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n}\n\nexport function flattenMiddlewares<\n T extends AnyFunctionMiddleware | AnyRequestMiddleware,\n>(middlewares: Array<T>, maxDepth: number = 100): Array<T> {\n const seen = new Set<T>()\n const flattened: Array<T> = []\n\n const recurse = (middleware: Array<T>, depth: number) => {\n if (depth > maxDepth) {\n throw new Error(\n `Middleware nesting depth exceeded maximum of ${maxDepth}. Check for circular references.`,\n )\n }\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware as Array<T>, depth + 1)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares, 0)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n serverFnMeta: ClientFnMeta\n fetch?: CustomFetch\n /** @internal - Preserves the call-site fetch to ensure it has highest priority over middleware */\n _callSiteFetch?: CustomFetch\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n}\n\nexport type NextFn = (\n ctx: ServerFnMiddlewareResult,\n) => Promise<ServerFnMiddlewareResult>\n\nexport type MiddlewareFn = (\n ctx: ServerFnMiddlewareOptions & {\n next: NextFn\n },\n) => Promise<ServerFnMiddlewareResult>\n\nexport async function execValidator(\n validator: AnyValidator,\n input: unknown,\n): Promise<unknown> {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = await validator['~standard'].validate(input)\n\n if (result.issues)\n throw new Error(JSON.stringify(result.issues, undefined, 2))\n\n return result.value\n }\n\n if ('parse' in validator) {\n return validator.parse(input)\n }\n\n if (typeof validator === 'function') {\n return validator(input)\n }\n\n throw new Error('Invalid validator type!')\n}\n\nfunction serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyFunctionMiddleware {\n return {\n '~types': undefined!,\n options: {\n inputValidator: options.inputValidator,\n client: async ({ next, sendContext, fetch, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n fetch,\n } as any\n\n // Execute the extracted function\n // but not before serializing the context\n const res = await options.extractedFn?.(payload)\n\n return next(res)\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx as TODO)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as FunctionMiddlewareServerFnResult<\n any,\n any,\n any,\n any,\n any\n >\n },\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createServerFn.js","names":[],"sources":["../../src/createServerFn.ts"],"sourcesContent":["import { mergeHeaders } from '@tanstack/router-core/ssr/client'\n\nimport { isRedirect, parseRedirect } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION_FACTORY } from './constants'\nimport { getStartOptions } from './getStartOptions'\nimport { getStartContextServerOnly } from './getStartContextServerOnly'\nimport { createNullProtoObject, safeObjectMerge } from './safeObjectMerge'\nimport type {\n ClientFnMeta,\n ServerFnMeta,\n TSS_SERVER_FUNCTION,\n} from './constants'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n Register,\n RegisteredSerializableInput,\n ResolveValidatorInput,\n ValidateSerializable,\n ValidateSerializableInput,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n AssignAllServerFnContext,\n FunctionMiddlewareServerFnResult,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n} from './createMiddleware'\n\ntype TODO = any\n\nexport type ServerFnStrict = boolean | { input?: boolean; output?: boolean }\n\nexport interface ServerFnOptions<\n TMethod extends Method = Method,\n TStrict extends ServerFnStrict = true,\n> {\n method?: TMethod\n strict?: TStrict\n}\n\nexport type ServerFnStrictInput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { input: infer TInput extends boolean }\n ? TInput\n : true\n\nexport type ServerFnStrictOutput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { output: infer TOutput extends boolean }\n ? TOutput\n : true\n\nexport type CreateServerFn<TRegister> = <\n TMethod extends Method,\n TStrict extends ServerFnStrict = true,\n TResponse = unknown,\n TMiddlewares = undefined,\n TInputValidator = undefined,\n>(\n options?: ServerFnOptions<TMethod, TStrict>,\n __opts?: ServerFnBaseOptions<\n TRegister,\n TMethod,\n TResponse,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n) => ServerFnBuilder<TRegister, TMethod, TStrict>\n\nexport const createServerFn: CreateServerFn<Register> = (options, __opts) => {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n any,\n any,\n any,\n any,\n any,\n any\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as Method\n }\n\n const res: ServerFnBuilder<Register, Method, ServerFnStrict> = {\n options: resolvedOptions,\n middleware: (middleware) => {\n // multiple calls to `middleware()` merge the middlewares with the previously supplied ones\n // this is primarily useful for letting users create their own abstractions on top of `createServerFn`\n\n const newMiddleware = [...(resolvedOptions.middleware || [])]\n middleware.map((m) => {\n if (TSS_SERVER_FUNCTION_FACTORY in m) {\n if (m.options.middleware) {\n newMiddleware.push(...m.options.middleware)\n }\n } else {\n newMiddleware.push(m)\n }\n })\n\n const newOptions = {\n ...resolvedOptions,\n middleware: newMiddleware,\n }\n const res = createServerFn(undefined, newOptions) as any\n res[TSS_SERVER_FUNCTION_FACTORY] = true\n return res\n },\n inputValidator: (inputValidator) => {\n const newOptions = { ...resolvedOptions, inputValidator }\n return createServerFn(undefined, newOptions) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<Register, any>,\n ServerFn<Register, Method, any, any, any>,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n const newOptions = { ...resolvedOptions, extractedFn, serverFn }\n\n const resolvedMiddleware = [\n ...(newOptions.middleware || []),\n serverFnBaseToMiddleware(newOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n\n // Propagate the declared HTTP method onto the extracted handler\n // so the manifest-exported symbol (resolved by getServerFnById)\n // carries `method`, enabling the server handler to reject\n // mismatched HTTP methods before parsing request payloads.\n ;(extractedFn as any).method = resolvedOptions.method\n\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n const result = await executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...newOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n fetch: opts?.fetch,\n context: createNullProtoObject(),\n })\n\n const redirect = parseRedirect(result.error)\n if (redirect) {\n throw redirect\n }\n\n if (result.error) throw result.error\n return result.result\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // Expose the declared HTTP method so the server handler\n // can reject mismatched methods before parsing payloads\n method: resolvedOptions.method,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts: any) => {\n const startContext = getStartContextServerOnly()\n const serverContextAfterGlobalMiddlewares =\n startContext.contextAfterGlobalMiddlewares\n const ctx = {\n ...extractedFn,\n ...opts,\n // Ensure we use the full serverFnMeta from the provider file's extractedFn\n // (which has id, name, filename) rather than the partial one from SSR/client\n // callers (which only has id)\n serverFnMeta: extractedFn.serverFnMeta,\n // Merge client context first so trusted server middleware context wins.\n context: safeObjectMerge(\n opts.context,\n serverContextAfterGlobalMiddlewares,\n ),\n request: startContext.request,\n }\n\n const result = await executeMiddleware(\n resolvedMiddleware,\n 'server',\n ctx,\n ).then((d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }))\n\n return result\n },\n },\n ) as any\n },\n } as ServerFnBuilder<Register, Method, ServerFnStrict>\n const fun = (options?: ServerFnOptions<Method, ServerFnStrict>) => {\n const newOptions = {\n ...resolvedOptions,\n ...options,\n }\n return createServerFn(undefined, newOptions) as any\n }\n return Object.assign(fun, res) as any\n}\n\nexport async function executeMiddleware(\n middlewares: Array<AnyFunctionMiddleware | AnyRequestMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const globalMiddlewares = getStartOptions()?.functionMiddleware || []\n let flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddlewares,\n ...middlewares,\n ])\n\n // On server, filter out middlewares that already executed in the request phase\n // to prevent duplicate execution (issue #5239)\n if (env === 'server') {\n const startContext = getStartContextServerOnly({ throwIfNotFound: false })\n if (startContext?.executedRequestMiddlewares) {\n flattenedMiddlewares = flattenedMiddlewares.filter(\n (m) => !startContext.executedRequestMiddlewares.has(m),\n )\n }\n }\n\n const callNextMiddleware: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n // Execute the middleware\n try {\n if (\n 'inputValidator' in nextMiddleware.options &&\n nextMiddleware.options.inputValidator &&\n env === 'server'\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(\n nextMiddleware.options.inputValidator,\n ctx.data,\n )\n }\n\n let middlewareFn: MiddlewareFn | undefined = undefined\n if (env === 'client') {\n if ('client' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.client as\n | MiddlewareFn\n | undefined\n }\n }\n // env === 'server'\n else if ('server' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.server as MiddlewareFn | undefined\n }\n\n if (middlewareFn) {\n const userNext = async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n // Use safeObjectMerge for context objects to prevent prototype pollution\n const nextCtx = {\n ...ctx,\n ...userCtx,\n context: safeObjectMerge(ctx.context, userCtx.context),\n sendContext: safeObjectMerge(ctx.sendContext, userCtx.sendContext),\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n _callSiteFetch: ctx._callSiteFetch,\n fetch: ctx._callSiteFetch ?? userCtx.fetch ?? ctx.fetch,\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : userCtx instanceof Response\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n }\n\n const result = await callNextMiddleware(nextCtx)\n\n if (result.error) {\n throw result.error\n }\n\n return result\n }\n\n // Execute the middleware\n const result = await middlewareFn({\n ...ctx,\n next: userNext,\n })\n\n // If result is NOT a ctx object, we need to return it as\n // the { result }\n if (isRedirect(result)) {\n return {\n ...ctx,\n error: result,\n }\n }\n\n if (result instanceof Response) {\n return {\n ...ctx,\n result,\n }\n }\n\n if (!(result as any)) {\n throw new Error(\n 'User middleware returned undefined. You must call next() or return a result in your middlewares.',\n )\n }\n\n return result\n }\n\n return callNextMiddleware(ctx)\n } catch (error: any) {\n return {\n ...ctx,\n error,\n }\n }\n }\n\n // Start the middleware chain\n return callNextMiddleware({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || createNullProtoObject(),\n _callSiteFetch: opts.fetch,\n })\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n context?: any\n}\n\nexport type Fetcher<TMiddlewares, TInputValidator, TResponse> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n ? OptionalFetcher<TMiddlewares, TInputValidator, TResponse>\n : RequiredFetcher<TMiddlewares, TInputValidator, TResponse>\n\nexport interface FetcherBase {\n [TSS_SERVER_FUNCTION]: true\n url: string\n method: Method\n __executeServer: (opts: {\n method: Method\n data: unknown\n headers?: HeadersInit\n context?: any\n }) => Promise<unknown>\n}\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\n// Ideally, this type should just be `export type CustomFetch = typeof globalThis.fetch`, but that conflicts with the type overrides the `bun-types` package - a dependency of unplugin.\n// Relevant bun issues:\n// - https://github.com/oven-sh/bun/issues/23500\n// - https://github.com/oven-sh/bun/issues/23741\nexport type CustomFetch = typeof fetch extends (...args: infer A) => infer R\n ? (...args: A) => R\n : never\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n}\n\nexport interface OptionalFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\n\nexport type ServerFnReturnType<\n TRegister,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictOutput<TStrict> extends false\n ? TResponse\n : TResponse extends PromiseLike<infer U>\n ? Promise<ServerFnReturnType<TRegister, U, TStrict>>\n : TResponse extends Response\n ? TResponse\n : ValidateSerializableInput<TRegister, TResponse>\n\nexport type ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> = (\n ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>,\n) => ServerFnReturnType<TRegister, TResponse, TStrict>\n\nexport interface ServerFnCtx<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n serverFnMeta: ServerFnMeta\n context: Expand<AssignAllServerFnContext<TRegister, TMiddlewares, {}>>\n method: TMethod\n}\n\nexport type CompiledFetcherFn<TRegister, TResponse> = {\n (\n opts: CompiledFetcherFnOptions & ServerFnBaseOptions<TRegister, Method>,\n ): Promise<TResponse>\n url: string\n serverFnMeta: ServerFnMeta\n}\n\nexport type ServerFnBaseOptions<\n TRegister,\n TMethod extends Method = 'GET',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInputValidator = unknown,\n TStrict extends ServerFnStrict = true,\n> = {\n method: TMethod\n strict?: TStrict\n middleware?: Constrain<\n TMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>\n >\n inputValidator?: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n extractedFn?: CompiledFetcherFn<TRegister, TResponse>\n serverFn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n}\n\nexport type ValidateValidatorInput<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictInput<TStrict> extends false\n ? ResolveValidatorInput<TInputValidator>\n : TMethod extends 'POST'\n ? ResolveValidatorInput<TInputValidator> extends FormData\n ? ResolveValidatorInput<TInputValidator>\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n\nexport type ValidateValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ValidateValidatorInput<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n > extends infer TInput\n ? Validator<TInput, any>\n : never\n\nexport type ConstrainValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n | (unknown extends TInputValidator\n ? TInputValidator\n : ResolveValidatorInput<TInputValidator> extends ValidateValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n ? TInputValidator\n : never)\n | ValidateValidator<TRegister, TMethod, TInputValidator, TStrict>\n\nexport type AppendMiddlewares<TMiddlewares, TNewMiddlewares> =\n TMiddlewares extends ReadonlyArray<any>\n ? TNewMiddlewares extends ReadonlyArray<any>\n ? readonly [...TMiddlewares, ...TNewMiddlewares]\n : TMiddlewares\n : TNewMiddlewares\n\nexport interface ServerFnMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n middleware: <const TNewMiddlewares>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>\n >,\n ) => ServerFnAfterMiddleware<\n TRegister,\n TMethod,\n AppendMiddlewares<TMiddlewares, TNewMiddlewares>,\n TInputValidator,\n TStrict\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, TMiddlewares, TStrict>,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnAfterMiddleware<\n TRegister,\n TNewMethod,\n TMiddlewares,\n TInputValidator,\n TNewStrict\n >\n}\n\nexport type ValidatorFn<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> = <TInputValidator>(\n inputValidator: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >,\n) => ServerFnAfterValidator<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n>\n\nexport interface ServerFnValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> {\n inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares, TStrict>\n}\n\nexport interface ServerFnAfterValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\nexport interface ServerFnAfterTyper<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TNewResponse,\n TStrict\n >,\n ) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>\n}\n\nexport interface ServerFnBuilder<\n TRegister,\n TMethod extends Method = 'GET',\n TStrict extends ServerFnStrict = true,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n undefined,\n undefined,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, undefined, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, undefined, TStrict>,\n ServerFnHandler<TRegister, TMethod, undefined, undefined, TStrict> {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnBuilder<TRegister, TNewMethod, TNewStrict>\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n}\n\nexport interface ServerFnWithTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n '~types': ServerFnTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n [TSS_SERVER_FUNCTION_FACTORY]: true\n}\n\nexport type AnyServerFn = ServerFnWithTypes<any, any, any, any, any, any>\n\nexport interface ServerFnTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n method: TMethod\n strict: TStrict\n middlewares: TMiddlewares\n inputValidator: TInputValidator\n response: TResponse\n allServerContext: AssignAllServerFnContext<TRegister, TMiddlewares>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n}\n\nexport function flattenMiddlewares<\n T extends AnyFunctionMiddleware | AnyRequestMiddleware,\n>(middlewares: Array<T>, maxDepth: number = 100): Array<T> {\n const seen = new Set<T>()\n const flattened: Array<T> = []\n\n const recurse = (middleware: Array<T>, depth: number) => {\n if (depth > maxDepth) {\n throw new Error(\n `Middleware nesting depth exceeded maximum of ${maxDepth}. Check for circular references.`,\n )\n }\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware as Array<T>, depth + 1)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares, 0)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n serverFnMeta: ClientFnMeta\n fetch?: CustomFetch\n /** @internal - Preserves the call-site fetch to ensure it has highest priority over middleware */\n _callSiteFetch?: CustomFetch\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n}\n\nexport type NextFn = (\n ctx: ServerFnMiddlewareResult,\n) => Promise<ServerFnMiddlewareResult>\n\nexport type MiddlewareFn = (\n ctx: ServerFnMiddlewareOptions & {\n next: NextFn\n },\n) => Promise<ServerFnMiddlewareResult>\n\nexport async function execValidator(\n validator: AnyValidator,\n input: unknown,\n): Promise<unknown> {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = await validator['~standard'].validate(input)\n\n if (result.issues)\n throw new Error(JSON.stringify(result.issues, undefined, 2))\n\n return result.value\n }\n\n if ('parse' in validator) {\n return validator.parse(input)\n }\n\n if (typeof validator === 'function') {\n return validator(input)\n }\n\n throw new Error('Invalid validator type!')\n}\n\nfunction serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyFunctionMiddleware {\n return {\n '~types': undefined!,\n options: {\n inputValidator: options.inputValidator,\n client: async ({ next, sendContext, fetch, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n fetch,\n } as any\n\n // Execute the extracted function\n // but not before serializing the context\n const res = await options.extractedFn?.(payload)\n\n return next(res)\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx as TODO)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as FunctionMiddlewareServerFnResult<\n any,\n any,\n any,\n any,\n any\n >\n },\n },\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"createStart.js","names":[],"sources":["../../src/createStart.ts"],"sourcesContent":["import { createMiddleware } from './createMiddleware'\nimport type { TSS_SERVER_FUNCTION } from './constants'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n CreateMiddlewareFn,\n} from './createMiddleware'\nimport type { CustomFetch } from './createServerFn'\nimport type {\n AnySerializationAdapter,\n Register,\n SSROption,\n} from '@tanstack/router-core'\n\nexport interface StartInstanceOptions<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n '~types': StartInstanceTypes<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n serializationAdapters?: TSerializationAdapters\n defaultSsr?: TDefaultSsr\n requestMiddleware?: TRequestMiddlewares\n functionMiddleware?: TFunctionMiddlewares\n /**\n * Configuration options for server functions.\n */\n serverFns?: {\n /**\n * A custom fetch implementation to use for all server function calls.\n * This can be overridden by middleware or at the call site.\n *\n * Precedence (highest to lowest):\n * 1. Call site: `serverFn({ fetch: customFetch })`\n * 2. Later middleware: Last middleware in chain that provides `fetch`\n * 3. Earlier middleware: First middleware in chain that provides `fetch`\n * 4. createStart: `createStart({ serverFns: { fetch: customFetch } })`\n * 5. Default: Global `fetch` function\n *\n * @note Only applies on the client side. During SSR, server functions are called directly.\n */\n fetch?: CustomFetch\n }\n}\n\nexport interface StartInstance<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n getOptions: () =>\n | Promise<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n >\n | StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n createMiddleware: CreateMiddlewareFn<Register>\n}\n\nexport interface StartInstanceTypes<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n serializationAdapters: TSerializationAdapters\n defaultSsr: TDefaultSsr\n requestMiddleware: TRequestMiddlewares\n functionMiddleware: TFunctionMiddlewares\n}\n\nfunction dedupeSerializationAdapters(\n deduped: Set<AnySerializationAdapter>,\n serializationAdapters: Array<AnySerializationAdapter>,\n): void {\n for (let i = 0, len = serializationAdapters.length; i < len; i++) {\n const current = serializationAdapters[i]!\n if (!deduped.has(current)) {\n deduped.add(current)\n if (current.extends) {\n dedupeSerializationAdapters(deduped, current.extends)\n }\n }\n }\n}\n\nexport const createStart = <\n const TSerializationAdapters extends ReadonlyArray<AnySerializationAdapter> =\n [],\n TDefaultSsr extends SSROption = SSROption,\n const TRequestMiddlewares extends ReadonlyArray<AnyRequestMiddleware> = [],\n const TFunctionMiddlewares extends ReadonlyArray<AnyFunctionMiddleware> = [],\n>(\n getOptions: () =>\n | Promise<\n Omit<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >,\n '~types'\n >\n >\n | Omit<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >,\n '~types'\n >,\n): StartInstance<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n> => {\n return {\n getOptions: async () => {\n const options = await getOptions()\n if (options.serializationAdapters) {\n const deduped = new Set<AnySerializationAdapter>()\n dedupeSerializationAdapters(\n deduped,\n options.serializationAdapters as unknown as Array<AnySerializationAdapter>,\n )\n options.serializationAdapters = Array.from(deduped) as any\n }\n return options\n },\n createMiddleware: createMiddleware,\n } as StartInstance<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n}\n\nexport type AnyStartInstance = StartInstance<any, any, any, any>\nexport type AnyStartInstanceOptions = StartInstanceOptions<any, any, any, any>\n\ndeclare module '@tanstack/router-core' {\n interface SerializableExtensions {\n serverFn: { [TSS_SERVER_FUNCTION]: true }\n }\n}\n"],"mappings":";;AAuFA,SAAS,4BACP,SACA,uBACM;AACN,MAAK,IAAI,IAAI,GAAG,MAAM,sBAAsB,QAAQ,IAAI,KAAK,KAAK;EAChE,MAAM,UAAU,sBAAsB;AACtC,MAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE;AACzB,WAAQ,IAAI,QAAQ;AACpB,OAAI,QAAQ,QACV,6BAA4B,SAAS,QAAQ,QAAQ;;;;AAM7D,IAAa,eAOX,eA0BG;AACH,QAAO;EACL,YAAY,YAAY;GACtB,MAAM,UAAU,MAAM,YAAY;AAClC,OAAI,QAAQ,uBAAuB;IACjC,MAAM,0BAAU,IAAI,KAA8B;AAClD,gCACE,SACA,QAAQ,sBACT;AACD,YAAQ,wBAAwB,MAAM,KAAK,QAAQ;;AAErD,UAAO;;EAES;EACnB"}
1
+ {"version":3,"file":"createStart.js","names":[],"sources":["../../src/createStart.ts"],"sourcesContent":["import { createMiddleware } from './createMiddleware'\nimport type { TSS_SERVER_FUNCTION } from './constants'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n CreateMiddlewareFn,\n} from './createMiddleware'\nimport type { CustomFetch } from './createServerFn'\nimport type {\n AnySerializationAdapter,\n Register,\n SSROption,\n} from '@tanstack/router-core'\n\nexport interface StartInstanceOptions<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n '~types': StartInstanceTypes<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n serializationAdapters?: TSerializationAdapters\n defaultSsr?: TDefaultSsr\n requestMiddleware?: TRequestMiddlewares\n functionMiddleware?: TFunctionMiddlewares\n /**\n * Configuration options for server functions.\n */\n serverFns?: {\n /**\n * A custom fetch implementation to use for all server function calls.\n * This can be overridden by middleware or at the call site.\n *\n * Precedence (highest to lowest):\n * 1. Call site: `serverFn({ fetch: customFetch })`\n * 2. Later middleware: Last middleware in chain that provides `fetch`\n * 3. Earlier middleware: First middleware in chain that provides `fetch`\n * 4. createStart: `createStart({ serverFns: { fetch: customFetch } })`\n * 5. Default: Global `fetch` function\n *\n * @note Only applies on the client side. During SSR, server functions are called directly.\n */\n fetch?: CustomFetch\n }\n}\n\nexport interface StartInstance<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n getOptions: () =>\n | Promise<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n >\n | StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n createMiddleware: CreateMiddlewareFn<Register>\n}\n\nexport interface StartInstanceTypes<\n in out TSerializationAdapters,\n in out TDefaultSsr,\n in out TRequestMiddlewares,\n in out TFunctionMiddlewares,\n> {\n serializationAdapters: TSerializationAdapters\n defaultSsr: TDefaultSsr\n requestMiddleware: TRequestMiddlewares\n functionMiddleware: TFunctionMiddlewares\n}\n\nfunction dedupeSerializationAdapters(\n deduped: Set<AnySerializationAdapter>,\n serializationAdapters: Array<AnySerializationAdapter>,\n): void {\n for (let i = 0, len = serializationAdapters.length; i < len; i++) {\n const current = serializationAdapters[i]!\n if (!deduped.has(current)) {\n deduped.add(current)\n if (current.extends) {\n dedupeSerializationAdapters(deduped, current.extends)\n }\n }\n }\n}\n\nexport const createStart = <\n const TSerializationAdapters extends ReadonlyArray<AnySerializationAdapter> =\n [],\n TDefaultSsr extends SSROption = SSROption,\n const TRequestMiddlewares extends ReadonlyArray<AnyRequestMiddleware> = [],\n const TFunctionMiddlewares extends ReadonlyArray<AnyFunctionMiddleware> = [],\n>(\n getOptions: () =>\n | Promise<\n Omit<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >,\n '~types'\n >\n >\n | Omit<\n StartInstanceOptions<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >,\n '~types'\n >,\n): StartInstance<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n> => {\n return {\n getOptions: async () => {\n const options = await getOptions()\n if (options.serializationAdapters) {\n const deduped = new Set<AnySerializationAdapter>()\n dedupeSerializationAdapters(\n deduped,\n options.serializationAdapters as unknown as Array<AnySerializationAdapter>,\n )\n options.serializationAdapters = Array.from(deduped) as any\n }\n return options\n },\n createMiddleware: createMiddleware,\n } as StartInstance<\n TSerializationAdapters,\n TDefaultSsr,\n TRequestMiddlewares,\n TFunctionMiddlewares\n >\n}\n\nexport type AnyStartInstance = StartInstance<any, any, any, any>\nexport type AnyStartInstanceOptions = StartInstanceOptions<any, any, any, any>\n\ndeclare module '@tanstack/router-core' {\n interface SerializableExtensions {\n serverFn: { [TSS_SERVER_FUNCTION]: true }\n }\n}\n"],"mappings":";;AAuFA,SAAS,4BACP,SACA,uBACM;CACN,KAAK,IAAI,IAAI,GAAG,MAAM,sBAAsB,QAAQ,IAAI,KAAK,KAAK;EAChE,MAAM,UAAU,sBAAsB;EACtC,IAAI,CAAC,QAAQ,IAAI,OAAO,GAAG;GACzB,QAAQ,IAAI,OAAO;GACnB,IAAI,QAAQ,SACV,4BAA4B,SAAS,QAAQ,OAAO;EAExD;CACF;AACF;AAEA,IAAa,eAOX,eA0BG;CACH,OAAO;EACL,YAAY,YAAY;GACtB,MAAM,UAAU,MAAM,WAAW;GACjC,IAAI,QAAQ,uBAAuB;IACjC,MAAM,0BAAU,IAAI,IAA6B;IACjD,4BACE,SACA,QAAQ,qBACV;IACA,QAAQ,wBAAwB,MAAM,KAAK,OAAO;GACpD;GACA,OAAO;EACT;EACkB;CACpB;AAMF"}
@@ -1,7 +1,7 @@
1
- //#region src/fake-entries/plugin-adapters.ts
1
+ //#region src/empty-plugin-adapters.ts
2
2
  var pluginSerializationAdapters = [];
3
3
  var hasPluginAdapters = false;
4
4
  //#endregion
5
5
  export { hasPluginAdapters, pluginSerializationAdapters };
6
6
 
7
- //# sourceMappingURL=plugin-adapters.js.map
7
+ //# sourceMappingURL=empty-plugin-adapters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"empty-plugin-adapters.js","names":[],"sources":["../../src/empty-plugin-adapters.ts"],"sourcesContent":["import type { AnySerializationAdapter } from '@tanstack/router-core'\n\nexport const pluginSerializationAdapters: Array<AnySerializationAdapter> = []\nexport const hasPluginAdapters = false\n"],"mappings":";AAEA,IAAa,8BAA8D,CAAC;AAC5E,IAAa,oBAAoB"}
@@ -1 +1 @@
1
- {"version":3,"file":"router.js","names":[],"sources":["../../../src/fake-entries/router.ts"],"sourcesContent":["export function getRouter() {}\n"],"mappings":";AAAA,SAAgB,YAAY"}
1
+ {"version":3,"file":"router.js","names":[],"sources":["../../../src/fake-entries/router.ts"],"sourcesContent":["export function getRouter() {}\n"],"mappings":";AAAA,SAAgB,YAAY,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getDefaultSerovalPlugins.js","names":[],"sources":["../../src/getDefaultSerovalPlugins.ts"],"sourcesContent":["import {\n makeSerovalPlugin,\n defaultSerovalPlugins as routerDefaultSerovalPlugins,\n} from '@tanstack/router-core'\nimport { getStartOptions } from './getStartOptions'\nimport type { AnySerializationAdapter } from '@tanstack/router-core'\nimport type { Plugin } from 'seroval'\n\nexport function getDefaultSerovalPlugins(): Array<Plugin<any, any>> {\n const start = getStartOptions()\n const adapters = start?.serializationAdapters as\n | Array<AnySerializationAdapter>\n | undefined\n return [\n ...(adapters?.map(makeSerovalPlugin) ?? []),\n ...routerDefaultSerovalPlugins,\n ]\n}\n"],"mappings":";;;AAQA,SAAgB,2BAAoD;AAKlE,QAAO,CACL,IALY,iBAAiB,EACP,wBAIR,IAAI,kBAAkB,IAAI,EAAE,EAC1C,GAAG,sBACJ"}
1
+ {"version":3,"file":"getDefaultSerovalPlugins.js","names":[],"sources":["../../src/getDefaultSerovalPlugins.ts"],"sourcesContent":["import {\n makeSerovalPlugin,\n defaultSerovalPlugins as routerDefaultSerovalPlugins,\n} from '@tanstack/router-core'\nimport { getStartOptions } from './getStartOptions'\nimport type { AnySerializationAdapter } from '@tanstack/router-core'\nimport type { Plugin } from 'seroval'\n\nexport function getDefaultSerovalPlugins(): Array<Plugin<any, any>> {\n const start = getStartOptions()\n const adapters = start?.serializationAdapters as\n | Array<AnySerializationAdapter>\n | undefined\n return [\n ...(adapters?.map(makeSerovalPlugin) ?? []),\n ...routerDefaultSerovalPlugins,\n ]\n}\n"],"mappings":";;;AAQA,SAAgB,2BAAoD;CAKlE,OAAO,CACL,IALY,gBACG,GAAO,wBAIR,IAAI,iBAAiB,KAAK,CAAC,GACzC,GAAG,qBACL;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"getGlobalStartContext.js","names":[],"sources":["../../src/getGlobalStartContext.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { AssignAllServerRequestContext } from './createMiddleware'\nimport type { Expand, Register } from '@tanstack/router-core'\n\nexport const getGlobalStartContext: () =>\n | Expand<AssignAllServerRequestContext<Register, []>>\n | undefined = createIsomorphicFn()\n .client(() => undefined)\n .server(() => {\n const context = getStartContext().contextAfterGlobalMiddlewares\n if (!context) {\n throw new Error(\n `Global context not set yet, you are calling getGlobalStartContext() before the global middlewares are applied.`,\n )\n }\n return context\n })\n"],"mappings":";;;AAKA,IAAa,wBAEG,oBAAoB,CACjC,aAAa,KAAA,EAAU,CACvB,aAAa;CACZ,MAAM,UAAU,iBAAiB,CAAC;AAClC,KAAI,CAAC,QACH,OAAM,IAAI,MACR,iHACD;AAEH,QAAO;EACP"}
1
+ {"version":3,"file":"getGlobalStartContext.js","names":[],"sources":["../../src/getGlobalStartContext.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { AssignAllServerRequestContext } from './createMiddleware'\nimport type { Expand, Register } from '@tanstack/router-core'\n\nexport const getGlobalStartContext: () =>\n | Expand<AssignAllServerRequestContext<Register, []>>\n | undefined = createIsomorphicFn()\n .client(() => undefined)\n .server(() => {\n const context = getStartContext().contextAfterGlobalMiddlewares\n if (!context) {\n throw new Error(\n `Global context not set yet, you are calling getGlobalStartContext() before the global middlewares are applied.`,\n )\n }\n return context\n })\n"],"mappings":";;;AAKA,IAAa,wBAEG,mBAAmB,EAChC,aAAa,KAAA,CAAS,EACtB,aAAa;CACZ,MAAM,UAAU,gBAAgB,EAAE;CAClC,IAAI,CAAC,SACH,MAAM,IAAI,MACR,gHACF;CAEF,OAAO;AACT,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getRouterInstance.js","names":[],"sources":["../../src/getRouterInstance.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { Awaitable, RegisteredRouter } from '@tanstack/router-core'\n\nexport const getRouterInstance: () => Awaitable<RegisteredRouter> =\n createIsomorphicFn()\n .client(() => window.__TSR_ROUTER__!)\n .server(() => getStartContext().getRouter())\n"],"mappings":";;;AAIA,IAAa,oBACX,oBAAoB,CACjB,aAAa,OAAO,eAAgB,CACpC,aAAa,iBAAiB,CAAC,WAAW,CAAC"}
1
+ {"version":3,"file":"getRouterInstance.js","names":[],"sources":["../../src/getRouterInstance.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { Awaitable, RegisteredRouter } from '@tanstack/router-core'\n\nexport const getRouterInstance: () => Awaitable<RegisteredRouter> =\n createIsomorphicFn()\n .client(() => window.__TSR_ROUTER__!)\n .server(() => getStartContext().getRouter())\n"],"mappings":";;;AAIA,IAAa,oBACX,mBAAmB,EAChB,aAAa,OAAO,cAAe,EACnC,aAAa,gBAAgB,EAAE,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getStartContextServerOnly.js","names":[],"sources":["../../src/getStartContextServerOnly.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createServerOnlyFn } from '@tanstack/start-fn-stubs'\n\nexport const getStartContextServerOnly = createServerOnlyFn(getStartContext)\n"],"mappings":";;;AAGA,IAAa,4BAA4B,mBAAmB,gBAAgB"}
1
+ {"version":3,"file":"getStartContextServerOnly.js","names":[],"sources":["../../src/getStartContextServerOnly.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createServerOnlyFn } from '@tanstack/start-fn-stubs'\n\nexport const getStartContextServerOnly = createServerOnlyFn(getStartContext)\n"],"mappings":";;;AAGA,IAAa,4BAA4B,mBAAmB,eAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"getStartOptions.js","names":[],"sources":["../../src/getStartOptions.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { AnyStartInstanceOptions } from './createStart'\n\nexport const getStartOptions: () => AnyStartInstanceOptions | undefined =\n createIsomorphicFn()\n .client(() => window.__TSS_START_OPTIONS__)\n .server(() => getStartContext().startOptions)\n"],"mappings":";;;AAIA,IAAa,kBACX,oBAAoB,CACjB,aAAa,OAAO,sBAAsB,CAC1C,aAAa,iBAAiB,CAAC,aAAa"}
1
+ {"version":3,"file":"getStartOptions.js","names":[],"sources":["../../src/getStartOptions.ts"],"sourcesContent":["import { getStartContext } from '@tanstack/start-storage-context'\nimport { createIsomorphicFn } from '@tanstack/start-fn-stubs'\nimport type { AnyStartInstanceOptions } from './createStart'\n\nexport const getStartOptions: () => AnyStartInstanceOptions | undefined =\n createIsomorphicFn()\n .client(() => window.__TSS_START_OPTIONS__)\n .server(() => getStartContext().startOptions)\n"],"mappings":";;;AAIA,IAAa,kBACX,mBAAmB,EAChB,aAAa,OAAO,qBAAqB,EACzC,aAAa,gBAAgB,EAAE,YAAY"}
@@ -1 +1 @@
1
- {"version":3,"file":"condition.js","names":[],"sources":["../../../src/hydration/condition.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst conditionType = 'condition'\n\nexport type HydrationCondition = boolean | (() => boolean)\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function condition(\n condition: HydrationCondition,\n): HydrationStrategy<typeof conditionType, false> {\n return {\n _t: conditionType,\n _d: () => !(typeof condition === 'function' ? condition() : condition),\n _s: ({ gate }) => {\n if (typeof condition === 'function' ? condition() : condition) {\n gate!.resolve()\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,gBAAgB;;AAKtB,SAAgB,UACd,WACgD;AAChD,QAAO;EACL,IAAI;EACJ,UAAU,EAAE,OAAO,cAAc,aAAa,WAAW,GAAG;EAC5D,KAAK,EAAE,WAAW;AAChB,OAAI,OAAO,cAAc,aAAa,WAAW,GAAG,UAClD,MAAM,SAAS;;EAGpB"}
1
+ {"version":3,"file":"condition.js","names":[],"sources":["../../../src/hydration/condition.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst conditionType = 'condition'\n\nexport type HydrationCondition = boolean | (() => boolean)\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function condition(\n condition: HydrationCondition,\n): HydrationStrategy<typeof conditionType, false> {\n return {\n _t: conditionType,\n _d: () => !(typeof condition === 'function' ? condition() : condition),\n _s: ({ gate }) => {\n if (typeof condition === 'function' ? condition() : condition) {\n gate!.resolve()\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,gBAAgB;;AAKtB,SAAgB,UACd,WACgD;CAChD,OAAO;EACL,IAAI;EACJ,UAAU,EAAE,OAAO,cAAc,aAAa,UAAU,IAAI;EAC5D,KAAK,EAAE,WAAW;GAChB,IAAI,OAAO,cAAc,aAAa,UAAU,IAAI,WAClD,KAAM,QAAQ;EAElB;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"idle.js","names":[],"sources":["../../../src/hydration/idle.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst idleType = 'idle'\n\nexport type IdleHydrationOptions = {\n timeout?: number\n}\n\nexport function idle(\n options: IdleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof idleType> {\n const timeout = options.timeout ?? 2000\n\n return {\n _t: idleType,\n _s: ({ gate, prefetch }) => {\n const schedule = globalThis as unknown as {\n requestIdleCallback?: (\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n ) => number\n cancelIdleCallback?: (handle: number) => void\n }\n const callback = prefetch ?? gate!.resolve\n\n if (schedule.requestIdleCallback) {\n const handle = schedule.requestIdleCallback(callback, { timeout })\n return () => schedule.cancelIdleCallback?.(handle)\n }\n\n const timeoutId = globalThis.setTimeout(callback, timeout)\n return () => globalThis.clearTimeout(timeoutId)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,WAAW;AAMjB,SAAgB,KACd,UAAgC,EAAE,EACU;CAC5C,MAAM,UAAU,QAAQ,WAAW;AAEnC,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;GAC1B,MAAM,WAAW;GAOjB,MAAM,WAAW,YAAY,KAAM;AAEnC,OAAI,SAAS,qBAAqB;IAChC,MAAM,SAAS,SAAS,oBAAoB,UAAU,EAAE,SAAS,CAAC;AAClE,iBAAa,SAAS,qBAAqB,OAAO;;GAGpD,MAAM,YAAY,WAAW,WAAW,UAAU,QAAQ;AAC1D,gBAAa,WAAW,aAAa,UAAU;;EAElD"}
1
+ {"version":3,"file":"idle.js","names":[],"sources":["../../../src/hydration/idle.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst idleType = 'idle'\n\nexport type IdleHydrationOptions = {\n timeout?: number\n}\n\nexport function idle(\n options: IdleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof idleType> {\n const timeout = options.timeout ?? 2000\n\n return {\n _t: idleType,\n _s: ({ gate, prefetch }) => {\n const schedule = globalThis as unknown as {\n requestIdleCallback?: (\n callback: IdleRequestCallback,\n options?: IdleRequestOptions,\n ) => number\n cancelIdleCallback?: (handle: number) => void\n }\n const callback = prefetch ?? gate!.resolve\n\n if (schedule.requestIdleCallback) {\n const handle = schedule.requestIdleCallback(callback, { timeout })\n return () => schedule.cancelIdleCallback?.(handle)\n }\n\n const timeoutId = globalThis.setTimeout(callback, timeout)\n return () => globalThis.clearTimeout(timeoutId)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,WAAW;AAMjB,SAAgB,KACd,UAAgC,CAAC,GACW;CAC5C,MAAM,UAAU,QAAQ,WAAW;CAEnC,OAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;GAC1B,MAAM,WAAW;GAOjB,MAAM,WAAW,YAAY,KAAM;GAEnC,IAAI,SAAS,qBAAqB;IAChC,MAAM,SAAS,SAAS,oBAAoB,UAAU,EAAE,QAAQ,CAAC;IACjE,aAAa,SAAS,qBAAqB,MAAM;GACnD;GAEA,MAAM,YAAY,WAAW,WAAW,UAAU,OAAO;GACzD,aAAa,WAAW,aAAa,SAAS;EAChD;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"interaction.js","names":[],"sources":["../../../src/hydration/interaction.ts"],"sourcesContent":["import {\n hydrateIdAttribute,\n hydrateInteractionEventsAttribute,\n hydrateWhenAttribute,\n} from './constants'\nimport {\n clearResolvedGateIdsInMarker,\n getMarkerGate,\n resolveHydrationMarker,\n} from './runtime'\nimport type {\n HydrationInteractionEvents,\n HydrationPrefetchStrategy,\n HydrationRuntimeContext,\n} from './types'\n\nexport type InteractionHydrationOptions = {\n events?: HydrationInteractionEvents\n}\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\ntype PendingReplayEvent = {\n marker: Element\n targetPath: Array<number>\n type: string\n event: Event\n}\n\nconst defaultInteractionEvents = [\n 'pointerenter',\n 'focusin',\n 'pointerdown',\n 'click',\n] as const\nconst supportedInteractionEvents = [\n 'auxclick',\n 'click',\n 'contextmenu',\n 'dblclick',\n 'focusin',\n 'keydown',\n 'keyup',\n 'mousedown',\n 'mouseenter',\n 'mouseover',\n 'mouseup',\n 'pointerdown',\n 'pointerenter',\n 'pointerover',\n 'pointerup',\n] as const\nconst interactionType = 'interaction'\nconst dynamicType = 'dynamic'\nconst interactionHydrateSelector = `[${hydrateWhenAttribute}=\"${interactionType}\"]`\nconst delegatedHydrateSelector = `${interactionHydrateSelector},[${hydrateWhenAttribute}=\"${dynamicType}\"]`\nconst replayEventsByGateId = /* @__PURE__ */ new Map<\n string,\n Array<PendingReplayEvent>\n>()\n\nfunction getIntentListenerEvents(\n marker: Element,\n events: ReadonlyArray<string>,\n) {\n const listenerEvents = new Set(events)\n\n marker.querySelectorAll(delegatedHydrateSelector).forEach((childMarker) => {\n if (childMarker.getAttribute(hydrateWhenAttribute) === dynamicType) {\n supportedInteractionEvents.forEach((eventName) => {\n listenerEvents.add(eventName)\n })\n return\n }\n\n const attr = childMarker.getAttribute(hydrateInteractionEventsAttribute)\n for (const eventName of attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)) {\n listenerEvents.add(eventName)\n }\n })\n\n return [...listenerEvents]\n}\n\nfunction queueHydrationReplayEvent(marker: Element, event: Event) {\n if (!event.bubbles) return\n\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') return\n\n const target = event.target\n if (!target) return\n\n const gate = getMarkerGate(marker)\n if (gate?.resolved) return\n\n event.preventDefault()\n event.stopPropagation()\n event.stopImmediatePropagation()\n\n let targetPath: Array<number> = []\n if (target instanceof Node && marker.contains(target)) {\n let node: Element | null =\n target instanceof Element ? target : target.parentElement\n\n while (node && node !== marker) {\n const parent = node.parentElement\n if (!parent) {\n targetPath = []\n break\n }\n targetPath.push(Array.prototype.indexOf.call(parent.children, node))\n node = parent\n }\n targetPath.reverse()\n }\n\n const pendingEvents = replayEventsByGateId.get(id) ?? []\n pendingEvents.push({\n marker,\n targetPath,\n type: event.type,\n event,\n })\n replayEventsByGateId.set(id, pendingEvents)\n}\n\nif (typeof document !== 'undefined') {\n const onIntent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element)) return\n\n let marker: Element | null = target.closest(hydrateIdSelector)\n const markers: Array<Element> = []\n let shouldHandle = false\n\n while (marker) {\n markers.push(marker)\n\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (when === dynamicType) {\n shouldHandle ||= event.type === 'click'\n } else if (when === interactionType) {\n const attr = marker.getAttribute(hydrateInteractionEventsAttribute)\n const events: ReadonlyArray<string> =\n attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)\n shouldHandle ||= events.includes(event.type)\n }\n\n marker = marker.parentElement?.closest(hydrateIdSelector) ?? null\n }\n\n if (!shouldHandle) return\n\n markers.reverse()\n if (markers.every((marker) => getMarkerGate(marker))) return\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n\n supportedInteractionEvents.forEach((eventName) => {\n document.addEventListener(eventName, onIntent, true)\n })\n}\n\nfunction listenForIntent(\n element: Element,\n events: ReadonlyArray<string>,\n context: HydrationRuntimeContext,\n) {\n const onIntent = (event: Event) => {\n const target = event.target\n let marker: Element | null\n if (target instanceof Element) {\n const closestMarker = target.closest(hydrateIdSelector)\n marker =\n closestMarker && element.contains(closestMarker)\n ? closestMarker\n : element\n } else {\n marker = element\n }\n\n const markers: Array<Element> = []\n while (marker) {\n if (marker.hasAttribute(hydrateIdAttribute)) {\n markers.push(marker)\n }\n if (marker === element) break\n marker = marker.parentElement\n }\n\n if (!markers.includes(element)) {\n markers.push(element)\n }\n\n markers.reverse()\n\n if (\n context.delegated &&\n !markers.some(\n (marker) =>\n marker.getAttribute(hydrateWhenAttribute) === interactionType ||\n marker.getAttribute(hydrateWhenAttribute) === dynamicType,\n )\n ) {\n return\n }\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, onIntent, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, onIntent, true)\n })\n }\n}\n\nexport function listenForDelegatedHydrationIntent(\n element: Element,\n context: HydrationRuntimeContext,\n) {\n const listenerEvents = getIntentListenerEvents(element, [])\n if (!listenerEvents.length) return\n\n const cleanupIntent = listenForIntent(element, listenerEvents, {\n ...context,\n delegated: true,\n })\n return () => {\n cleanupIntent()\n clearResolvedGateIdsInMarker(element)\n }\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function interaction(\n options: InteractionHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof interactionType> {\n let events: ReadonlyArray<string> = defaultInteractionEvents\n if (options.events !== undefined) {\n const eventList: ReadonlyArray<string> =\n typeof options.events === 'string' ? [options.events] : options.events\n const normalizedEvents: Array<string> = []\n const seen = new Set<string>()\n\n for (const eventName of eventList) {\n if (!eventName || seen.has(eventName)) continue\n seen.add(eventName)\n normalizedEvents.push(eventName)\n }\n\n events = normalizedEvents\n }\n\n const eventKey = events.join(' ')\n\n return {\n _t: interactionType,\n _s: (context) => {\n const element = context.element\n if (!element) return\n const prefetch = context.prefetch\n if (prefetch) {\n if (!events.length) return\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, prefetch, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, prefetch, true)\n })\n }\n }\n\n const listenerEvents = getIntentListenerEvents(element, events)\n const cleanupIntent = listenerEvents.length\n ? listenForIntent(element, listenerEvents, context)\n : undefined\n return () => {\n cleanupIntent?.()\n clearResolvedGateIdsInMarker(element)\n }\n },\n _o: (id) => {\n globalThis.requestAnimationFrame(() => {\n const pendingEvents = replayEventsByGateId.get(id)\n if (!pendingEvents?.length) return\n\n replayEventsByGateId.delete(id)\n\n for (const pendingEvent of pendingEvents) {\n let replayTarget: Element | null = pendingEvent.marker\n for (const index of pendingEvent.targetPath) {\n replayTarget = replayTarget.children[index] ?? null\n if (!replayTarget) break\n }\n\n const event = pendingEvent.event\n replayTarget ??= pendingEvent.marker\n replayTarget.dispatchEvent(\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : event instanceof FocusEvent\n ? new FocusEvent(event.type, event)\n : new Event(event.type, event),\n )\n }\n })\n },\n _a: () =>\n options.events === undefined\n ? undefined\n : {\n [hydrateInteractionEventsAttribute]: eventKey,\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"interaction.js","names":[],"sources":["../../../src/hydration/interaction.ts"],"sourcesContent":["import {\n hydrateIdAttribute,\n hydrateInteractionEventsAttribute,\n hydrateWhenAttribute,\n} from './constants'\nimport {\n clearResolvedGateIdsInMarker,\n getMarkerGate,\n resolveHydrationMarker,\n} from './runtime'\nimport type {\n HydrationInteractionEvents,\n HydrationPrefetchStrategy,\n HydrationRuntimeContext,\n} from './types'\n\nexport type InteractionHydrationOptions = {\n events?: HydrationInteractionEvents\n}\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\ntype PendingReplayEvent = {\n marker: Element\n targetPath: Array<number>\n type: string\n event: Event\n}\n\nconst defaultInteractionEvents = [\n 'pointerenter',\n 'focusin',\n 'pointerdown',\n 'click',\n] as const\nconst supportedInteractionEvents = [\n 'auxclick',\n 'click',\n 'contextmenu',\n 'dblclick',\n 'focusin',\n 'keydown',\n 'keyup',\n 'mousedown',\n 'mouseenter',\n 'mouseover',\n 'mouseup',\n 'pointerdown',\n 'pointerenter',\n 'pointerover',\n 'pointerup',\n] as const\nconst interactionType = 'interaction'\nconst dynamicType = 'dynamic'\nconst interactionHydrateSelector = `[${hydrateWhenAttribute}=\"${interactionType}\"]`\nconst delegatedHydrateSelector = `${interactionHydrateSelector},[${hydrateWhenAttribute}=\"${dynamicType}\"]`\nconst replayEventsByGateId = /* @__PURE__ */ new Map<\n string,\n Array<PendingReplayEvent>\n>()\n\nfunction getIntentListenerEvents(\n marker: Element,\n events: ReadonlyArray<string>,\n) {\n const listenerEvents = new Set(events)\n\n marker.querySelectorAll(delegatedHydrateSelector).forEach((childMarker) => {\n if (childMarker.getAttribute(hydrateWhenAttribute) === dynamicType) {\n supportedInteractionEvents.forEach((eventName) => {\n listenerEvents.add(eventName)\n })\n return\n }\n\n const attr = childMarker.getAttribute(hydrateInteractionEventsAttribute)\n for (const eventName of attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)) {\n listenerEvents.add(eventName)\n }\n })\n\n return [...listenerEvents]\n}\n\nfunction queueHydrationReplayEvent(marker: Element, event: Event) {\n if (!event.bubbles) return\n\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') return\n\n const target = event.target\n if (!target) return\n\n const gate = getMarkerGate(marker)\n if (gate?.resolved) return\n\n event.preventDefault()\n event.stopPropagation()\n event.stopImmediatePropagation()\n\n let targetPath: Array<number> = []\n if (target instanceof Node && marker.contains(target)) {\n let node: Element | null =\n target instanceof Element ? target : target.parentElement\n\n while (node && node !== marker) {\n const parent = node.parentElement\n if (!parent) {\n targetPath = []\n break\n }\n targetPath.push(Array.prototype.indexOf.call(parent.children, node))\n node = parent\n }\n targetPath.reverse()\n }\n\n const pendingEvents = replayEventsByGateId.get(id) ?? []\n pendingEvents.push({\n marker,\n targetPath,\n type: event.type,\n event,\n })\n replayEventsByGateId.set(id, pendingEvents)\n}\n\nif (typeof document !== 'undefined') {\n const onIntent = (event: Event) => {\n const target = event.target\n if (!(target instanceof Element)) return\n\n let marker: Element | null = target.closest(hydrateIdSelector)\n const markers: Array<Element> = []\n let shouldHandle = false\n\n while (marker) {\n markers.push(marker)\n\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (when === dynamicType) {\n shouldHandle ||= event.type === 'click'\n } else if (when === interactionType) {\n const attr = marker.getAttribute(hydrateInteractionEventsAttribute)\n const events: ReadonlyArray<string> =\n attr === null\n ? defaultInteractionEvents\n : attr.split(/\\s+/).filter(Boolean)\n shouldHandle ||= events.includes(event.type)\n }\n\n marker = marker.parentElement?.closest(hydrateIdSelector) ?? null\n }\n\n if (!shouldHandle) return\n\n markers.reverse()\n if (markers.every((marker) => getMarkerGate(marker))) return\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n\n supportedInteractionEvents.forEach((eventName) => {\n document.addEventListener(eventName, onIntent, true)\n })\n}\n\nfunction listenForIntent(\n element: Element,\n events: ReadonlyArray<string>,\n context: HydrationRuntimeContext,\n) {\n const onIntent = (event: Event) => {\n const target = event.target\n let marker: Element | null\n if (target instanceof Element) {\n const closestMarker = target.closest(hydrateIdSelector)\n marker =\n closestMarker && element.contains(closestMarker)\n ? closestMarker\n : element\n } else {\n marker = element\n }\n\n const markers: Array<Element> = []\n while (marker) {\n if (marker.hasAttribute(hydrateIdAttribute)) {\n markers.push(marker)\n }\n if (marker === element) break\n marker = marker.parentElement\n }\n\n if (!markers.includes(element)) {\n markers.push(element)\n }\n\n markers.reverse()\n\n if (\n context.delegated &&\n !markers.some(\n (marker) =>\n marker.getAttribute(hydrateWhenAttribute) === interactionType ||\n marker.getAttribute(hydrateWhenAttribute) === dynamicType,\n )\n ) {\n return\n }\n\n markers.forEach((marker) => {\n queueHydrationReplayEvent(marker, event)\n resolveHydrationMarker(marker)\n })\n }\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, onIntent, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, onIntent, true)\n })\n }\n}\n\nexport function listenForDelegatedHydrationIntent(\n element: Element,\n context: HydrationRuntimeContext,\n) {\n const listenerEvents = getIntentListenerEvents(element, [])\n if (!listenerEvents.length) return\n\n const cleanupIntent = listenForIntent(element, listenerEvents, {\n ...context,\n delegated: true,\n })\n return () => {\n cleanupIntent()\n clearResolvedGateIdsInMarker(element)\n }\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function interaction(\n options: InteractionHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof interactionType> {\n let events: ReadonlyArray<string> = defaultInteractionEvents\n if (options.events !== undefined) {\n const eventList: ReadonlyArray<string> =\n typeof options.events === 'string' ? [options.events] : options.events\n const normalizedEvents: Array<string> = []\n const seen = new Set<string>()\n\n for (const eventName of eventList) {\n if (!eventName || seen.has(eventName)) continue\n seen.add(eventName)\n normalizedEvents.push(eventName)\n }\n\n events = normalizedEvents\n }\n\n const eventKey = events.join(' ')\n\n return {\n _t: interactionType,\n _s: (context) => {\n const element = context.element\n if (!element) return\n const prefetch = context.prefetch\n if (prefetch) {\n if (!events.length) return\n let disposed = false\n\n events.forEach((eventName) => {\n element.addEventListener(eventName, prefetch, true)\n })\n\n return () => {\n if (disposed) return\n disposed = true\n events.forEach((eventName) => {\n element.removeEventListener(eventName, prefetch, true)\n })\n }\n }\n\n const listenerEvents = getIntentListenerEvents(element, events)\n const cleanupIntent = listenerEvents.length\n ? listenForIntent(element, listenerEvents, context)\n : undefined\n return () => {\n cleanupIntent?.()\n clearResolvedGateIdsInMarker(element)\n }\n },\n _o: (id) => {\n globalThis.requestAnimationFrame(() => {\n const pendingEvents = replayEventsByGateId.get(id)\n if (!pendingEvents?.length) return\n\n replayEventsByGateId.delete(id)\n\n for (const pendingEvent of pendingEvents) {\n let replayTarget: Element | null = pendingEvent.marker\n for (const index of pendingEvent.targetPath) {\n replayTarget = replayTarget.children[index] ?? null\n if (!replayTarget) break\n }\n\n const event = pendingEvent.event\n replayTarget ??= pendingEvent.marker\n replayTarget.dispatchEvent(\n event instanceof MouseEvent\n ? new MouseEvent(event.type, event)\n : event instanceof FocusEvent\n ? new FocusEvent(event.type, event)\n : new Event(event.type, event),\n )\n }\n })\n },\n _a: () =>\n options.events === undefined\n ? undefined\n : {\n [hydrateInteractionEventsAttribute]: eventKey,\n },\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","names":[],"sources":["../../../src/hydration/load.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst loadType = 'load'\n\nconst loadStrategy: HydrationPrefetchStrategy<typeof loadType> = {\n _t: loadType,\n _d: () => false,\n _s: ({ gate, prefetch }) => {\n ;(prefetch ?? gate!.resolve)()\n },\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function load(): HydrationPrefetchStrategy<typeof loadType> {\n return loadStrategy\n}\n"],"mappings":";AAIA,IAAM,eAA2D;CAC/D,IAHe;CAIf,UAAU;CACV,KAAK,EAAE,MAAM,eAAe;AACzB,GAAC,YAAY,KAAM,UAAU;;CAEjC;;AAGD,SAAgB,OAAmD;AACjE,QAAO"}
1
+ {"version":3,"file":"load.js","names":[],"sources":["../../../src/hydration/load.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst loadType = 'load'\n\nconst loadStrategy: HydrationPrefetchStrategy<typeof loadType> = {\n _t: loadType,\n _d: () => false,\n _s: ({ gate, prefetch }) => {\n ;(prefetch ?? gate!.resolve)()\n },\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function load(): HydrationPrefetchStrategy<typeof loadType> {\n return loadStrategy\n}\n"],"mappings":";AAIA,IAAM,eAA2D;CAC/D,IAAI;CACJ,UAAU;CACV,KAAK,EAAE,MAAM,eAAe;EACzB,CAAC,YAAY,KAAM,SAAS;CAC/B;AACF;;AAGA,SAAgB,OAAmD;CACjE,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"media.js","names":[],"sources":["../../../src/hydration/media.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst mediaType = 'media'\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function media(\n query: string,\n): HydrationPrefetchStrategy<typeof mediaType> {\n return {\n _t: mediaType,\n _s: ({ gate, prefetch }) => {\n if (!query) return\n\n const callback = prefetch ?? gate!.resolve\n const mediaQuery = window.matchMedia(query)\n const onChange = () => {\n if (mediaQuery.matches) callback()\n }\n mediaQuery.addEventListener('change', onChange)\n onChange()\n\n return () => mediaQuery.removeEventListener('change', onChange)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,YAAY;;AAGlB,SAAgB,MACd,OAC6C;AAC7C,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;AAC1B,OAAI,CAAC,MAAO;GAEZ,MAAM,WAAW,YAAY,KAAM;GACnC,MAAM,aAAa,OAAO,WAAW,MAAM;GAC3C,MAAM,iBAAiB;AACrB,QAAI,WAAW,QAAS,WAAU;;AAEpC,cAAW,iBAAiB,UAAU,SAAS;AAC/C,aAAU;AAEV,gBAAa,WAAW,oBAAoB,UAAU,SAAS;;EAElE"}
1
+ {"version":3,"file":"media.js","names":[],"sources":["../../../src/hydration/media.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst mediaType = 'media'\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function media(\n query: string,\n): HydrationPrefetchStrategy<typeof mediaType> {\n return {\n _t: mediaType,\n _s: ({ gate, prefetch }) => {\n if (!query) return\n\n const callback = prefetch ?? gate!.resolve\n const mediaQuery = window.matchMedia(query)\n const onChange = () => {\n if (mediaQuery.matches) callback()\n }\n mediaQuery.addEventListener('change', onChange)\n onChange()\n\n return () => mediaQuery.removeEventListener('change', onChange)\n },\n }\n}\n"],"mappings":";AAEA,IAAM,YAAY;;AAGlB,SAAgB,MACd,OAC6C;CAC7C,OAAO;EACL,IAAI;EACJ,KAAK,EAAE,MAAM,eAAe;GAC1B,IAAI,CAAC,OAAO;GAEZ,MAAM,WAAW,YAAY,KAAM;GACnC,MAAM,aAAa,OAAO,WAAW,KAAK;GAC1C,MAAM,iBAAiB;IACrB,IAAI,WAAW,SAAS,SAAS;GACnC;GACA,WAAW,iBAAiB,UAAU,QAAQ;GAC9C,SAAS;GAET,aAAa,WAAW,oBAAoB,UAAU,QAAQ;EAChE;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"never.js","names":[],"sources":["../../../src/hydration/never.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst neverType = 'never'\n\nconst neverStrategy: HydrationStrategy<typeof neverType, false> = {\n _t: neverType,\n _d: () => true,\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function never(): HydrationStrategy<typeof neverType, false> {\n return neverStrategy\n}\n"],"mappings":";AAIA,IAAM,gBAA4D;CAChE,IAHgB;CAIhB,UAAU;CACX;;AAGD,SAAgB,QAAoD;AAClE,QAAO"}
1
+ {"version":3,"file":"never.js","names":[],"sources":["../../../src/hydration/never.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nconst neverType = 'never'\n\nconst neverStrategy: HydrationStrategy<typeof neverType, false> = {\n _t: neverType,\n _d: () => true,\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function never(): HydrationStrategy<typeof neverType, false> {\n return neverStrategy\n}\n"],"mappings":";AAIA,IAAM,gBAA4D;CAChE,IAAI;CACJ,UAAU;AACZ;;AAGA,SAAgB,QAAoD;CAClE,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","names":[],"sources":["../../../src/hydration/renderer.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nexport type HydrationStrategyWithRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n> = TStrategy & {\n _h: TRenderer\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function withHydrationRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n>(\n strategy: TStrategy,\n renderer: TRenderer,\n): HydrationStrategyWithRenderer<TStrategy, TRenderer> {\n return /* @__PURE__ */ Object.assign(strategy, {\n _h: renderer,\n })\n}\n"],"mappings":";;AAUA,SAAgB,sBAId,UACA,UACqD;AACrD,QAAuB,uBAAO,OAAO,UAAU,EAC7C,IAAI,UACL,CAAC"}
1
+ {"version":3,"file":"renderer.js","names":[],"sources":["../../../src/hydration/renderer.ts"],"sourcesContent":["import type { HydrationStrategy } from './types'\n\nexport type HydrationStrategyWithRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n> = TStrategy & {\n _h: TRenderer\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function withHydrationRenderer<\n TStrategy extends HydrationStrategy,\n TRenderer,\n>(\n strategy: TStrategy,\n renderer: TRenderer,\n): HydrationStrategyWithRenderer<TStrategy, TRenderer> {\n return /* @__PURE__ */ Object.assign(strategy, {\n _h: renderer,\n })\n}\n"],"mappings":";;AAUA,SAAgB,sBAId,UACA,UACqD;CACrD,OAAuB,uBAAO,OAAO,UAAU,EAC7C,IAAI,SACN,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","names":[],"sources":["../../../src/hydration/runtime.ts"],"sourcesContent":["import { hydrateIdAttribute, hydrateWhenAttribute } from './constants'\nimport type {\n HydrationPrefetchStrategy,\n HydrationPrefetchWaitReason,\n HydrationRuntimeGate,\n HydrationWhen,\n} from './types'\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\nexport type HydrationGateRecord = HydrationRuntimeGate & {\n id: string\n when: HydrationWhen\n promise: Promise<void>\n consumers: number\n resolveListeners: Set<() => void>\n}\n\nconst gateRegistry = /* @__PURE__ */ new Map<string, HydrationGateRecord>()\nconst resolvedGateIds = /* @__PURE__ */ new Set<string>()\nconst fallbackHtmlByGateId = /* @__PURE__ */ new Map<string, string>()\n\nexport function createResolvedGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n return {\n id,\n when,\n promise: Promise.resolve(),\n resolve: () => {},\n resolved: true,\n consumers: 0,\n resolveListeners: new Set<() => void>(),\n }\n}\n\nexport function getOrCreateGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n const existing = gateRegistry.get(id)\n if (existing?.when === when) {\n existing.consumers++\n return existing\n }\n\n let resolvePromise!: () => void\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve\n })\n\n const gate: HydrationGateRecord = {\n id,\n promise,\n resolved: false,\n consumers: 1,\n when,\n resolveListeners: new Set(),\n resolve: () => {\n if (gate.resolved) return\n gate.resolved = true\n resolvePromise()\n gate.resolveListeners.forEach((listener) => listener())\n gate.resolveListeners.clear()\n },\n }\n\n gateRegistry.set(id, gate)\n if (when !== 'never' && resolvedGateIds.has(id)) {\n resolvedGateIds.delete(id)\n gate.resolve()\n }\n return gate\n}\n\nexport function releaseGate(gate: HydrationGateRecord) {\n resolvedGateIds.delete(gate.id)\n gate.consumers--\n if (gate.consumers > 0) return\n if (gateRegistry.get(gate.id) === gate) {\n gateRegistry.delete(gate.id)\n fallbackHtmlByGateId.delete(gate.id)\n gate.resolveListeners.clear()\n }\n}\n\nexport function onGateResolve(gate: HydrationGateRecord, listener: () => void) {\n if (gate.resolved) {\n listener()\n return () => {}\n }\n\n gate.resolveListeners.add(listener)\n return () => {\n gate.resolveListeners.delete(listener)\n }\n}\n\nexport function runHydrationStrategyCleanup(cleanup: void | (() => void)) {\n if (typeof cleanup === 'function') return cleanup\n return undefined\n}\n\nexport function waitForHydrationPrefetchStrategy(\n strategy: HydrationPrefetchStrategy,\n options: {\n element: Element | null\n signal: AbortSignal\n onHydrate: (listener: () => void) => () => void\n },\n): Promise<HydrationPrefetchWaitReason> {\n if (options.signal.aborted) {\n return Promise.resolve('abort')\n }\n\n return new Promise((resolve) => {\n const state = { disposed: false }\n const cleanupStrategyRef: { current: void | (() => void) } = {\n current: undefined,\n }\n let cleanupHydrate = () => {}\n\n const finish = (reason: HydrationPrefetchWaitReason) => {\n if (state.disposed) return\n state.disposed = true\n options.signal.removeEventListener('abort', onAbort)\n cleanupHydrate()\n runHydrationStrategyCleanup(cleanupStrategyRef.current)?.()\n resolve(reason)\n }\n\n const onAbort = () => finish('abort')\n\n options.signal.addEventListener('abort', onAbort, { once: true })\n cleanupHydrate = options.onHydrate(() => finish('hydrate'))\n const cleanupStrategy = strategy._s?.({\n element: options.element,\n prefetch: () => finish('prefetch'),\n })\n cleanupStrategyRef.current = cleanupStrategy\n if (state.disposed) {\n runHydrationStrategyCleanup(cleanupStrategy)?.()\n }\n })\n}\n\nexport function getMarkerGate(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n return id ? gateRegistry.get(id) : undefined\n}\n\nexport function resolveHydrationMarker(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') {\n return\n }\n\n const gate = gateRegistry.get(id)\n if (gate) {\n if (gate.when !== 'never') gate.resolve()\n return\n }\n\n resolvedGateIds.add(id)\n}\n\nexport function clearResolvedGateIdsInMarker(marker: Element) {\n const ownId = marker.getAttribute(hydrateIdAttribute)\n if (ownId) {\n resolvedGateIds.delete(ownId)\n }\n\n marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => {\n const childId = childMarker.getAttribute(hydrateIdAttribute)\n if (childId) {\n resolvedGateIds.delete(childId)\n }\n })\n}\n\nexport function saveFallbackHtml(id: string, element: Element) {\n if (!fallbackHtmlByGateId.has(id)) {\n fallbackHtmlByGateId.set(id, element.innerHTML)\n }\n}\n\nexport function getFallbackHtml(id: string) {\n return fallbackHtmlByGateId.get(id)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"runtime.js","names":[],"sources":["../../../src/hydration/runtime.ts"],"sourcesContent":["import { hydrateIdAttribute, hydrateWhenAttribute } from './constants'\nimport type {\n HydrationPrefetchStrategy,\n HydrationPrefetchWaitReason,\n HydrationRuntimeGate,\n HydrationWhen,\n} from './types'\n\nconst hydrateIdSelector = `[${hydrateIdAttribute}]`\n\nexport type HydrationGateRecord = HydrationRuntimeGate & {\n id: string\n when: HydrationWhen\n promise: Promise<void>\n consumers: number\n resolveListeners: Set<() => void>\n}\n\nconst gateRegistry = /* @__PURE__ */ new Map<string, HydrationGateRecord>()\nconst resolvedGateIds = /* @__PURE__ */ new Set<string>()\nconst fallbackHtmlByGateId = /* @__PURE__ */ new Map<string, string>()\n\nexport function createResolvedGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n return {\n id,\n when,\n promise: Promise.resolve(),\n resolve: () => {},\n resolved: true,\n consumers: 0,\n resolveListeners: new Set<() => void>(),\n }\n}\n\nexport function getOrCreateGate(\n id: string,\n when: HydrationWhen,\n): HydrationGateRecord {\n const existing = gateRegistry.get(id)\n if (existing?.when === when) {\n existing.consumers++\n return existing\n }\n\n let resolvePromise!: () => void\n const promise = new Promise<void>((resolve) => {\n resolvePromise = resolve\n })\n\n const gate: HydrationGateRecord = {\n id,\n promise,\n resolved: false,\n consumers: 1,\n when,\n resolveListeners: new Set(),\n resolve: () => {\n if (gate.resolved) return\n gate.resolved = true\n resolvePromise()\n gate.resolveListeners.forEach((listener) => listener())\n gate.resolveListeners.clear()\n },\n }\n\n gateRegistry.set(id, gate)\n if (when !== 'never' && resolvedGateIds.has(id)) {\n resolvedGateIds.delete(id)\n gate.resolve()\n }\n return gate\n}\n\nexport function releaseGate(gate: HydrationGateRecord) {\n resolvedGateIds.delete(gate.id)\n gate.consumers--\n if (gate.consumers > 0) return\n if (gateRegistry.get(gate.id) === gate) {\n gateRegistry.delete(gate.id)\n fallbackHtmlByGateId.delete(gate.id)\n gate.resolveListeners.clear()\n }\n}\n\nexport function onGateResolve(gate: HydrationGateRecord, listener: () => void) {\n if (gate.resolved) {\n listener()\n return () => {}\n }\n\n gate.resolveListeners.add(listener)\n return () => {\n gate.resolveListeners.delete(listener)\n }\n}\n\nexport function runHydrationStrategyCleanup(cleanup: void | (() => void)) {\n if (typeof cleanup === 'function') return cleanup\n return undefined\n}\n\nexport function waitForHydrationPrefetchStrategy(\n strategy: HydrationPrefetchStrategy,\n options: {\n element: Element | null\n signal: AbortSignal\n onHydrate: (listener: () => void) => () => void\n },\n): Promise<HydrationPrefetchWaitReason> {\n if (options.signal.aborted) {\n return Promise.resolve('abort')\n }\n\n return new Promise((resolve) => {\n const state = { disposed: false }\n const cleanupStrategyRef: { current: void | (() => void) } = {\n current: undefined,\n }\n let cleanupHydrate = () => {}\n\n const finish = (reason: HydrationPrefetchWaitReason) => {\n if (state.disposed) return\n state.disposed = true\n options.signal.removeEventListener('abort', onAbort)\n cleanupHydrate()\n runHydrationStrategyCleanup(cleanupStrategyRef.current)?.()\n resolve(reason)\n }\n\n const onAbort = () => finish('abort')\n\n options.signal.addEventListener('abort', onAbort, { once: true })\n cleanupHydrate = options.onHydrate(() => finish('hydrate'))\n const cleanupStrategy = strategy._s?.({\n element: options.element,\n prefetch: () => finish('prefetch'),\n })\n cleanupStrategyRef.current = cleanupStrategy\n if (state.disposed) {\n runHydrationStrategyCleanup(cleanupStrategy)?.()\n }\n })\n}\n\nexport function getMarkerGate(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n return id ? gateRegistry.get(id) : undefined\n}\n\nexport function resolveHydrationMarker(marker: Element) {\n const id = marker.getAttribute(hydrateIdAttribute)\n const when = marker.getAttribute(hydrateWhenAttribute)\n if (!id || !when || when === 'never') {\n return\n }\n\n const gate = gateRegistry.get(id)\n if (gate) {\n if (gate.when !== 'never') gate.resolve()\n return\n }\n\n resolvedGateIds.add(id)\n}\n\nexport function clearResolvedGateIdsInMarker(marker: Element) {\n const ownId = marker.getAttribute(hydrateIdAttribute)\n if (ownId) {\n resolvedGateIds.delete(ownId)\n }\n\n marker.querySelectorAll(hydrateIdSelector).forEach((childMarker) => {\n const childId = childMarker.getAttribute(hydrateIdAttribute)\n if (childId) {\n resolvedGateIds.delete(childId)\n }\n })\n}\n\nexport function saveFallbackHtml(id: string, element: Element) {\n if (!fallbackHtmlByGateId.has(id)) {\n fallbackHtmlByGateId.set(id, element.innerHTML)\n }\n}\n\nexport function getFallbackHtml(id: string) {\n return fallbackHtmlByGateId.get(id)\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"visible.js","names":[],"sources":["../../../src/hydration/visible.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst visibleType = 'visible'\n\nexport type VisibleHydrationOptions = {\n rootMargin?: string\n threshold?: number | Array<number>\n}\n\ntype VisibleObserverEntry = {\n key: string\n observer: IntersectionObserver\n elements: Map<Element, Set<() => void>>\n}\n\nconst observerRegistry = /* @__PURE__ */ new Map<string, VisibleObserverEntry>()\n\nfunction cleanupVisibleObserverEntry(observerEntry: VisibleObserverEntry) {\n if (observerEntry.elements.size > 0) return\n observerEntry.observer.disconnect()\n observerRegistry.delete(observerEntry.key)\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function visible(\n options: VisibleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof visibleType> {\n const rootMargin = options.rootMargin ?? '600px'\n const threshold = options.threshold ?? 0\n\n return {\n _t: visibleType,\n _s: ({ element, gate, prefetch }) => {\n const callback = prefetch ?? gate!.resolve\n\n if (!element) {\n callback()\n return\n }\n\n const key = `${rootMargin}|${\n Array.isArray(threshold) ? threshold.join(',') : String(threshold)\n }`\n let observerEntry = observerRegistry.get(key)\n\n if (!observerEntry) {\n const entry: VisibleObserverEntry = {\n key,\n elements: new Map<Element, Set<() => void>>(),\n observer: new IntersectionObserver(\n (entries) => {\n for (const intersectingEntry of entries) {\n if (!intersectingEntry.isIntersecting) continue\n\n const callbacks = entry.elements.get(intersectingEntry.target)\n if (!callbacks) continue\n\n callbacks.forEach((callback) => callback())\n entry.elements.delete(intersectingEntry.target)\n entry.observer.unobserve(intersectingEntry.target)\n cleanupVisibleObserverEntry(entry)\n }\n },\n { rootMargin, threshold },\n ),\n }\n observerRegistry.set(key, entry)\n observerEntry = entry\n }\n\n let callbacks = observerEntry.elements.get(element)\n if (!callbacks) {\n callbacks = new Set()\n observerEntry.elements.set(element, callbacks)\n observerEntry.observer.observe(element)\n }\n callbacks.add(callback)\n\n return () => {\n const currentCallbacks = observerEntry.elements.get(element)\n currentCallbacks?.delete(callback)\n if (currentCallbacks?.size === 0) {\n observerEntry.elements.delete(element)\n observerEntry.observer.unobserve(element)\n }\n cleanupVisibleObserverEntry(observerEntry)\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,cAAc;AAapB,IAAM,mCAAmC,IAAI,KAAmC;AAEhF,SAAS,4BAA4B,eAAqC;AACxE,KAAI,cAAc,SAAS,OAAO,EAAG;AACrC,eAAc,SAAS,YAAY;AACnC,kBAAiB,OAAO,cAAc,IAAI;;;AAI5C,SAAgB,QACd,UAAmC,EAAE,EACU;CAC/C,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,YAAY,QAAQ,aAAa;AAEvC,QAAO;EACL,IAAI;EACJ,KAAK,EAAE,SAAS,MAAM,eAAe;GACnC,MAAM,WAAW,YAAY,KAAM;AAEnC,OAAI,CAAC,SAAS;AACZ,cAAU;AACV;;GAGF,MAAM,MAAM,GAAG,WAAW,GACxB,MAAM,QAAQ,UAAU,GAAG,UAAU,KAAK,IAAI,GAAG,OAAO,UAAU;GAEpE,IAAI,gBAAgB,iBAAiB,IAAI,IAAI;AAE7C,OAAI,CAAC,eAAe;IAClB,MAAM,QAA8B;KAClC;KACA,0BAAU,IAAI,KAA+B;KAC7C,UAAU,IAAI,sBACX,YAAY;AACX,WAAK,MAAM,qBAAqB,SAAS;AACvC,WAAI,CAAC,kBAAkB,eAAgB;OAEvC,MAAM,YAAY,MAAM,SAAS,IAAI,kBAAkB,OAAO;AAC9D,WAAI,CAAC,UAAW;AAEhB,iBAAU,SAAS,aAAa,UAAU,CAAC;AAC3C,aAAM,SAAS,OAAO,kBAAkB,OAAO;AAC/C,aAAM,SAAS,UAAU,kBAAkB,OAAO;AAClD,mCAA4B,MAAM;;QAGtC;MAAE;MAAY;MAAW,CAC1B;KACF;AACD,qBAAiB,IAAI,KAAK,MAAM;AAChC,oBAAgB;;GAGlB,IAAI,YAAY,cAAc,SAAS,IAAI,QAAQ;AACnD,OAAI,CAAC,WAAW;AACd,gCAAY,IAAI,KAAK;AACrB,kBAAc,SAAS,IAAI,SAAS,UAAU;AAC9C,kBAAc,SAAS,QAAQ,QAAQ;;AAEzC,aAAU,IAAI,SAAS;AAEvB,gBAAa;IACX,MAAM,mBAAmB,cAAc,SAAS,IAAI,QAAQ;AAC5D,sBAAkB,OAAO,SAAS;AAClC,QAAI,kBAAkB,SAAS,GAAG;AAChC,mBAAc,SAAS,OAAO,QAAQ;AACtC,mBAAc,SAAS,UAAU,QAAQ;;AAE3C,gCAA4B,cAAc;;;EAG/C"}
1
+ {"version":3,"file":"visible.js","names":[],"sources":["../../../src/hydration/visible.ts"],"sourcesContent":["import type { HydrationPrefetchStrategy } from './types'\n\nconst visibleType = 'visible'\n\nexport type VisibleHydrationOptions = {\n rootMargin?: string\n threshold?: number | Array<number>\n}\n\ntype VisibleObserverEntry = {\n key: string\n observer: IntersectionObserver\n elements: Map<Element, Set<() => void>>\n}\n\nconst observerRegistry = /* @__PURE__ */ new Map<string, VisibleObserverEntry>()\n\nfunction cleanupVisibleObserverEntry(observerEntry: VisibleObserverEntry) {\n if (observerEntry.elements.size > 0) return\n observerEntry.observer.disconnect()\n observerRegistry.delete(observerEntry.key)\n}\n\n/* @__NO_SIDE_EFFECTS__ */\nexport function visible(\n options: VisibleHydrationOptions = {},\n): HydrationPrefetchStrategy<typeof visibleType> {\n const rootMargin = options.rootMargin ?? '600px'\n const threshold = options.threshold ?? 0\n\n return {\n _t: visibleType,\n _s: ({ element, gate, prefetch }) => {\n const callback = prefetch ?? gate!.resolve\n\n if (!element) {\n callback()\n return\n }\n\n const key = `${rootMargin}|${\n Array.isArray(threshold) ? threshold.join(',') : String(threshold)\n }`\n let observerEntry = observerRegistry.get(key)\n\n if (!observerEntry) {\n const entry: VisibleObserverEntry = {\n key,\n elements: new Map<Element, Set<() => void>>(),\n observer: new IntersectionObserver(\n (entries) => {\n for (const intersectingEntry of entries) {\n if (!intersectingEntry.isIntersecting) continue\n\n const callbacks = entry.elements.get(intersectingEntry.target)\n if (!callbacks) continue\n\n callbacks.forEach((callback) => callback())\n entry.elements.delete(intersectingEntry.target)\n entry.observer.unobserve(intersectingEntry.target)\n cleanupVisibleObserverEntry(entry)\n }\n },\n { rootMargin, threshold },\n ),\n }\n observerRegistry.set(key, entry)\n observerEntry = entry\n }\n\n let callbacks = observerEntry.elements.get(element)\n if (!callbacks) {\n callbacks = new Set()\n observerEntry.elements.set(element, callbacks)\n observerEntry.observer.observe(element)\n }\n callbacks.add(callback)\n\n return () => {\n const currentCallbacks = observerEntry.elements.get(element)\n currentCallbacks?.delete(callback)\n if (currentCallbacks?.size === 0) {\n observerEntry.elements.delete(element)\n observerEntry.observer.unobserve(element)\n }\n cleanupVisibleObserverEntry(observerEntry)\n }\n },\n }\n}\n"],"mappings":";AAEA,IAAM,cAAc;AAapB,IAAM,mCAAmC,IAAI,IAAkC;AAE/E,SAAS,4BAA4B,eAAqC;CACxE,IAAI,cAAc,SAAS,OAAO,GAAG;CACrC,cAAc,SAAS,WAAW;CAClC,iBAAiB,OAAO,cAAc,GAAG;AAC3C;;AAGA,SAAgB,QACd,UAAmC,CAAC,GACW;CAC/C,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,YAAY,QAAQ,aAAa;CAEvC,OAAO;EACL,IAAI;EACJ,KAAK,EAAE,SAAS,MAAM,eAAe;GACnC,MAAM,WAAW,YAAY,KAAM;GAEnC,IAAI,CAAC,SAAS;IACZ,SAAS;IACT;GACF;GAEA,MAAM,MAAM,GAAG,WAAW,GACxB,MAAM,QAAQ,SAAS,IAAI,UAAU,KAAK,GAAG,IAAI,OAAO,SAAS;GAEnE,IAAI,gBAAgB,iBAAiB,IAAI,GAAG;GAE5C,IAAI,CAAC,eAAe;IAClB,MAAM,QAA8B;KAClC;KACA,0BAAU,IAAI,IAA8B;KAC5C,UAAU,IAAI,sBACX,YAAY;MACX,KAAK,MAAM,qBAAqB,SAAS;OACvC,IAAI,CAAC,kBAAkB,gBAAgB;OAEvC,MAAM,YAAY,MAAM,SAAS,IAAI,kBAAkB,MAAM;OAC7D,IAAI,CAAC,WAAW;OAEhB,UAAU,SAAS,aAAa,SAAS,CAAC;OAC1C,MAAM,SAAS,OAAO,kBAAkB,MAAM;OAC9C,MAAM,SAAS,UAAU,kBAAkB,MAAM;OACjD,4BAA4B,KAAK;MACnC;KACF,GACA;MAAE;MAAY;KAAU,CAC1B;IACF;IACA,iBAAiB,IAAI,KAAK,KAAK;IAC/B,gBAAgB;GAClB;GAEA,IAAI,YAAY,cAAc,SAAS,IAAI,OAAO;GAClD,IAAI,CAAC,WAAW;IACd,4BAAY,IAAI,IAAI;IACpB,cAAc,SAAS,IAAI,SAAS,SAAS;IAC7C,cAAc,SAAS,QAAQ,OAAO;GACxC;GACA,UAAU,IAAI,QAAQ;GAEtB,aAAa;IACX,MAAM,mBAAmB,cAAc,SAAS,IAAI,OAAO;IAC3D,kBAAkB,OAAO,QAAQ;IACjC,IAAI,kBAAkB,SAAS,GAAG;KAChC,cAAc,SAAS,OAAO,OAAO;KACrC,cAAc,SAAS,UAAU,OAAO;IAC1C;IACA,4BAA4B,aAAa;GAC3C;EACF;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"safeObjectMerge.js","names":[],"sources":["../../src/safeObjectMerge.ts"],"sourcesContent":["function isSafeKey(key: string): boolean {\n return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'\n}\n\n/**\n * Merge target and source into a new null-proto object, filtering dangerous keys.\n */\nexport function safeObjectMerge<T extends Record<string, unknown>>(\n target: T | undefined,\n source: Record<string, unknown> | null | undefined,\n): T {\n const result = Object.create(null) as T\n if (target) {\n for (const key of Object.keys(target)) {\n if (isSafeKey(key)) result[key as keyof T] = target[key] as T[keyof T]\n }\n }\n if (source && typeof source === 'object') {\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) result[key as keyof T] = source[key] as T[keyof T]\n }\n }\n return result\n}\n\n/**\n * Create a null-prototype object, optionally copying from source.\n */\nexport function createNullProtoObject<T extends object>(\n source?: T,\n): { [K in keyof T]: T[K] } {\n if (!source) return Object.create(null)\n const obj = Object.create(null)\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) obj[key] = (source as Record<string, unknown>)[key]\n }\n return obj\n}\n"],"mappings":";AAAA,SAAS,UAAU,KAAsB;AACvC,QAAO,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ;;;;;AAMjE,SAAgB,gBACd,QACA,QACG;CACH,MAAM,SAAS,OAAO,OAAO,KAAK;AAClC,KAAI;OACG,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,QAAO,OAAkB,OAAO;;AAGxD,KAAI,UAAU,OAAO,WAAW;OACzB,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,QAAO,OAAkB,OAAO;;AAGxD,QAAO;;;;;AAMT,SAAgB,sBACd,QAC0B;AAC1B,KAAI,CAAC,OAAQ,QAAO,OAAO,OAAO,KAAK;CACvC,MAAM,MAAM,OAAO,OAAO,KAAK;AAC/B,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,UAAU,IAAI,CAAE,KAAI,OAAQ,OAAmC;AAErE,QAAO"}
1
+ {"version":3,"file":"safeObjectMerge.js","names":[],"sources":["../../src/safeObjectMerge.ts"],"sourcesContent":["function isSafeKey(key: string): boolean {\n return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'\n}\n\n/**\n * Merge target and source into a new null-proto object, filtering dangerous keys.\n */\nexport function safeObjectMerge<T extends Record<string, unknown>>(\n target: T | undefined,\n source: Record<string, unknown> | null | undefined,\n): T {\n const result = Object.create(null) as T\n if (target) {\n for (const key of Object.keys(target)) {\n if (isSafeKey(key)) result[key as keyof T] = target[key] as T[keyof T]\n }\n }\n if (source && typeof source === 'object') {\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) result[key as keyof T] = source[key] as T[keyof T]\n }\n }\n return result\n}\n\n/**\n * Create a null-prototype object, optionally copying from source.\n */\nexport function createNullProtoObject<T extends object>(\n source?: T,\n): { [K in keyof T]: T[K] } {\n if (!source) return Object.create(null)\n const obj = Object.create(null)\n for (const key of Object.keys(source)) {\n if (isSafeKey(key)) obj[key] = (source as Record<string, unknown>)[key]\n }\n return obj\n}\n"],"mappings":";AAAA,SAAS,UAAU,KAAsB;CACvC,OAAO,QAAQ,eAAe,QAAQ,iBAAiB,QAAQ;AACjE;;;;AAKA,SAAgB,gBACd,QACA,QACG;CACH,MAAM,SAAS,OAAO,OAAO,IAAI;CACjC,IAAI;OACG,MAAM,OAAO,OAAO,KAAK,MAAM,GAClC,IAAI,UAAU,GAAG,GAAG,OAAO,OAAkB,OAAO;CAAA;CAGxD,IAAI,UAAU,OAAO,WAAW;OACzB,MAAM,OAAO,OAAO,KAAK,MAAM,GAClC,IAAI,UAAU,GAAG,GAAG,OAAO,OAAkB,OAAO;CAAA;CAGxD,OAAO;AACT;;;;AAKA,SAAgB,sBACd,QAC0B;CAC1B,IAAI,CAAC,QAAQ,OAAO,OAAO,OAAO,IAAI;CACtC,MAAM,MAAM,OAAO,OAAO,IAAI;CAC9B,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,GAClC,IAAI,UAAU,GAAG,GAAG,IAAI,OAAQ,OAAmC;CAErE,OAAO;AACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-client-core",
3
- "version": "1.170.2",
3
+ "version": "1.170.4",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -75,7 +75,7 @@
75
75
  },
76
76
  "#tanstack-start-plugin-adapters": {
77
77
  "types": "./src/start-entry.d.ts",
78
- "default": "./dist/esm/fake-entries/plugin-adapters.js"
78
+ "default": "./dist/esm/empty-plugin-adapters.js"
79
79
  }
80
80
  },
81
81
  "sideEffects": false,
@@ -91,9 +91,9 @@
91
91
  },
92
92
  "dependencies": {
93
93
  "seroval": "^1.5.4",
94
- "@tanstack/router-core": "1.171.5",
94
+ "@tanstack/router-core": "1.171.6",
95
95
  "@tanstack/start-fn-stubs": "1.162.0",
96
- "@tanstack/start-storage-context": "1.167.7"
96
+ "@tanstack/start-storage-context": "1.167.8"
97
97
  },
98
98
  "devDependencies": {
99
99
  "vite": "*",
@@ -1 +0,0 @@
1
- {"version":3,"file":"plugin-adapters.js","names":[],"sources":["../../../src/fake-entries/plugin-adapters.ts"],"sourcesContent":["import type { AnySerializationAdapter } from '@tanstack/router-core'\n\nexport const pluginSerializationAdapters: Array<AnySerializationAdapter> = []\nexport const hasPluginAdapters = false\n"],"mappings":";AAEA,IAAa,8BAA8D,EAAE;AAC7E,IAAa,oBAAoB"}