@tanstack/start-server-core 1.168.0 → 1.168.2

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.
@@ -167,7 +167,93 @@ function getResponseLinkHeaderEntries(opts) {
167
167
  return [];
168
168
  }
169
169
  }
170
+ function notifyEarlyHints(phase, event, onEarlyHints) {
171
+ try {
172
+ const result = onEarlyHints(event);
173
+ if (result) Promise.resolve(result).catch((err) => {
174
+ console.error(`Error sending ${phase} early hints:`, err);
175
+ });
176
+ } catch (err) {
177
+ console.error(`Error sending ${phase} early hints:`, err);
178
+ }
179
+ }
180
+ function getResponseLinkHeaderFilter(responseLinkHeader) {
181
+ if (typeof responseLinkHeader !== "object") return;
182
+ return responseLinkHeader.filter;
183
+ }
184
+ function appendResponseLinkHeaders(opts) {
185
+ for (const link of getResponseLinkHeaderEntries(opts)) opts.responseHeaders.append("Link", link);
186
+ }
187
+ function collectResponseLinkHeaderEntries(opts) {
188
+ for (let index = 0; index < opts.event.hints.length; index++) opts.entries.push({
189
+ phase: opts.phase,
190
+ hint: opts.event.hints[index],
191
+ link: opts.event.links[index]
192
+ });
193
+ }
194
+ function collectEarlyHintsPhase(opts) {
195
+ const event = opts.onEarlyHints ? createEarlyHintsEvent({
196
+ phase: opts.phase,
197
+ hints: opts.hints,
198
+ sentLinks: opts.sentLinks,
199
+ sentHints: opts.sentHints
200
+ }) : void 0;
201
+ if (event) notifyEarlyHints(opts.phase, event, opts.onEarlyHints);
202
+ if (!opts.responseLinkHeaderEntries) return;
203
+ if (event) {
204
+ collectResponseLinkHeaderEntries({
205
+ phase: opts.phase,
206
+ event,
207
+ entries: opts.responseLinkHeaderEntries
208
+ });
209
+ return;
210
+ }
211
+ createResponseLinkHeaderEntries({
212
+ phase: opts.phase,
213
+ hints: opts.hints,
214
+ sentLinks: opts.sentLinks,
215
+ entries: opts.responseLinkHeaderEntries
216
+ });
217
+ }
218
+ function createEarlyHintsCollector(opts) {
219
+ if (process.env.TSS_DEV_SERVER === "true" || !opts?.onEarlyHints && !opts?.responseLinkHeader) return;
220
+ const sentLinks = /* @__PURE__ */ new Set();
221
+ const sentHints = opts.onEarlyHints ? new Array() : void 0;
222
+ const responseLinkHeaderEntries = opts.responseLinkHeader ? new Array() : void 0;
223
+ const responseLinkHeaderFilter = getResponseLinkHeaderFilter(opts.responseLinkHeader);
224
+ return {
225
+ collectStatic: ({ manifest, matchedRoutes }) => {
226
+ if (!matchedRoutes?.length) return;
227
+ collectEarlyHintsPhase({
228
+ phase: "static",
229
+ hints: collectStaticHintsFromManifest(manifest, matchedRoutes),
230
+ sentLinks,
231
+ sentHints,
232
+ onEarlyHints: opts.onEarlyHints,
233
+ responseLinkHeaderEntries
234
+ });
235
+ },
236
+ collectDynamic: (matches) => {
237
+ collectEarlyHintsPhase({
238
+ phase: "dynamic",
239
+ hints: collectDynamicHintsFromMatches(matches),
240
+ sentLinks,
241
+ sentHints,
242
+ onEarlyHints: opts.onEarlyHints,
243
+ responseLinkHeaderEntries
244
+ });
245
+ },
246
+ appendResponseHeaders: (headers) => {
247
+ if (!responseLinkHeaderEntries?.length) return;
248
+ appendResponseLinkHeaders({
249
+ responseHeaders: headers,
250
+ entries: responseLinkHeaderEntries,
251
+ filter: responseLinkHeaderFilter
252
+ });
253
+ }
254
+ };
255
+ }
170
256
  //#endregion
171
- export { collectDynamicHintsFromMatches, collectStaticHintsFromManifest, createEarlyHintsEvent, createResponseLinkHeaderEntries, getResponseLinkHeaderEntries };
257
+ export { createEarlyHintsCollector };
172
258
 
