@tanstack/start-server-core 1.169.2 → 1.169.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 (38) hide show
  1. package/dist/esm/constants.js.map +1 -1
  2. package/dist/esm/createServerRpc.js.map +1 -1
  3. package/dist/esm/createSsrRpc.js.map +1 -1
  4. package/dist/esm/createStartHandler.js +1 -2
  5. package/dist/esm/createStartHandler.js.map +1 -1
  6. package/dist/esm/early-hints.d.ts +3 -3
  7. package/dist/esm/early-hints.js +16 -21
  8. package/dist/esm/early-hints.js.map +1 -1
  9. package/dist/esm/empty-plugin-adapters.d.ts +3 -0
  10. package/dist/esm/empty-plugin-adapters.js +7 -0
  11. package/dist/esm/empty-plugin-adapters.js.map +1 -0
  12. package/dist/esm/fake-start-server-fn-resolver.js.map +1 -1
  13. package/dist/esm/finalManifest.d.ts +4 -4
  14. package/dist/esm/finalManifest.js.map +1 -1
  15. package/dist/esm/frame-protocol.js.map +1 -1
  16. package/dist/esm/inlineCss.js.map +1 -1
  17. package/dist/esm/request-handler.d.ts +2 -1
  18. package/dist/esm/request-response.js.map +1 -1
  19. package/dist/esm/router-manifest.js +27 -30
  20. package/dist/esm/router-manifest.js.map +1 -1
  21. package/dist/esm/serializer/ServerFunctionSerializationAdapter.js.map +1 -1
  22. package/dist/esm/server-functions-handler.js.map +1 -1
  23. package/dist/esm/transformAssetUrls.d.ts +11 -16
  24. package/dist/esm/transformAssetUrls.js +80 -53
  25. package/dist/esm/transformAssetUrls.js.map +1 -1
  26. package/dist/esm/virtual-modules.d.ts +0 -1
  27. package/dist/esm/virtual-modules.js +0 -1
  28. package/dist/esm/virtual-modules.js.map +1 -1
  29. package/package.json +7 -4
  30. package/src/createStartHandler.ts +0 -1
  31. package/src/early-hints.ts +24 -24
  32. package/src/empty-plugin-adapters.ts +4 -0
  33. package/src/finalManifest.ts +14 -12
  34. package/src/request-handler.ts +2 -1
  35. package/src/router-manifest.ts +45 -47
  36. package/src/tanstack-start.d.ts +2 -6
  37. package/src/transformAssetUrls.ts +160 -91
  38. package/src/virtual-modules.ts +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"transformAssetUrls.js","names":[],"sources":["../../src/transformAssetUrls.ts"],"sourcesContent":["import { resolveManifestAssetLink, rootRouteId } from '@tanstack/router-core'\n\nimport type {\n AssetCrossOrigin,\n Awaitable,\n Manifest,\n ManifestAssetLink,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nexport type { AssetCrossOrigin }\n\nexport type TransformAssetsContext =\n | {\n url: string\n kind: 'modulepreload'\n }\n | {\n url: string\n kind: 'stylesheet'\n }\n | {\n url: string\n kind: 'clientEntry'\n }\n | {\n url: string\n kind: 'css-url'\n stylesheetHref: string\n }\n\nexport type TransformAssetKind = TransformAssetsContext['kind']\n\ntype TransformAssetsShorthandCrossOriginKind = Exclude<\n TransformAssetKind,\n 'clientEntry' | 'css-url'\n>\n\nexport type TransformAssetResult =\n | string\n | {\n href: string\n crossOrigin?: AssetCrossOrigin\n }\n\nexport type TransformAssetsFn = (\n context: TransformAssetsContext,\n) => Awaitable<TransformAssetResult>\n\nexport type CreateTransformAssetsContext =\n | {\n /** True when the server is computing the cached manifest during startup warmup. */\n warmup: true\n }\n | {\n /**\n * The current Request.\n *\n * Only available during request handling (i.e. when `warmup: false`).\n */\n request: Request\n /** False when transforming URLs as part of request handling. */\n warmup: false\n }\n\nexport type CreateTransformAssetsFn = (\n ctx: CreateTransformAssetsContext,\n) => Awaitable<TransformAssetsFn>\n\ntype TransformAssetsOptionsBase = {\n /**\n * Whether to cache the transformed manifest after the first request.\n *\n * When `true` (default), the transform runs once on the first request and\n * the resulting manifest is reused for all subsequent requests in production.\n *\n * Set to `false` for per-request transforms (e.g. geo-routing to different\n * CDNs based on request headers).\n *\n * @default true\n */\n cache?: boolean\n\n /**\n * When `true`, warms up the cached transformed manifest in the background when\n * the server starts (production only).\n *\n * This can reduce latency for the first request when `cache` is `true`.\n * Has no effect when `cache: false` (per-request transforms) or in dev mode.\n *\n * @default false\n */\n warmup?: boolean\n}\n\nexport type TransformAssetsOptions =\n | (TransformAssetsOptionsBase & {\n transform: string | TransformAssetsFn\n createTransform?: never\n })\n | (TransformAssetsOptionsBase & {\n createTransform: CreateTransformAssetsFn\n transform?: never\n })\n\n/**\n * Per-kind crossOrigin configuration for the object shorthand.\n *\n * Accepts either a single value applied to all asset kinds, or a per-kind\n * record (matching `HeadContent`'s `assetCrossOrigin` shape):\n *\n * ```ts\n * // All assets get the same value\n * crossOrigin: 'anonymous'\n *\n * // Different values per kind\n * crossOrigin: { modulepreload: 'anonymous', stylesheet: 'use-credentials' }\n * ```\n */\nexport type TransformAssetsCrossOriginConfig =\n | AssetCrossOrigin\n | Partial<Record<TransformAssetsShorthandCrossOriginKind, AssetCrossOrigin>>\n\n/**\n * Object shorthand for `transformAssets`. Combines a URL prefix with optional\n * per-asset `crossOrigin` without needing a callback:\n *\n * ```ts\n * transformAssets: {\n * prefix: 'https://cdn.example.com',\n * crossOrigin: 'anonymous',\n * }\n * ```\n */\nexport interface TransformAssetsObjectShorthand {\n /** URL prefix prepended to every asset URL. */\n prefix: string\n /**\n * Optional crossOrigin attribute applied to manifest-managed `<link>` assets.\n *\n * Accepts a single value or a per-kind record.\n */\n crossOrigin?: TransformAssetsCrossOriginConfig\n}\n\nexport type TransformAssets =\n | string\n | TransformAssetsFn\n | TransformAssetsObjectShorthand\n | TransformAssetsOptions\n\nexport type ResolvedTransformAssetsConfig =\n | {\n type: 'transform'\n transformFn: TransformAssetsFn\n cache: boolean\n }\n | {\n type: 'createTransform'\n createTransform: CreateTransformAssetsFn\n cache: boolean\n }\n\nfunction normalizeTransformAssetResult(\n result: TransformAssetResult,\n): Exclude<TransformAssetResult, string> {\n if (typeof result === 'string') {\n return { href: result }\n }\n\n return result\n}\n\nfunction escapeCssString(value: string) {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\a ')\n .replace(/\\r/g, '\\\\d ')\n .replace(/\\f/g, '\\\\c ')\n}\n\nasync function transformInlineCssTemplate(options: {\n stylesheetHref: string\n template: { strings: Array<string>; urls: Array<string> }\n transformFn: TransformAssetsFn\n}) {\n const { strings, urls } = options.template\n\n if (strings.length !== urls.length + 1) {\n throw new Error(\n `TanStack Start inlineCss template for ${options.stylesheetHref} is invalid`,\n )\n }\n\n let css = strings[0]!\n\n for (let index = 0; index < urls.length; index++) {\n const transformed = normalizeTransformAssetResult(\n await options.transformFn({\n kind: 'css-url',\n url: urls[index]!,\n stylesheetHref: options.stylesheetHref,\n }),\n )\n\n css += escapeCssString(transformed.href) + strings[index + 1]!\n }\n\n return css\n}\n\nasync function transformInlineCssStyles(\n inlineCss: NonNullable<Manifest['inlineCss']>,\n transformFn: TransformAssetsFn,\n) {\n const transformedStyles: Record<string, string> = {}\n\n const transformedEntries = await Promise.all(\n Object.entries(inlineCss.styles).map(async ([stylesheetHref, css]) => {\n const template = inlineCss.templates?.[stylesheetHref]\n return [\n stylesheetHref,\n template\n ? await transformInlineCssTemplate({\n stylesheetHref,\n template,\n transformFn,\n })\n : css,\n ] as const\n }),\n )\n\n for (const [stylesheetHref, css] of transformedEntries) {\n transformedStyles[stylesheetHref] = css\n }\n\n return {\n styles: transformedStyles,\n ...(inlineCss.templates ? { templates: inlineCss.templates } : {}),\n }\n}\n\nfunction resolveTransformAssetsCrossOrigin(\n config: TransformAssetsCrossOriginConfig | undefined,\n kind: TransformAssetsShorthandCrossOriginKind,\n): AssetCrossOrigin | undefined {\n if (!config) return undefined\n if (typeof config === 'string') return config\n\n return config[kind]\n}\n\nfunction isObjectShorthand(\n transform: TransformAssetsObjectShorthand | TransformAssetsOptions,\n): transform is TransformAssetsObjectShorthand {\n return 'prefix' in transform\n}\n\nexport function resolveTransformAssetsConfig(\n transform: TransformAssets,\n): ResolvedTransformAssetsConfig {\n if (typeof transform === 'string') {\n const prefix = transform\n return {\n type: 'transform',\n transformFn: ({ url }) => ({ href: `${prefix}${url}` }),\n cache: true,\n }\n }\n\n if (typeof transform === 'function') {\n return {\n type: 'transform',\n transformFn: transform,\n cache: true,\n }\n }\n\n // Object shorthand: { prefix, crossOrigin? }\n if (isObjectShorthand(transform)) {\n const { prefix, crossOrigin } = transform\n\n return {\n type: 'transform',\n transformFn: ({ url, kind }) => {\n const href = `${prefix}${url}`\n\n if (kind === 'clientEntry' || kind === 'css-url') {\n return { href }\n }\n\n const co = resolveTransformAssetsCrossOrigin(crossOrigin, kind)\n return co ? { href, crossOrigin: co } : { href }\n },\n cache: true,\n }\n }\n\n if ('createTransform' in transform && transform.createTransform) {\n return {\n type: 'createTransform',\n createTransform: transform.createTransform,\n cache: transform.cache !== false,\n }\n }\n\n const transformFn =\n typeof transform.transform === 'string'\n ? ((({ url }: TransformAssetsContext) => ({\n href: `${transform.transform}${url}`,\n })) as TransformAssetsFn)\n : transform.transform\n\n return {\n type: 'transform',\n transformFn,\n cache: transform.cache !== false,\n }\n}\n\nexport interface StartManifestWithClientEntry {\n manifest: Manifest\n clientEntry: string\n /** Script content prepended before the client entry import (dev only) */\n injectedHeadScripts?: string\n}\n\n/**\n * Builds the client entry `<script>` tag from a (possibly transformed) client\n * entry URL and optional injected head scripts.\n */\nexport function buildClientEntryScriptTag(\n clientEntry: string,\n injectedHeadScripts?: string,\n): RouterManagedTag {\n const clientEntryLiteral = JSON.stringify(clientEntry)\n let script = `import(${clientEntryLiteral})`\n if (injectedHeadScripts) {\n script = `${injectedHeadScripts};${script}`\n }\n return {\n tag: 'script',\n attrs: {\n type: 'module',\n async: true,\n },\n children: script,\n }\n}\n\nfunction assignManifestAssetLink(\n link: ManifestAssetLink,\n next: { href: string; crossOrigin?: AssetCrossOrigin },\n): ManifestAssetLink {\n if (typeof link === 'string') {\n return next.crossOrigin ? next : next.href\n }\n\n return next.crossOrigin ? next : { href: next.href }\n}\n\nexport async function transformManifestAssets(\n source: StartManifestWithClientEntry,\n transformFn: TransformAssetsFn,\n _opts?: {\n clone?: boolean\n inlineCss?: boolean\n },\n): Promise<Manifest> {\n const manifest = structuredClone(source.manifest)\n const inlineCssEnabled = _opts?.inlineCss !== false\n\n if (!inlineCssEnabled) {\n delete manifest.inlineCss\n } else if (manifest.inlineCss) {\n manifest.inlineCss = await transformInlineCssStyles(\n manifest.inlineCss,\n transformFn,\n )\n }\n\n for (const route of Object.values(manifest.routes)) {\n if (route.preloads) {\n route.preloads = await Promise.all(\n route.preloads.map(async (link) => {\n const resolved = resolveManifestAssetLink(link)\n const result = normalizeTransformAssetResult(\n await transformFn({\n url: resolved.href,\n kind: 'modulepreload',\n }),\n )\n\n return assignManifestAssetLink(link, {\n href: result.href,\n crossOrigin: result.crossOrigin,\n })\n }),\n )\n }\n\n if (route.assets && !manifest.inlineCss) {\n for (const asset of route.assets) {\n if (asset.tag === 'link' && asset.attrs?.href) {\n const rel = asset.attrs.rel\n const relTokens = typeof rel === 'string' ? rel.split(/\\s+/) : []\n\n if (!relTokens.includes('stylesheet')) {\n continue\n }\n\n const result = normalizeTransformAssetResult(\n await transformFn({\n url: asset.attrs.href,\n kind: 'stylesheet',\n }),\n )\n\n asset.attrs.href = result.href\n if (result.crossOrigin) {\n asset.attrs.crossOrigin = result.crossOrigin\n } else {\n delete asset.attrs.crossOrigin\n }\n }\n }\n }\n }\n\n const transformedClientEntry = normalizeTransformAssetResult(\n await transformFn({\n url: source.clientEntry,\n kind: 'clientEntry',\n }),\n )\n\n const rootRoute = (manifest.routes[rootRouteId] =\n manifest.routes[rootRouteId] || {})\n rootRoute.assets = rootRoute.assets || []\n rootRoute.assets.push(\n buildClientEntryScriptTag(\n transformedClientEntry.href,\n source.injectedHeadScripts,\n ),\n )\n\n return manifest\n}\n\n/**\n * Builds a final Manifest from a StartManifestWithClientEntry without any\n * URL transforms. Used when no transformAssets option is provided.\n *\n * Returns a new manifest object so the cached base manifest is never mutated.\n */\nexport function buildManifestWithClientEntry(\n source: StartManifestWithClientEntry,\n opts?: { inlineCss?: boolean },\n): Manifest {\n const scriptTag = buildClientEntryScriptTag(\n source.clientEntry,\n source.injectedHeadScripts,\n )\n\n const baseRootRoute = source.manifest.routes[rootRouteId]\n const routes = {\n ...source.manifest.routes,\n [rootRouteId]: {\n ...baseRootRoute,\n assets: [...(baseRootRoute?.assets || []), scriptTag],\n },\n }\n\n return {\n ...(opts?.inlineCss === false\n ? {}\n : { inlineCss: structuredClone(source.manifest.inlineCss) }),\n routes,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"transformAssetUrls.js","names":[],"sources":["../../src/transformAssetUrls.ts"],"sourcesContent":["import {\n getManifestScriptFormat,\n resolveManifestAssetLink,\n resolveManifestCssLink,\n} from '@tanstack/router-core'\n\nimport type {\n AssetCrossOrigin,\n Awaitable,\n ManifestAssetLink,\n ManifestCssLink,\n ManifestScript,\n ScriptFormat,\n ServerManifest,\n} from '@tanstack/router-core'\n\nexport type { AssetCrossOrigin }\n\nexport type TransformAssetsContext =\n | {\n url: string\n kind: 'script'\n }\n | {\n url: string\n kind: 'stylesheet'\n }\n | {\n url: string\n kind: 'css-url'\n stylesheetHref: string\n }\n\nexport type TransformAssetKind = TransformAssetsContext['kind']\n\ntype TransformAssetsShorthandCrossOriginKind = Exclude<\n TransformAssetKind,\n 'css-url'\n>\n\nexport type TransformAssetResult =\n | string\n | {\n href: string\n crossOrigin?: AssetCrossOrigin\n }\n\nexport type TransformAssetsFn = (\n context: TransformAssetsContext,\n) => Awaitable<TransformAssetResult>\n\nexport type CreateTransformAssetsContext =\n | {\n /** True when the server is computing the cached manifest during startup warmup. */\n warmup: true\n }\n | {\n /**\n * The current Request.\n *\n * Only available during request handling (i.e. when `warmup: false`).\n */\n request: Request\n /** False when transforming URLs as part of request handling. */\n warmup: false\n }\n\nexport type CreateTransformAssetsFn = (\n ctx: CreateTransformAssetsContext,\n) => Awaitable<TransformAssetsFn>\n\ntype TransformAssetsOptionsBase = {\n /**\n * Whether to cache the transformed manifest after the first request.\n *\n * When `true` (default), the transform runs once on the first request and\n * the resulting manifest is reused for all subsequent requests in production.\n *\n * Set to `false` for per-request transforms (e.g. geo-routing to different\n * CDNs based on request headers).\n *\n * @default true\n */\n cache?: boolean\n\n /**\n * When `true`, warms up the cached transformed manifest in the background when\n * the server starts (production only).\n *\n * This can reduce latency for the first request when `cache` is `true`.\n * Has no effect when `cache: false` (per-request transforms) or in dev mode.\n *\n * @default false\n */\n warmup?: boolean\n}\n\nexport type TransformAssetsOptions =\n | (TransformAssetsOptionsBase & {\n transform: string | TransformAssetsFn\n createTransform?: never\n })\n | (TransformAssetsOptionsBase & {\n createTransform: CreateTransformAssetsFn\n transform?: never\n })\n\n/**\n * Per-kind crossOrigin configuration for the object shorthand.\n *\n * Accepts either a single value applied to all asset kinds, or a per-kind\n * record (matching `HeadContent`'s `assetCrossOrigin` shape):\n *\n * ```ts\n * // All assets get the same value\n * crossOrigin: 'anonymous'\n *\n * // Different values per kind\n * crossOrigin: { script: 'anonymous', stylesheet: 'use-credentials' }\n * ```\n */\nexport type TransformAssetsCrossOriginConfig =\n | AssetCrossOrigin\n | Partial<Record<TransformAssetsShorthandCrossOriginKind, AssetCrossOrigin>>\n\n/**\n * Object shorthand for `transformAssets`. Combines a URL prefix with optional\n * per-asset `crossOrigin` without needing a callback:\n *\n * ```ts\n * transformAssets: {\n * prefix: 'https://cdn.example.com',\n * crossOrigin: 'anonymous',\n * }\n * ```\n */\nexport interface TransformAssetsObjectShorthand {\n /** URL prefix prepended to every asset URL. */\n prefix: string\n /**\n * Optional crossOrigin attribute applied to transformed script and stylesheet assets.\n *\n * Accepts a single value or a per-kind record.\n */\n crossOrigin?: TransformAssetsCrossOriginConfig\n}\n\nexport type TransformAssets =\n | string\n | TransformAssetsFn\n | TransformAssetsObjectShorthand\n | TransformAssetsOptions\n\nexport type ResolvedTransformAssetsConfig =\n | {\n type: 'transform'\n transformFn: TransformAssetsFn\n cache: boolean\n }\n | {\n type: 'createTransform'\n createTransform: CreateTransformAssetsFn\n cache: boolean\n }\n\nfunction normalizeTransformAssetResult(\n result: TransformAssetResult,\n): Exclude<TransformAssetResult, string> {\n if (typeof result === 'string') {\n return { href: result }\n }\n\n return result\n}\n\nfunction escapeCssString(value: string) {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\a ')\n .replace(/\\r/g, '\\\\d ')\n .replace(/\\f/g, '\\\\c ')\n}\n\nasync function transformInlineCssTemplate(options: {\n stylesheetHref: string\n template: { strings: Array<string>; urls: Array<string> }\n transformFn: TransformAssetsFn\n}) {\n const { strings, urls } = options.template\n\n if (strings.length !== urls.length + 1) {\n throw new Error(\n `TanStack Start inlineCss template for ${options.stylesheetHref} is invalid`,\n )\n }\n\n let css = strings[0]!\n\n for (let index = 0; index < urls.length; index++) {\n const transformed = normalizeTransformAssetResult(\n await options.transformFn({\n kind: 'css-url',\n url: urls[index]!,\n stylesheetHref: options.stylesheetHref,\n }),\n )\n\n css += escapeCssString(transformed.href) + strings[index + 1]!\n }\n\n return css\n}\n\nasync function transformInlineCssStyles(\n inlineCss: NonNullable<ServerManifest['inlineCss']>,\n transformFn: TransformAssetsFn,\n) {\n const transformedStyles: Record<string, string> = {}\n\n const transformedEntries = await Promise.all(\n Object.entries(inlineCss.styles).map(async ([stylesheetHref, css]) => {\n const template = inlineCss.templates?.[stylesheetHref]\n return [\n stylesheetHref,\n template\n ? await transformInlineCssTemplate({\n stylesheetHref,\n template,\n transformFn,\n })\n : css,\n ] as const\n }),\n )\n\n for (const [stylesheetHref, css] of transformedEntries) {\n transformedStyles[stylesheetHref] = css\n }\n\n return {\n styles: transformedStyles,\n ...(inlineCss.templates ? { templates: inlineCss.templates } : {}),\n }\n}\n\nfunction resolveTransformAssetsCrossOrigin(\n config: TransformAssetsCrossOriginConfig | undefined,\n kind: TransformAssetsShorthandCrossOriginKind,\n): AssetCrossOrigin | undefined {\n if (!config) return undefined\n if (typeof config === 'string') return config\n\n return config[kind]\n}\n\nfunction isObjectShorthand(\n transform: TransformAssetsObjectShorthand | TransformAssetsOptions,\n): transform is TransformAssetsObjectShorthand {\n return 'prefix' in transform\n}\n\nexport function resolveTransformAssetsConfig(\n transform: TransformAssets,\n): ResolvedTransformAssetsConfig {\n if (typeof transform === 'string') {\n const prefix = transform\n return {\n type: 'transform',\n transformFn: ({ url }) => ({ href: `${prefix}${url}` }),\n cache: true,\n }\n }\n\n if (typeof transform === 'function') {\n return {\n type: 'transform',\n transformFn: transform,\n cache: true,\n }\n }\n\n // Object shorthand: { prefix, crossOrigin? }\n if (isObjectShorthand(transform)) {\n const { prefix, crossOrigin } = transform\n\n return {\n type: 'transform',\n transformFn: ({ url, kind }) => {\n const href = `${prefix}${url}`\n\n if (kind === 'css-url') {\n return { href }\n }\n\n const co = resolveTransformAssetsCrossOrigin(crossOrigin, kind)\n return co ? { href, crossOrigin: co } : { href }\n },\n cache: true,\n }\n }\n\n if ('createTransform' in transform && transform.createTransform) {\n return {\n type: 'createTransform',\n createTransform: transform.createTransform,\n cache: transform.cache !== false,\n }\n }\n\n const transformFn =\n typeof transform.transform === 'string'\n ? ((({ url }: TransformAssetsContext) => ({\n href: `${transform.transform}${url}`,\n })) as TransformAssetsFn)\n : transform.transform\n\n return {\n type: 'transform',\n transformFn,\n cache: transform.cache !== false,\n }\n}\n\nexport interface StartManifestWithClientEntry {\n manifest: ServerManifest\n clientEntry: string\n}\n\n/**\n * Builds the client entry `<script>` tag from a (possibly transformed) client\n * entry URL.\n */\nexport function buildClientEntryScriptTag(\n clientEntry: string,\n scriptFormat: ScriptFormat = 'module',\n crossOrigin?: AssetCrossOrigin,\n): ManifestScript {\n return {\n attrs: {\n ...(scriptFormat === 'module' ? { type: 'module' } : {}),\n async: true,\n src: clientEntry,\n ...(crossOrigin ? { crossOrigin } : {}),\n },\n }\n}\n\ntype AssignableManifestLink = ManifestAssetLink | ManifestCssLink\n\nfunction assignManifestLink(\n link: ManifestAssetLink,\n next: { href: string; crossOrigin?: AssetCrossOrigin },\n): ManifestAssetLink\nfunction assignManifestLink(\n link: ManifestCssLink,\n next: { href: string; crossOrigin?: AssetCrossOrigin },\n): ManifestCssLink\nfunction assignManifestLink(\n link: AssignableManifestLink,\n next: { href: string; crossOrigin?: AssetCrossOrigin },\n): AssignableManifestLink {\n if (typeof link === 'string') {\n return next.crossOrigin ? next : next.href\n }\n\n const nextLink: Exclude<ManifestCssLink, string> = {\n ...link,\n href: next.href,\n }\n\n if (next.crossOrigin) {\n nextLink.crossOrigin = next.crossOrigin\n } else {\n delete nextLink.crossOrigin\n }\n\n return nextLink\n}\n\nfunction appendUniqueManifestAssetLink(\n target: Array<ManifestAssetLink> | undefined,\n link: ManifestAssetLink,\n) {\n const href = typeof link === 'string' ? link : link.href\n\n if (target) {\n for (const item of target) {\n if ((typeof item === 'string' ? item : item.href) === href) {\n return target\n }\n }\n }\n\n return [...(target ?? []), link]\n}\n\nfunction addClientEntryToManifest(\n manifest: ServerManifest,\n clientEntry: string,\n) {\n const rootRoute = manifest.routes.__root__ ?? {}\n const rootScripts = rootRoute.scripts ?? []\n const scripts = rootScripts.some(\n (script) => script.attrs?.src === clientEntry,\n )\n ? rootScripts\n : [\n ...rootScripts,\n buildClientEntryScriptTag(\n clientEntry,\n getManifestScriptFormat(manifest),\n ),\n ]\n\n manifest.routes = {\n ...manifest.routes,\n __root__: {\n ...rootRoute,\n preloads: appendUniqueManifestAssetLink(rootRoute.preloads, clientEntry),\n scripts,\n },\n }\n}\n\nexport async function transformManifestAssets(\n source: StartManifestWithClientEntry,\n transformFn: TransformAssetsFn,\n _opts?: {\n clone?: boolean\n inlineCss?: boolean\n },\n): Promise<ServerManifest> {\n const manifest = structuredClone(source.manifest)\n const inlineCssEnabled = _opts?.inlineCss !== false\n const scriptTransforms = new Map<\n string,\n Promise<Exclude<TransformAssetResult, string>>\n >()\n const transformScript = (url: string) => {\n const cached = scriptTransforms.get(url)\n if (cached) {\n return cached\n }\n\n const transformed = Promise.resolve(\n transformFn({\n url,\n kind: 'script',\n }),\n ).then(normalizeTransformAssetResult)\n scriptTransforms.set(url, transformed)\n return transformed\n }\n\n if (!inlineCssEnabled) {\n delete manifest.inlineCss\n } else if (manifest.inlineCss) {\n manifest.inlineCss = await transformInlineCssStyles(\n manifest.inlineCss,\n transformFn,\n )\n }\n\n addClientEntryToManifest(manifest, source.clientEntry)\n\n for (const route of Object.values(manifest.routes)) {\n if (route.preloads?.length) {\n route.preloads = await Promise.all(\n route.preloads.map(async (link) => {\n const resolved = resolveManifestAssetLink(link)\n const result = await transformScript(resolved.href)\n\n return assignManifestLink(link, {\n href: result.href,\n crossOrigin: result.crossOrigin,\n })\n }),\n )\n }\n\n if (route.css?.length && !manifest.inlineCss) {\n route.css = await Promise.all(\n route.css.map(async (link) => {\n const resolved = resolveManifestCssLink(link)\n const result = normalizeTransformAssetResult(\n await transformFn({\n url: resolved.href,\n kind: 'stylesheet',\n }),\n )\n\n return assignManifestLink(link, {\n href: result.href,\n crossOrigin: result.crossOrigin,\n })\n }),\n )\n }\n\n if (route.scripts?.length) {\n for (const script of route.scripts) {\n const src = script.attrs?.src\n if (typeof src !== 'string') {\n continue\n }\n\n const result = await transformScript(src)\n\n script.attrs = {\n ...script.attrs,\n src: result.href,\n }\n if (result.crossOrigin) {\n script.attrs.crossOrigin = result.crossOrigin\n } else {\n delete script.attrs.crossOrigin\n }\n }\n }\n }\n\n return manifest\n}\n\n/**\n * Builds a final ServerManifest from a StartManifestWithClientEntry without any\n * URL transforms. Used when no transformAssets option is provided.\n *\n * Returns a new manifest object so the cached base manifest is never mutated.\n */\nexport function buildManifestWithClientEntry(\n source: StartManifestWithClientEntry,\n opts?: { inlineCss?: boolean },\n): ServerManifest {\n const manifest: ServerManifest = {\n ...(source.manifest.scriptFormat\n ? { scriptFormat: source.manifest.scriptFormat }\n : {}),\n ...(opts?.inlineCss !== false && source.manifest.inlineCss\n ? { inlineCss: structuredClone(source.manifest.inlineCss) }\n : {}),\n routes: {\n ...source.manifest.routes,\n },\n }\n\n addClientEntryToManifest(manifest, source.clientEntry)\n\n return manifest\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
1
  export declare const VIRTUAL_MODULES: {
2
2
  readonly startManifest: "tanstack-start-manifest:v";
3
- readonly injectedHeadScripts: "tanstack-start-injected-head-scripts:v";
4
3
  readonly serverFnResolver: "#tanstack-start-server-fn-resolver";
5
4
  readonly pluginAdapters: "#tanstack-start-plugin-adapters";
6
5
  };
@@ -1,7 +1,6 @@
1
1
  //#region src/virtual-modules.ts
2
2
  var VIRTUAL_MODULES = {
3
3
  startManifest: "tanstack-start-manifest:v",
4
- injectedHeadScripts: "tanstack-start-injected-head-scripts:v",
5
4
  serverFnResolver: "#tanstack-start-server-fn-resolver",
6
5
  pluginAdapters: "#tanstack-start-plugin-adapters"
7
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"virtual-modules.js","names":[],"sources":["../../src/virtual-modules.ts"],"sourcesContent":["export const VIRTUAL_MODULES = {\n startManifest: 'tanstack-start-manifest:v',\n injectedHeadScripts: 'tanstack-start-injected-head-scripts:v',\n serverFnResolver: '#tanstack-start-server-fn-resolver',\n pluginAdapters: '#tanstack-start-plugin-adapters',\n} as const\n"],"mappings":";AAAA,IAAa,kBAAkB;CAC7B,eAAe;CACf,qBAAqB;CACrB,kBAAkB;CAClB,gBAAgB;CACjB"}
1
+ {"version":3,"file":"virtual-modules.js","names":[],"sources":["../../src/virtual-modules.ts"],"sourcesContent":["export const VIRTUAL_MODULES = {\n startManifest: 'tanstack-start-manifest:v',\n serverFnResolver: '#tanstack-start-server-fn-resolver',\n pluginAdapters: '#tanstack-start-plugin-adapters',\n} as const\n"],"mappings":";AAAA,IAAa,kBAAkB;CAC7B,eAAe;CACf,kBAAkB;CAClB,gBAAgB;AAClB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-server-core",
3
- "version": "1.169.2",
3
+ "version": "1.169.4",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -49,6 +49,9 @@
49
49
  "imports": {
50
50
  "#tanstack-start-server-fn-resolver": {
51
51
  "default": "./dist/esm/fake-start-server-fn-resolver.js"
52
+ },
53
+ "#tanstack-start-plugin-adapters": {
54
+ "default": "./dist/esm/empty-plugin-adapters.js"
52
55
  }
53
56
  },
54
57
  "sideEffects": false,
@@ -67,9 +70,9 @@
67
70
  "h3-v2": "npm:h3@2.0.1-rc.20",
68
71
  "seroval": "^1.5.4",
69
72
  "@tanstack/history": "1.162.0",
70
- "@tanstack/router-core": "1.171.5",
71
- "@tanstack/start-client-core": "1.170.2",
72
- "@tanstack/start-storage-context": "1.167.7"
73
+ "@tanstack/router-core": "1.171.6",
74
+ "@tanstack/start-client-core": "1.170.4",
75
+ "@tanstack/start-storage-context": "1.167.8"
73
76
  },
74
77
  "devDependencies": {
75
78
  "@standard-schema/spec": "^1.0.0",
@@ -497,7 +497,6 @@ export function createStartHandler<TRegister = Register>(
497
497
  manifest,
498
498
  getRequestAssets: () =>
499
499
  getStartContext({ throwIfNotFound: false })?.requestAssets,
500
- includeUnmatchedRouteAssets: false,
501
500
  })
502
501
 
503
502
  routerInstance.update({ additionalContext: { serverContext } })
@@ -1,13 +1,14 @@
1
1
  import {
2
+ getScriptPreloadAttrs,
2
3
  getStylesheetHref,
3
- resolveManifestAssetLink,
4
+ resolveManifestCssLink,
4
5
  } from '@tanstack/router-core'
5
6
  import type {
6
7
  AnyRoute,
7
8
  AnyRouteMatch,
8
9
  AssetCrossOrigin,
9
- Manifest,
10
10
  RouterManagedTag,
11
+ ServerManifest,
11
12
  } from '@tanstack/router-core'
12
13
 
13
14
  export type EarlyHint = {
@@ -49,7 +50,7 @@ export type ResponseLinkHeaderOptions = {
49
50
 
50
51
  export interface EarlyHintsCollector {
51
52
  collectStatic: (opts: {
52
- manifest: Manifest
53
+ manifest: ServerManifest
53
54
  matchedRoutes?: ReadonlyArray<AnyRoute>
54
55
  }) => void
55
56
  collectDynamic: (matches: ReadonlyArray<AnyRouteMatch>) => void
@@ -174,7 +175,7 @@ function linkAttrsToEarlyHint(
174
175
  }
175
176
 
176
177
  export function collectStaticHintsFromManifest(
177
- manifest: Manifest,
178
+ manifest: ServerManifest,
178
179
  matchedRoutes: ReadonlyArray<AnyRoute>,
179
180
  ): Array<EarlyHint> {
180
181
  const hints: Array<EarlyHint> = []
@@ -184,33 +185,32 @@ export function collectStaticHintsFromManifest(
184
185
  if (!routeManifest) continue
185
186
 
186
187
  for (const link of routeManifest.preloads ?? []) {
187
- const { href, crossOrigin } = resolveManifestAssetLink(link)
188
- const hint: EarlyHint = { href, rel: 'modulepreload', as: 'script' }
189
- if (crossOrigin !== undefined) hint.crossOrigin = crossOrigin
188
+ const attrs = getScriptPreloadAttrs(manifest, link)
189
+ const hint: EarlyHint = {
190
+ href: attrs.href,
191
+ rel: attrs.rel,
192
+ as: 'script',
193
+ }
194
+ if (attrs.crossOrigin !== undefined) hint.crossOrigin = attrs.crossOrigin
190
195
  hints.push(hint)
191
196
  }
192
197
 
193
- for (const asset of routeManifest.assets ?? []) {
194
- if (asset.tag !== 'link') continue
195
-
196
- const stylesheetHref = getStylesheetHref(asset)
197
- if (stylesheetHref) {
198
- if (manifest.inlineCss?.styles[stylesheetHref] !== undefined) continue
199
-
200
- const hint: EarlyHint = {
201
- href: stylesheetHref,
202
- rel: 'preload',
203
- as: 'style',
204
- }
205
- addEarlyHintFetchAttrs(hint, asset.attrs)
206
- hints.push(hint)
198
+ for (const link of routeManifest.css ?? []) {
199
+ const stylesheetHref = getStylesheetHref(link)
200
+ if (manifest.inlineCss?.styles[stylesheetHref] !== undefined) {
207
201
  continue
208
202
  }
203
+ const resolvedLink = resolveManifestCssLink(link)
209
204
 
210
- const hint = linkAttrsToEarlyHint(asset.attrs)
211
- if (hint) {
212
- hints.push(hint)
205
+ const hint: EarlyHint = {
206
+ href: stylesheetHref,
207
+ rel: 'preload',
208
+ as: 'style',
213
209
  }
210
+ if (resolvedLink.crossOrigin !== undefined) {
211
+ hint.crossOrigin = resolvedLink.crossOrigin
212
+ }
213
+ hints.push(hint)
214
214
  }
215
215
  }
216
216
 
@@ -0,0 +1,4 @@
1
+ import type { AnySerializationAdapter } from '@tanstack/router-core'
2
+
3
+ export const pluginSerializationAdapters: Array<AnySerializationAdapter> = []
4
+ export const hasPluginAdapters = false
@@ -7,7 +7,7 @@ import {
7
7
  getStaticHandlerInlineCssDefault,
8
8
  resolveInlineCssForRequest,
9
9
  } from './inlineCss'
10
- import type { Manifest } from '@tanstack/router-core'
10
+ import type { ServerManifest } from '@tanstack/router-core'
11
11
  import type { HandlerInlineCssOption } from './inlineCss'
12
12
  import type {
13
13
  CreateTransformAssetsContext,
@@ -45,7 +45,7 @@ export interface FinalManifestOptions {
45
45
  }
46
46
 
47
47
  type FinalManifestCacheKey = 'inline-css' | 'linked-css'
48
- type FinalManifestCache = Map<FinalManifestCacheKey, Promise<Manifest>>
48
+ type FinalManifestCache = Map<FinalManifestCacheKey, Promise<ServerManifest>>
49
49
  export type GetBaseManifest = () => Promise<StartManifestWithClientEntry>
50
50
 
51
51
  export interface FinalManifestRequestOptions {
@@ -66,9 +66,11 @@ interface FinalManifestTransformResolver {
66
66
  export interface FinalManifestResolver {
67
67
  warmup: (opts: {
68
68
  getBaseManifest: GetBaseManifest
69
- }) => Promise<Manifest> | undefined
70
- resolveCached: (opts: FinalManifestRequestOptions) => Promise<Manifest>
71
- resolveUncached: (opts: FinalManifestRequestOptions) => Promise<Manifest>
69
+ }) => Promise<ServerManifest> | undefined
70
+ resolveCached: (opts: FinalManifestRequestOptions) => Promise<ServerManifest>
71
+ resolveUncached: (
72
+ opts: FinalManifestRequestOptions,
73
+ ) => Promise<ServerManifest>
72
74
  }
73
75
 
74
76
  export function createCachedBaseManifestLoader(
@@ -206,8 +208,8 @@ function getFinalManifestCacheKey(inlineCss: boolean): FinalManifestCacheKey {
206
208
  function cacheFinalManifestPromise(
207
209
  cachedFinalManifestPromises: FinalManifestCache,
208
210
  cacheKey: FinalManifestCacheKey,
209
- promise: Promise<Manifest>,
210
- ): Promise<Manifest> {
211
+ promise: Promise<ServerManifest>,
212
+ ): Promise<ServerManifest> {
211
213
  const cachedFinalManifestPromise = promise.catch((error) => {
212
214
  if (
213
215
  cachedFinalManifestPromises.get(cacheKey) === cachedFinalManifestPromise
@@ -224,8 +226,8 @@ function cacheFinalManifestPromise(
224
226
  function getOrCreateCachedFinalManifestPromise(
225
227
  cachedFinalManifestPromises: FinalManifestCache,
226
228
  cacheKey: FinalManifestCacheKey,
227
- computeFinalManifest: () => Promise<Manifest>,
228
- ): Promise<Manifest> {
229
+ computeFinalManifest: () => Promise<ServerManifest>,
230
+ ): Promise<ServerManifest> {
229
231
  const cachedFinalManifestPromise = cachedFinalManifestPromises.get(cacheKey)
230
232
  if (cachedFinalManifestPromise) {
231
233
  return cachedFinalManifestPromise
@@ -242,7 +244,7 @@ async function buildFinalManifest(opts: {
242
244
  base: StartManifestWithClientEntry
243
245
  transformFn: TransformAssetsFn | undefined
244
246
  inlineCss: boolean
245
- }): Promise<Manifest> {
247
+ }): Promise<ServerManifest> {
246
248
  return opts.transformFn
247
249
  ? await transformManifestAssets(opts.base, opts.transformFn, {
248
250
  inlineCss: opts.inlineCss,
@@ -256,7 +258,7 @@ async function resolveFinalManifest(opts: {
256
258
  cache: boolean
257
259
  inlineCss: boolean
258
260
  finalManifestCache?: FinalManifestCache
259
- }): Promise<Manifest> {
261
+ }): Promise<ServerManifest> {
260
262
  const computeFinalManifest = async () => {
261
263
  return buildFinalManifest({
262
264
  base: await opts.getBaseManifest(),
@@ -284,7 +286,7 @@ function warmupFinalManifest(opts: {
284
286
  getBaseManifest: () => Promise<StartManifestWithClientEntry>
285
287
  getTransformFn: () => Promise<TransformAssetsFn | undefined>
286
288
  onError?: () => void
287
- }): Promise<Manifest> | undefined {
289
+ }): Promise<ServerManifest> | undefined {
288
290
  if (
289
291
  !opts.enabled ||
290
292
  opts.handlerDefaultInlineCss === undefined ||
@@ -9,7 +9,8 @@ type EarlyHintsOptions = {
9
9
  * Fire-and-forget callback for HTTP 103 Early Hints.
10
10
  * Only invoked in production (when TSS_DEV_SERVER !== 'true').
11
11
  *
12
- * The `static` phase contains transformed manifest assets for matched routes.
12
+ * The `static` phase contains transformed manifest preloads and stylesheets
13
+ * for matched routes.
13
14
  * The `dynamic` phase runs after route load, is skipped for redirects, and
14
15
  * can contain route `head().links` or empty `hints` and `links` arrays.
15
16
  * `hints` and `links` contain only values not emitted in earlier phases.
@@ -1,16 +1,15 @@
1
- import { buildDevStylesUrl, rootRouteId } from '@tanstack/router-core'
2
- import type {
3
- AnyRoute,
4
- ManifestAssetLink,
5
- RouterManagedTag,
1
+ import {
2
+ DEV_STYLES_ATTR,
3
+ buildDevStylesUrl,
4
+ rootRouteId,
6
5
  } from '@tanstack/router-core'
6
+ import type { AnyRoute, ServerManifestRoute } from '@tanstack/router-core'
7
7
  import type { StartManifestWithClientEntry } from './transformAssetUrls'
8
8
 
9
9
  // Pre-computed constant for dev styles URL basepath.
10
10
  // Defaults to vite `base` (set via TSS_DEV_SSR_STYLES_BASEPATH in the plugin),
11
11
  // aligning dev styles with how other CSS/JS assets are served.
12
12
  const DEV_SSR_STYLES_BASEPATH = process.env.TSS_DEV_SSR_STYLES_BASEPATH || '/'
13
-
14
13
  /**
15
14
  * @description Returns the router manifest data that should be sent to the client.
16
15
  * This includes only the assets and preloads for the current route and any
@@ -28,11 +27,16 @@ export async function getStartManifest(
28
27
  ): Promise<StartManifestWithClientEntry> {
29
28
  const { tsrStartManifest } = await import('tanstack-start-manifest:v')
30
29
  const startManifest = tsrStartManifest()
30
+ let routes = startManifest.routes
31
+ let rootRoute = routes[rootRouteId]
31
32
 
32
- const rootRoute = (startManifest.routes[rootRouteId] =
33
- startManifest.routes[rootRouteId] || {})
34
-
35
- rootRoute.assets = rootRoute.assets || []
33
+ const updateRootRoute = (nextRootRoute: ServerManifestRoute) => {
34
+ rootRoute = nextRootRoute
35
+ routes = {
36
+ ...routes,
37
+ [rootRouteId]: rootRoute,
38
+ }
39
+ }
36
40
 
37
41
  // Inject dev styles link in dev mode (when SSR styles are enabled)
38
42
  if (
@@ -41,54 +45,48 @@ export async function getStartManifest(
41
45
  matchedRoutes
42
46
  ) {
43
47
  const matchedRouteIds = matchedRoutes.map((route) => route.id)
44
- rootRoute.assets.push({
45
- tag: 'link',
46
- attrs: {
47
- rel: 'stylesheet',
48
- href: buildDevStylesUrl(DEV_SSR_STYLES_BASEPATH, matchedRouteIds),
49
- 'data-tanstack-router-dev-styles': 'true',
50
- },
48
+ updateRootRoute({
49
+ ...rootRoute,
50
+ css: [
51
+ ...(rootRoute?.css ?? []),
52
+ {
53
+ href: buildDevStylesUrl(DEV_SSR_STYLES_BASEPATH, matchedRouteIds),
54
+ [DEV_STYLES_ATTR]: true,
55
+ },
56
+ ],
51
57
  })
52
58
  }
53
59
 
54
- // Collect injected head scripts in dev mode (returned separately so we can
55
- // build the client entry script tag after URL transforms are applied)
56
- let injectedHeadScripts: string | undefined
57
- if (process.env.TSS_DEV_SERVER === 'true') {
58
- const mod = await import('tanstack-start-injected-head-scripts:v')
59
- if (mod.injectedHeadScripts) {
60
- injectedHeadScripts = mod.injectedHeadScripts
60
+ const manifestRoutes: Record<string, ServerManifestRoute> = {}
61
+
62
+ for (const k in routes) {
63
+ const v = routes[k]!
64
+ const result = {} as ServerManifestRoute
65
+
66
+ if (v.preloads && v.preloads.length > 0) {
67
+ result.preloads = v.preloads
68
+ }
69
+ if (v.scripts && v.scripts.length > 0) {
70
+ result.scripts = v.scripts
71
+ }
72
+ if (v.css?.length) {
73
+ result.css = v.css
74
+ }
75
+ if (result.preloads || result.scripts || result.css) {
76
+ manifestRoutes[k] = result
61
77
  }
62
78
  }
63
79
 
64
80
  const manifest = {
65
- inlineCss: startManifest.inlineCss,
66
- routes: Object.fromEntries(
67
- Object.entries(startManifest.routes).flatMap(([k, v]) => {
68
- const result = {} as {
69
- preloads?: Array<ManifestAssetLink>
70
- assets?: Array<RouterManagedTag>
71
- }
72
- let hasData = false
73
- if (v.preloads && v.preloads.length > 0) {
74
- result['preloads'] = v.preloads
75
- hasData = true
76
- }
77
- if (v.assets && v.assets.length > 0) {
78
- result['assets'] = v.assets
79
- hasData = true
80
- }
81
- if (!hasData) {
82
- return []
83
- }
84
- return [[k, result]]
85
- }),
86
- ),
81
+ ...(startManifest.scriptFormat
82
+ ? { scriptFormat: startManifest.scriptFormat }
83
+ : {}),
84
+ ...(startManifest.inlineCss ? { inlineCss: startManifest.inlineCss } : {}),
85
+ routes: manifestRoutes,
87
86
  }
88
87
 
89
88
  return {
90
89
  manifest: manifest as StartManifestWithClientEntry['manifest'],
91
90
  clientEntry: startManifest.clientEntry,
92
- injectedHeadScripts,
93
91
  }
94
92
  }
@@ -1,7 +1,7 @@
1
1
  declare module 'tanstack-start-manifest:v' {
2
- import type { Manifest } from '@tanstack/router-core'
2
+ import type { ServerManifest } from '@tanstack/router-core'
3
3
 
4
- export const tsrStartManifest: () => Manifest & { clientEntry: string }
4
+ export const tsrStartManifest: () => ServerManifest & { clientEntry: string }
5
5
  }
6
6
 
7
7
  declare module 'tanstack-start-route-tree:v' {
@@ -21,7 +21,3 @@ declare module '#tanstack-start-server-fn-resolver' {
21
21
  access: ServerFnLookupAccess,
22
22
  ): Promise<ServerFn>
23
23
  }
24
-
25
- declare module 'tanstack-start-injected-head-scripts:v' {
26
- export const injectedHeadScripts: string | undefined
27
- }