UNPKG

@tanstack/start-server-core

Version:

Modern and scalable routing for React applications

102 lines (101 loc) 3.38 kB
import { rootRouteId } from "@tanstack/router-core"; //#region src/transformAssetUrls.ts /** * Resolves a TransformAssetUrls value (string prefix, callback, or options * object) into a concrete transform function and cache flag. */ function resolveTransformConfig(transform) { if (typeof transform === "string") { const prefix = transform; return { type: "transform", transformFn: ({ url }) => `${prefix}${url}`, cache: true }; } if (typeof transform === "function") return { type: "transform", transformFn: transform, cache: true }; if ("createTransform" in transform && transform.createTransform) return { type: "createTransform", createTransform: transform.createTransform, cache: transform.cache !== false }; return { type: "transform", transformFn: typeof transform.transform === "string" ? (({ url }) => `${transform.transform}${url}`) : transform.transform, cache: transform.cache !== false }; } /** * Builds the client entry `<script>` tag from a (possibly transformed) client * entry URL and optional injected head scripts. */ function buildClientEntryScriptTag(clientEntry, injectedHeadScripts) { let script = `import(${JSON.stringify(clientEntry)})`; if (injectedHeadScripts) script = `${injectedHeadScripts};${script}`; return { tag: "script", attrs: { type: "module", async: true }, children: script }; } /** * Applies a URL transform to every asset URL in the manifest and returns a * new manifest with a client entry script tag appended to the root route's * assets. * * The source manifest is deep-cloned so the cached original is never mutated. */ function transformManifestUrls(source, transformFn, opts) { return (async () => { const manifest = opts?.clone ? structuredClone(source.manifest) : source.manifest; for (const route of Object.values(manifest.routes)) { if (route.preloads) route.preloads = await Promise.all(route.preloads.map((url) => Promise.resolve(transformFn({ url, type: "modulepreload" })))); if (route.assets) { for (const asset of route.assets) if (asset.tag === "link" && asset.attrs?.href) asset.attrs.href = await Promise.resolve(transformFn({ url: asset.attrs.href, type: "stylesheet" })); } } const transformedClientEntry = await Promise.resolve(transformFn({ url: source.clientEntry, type: "clientEntry" })); const rootRoute = manifest.routes[rootRouteId]; if (rootRoute) { rootRoute.assets = rootRoute.assets || []; rootRoute.assets.push(buildClientEntryScriptTag(transformedClientEntry, source.injectedHeadScripts)); } return manifest; })(); } /** * Builds a final Manifest from a StartManifestWithClientEntry without any * URL transforms. Used when no transformAssetUrls option is provided. * * Returns a new manifest object so the cached base manifest is never mutated. */ function buildManifestWithClientEntry(source) { const scriptTag = buildClientEntryScriptTag(source.clientEntry, source.injectedHeadScripts); const baseRootRoute = source.manifest.routes[rootRouteId]; return { routes: { ...source.manifest.routes, ...baseRootRoute ? { [rootRouteId]: { ...baseRootRoute, assets: [...baseRootRoute.assets || [], scriptTag] } } : {} } }; } //#endregion export { buildManifestWithClientEntry, resolveTransformConfig, transformManifestUrls }; //# sourceMappingURL=transformAssetUrls.js.map