173
259
  //# sourceMappingURL=early-hints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"early-hints.js","names":[],"sources":["../../src/early-hints.ts"],"sourcesContent":["import {\n getStylesheetHref,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport type {\n AnyRoute,\n AnyRouteMatch,\n AssetCrossOrigin,\n Manifest,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nexport type EarlyHint = {\n href: string\n rel: 'preload' | 'modulepreload' | 'preconnect' | 'dns-prefetch'\n as?: 'fetch' | 'font' | 'image' | 'script' | 'style' | 'track'\n crossOrigin?: AssetCrossOrigin | ''\n type?: string\n integrity?: string\n referrerPolicy?: string\n fetchPriority?: string\n}\n\nexport type EarlyHintsPhase = 'static' | 'dynamic'\n\nexport type EarlyHintsEvent = {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n links: Array<string>\n allHints: ReadonlyArray<EarlyHint>\n allLinks: Array<string>\n}\n\nexport type OnEarlyHints = (event: EarlyHintsEvent) => void | Promise<void>\n\nexport type ResponseLinkHeaderEntry = {\n phase: EarlyHintsPhase\n hint: EarlyHint\n link: string\n}\n\nexport type ResponseLinkHeaderFilter = (\n entry: ResponseLinkHeaderEntry,\n) => boolean\n\nexport type ResponseLinkHeaderOptions = {\n filter?: ResponseLinkHeaderFilter\n}\n\nconst LINK_PARAM_TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/\nconst PRELOAD_AS_VALUES = new Set<EarlyHint['as']>([\n 'fetch',\n 'font',\n 'image',\n 'script',\n 'style',\n 'track',\n])\n\nfunction buildLinkParam(name: string, value: string | undefined): string {\n if (value === undefined) return name\n if (LINK_PARAM_TOKEN_RE.test(value)) return `${name}=${value}`\n return `${name}=${JSON.stringify(value)}`\n}\n\nexport function serializeEarlyHint(hint: EarlyHint): string {\n const parts = [`<${hint.href}>`, buildLinkParam('rel', hint.rel)]\n if (hint.as) parts.push(buildLinkParam('as', hint.as))\n if (hint.crossOrigin !== undefined) {\n parts.push(buildLinkParam('crossorigin', hint.crossOrigin || undefined))\n }\n if (hint.type) parts.push(buildLinkParam('type', hint.type))\n if (hint.integrity) parts.push(buildLinkParam('integrity', hint.integrity))\n if (hint.referrerPolicy) {\n parts.push(buildLinkParam('referrerpolicy', hint.referrerPolicy))\n }\n if (hint.fetchPriority) {\n parts.push(buildLinkParam('fetchpriority', hint.fetchPriority))\n }\n return parts.join('; ')\n}\n\nfunction getStringAttr(\n attrs: Record<string, any> | undefined,\n name: string,\n fallbackName?: string,\n): string | undefined {\n const value =\n attrs?.[name] ?? (fallbackName ? attrs?.[fallbackName] : undefined)\n return typeof value === 'string' ? value : undefined\n}\n\nfunction getPreloadAs(\n attrs: Record<string, any> | undefined,\n): EarlyHint['as'] | undefined {\n const as = getStringAttr(attrs, 'as')\n return as && PRELOAD_AS_VALUES.has(as as EarlyHint['as'])\n ? (as as EarlyHint['as'])\n : undefined\n}\n\nfunction addEarlyHintFetchAttrs(\n hint: EarlyHint,\n attrs: Record<string, any> | undefined,\n) {\n const crossOrigin = getStringAttr(attrs, 'crossOrigin', 'crossorigin') as\n | EarlyHint['crossOrigin']\n | undefined\n const type = getStringAttr(attrs, 'type')\n const integrity = getStringAttr(attrs, 'integrity')\n const referrerPolicy = getStringAttr(\n attrs,\n 'referrerPolicy',\n 'referrerpolicy',\n )\n const fetchPriority = getStringAttr(attrs, 'fetchPriority', 'fetchpriority')\n\n if (crossOrigin !== undefined) hint.crossOrigin = crossOrigin\n if (type) hint.type = type\n if (integrity) hint.integrity = integrity\n if (referrerPolicy) hint.referrerPolicy = referrerPolicy\n if (fetchPriority) hint.fetchPriority = fetchPriority\n}\n\nfunction linkAttrsToEarlyHint(\n attrs: Record<string, any> | undefined,\n): EarlyHint | undefined {\n const href = getStringAttr(attrs, 'href')\n const rel = getStringAttr(attrs, 'rel')\n if (!href || !rel) return undefined\n\n const relTokens = rel.split(/\\s+/)\n let hintRel: EarlyHint['rel'] | undefined\n let hintAs: EarlyHint['as'] | undefined\n\n if (relTokens.includes('modulepreload')) {\n hintRel = 'modulepreload'\n hintAs = 'script'\n } else if (relTokens.includes('stylesheet')) {\n hintRel = 'preload'\n hintAs = 'style'\n } else if (relTokens.includes('preload')) {\n hintAs = getPreloadAs(attrs)\n if (!hintAs) return undefined\n hintRel = 'preload'\n } else if (relTokens.includes('preconnect')) {\n hintRel = 'preconnect'\n hintAs = undefined\n } else if (relTokens.includes('dns-prefetch')) {\n hintRel = 'dns-prefetch'\n hintAs = undefined\n }\n\n if (!hintRel) return undefined\n\n const hint: EarlyHint = {\n href,\n rel: hintRel,\n }\n\n if (hintAs) hint.as = hintAs\n addEarlyHintFetchAttrs(hint, attrs)\n\n return hint\n}\n\nexport function collectStaticHintsFromManifest(\n manifest: Manifest,\n matchedRoutes: ReadonlyArray<AnyRoute>,\n): Array<EarlyHint> {\n const hints: Array<EarlyHint> = []\n\n for (const route of matchedRoutes) {\n const routeManifest = manifest.routes[route.id]\n if (!routeManifest) continue\n\n for (const link of routeManifest.preloads ?? []) {\n const { href, crossOrigin } = resolveManifestAssetLink(link)\n const hint: EarlyHint = { href, rel: 'modulepreload', as: 'script' }\n if (crossOrigin !== undefined) hint.crossOrigin = crossOrigin\n hints.push(hint)\n }\n\n for (const asset of routeManifest.assets ?? []) {\n if (asset.tag !== 'link') continue\n\n const stylesheetHref = getStylesheetHref(asset)\n if (stylesheetHref) {\n if (manifest.inlineCss?.styles[stylesheetHref] !== undefined) continue\n\n const hint: EarlyHint = {\n href: stylesheetHref,\n rel: 'preload',\n as: 'style',\n }\n addEarlyHintFetchAttrs(hint, asset.attrs)\n hints.push(hint)\n continue\n }\n\n const hint = linkAttrsToEarlyHint(asset.attrs)\n if (hint) {\n hints.push(hint)\n }\n }\n }\n\n return hints\n}\n\nexport function collectDynamicHintsFromMatches(\n matches: ReadonlyArray<AnyRouteMatch>,\n): Array<EarlyHint> {\n const hints: Array<EarlyHint> = []\n\n for (const match of matches) {\n const links = match.links\n if (!Array.isArray(links)) continue\n\n for (const link of links as Array<RouterManagedTag['attrs']>) {\n const hint = linkAttrsToEarlyHint(link)\n if (hint) hints.push(hint)\n }\n }\n\n return hints\n}\n\nexport function createEarlyHintsEvent(opts: {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n sentLinks: Set<string>\n sentHints: Array<EarlyHint>\n}): EarlyHintsEvent | undefined {\n const nextHints: Array<EarlyHint> = []\n const nextLinks: Array<string> = []\n\n for (const hint of opts.hints) {\n const link = serializeEarlyHint(hint)\n if (opts.sentLinks.has(link)) continue\n opts.sentLinks.add(link)\n opts.sentHints.push(hint)\n nextHints.push(hint)\n nextLinks.push(link)\n }\n\n if (!nextHints.length && opts.phase !== 'dynamic') return undefined\n\n return {\n phase: opts.phase,\n hints: nextHints,\n links: nextLinks,\n allHints: opts.sentHints.slice(),\n allLinks: Array.from(opts.sentLinks),\n }\n}\n\nexport function createResponseLinkHeaderEntries(opts: {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n sentLinks: Set<string>\n entries: Array<ResponseLinkHeaderEntry>\n}) {\n for (const hint of opts.hints) {\n const link = serializeEarlyHint(hint)\n if (opts.sentLinks.has(link)) continue\n\n opts.sentLinks.add(link)\n opts.entries.push({ phase: opts.phase, hint, link })\n }\n}\n\nexport function getResponseLinkHeaderEntries(opts: {\n entries: ReadonlyArray<ResponseLinkHeaderEntry>\n filter?: ResponseLinkHeaderFilter\n}): Array<string> {\n if (!opts.filter) {\n return opts.entries.map((entry) => entry.link)\n }\n\n try {\n const links: Array<string> = []\n\n for (const entry of opts.entries) {\n if (opts.filter(entry)) {\n links.push(entry.link)\n }\n }\n\n return links\n } catch (err) {\n console.error('Error filtering response Link headers:', err)\n return []\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"early-hints.js","names":[],"sources":["../../src/early-hints.ts"],"sourcesContent":["import {\n getStylesheetHref,\n resolveManifestAssetLink,\n} from '@tanstack/router-core'\nimport type {\n AnyRoute,\n AnyRouteMatch,\n AssetCrossOrigin,\n Manifest,\n RouterManagedTag,\n} from '@tanstack/router-core'\n\nexport type EarlyHint = {\n href: string\n rel: 'preload' | 'modulepreload' | 'preconnect' | 'dns-prefetch'\n as?: 'fetch' | 'font' | 'image' | 'script' | 'style' | 'track'\n crossOrigin?: AssetCrossOrigin | ''\n type?: string\n integrity?: string\n referrerPolicy?: string\n fetchPriority?: string\n}\n\nexport type EarlyHintsPhase = 'static' | 'dynamic'\n\nexport type EarlyHintsEvent = {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n links: Array<string>\n allHints: ReadonlyArray<EarlyHint>\n allLinks: Array<string>\n}\n\nexport type OnEarlyHints = (event: EarlyHintsEvent) => void | Promise<void>\n\nexport type ResponseLinkHeaderEntry = {\n phase: EarlyHintsPhase\n hint: EarlyHint\n link: string\n}\n\nexport type ResponseLinkHeaderFilter = (\n entry: ResponseLinkHeaderEntry,\n) => boolean\n\nexport type ResponseLinkHeaderOptions = {\n filter?: ResponseLinkHeaderFilter\n}\n\nexport interface EarlyHintsCollector {\n collectStatic: (opts: {\n manifest: Manifest\n matchedRoutes?: ReadonlyArray<AnyRoute>\n }) => void\n collectDynamic: (matches: ReadonlyArray<AnyRouteMatch>) => void\n appendResponseHeaders: (headers: Headers) => void\n}\n\nconst LINK_PARAM_TOKEN_RE = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/\nconst PRELOAD_AS_VALUES = new Set<EarlyHint['as']>([\n 'fetch',\n 'font',\n 'image',\n 'script',\n 'style',\n 'track',\n])\n\nfunction buildLinkParam(name: string, value: string | undefined): string {\n if (value === undefined) return name\n if (LINK_PARAM_TOKEN_RE.test(value)) return `${name}=${value}`\n return `${name}=${JSON.stringify(value)}`\n}\n\nexport function serializeEarlyHint(hint: EarlyHint): string {\n const parts = [`<${hint.href}>`, buildLinkParam('rel', hint.rel)]\n if (hint.as) parts.push(buildLinkParam('as', hint.as))\n if (hint.crossOrigin !== undefined) {\n parts.push(buildLinkParam('crossorigin', hint.crossOrigin || undefined))\n }\n if (hint.type) parts.push(buildLinkParam('type', hint.type))\n if (hint.integrity) parts.push(buildLinkParam('integrity', hint.integrity))\n if (hint.referrerPolicy) {\n parts.push(buildLinkParam('referrerpolicy', hint.referrerPolicy))\n }\n if (hint.fetchPriority) {\n parts.push(buildLinkParam('fetchpriority', hint.fetchPriority))\n }\n return parts.join('; ')\n}\n\nfunction getStringAttr(\n attrs: Record<string, any> | undefined,\n name: string,\n fallbackName?: string,\n): string | undefined {\n const value =\n attrs?.[name] ?? (fallbackName ? attrs?.[fallbackName] : undefined)\n return typeof value === 'string' ? value : undefined\n}\n\nfunction getPreloadAs(\n attrs: Record<string, any> | undefined,\n): EarlyHint['as'] | undefined {\n const as = getStringAttr(attrs, 'as')\n return as && PRELOAD_AS_VALUES.has(as as EarlyHint['as'])\n ? (as as EarlyHint['as'])\n : undefined\n}\n\nfunction addEarlyHintFetchAttrs(\n hint: EarlyHint,\n attrs: Record<string, any> | undefined,\n) {\n const crossOrigin = getStringAttr(attrs, 'crossOrigin', 'crossorigin') as\n | EarlyHint['crossOrigin']\n | undefined\n const type = getStringAttr(attrs, 'type')\n const integrity = getStringAttr(attrs, 'integrity')\n const referrerPolicy = getStringAttr(\n attrs,\n 'referrerPolicy',\n 'referrerpolicy',\n )\n const fetchPriority = getStringAttr(attrs, 'fetchPriority', 'fetchpriority')\n\n if (crossOrigin !== undefined) hint.crossOrigin = crossOrigin\n if (type) hint.type = type\n if (integrity) hint.integrity = integrity\n if (referrerPolicy) hint.referrerPolicy = referrerPolicy\n if (fetchPriority) hint.fetchPriority = fetchPriority\n}\n\nfunction linkAttrsToEarlyHint(\n attrs: Record<string, any> | undefined,\n): EarlyHint | undefined {\n const href = getStringAttr(attrs, 'href')\n const rel = getStringAttr(attrs, 'rel')\n if (!href || !rel) return undefined\n\n const relTokens = rel.split(/\\s+/)\n let hintRel: EarlyHint['rel'] | undefined\n let hintAs: EarlyHint['as'] | undefined\n\n if (relTokens.includes('modulepreload')) {\n hintRel = 'modulepreload'\n hintAs = 'script'\n } else if (relTokens.includes('stylesheet')) {\n hintRel = 'preload'\n hintAs = 'style'\n } else if (relTokens.includes('preload')) {\n hintAs = getPreloadAs(attrs)\n if (!hintAs) return undefined\n hintRel = 'preload'\n } else if (relTokens.includes('preconnect')) {\n hintRel = 'preconnect'\n hintAs = undefined\n } else if (relTokens.includes('dns-prefetch')) {\n hintRel = 'dns-prefetch'\n hintAs = undefined\n }\n\n if (!hintRel) return undefined\n\n const hint: EarlyHint = {\n href,\n rel: hintRel,\n }\n\n if (hintAs) hint.as = hintAs\n addEarlyHintFetchAttrs(hint, attrs)\n\n return hint\n}\n\nexport function collectStaticHintsFromManifest(\n manifest: Manifest,\n matchedRoutes: ReadonlyArray<AnyRoute>,\n): Array<EarlyHint> {\n const hints: Array<EarlyHint> = []\n\n for (const route of matchedRoutes) {\n const routeManifest = manifest.routes[route.id]\n if (!routeManifest) continue\n\n for (const link of routeManifest.preloads ?? []) {\n const { href, crossOrigin } = resolveManifestAssetLink(link)\n const hint: EarlyHint = { href, rel: 'modulepreload', as: 'script' }\n if (crossOrigin !== undefined) hint.crossOrigin = crossOrigin\n hints.push(hint)\n }\n\n for (const asset of routeManifest.assets ?? []) {\n if (asset.tag !== 'link') continue\n\n const stylesheetHref = getStylesheetHref(asset)\n if (stylesheetHref) {\n if (manifest.inlineCss?.styles[stylesheetHref] !== undefined) continue\n\n const hint: EarlyHint = {\n href: stylesheetHref,\n rel: 'preload',\n as: 'style',\n }\n addEarlyHintFetchAttrs(hint, asset.attrs)\n hints.push(hint)\n continue\n }\n\n const hint = linkAttrsToEarlyHint(asset.attrs)\n if (hint) {\n hints.push(hint)\n }\n }\n }\n\n return hints\n}\n\nexport function collectDynamicHintsFromMatches(\n matches: ReadonlyArray<AnyRouteMatch>,\n): Array<EarlyHint> {\n const hints: Array<EarlyHint> = []\n\n for (const match of matches) {\n const links = match.links\n if (!Array.isArray(links)) continue\n\n for (const link of links as Array<RouterManagedTag['attrs']>) {\n const hint = linkAttrsToEarlyHint(link)\n if (hint) hints.push(hint)\n }\n }\n\n return hints\n}\n\nexport function createEarlyHintsEvent(opts: {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n sentLinks: Set<string>\n sentHints: Array<EarlyHint>\n}): EarlyHintsEvent | undefined {\n const nextHints: Array<EarlyHint> = []\n const nextLinks: Array<string> = []\n\n for (const hint of opts.hints) {\n const link = serializeEarlyHint(hint)\n if (opts.sentLinks.has(link)) continue\n opts.sentLinks.add(link)\n opts.sentHints.push(hint)\n nextHints.push(hint)\n nextLinks.push(link)\n }\n\n if (!nextHints.length && opts.phase !== 'dynamic') return undefined\n\n return {\n phase: opts.phase,\n hints: nextHints,\n links: nextLinks,\n allHints: opts.sentHints.slice(),\n allLinks: Array.from(opts.sentLinks),\n }\n}\n\nexport function createResponseLinkHeaderEntries(opts: {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n sentLinks: Set<string>\n entries: Array<ResponseLinkHeaderEntry>\n}) {\n for (const hint of opts.hints) {\n const link = serializeEarlyHint(hint)\n if (opts.sentLinks.has(link)) continue\n\n opts.sentLinks.add(link)\n opts.entries.push({ phase: opts.phase, hint, link })\n }\n}\n\nexport function getResponseLinkHeaderEntries(opts: {\n entries: ReadonlyArray<ResponseLinkHeaderEntry>\n filter?: ResponseLinkHeaderFilter\n}): Array<string> {\n if (!opts.filter) {\n return opts.entries.map((entry) => entry.link)\n }\n\n try {\n const links: Array<string> = []\n\n for (const entry of opts.entries) {\n if (opts.filter(entry)) {\n links.push(entry.link)\n }\n }\n\n return links\n } catch (err) {\n console.error('Error filtering response Link headers:', err)\n return []\n }\n}\n\nfunction notifyEarlyHints(\n phase: EarlyHintsPhase,\n event: EarlyHintsEvent,\n onEarlyHints: OnEarlyHints,\n) {\n try {\n const result = onEarlyHints(event)\n if (result) {\n void Promise.resolve(result).catch((err) => {\n console.error(`Error sending ${phase} early hints:`, err)\n })\n }\n } catch (err) {\n console.error(`Error sending ${phase} early hints:`, err)\n }\n}\n\nfunction getResponseLinkHeaderFilter(\n responseLinkHeader: boolean | ResponseLinkHeaderOptions | undefined,\n): ResponseLinkHeaderFilter | undefined {\n if (typeof responseLinkHeader !== 'object') {\n return undefined\n }\n\n return responseLinkHeader.filter\n}\n\nfunction appendResponseLinkHeaders(opts: {\n responseHeaders: Headers\n entries: ReadonlyArray<ResponseLinkHeaderEntry>\n filter?: ResponseLinkHeaderFilter\n}) {\n for (const link of getResponseLinkHeaderEntries(opts)) {\n opts.responseHeaders.append('Link', link)\n }\n}\n\nfunction collectResponseLinkHeaderEntries(opts: {\n phase: EarlyHintsPhase\n event: EarlyHintsEvent\n entries: Array<ResponseLinkHeaderEntry>\n}) {\n for (let index = 0; index < opts.event.hints.length; index++) {\n opts.entries.push({\n phase: opts.phase,\n hint: opts.event.hints[index]!,\n link: opts.event.links[index]!,\n })\n }\n}\n\nfunction collectEarlyHintsPhase(opts: {\n phase: EarlyHintsPhase\n hints: ReadonlyArray<EarlyHint>\n sentLinks: Set<string>\n sentHints?: Array<EarlyHint>\n onEarlyHints?: OnEarlyHints\n responseLinkHeaderEntries?: Array<ResponseLinkHeaderEntry>\n}) {\n const event = opts.onEarlyHints\n ? createEarlyHintsEvent({\n phase: opts.phase,\n hints: opts.hints,\n sentLinks: opts.sentLinks,\n sentHints: opts.sentHints!,\n })\n : undefined\n\n if (event) {\n notifyEarlyHints(opts.phase, event, opts.onEarlyHints!)\n }\n\n if (!opts.responseLinkHeaderEntries) return\n\n if (event) {\n collectResponseLinkHeaderEntries({\n phase: opts.phase,\n event,\n entries: opts.responseLinkHeaderEntries,\n })\n return\n }\n\n createResponseLinkHeaderEntries({\n phase: opts.phase,\n hints: opts.hints,\n sentLinks: opts.sentLinks,\n entries: opts.responseLinkHeaderEntries,\n })\n}\n\nexport function createEarlyHintsCollector(\n opts:\n | {\n onEarlyHints?: OnEarlyHints\n responseLinkHeader?: boolean | ResponseLinkHeaderOptions\n }\n | undefined,\n): EarlyHintsCollector | undefined {\n if (\n process.env.TSS_DEV_SERVER === 'true' ||\n (!opts?.onEarlyHints && !opts?.responseLinkHeader)\n ) {\n return undefined\n }\n\n const sentLinks = new Set<string>()\n const sentHints = opts.onEarlyHints ? new Array<EarlyHint>() : undefined\n const responseLinkHeaderEntries = opts.responseLinkHeader\n ? new Array<ResponseLinkHeaderEntry>()\n : undefined\n const responseLinkHeaderFilter = getResponseLinkHeaderFilter(\n opts.responseLinkHeader,\n )\n\n return {\n collectStatic: ({ manifest, matchedRoutes }) => {\n if (!matchedRoutes?.length) return\n\n collectEarlyHintsPhase({\n phase: 'static',\n hints: collectStaticHintsFromManifest(manifest, matchedRoutes),\n sentLinks,\n sentHints,\n onEarlyHints: opts.onEarlyHints,\n responseLinkHeaderEntries,\n })\n },\n collectDynamic: (matches) => {\n collectEarlyHintsPhase({\n phase: 'dynamic',\n hints: collectDynamicHintsFromMatches(matches),\n sentLinks,\n sentHints,\n onEarlyHints: opts.onEarlyHints,\n responseLinkHeaderEntries,\n })\n },\n appendResponseHeaders: (headers) => {\n if (!responseLinkHeaderEntries?.length) return\n\n appendResponseLinkHeaders({\n responseHeaders: headers,\n entries: responseLinkHeaderEntries,\n filter: responseLinkHeaderFilter,\n })\n },\n }\n}\n"],"mappings":";;AA0DA,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB,IAAI,IAAqB;CACjD;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,eAAe,MAAc,OAAmC;AACvE,KAAI,UAAU,KAAA,EAAW,QAAO;AAChC,KAAI,oBAAoB,KAAK,MAAM,CAAE,QAAO,GAAG,KAAK,GAAG;AACvD,QAAO,GAAG,KAAK,GAAG,KAAK,UAAU,MAAM;;AAGzC,SAAgB,mBAAmB,MAAyB;CAC1D,MAAM,QAAQ,CAAC,IAAI,KAAK,KAAK,IAAI,eAAe,OAAO,KAAK,IAAI,CAAC;AACjE,KAAI,KAAK,GAAI,OAAM,KAAK,eAAe,MAAM,KAAK,GAAG,CAAC;AACtD,KAAI,KAAK,gBAAgB,KAAA,EACvB,OAAM,KAAK,eAAe,eAAe,KAAK,eAAe,KAAA,EAAU,CAAC;AAE1E,KAAI,KAAK,KAAM,OAAM,KAAK,eAAe,QAAQ,KAAK,KAAK,CAAC;AAC5D,KAAI,KAAK,UAAW,OAAM,KAAK,eAAe,aAAa,KAAK,UAAU,CAAC;AAC3E,KAAI,KAAK,eACP,OAAM,KAAK,eAAe,kBAAkB,KAAK,eAAe,CAAC;AAEnE,KAAI,KAAK,cACP,OAAM,KAAK,eAAe,iBAAiB,KAAK,cAAc,CAAC;AAEjE,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAS,cACP,OACA,MACA,cACoB;CACpB,MAAM,QACJ,QAAQ,UAAU,eAAe,QAAQ,gBAAgB,KAAA;AAC3D,QAAO,OAAO,UAAU,WAAW,QAAQ,KAAA;;AAG7C,SAAS,aACP,OAC6B;CAC7B,MAAM,KAAK,cAAc,OAAO,KAAK;AACrC,QAAO,MAAM,kBAAkB,IAAI,GAAsB,GACpD,KACD,KAAA;;AAGN,SAAS,uBACP,MACA,OACA;CACA,MAAM,cAAc,cAAc,OAAO,eAAe,cAAc;CAGtE,MAAM,OAAO,cAAc,OAAO,OAAO;CACzC,MAAM,YAAY,cAAc,OAAO,YAAY;CACnD,MAAM,iBAAiB,cACrB,OACA,kBACA,iBACD;CACD,MAAM,gBAAgB,cAAc,OAAO,iBAAiB,gBAAgB;AAE5E,KAAI,gBAAgB,KAAA,EAAW,MAAK,cAAc;AAClD,KAAI,KAAM,MAAK,OAAO;AACtB,KAAI,UAAW,MAAK,YAAY;AAChC,KAAI,eAAgB,MAAK,iBAAiB;AAC1C,KAAI,cAAe,MAAK,gBAAgB;;AAG1C,SAAS,qBACP,OACuB;CACvB,MAAM,OAAO,cAAc,OAAO,OAAO;CACzC,MAAM,MAAM,cAAc,OAAO,MAAM;AACvC,KAAI,CAAC,QAAQ,CAAC,IAAK,QAAO,KAAA;CAE1B,MAAM,YAAY,IAAI,MAAM,MAAM;CAClC,IAAI;CACJ,IAAI;AAEJ,KAAI,UAAU,SAAS,gBAAgB,EAAE;AACvC,YAAU;AACV,WAAS;YACA,UAAU,SAAS,aAAa,EAAE;AAC3C,YAAU;AACV,WAAS;YACA,UAAU,SAAS,UAAU,EAAE;AACxC,WAAS,aAAa,MAAM;AAC5B,MAAI,CAAC,OAAQ,QAAO,KAAA;AACpB,YAAU;YACD,UAAU,SAAS,aAAa,EAAE;AAC3C,YAAU;AACV,WAAS,KAAA;YACA,UAAU,SAAS,eAAe,EAAE;AAC7C,YAAU;AACV,WAAS,KAAA;;AAGX,KAAI,CAAC,QAAS,QAAO,KAAA;CAErB,MAAM,OAAkB;EACtB;EACA,KAAK;EACN;AAED,KAAI,OAAQ,MAAK,KAAK;AACtB,wBAAuB,MAAM,MAAM;AAEnC,QAAO;;AAGT,SAAgB,+BACd,UACA,eACkB;CAClB,MAAM,QAA0B,EAAE;AAElC,MAAK,MAAM,SAAS,eAAe;EACjC,MAAM,gBAAgB,SAAS,OAAO,MAAM;AAC5C,MAAI,CAAC,cAAe;AAEpB,OAAK,MAAM,QAAQ,cAAc,YAAY,EAAE,EAAE;GAC/C,MAAM,EAAE,MAAM,gBAAgB,yBAAyB,KAAK;GAC5D,MAAM,OAAkB;IAAE;IAAM,KAAK;IAAiB,IAAI;IAAU;AACpE,OAAI,gBAAgB,KAAA,EAAW,MAAK,cAAc;AAClD,SAAM,KAAK,KAAK;;AAGlB,OAAK,MAAM,SAAS,cAAc,UAAU,EAAE,EAAE;AAC9C,OAAI,MAAM,QAAQ,OAAQ;GAE1B,MAAM,iBAAiB,kBAAkB,MAAM;AAC/C,OAAI,gBAAgB;AAClB,QAAI,SAAS,WAAW,OAAO,oBAAoB,KAAA,EAAW;IAE9D,MAAM,OAAkB;KACtB,MAAM;KACN,KAAK;KACL,IAAI;KACL;AACD,2BAAuB,MAAM,MAAM,MAAM;AACzC,UAAM,KAAK,KAAK;AAChB;;GAGF,MAAM,OAAO,qBAAqB,MAAM,MAAM;AAC9C,OAAI,KACF,OAAM,KAAK,KAAK;;;AAKtB,QAAO;;AAGT,SAAgB,+BACd,SACkB;CAClB,MAAM,QAA0B,EAAE;AAElC,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,QAAQ,MAAM;AACpB,MAAI,CAAC,MAAM,QAAQ,MAAM,CAAE;AAE3B,OAAK,MAAM,QAAQ,OAA2C;GAC5D,MAAM,OAAO,qBAAqB,KAAK;AACvC,OAAI,KAAM,OAAM,KAAK,KAAK;;;AAI9B,QAAO;;AAGT,SAAgB,sBAAsB,MAKN;CAC9B,MAAM,YAA8B,EAAE;CACtC,MAAM,YAA2B,EAAE;AAEnC,MAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,MAAM,OAAO,mBAAmB,KAAK;AACrC,MAAI,KAAK,UAAU,IAAI,KAAK,CAAE;AAC9B,OAAK,UAAU,IAAI,KAAK;AACxB,OAAK,UAAU,KAAK,KAAK;AACzB,YAAU,KAAK,KAAK;AACpB,YAAU,KAAK,KAAK;;AAGtB,KAAI,CAAC,UAAU,UAAU,KAAK,UAAU,UAAW,QAAO,KAAA;AAE1D,QAAO;EACL,OAAO,KAAK;EACZ,OAAO;EACP,OAAO;EACP,UAAU,KAAK,UAAU,OAAO;EAChC,UAAU,MAAM,KAAK,KAAK,UAAU;EACrC;;AAGH,SAAgB,gCAAgC,MAK7C;AACD,MAAK,MAAM,QAAQ,KAAK,OAAO;EAC7B,MAAM,OAAO,mBAAmB,KAAK;AACrC,MAAI,KAAK,UAAU,IAAI,KAAK,CAAE;AAE9B,OAAK,UAAU,IAAI,KAAK;AACxB,OAAK,QAAQ,KAAK;GAAE,OAAO,KAAK;GAAO;GAAM;GAAM,CAAC;;;AAIxD,SAAgB,6BAA6B,MAG3B;AAChB,KAAI,CAAC,KAAK,OACR,QAAO,KAAK,QAAQ,KAAK,UAAU,MAAM,KAAK;AAGhD,KAAI;EACF,MAAM,QAAuB,EAAE;AAE/B,OAAK,MAAM,SAAS,KAAK,QACvB,KAAI,KAAK,OAAO,MAAM,CACpB,OAAM,KAAK,MAAM,KAAK;AAI1B,SAAO;UACA,KAAK;AACZ,UAAQ,MAAM,0CAA0C,IAAI;AAC5D,SAAO,EAAE;;;AAIb,SAAS,iBACP,OACA,OACA,cACA;AACA,KAAI;EACF,MAAM,SAAS,aAAa,MAAM;AAClC,MAAI,OACG,SAAQ,QAAQ,OAAO,CAAC,OAAO,QAAQ;AAC1C,WAAQ,MAAM,iBAAiB,MAAM,gBAAgB,IAAI;IACzD;UAEG,KAAK;AACZ,UAAQ,MAAM,iBAAiB,MAAM,gBAAgB,IAAI;;;AAI7D,SAAS,4BACP,oBACsC;AACtC,KAAI,OAAO,uBAAuB,SAChC;AAGF,QAAO,mBAAmB;;AAG5B,SAAS,0BAA0B,MAIhC;AACD,MAAK,MAAM,QAAQ,6BAA6B,KAAK,CACnD,MAAK,gBAAgB,OAAO,QAAQ,KAAK;;AAI7C,SAAS,iCAAiC,MAIvC;AACD,MAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,MAAM,MAAM,QAAQ,QACnD,MAAK,QAAQ,KAAK;EAChB,OAAO,KAAK;EACZ,MAAM,KAAK,MAAM,MAAM;EACvB,MAAM,KAAK,MAAM,MAAM;EACxB,CAAC;;AAIN,SAAS,uBAAuB,MAO7B;CACD,MAAM,QAAQ,KAAK,eACf,sBAAsB;EACpB,OAAO,KAAK;EACZ,OAAO,KAAK;EACZ,WAAW,KAAK;EAChB,WAAW,KAAK;EACjB,CAAC,GACF,KAAA;AAEJ,KAAI,MACF,kBAAiB,KAAK,OAAO,OAAO,KAAK,aAAc;AAGzD,KAAI,CAAC,KAAK,0BAA2B;AAErC,KAAI,OAAO;AACT,mCAAiC;GAC/B,OAAO,KAAK;GACZ;GACA,SAAS,KAAK;GACf,CAAC;AACF;;AAGF,iCAAgC;EAC9B,OAAO,KAAK;EACZ,OAAO,KAAK;EACZ,WAAW,KAAK;EAChB,SAAS,KAAK;EACf,CAAC;;AAGJ,SAAgB,0BACd,MAMiC;AACjC,KACE,QAAQ,IAAI,mBAAmB,UAC9B,CAAC,MAAM,gBAAgB,CAAC,MAAM,mBAE/B;CAGF,MAAM,4BAAY,IAAI,KAAa;CACnC,MAAM,YAAY,KAAK,eAAe,IAAI,OAAkB,GAAG,KAAA;CAC/D,MAAM,4BAA4B,KAAK,qBACnC,IAAI,OAAgC,GACpC,KAAA;CACJ,MAAM,2BAA2B,4BAC/B,KAAK,mBACN;AAED,QAAO;EACL,gBAAgB,EAAE,UAAU,oBAAoB;AAC9C,OAAI,CAAC,eAAe,OAAQ;AAE5B,0BAAuB;IACrB,OAAO;IACP,OAAO,+BAA+B,UAAU,cAAc;IAC9D;IACA;IACA,cAAc,KAAK;IACnB;IACD,CAAC;;EAEJ,iBAAiB,YAAY;AAC3B,0BAAuB;IACrB,OAAO;IACP,OAAO,+BAA+B,QAAQ;IAC9C;IACA;IACA,cAAc,KAAK;IACnB;IACD,CAAC;;EAEJ,wBAAwB,YAAY;AAClC,OAAI,CAAC,2BAA2B,OAAQ;AAExC,6BAA0B;IACxB,iBAAiB;IACjB,SAAS;IACT,QAAQ;IACT,CAAC;;EAEL"}
@@ -0,0 +1,42 @@
1
+ import { Manifest } from '@tanstack/router-core';
2
+ import { HandlerInlineCssOption } from './inlineCss.js';
3
+ import { StartManifestWithClientEntry, TransformAssets } from './transformAssetUrls.js';
4
+ export type { HandlerInlineCssOption, StartManifestWithClientEntry, TransformAssets, };
5
+ export interface FinalManifestOptions {
6
+ /**
7
+ * Controls whether Start inlines build-collected CSS by default at runtime.
8
+ *
9
+ * This only has an effect when the build was created with
10
+ * `server.build.inlineCss` enabled. Pass a callback to decide per request.
11
+ * `handler(request, { inlineCss })` overrides this value for that request.
12
+ *
13
+ * @default true
14
+ */
15
+ inlineCss?: HandlerInlineCssOption;
16
+ /**
17
+ * Transform manifest-managed asset URLs and attributes at runtime, e.g. to
18
+ * prepend a CDN prefix.
19
+ *
20
+ * This covers JS preloads, CSS links, the client entry script, and URLs
21
+ * inside build-collected inline CSS. Asset imports used directly in
22
+ * components should be handled by the bundler instead.
23
+ */
24
+ transformAssets?: TransformAssets;
25
+ }
26
+ export type GetBaseManifest = () => Promise<StartManifestWithClientEntry>;
27
+ export interface FinalManifestRequestOptions {
28
+ request: Request;
29
+ requestInlineCss: boolean | undefined;
30
+ getBaseManifest: GetBaseManifest;
31
+ }
32
+ export interface FinalManifestResolver {
33
+ warmup: (opts: {
34
+ getBaseManifest: GetBaseManifest;
35
+ }) => Promise<Manifest> | undefined;
36
+ resolveCached: (opts: FinalManifestRequestOptions) => Promise<Manifest>;
37
+ resolveUncached: (opts: FinalManifestRequestOptions) => Promise<Manifest>;
38
+ }
39
+ export declare function createCachedBaseManifestLoader(loadBaseManifest: GetBaseManifest): GetBaseManifest;
40
+ export declare function createFinalManifestResolver(opts: FinalManifestOptions & {
41
+ cacheCreateTransform: boolean;
42
+ }): FinalManifestResolver;
@@ -0,0 +1,126 @@
1
+ import { buildManifestWithClientEntry, resolveTransformAssetsConfig, transformManifestAssets } from "./transformAssetUrls.js";
2
+ import { getStaticHandlerInlineCssDefault, resolveInlineCssForRequest } from "./inlineCss.js";
3
+ //#region src/finalManifest.ts
4
+ function createCachedBaseManifestLoader(loadBaseManifest) {
5
+ let baseManifestPromise;
6
+ return () => {
7
+ if (!baseManifestPromise) baseManifestPromise = loadBaseManifest().catch((error) => {
8
+ baseManifestPromise = void 0;
9
+ throw error;
10
+ });
11
+ return baseManifestPromise;
12
+ };
13
+ }
14
+ function createFinalManifestTransformResolver(transformAssets, opts) {
15
+ const transformConfig = transformAssets !== void 0 ? resolveTransformAssetsConfig(transformAssets) : void 0;
16
+ const cache = transformConfig ? transformConfig.cache : true;
17
+ const warmup = !!transformAssets && typeof transformAssets === "object" && "warmup" in transformAssets && transformAssets.warmup === true;
18
+ let cachedCreateTransformPromise;
19
+ const clearCachedCreateTransform = () => {
20
+ cachedCreateTransformPromise = void 0;
21
+ };
22
+ return {
23
+ cache,
24
+ warmup,
25
+ clearCachedCreateTransform,
26
+ getTransformFn: async (ctx) => {
27
+ if (!transformConfig) return void 0;
28
+ if (transformConfig.type !== "createTransform") return transformConfig.transformFn;
29
+ if (!cache || !opts.cacheCreateTransform) return transformConfig.createTransform(ctx);
30
+ if (!cachedCreateTransformPromise) cachedCreateTransformPromise = Promise.resolve(transformConfig.createTransform(ctx)).catch((error) => {
31
+ clearCachedCreateTransform();
32
+ throw error;
33
+ });
34
+ return cachedCreateTransformPromise;
35
+ }
36
+ };
37
+ }
38
+ function createFinalManifestResolver(opts) {
39
+ const finalManifestCache = /* @__PURE__ */ new Map();
40
+ const transformResolver = createFinalManifestTransformResolver(opts.transformAssets, { cacheCreateTransform: opts.cacheCreateTransform });
41
+ const handlerDefaultInlineCss = getStaticHandlerInlineCssDefault(opts.inlineCss);
42
+ const getRequestManifestOptions = async (requestOpts) => {
43
+ const transformFn = await transformResolver.getTransformFn({
44
+ warmup: false,
45
+ request: requestOpts.request
46
+ });
47
+ const inlineCss = await resolveInlineCssForRequest({
48
+ request: requestOpts.request,
49
+ handlerInlineCss: opts.inlineCss,
50
+ requestInlineCss: requestOpts.requestInlineCss
51
+ });
52
+ return {
53
+ getBaseManifest: requestOpts.getBaseManifest,
54
+ transformFn,
55
+ cache: transformResolver.cache,
56
+ inlineCss
57
+ };
58
+ };
59
+ const resolveRequest = async (requestOpts, cache) => {
60
+ return resolveFinalManifest({
61
+ ...await getRequestManifestOptions(requestOpts),
62
+ finalManifestCache: cache
63
+ });
64
+ };
65
+ return {
66
+ warmup: ({ getBaseManifest }) => warmupFinalManifest({
67
+ enabled: transformResolver.warmup,
68
+ handlerDefaultInlineCss,
69
+ cache: transformResolver.cache,
70
+ finalManifestCache,
71
+ getBaseManifest,
72
+ getTransformFn: () => transformResolver.getTransformFn({ warmup: true }),
73
+ onError: transformResolver.clearCachedCreateTransform
74
+ }),
75
+ resolveCached: (requestOpts) => resolveRequest(requestOpts, finalManifestCache),
76
+ resolveUncached: (requestOpts) => resolveRequest(requestOpts, void 0)
77
+ };
78
+ }
79
+ function getFinalManifestCacheKey(inlineCss) {
80
+ return inlineCss ? "inline-css" : "linked-css";
81
+ }
82
+ function cacheFinalManifestPromise(cachedFinalManifestPromises, cacheKey, promise) {
83
+ const cachedFinalManifestPromise = promise.catch((error) => {
84
+ if (cachedFinalManifestPromises.get(cacheKey) === cachedFinalManifestPromise) cachedFinalManifestPromises.delete(cacheKey);
85
+ throw error;
86
+ });
87
+ cachedFinalManifestPromises.set(cacheKey, cachedFinalManifestPromise);
88
+ return cachedFinalManifestPromise;
89
+ }
90
+ function getOrCreateCachedFinalManifestPromise(cachedFinalManifestPromises, cacheKey, computeFinalManifest) {
91
+ const cachedFinalManifestPromise = cachedFinalManifestPromises.get(cacheKey);
92
+ if (cachedFinalManifestPromise) return cachedFinalManifestPromise;
93
+ return cacheFinalManifestPromise(cachedFinalManifestPromises, cacheKey, Promise.resolve().then(computeFinalManifest));
94
+ }
95
+ async function buildFinalManifest(opts) {
96
+ return opts.transformFn ? await transformManifestAssets(opts.base, opts.transformFn, { inlineCss: opts.inlineCss }) : buildManifestWithClientEntry(opts.base, { inlineCss: opts.inlineCss });
97
+ }
98
+ async function resolveFinalManifest(opts) {
99
+ const computeFinalManifest = async () => {
100
+ return buildFinalManifest({
101
+ base: await opts.getBaseManifest(),
102
+ transformFn: opts.transformFn,
103
+ inlineCss: opts.inlineCss
104
+ });
105
+ };
106
+ if (opts.finalManifestCache && (!opts.transformFn || opts.cache)) return getOrCreateCachedFinalManifestPromise(opts.finalManifestCache, getFinalManifestCacheKey(opts.inlineCss), computeFinalManifest);
107
+ return computeFinalManifest();
108
+ }
109
+ function warmupFinalManifest(opts) {
110
+ if (!opts.enabled || opts.handlerDefaultInlineCss === void 0 || !opts.cache) return;
111
+ const inlineCss = opts.handlerDefaultInlineCss;
112
+ const warmupPromise = getOrCreateCachedFinalManifestPromise(opts.finalManifestCache, getFinalManifestCacheKey(inlineCss), async () => {
113
+ const [base, transformFn] = await Promise.all([opts.getBaseManifest(), opts.getTransformFn()]);
114
+ return buildFinalManifest({
115
+ base,
116
+ transformFn,
117
+ inlineCss
118
+ });
119
+ });
120
+ if (opts.onError) warmupPromise.catch(opts.onError);
121
+ return warmupPromise;
122
+ }
123
+ //#endregion
124
+ export { createCachedBaseManifestLoader, createFinalManifestResolver };
125
+
126
+ //# sourceMappingURL=finalManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finalManifest.js","names":[],"sources":["../../src/finalManifest.ts"],"sourcesContent":["import {\n buildManifestWithClientEntry,\n resolveTransformAssetsConfig,\n transformManifestAssets,\n} from './transformAssetUrls'\nimport {\n getStaticHandlerInlineCssDefault,\n resolveInlineCssForRequest,\n} from './inlineCss'\nimport type { Manifest } from '@tanstack/router-core'\nimport type { HandlerInlineCssOption } from './inlineCss'\nimport type {\n CreateTransformAssetsContext,\n StartManifestWithClientEntry,\n TransformAssets,\n TransformAssetsFn,\n} from './transformAssetUrls'\n\nexport type {\n HandlerInlineCssOption,\n StartManifestWithClientEntry,\n TransformAssets,\n}\n\nexport interface FinalManifestOptions {\n /**\n * Controls whether Start inlines build-collected CSS by default at runtime.\n *\n * This only has an effect when the build was created with\n * `server.build.inlineCss` enabled. Pass a callback to decide per request.\n * `handler(request, { inlineCss })` overrides this value for that request.\n *\n * @default true\n */\n inlineCss?: HandlerInlineCssOption\n /**\n * Transform manifest-managed asset URLs and attributes at runtime, e.g. to\n * prepend a CDN prefix.\n *\n * This covers JS preloads, CSS links, the client entry script, and URLs\n * inside build-collected inline CSS. Asset imports used directly in\n * components should be handled by the bundler instead.\n */\n transformAssets?: TransformAssets\n}\n\ntype FinalManifestCacheKey = 'inline-css' | 'linked-css'\ntype FinalManifestCache = Map<FinalManifestCacheKey, Promise<Manifest>>\nexport type GetBaseManifest = () => Promise<StartManifestWithClientEntry>\n\nexport interface FinalManifestRequestOptions {\n request: Request\n requestInlineCss: boolean | undefined\n getBaseManifest: GetBaseManifest\n}\n\ninterface FinalManifestTransformResolver {\n cache: boolean\n warmup: boolean\n getTransformFn: (\n ctx: CreateTransformAssetsContext,\n ) => Promise<TransformAssetsFn | undefined>\n clearCachedCreateTransform: () => void\n}\n\nexport interface FinalManifestResolver {\n warmup: (opts: {\n getBaseManifest: GetBaseManifest\n }) => Promise<Manifest> | undefined\n resolveCached: (opts: FinalManifestRequestOptions) => Promise<Manifest>\n resolveUncached: (opts: FinalManifestRequestOptions) => Promise<Manifest>\n}\n\nexport function createCachedBaseManifestLoader(\n loadBaseManifest: GetBaseManifest,\n): GetBaseManifest {\n let baseManifestPromise: Promise<StartManifestWithClientEntry> | undefined\n\n return () => {\n if (!baseManifestPromise) {\n baseManifestPromise = loadBaseManifest().catch((error) => {\n baseManifestPromise = undefined\n throw error\n })\n }\n\n return baseManifestPromise\n }\n}\n\nfunction createFinalManifestTransformResolver(\n transformAssets: TransformAssets | undefined,\n opts: { cacheCreateTransform: boolean },\n): FinalManifestTransformResolver {\n const transformConfig =\n transformAssets !== undefined\n ? resolveTransformAssetsConfig(transformAssets)\n : undefined\n const cache = transformConfig ? transformConfig.cache : true\n const warmup =\n !!transformAssets &&\n typeof transformAssets === 'object' &&\n 'warmup' in transformAssets &&\n transformAssets.warmup === true\n\n let cachedCreateTransformPromise: Promise<TransformAssetsFn> | undefined\n\n const clearCachedCreateTransform = () => {\n cachedCreateTransformPromise = undefined\n }\n\n return {\n cache,\n warmup,\n clearCachedCreateTransform,\n getTransformFn: async (ctx) => {\n if (!transformConfig) return undefined\n\n if (transformConfig.type !== 'createTransform') {\n return transformConfig.transformFn\n }\n\n if (!cache || !opts.cacheCreateTransform) {\n return transformConfig.createTransform(ctx)\n }\n\n if (!cachedCreateTransformPromise) {\n cachedCreateTransformPromise = Promise.resolve(\n transformConfig.createTransform(ctx),\n ).catch((error) => {\n clearCachedCreateTransform()\n throw error\n })\n }\n\n return cachedCreateTransformPromise\n },\n }\n}\n\nexport function createFinalManifestResolver(\n opts: FinalManifestOptions & { cacheCreateTransform: boolean },\n): FinalManifestResolver {\n const finalManifestCache: FinalManifestCache = new Map()\n const transformResolver = createFinalManifestTransformResolver(\n opts.transformAssets,\n { cacheCreateTransform: opts.cacheCreateTransform },\n )\n const handlerDefaultInlineCss = getStaticHandlerInlineCssDefault(\n opts.inlineCss,\n )\n\n const getRequestManifestOptions = async (\n requestOpts: FinalManifestRequestOptions,\n ) => {\n const transformFn = await transformResolver.getTransformFn({\n warmup: false,\n request: requestOpts.request,\n })\n const inlineCss = await resolveInlineCssForRequest({\n request: requestOpts.request,\n handlerInlineCss: opts.inlineCss,\n requestInlineCss: requestOpts.requestInlineCss,\n })\n\n return {\n getBaseManifest: requestOpts.getBaseManifest,\n transformFn,\n cache: transformResolver.cache,\n inlineCss,\n }\n }\n\n const resolveRequest = async (\n requestOpts: FinalManifestRequestOptions,\n cache: FinalManifestCache | undefined,\n ) => {\n return resolveFinalManifest({\n ...(await getRequestManifestOptions(requestOpts)),\n finalManifestCache: cache,\n })\n }\n\n return {\n warmup: ({ getBaseManifest }) =>\n warmupFinalManifest({\n enabled: transformResolver.warmup,\n handlerDefaultInlineCss,\n cache: transformResolver.cache,\n finalManifestCache,\n getBaseManifest,\n getTransformFn: () =>\n transformResolver.getTransformFn({ warmup: true }),\n onError: transformResolver.clearCachedCreateTransform,\n }),\n resolveCached: (requestOpts) =>\n resolveRequest(requestOpts, finalManifestCache),\n resolveUncached: (requestOpts) => resolveRequest(requestOpts, undefined),\n }\n}\n\nfunction getFinalManifestCacheKey(inlineCss: boolean): FinalManifestCacheKey {\n return inlineCss ? 'inline-css' : 'linked-css'\n}\n\nfunction cacheFinalManifestPromise(\n cachedFinalManifestPromises: FinalManifestCache,\n cacheKey: FinalManifestCacheKey,\n promise: Promise<Manifest>,\n): Promise<Manifest> {\n const cachedFinalManifestPromise = promise.catch((error) => {\n if (\n cachedFinalManifestPromises.get(cacheKey) === cachedFinalManifestPromise\n ) {\n cachedFinalManifestPromises.delete(cacheKey)\n }\n throw error\n })\n\n cachedFinalManifestPromises.set(cacheKey, cachedFinalManifestPromise)\n return cachedFinalManifestPromise\n}\n\nfunction getOrCreateCachedFinalManifestPromise(\n cachedFinalManifestPromises: FinalManifestCache,\n cacheKey: FinalManifestCacheKey,\n computeFinalManifest: () => Promise<Manifest>,\n): Promise<Manifest> {\n const cachedFinalManifestPromise = cachedFinalManifestPromises.get(cacheKey)\n if (cachedFinalManifestPromise) {\n return cachedFinalManifestPromise\n }\n\n return cacheFinalManifestPromise(\n cachedFinalManifestPromises,\n cacheKey,\n Promise.resolve().then(computeFinalManifest),\n )\n}\n\nasync function buildFinalManifest(opts: {\n base: StartManifestWithClientEntry\n transformFn: TransformAssetsFn | undefined\n inlineCss: boolean\n}): Promise<Manifest> {\n return opts.transformFn\n ? await transformManifestAssets(opts.base, opts.transformFn, {\n inlineCss: opts.inlineCss,\n })\n : buildManifestWithClientEntry(opts.base, { inlineCss: opts.inlineCss })\n}\n\nasync function resolveFinalManifest(opts: {\n getBaseManifest: () => Promise<StartManifestWithClientEntry>\n transformFn: TransformAssetsFn | undefined\n cache: boolean\n inlineCss: boolean\n finalManifestCache?: FinalManifestCache\n}): Promise<Manifest> {\n const computeFinalManifest = async () => {\n return buildFinalManifest({\n base: await opts.getBaseManifest(),\n transformFn: opts.transformFn,\n inlineCss: opts.inlineCss,\n })\n }\n\n if (opts.finalManifestCache && (!opts.transformFn || opts.cache)) {\n return getOrCreateCachedFinalManifestPromise(\n opts.finalManifestCache,\n getFinalManifestCacheKey(opts.inlineCss),\n computeFinalManifest,\n )\n }\n\n return computeFinalManifest()\n}\n\nfunction warmupFinalManifest(opts: {\n enabled: boolean\n handlerDefaultInlineCss: boolean | undefined\n cache: boolean\n finalManifestCache: FinalManifestCache\n getBaseManifest: () => Promise<StartManifestWithClientEntry>\n getTransformFn: () => Promise<TransformAssetsFn | undefined>\n onError?: () => void\n}): Promise<Manifest> | undefined {\n if (\n !opts.enabled ||\n opts.handlerDefaultInlineCss === undefined ||\n !opts.cache\n ) {\n return undefined\n }\n\n const inlineCss = opts.handlerDefaultInlineCss\n const warmupPromise = getOrCreateCachedFinalManifestPromise(\n opts.finalManifestCache,\n getFinalManifestCacheKey(inlineCss),\n async () => {\n const [base, transformFn] = await Promise.all([\n opts.getBaseManifest(),\n opts.getTransformFn(),\n ])\n\n return buildFinalManifest({\n base,\n transformFn,\n inlineCss,\n })\n },\n )\n\n if (opts.onError) {\n void warmupPromise.catch(opts.onError)\n }\n\n return warmupPromise\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  export { createStartHandler } from './createStartHandler.js';
2
2
  export type { CreateStartHandlerOptions } from './createStartHandler.js';
3
- export type { TransformAssets, TransformAssetsFn, TransformAssetsContext, TransformAssetsOptions, TransformAssetsObjectShorthand, TransformAssetsCrossOriginConfig, TransformAssetResult, TransformAssetUrls, TransformAssetUrlsFn, TransformAssetUrlsContext, TransformAssetUrlsOptions, AssetUrlType, TransformAssetKind, } from './transformAssetUrls.js';
3
+ export type { TransformAssets, TransformAssetsFn, TransformAssetsContext, TransformAssetsOptions, TransformAssetsObjectShorthand, TransformAssetsCrossOriginConfig, TransformAssetResult, TransformAssetKind, CreateTransformAssetsContext, } from './transformAssetUrls.js';
4
4
  export { attachRouterServerSsrUtils, createRequestHandler, defineHandlerCallback, transformReadableStreamWithRouter, transformPipeableStreamWithRouter, } from '@tanstack/router-core/ssr/server';
5
5
  export type { HandlerCallback } from '@tanstack/router-core/ssr/server';
6
6
  export * from './request-response.js';
@@ -0,0 +1,10 @@
1
+ import { Awaitable } from '@tanstack/router-core';
2
+ export type HandlerInlineCssOption = boolean | ((ctx: {
3
+ request: Request;
4
+ }) => Awaitable<boolean>);
5
+ export declare function getStaticHandlerInlineCssDefault(handlerInlineCss: HandlerInlineCssOption | undefined): boolean | undefined;
6
+ export declare function resolveInlineCssForRequest(opts: {
7
+ request: Request;
8
+ handlerInlineCss: HandlerInlineCssOption | undefined;
9
+ requestInlineCss: boolean | undefined;
10
+ }): Promise<boolean>;
@@ -0,0 +1,14 @@
1
+ //#region src/inlineCss.ts
2
+ function getStaticHandlerInlineCssDefault(handlerInlineCss) {
3
+ if (typeof handlerInlineCss === "function") return;
4
+ return handlerInlineCss ?? true;
5
+ }
6
+ async function resolveInlineCssForRequest(opts) {
7
+ if (opts.requestInlineCss !== void 0) return opts.requestInlineCss;
8
+ if (typeof opts.handlerInlineCss === "function") return await opts.handlerInlineCss({ request: opts.request });
9
+ return opts.handlerInlineCss ?? true;
10
+ }
11
+ //#endregion
12
+ export { getStaticHandlerInlineCssDefault, resolveInlineCssForRequest };
13
+
14
+ //# sourceMappingURL=inlineCss.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inlineCss.js","names":[],"sources":["../../src/inlineCss.ts"],"sourcesContent":["import type { Awaitable } from '@tanstack/router-core'\n\nexport type HandlerInlineCssOption =\n | boolean\n | ((ctx: { request: Request }) => Awaitable<boolean>)\n\nexport function getStaticHandlerInlineCssDefault(\n handlerInlineCss: HandlerInlineCssOption | undefined,\n) {\n if (typeof handlerInlineCss === 'function') {\n return undefined\n }\n\n return handlerInlineCss ?? true\n}\n\nexport async function resolveInlineCssForRequest(opts: {\n request: Request\n handlerInlineCss: HandlerInlineCssOption | undefined\n requestInlineCss: boolean | undefined\n}) {\n if (opts.requestInlineCss !== undefined) {\n return opts.requestInlineCss\n }\n\n if (typeof opts.handlerInlineCss === 'function') {\n return await opts.handlerInlineCss({ request: opts.request })\n }\n\n return opts.handlerInlineCss ?? true\n}\n"],"mappings":";AAMA,SAAgB,iCACd,kBACA;AACA,KAAI,OAAO,qBAAqB,WAC9B;AAGF,QAAO,oBAAoB;;AAG7B,eAAsB,2BAA2B,MAI9C;AACD,KAAI,KAAK,qBAAqB,KAAA,EAC5B,QAAO,KAAK;AAGd,KAAI,OAAO,KAAK,qBAAqB,WACnC,QAAO,MAAM,KAAK,iBAAiB,EAAE,SAAS,KAAK,SAAS,CAAC;AAG/D,QAAO,KAAK,oBAAoB"}
@@ -42,7 +42,17 @@ type EarlyHintsOptions = {
42
42
  */
43
43
  responseLinkHeader?: boolean | ResponseLinkHeaderOptions;
44
44
  };
45
- export type RequestOptions<TRegister> = EarlyHintsOptions & (TRegister extends {
45
+ type InlineCssOptions = {
46
+ /**
47
+ * Controls whether Start inlines build-collected CSS for this request.
48
+ *
49
+ * This only has an effect when the build was created with
50
+ * `server.build.inlineCss` enabled. Defaults to `true` so builds with inline
51
+ * CSS enabled continue to inline CSS unless a request opts out.
52
+ */
53
+ inlineCss?: boolean;
54
+ };
55
+ export type RequestOptions<TRegister> = EarlyHintsOptions & InlineCssOptions & (TRegister extends {
46
56
  server: {
47
57
  requestContext: infer TRequestContext;
48
58
  };
@@ -1,23 +1,27 @@
1
1
  import { AssetCrossOrigin, Awaitable, Manifest, RouterManagedTag } from '@tanstack/router-core';
2
2
  export type { AssetCrossOrigin };
3
- export type TransformAssetKind = 'modulepreload' | 'stylesheet' | 'clientEntry';
4
- type TransformAssetsShorthandCrossOriginKind = Exclude<TransformAssetKind, 'clientEntry'>;
5
- export type AssetUrlType = TransformAssetKind;
6
- export interface TransformAssetsContext {
3
+ export type TransformAssetsContext = {
7
4
  url: string;
8
- kind: TransformAssetKind;
9
- }
5
+ kind: 'modulepreload';
6
+ } | {
7
+ url: string;
8
+ kind: 'stylesheet';
9
+ } | {
10
+ url: string;
11
+ kind: 'clientEntry';
12
+ } | {
13
+ url: string;
14
+ kind: 'css-url';
15
+ stylesheetHref: string;
16
+ };
17
+ export type TransformAssetKind = TransformAssetsContext['kind'];
18
+ type TransformAssetsShorthandCrossOriginKind = Exclude<TransformAssetKind, 'clientEntry' | 'css-url'>;
10
19
  export type TransformAssetResult = string | {
11
20
  href: string;
12
21
  crossOrigin?: AssetCrossOrigin;
13
22
  };
14
23
  export type TransformAssetsFn = (context: TransformAssetsContext) => Awaitable<TransformAssetResult>;
15
- export interface TransformAssetUrlsContext {
16
- url: string;
17
- type: AssetUrlType;
18
- }
19
- export type TransformAssetUrlsFn = (context: TransformAssetUrlsContext) => Awaitable<string>;
20
- export type CreateTransformAssetUrlsContext = {
24
+ export type CreateTransformAssetsContext = {
21
25
  /** True when the server is computing the cached manifest during startup warmup. */
22
26
  warmup: true;
23
27
  } | {
@@ -30,13 +34,8 @@ export type CreateTransformAssetUrlsContext = {
30
34
  /** False when transforming URLs as part of request handling. */
31
35
  warmup: false;
32
36
  };
33
- /**
34
- * Async factory that runs once per manifest computation and returns the
35
- * per-asset transform.
36
- */
37
- export type CreateTransformAssetUrlsFn = (ctx: CreateTransformAssetUrlsContext) => Awaitable<TransformAssetUrlsFn>;
38
- export type CreateTransformAssetsFn = (ctx: CreateTransformAssetUrlsContext) => Awaitable<TransformAssetsFn>;
39
- type TransformAssetUrlsOptionsBase = {
37
+ export type CreateTransformAssetsFn = (ctx: CreateTransformAssetsContext) => Awaitable<TransformAssetsFn>;
38
+ type TransformAssetsOptionsBase = {
40
39
  /**
41
40
  * Whether to cache the transformed manifest after the first request.
42
41
  *
@@ -60,35 +59,13 @@ type TransformAssetUrlsOptionsBase = {
60
59
  */
61
60
  warmup?: boolean;
62
61
  };
63
- export type TransformAssetUrlsOptions = (TransformAssetUrlsOptionsBase & {
64
- /**
65
- * The transform to apply to asset URLs. Can be a string prefix or a callback.
66
- *
67
- * **String** — prepended to every asset URL.
68
- * **Callback** — receives `{ url, type }` and returns a new URL.
69
- */
70
- transform: string | TransformAssetUrlsFn;
71
- createTransform?: never;
72
- }) | (TransformAssetUrlsOptionsBase & {
73
- /**
74
- * Create a per-asset transform function.
75
- *
76
- * This factory runs once per manifest computation (per request when
77
- * `cache: false`, or once per server when `cache: true`). It can do async
78
- * setup work (fetch config, read from a KV, etc.) and return a fast
79
- * per-asset transformer.
80
- */
81
- createTransform: CreateTransformAssetUrlsFn;
82
- transform?: never;
83
- });
84
- export type TransformAssetsOptions = (TransformAssetUrlsOptionsBase & {
62
+ export type TransformAssetsOptions = (TransformAssetsOptionsBase & {
85
63
  transform: string | TransformAssetsFn;
86
64
  createTransform?: never;
87
- }) | (TransformAssetUrlsOptionsBase & {
65
+ }) | (TransformAssetsOptionsBase & {
88
66
  createTransform: CreateTransformAssetsFn;
89
67
  transform?: never;
90
68
  });
91
- export type TransformAssetUrls = string | TransformAssetUrlsFn | TransformAssetUrlsOptions;
92
69
  /**
93
70
  * Per-kind crossOrigin configuration for the object shorthand.
94
71
  *
@@ -135,10 +112,7 @@ export type ResolvedTransformAssetsConfig = {
135
112
  createTransform: CreateTransformAssetsFn;
136
113
  cache: boolean;
137
114
  };
138
- export declare function warnDeprecatedTransformAssetUrls(): void;
139
115
  export declare function resolveTransformAssetsConfig(transform: TransformAssets): ResolvedTransformAssetsConfig;
140
- export declare function adaptTransformAssetUrlsToTransformAssets(transformFn: TransformAssetUrlsFn): TransformAssetsFn;
141
- export declare function adaptTransformAssetUrlsConfigToTransformAssets(transform: TransformAssetUrls): TransformAssets;
142
116
  export interface StartManifestWithClientEntry {
143
117
  manifest: Manifest;
144
118
  clientEntry: string;
@@ -152,11 +126,14 @@ export interface StartManifestWithClientEntry {
152
126
  export declare function buildClientEntryScriptTag(clientEntry: string, injectedHeadScripts?: string): RouterManagedTag;
153
127
  export declare function transformManifestAssets(source: StartManifestWithClientEntry, transformFn: TransformAssetsFn, _opts?: {
154
128
  clone?: boolean;
129
+ inlineCss?: boolean;
155
130
  }): Promise<Manifest>;
156
131
  /**
157
132
  * Builds a final Manifest from a StartManifestWithClientEntry without any
158
- * URL transforms. Used when no transformAssetUrls option is provided.
133
+ * URL transforms. Used when no transformAssets option is provided.
159
134
  *
160
135
  * Returns a new manifest object so the cached base manifest is never mutated.
161
136
  */
162
- export declare function buildManifestWithClientEntry(source: StartManifestWithClientEntry): Manifest;
137
+ export declare function buildManifestWithClientEntry(source: StartManifestWithClientEntry, opts?: {
138
+ inlineCss?: boolean;
139
+ }): Manifest;