@domphy/app 0.4.0 → 0.5.0
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.
- package/dist/app.global.js +3 -3
- package/dist/app.global.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -2
- package/dist/index.d.ts +83 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/matcher.ts","../src/navigation.ts","../src/api.ts","../src/app.ts","../src/metadata.ts","../src/router.ts","../src/dataCache.ts","../src/history.ts","../src/tree.ts","../src/image.ts","../src/link.ts","../src/script.ts","../src/types.ts"],"sourcesContent":["export * from \"./api.js\";\nexport * from \"./app.js\";\nexport * from \"./dataCache.js\";\nexport * from \"./history.js\";\nexport * from \"./image.js\";\nexport * from \"./link.js\";\nexport * from \"./matcher.js\";\nexport * from \"./metadata.js\";\nexport * from \"./navigation.js\";\nexport * from \"./router.js\";\nexport * from \"./script.js\";\nexport * from \"./tree.js\";\nexport * from \"./types.js\";\n","import type { Params, Route } from \"./types.js\";\n\nexport type SegmentKind =\n | \"static\"\n | \"dynamic\"\n | \"catchall\"\n | \"optional-catchall\"\n | \"group\";\n\nexport interface PatternSegment {\n kind: SegmentKind;\n /** Literal value for static segments, param name otherwise. */\n value: string;\n}\n\n/** One routable endpoint: the chain of route nodes from root to the segment that owns the page. */\nexport interface CompiledRoute {\n /** Stable id, the full pattern path including groups, e.g. \"/(shop)/products/[id]\". */\n id: string;\n /** URL pattern segments, groups excluded. */\n segments: PatternSegment[];\n /** Route nodes from root to leaf. */\n chain: Route[];\n /** Segment id for each chain node, used as data cache key and diff key. */\n chainIds: string[];\n}\n\nexport interface RouteMatch {\n route: CompiledRoute;\n params: Params;\n pathname: string;\n}\n\nexport function parseSegment(part: string): PatternSegment {\n if (part.startsWith(\"(\") && part.endsWith(\")\")) {\n return { kind: \"group\", value: part.slice(1, -1) };\n }\n if (part.startsWith(\"[[...\") && part.endsWith(\"]]\")) {\n return { kind: \"optional-catchall\", value: part.slice(5, -2) };\n }\n if (part.startsWith(\"[...\") && part.endsWith(\"]\")) {\n return { kind: \"catchall\", value: part.slice(4, -1) };\n }\n if (part.startsWith(\"[\") && part.endsWith(\"]\")) {\n return { kind: \"dynamic\", value: part.slice(1, -1) };\n }\n return { kind: \"static\", value: part };\n}\n\nexport function splitPath(path: string): string[] {\n return path.split(\"/\").filter((part) => part.length > 0);\n}\n\n/** Flattens a route tree into a list of routable endpoints. */\nexport function compileRoutes(routes: Route[]): CompiledRoute[] {\n const compiled: CompiledRoute[] = [];\n\n function walk(\n nodes: Route[],\n parentSegments: PatternSegment[],\n parentChain: Route[],\n parentChainIds: string[],\n parentId: string,\n ): void {\n for (const node of nodes) {\n const parts = splitPath(node.path);\n const ownSegments = parts.map(parseSegment);\n const urlSegments = [\n ...parentSegments,\n ...ownSegments.filter((segment) => segment.kind !== \"group\"),\n ];\n const id = `${parentId}/${parts.join(\"/\")}`.replace(/\\/+/g, \"/\");\n const chain = [...parentChain, node];\n const chainIds = [...parentChainIds, id === \"\" ? \"/\" : id];\n\n if (node.page || node.redirect) {\n compiled.push({\n id: id === \"\" ? \"/\" : id,\n segments: urlSegments,\n chain,\n chainIds,\n });\n }\n if (node.children) {\n walk(node.children, urlSegments, chain, chainIds, id);\n }\n }\n }\n\n walk(routes, [], [], [], \"\");\n compiled.sort(compareSpecificity);\n return compiled;\n}\n\nconst KIND_RANK: Record<SegmentKind, number> = {\n static: 0,\n dynamic: 1,\n catchall: 2,\n \"optional-catchall\": 3,\n group: 0,\n};\n\n/** Static segments win over dynamic, dynamic over catch-all — same priority order as Next.js. */\nexport function compareSpecificity(a: CompiledRoute, b: CompiledRoute): number {\n const length = Math.max(a.segments.length, b.segments.length);\n for (let i = 0; i < length; i++) {\n const segmentA = a.segments[i];\n const segmentB = b.segments[i];\n if (!segmentA) return -1;\n if (!segmentB) return 1;\n const rankDifference = KIND_RANK[segmentA.kind] - KIND_RANK[segmentB.kind];\n if (rankDifference !== 0) return rankDifference;\n }\n return 0;\n}\n\nexport function matchPath(\n segments: PatternSegment[],\n pathname: string,\n): Params | null {\n const parts = splitPath(pathname).map((part) => decodeURIComponent(part));\n const params: Params = {};\n let partIndex = 0;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n const isLast = i === segments.length - 1;\n\n if (segment.kind === \"static\") {\n if (parts[partIndex] !== segment.value) return null;\n partIndex++;\n continue;\n }\n if (segment.kind === \"dynamic\") {\n if (partIndex >= parts.length) return null;\n params[segment.value] = parts[partIndex];\n partIndex++;\n continue;\n }\n if (segment.kind === \"catchall\") {\n if (!isLast || partIndex >= parts.length) return null;\n params[segment.value] = parts.slice(partIndex);\n return params;\n }\n if (segment.kind === \"optional-catchall\") {\n if (!isLast) return null;\n params[segment.value] = parts.slice(partIndex);\n return params;\n }\n }\n\n if (partIndex !== parts.length) return null;\n return params;\n}\n\nexport function matchRoute(\n compiled: CompiledRoute[],\n pathname: string,\n): RouteMatch | null {\n for (const route of compiled) {\n const params = matchPath(route.segments, pathname);\n if (params) {\n return { route, params, pathname };\n }\n }\n return null;\n}\n\n/** Replaces pattern placeholders with params, the inverse of `matchPath`. */\nexport function buildHref(pattern: string, params: Params = {}): string {\n const parts = splitPath(pattern)\n .map(parseSegment)\n .filter((segment) => segment.kind !== \"group\")\n .flatMap((segment) => {\n if (segment.kind === \"static\") return [segment.value];\n const value = params[segment.value];\n if (value === undefined) {\n if (segment.kind === \"optional-catchall\") return [];\n throw new Error(\n `Missing param \"${segment.value}\" for pattern \"${pattern}\".`,\n );\n }\n const list = Array.isArray(value) ? value : [value];\n return list.map((part) => encodeURIComponent(part));\n });\n return `/${parts.join(\"/\")}`;\n}\n","import type { RewriteResult } from \"./types.js\";\n\n/**\n * Control-flow signals, the equivalents of `redirect()`, `permanentRedirect()` and\n * `notFound()` from `next/navigation`. They throw and are caught by the router\n * (or by `renderToString` on the server), so they can be called from loaders,\n * metadata functions and middleware.\n */\n\nexport class RedirectSignal extends Error {\n readonly to: string;\n readonly permanent: boolean;\n\n constructor(to: string, permanent: boolean) {\n super(`Redirect to ${to}`);\n this.name = \"RedirectSignal\";\n this.to = to;\n this.permanent = permanent;\n }\n}\n\nexport class NotFoundSignal extends Error {\n constructor() {\n super(\"Not found\");\n this.name = \"NotFoundSignal\";\n }\n}\n\nexport function redirect(to: string): never {\n throw new RedirectSignal(to, false);\n}\n\nexport function permanentRedirect(to: string): never {\n throw new RedirectSignal(to, true);\n}\n\nexport function notFound(): never {\n throw new NotFoundSignal();\n}\n\n/** Returned from middleware to render another route while keeping the URL. */\nexport function rewrite(to: string): RewriteResult {\n return { __domphyRewrite: to };\n}\n\nexport function isRewrite(value: unknown): value is RewriteResult {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as RewriteResult).__domphyRewrite === \"string\"\n );\n}\n","import { compileRoutes, matchRoute } from \"./matcher.js\";\nimport { NotFoundSignal, RedirectSignal } from \"./navigation.js\";\nimport type { Params, Route } from \"./types.js\";\n\n/**\n * API route handlers on web-standard Request/Response, the equivalent of\n * `route.ts` files. Works in Node 18+, Bun, Deno, and edge runtimes; adapt to\n * `http.createServer` with any Request/Response bridge.\n */\n\nexport type HttpMethod =\n | \"GET\"\n | \"POST\"\n | \"PUT\"\n | \"PATCH\"\n | \"DELETE\"\n | \"HEAD\"\n | \"OPTIONS\";\n\nexport interface ApiContext {\n params: Params;\n}\n\nexport type ApiMethodHandler = (\n request: Request,\n context: ApiContext,\n) => Response | Promise<Response>;\n\nexport interface ApiRoute {\n /** Same pattern syntax as page routes: `\"/api/users/[id]\"`. */\n path: string;\n GET?: ApiMethodHandler;\n POST?: ApiMethodHandler;\n PUT?: ApiMethodHandler;\n PATCH?: ApiMethodHandler;\n DELETE?: ApiMethodHandler;\n HEAD?: ApiMethodHandler;\n OPTIONS?: ApiMethodHandler;\n}\n\nconst METHODS: HttpMethod[] = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n \"OPTIONS\",\n];\n\n/** Shorthand for JSON responses, the equivalent of `NextResponse.json()`. */\nexport function json(data: unknown, init: ResponseInit = {}): Response {\n const headers = new Headers(init.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json; charset=utf-8\");\n }\n return new Response(JSON.stringify(data), { ...init, headers });\n}\n\nexport function createApiHandler(\n routes: ApiRoute[],\n): (request: Request) => Promise<Response> {\n const pairs = routes.map((apiRoute) => ({\n apiRoute,\n routeNode: { path: apiRoute.path, page: () => ({ div: \"\" }) } as Route,\n }));\n const compiled = compileRoutes(pairs.map((pair) => pair.routeNode));\n const byNode = new Map(pairs.map((pair) => [pair.routeNode, pair.apiRoute]));\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const match = matchRoute(compiled, url.pathname);\n if (!match) {\n return json({ error: \"Not Found\" }, { status: 404 });\n }\n\n const route = byNode.get(\n match.route.chain[match.route.chain.length - 1],\n ) as ApiRoute;\n const allowed = METHODS.filter((method) => route[method]);\n const method = request.method.toUpperCase() as HttpMethod;\n let handler = route[method];\n\n if (!handler && method === \"HEAD\" && route.GET) {\n handler = route.GET;\n }\n if (!handler && method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: { allow: allowed.join(\", \") },\n });\n }\n if (!handler) {\n return json(\n { error: \"Method Not Allowed\" },\n { status: 405, headers: { allow: allowed.join(\", \") } },\n );\n }\n\n try {\n const response = await handler(request, { params: match.params });\n if (method === \"HEAD\") {\n return new Response(null, {\n status: response.status,\n headers: response.headers,\n });\n }\n return response;\n } catch (error) {\n if (error instanceof RedirectSignal) {\n return new Response(null, {\n status: error.permanent ? 308 : 307,\n headers: { location: error.to },\n });\n }\n if (error instanceof NotFoundSignal) {\n return json({ error: \"Not Found\" }, { status: 404 });\n }\n return json({ error: \"Internal Server Error\" }, { status: 500 });\n }\n };\n}\n","import { type DomphyElement, ElementNode } from \"@domphy/core\";\nimport type { HistoryAdapter } from \"./history.js\";\nimport { metadataToHeadTags, renderHeadTags } from \"./metadata.js\";\nimport { AppRouter, type RouterOptions } from \"./router.js\";\nimport type { Route } from \"./types.js\";\n\nexport interface AppOptions extends Omit<RouterOptions, \"history\" | \"headers\"> {\n history?: HistoryAdapter | null;\n}\n\nexport interface RenderToStringOptions {\n headers?: Headers;\n}\n\nexport interface SSRResult {\n /** Body markup of the app root, ready to place inside the mount element. */\n html: string;\n /** Scoped CSS of the rendered tree, place inside `<style id=\"domphy-style\">`. */\n css: string;\n /** Serialized `<title>`, `<meta>` and `<link>` tags for the document head. */\n head: string;\n /** 200, 404, or the redirect status. */\n status: number;\n /** Set when a loader or middleware redirected. */\n redirect?: string;\n /** Loader data to embed for hydration, see `bootstrapScript`. */\n data: Record<string, unknown>;\n /** Inline script that exposes loader data to `hydrate()` on the client. */\n bootstrapScript: string;\n}\n\nconst HYDRATION_GLOBAL = \"__DOMPHY_APP_DATA__\";\n\n/**\n * The app shell: routing, rendering and server rendering in one object, the\n * Domphy equivalent of a Next.js application instance.\n */\nexport class DomphyApp {\n readonly routes: Route[];\n readonly options: AppOptions;\n readonly router: AppRouter;\n private node: ElementNode | null = null;\n\n constructor(routes: Route[], options: AppOptions = {}) {\n this.routes = routes;\n this.options = options;\n this.router = new AppRouter(routes, options);\n }\n\n /** The root element; the whole route tree re-renders through one reactive child. */\n element(): DomphyElement {\n const router = this.router;\n return {\n div: (listener) => [router.tree.get(listener)],\n style: { display: \"contents\" },\n };\n }\n\n /** Client-side render from scratch. */\n async render(target: HTMLElement): Promise<ElementNode> {\n await this.router.start();\n this.node = new ElementNode(this.element());\n this.node.render(target);\n return this.node;\n }\n\n /**\n * Hydrates server-rendered markup. Reads the loader data embedded by\n * `bootstrapScript` so loaders are not re-run and the tree matches the HTML.\n */\n async hydrate(\n target: HTMLElement,\n style?: HTMLStyleElement,\n ): Promise<ElementNode> {\n const seeded = (globalThis as Record<string, unknown>)[HYDRATION_GLOBAL];\n if (seeded && typeof seeded === \"object\") {\n this.router.cache.seed(seeded as Record<string, unknown>);\n }\n await this.router.start();\n this.node = new ElementNode(this.element());\n this.node.mount(target, style);\n return this.node;\n }\n\n destroy(): void {\n this.node?.remove();\n this.node = null;\n this.router.destroy();\n }\n\n /** Server rendering: runs middleware and loaders for `url`, returns markup + CSS + head. */\n async renderToString(\n url: string | URL,\n options: RenderToStringOptions = {},\n ): Promise<SSRResult> {\n const requestUrl =\n typeof url === \"string\" ? new URL(url, \"http://localhost\") : url;\n const serverRouter = new AppRouter(this.routes, {\n ...this.options,\n history: null,\n headers: options.headers,\n });\n\n await serverRouter.transition(requestUrl, { initial: true });\n\n const status = serverRouter.state.get(\"status\");\n const redirect = serverRouter.lastRedirect;\n const node = new ElementNode({\n div: [serverRouter.tree.get()],\n style: { display: \"contents\" },\n });\n\n const data = serverRouter.lastData;\n\n const result: SSRResult = {\n html: node.generateHTML(),\n css: node.generateCSS(),\n head: renderHeadTags(metadataToHeadTags(serverRouter.metadata)),\n status: redirect\n ? redirect.permanent\n ? 308\n : 307\n : status === \"notfound\"\n ? 404\n : 200,\n redirect: redirect?.to,\n data,\n bootstrapScript: `<script>window.${HYDRATION_GLOBAL} = ${serializeData(data)};</script>`,\n };\n serverRouter.destroy();\n return result;\n }\n}\n\n/** JSON with `</script>`-safe escaping so the payload can be inlined. */\nfunction serializeData(data: Record<string, unknown>): string {\n return JSON.stringify(data).replace(/</g, \"\\\\u003c\");\n}\n\nexport function createApp(routes: Route[], options: AppOptions = {}): DomphyApp {\n return new DomphyApp(routes, options);\n}\n","import type { LoaderContext, MetadataValue } from \"./types.js\";\n\n/**\n * Port of the Next.js Metadata API. Static objects merge from root layout to\n * page; later segments override earlier ones. `title.template` applies to the\n * titles of child segments, exactly like Next.js.\n */\n\nexport interface MetadataTitle {\n default?: string;\n template?: string;\n absolute?: string;\n}\n\nexport interface OpenGraphImage {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface OpenGraphMetadata {\n title?: string;\n description?: string;\n url?: string;\n siteName?: string;\n type?: string;\n locale?: string;\n images?: (string | OpenGraphImage)[];\n}\n\nexport interface TwitterMetadata {\n card?: \"summary\" | \"summary_large_image\" | \"app\" | \"player\";\n title?: string;\n description?: string;\n site?: string;\n creator?: string;\n images?: string[];\n}\n\nexport interface RobotsMetadata {\n index?: boolean;\n follow?: boolean;\n noarchive?: boolean;\n nosnippet?: boolean;\n noimageindex?: boolean;\n}\n\nexport interface IconsMetadata {\n icon?: string;\n shortcut?: string;\n apple?: string;\n}\n\nexport interface AlternatesMetadata {\n canonical?: string;\n languages?: Record<string, string>;\n}\n\nexport interface Metadata {\n title?: string | MetadataTitle;\n description?: string;\n applicationName?: string;\n generator?: string;\n keywords?: string[];\n authors?: { name: string; url?: string }[];\n referrer?: string;\n themeColor?: string;\n colorScheme?: string;\n viewport?: string;\n robots?: string | RobotsMetadata;\n icons?: string | IconsMetadata;\n openGraph?: OpenGraphMetadata;\n twitter?: TwitterMetadata;\n alternates?: AlternatesMetadata;\n metadataBase?: string;\n /** Arbitrary extra meta tags: name -> content. */\n other?: Record<string, string>;\n}\n\nexport interface ResolvedMetadata extends Omit<Metadata, \"title\"> {\n title?: string;\n}\n\nexport interface HeadTag {\n tag: \"title\" | \"meta\" | \"link\";\n attributes: Record<string, string>;\n content?: string;\n}\n\n/** Resolves the metadata chain of all matched segments into one flat object. */\nexport async function resolveMetadata(\n values: (MetadataValue | undefined)[],\n context: LoaderContext,\n): Promise<ResolvedMetadata> {\n const resolved: ResolvedMetadata = {};\n let template: string | null = null;\n\n for (const value of values) {\n if (!value) continue;\n const metadata = typeof value === \"function\" ? await value(context) : value;\n\n for (const key of Object.keys(metadata) as (keyof Metadata)[]) {\n if (key === \"title\") continue;\n const entry = metadata[key];\n if (entry !== undefined) {\n (resolved as Record<string, unknown>)[key] = entry;\n }\n }\n\n const title = metadata.title;\n if (title === undefined) continue;\n if (typeof title === \"string\") {\n resolved.title = template ? template.replace(\"%s\", title) : title;\n continue;\n }\n if (title.absolute !== undefined) {\n resolved.title = title.absolute;\n } else if (title.default !== undefined) {\n resolved.title = template\n ? template.replace(\"%s\", title.default)\n : title.default;\n }\n if (title.template !== undefined) {\n template = title.template;\n }\n }\n\n return resolved;\n}\n\nfunction absoluteUrl(url: string, base: string | undefined): string {\n if (!base || /^[a-z][a-z0-9+.-]*:/i.test(url)) return url;\n return new URL(url, base).toString();\n}\n\nfunction robotsContent(robots: string | RobotsMetadata): string {\n if (typeof robots === \"string\") return robots;\n const directives: string[] = [];\n directives.push(robots.index === false ? \"noindex\" : \"index\");\n directives.push(robots.follow === false ? \"nofollow\" : \"follow\");\n if (robots.noarchive) directives.push(\"noarchive\");\n if (robots.nosnippet) directives.push(\"nosnippet\");\n if (robots.noimageindex) directives.push(\"noimageindex\");\n return directives.join(\", \");\n}\n\n/** Converts resolved metadata into a flat list of head tag descriptions. */\nexport function metadataToHeadTags(metadata: ResolvedMetadata): HeadTag[] {\n const tags: HeadTag[] = [];\n const base = metadata.metadataBase;\n const meta = (name: string, content: string | undefined) => {\n if (content !== undefined)\n tags.push({ tag: \"meta\", attributes: { name, content } });\n };\n const property = (name: string, content: string | undefined) => {\n if (content !== undefined) {\n tags.push({ tag: \"meta\", attributes: { property: name, content } });\n }\n };\n\n if (metadata.title !== undefined) {\n tags.push({ tag: \"title\", attributes: {}, content: metadata.title });\n }\n meta(\"description\", metadata.description);\n meta(\"application-name\", metadata.applicationName);\n meta(\"generator\", metadata.generator);\n meta(\"keywords\", metadata.keywords?.join(\", \"));\n meta(\"referrer\", metadata.referrer);\n meta(\"theme-color\", metadata.themeColor);\n meta(\"color-scheme\", metadata.colorScheme);\n meta(\"viewport\", metadata.viewport);\n if (metadata.robots !== undefined)\n meta(\"robots\", robotsContent(metadata.robots));\n for (const author of metadata.authors ?? []) {\n meta(\"author\", author.name);\n if (author.url) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"author\", href: author.url },\n });\n }\n }\n\n if (metadata.icons !== undefined) {\n const icons =\n typeof metadata.icons === \"string\"\n ? { icon: metadata.icons }\n : metadata.icons;\n if (icons.icon)\n tags.push({ tag: \"link\", attributes: { rel: \"icon\", href: icons.icon } });\n if (icons.shortcut) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"shortcut icon\", href: icons.shortcut },\n });\n }\n if (icons.apple) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"apple-touch-icon\", href: icons.apple },\n });\n }\n }\n\n const openGraph = metadata.openGraph;\n if (openGraph) {\n property(\"og:title\", openGraph.title ?? metadata.title);\n property(\"og:description\", openGraph.description ?? metadata.description);\n property(\n \"og:url\",\n openGraph.url ? absoluteUrl(openGraph.url, base) : undefined,\n );\n property(\"og:site_name\", openGraph.siteName);\n property(\"og:type\", openGraph.type);\n property(\"og:locale\", openGraph.locale);\n for (const image of openGraph.images ?? []) {\n const value = typeof image === \"string\" ? { url: image } : image;\n property(\"og:image\", absoluteUrl(value.url, base));\n if (value.width !== undefined)\n property(\"og:image:width\", String(value.width));\n if (value.height !== undefined)\n property(\"og:image:height\", String(value.height));\n if (value.alt !== undefined) property(\"og:image:alt\", value.alt);\n }\n }\n\n const twitter = metadata.twitter;\n if (twitter) {\n meta(\"twitter:card\", twitter.card ?? \"summary\");\n meta(\"twitter:title\", twitter.title ?? metadata.title);\n meta(\"twitter:description\", twitter.description ?? metadata.description);\n meta(\"twitter:site\", twitter.site);\n meta(\"twitter:creator\", twitter.creator);\n for (const image of twitter.images ?? []) {\n meta(\"twitter:image\", absoluteUrl(image, base));\n }\n }\n\n const alternates = metadata.alternates;\n if (alternates) {\n if (alternates.canonical) {\n tags.push({\n tag: \"link\",\n attributes: {\n rel: \"canonical\",\n href: absoluteUrl(alternates.canonical, base),\n },\n });\n }\n for (const language of Object.keys(alternates.languages ?? {})) {\n tags.push({\n tag: \"link\",\n attributes: {\n rel: \"alternate\",\n hreflang: language,\n href: absoluteUrl(\n (alternates.languages as Record<string, string>)[language],\n base,\n ),\n },\n });\n }\n }\n\n for (const name of Object.keys(metadata.other ?? {})) {\n meta(name, (metadata.other as Record<string, string>)[name]);\n }\n\n return tags;\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\");\n}\n\nfunction escapeText(value: string): string {\n return value.replace(/&/g, \"&\").replace(/</g, \"<\");\n}\n\n/** Serializes head tags for server rendering. */\nexport function renderHeadTags(tags: HeadTag[]): string {\n return tags\n .map((tag) => {\n const attributes = Object.keys(tag.attributes)\n .map((name) => ` ${name}=\"${escapeAttribute(tag.attributes[name])}\"`)\n .join(\"\");\n if (tag.tag === \"title\") {\n return `<title>${escapeText(tag.content ?? \"\")}</title>`;\n }\n return `<${tag.tag}${attributes}>`;\n })\n .join(\"\\n\");\n}\n\nconst MANAGED_ATTRIBUTE = \"data-domphy-head\";\n\n/** Applies head tags to `document.head`, replacing tags from the previous navigation. */\nexport function applyHeadTags(tags: HeadTag[]): void {\n if (typeof document === \"undefined\") return;\n\n for (const element of Array.from(\n document.head.querySelectorAll(`[${MANAGED_ATTRIBUTE}]`),\n )) {\n element.remove();\n }\n\n for (const tag of tags) {\n if (tag.tag === \"title\") {\n document.title = tag.content ?? \"\";\n continue;\n }\n const element = document.createElement(tag.tag);\n for (const name of Object.keys(tag.attributes)) {\n element.setAttribute(name, tag.attributes[name]);\n }\n element.setAttribute(MANAGED_ATTRIBUTE, \"\");\n document.head.appendChild(element);\n }\n}\n","import {\n type DomphyElement,\n Notifier,\n RecordState,\n type State,\n toState,\n} from \"@domphy/core\";\nimport { DataCache } from \"./dataCache.js\";\nimport { createBrowserHistory, type HistoryAdapter } from \"./history.js\";\nimport {\n type CompiledRoute,\n compileRoutes,\n matchRoute,\n type RouteMatch,\n} from \"./matcher.js\";\nimport {\n applyHeadTags,\n metadataToHeadTags,\n type ResolvedMetadata,\n resolveMetadata,\n} from \"./metadata.js\";\nimport { isRewrite, NotFoundSignal, RedirectSignal } from \"./navigation.js\";\nimport {\n buildNotFoundTree,\n buildTree,\n defaultErrorBlock,\n defaultNotFoundBlock,\n type SegmentResult,\n} from \"./tree.js\";\nimport type {\n ErrorBlock,\n LoaderContext,\n Middleware,\n NavigateOptions,\n NotFoundBlock,\n Route,\n RouterEventName,\n RouterStateRecord,\n} from \"./types.js\";\n\nexport interface RouterOptions {\n /** Defaults to the browser history in a DOM environment, otherwise none (SSR). */\n history?: HistoryAdapter | null;\n /** Global middleware, the equivalent of `middleware.ts`. */\n middleware?: Middleware[];\n /** App-level not-found block, the equivalent of the root `not-found.tsx`. */\n notFound?: NotFoundBlock;\n /** App-level error block, the equivalent of `global-error.tsx`. */\n error?: ErrorBlock;\n /** Request headers, forwarded to loaders and middleware during server rendering. */\n headers?: Headers;\n}\n\ninterface TransitionOptions {\n replace?: boolean;\n scroll?: boolean;\n fromHistory?: boolean;\n initial?: boolean;\n}\n\nlet defaultRouter: AppRouter | null = null;\n\n/** The most recently created router, used by `navLink` when no router is passed explicitly. */\nexport function getRouter(): AppRouter {\n if (!defaultRouter) {\n throw new Error(\n \"No router created yet. Call createApp() or new AppRouter() first.\",\n );\n }\n return defaultRouter;\n}\n\nexport class AppRouter {\n readonly routes: CompiledRoute[];\n readonly state: RecordState<RouterStateRecord>;\n readonly tree: State<DomphyElement>;\n readonly events = new Notifier();\n readonly cache = new DataCache();\n\n private history: HistoryAdapter | null;\n private middleware: Middleware[];\n private notFoundBlock: NotFoundBlock;\n private errorBlock: ErrorBlock;\n private headers?: Headers;\n private navigationToken = 0;\n private releaseHistory: (() => void) | null = null;\n private currentMatch: RouteMatch | null = null;\n /** Metadata resolved for the current route, exposed for server rendering. */\n metadata: ResolvedMetadata = {};\n /** The last redirect followed during a transition, exposed for server rendering. */\n lastRedirect: { to: string; permanent: boolean } | null = null;\n /** Loader data of the latest render keyed by cache key, used for SSR payloads. */\n lastData: Record<string, unknown> = {};\n\n constructor(routes: Route[], options: RouterOptions = {}) {\n this.routes = compileRoutes(routes);\n this.middleware = options.middleware ?? [];\n this.notFoundBlock = options.notFound ?? defaultNotFoundBlock;\n this.errorBlock = options.error ?? ((error) => defaultErrorBlock(error));\n this.headers = options.headers;\n this.history =\n options.history !== undefined\n ? options.history\n : typeof window !== \"undefined\"\n ? createBrowserHistory()\n : null;\n\n this.state = new RecordState<RouterStateRecord>({\n pathname: \"/\",\n search: \"\",\n hash: \"\",\n params: {},\n status: \"idle\",\n error: null,\n });\n this.tree = toState<DomphyElement>({ div: \"\" });\n defaultRouter = this;\n }\n\n /** Renders the current URL and starts listening to history navigation. */\n async start(): Promise<void> {\n if (this.history && !this.releaseHistory) {\n this.releaseHistory = this.history.listen((url) => {\n void this.transition(url, { fromHistory: true });\n });\n }\n const url = this.history\n ? this.history.url()\n : new URL(\"/\", \"http://localhost\");\n await this.transition(url, { initial: true });\n }\n\n destroy(): void {\n this.releaseHistory?.();\n this.releaseHistory = null;\n if (defaultRouter === this) defaultRouter = null;\n }\n\n currentUrl(): URL {\n if (this.history) return this.history.url();\n const search = this.state.get(\"search\");\n return new URL(\n `${this.state.get(\"pathname\")}${search}`,\n \"http://localhost\",\n );\n }\n\n resolve(href: string): URL {\n return new URL(href, this.currentUrl());\n }\n\n async navigate(href: string, options: NavigateOptions = {}): Promise<void> {\n const url = this.resolve(href);\n if (\n typeof window !== \"undefined\" &&\n url.origin !== this.currentUrl().origin\n ) {\n window.location.assign(url.href);\n return;\n }\n await this.transition(url, options);\n }\n\n push(\n href: string,\n options: Omit<NavigateOptions, \"replace\"> = {},\n ): Promise<void> {\n return this.navigate(href, options);\n }\n\n replace(\n href: string,\n options: Omit<NavigateOptions, \"replace\"> = {},\n ): Promise<void> {\n return this.navigate(href, { ...options, replace: true });\n }\n\n back(): void {\n this.history?.go(-1);\n }\n\n forward(): void {\n this.history?.go(1);\n }\n\n /** Clears the loader cache and re-renders the current URL, like `router.refresh()`. */\n async refresh(): Promise<void> {\n this.cache.invalidate();\n await this.transition(this.currentUrl(), { replace: true, scroll: false });\n }\n\n /** Runs the loaders of a route ahead of navigation, like `router.prefetch()`. */\n async prefetch(href: string): Promise<void> {\n try {\n const url = this.resolve(href);\n const match = matchRoute(this.routes, url.pathname);\n if (!match) return;\n const context = this.loaderContext(url, match);\n await Promise.all(\n match.route.chain.map((route, index) => {\n if (!route.loader) return Promise.resolve();\n const key = this.cacheKey(match.route.chainIds[index], url);\n return this.cache.prefetch(\n key,\n route.loader,\n context,\n route.revalidate,\n );\n }),\n );\n } catch {\n // Prefetch failures are silent; the real navigation reports errors.\n }\n }\n\n searchParams(\n listener?: Parameters<RecordState<RouterStateRecord>[\"get\"]>[1],\n ): URLSearchParams {\n return new URLSearchParams(this.state.get(\"search\", listener) as string);\n }\n\n addEventListener(\n event: RouterEventName,\n callback: (...args: unknown[]) => void,\n ): () => void {\n return this.events.addListener(event, callback);\n }\n\n /** The match rendered by the latest completed transition, null when no route matched. */\n getMatch(): RouteMatch | null {\n return this.currentMatch;\n }\n\n private cacheKey(segmentId: string, url: URL): string {\n return `${segmentId}|${url.pathname}${url.search}`;\n }\n\n private loaderContext(url: URL, match: RouteMatch): LoaderContext {\n return {\n pathname: match.pathname,\n url: url.pathname + url.search,\n params: match.params,\n searchParams: url.searchParams,\n headers: this.headers,\n };\n }\n\n /** Core navigation pipeline: middleware -> match -> loaders -> tree -> history/scroll. */\n async transition(url: URL, options: TransitionOptions = {}): Promise<void> {\n const token = ++this.navigationToken;\n const href = url.pathname + url.search + url.hash;\n if (!options.fromHistory) this.lastRedirect = null;\n this.events.notify(\"routeChangeStart\", href);\n this.saveScroll();\n\n try {\n let renderPathname = url.pathname;\n const middlewareContext = {\n url,\n pathname: url.pathname,\n searchParams: url.searchParams,\n headers: this.headers,\n };\n for (const middleware of this.middleware) {\n const result = await middleware(middlewareContext);\n if (isRewrite(result)) renderPathname = result.__domphyRewrite;\n }\n if (token !== this.navigationToken) return;\n\n const match = matchRoute(this.routes, renderPathname);\n\n if (match) {\n const leaf = match.route.chain[match.route.chain.length - 1];\n if (leaf.redirect) {\n throw new RedirectSignal(leaf.redirect, leaf.permanent ?? false);\n }\n for (const route of match.route.chain) {\n for (const middleware of route.middleware ?? []) {\n const result = await middleware(middlewareContext);\n if (isRewrite(result)) {\n await this.transition(\n new URL(result.__domphyRewrite, url),\n options,\n );\n return;\n }\n }\n }\n if (token !== this.navigationToken) return;\n await this.renderMatch(url, match, token, options);\n } else {\n await this.renderNotFound(url, token, options);\n }\n } catch (error) {\n if (token !== this.navigationToken) return;\n if (error instanceof RedirectSignal) {\n await this.transition(this.resolve(error.to), {\n ...options,\n replace: true,\n });\n // Set after the inner transition so its entry reset does not erase this.\n this.lastRedirect = { to: error.to, permanent: error.permanent };\n return;\n }\n if (error instanceof NotFoundSignal) {\n await this.renderNotFound(url, token, options);\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n this.tree.set(this.errorBlock(failure, () => void this.refresh()));\n this.state.set(\"status\", \"error\");\n this.state.set(\"error\", failure);\n this.events.notify(\"routeChangeError\", failure, href);\n return;\n }\n\n if (token === this.navigationToken) {\n this.events.notify(\"routeChangeComplete\", href);\n }\n }\n\n private async renderMatch(\n url: URL,\n match: RouteMatch,\n token: number,\n options: TransitionOptions,\n ): Promise<void> {\n const { chain, chainIds } = match.route;\n const context = this.loaderContext(url, match);\n const results: SegmentResult[] = chain.map(() => ({ status: \"pending\" }));\n let redirectSignal: RedirectSignal | null = null;\n\n const promises = chain.map((route, index) => {\n if (!route.loader) {\n results[index] = { status: \"success\", data: undefined };\n return Promise.resolve();\n }\n const key = this.cacheKey(chainIds[index], url);\n return this.cache.load(key, route.loader, context, route.revalidate).then(\n (data) => {\n results[index] = { status: \"success\", data };\n },\n (error) => {\n if (error instanceof RedirectSignal) {\n redirectSignal = redirectSignal ?? error;\n } else if (error instanceof NotFoundSignal) {\n results[index] = { status: \"notfound\" };\n } else {\n results[index] = {\n status: \"error\",\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n },\n );\n });\n\n let settled = false;\n const allSettled = Promise.all(promises).then(() => {\n settled = true;\n });\n\n // Give already-resolved (cached) loaders a chance to finish before showing loading UI.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!settled && chain.some((route) => route.loading)) {\n const interim = buildTree({\n match,\n baseContext: this.baseContext(url, match),\n results: results.map((result) => ({ ...result })),\n retry: () => void this.refresh(),\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n });\n if (token === this.navigationToken && interim.status === \"loading\") {\n this.state.set(\"status\", \"loading\");\n this.tree.set(interim.element);\n }\n }\n\n await allSettled;\n if (token !== this.navigationToken) return;\n if (redirectSignal) throw redirectSignal;\n\n const built = buildTree({\n match,\n baseContext: this.baseContext(url, match),\n results,\n retry: () => void this.refresh(),\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n });\n\n const dataRecord: Record<string, unknown> = {};\n chain.forEach((route, index) => {\n if (route.loader && results[index].status === \"success\") {\n dataRecord[this.cacheKey(chainIds[index], url)] = results[index].data;\n }\n });\n this.lastData = dataRecord;\n\n this.currentMatch = match;\n await this.applyMetadata(match, context);\n if (token !== this.navigationToken) return;\n\n this.commit(url, match, built.element, built.status, options);\n }\n\n private async renderNotFound(\n url: URL,\n token: number,\n options: TransitionOptions,\n ): Promise<void> {\n const built = buildNotFoundTree(this.notFoundBlock);\n this.currentMatch = null;\n this.metadata = {};\n applyHeadTags([]);\n if (token !== this.navigationToken) return;\n this.commit(url, null, built.element, \"notfound\", options);\n }\n\n private baseContext(url: URL, match: RouteMatch) {\n return {\n pathname: match.pathname,\n url: url.pathname + url.search,\n params: match.params,\n searchParams: url.searchParams,\n hash: url.hash,\n headers: this.headers,\n };\n }\n\n private async applyMetadata(\n match: RouteMatch,\n context: LoaderContext,\n ): Promise<void> {\n try {\n this.metadata = await resolveMetadata(\n match.route.chain.map((route) => route.metadata),\n context,\n );\n } catch {\n this.metadata = {};\n }\n applyHeadTags(metadataToHeadTags(this.metadata));\n }\n\n private commit(\n url: URL,\n match: RouteMatch | null,\n element: DomphyElement,\n status: RouterStateRecord[\"status\"],\n options: TransitionOptions,\n ): void {\n if (this.history && !options.fromHistory && !options.initial) {\n const href = url.pathname + url.search + url.hash;\n if (options.replace) {\n this.history.replace(href);\n } else {\n this.history.push(href);\n }\n }\n\n this.state.set(\"pathname\", url.pathname);\n this.state.set(\"search\", url.search);\n this.state.set(\"hash\", url.hash);\n this.state.set(\"params\", match?.params ?? {});\n this.state.set(\"error\", null);\n this.state.set(\"status\", status);\n this.tree.set(element);\n\n this.restoreScroll(url, options);\n }\n\n private saveScroll(): void {\n if (typeof window === \"undefined\") return;\n this.history?.saveScroll?.({ x: window.scrollX, y: window.scrollY });\n }\n\n private restoreScroll(url: URL, options: TransitionOptions): void {\n if (\n typeof window === \"undefined\" ||\n options.scroll === false ||\n options.initial\n )\n return;\n if (options.fromHistory) {\n const position = this.history?.readScroll?.();\n window.scrollTo(position?.x ?? 0, position?.y ?? 0);\n return;\n }\n if (url.hash) {\n const target = document.getElementById(url.hash.slice(1));\n if (target) {\n target.scrollIntoView();\n return;\n }\n }\n window.scrollTo(0, 0);\n }\n}\n","import type { Loader, LoaderContext } from \"./types.js\";\n\ninterface CacheEntry {\n data: unknown;\n timestamp: number;\n /** Entries seeded from SSR or prefetch are consumed once even by uncached loaders. */\n consumable: boolean;\n}\n\n/** How long a prefetched entry stays usable, mirrors the Next.js client router cache. */\nexport const PREFETCH_LIFETIME = 30_000;\n\n/**\n * Loader result cache. The `revalidate` option of a route controls the entry\n * lifetime, the equivalent of fetch caching / ISR in Next.js.\n */\nexport class DataCache {\n private entries = new Map<string, CacheEntry>();\n private inflight = new Map<string, Promise<unknown>>();\n\n /** Seeds entries (from SSR payloads) that satisfy the next load exactly once. */\n seed(record: Record<string, unknown>): void {\n for (const key of Object.keys(record)) {\n this.entries.set(key, {\n data: record[key],\n timestamp: Date.now(),\n consumable: true,\n });\n }\n }\n\n snapshot(keys: string[]): Record<string, unknown> {\n const record: Record<string, unknown> = {};\n for (const key of keys) {\n const entry = this.entries.get(key);\n if (entry) record[key] = entry.data;\n }\n return record;\n }\n\n invalidate(prefix?: string): void {\n if (prefix === undefined) {\n this.entries.clear();\n return;\n }\n for (const key of this.entries.keys()) {\n if (key.startsWith(prefix)) this.entries.delete(key);\n }\n }\n\n async load(\n key: string,\n loader: Loader,\n context: LoaderContext,\n revalidate: number | undefined,\n ): Promise<unknown> {\n const entry = this.entries.get(key);\n if (entry) {\n const lifetime = revalidate !== undefined ? revalidate * 1000 : 0;\n const fresh = Date.now() - entry.timestamp <= lifetime;\n const usableSeed =\n entry.consumable && Date.now() - entry.timestamp <= PREFETCH_LIFETIME;\n if (fresh || usableSeed) {\n if (entry.consumable && !fresh) this.entries.delete(key);\n return entry.data;\n }\n this.entries.delete(key);\n }\n\n const pending = this.inflight.get(key);\n if (pending) return pending;\n\n const promise = Promise.resolve(loader(context)).then(\n (data) => {\n this.inflight.delete(key);\n if (revalidate !== undefined && revalidate > 0) {\n this.entries.set(key, {\n data,\n timestamp: Date.now(),\n consumable: false,\n });\n }\n return data;\n },\n (error) => {\n this.inflight.delete(key);\n throw error;\n },\n );\n this.inflight.set(key, promise);\n return promise;\n }\n\n /** Runs the loader ahead of navigation and stores the result as a one-shot entry. */\n async prefetch(\n key: string,\n loader: Loader,\n context: LoaderContext,\n revalidate: number | undefined,\n ): Promise<void> {\n if (revalidate !== undefined) {\n await this.load(key, loader, context, revalidate);\n return;\n }\n const existing = this.entries.get(key);\n if (existing && Date.now() - existing.timestamp <= PREFETCH_LIFETIME)\n return;\n if (this.inflight.has(key)) return;\n const data = await loader(context);\n this.entries.set(key, { data, timestamp: Date.now(), consumable: true });\n }\n}\n","/**\n * Minimal history abstraction so the router runs against the real browser\n * history, an in-memory stack (tests, embedded demos) or nothing at all (SSR).\n */\n\nexport interface HistoryAdapter {\n url(): URL;\n push(url: string): void;\n replace(url: string): void;\n go(delta: number): void;\n /** Subscribes to external navigation (popstate / memory go). Returns a release function. */\n listen(callback: (url: URL) => void): () => void;\n /** Saves and restores scroll positions per history entry. */\n saveScroll?(position: { x: number; y: number }): void;\n readScroll?(): { x: number; y: number } | null;\n}\n\ninterface BrowserHistoryState {\n __domphyIndex: number;\n}\n\nexport function createBrowserHistory(): HistoryAdapter {\n const scrollPositions = new Map<number, { x: number; y: number }>();\n let index =\n (window.history.state as BrowserHistoryState | null)?.__domphyIndex ?? 0;\n if (window.history.state?.__domphyIndex === undefined) {\n window.history.replaceState({ __domphyIndex: index }, \"\");\n }\n if (\"scrollRestoration\" in window.history) {\n window.history.scrollRestoration = \"manual\";\n }\n\n return {\n url: () => new URL(window.location.href),\n push: (url) => {\n index++;\n window.history.pushState({ __domphyIndex: index }, \"\", url);\n },\n replace: (url) => {\n window.history.replaceState({ __domphyIndex: index }, \"\", url);\n },\n go: (delta) => window.history.go(delta),\n listen: (callback) => {\n const handler = () => {\n index =\n (window.history.state as BrowserHistoryState | null)?.__domphyIndex ??\n 0;\n callback(new URL(window.location.href));\n };\n window.addEventListener(\"popstate\", handler);\n return () => window.removeEventListener(\"popstate\", handler);\n },\n saveScroll: (position) => scrollPositions.set(index, position),\n readScroll: () => scrollPositions.get(index) ?? null,\n };\n}\n\nconst MEMORY_ORIGIN = \"http://localhost\";\n\nexport function createMemoryHistory(initial = \"/\"): HistoryAdapter {\n const stack: string[] = [initial];\n let index = 0;\n const listeners = new Set<(url: URL) => void>();\n\n return {\n url: () => new URL(stack[index], MEMORY_ORIGIN),\n push: (url) => {\n stack.splice(index + 1);\n stack.push(url);\n index++;\n },\n replace: (url) => {\n stack[index] = url;\n },\n go: (delta) => {\n const next = Math.min(Math.max(index + delta, 0), stack.length - 1);\n if (next === index) return;\n index = next;\n const url = new URL(stack[index], MEMORY_ORIGIN);\n for (const listener of listeners) listener(url);\n },\n listen: (callback) => {\n listeners.add(callback);\n return () => listeners.delete(callback);\n },\n };\n}\n","import type { DomphyElement } from \"@domphy/core\";\nimport type { RouteMatch } from \"./matcher.js\";\nimport type {\n ErrorBlock,\n NotFoundBlock,\n RouteContext,\n RouterStatus,\n} from \"./types.js\";\n\nexport type SegmentStatus = \"success\" | \"pending\" | \"error\" | \"notfound\";\n\nexport interface SegmentResult {\n status: SegmentStatus;\n data?: unknown;\n error?: Error;\n}\n\nexport interface BuildTreeInput {\n match: RouteMatch;\n baseContext: Omit<RouteContext, \"data\" | \"segmentData\">;\n results: SegmentResult[];\n retry: () => void;\n defaultError: ErrorBlock;\n defaultNotFound: NotFoundBlock;\n}\n\nexport interface BuiltTree {\n element: DomphyElement;\n status: RouterStatus;\n}\n\nexport function defaultErrorBlock(error: Error): DomphyElement {\n return {\n div: [{ h2: \"Application error\" }, { p: error.message }],\n };\n}\n\nexport function defaultNotFoundBlock(): DomphyElement {\n return {\n div: [{ h2: \"404\" }, { p: \"This page could not be found.\" }],\n };\n}\n\nfunction findBoundary(results: SegmentResult[], status: SegmentStatus): number {\n return results.findIndex((result) => result.status === status);\n}\n\n/**\n * Composes the matched chain into one element: page wrapped by every layout,\n * exactly like nested `layout.tsx` files. When a segment failed, is pending or\n * raised `notFound()`, the subtree below the nearest boundary block (`error`,\n * `loading`, `notFound`) is replaced by that block while ancestor layouts keep\n * rendering — the same boundary model as the Next.js App Router.\n */\nexport function buildTree(input: BuildTreeInput): BuiltTree {\n const { match, baseContext, results, retry, defaultError, defaultNotFound } =\n input;\n const { chain, chainIds } = match.route;\n\n const segmentData: Record<string, unknown> = {};\n for (let i = 0; i < chain.length; i++) {\n segmentData[chainIds[i]] = results[i]?.data;\n }\n const contexts: RouteContext[] = chain.map((_, i) => ({\n ...baseContext,\n data: results[i]?.data,\n segmentData,\n }));\n\n const errorIndex = findBoundary(results, \"error\");\n const notFoundIndex = findBoundary(results, \"notfound\");\n const pendingIndex = findBoundary(results, \"pending\");\n\n let inner: DomphyElement;\n let wrapLimit: number;\n let status: RouterStatus;\n\n if (errorIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, errorIndex, (route) =>\n Boolean(route.error),\n );\n const block =\n blockIndex === -1\n ? defaultError\n : (chain[blockIndex].error as ErrorBlock);\n inner = block(results[errorIndex].error as Error, retry);\n inner._key = `${chainIds[Math.max(blockIndex, 0)]}:error`;\n wrapLimit = Math.min(blockIndex, errorIndex - 1);\n status = \"error\";\n } else if (notFoundIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, notFoundIndex, (route) =>\n Boolean(route.notFound),\n );\n const block =\n blockIndex === -1\n ? defaultNotFound\n : (chain[blockIndex].notFound as NotFoundBlock);\n inner = block();\n inner._key = `${chainIds[Math.max(blockIndex, 0)]}:notfound`;\n wrapLimit = Math.min(blockIndex, notFoundIndex - 1);\n status = \"notfound\";\n } else if (pendingIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, pendingIndex, (route) =>\n Boolean(route.loading),\n );\n if (blockIndex === -1) {\n // No loading block anywhere: caller keeps the previous tree on screen.\n return { element: { div: \"\" }, status: \"loading\" };\n }\n inner = chain[blockIndex].loading!(contexts[blockIndex]);\n inner._key = `${chainIds[blockIndex]}:loading`;\n wrapLimit = Math.min(blockIndex, pendingIndex - 1);\n status = \"loading\";\n } else {\n const leaf = chain[chain.length - 1];\n inner = leaf.page!(contexts[chain.length - 1]);\n inner._key = `${match.route.id}:page`;\n wrapLimit = chain.length - 1;\n status = \"idle\";\n }\n\n let element = inner;\n for (let i = wrapLimit; i >= 0; i--) {\n const layout = chain[i].layout;\n if (!layout) continue;\n element = layout(element, contexts[i]);\n if (element._key === undefined) element._key = `${chainIds[i]}:layout`;\n }\n\n return { element, status };\n}\n\nfunction nearestBlockIndex(\n chain: BuildTreeInput[\"match\"][\"route\"][\"chain\"],\n fromIndex: number,\n predicate: (\n route: BuildTreeInput[\"match\"][\"route\"][\"chain\"][number],\n ) => boolean,\n): number {\n for (let i = fromIndex; i >= 0; i--) {\n if (predicate(chain[i])) return i;\n }\n return -1;\n}\n\n/** Wraps a bare not-found block with the root layouts of a match-less render. */\nexport function buildNotFoundTree(block: NotFoundBlock): BuiltTree {\n const element = block();\n if (element._key === undefined) element._key = \"app:notfound\";\n return { element, status: \"notfound\" };\n}\n","import type { PartialElement } from \"@domphy/core\";\n\nexport interface ImageLoaderInput {\n src: string;\n width: number;\n quality: number;\n}\n\nexport type ImageLoader = (input: ImageLoaderInput) => string;\n\nexport interface OptimizedImageProps {\n src: string;\n alt?: string;\n width?: number;\n height?: number;\n /** Stretch over the positioned parent, like the `fill` prop of `next/image`. */\n fill?: boolean;\n sizes?: string;\n quality?: number;\n /** Load eagerly with high fetch priority — use for the LCP image. */\n priority?: boolean;\n placeholder?: \"blur\" | \"empty\";\n blurDataURL?: string;\n /** Maps `src` + width to an optimized URL; enables `srcset` generation. */\n loader?: ImageLoader;\n deviceSizes?: number[];\n}\n\nconst DEFAULT_DEVICE_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];\n\n/**\n * Patch for `img` elements, the equivalent of `next/image`: lazy loading,\n * async decoding, fetch priority, `srcset` through a custom loader, fill\n * layout and blur placeholders. URL optimization itself is the loader's job —\n * point it at any image CDN.\n */\nexport function optimizedImage(props: OptimizedImageProps): PartialElement<\"img\"> {\n const {\n src,\n alt = \"\",\n width,\n height,\n fill = false,\n sizes,\n quality = 75,\n priority = false,\n placeholder = \"empty\",\n blurDataURL,\n loader,\n deviceSizes = DEFAULT_DEVICE_SIZES,\n } = props;\n\n const part: PartialElement<\"img\"> = {\n src: loader\n ? loader({\n src,\n width: width ?? deviceSizes[deviceSizes.length - 1],\n quality,\n })\n : src,\n alt,\n loading: priority ? \"eager\" : \"lazy\",\n decoding: \"async\",\n fetchPriority: priority ? \"high\" : \"auto\",\n style: {},\n };\n\n if (loader) {\n part.srcSet = deviceSizes\n .map((size) => `${loader({ src, width: size, quality })} ${size}w`)\n .join(\", \");\n if (sizes) part.sizes = sizes;\n }\n\n if (width !== undefined) part.width = width;\n if (height !== undefined) part.height = height;\n\n if (fill) {\n part.style = {\n ...part.style,\n position: \"absolute\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n };\n }\n\n if (placeholder === \"blur\" && blurDataURL) {\n part.style = {\n ...part.style,\n backgroundImage: `url(\"${blurDataURL}\")`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n };\n part.onLoad = (event) => {\n const image = event.target as HTMLImageElement;\n image.style.backgroundImage = \"\";\n };\n }\n\n return part;\n}\n","import type { PartialElement } from \"@domphy/core\";\nimport { type AppRouter, getRouter } from \"./router.js\";\n\nexport interface NavLinkProps {\n href: string;\n /** Replace the current history entry instead of pushing. */\n replace?: boolean;\n /** Scroll after navigation, defaults to true. */\n scroll?: boolean;\n /**\n * Prefetch strategy, like the `prefetch` prop of `next/link`:\n * `\"visible\"` when the link enters the viewport, `\"hover\"` on pointer/focus,\n * `false` never. Defaults to `\"hover\"`.\n */\n prefetch?: \"visible\" | \"hover\" | false;\n /** Mark active only on an exact pathname match, not on descendants. */\n exact?: boolean;\n /** Explicit router; defaults to the app router. */\n router?: AppRouter;\n}\n\nfunction isModifiedClick(event: MouseEvent): boolean {\n return (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n );\n}\n\n/**\n * Patch for `a` elements, the equivalent of `next/link`: client-side\n * navigation, prefetching and active state (`aria-current` + `data-active`).\n */\nexport function navLink(props: NavLinkProps): PartialElement<\"a\"> {\n const {\n href,\n replace = false,\n scroll = true,\n prefetch = \"hover\",\n exact = false,\n } = props;\n const router = () => props.router ?? getRouter();\n\n const isActive = (pathname: string): boolean => {\n const target = new URL(href, \"http://localhost\").pathname;\n if (exact || target === \"/\") return pathname === target;\n return pathname === target || pathname.startsWith(`${target}/`);\n };\n\n let prefetched = false;\n const prefetchOnce = () => {\n if (prefetched) return;\n prefetched = true;\n void router().prefetch(href);\n };\n\n return {\n href,\n ariaCurrent: (listener) =>\n isActive(router().state.get(\"pathname\", listener) as string)\n ? \"page\"\n : null,\n dataActive: (listener) =>\n isActive(router().state.get(\"pathname\", listener) as string) ? \"\" : null,\n onClick: (event) => {\n const mouseEvent = event as MouseEvent;\n const anchor = mouseEvent.currentTarget as HTMLAnchorElement;\n if (isModifiedClick(mouseEvent)) return;\n if (anchor.target && anchor.target !== \"_self\") return;\n if (anchor.hasAttribute(\"download\")) return;\n if (\n new URL(anchor.href, window.location.href).origin !==\n window.location.origin\n )\n return;\n mouseEvent.preventDefault();\n void router().navigate(href, { replace, scroll });\n },\n onMouseEnter: () => {\n if (prefetch === \"hover\") prefetchOnce();\n },\n onFocus: () => {\n if (prefetch === \"hover\") prefetchOnce();\n },\n _onMount: (node) => {\n if (prefetch !== \"visible\") return;\n if (typeof IntersectionObserver === \"undefined\") {\n prefetchOnce();\n return;\n }\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n prefetchOnce();\n observer.disconnect();\n }\n });\n observer.observe(node.domElement as Element);\n node.setMetadata(\"navLinkObserver\", observer);\n },\n _onRemove: (node) => {\n const observer = node.getMetadata(\"navLinkObserver\") as\n | IntersectionObserver\n | undefined;\n observer?.disconnect();\n },\n };\n}\n","import type { DomphyElement } from \"@domphy/core\";\n\nexport interface ScriptProps {\n src: string;\n /**\n * Loading strategy, like `next/script`:\n * `\"afterInteractive\"` loads as soon as the element mounts (default),\n * `\"lazyOnload\"` waits for the window `load` event plus idle time.\n */\n strategy?: \"afterInteractive\" | \"lazyOnload\";\n id?: string;\n async?: boolean;\n onLoad?: () => void;\n onError?: () => void;\n}\n\nconst loadedScripts = new Set<string>();\n\n/** Resets script dedupe between tests. */\nexport function resetScripts(): void {\n loadedScripts.clear();\n}\n\nfunction whenIdle(callback: () => void): void {\n const idle = (\n globalThis as { requestIdleCallback?: (cb: () => void) => void }\n ).requestIdleCallback;\n if (idle) {\n idle(callback);\n } else {\n setTimeout(callback, 0);\n }\n}\n\n/**\n * Block that loads an external script once, the equivalent of `next/script`.\n * Place it anywhere in the tree; duplicate sources are loaded only once.\n */\nexport function script(props: ScriptProps): DomphyElement<\"script\"> {\n const {\n src,\n strategy = \"afterInteractive\",\n id,\n async = true,\n onLoad,\n onError,\n } = props;\n const dedupeKey = id ?? src;\n\n const start = (element: HTMLScriptElement) => {\n if (loadedScripts.has(dedupeKey)) return;\n loadedScripts.add(dedupeKey);\n element.src = src;\n };\n\n const part: DomphyElement<\"script\"> = {\n script: \"\",\n async,\n onLoad: () => onLoad?.(),\n onError: () => onError?.(),\n _onMount: (node) => {\n const element = node.domElement as HTMLScriptElement;\n if (strategy === \"afterInteractive\") {\n start(element);\n return;\n }\n if (document.readyState === \"complete\") {\n whenIdle(() => start(element));\n } else {\n window.addEventListener(\"load\", () => whenIdle(() => start(element)), {\n once: true,\n });\n }\n },\n };\n if (id !== undefined) part.id = id;\n return part;\n}\n","import type { DomphyElement } from \"@domphy/core\";\nimport type { Metadata } from \"./metadata.js\";\n\n/** Route params. Dynamic segments map to strings, catch-all segments to string arrays. */\nexport type Params = Record<string, string | string[]>;\n\n/** Shared context given to pages, layouts, loaders, metadata functions and middleware. */\nexport interface RouteContext<TData = unknown> {\n /** Pathname actually rendered (after middleware rewrites). */\n pathname: string;\n /** Pathname shown in the address bar (before rewrites). */\n url: string;\n params: Params;\n searchParams: URLSearchParams;\n hash: string;\n /** Resolved loader data of the owning segment. */\n data: TData;\n /** Resolved loader data of every matched segment, keyed by segment id. */\n segmentData: Record<string, unknown>;\n /** Request headers, only present during server rendering. */\n headers?: Headers;\n}\n\nexport type PageBlock<TData = unknown> = (\n context: RouteContext<TData>,\n) => DomphyElement;\n\nexport type LayoutBlock<TData = unknown> = (\n children: DomphyElement,\n context: RouteContext<TData>,\n) => DomphyElement;\n\nexport type LoadingBlock = (context: RouteContext) => DomphyElement;\n\nexport type ErrorBlock = (error: Error, retry: () => void) => DomphyElement;\n\nexport type NotFoundBlock = () => DomphyElement;\n\nexport interface LoaderContext {\n pathname: string;\n url: string;\n params: Params;\n searchParams: URLSearchParams;\n headers?: Headers;\n}\n\nexport type Loader<TData = unknown> = (\n context: LoaderContext,\n) => TData | Promise<TData>;\n\nexport type MetadataValue =\n | Metadata\n | ((context: LoaderContext) => Metadata | Promise<Metadata>);\n\nexport interface MiddlewareContext {\n url: URL;\n pathname: string;\n searchParams: URLSearchParams;\n headers?: Headers;\n}\n\n/** A rewrite instruction returned from middleware. Create with `rewrite()`. */\nexport interface RewriteResult {\n __domphyRewrite: string;\n}\n\n/**\n * Middleware runs before every navigation and server render.\n * Return `rewrite(path)` to render another route under the same URL,\n * call `redirect(path)` / `notFound()` to interrupt, or return nothing to continue.\n */\nexport type Middleware = (\n context: MiddlewareContext,\n) =>\n | RewriteResult\n | undefined\n | void\n | Promise<RewriteResult | undefined | void>;\n\n/**\n * One route segment, the equivalent of one folder in the Next.js `app` directory.\n *\n * `path` uses Next.js conventions:\n * - `\"about\"` static segment (may contain several parts: `\"docs/getting-started\"`)\n * - `\"[slug]\"` dynamic segment\n * - `\"[...slug]\"` catch-all segment\n * - `\"[[...slug]]\"` optional catch-all segment\n * - `\"(marketing)\"` route group, organizes the tree without affecting the URL\n *\n * A segment is routable when it declares `page` or `redirect`.\n */\nexport interface Route {\n path: string;\n page?: PageBlock<any>;\n layout?: LayoutBlock<any>;\n loading?: LoadingBlock;\n error?: ErrorBlock;\n notFound?: NotFoundBlock;\n metadata?: MetadataValue;\n loader?: Loader<any>;\n /**\n * Loader cache lifetime in seconds, the equivalent of Next.js `revalidate`.\n * `undefined` re-runs the loader on every navigation, `Infinity` caches forever.\n */\n revalidate?: number;\n middleware?: Middleware[];\n /** Static redirect: navigating to this route immediately redirects to the target. */\n redirect?: string;\n /** Use a 308 redirect on the server when `redirect` is set. */\n permanent?: boolean;\n children?: Route[];\n}\n\nexport type RouterStatus = \"idle\" | \"loading\" | \"error\" | \"notfound\";\n\nexport interface RouterStateRecord {\n pathname: string;\n search: string;\n hash: string;\n params: Params;\n status: RouterStatus;\n error: Error | null;\n\n [key: string]: unknown;\n}\n\nexport interface NavigateOptions {\n replace?: boolean;\n /** Scroll to the top (or the URL hash) after navigation. Defaults to true. */\n scroll?: boolean;\n}\n\nexport type RouterEventName =\n | \"routeChangeStart\"\n | \"routeChangeComplete\"\n | \"routeChangeError\";\n\n/** Identity helper that keeps route literals fully typed. */\nexport function defineRoutes(routes: Route[]): Route[] {\n return routes;\n}\n"],"mappings":"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","names":["index_exports","__export","AppRouter","DataCache","DomphyApp","NotFoundSignal","PREFETCH_LIFETIME","RedirectSignal","applyHeadTags","buildHref","buildNotFoundTree","buildTree","compareSpecificity","compileRoutes","createApiHandler","createApp","createBrowserHistory","createMemoryHistory","defaultErrorBlock","defaultNotFoundBlock","defineRoutes","getRouter","isRewrite","json","matchPath","matchRoute","metadataToHeadTags","navLink","notFound","optimizedImage","parseSegment","permanentRedirect","redirect","renderHeadTags","resetScripts","resolveMetadata","rewrite","script","splitPath","__toCommonJS","parseSegment","part","splitPath","path","compileRoutes","routes","compiled","walk","nodes","parentSegments","parentChain","parentChainIds","parentId","node","parts","ownSegments","urlSegments","segment","id","chain","chainIds","compareSpecificity","KIND_RANK","a","b","length","i","segmentA","segmentB","rankDifference","matchPath","segments","pathname","params","partIndex","isLast","matchRoute","route","buildHref","pattern","value","RedirectSignal","to","permanent","NotFoundSignal","redirect","permanentRedirect","notFound","rewrite","isRewrite","value","METHODS","json","data","init","headers","__spreadProps","__spreadValues","createApiHandler","routes","pairs","apiRoute","compiled","compileRoutes","pair","byNode","request","__async","url","match","matchRoute","route","allowed","method","handler","response","error","RedirectSignal","NotFoundSignal","import_core","resolveMetadata","values","context","__async","resolved","template","value","metadata","key","entry","title","absoluteUrl","url","base","robotsContent","robots","directives","metadataToHeadTags","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","tags","meta","name","content","property","author","icons","openGraph","image","twitter","alternates","language","escapeAttribute","escapeText","renderHeadTags","tag","attributes","MANAGED_ATTRIBUTE","applyHeadTags","element","import_core","PREFETCH_LIFETIME","DataCache","record","key","keys","entry","prefix","loader","context","revalidate","__async","lifetime","fresh","usableSeed","pending","promise","data","error","existing","createBrowserHistory","_a","_b","_c","scrollPositions","index","url","delta","callback","handler","position","MEMORY_ORIGIN","createMemoryHistory","initial","stack","listeners","next","listener","defaultErrorBlock","error","defaultNotFoundBlock","findBoundary","results","status","result","buildTree","input","_a","match","baseContext","retry","defaultError","defaultNotFound","chain","chainIds","segmentData","i","contexts","_","__spreadProps","__spreadValues","errorIndex","notFoundIndex","pendingIndex","inner","wrapLimit","blockIndex","nearestBlockIndex","route","element","layout","fromIndex","predicate","buildNotFoundTree","block","defaultRouter","getRouter","AppRouter","routes","options","DataCache","_a","_b","_c","compileRoutes","defaultNotFoundBlock","error","defaultErrorBlock","createBrowserHistory","__async","url","search","href","_0","__spreadProps","__spreadValues","match","matchRoute","context","route","index","key","e","listener","event","callback","segmentId","token","renderPathname","middlewareContext","middleware","result","isRewrite","leaf","RedirectSignal","NotFoundSignal","failure","chain","chainIds","results","redirectSignal","promises","data","settled","allSettled","resolve","interim","buildTree","built","dataRecord","buildNotFoundTree","applyHeadTags","resolveMetadata","metadataToHeadTags","element","status","_d","position","target","HYDRATION_GLOBAL","DomphyApp","routes","options","AppRouter","router","listener","target","__async","style","seeded","_a","_0","url","requestUrl","serverRouter","__spreadProps","__spreadValues","status","redirect","node","data","result","renderHeadTags","metadataToHeadTags","serializeData","createApp","DEFAULT_DEVICE_SIZES","optimizedImage","props","src","alt","width","height","fill","sizes","quality","priority","placeholder","blurDataURL","loader","deviceSizes","part","size","__spreadProps","__spreadValues","event","image","isModifiedClick","event","navLink","props","href","replace","scroll","prefetch","exact","router","_a","getRouter","isActive","pathname","target","prefetched","prefetchOnce","listener","mouseEvent","anchor","node","observer","entries","entry","loadedScripts","resetScripts","whenIdle","callback","idle","script","props","src","strategy","id","async","onLoad","onError","dedupeKey","start","element","part","node","defineRoutes","routes"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/matcher.ts","../src/navigation.ts","../src/api.ts","../src/app.ts","../src/metadata.ts","../src/router.ts","../src/dataCache.ts","../src/history.ts","../src/tree.ts","../src/image.ts","../src/link.ts","../src/script.ts","../src/types.ts"],"sourcesContent":["export * from \"./api.js\";\nexport * from \"./app.js\";\nexport * from \"./dataCache.js\";\nexport * from \"./history.js\";\nexport * from \"./image.js\";\nexport * from \"./link.js\";\nexport * from \"./matcher.js\";\nexport * from \"./metadata.js\";\nexport * from \"./navigation.js\";\nexport * from \"./router.js\";\nexport * from \"./script.js\";\nexport * from \"./tree.js\";\nexport * from \"./types.js\";\n","import type { Params, Route } from \"./types.js\";\n\nexport type SegmentKind =\n | \"static\"\n | \"dynamic\"\n | \"catchall\"\n | \"optional-catchall\"\n | \"group\";\n\nexport interface PatternSegment {\n kind: SegmentKind;\n /** Literal value for static segments, param name otherwise. */\n value: string;\n}\n\n/** One routable endpoint: the chain of route nodes from root to the segment that owns the page. */\nexport interface CompiledRoute {\n /** Stable id, the full pattern path including groups, e.g. \"/(shop)/products/[id]\". */\n id: string;\n /** URL pattern segments, groups excluded. */\n segments: PatternSegment[];\n /** Route nodes from root to leaf. */\n chain: Route[];\n /** Segment id for each chain node, used as data cache key and diff key. */\n chainIds: string[];\n}\n\nexport interface RouteMatch {\n route: CompiledRoute;\n params: Params;\n pathname: string;\n}\n\nexport function parseSegment(part: string): PatternSegment {\n if (part.startsWith(\"(\") && part.endsWith(\")\")) {\n return { kind: \"group\", value: part.slice(1, -1) };\n }\n if (part.startsWith(\"[[...\") && part.endsWith(\"]]\")) {\n return { kind: \"optional-catchall\", value: part.slice(5, -2) };\n }\n if (part.startsWith(\"[...\") && part.endsWith(\"]\")) {\n return { kind: \"catchall\", value: part.slice(4, -1) };\n }\n if (part.startsWith(\"[\") && part.endsWith(\"]\")) {\n return { kind: \"dynamic\", value: part.slice(1, -1) };\n }\n return { kind: \"static\", value: part };\n}\n\nexport function splitPath(path: string): string[] {\n return path.split(\"/\").filter((part) => part.length > 0);\n}\n\n/** Number of URL parts a route path contributes (route groups don't count). */\nexport function urlPartCount(path: string): number {\n return splitPath(path)\n .map(parseSegment)\n .filter((segment) => segment.kind !== \"group\").length;\n}\n\n/** Matches `pathname` after dropping the first `prefixParts` URL parts (slot/intercept matching). */\nexport function matchRouteSuffix(\n compiled: CompiledRoute[],\n pathname: string,\n prefixParts: number,\n): RouteMatch | null {\n const suffix = `/${splitPath(pathname).slice(prefixParts).join(\"/\")}`;\n return matchRoute(compiled, suffix);\n}\n\n/** Flattens a route tree into a list of routable endpoints. */\nexport function compileRoutes(routes: Route[]): CompiledRoute[] {\n const compiled: CompiledRoute[] = [];\n\n function walk(\n nodes: Route[],\n parentSegments: PatternSegment[],\n parentChain: Route[],\n parentChainIds: string[],\n parentId: string,\n ): void {\n for (const node of nodes) {\n const parts = splitPath(node.path);\n const ownSegments = parts.map(parseSegment);\n const urlSegments = [\n ...parentSegments,\n ...ownSegments.filter((segment) => segment.kind !== \"group\"),\n ];\n const id = `${parentId}/${parts.join(\"/\")}`.replace(/\\/+/g, \"/\");\n const chain = [...parentChain, node];\n const chainIds = [...parentChainIds, id === \"\" ? \"/\" : id];\n\n if (node.page || node.redirect) {\n compiled.push({\n id: id === \"\" ? \"/\" : id,\n segments: urlSegments,\n chain,\n chainIds,\n });\n }\n if (node.children) {\n walk(node.children, urlSegments, chain, chainIds, id);\n }\n }\n }\n\n walk(routes, [], [], [], \"\");\n compiled.sort(compareSpecificity);\n return compiled;\n}\n\nconst KIND_RANK: Record<SegmentKind, number> = {\n static: 0,\n dynamic: 1,\n catchall: 2,\n \"optional-catchall\": 3,\n group: 0,\n};\n\n/** Static segments win over dynamic, dynamic over catch-all — same priority order as Next.js. */\nexport function compareSpecificity(a: CompiledRoute, b: CompiledRoute): number {\n const length = Math.max(a.segments.length, b.segments.length);\n for (let i = 0; i < length; i++) {\n const segmentA = a.segments[i];\n const segmentB = b.segments[i];\n if (!segmentA) return -1;\n if (!segmentB) return 1;\n const rankDifference = KIND_RANK[segmentA.kind] - KIND_RANK[segmentB.kind];\n if (rankDifference !== 0) return rankDifference;\n }\n return 0;\n}\n\nexport function matchPath(\n segments: PatternSegment[],\n pathname: string,\n): Params | null {\n const parts = splitPath(pathname).map((part) => decodeURIComponent(part));\n const params: Params = {};\n let partIndex = 0;\n\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n const isLast = i === segments.length - 1;\n\n if (segment.kind === \"static\") {\n if (parts[partIndex] !== segment.value) return null;\n partIndex++;\n continue;\n }\n if (segment.kind === \"dynamic\") {\n if (partIndex >= parts.length) return null;\n params[segment.value] = parts[partIndex];\n partIndex++;\n continue;\n }\n if (segment.kind === \"catchall\") {\n if (!isLast || partIndex >= parts.length) return null;\n params[segment.value] = parts.slice(partIndex);\n return params;\n }\n if (segment.kind === \"optional-catchall\") {\n if (!isLast) return null;\n params[segment.value] = parts.slice(partIndex);\n return params;\n }\n }\n\n if (partIndex !== parts.length) return null;\n return params;\n}\n\nexport function matchRoute(\n compiled: CompiledRoute[],\n pathname: string,\n): RouteMatch | null {\n for (const route of compiled) {\n const params = matchPath(route.segments, pathname);\n if (params) {\n return { route, params, pathname };\n }\n }\n return null;\n}\n\n/** Replaces pattern placeholders with params, the inverse of `matchPath`. */\nexport function buildHref(pattern: string, params: Params = {}): string {\n const parts = splitPath(pattern)\n .map(parseSegment)\n .filter((segment) => segment.kind !== \"group\")\n .flatMap((segment) => {\n if (segment.kind === \"static\") return [segment.value];\n const value = params[segment.value];\n if (value === undefined) {\n if (segment.kind === \"optional-catchall\") return [];\n throw new Error(\n `Missing param \"${segment.value}\" for pattern \"${pattern}\".`,\n );\n }\n const list = Array.isArray(value) ? value : [value];\n return list.map((part) => encodeURIComponent(part));\n });\n return `/${parts.join(\"/\")}`;\n}\n","import type { RewriteResult } from \"./types.js\";\n\n/**\n * Control-flow signals, the equivalents of `redirect()`, `permanentRedirect()` and\n * `notFound()` from `next/navigation`. They throw and are caught by the router\n * (or by `renderToString` on the server), so they can be called from loaders,\n * metadata functions and middleware.\n */\n\nexport class RedirectSignal extends Error {\n readonly to: string;\n readonly permanent: boolean;\n\n constructor(to: string, permanent: boolean) {\n super(`Redirect to ${to}`);\n this.name = \"RedirectSignal\";\n this.to = to;\n this.permanent = permanent;\n }\n}\n\nexport class NotFoundSignal extends Error {\n constructor() {\n super(\"Not found\");\n this.name = \"NotFoundSignal\";\n }\n}\n\nexport function redirect(to: string): never {\n throw new RedirectSignal(to, false);\n}\n\nexport function permanentRedirect(to: string): never {\n throw new RedirectSignal(to, true);\n}\n\nexport function notFound(): never {\n throw new NotFoundSignal();\n}\n\n/** Returned from middleware to render another route while keeping the URL. */\nexport function rewrite(to: string): RewriteResult {\n return { __domphyRewrite: to };\n}\n\nexport function isRewrite(value: unknown): value is RewriteResult {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as RewriteResult).__domphyRewrite === \"string\"\n );\n}\n","import { compileRoutes, matchRoute } from \"./matcher.js\";\nimport { NotFoundSignal, RedirectSignal } from \"./navigation.js\";\nimport type { Params, Route } from \"./types.js\";\n\n/**\n * API route handlers on web-standard Request/Response, the equivalent of\n * `route.ts` files. Works in Node 18+, Bun, Deno, and edge runtimes; adapt to\n * `http.createServer` with any Request/Response bridge.\n */\n\nexport type HttpMethod =\n | \"GET\"\n | \"POST\"\n | \"PUT\"\n | \"PATCH\"\n | \"DELETE\"\n | \"HEAD\"\n | \"OPTIONS\";\n\nexport interface ApiContext {\n params: Params;\n}\n\nexport type ApiMethodHandler = (\n request: Request,\n context: ApiContext,\n) => Response | Promise<Response>;\n\nexport interface ApiRoute {\n /** Same pattern syntax as page routes: `\"/api/users/[id]\"`. */\n path: string;\n GET?: ApiMethodHandler;\n POST?: ApiMethodHandler;\n PUT?: ApiMethodHandler;\n PATCH?: ApiMethodHandler;\n DELETE?: ApiMethodHandler;\n HEAD?: ApiMethodHandler;\n OPTIONS?: ApiMethodHandler;\n}\n\nconst METHODS: HttpMethod[] = [\n \"GET\",\n \"POST\",\n \"PUT\",\n \"PATCH\",\n \"DELETE\",\n \"HEAD\",\n \"OPTIONS\",\n];\n\n/** Shorthand for JSON responses, the equivalent of `NextResponse.json()`. */\nexport function json(data: unknown, init: ResponseInit = {}): Response {\n const headers = new Headers(init.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json; charset=utf-8\");\n }\n return new Response(JSON.stringify(data), { ...init, headers });\n}\n\nexport function createApiHandler(\n routes: ApiRoute[],\n): (request: Request) => Promise<Response> {\n const pairs = routes.map((apiRoute) => ({\n apiRoute,\n routeNode: { path: apiRoute.path, page: () => ({ div: \"\" }) } as Route,\n }));\n const compiled = compileRoutes(pairs.map((pair) => pair.routeNode));\n const byNode = new Map(pairs.map((pair) => [pair.routeNode, pair.apiRoute]));\n\n return async (request: Request): Promise<Response> => {\n const url = new URL(request.url);\n const match = matchRoute(compiled, url.pathname);\n if (!match) {\n return json({ error: \"Not Found\" }, { status: 404 });\n }\n\n const route = byNode.get(\n match.route.chain[match.route.chain.length - 1],\n ) as ApiRoute;\n const allowed = METHODS.filter((method) => route[method]);\n const method = request.method.toUpperCase() as HttpMethod;\n let handler = route[method];\n\n if (!handler && method === \"HEAD\" && route.GET) {\n handler = route.GET;\n }\n if (!handler && method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: { allow: allowed.join(\", \") },\n });\n }\n if (!handler) {\n return json(\n { error: \"Method Not Allowed\" },\n { status: 405, headers: { allow: allowed.join(\", \") } },\n );\n }\n\n try {\n const response = await handler(request, { params: match.params });\n if (method === \"HEAD\") {\n return new Response(null, {\n status: response.status,\n headers: response.headers,\n });\n }\n return response;\n } catch (error) {\n if (error instanceof RedirectSignal) {\n return new Response(null, {\n status: error.permanent ? 308 : 307,\n headers: { location: error.to },\n });\n }\n if (error instanceof NotFoundSignal) {\n return json({ error: \"Not Found\" }, { status: 404 });\n }\n return json({ error: \"Internal Server Error\" }, { status: 500 });\n }\n };\n}\n","import { type DomphyElement, ElementNode } from \"@domphy/core\";\nimport type { HistoryAdapter } from \"./history.js\";\nimport { metadataToHeadTags, renderHeadTags } from \"./metadata.js\";\nimport { AppRouter, type RouterOptions } from \"./router.js\";\nimport type { Route } from \"./types.js\";\n\nexport interface AppOptions extends Omit<RouterOptions, \"history\" | \"headers\"> {\n history?: HistoryAdapter | null;\n}\n\nexport interface RenderToStringOptions {\n headers?: Headers;\n}\n\nexport interface RenderToStreamOptions extends RenderToStringOptions {\n /** Extra HTML for `<head>` (charset, viewport, fonts, a CSS link…), sent in the first flush. */\n head?: string;\n /** Markup appended before `</body>`, typically the client bundle `<script>` that calls `hydrate()`. */\n bootstrap?: string;\n}\n\nexport interface StreamResult {\n /** A web `ReadableStream` of UTF-8 bytes: the shell flushes first, content follows. */\n stream: ReadableStream<Uint8Array>;\n status: number;\n redirect?: string;\n}\n\n/** Swaps the streamed content/head templates into place as soon as they arrive. */\nconst STREAM_SWAP_SCRIPT =\n \"(function(){var h=document.getElementById('domphy-head');\" +\n \"if(h){document.head.appendChild(h.content.cloneNode(true));h.remove();}\" +\n \"var c=document.getElementById('domphy-content'),a=document.getElementById('domphy-app');\" +\n \"if(c&&a){a.replaceChildren(c.content.cloneNode(true));c.remove();}})();\";\n\nexport interface SSRResult {\n /** Body markup of the app root, ready to place inside the mount element. */\n html: string;\n /** Scoped CSS of the rendered tree, place inside `<style id=\"domphy-style\">`. */\n css: string;\n /** Serialized `<title>`, `<meta>` and `<link>` tags for the document head. */\n head: string;\n /** 200, 404, or the redirect status. */\n status: number;\n /** Set when a loader or middleware redirected. */\n redirect?: string;\n /** Loader data to embed for hydration, see `bootstrapScript`. */\n data: Record<string, unknown>;\n /** Inline script that exposes loader data to `hydrate()` on the client. */\n bootstrapScript: string;\n}\n\nconst HYDRATION_GLOBAL = \"__DOMPHY_APP_DATA__\";\n\n/**\n * The app shell: routing, rendering and server rendering in one object, the\n * Domphy equivalent of a Next.js application instance.\n */\nexport class DomphyApp {\n readonly routes: Route[];\n readonly options: AppOptions;\n readonly router: AppRouter;\n private node: ElementNode | null = null;\n\n constructor(routes: Route[], options: AppOptions = {}) {\n this.routes = routes;\n this.options = options;\n this.router = new AppRouter(routes, options);\n }\n\n /** The root element; the whole route tree re-renders through one reactive child. */\n element(): DomphyElement {\n const router = this.router;\n return {\n div: (listener) => [router.tree.get(listener)],\n style: { display: \"contents\" },\n };\n }\n\n /** Client-side render from scratch. */\n async render(target: HTMLElement): Promise<ElementNode> {\n await this.router.start();\n this.node = new ElementNode(this.element());\n this.node.render(target);\n return this.node;\n }\n\n /**\n * Hydrates server-rendered markup. Reads the loader data embedded by\n * `bootstrapScript` so loaders are not re-run and the tree matches the HTML.\n */\n async hydrate(\n target: HTMLElement,\n style?: HTMLStyleElement,\n ): Promise<ElementNode> {\n const seeded = (globalThis as Record<string, unknown>)[HYDRATION_GLOBAL];\n if (seeded && typeof seeded === \"object\") {\n this.router.cache.seed(seeded as Record<string, unknown>);\n }\n await this.router.start();\n this.node = new ElementNode(this.element());\n this.node.mount(target, style);\n return this.node;\n }\n\n destroy(): void {\n this.node?.remove();\n this.node = null;\n this.router.destroy();\n }\n\n /** Server rendering: runs middleware and loaders for `url`, returns markup + CSS + head. */\n async renderToString(\n url: string | URL,\n options: RenderToStringOptions = {},\n ): Promise<SSRResult> {\n const requestUrl =\n typeof url === \"string\" ? new URL(url, \"http://localhost\") : url;\n const serverRouter = new AppRouter(this.routes, {\n ...this.options,\n history: null,\n headers: options.headers,\n });\n\n await serverRouter.transition(requestUrl, { initial: true });\n\n const status = serverRouter.state.get(\"status\");\n const redirect = serverRouter.lastRedirect;\n const node = new ElementNode({\n div: [serverRouter.tree.get()],\n style: { display: \"contents\" },\n });\n\n const data = serverRouter.lastData;\n\n const result: SSRResult = {\n html: node.generateHTML(),\n css: node.generateCSS(),\n head: renderHeadTags(metadataToHeadTags(serverRouter.metadata)),\n status: redirect\n ? redirect.permanent\n ? 308\n : 307\n : status === \"notfound\"\n ? 404\n : 200,\n redirect: redirect?.to,\n data,\n bootstrapScript: `<script>window.${HYDRATION_GLOBAL} = ${serializeData(data)};</script>`,\n };\n serverRouter.destroy();\n return result;\n }\n\n /**\n * Streaming server render. Flushes the shell (layouts + loading fallbacks)\n * immediately for a fast TTFB, then streams the resolved content, head and\n * hydration data once loaders settle. The content arrives in `<template>`s\n * that an inline script swaps into place; the client then calls `hydrate`.\n */\n async renderToStream(\n url: string | URL,\n options: RenderToStreamOptions = {},\n ): Promise<StreamResult> {\n const requestUrl =\n typeof url === \"string\" ? new URL(url, \"http://localhost\") : url;\n const serverRouter = new AppRouter(this.routes, {\n ...this.options,\n history: null,\n headers: options.headers,\n });\n\n const { shell, status, redirect, rest } =\n await serverRouter.renderStream(requestUrl);\n\n const encoder = new TextEncoder();\n const shellNode = new ElementNode({\n div: [shell],\n style: { display: \"contents\" },\n });\n const open =\n `<!DOCTYPE html><html><head>${options.head ?? \"\"}` +\n `<style id=\"domphy-style\">${shellNode.generateCSS()}</style>` +\n `</head><body><div id=\"domphy-app\">${shellNode.generateHTML()}</div>`;\n const bootstrap = options.bootstrap ?? \"\";\n\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n controller.enqueue(encoder.encode(open));\n const { content, data, head } = await rest;\n const contentNode = new ElementNode({\n div: [content],\n style: { display: \"contents\" },\n });\n const chunk =\n `<style>${contentNode.generateCSS()}</style>` +\n `<template id=\"domphy-head\">${head}</template>` +\n `<template id=\"domphy-content\">${contentNode.generateHTML()}</template>` +\n `<script>${STREAM_SWAP_SCRIPT}</script>` +\n `<script>window.${HYDRATION_GLOBAL} = ${serializeData(data)};</script>` +\n `${bootstrap}</body></html>`;\n controller.enqueue(encoder.encode(chunk));\n controller.close();\n serverRouter.destroy();\n },\n });\n\n return { stream, status, redirect: redirect ?? undefined };\n }\n}\n\n/** JSON with `</script>`-safe escaping so the payload can be inlined. */\nfunction serializeData(data: Record<string, unknown>): string {\n return JSON.stringify(data).replace(/</g, \"\\\\u003c\");\n}\n\nexport function createApp(routes: Route[], options: AppOptions = {}): DomphyApp {\n return new DomphyApp(routes, options);\n}\n","import type { LoaderContext, MetadataValue } from \"./types.js\";\n\n/**\n * Port of the Next.js Metadata API. Static objects merge from root layout to\n * page; later segments override earlier ones. `title.template` applies to the\n * titles of child segments, exactly like Next.js.\n */\n\nexport interface MetadataTitle {\n default?: string;\n template?: string;\n absolute?: string;\n}\n\nexport interface OpenGraphImage {\n url: string;\n width?: number;\n height?: number;\n alt?: string;\n}\n\nexport interface OpenGraphMetadata {\n title?: string;\n description?: string;\n url?: string;\n siteName?: string;\n type?: string;\n locale?: string;\n images?: (string | OpenGraphImage)[];\n}\n\nexport interface TwitterMetadata {\n card?: \"summary\" | \"summary_large_image\" | \"app\" | \"player\";\n title?: string;\n description?: string;\n site?: string;\n creator?: string;\n images?: string[];\n}\n\nexport interface RobotsMetadata {\n index?: boolean;\n follow?: boolean;\n noarchive?: boolean;\n nosnippet?: boolean;\n noimageindex?: boolean;\n}\n\nexport interface IconsMetadata {\n icon?: string;\n shortcut?: string;\n apple?: string;\n}\n\nexport interface AlternatesMetadata {\n canonical?: string;\n languages?: Record<string, string>;\n}\n\nexport interface Metadata {\n title?: string | MetadataTitle;\n description?: string;\n applicationName?: string;\n generator?: string;\n keywords?: string[];\n authors?: { name: string; url?: string }[];\n referrer?: string;\n themeColor?: string;\n colorScheme?: string;\n viewport?: string;\n robots?: string | RobotsMetadata;\n icons?: string | IconsMetadata;\n openGraph?: OpenGraphMetadata;\n twitter?: TwitterMetadata;\n alternates?: AlternatesMetadata;\n metadataBase?: string;\n /** Arbitrary extra meta tags: name -> content. */\n other?: Record<string, string>;\n}\n\nexport interface ResolvedMetadata extends Omit<Metadata, \"title\"> {\n title?: string;\n}\n\nexport interface HeadTag {\n tag: \"title\" | \"meta\" | \"link\";\n attributes: Record<string, string>;\n content?: string;\n}\n\n/** Resolves the metadata chain of all matched segments into one flat object. */\nexport async function resolveMetadata(\n values: (MetadataValue | undefined)[],\n context: LoaderContext,\n): Promise<ResolvedMetadata> {\n const resolved: ResolvedMetadata = {};\n let template: string | null = null;\n\n for (const value of values) {\n if (!value) continue;\n const metadata = typeof value === \"function\" ? await value(context) : value;\n\n for (const key of Object.keys(metadata) as (keyof Metadata)[]) {\n if (key === \"title\") continue;\n const entry = metadata[key];\n if (entry !== undefined) {\n (resolved as Record<string, unknown>)[key] = entry;\n }\n }\n\n const title = metadata.title;\n if (title === undefined) continue;\n if (typeof title === \"string\") {\n resolved.title = template ? template.replace(\"%s\", title) : title;\n continue;\n }\n if (title.absolute !== undefined) {\n resolved.title = title.absolute;\n } else if (title.default !== undefined) {\n resolved.title = template\n ? template.replace(\"%s\", title.default)\n : title.default;\n }\n if (title.template !== undefined) {\n template = title.template;\n }\n }\n\n return resolved;\n}\n\nfunction absoluteUrl(url: string, base: string | undefined): string {\n if (!base || /^[a-z][a-z0-9+.-]*:/i.test(url)) return url;\n return new URL(url, base).toString();\n}\n\nfunction robotsContent(robots: string | RobotsMetadata): string {\n if (typeof robots === \"string\") return robots;\n const directives: string[] = [];\n directives.push(robots.index === false ? \"noindex\" : \"index\");\n directives.push(robots.follow === false ? \"nofollow\" : \"follow\");\n if (robots.noarchive) directives.push(\"noarchive\");\n if (robots.nosnippet) directives.push(\"nosnippet\");\n if (robots.noimageindex) directives.push(\"noimageindex\");\n return directives.join(\", \");\n}\n\n/** Converts resolved metadata into a flat list of head tag descriptions. */\nexport function metadataToHeadTags(metadata: ResolvedMetadata): HeadTag[] {\n const tags: HeadTag[] = [];\n const base = metadata.metadataBase;\n const meta = (name: string, content: string | undefined) => {\n if (content !== undefined)\n tags.push({ tag: \"meta\", attributes: { name, content } });\n };\n const property = (name: string, content: string | undefined) => {\n if (content !== undefined) {\n tags.push({ tag: \"meta\", attributes: { property: name, content } });\n }\n };\n\n if (metadata.title !== undefined) {\n tags.push({ tag: \"title\", attributes: {}, content: metadata.title });\n }\n meta(\"description\", metadata.description);\n meta(\"application-name\", metadata.applicationName);\n meta(\"generator\", metadata.generator);\n meta(\"keywords\", metadata.keywords?.join(\", \"));\n meta(\"referrer\", metadata.referrer);\n meta(\"theme-color\", metadata.themeColor);\n meta(\"color-scheme\", metadata.colorScheme);\n meta(\"viewport\", metadata.viewport);\n if (metadata.robots !== undefined)\n meta(\"robots\", robotsContent(metadata.robots));\n for (const author of metadata.authors ?? []) {\n meta(\"author\", author.name);\n if (author.url) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"author\", href: author.url },\n });\n }\n }\n\n if (metadata.icons !== undefined) {\n const icons =\n typeof metadata.icons === \"string\"\n ? { icon: metadata.icons }\n : metadata.icons;\n if (icons.icon)\n tags.push({ tag: \"link\", attributes: { rel: \"icon\", href: icons.icon } });\n if (icons.shortcut) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"shortcut icon\", href: icons.shortcut },\n });\n }\n if (icons.apple) {\n tags.push({\n tag: \"link\",\n attributes: { rel: \"apple-touch-icon\", href: icons.apple },\n });\n }\n }\n\n const openGraph = metadata.openGraph;\n if (openGraph) {\n property(\"og:title\", openGraph.title ?? metadata.title);\n property(\"og:description\", openGraph.description ?? metadata.description);\n property(\n \"og:url\",\n openGraph.url ? absoluteUrl(openGraph.url, base) : undefined,\n );\n property(\"og:site_name\", openGraph.siteName);\n property(\"og:type\", openGraph.type);\n property(\"og:locale\", openGraph.locale);\n for (const image of openGraph.images ?? []) {\n const value = typeof image === \"string\" ? { url: image } : image;\n property(\"og:image\", absoluteUrl(value.url, base));\n if (value.width !== undefined)\n property(\"og:image:width\", String(value.width));\n if (value.height !== undefined)\n property(\"og:image:height\", String(value.height));\n if (value.alt !== undefined) property(\"og:image:alt\", value.alt);\n }\n }\n\n const twitter = metadata.twitter;\n if (twitter) {\n meta(\"twitter:card\", twitter.card ?? \"summary\");\n meta(\"twitter:title\", twitter.title ?? metadata.title);\n meta(\"twitter:description\", twitter.description ?? metadata.description);\n meta(\"twitter:site\", twitter.site);\n meta(\"twitter:creator\", twitter.creator);\n for (const image of twitter.images ?? []) {\n meta(\"twitter:image\", absoluteUrl(image, base));\n }\n }\n\n const alternates = metadata.alternates;\n if (alternates) {\n if (alternates.canonical) {\n tags.push({\n tag: \"link\",\n attributes: {\n rel: \"canonical\",\n href: absoluteUrl(alternates.canonical, base),\n },\n });\n }\n for (const language of Object.keys(alternates.languages ?? {})) {\n tags.push({\n tag: \"link\",\n attributes: {\n rel: \"alternate\",\n hreflang: language,\n href: absoluteUrl(\n (alternates.languages as Record<string, string>)[language],\n base,\n ),\n },\n });\n }\n }\n\n for (const name of Object.keys(metadata.other ?? {})) {\n meta(name, (metadata.other as Record<string, string>)[name]);\n }\n\n return tags;\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\");\n}\n\nfunction escapeText(value: string): string {\n return value.replace(/&/g, \"&\").replace(/</g, \"<\");\n}\n\n/** Serializes head tags for server rendering. */\nexport function renderHeadTags(tags: HeadTag[]): string {\n return tags\n .map((tag) => {\n const attributes = Object.keys(tag.attributes)\n .map((name) => ` ${name}=\"${escapeAttribute(tag.attributes[name])}\"`)\n .join(\"\");\n if (tag.tag === \"title\") {\n return `<title>${escapeText(tag.content ?? \"\")}</title>`;\n }\n return `<${tag.tag}${attributes}>`;\n })\n .join(\"\\n\");\n}\n\nconst MANAGED_ATTRIBUTE = \"data-domphy-head\";\n\n/** Applies head tags to `document.head`, replacing tags from the previous navigation. */\nexport function applyHeadTags(tags: HeadTag[]): void {\n if (typeof document === \"undefined\") return;\n\n for (const element of Array.from(\n document.head.querySelectorAll(`[${MANAGED_ATTRIBUTE}]`),\n )) {\n element.remove();\n }\n\n for (const tag of tags) {\n if (tag.tag === \"title\") {\n document.title = tag.content ?? \"\";\n continue;\n }\n const element = document.createElement(tag.tag);\n for (const name of Object.keys(tag.attributes)) {\n element.setAttribute(name, tag.attributes[name]);\n }\n element.setAttribute(MANAGED_ATTRIBUTE, \"\");\n document.head.appendChild(element);\n }\n}\n","import {\n type DomphyElement,\n Notifier,\n RecordState,\n type State,\n toState,\n} from \"@domphy/core\";\nimport { DataCache } from \"./dataCache.js\";\nimport { createBrowserHistory, type HistoryAdapter } from \"./history.js\";\nimport {\n type CompiledRoute,\n compileRoutes,\n matchRoute,\n matchRouteSuffix,\n type RouteMatch,\n urlPartCount,\n} from \"./matcher.js\";\nimport {\n applyHeadTags,\n metadataToHeadTags,\n renderHeadTags,\n type ResolvedMetadata,\n resolveMetadata,\n} from \"./metadata.js\";\nimport { isRewrite, NotFoundSignal, RedirectSignal } from \"./navigation.js\";\nimport {\n buildNotFoundTree,\n buildTree,\n defaultErrorBlock,\n defaultNotFoundBlock,\n type SegmentResult,\n} from \"./tree.js\";\nimport type {\n ErrorBlock,\n LoaderContext,\n Middleware,\n NavigateOptions,\n NotFoundBlock,\n Route,\n RouterEventName,\n RouterStateRecord,\n} from \"./types.js\";\n\nexport interface RouterOptions {\n /** Defaults to the browser history in a DOM environment, otherwise none (SSR). */\n history?: HistoryAdapter | null;\n /** Global middleware, the equivalent of `middleware.ts`. */\n middleware?: Middleware[];\n /** App-level not-found block, the equivalent of the root `not-found.tsx`. */\n notFound?: NotFoundBlock;\n /** App-level error block, the equivalent of `global-error.tsx`. */\n error?: ErrorBlock;\n /** Request headers, forwarded to loaders and middleware during server rendering. */\n headers?: Headers;\n}\n\ninterface TransitionOptions {\n replace?: boolean;\n scroll?: boolean;\n fromHistory?: boolean;\n initial?: boolean;\n}\n\nlet defaultRouter: AppRouter | null = null;\n\n/** The most recently created router, used by `navLink` when no router is passed explicitly. */\nexport function getRouter(): AppRouter {\n if (!defaultRouter) {\n throw new Error(\n \"No router created yet. Call createApp() or new AppRouter() first.\",\n );\n }\n return defaultRouter;\n}\n\nexport class AppRouter {\n readonly routes: CompiledRoute[];\n readonly state: RecordState<RouterStateRecord>;\n readonly tree: State<DomphyElement>;\n readonly events = new Notifier();\n readonly cache = new DataCache();\n\n private history: HistoryAdapter | null;\n private middleware: Middleware[];\n private notFoundBlock: NotFoundBlock;\n private errorBlock: ErrorBlock;\n private headers?: Headers;\n private navigationToken = 0;\n private releaseHistory: (() => void) | null = null;\n private currentMatch: RouteMatch | null = null;\n /** Cache keys backing the current render, used to drive stale-while-revalidate re-renders. */\n private currentRenderKeys = new Set<string>();\n /** Per-route compiled parallel-route slots: hard (no interception) and soft (with). */\n private slotCompiled = new Map<\n Route,\n Record<string, { soft: CompiledRoute[]; hard: CompiledRoute[] }>\n >();\n /** Metadata resolved for the current route, exposed for server rendering. */\n metadata: ResolvedMetadata = {};\n /** The last redirect followed during a transition, exposed for server rendering. */\n lastRedirect: { to: string; permanent: boolean } | null = null;\n /** Loader data of the latest render keyed by cache key, used for SSR payloads. */\n lastData: Record<string, unknown> = {};\n\n constructor(routes: Route[], options: RouterOptions = {}) {\n this.routes = compileRoutes(routes);\n this.compileSlots(routes);\n this.middleware = options.middleware ?? [];\n this.notFoundBlock = options.notFound ?? defaultNotFoundBlock;\n this.errorBlock = options.error ?? ((error) => defaultErrorBlock(error));\n this.headers = options.headers;\n this.history =\n options.history !== undefined\n ? options.history\n : typeof window !== \"undefined\"\n ? createBrowserHistory()\n : null;\n\n this.state = new RecordState<RouterStateRecord>({\n pathname: \"/\",\n search: \"\",\n hash: \"\",\n params: {},\n status: \"idle\",\n error: null,\n });\n this.tree = toState<DomphyElement>({ div: \"\" });\n // Stale-while-revalidate: when a displayed loader entry refreshes in the\n // background, re-render the current route so the fresh data appears.\n this.cache.onRevalidated((key) => this.onRevalidated(key));\n defaultRouter = this;\n }\n\n /** Precompiles parallel-route slots for every segment (recursively). */\n private compileSlots(routes: Route[]): void {\n for (const route of routes) {\n if (route.slots) {\n const entry: Record<\n string,\n { soft: CompiledRoute[]; hard: CompiledRoute[] }\n > = {};\n for (const name of Object.keys(route.slots)) {\n const slotRoutes = route.slots[name];\n entry[name] = {\n soft: compileRoutes(slotRoutes),\n hard: compileRoutes(slotRoutes.filter((route) => !route.intercept)),\n };\n this.compileSlots(slotRoutes);\n }\n this.slotCompiled.set(route, entry);\n }\n if (route.children) this.compileSlots(route.children);\n }\n }\n\n /** Runs a match's loaders and returns one result per chain segment (no loading UI). */\n private async loadMatch(\n match: RouteMatch,\n url: URL,\n ): Promise<SegmentResult[]> {\n const { chain, chainIds } = match.route;\n const context = this.loaderContext(url, match);\n const results: SegmentResult[] = chain.map(() => ({ status: \"pending\" }));\n await Promise.all(\n chain.map((route, index) => {\n if (!route.loader) {\n results[index] = { status: \"success\", data: undefined };\n return Promise.resolve();\n }\n const key = this.cacheKey(chainIds[index], url);\n return this.cache\n .load(key, route.loader, context, route.revalidate)\n .then(\n (data) => {\n results[index] = { status: \"success\", data };\n },\n (error) => {\n if (error instanceof NotFoundSignal) {\n results[index] = { status: \"notfound\" };\n } else {\n results[index] = {\n status: \"error\",\n error:\n error instanceof Error ? error : new Error(String(error)),\n };\n }\n },\n );\n }),\n );\n return results;\n }\n\n /** Renders the parallel-route slots declared on chain segment `chainIndex`. */\n private async renderSlots(\n chainIndex: number,\n match: RouteMatch,\n url: URL,\n soft: boolean,\n ): Promise<Record<string, DomphyElement>> {\n const route = match.route.chain[chainIndex];\n const compiledSlots = this.slotCompiled.get(route);\n if (!compiledSlots) return {};\n\n let prefixParts = 0;\n for (let i = 0; i <= chainIndex; i++) {\n prefixParts += urlPartCount(match.route.chain[i].path);\n }\n\n const slots: Record<string, DomphyElement> = {};\n for (const name of Object.keys(compiledSlots)) {\n const compiled = soft\n ? compiledSlots[name].soft\n : compiledSlots[name].hard;\n const slotMatch = matchRouteSuffix(compiled, url.pathname, prefixParts);\n if (!slotMatch) continue;\n slotMatch.pathname = url.pathname;\n slotMatch.params = { ...match.params, ...slotMatch.params };\n const results = await this.loadMatch(slotMatch, url);\n slots[name] = buildTree({\n match: slotMatch,\n baseContext: this.baseContext(url, slotMatch),\n results,\n retry: () => void this.refresh(),\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n }).element;\n }\n return slots;\n }\n\n private onRevalidated(key: string): void {\n // Only on the client and only when the refreshed key backs the current view.\n if (!this.history || !this.currentRenderKeys.has(key)) return;\n void this.transition(this.currentUrl(), {\n replace: true,\n scroll: false,\n fromHistory: true,\n });\n }\n\n /** Renders the current URL and starts listening to history navigation. */\n async start(): Promise<void> {\n if (this.history && !this.releaseHistory) {\n this.releaseHistory = this.history.listen((url) => {\n void this.transition(url, { fromHistory: true });\n });\n }\n const url = this.history\n ? this.history.url()\n : new URL(\"/\", \"http://localhost\");\n await this.transition(url, { initial: true });\n }\n\n destroy(): void {\n this.releaseHistory?.();\n this.releaseHistory = null;\n if (defaultRouter === this) defaultRouter = null;\n }\n\n currentUrl(): URL {\n if (this.history) return this.history.url();\n const search = this.state.get(\"search\");\n return new URL(\n `${this.state.get(\"pathname\")}${search}`,\n \"http://localhost\",\n );\n }\n\n resolve(href: string): URL {\n return new URL(href, this.currentUrl());\n }\n\n async navigate(href: string, options: NavigateOptions = {}): Promise<void> {\n const url = this.resolve(href);\n if (\n typeof window !== \"undefined\" &&\n url.origin !== this.currentUrl().origin\n ) {\n window.location.assign(url.href);\n return;\n }\n await this.transition(url, options);\n }\n\n push(\n href: string,\n options: Omit<NavigateOptions, \"replace\"> = {},\n ): Promise<void> {\n return this.navigate(href, options);\n }\n\n replace(\n href: string,\n options: Omit<NavigateOptions, \"replace\"> = {},\n ): Promise<void> {\n return this.navigate(href, { ...options, replace: true });\n }\n\n back(): void {\n this.history?.go(-1);\n }\n\n forward(): void {\n this.history?.go(1);\n }\n\n /** Clears the loader cache and re-renders the current URL, like `router.refresh()`. */\n async refresh(): Promise<void> {\n this.cache.invalidate();\n await this.transition(this.currentUrl(), { replace: true, scroll: false });\n }\n\n /** Runs the loaders of a route ahead of navigation, like `router.prefetch()`. */\n async prefetch(href: string): Promise<void> {\n try {\n const url = this.resolve(href);\n const match = matchRoute(this.routes, url.pathname);\n if (!match) return;\n const context = this.loaderContext(url, match);\n await Promise.all(\n match.route.chain.map((route, index) => {\n if (!route.loader) return Promise.resolve();\n const key = this.cacheKey(match.route.chainIds[index], url);\n return this.cache.prefetch(\n key,\n route.loader,\n context,\n route.revalidate,\n );\n }),\n );\n } catch {\n // Prefetch failures are silent; the real navigation reports errors.\n }\n }\n\n searchParams(\n listener?: Parameters<RecordState<RouterStateRecord>[\"get\"]>[1],\n ): URLSearchParams {\n return new URLSearchParams(this.state.get(\"search\", listener) as string);\n }\n\n addEventListener(\n event: RouterEventName,\n callback: (...args: unknown[]) => void,\n ): () => void {\n return this.events.addListener(event, callback);\n }\n\n /** The match rendered by the latest completed transition, null when no route matched. */\n getMatch(): RouteMatch | null {\n return this.currentMatch;\n }\n\n /**\n * Two-phase server render for streaming SSR: returns the shell (layouts +\n * loading fallbacks) synchronously, plus a promise for the resolved content,\n * head and loader data once the loaders settle. The caller streams the shell\n * first for a fast TTFB, then the content chunk when `rest` resolves.\n */\n async renderStream(url: URL): Promise<{\n shell: DomphyElement;\n status: number;\n redirect: string | null;\n rest: Promise<{\n content: DomphyElement;\n data: Record<string, unknown>;\n head: string;\n }>;\n }> {\n let renderPathname = url.pathname;\n const middlewareContext = {\n url,\n pathname: url.pathname,\n searchParams: url.searchParams,\n headers: this.headers,\n };\n for (const middleware of this.middleware) {\n const result = await middleware(middlewareContext);\n if (isRewrite(result)) renderPathname = result.__domphyRewrite;\n }\n\n const match = matchRoute(this.routes, renderPathname);\n if (!match) {\n const built = buildNotFoundTree(this.notFoundBlock);\n return {\n shell: built.element,\n status: 404,\n redirect: null,\n rest: Promise.resolve({ content: built.element, data: {}, head: \"\" }),\n };\n }\n\n const leaf = match.route.chain[match.route.chain.length - 1];\n if (leaf.redirect) {\n return {\n shell: { div: \"\" },\n status: leaf.permanent ? 308 : 307,\n redirect: leaf.redirect,\n rest: Promise.resolve({ content: { div: \"\" }, data: {}, head: \"\" }),\n };\n }\n\n const baseContext = this.baseContext(url, match);\n // Only loader-bearing segments are pending in the shell; the rest render now.\n const pending = match.route.chain.map((route) =>\n route.loader\n ? ({ status: \"pending\" } as SegmentResult)\n : ({ status: \"success\", data: undefined } as SegmentResult),\n );\n const shell = buildTree({\n match,\n baseContext,\n results: pending,\n retry: () => {},\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n }).element;\n\n const rest = (async () => {\n const results = await this.loadMatch(match, url);\n const slots: Record<number, Record<string, DomphyElement>> = {};\n await Promise.all(\n match.route.chain.map(async (route, index) => {\n if (this.slotCompiled.has(route)) {\n slots[index] = await this.renderSlots(index, match, url, false);\n }\n }),\n );\n const content = buildTree({\n match,\n baseContext,\n results,\n retry: () => {},\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n slots,\n }).element;\n\n const data: Record<string, unknown> = {};\n match.route.chain.forEach((route, index) => {\n if (route.loader && results[index].status === \"success\") {\n data[this.cacheKey(match.route.chainIds[index], url)] =\n results[index].data;\n }\n });\n\n let head = \"\";\n try {\n const metadata = await resolveMetadata(\n match.route.chain.map((route) => route.metadata),\n this.loaderContext(url, match),\n );\n head = renderHeadTags(metadataToHeadTags(metadata));\n } catch {\n head = \"\";\n }\n\n return { content, data, head };\n })();\n\n return { shell, status: 200, redirect: null, rest };\n }\n\n private cacheKey(segmentId: string, url: URL): string {\n return `${segmentId}|${url.pathname}${url.search}`;\n }\n\n private loaderContext(url: URL, match: RouteMatch): LoaderContext {\n return {\n pathname: match.pathname,\n url: url.pathname + url.search,\n params: match.params,\n searchParams: url.searchParams,\n headers: this.headers,\n };\n }\n\n /** Core navigation pipeline: middleware -> match -> loaders -> tree -> history/scroll. */\n async transition(url: URL, options: TransitionOptions = {}): Promise<void> {\n const token = ++this.navigationToken;\n const href = url.pathname + url.search + url.hash;\n if (!options.fromHistory) this.lastRedirect = null;\n this.events.notify(\"routeChangeStart\", href);\n this.saveScroll();\n\n try {\n let renderPathname = url.pathname;\n const middlewareContext = {\n url,\n pathname: url.pathname,\n searchParams: url.searchParams,\n headers: this.headers,\n };\n for (const middleware of this.middleware) {\n const result = await middleware(middlewareContext);\n if (isRewrite(result)) renderPathname = result.__domphyRewrite;\n }\n if (token !== this.navigationToken) return;\n\n const match = matchRoute(this.routes, renderPathname);\n\n if (match) {\n const leaf = match.route.chain[match.route.chain.length - 1];\n if (leaf.redirect) {\n throw new RedirectSignal(leaf.redirect, leaf.permanent ?? false);\n }\n for (const route of match.route.chain) {\n for (const middleware of route.middleware ?? []) {\n const result = await middleware(middlewareContext);\n if (isRewrite(result)) {\n await this.transition(\n new URL(result.__domphyRewrite, url),\n options,\n );\n return;\n }\n }\n }\n if (token !== this.navigationToken) return;\n await this.renderMatch(url, match, token, options);\n } else {\n await this.renderNotFound(url, token, options);\n }\n } catch (error) {\n if (token !== this.navigationToken) return;\n if (error instanceof RedirectSignal) {\n await this.transition(this.resolve(error.to), {\n ...options,\n replace: true,\n });\n // Set after the inner transition so its entry reset does not erase this.\n this.lastRedirect = { to: error.to, permanent: error.permanent };\n return;\n }\n if (error instanceof NotFoundSignal) {\n await this.renderNotFound(url, token, options);\n return;\n }\n const failure = error instanceof Error ? error : new Error(String(error));\n this.tree.set(this.errorBlock(failure, () => void this.refresh()));\n this.state.set(\"status\", \"error\");\n this.state.set(\"error\", failure);\n this.events.notify(\"routeChangeError\", failure, href);\n return;\n }\n\n if (token === this.navigationToken) {\n this.events.notify(\"routeChangeComplete\", href);\n }\n }\n\n private async renderMatch(\n url: URL,\n match: RouteMatch,\n token: number,\n options: TransitionOptions,\n ): Promise<void> {\n const { chain, chainIds } = match.route;\n const context = this.loaderContext(url, match);\n const results: SegmentResult[] = chain.map(() => ({ status: \"pending\" }));\n let redirectSignal: RedirectSignal | null = null;\n\n const promises = chain.map((route, index) => {\n if (!route.loader) {\n results[index] = { status: \"success\", data: undefined };\n return Promise.resolve();\n }\n const key = this.cacheKey(chainIds[index], url);\n return this.cache.load(key, route.loader, context, route.revalidate).then(\n (data) => {\n results[index] = { status: \"success\", data };\n },\n (error) => {\n if (error instanceof RedirectSignal) {\n redirectSignal = redirectSignal ?? error;\n } else if (error instanceof NotFoundSignal) {\n results[index] = { status: \"notfound\" };\n } else {\n results[index] = {\n status: \"error\",\n error: error instanceof Error ? error : new Error(String(error)),\n };\n }\n },\n );\n });\n\n let settled = false;\n const allSettled = Promise.all(promises).then(() => {\n settled = true;\n });\n\n // Give already-resolved (cached) loaders a chance to finish before showing loading UI.\n await new Promise((resolve) => setTimeout(resolve, 0));\n if (!settled && chain.some((route) => route.loading)) {\n const interim = buildTree({\n match,\n baseContext: this.baseContext(url, match),\n results: results.map((result) => ({ ...result })),\n retry: () => void this.refresh(),\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n });\n if (token === this.navigationToken && interim.status === \"loading\") {\n this.state.set(\"status\", \"loading\");\n this.tree.set(interim.element);\n }\n }\n\n await allSettled;\n if (token !== this.navigationToken) return;\n if (redirectSignal) throw redirectSignal;\n\n // Parallel routes: render each segment's slots ((.)intercept routes match\n // only on soft navigation, i.e. not the initial hard load).\n const soft = !options.initial;\n const slots: Record<number, Record<string, DomphyElement>> = {};\n await Promise.all(\n chain.map(async (route, index) => {\n if (this.slotCompiled.has(route)) {\n slots[index] = await this.renderSlots(index, match, url, soft);\n }\n }),\n );\n if (token !== this.navigationToken) return;\n\n const built = buildTree({\n match,\n baseContext: this.baseContext(url, match),\n results,\n retry: () => void this.refresh(),\n defaultError: this.errorBlock,\n defaultNotFound: this.notFoundBlock,\n slots,\n });\n\n const dataRecord: Record<string, unknown> = {};\n chain.forEach((route, index) => {\n if (route.loader && results[index].status === \"success\") {\n dataRecord[this.cacheKey(chainIds[index], url)] = results[index].data;\n }\n });\n this.lastData = dataRecord;\n this.currentRenderKeys = new Set(Object.keys(dataRecord));\n\n this.currentMatch = match;\n await this.applyMetadata(match, context);\n if (token !== this.navigationToken) return;\n\n this.commit(url, match, built.element, built.status, options);\n // Kick off stale-while-revalidate refetches now that the route is committed,\n // so onRevalidated re-renders against the current view.\n this.cache.flushRevalidations();\n }\n\n private async renderNotFound(\n url: URL,\n token: number,\n options: TransitionOptions,\n ): Promise<void> {\n const built = buildNotFoundTree(this.notFoundBlock);\n this.currentMatch = null;\n this.metadata = {};\n applyHeadTags([]);\n if (token !== this.navigationToken) return;\n this.commit(url, null, built.element, \"notfound\", options);\n }\n\n private baseContext(url: URL, match: RouteMatch) {\n return {\n pathname: match.pathname,\n url: url.pathname + url.search,\n params: match.params,\n searchParams: url.searchParams,\n hash: url.hash,\n headers: this.headers,\n };\n }\n\n private async applyMetadata(\n match: RouteMatch,\n context: LoaderContext,\n ): Promise<void> {\n try {\n this.metadata = await resolveMetadata(\n match.route.chain.map((route) => route.metadata),\n context,\n );\n } catch {\n this.metadata = {};\n }\n applyHeadTags(metadataToHeadTags(this.metadata));\n }\n\n private commit(\n url: URL,\n match: RouteMatch | null,\n element: DomphyElement,\n status: RouterStateRecord[\"status\"],\n options: TransitionOptions,\n ): void {\n if (this.history && !options.fromHistory && !options.initial) {\n const href = url.pathname + url.search + url.hash;\n if (options.replace) {\n this.history.replace(href);\n } else {\n this.history.push(href);\n }\n }\n\n this.state.set(\"pathname\", url.pathname);\n this.state.set(\"search\", url.search);\n this.state.set(\"hash\", url.hash);\n this.state.set(\"params\", match?.params ?? {});\n this.state.set(\"error\", null);\n this.state.set(\"status\", status);\n this.tree.set(element);\n\n this.restoreScroll(url, options);\n }\n\n private saveScroll(): void {\n if (typeof window === \"undefined\") return;\n this.history?.saveScroll?.({ x: window.scrollX, y: window.scrollY });\n }\n\n private restoreScroll(url: URL, options: TransitionOptions): void {\n if (\n typeof window === \"undefined\" ||\n options.scroll === false ||\n options.initial\n )\n return;\n if (options.fromHistory) {\n const position = this.history?.readScroll?.();\n window.scrollTo(position?.x ?? 0, position?.y ?? 0);\n return;\n }\n if (url.hash) {\n const target = document.getElementById(url.hash.slice(1));\n if (target) {\n target.scrollIntoView();\n return;\n }\n }\n window.scrollTo(0, 0);\n }\n}\n","import { Notifier } from \"@domphy/core\";\nimport type { Loader, LoaderContext } from \"./types.js\";\n\ninterface CacheEntry {\n data: unknown;\n timestamp: number;\n /** Entries seeded from SSR or prefetch are consumed once even by uncached loaders. */\n consumable: boolean;\n}\n\n/** How long a prefetched entry stays usable, mirrors the Next.js client router cache. */\nexport const PREFETCH_LIFETIME = 30_000;\n\n/**\n * Loader result cache. The `revalidate` option of a route controls the entry\n * lifetime, the equivalent of fetch caching / ISR in Next.js.\n */\nexport class DataCache {\n private entries = new Map<string, CacheEntry>();\n private inflight = new Map<string, Promise<unknown>>();\n private notifier = new Notifier();\n /** Stale entries served this render, queued for background refetch after commit. */\n private pending = new Map<string, () => void>();\n\n /**\n * Subscribes to background revalidation. Fires with the entry key once a\n * stale-while-revalidate refetch lands fresh data, so the router can re-render\n * the route that served the stale value.\n */\n onRevalidated(callback: (key: string) => void): () => void {\n return this.notifier.addListener(\"revalidated\", callback);\n }\n\n /** Seeds entries (from SSR payloads) that satisfy the next load exactly once. */\n seed(record: Record<string, unknown>): void {\n for (const key of Object.keys(record)) {\n this.entries.set(key, {\n data: record[key],\n timestamp: Date.now(),\n consumable: true,\n });\n }\n }\n\n snapshot(keys: string[]): Record<string, unknown> {\n const record: Record<string, unknown> = {};\n for (const key of keys) {\n const entry = this.entries.get(key);\n if (entry) record[key] = entry.data;\n }\n return record;\n }\n\n invalidate(prefix?: string): void {\n if (prefix === undefined) {\n this.entries.clear();\n return;\n }\n for (const key of this.entries.keys()) {\n if (key.startsWith(prefix)) this.entries.delete(key);\n }\n }\n\n async load(\n key: string,\n loader: Loader,\n context: LoaderContext,\n revalidate: number | undefined,\n ): Promise<unknown> {\n const entry = this.entries.get(key);\n if (entry) {\n const lifetime = revalidate !== undefined ? revalidate * 1000 : 0;\n const fresh = Date.now() - entry.timestamp <= lifetime;\n const usableSeed =\n entry.consumable && Date.now() - entry.timestamp <= PREFETCH_LIFETIME;\n if (fresh || usableSeed) {\n if (entry.consumable && !fresh) this.entries.delete(key);\n return entry.data;\n }\n // Stale-while-revalidate: a cached (revalidate > 0) entry that aged out is\n // served immediately and queued for a background refetch. The refetch is\n // deferred until `flushRevalidations()` (called after the current render\n // commits) so `onRevalidated` fires against the committed route.\n if (revalidate !== undefined && revalidate > 0) {\n this.pending.set(key, () => this.revalidate(key, loader, context));\n return entry.data;\n }\n this.entries.delete(key);\n }\n\n const pending = this.inflight.get(key);\n if (pending) return pending;\n\n const promise = Promise.resolve(loader(context)).then(\n (data) => {\n this.inflight.delete(key);\n if (revalidate !== undefined && revalidate > 0) {\n this.entries.set(key, {\n data,\n timestamp: Date.now(),\n consumable: false,\n });\n }\n return data;\n },\n (error) => {\n this.inflight.delete(key);\n throw error;\n },\n );\n this.inflight.set(key, promise);\n return promise;\n }\n\n /** Starts the background refetch for every stale entry served by the last render. */\n flushRevalidations(): void {\n if (this.pending.size === 0) return;\n const thunks = [...this.pending.values()];\n this.pending.clear();\n for (const thunk of thunks) thunk();\n }\n\n /** Background refetch for stale-while-revalidate; updates the entry and notifies on success. */\n private revalidate(\n key: string,\n loader: Loader,\n context: LoaderContext,\n ): void {\n if (this.inflight.has(key)) return;\n const promise = Promise.resolve(loader(context)).then(\n (data) => {\n this.inflight.delete(key);\n this.entries.set(key, {\n data,\n timestamp: Date.now(),\n consumable: false,\n });\n this.notifier.notify(\"revalidated\", key);\n return data;\n },\n (error) => {\n // Keep the stale entry on failure; revalidation errors are silent.\n this.inflight.delete(key);\n throw error;\n },\n );\n // Swallow rejection here so the background refetch never becomes an\n // unhandled rejection; the stale entry simply remains.\n promise.catch(() => {});\n this.inflight.set(key, promise);\n }\n\n /** Runs the loader ahead of navigation and stores the result as a one-shot entry. */\n async prefetch(\n key: string,\n loader: Loader,\n context: LoaderContext,\n revalidate: number | undefined,\n ): Promise<void> {\n if (revalidate !== undefined) {\n await this.load(key, loader, context, revalidate);\n return;\n }\n const existing = this.entries.get(key);\n if (existing && Date.now() - existing.timestamp <= PREFETCH_LIFETIME)\n return;\n if (this.inflight.has(key)) return;\n const data = await loader(context);\n this.entries.set(key, { data, timestamp: Date.now(), consumable: true });\n }\n}\n","/**\n * Minimal history abstraction so the router runs against the real browser\n * history, an in-memory stack (tests, embedded demos) or nothing at all (SSR).\n */\n\nexport interface HistoryAdapter {\n url(): URL;\n push(url: string): void;\n replace(url: string): void;\n go(delta: number): void;\n /** Subscribes to external navigation (popstate / memory go). Returns a release function. */\n listen(callback: (url: URL) => void): () => void;\n /** Saves and restores scroll positions per history entry. */\n saveScroll?(position: { x: number; y: number }): void;\n readScroll?(): { x: number; y: number } | null;\n}\n\ninterface BrowserHistoryState {\n __domphyIndex: number;\n}\n\nexport function createBrowserHistory(): HistoryAdapter {\n const scrollPositions = new Map<number, { x: number; y: number }>();\n let index =\n (window.history.state as BrowserHistoryState | null)?.__domphyIndex ?? 0;\n if (window.history.state?.__domphyIndex === undefined) {\n window.history.replaceState({ __domphyIndex: index }, \"\");\n }\n if (\"scrollRestoration\" in window.history) {\n window.history.scrollRestoration = \"manual\";\n }\n\n return {\n url: () => new URL(window.location.href),\n push: (url) => {\n index++;\n window.history.pushState({ __domphyIndex: index }, \"\", url);\n },\n replace: (url) => {\n window.history.replaceState({ __domphyIndex: index }, \"\", url);\n },\n go: (delta) => window.history.go(delta),\n listen: (callback) => {\n const handler = () => {\n index =\n (window.history.state as BrowserHistoryState | null)?.__domphyIndex ??\n 0;\n callback(new URL(window.location.href));\n };\n window.addEventListener(\"popstate\", handler);\n return () => window.removeEventListener(\"popstate\", handler);\n },\n saveScroll: (position) => scrollPositions.set(index, position),\n readScroll: () => scrollPositions.get(index) ?? null,\n };\n}\n\nconst MEMORY_ORIGIN = \"http://localhost\";\n\nexport function createMemoryHistory(initial = \"/\"): HistoryAdapter {\n const stack: string[] = [initial];\n let index = 0;\n const listeners = new Set<(url: URL) => void>();\n\n return {\n url: () => new URL(stack[index], MEMORY_ORIGIN),\n push: (url) => {\n stack.splice(index + 1);\n stack.push(url);\n index++;\n },\n replace: (url) => {\n stack[index] = url;\n },\n go: (delta) => {\n const next = Math.min(Math.max(index + delta, 0), stack.length - 1);\n if (next === index) return;\n index = next;\n const url = new URL(stack[index], MEMORY_ORIGIN);\n for (const listener of listeners) listener(url);\n },\n listen: (callback) => {\n listeners.add(callback);\n return () => listeners.delete(callback);\n },\n };\n}\n","import type { DomphyElement } from \"@domphy/core\";\nimport type { RouteMatch } from \"./matcher.js\";\nimport type {\n ErrorBlock,\n NotFoundBlock,\n RouteContext,\n RouterStatus,\n} from \"./types.js\";\n\nexport type SegmentStatus = \"success\" | \"pending\" | \"error\" | \"notfound\";\n\nexport interface SegmentResult {\n status: SegmentStatus;\n data?: unknown;\n error?: Error;\n}\n\nexport interface BuildTreeInput {\n match: RouteMatch;\n baseContext: Omit<RouteContext, \"data\" | \"segmentData\">;\n results: SegmentResult[];\n retry: () => void;\n defaultError: ErrorBlock;\n defaultNotFound: NotFoundBlock;\n /** Rendered parallel-route slots per chain index, passed to that segment's layout. */\n slots?: Record<number, Record<string, DomphyElement>>;\n}\n\nexport interface BuiltTree {\n element: DomphyElement;\n status: RouterStatus;\n}\n\nexport function defaultErrorBlock(error: Error): DomphyElement {\n return {\n div: [{ h2: \"Application error\" }, { p: error.message }],\n };\n}\n\nexport function defaultNotFoundBlock(): DomphyElement {\n return {\n div: [{ h2: \"404\" }, { p: \"This page could not be found.\" }],\n };\n}\n\nfunction findBoundary(results: SegmentResult[], status: SegmentStatus): number {\n return results.findIndex((result) => result.status === status);\n}\n\n/**\n * Composes the matched chain into one element: page wrapped by every layout,\n * exactly like nested `layout.tsx` files. When a segment failed, is pending or\n * raised `notFound()`, the subtree below the nearest boundary block (`error`,\n * `loading`, `notFound`) is replaced by that block while ancestor layouts keep\n * rendering — the same boundary model as the Next.js App Router.\n */\nexport function buildTree(input: BuildTreeInput): BuiltTree {\n const { match, baseContext, results, retry, defaultError, defaultNotFound } =\n input;\n const { chain, chainIds } = match.route;\n\n const segmentData: Record<string, unknown> = {};\n for (let i = 0; i < chain.length; i++) {\n segmentData[chainIds[i]] = results[i]?.data;\n }\n const contexts: RouteContext[] = chain.map((_, i) => ({\n ...baseContext,\n data: results[i]?.data,\n segmentData,\n }));\n\n const errorIndex = findBoundary(results, \"error\");\n const notFoundIndex = findBoundary(results, \"notfound\");\n const pendingIndex = findBoundary(results, \"pending\");\n\n let inner: DomphyElement;\n let wrapLimit: number;\n let status: RouterStatus;\n\n if (errorIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, errorIndex, (route) =>\n Boolean(route.error),\n );\n const block =\n blockIndex === -1\n ? defaultError\n : (chain[blockIndex].error as ErrorBlock);\n inner = block(results[errorIndex].error as Error, retry);\n inner._key = `${chainIds[Math.max(blockIndex, 0)]}:error`;\n wrapLimit = Math.min(blockIndex, errorIndex - 1);\n status = \"error\";\n } else if (notFoundIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, notFoundIndex, (route) =>\n Boolean(route.notFound),\n );\n const block =\n blockIndex === -1\n ? defaultNotFound\n : (chain[blockIndex].notFound as NotFoundBlock);\n inner = block();\n inner._key = `${chainIds[Math.max(blockIndex, 0)]}:notfound`;\n wrapLimit = Math.min(blockIndex, notFoundIndex - 1);\n status = \"notfound\";\n } else if (pendingIndex !== -1) {\n const blockIndex = nearestBlockIndex(chain, pendingIndex, (route) =>\n Boolean(route.loading),\n );\n if (blockIndex === -1) {\n // No loading block anywhere: caller keeps the previous tree on screen.\n return { element: { div: \"\" }, status: \"loading\" };\n }\n inner = chain[blockIndex].loading!(contexts[blockIndex]);\n inner._key = `${chainIds[blockIndex]}:loading`;\n wrapLimit = Math.min(blockIndex, pendingIndex - 1);\n status = \"loading\";\n } else {\n const leaf = chain[chain.length - 1];\n inner = leaf.page!(contexts[chain.length - 1]);\n inner._key = `${match.route.id}:page`;\n wrapLimit = chain.length - 1;\n status = \"idle\";\n }\n\n let element = inner;\n for (let i = wrapLimit; i >= 0; i--) {\n const layout = chain[i].layout;\n if (!layout) continue;\n element = layout(element, contexts[i], input.slots?.[i] ?? {});\n if (element._key === undefined) element._key = `${chainIds[i]}:layout`;\n }\n\n return { element, status };\n}\n\nfunction nearestBlockIndex(\n chain: BuildTreeInput[\"match\"][\"route\"][\"chain\"],\n fromIndex: number,\n predicate: (\n route: BuildTreeInput[\"match\"][\"route\"][\"chain\"][number],\n ) => boolean,\n): number {\n for (let i = fromIndex; i >= 0; i--) {\n if (predicate(chain[i])) return i;\n }\n return -1;\n}\n\n/** Wraps a bare not-found block with the root layouts of a match-less render. */\nexport function buildNotFoundTree(block: NotFoundBlock): BuiltTree {\n const element = block();\n if (element._key === undefined) element._key = \"app:notfound\";\n return { element, status: \"notfound\" };\n}\n","import type { PartialElement } from \"@domphy/core\";\n\nexport interface ImageLoaderInput {\n src: string;\n width: number;\n quality: number;\n}\n\nexport type ImageLoader = (input: ImageLoaderInput) => string;\n\nexport interface OptimizedImageProps {\n src: string;\n alt?: string;\n width?: number;\n height?: number;\n /** Stretch over the positioned parent, like the `fill` prop of `next/image`. */\n fill?: boolean;\n sizes?: string;\n quality?: number;\n /** Load eagerly with high fetch priority — use for the LCP image. */\n priority?: boolean;\n placeholder?: \"blur\" | \"empty\";\n blurDataURL?: string;\n /** Maps `src` + width to an optimized URL; enables `srcset` generation. */\n loader?: ImageLoader;\n deviceSizes?: number[];\n}\n\nconst DEFAULT_DEVICE_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];\n\n/**\n * Patch for `img` elements, the equivalent of `next/image`: lazy loading,\n * async decoding, fetch priority, `srcset` through a custom loader, fill\n * layout and blur placeholders. URL optimization itself is the loader's job —\n * point it at any image CDN.\n */\nexport function optimizedImage(props: OptimizedImageProps): PartialElement<\"img\"> {\n const {\n src,\n alt = \"\",\n width,\n height,\n fill = false,\n sizes,\n quality = 75,\n priority = false,\n placeholder = \"empty\",\n blurDataURL,\n loader,\n deviceSizes = DEFAULT_DEVICE_SIZES,\n } = props;\n\n const part: PartialElement<\"img\"> = {\n src: loader\n ? loader({\n src,\n width: width ?? deviceSizes[deviceSizes.length - 1],\n quality,\n })\n : src,\n alt,\n loading: priority ? \"eager\" : \"lazy\",\n decoding: \"async\",\n fetchPriority: priority ? \"high\" : \"auto\",\n style: {},\n };\n\n if (loader) {\n part.srcSet = deviceSizes\n .map((size) => `${loader({ src, width: size, quality })} ${size}w`)\n .join(\", \");\n if (sizes) part.sizes = sizes;\n }\n\n if (width !== undefined) part.width = width;\n if (height !== undefined) part.height = height;\n\n if (fill) {\n part.style = {\n ...part.style,\n position: \"absolute\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n };\n }\n\n if (placeholder === \"blur\" && blurDataURL) {\n part.style = {\n ...part.style,\n backgroundImage: `url(\"${blurDataURL}\")`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n };\n part.onLoad = (event) => {\n const image = event.target as HTMLImageElement;\n image.style.backgroundImage = \"\";\n };\n }\n\n return part;\n}\n","import type { PartialElement } from \"@domphy/core\";\nimport { type AppRouter, getRouter } from \"./router.js\";\n\nexport interface NavLinkProps {\n href: string;\n /** Replace the current history entry instead of pushing. */\n replace?: boolean;\n /** Scroll after navigation, defaults to true. */\n scroll?: boolean;\n /**\n * Prefetch strategy, like the `prefetch` prop of `next/link`:\n * `\"visible\"` when the link enters the viewport, `\"hover\"` on pointer/focus,\n * `false` never. Defaults to `\"hover\"`.\n */\n prefetch?: \"visible\" | \"hover\" | false;\n /** Mark active only on an exact pathname match, not on descendants. */\n exact?: boolean;\n /** Explicit router; defaults to the app router. */\n router?: AppRouter;\n}\n\nfunction isModifiedClick(event: MouseEvent): boolean {\n return (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n );\n}\n\n/**\n * Patch for `a` elements, the equivalent of `next/link`: client-side\n * navigation, prefetching and active state (`aria-current` + `data-active`).\n */\nexport function navLink(props: NavLinkProps): PartialElement<\"a\"> {\n const {\n href,\n replace = false,\n scroll = true,\n prefetch = \"hover\",\n exact = false,\n } = props;\n const router = () => props.router ?? getRouter();\n\n const isActive = (pathname: string): boolean => {\n const target = new URL(href, \"http://localhost\").pathname;\n if (exact || target === \"/\") return pathname === target;\n return pathname === target || pathname.startsWith(`${target}/`);\n };\n\n let prefetched = false;\n const prefetchOnce = () => {\n if (prefetched) return;\n prefetched = true;\n void router().prefetch(href);\n };\n\n return {\n href,\n ariaCurrent: (listener) =>\n isActive(router().state.get(\"pathname\", listener) as string)\n ? \"page\"\n : null,\n dataActive: (listener) =>\n isActive(router().state.get(\"pathname\", listener) as string) ? \"\" : null,\n onClick: (event) => {\n const mouseEvent = event as MouseEvent;\n const anchor = mouseEvent.currentTarget as HTMLAnchorElement;\n if (isModifiedClick(mouseEvent)) return;\n if (anchor.target && anchor.target !== \"_self\") return;\n if (anchor.hasAttribute(\"download\")) return;\n if (\n new URL(anchor.href, window.location.href).origin !==\n window.location.origin\n )\n return;\n mouseEvent.preventDefault();\n void router().navigate(href, { replace, scroll });\n },\n onMouseEnter: () => {\n if (prefetch === \"hover\") prefetchOnce();\n },\n onFocus: () => {\n if (prefetch === \"hover\") prefetchOnce();\n },\n _onMount: (node) => {\n if (prefetch !== \"visible\") return;\n if (typeof IntersectionObserver === \"undefined\") {\n prefetchOnce();\n return;\n }\n const observer = new IntersectionObserver((entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n prefetchOnce();\n observer.disconnect();\n }\n });\n observer.observe(node.domElement as Element);\n node.setMetadata(\"navLinkObserver\", observer);\n },\n _onRemove: (node) => {\n const observer = node.getMetadata(\"navLinkObserver\") as\n | IntersectionObserver\n | undefined;\n observer?.disconnect();\n },\n };\n}\n","import type { DomphyElement } from \"@domphy/core\";\n\nexport interface ScriptProps {\n src: string;\n /**\n * Loading strategy, like `next/script`:\n * `\"afterInteractive\"` loads as soon as the element mounts (default),\n * `\"lazyOnload\"` waits for the window `load` event plus idle time.\n */\n strategy?: \"afterInteractive\" | \"lazyOnload\";\n id?: string;\n async?: boolean;\n onLoad?: () => void;\n onError?: () => void;\n}\n\nconst loadedScripts = new Set<string>();\n\n/** Resets script dedupe between tests. */\nexport function resetScripts(): void {\n loadedScripts.clear();\n}\n\nfunction whenIdle(callback: () => void): void {\n const idle = (\n globalThis as { requestIdleCallback?: (cb: () => void) => void }\n ).requestIdleCallback;\n if (idle) {\n idle(callback);\n } else {\n setTimeout(callback, 0);\n }\n}\n\n/**\n * Block that loads an external script once, the equivalent of `next/script`.\n * Place it anywhere in the tree; duplicate sources are loaded only once.\n */\nexport function script(props: ScriptProps): DomphyElement<\"script\"> {\n const {\n src,\n strategy = \"afterInteractive\",\n id,\n async = true,\n onLoad,\n onError,\n } = props;\n const dedupeKey = id ?? src;\n\n const start = (element: HTMLScriptElement) => {\n if (loadedScripts.has(dedupeKey)) return;\n loadedScripts.add(dedupeKey);\n element.src = src;\n };\n\n const part: DomphyElement<\"script\"> = {\n script: \"\",\n async,\n onLoad: () => onLoad?.(),\n onError: () => onError?.(),\n _onMount: (node) => {\n const element = node.domElement as HTMLScriptElement;\n if (strategy === \"afterInteractive\") {\n start(element);\n return;\n }\n if (document.readyState === \"complete\") {\n whenIdle(() => start(element));\n } else {\n window.addEventListener(\"load\", () => whenIdle(() => start(element)), {\n once: true,\n });\n }\n },\n };\n if (id !== undefined) part.id = id;\n return part;\n}\n","import type { DomphyElement } from \"@domphy/core\";\nimport type { Metadata } from \"./metadata.js\";\n\n/** Route params. Dynamic segments map to strings, catch-all segments to string arrays. */\nexport type Params = Record<string, string | string[]>;\n\n/** Shared context given to pages, layouts, loaders, metadata functions and middleware. */\nexport interface RouteContext<TData = unknown> {\n /** Pathname actually rendered (after middleware rewrites). */\n pathname: string;\n /** Pathname shown in the address bar (before rewrites). */\n url: string;\n params: Params;\n searchParams: URLSearchParams;\n hash: string;\n /** Resolved loader data of the owning segment. */\n data: TData;\n /** Resolved loader data of every matched segment, keyed by segment id. */\n segmentData: Record<string, unknown>;\n /** Request headers, only present during server rendering. */\n headers?: Headers;\n}\n\nexport type PageBlock<TData = unknown> = (\n context: RouteContext<TData>,\n) => DomphyElement;\n\nexport type LayoutBlock<TData = unknown> = (\n children: DomphyElement,\n context: RouteContext<TData>,\n /** Rendered parallel-route slots declared on this segment, keyed by slot name. */\n slots: Record<string, DomphyElement>,\n) => DomphyElement;\n\nexport type LoadingBlock = (context: RouteContext) => DomphyElement;\n\nexport type ErrorBlock = (error: Error, retry: () => void) => DomphyElement;\n\nexport type NotFoundBlock = () => DomphyElement;\n\nexport interface LoaderContext {\n pathname: string;\n url: string;\n params: Params;\n searchParams: URLSearchParams;\n headers?: Headers;\n}\n\nexport type Loader<TData = unknown> = (\n context: LoaderContext,\n) => TData | Promise<TData>;\n\nexport type MetadataValue =\n | Metadata\n | ((context: LoaderContext) => Metadata | Promise<Metadata>);\n\nexport interface MiddlewareContext {\n url: URL;\n pathname: string;\n searchParams: URLSearchParams;\n headers?: Headers;\n}\n\n/** A rewrite instruction returned from middleware. Create with `rewrite()`. */\nexport interface RewriteResult {\n __domphyRewrite: string;\n}\n\n/**\n * Middleware runs before every navigation and server render.\n * Return `rewrite(path)` to render another route under the same URL,\n * call `redirect(path)` / `notFound()` to interrupt, or return nothing to continue.\n */\nexport type Middleware = (\n context: MiddlewareContext,\n) =>\n | RewriteResult\n | undefined\n | void\n | Promise<RewriteResult | undefined | void>;\n\n/**\n * One route segment, the equivalent of one folder in the Next.js `app` directory.\n *\n * `path` uses Next.js conventions:\n * - `\"about\"` static segment (may contain several parts: `\"docs/getting-started\"`)\n * - `\"[slug]\"` dynamic segment\n * - `\"[...slug]\"` catch-all segment\n * - `\"[[...slug]]\"` optional catch-all segment\n * - `\"(marketing)\"` route group, organizes the tree without affecting the URL\n *\n * A segment is routable when it declares `page` or `redirect`.\n */\nexport interface Route {\n path: string;\n page?: PageBlock<any>;\n layout?: LayoutBlock<any>;\n loading?: LoadingBlock;\n error?: ErrorBlock;\n notFound?: NotFoundBlock;\n metadata?: MetadataValue;\n loader?: Loader<any>;\n /**\n * Loader cache lifetime in seconds, the equivalent of Next.js `revalidate`.\n * `undefined` re-runs the loader on every navigation, `Infinity` caches forever.\n */\n revalidate?: number;\n middleware?: Middleware[];\n /** Static redirect: navigating to this route immediately redirects to the target. */\n redirect?: string;\n /** Use a 308 redirect on the server when `redirect` is set. */\n permanent?: boolean;\n children?: Route[];\n /**\n * Parallel routes (Next.js `@slot` folders). Each slot is an independent route\n * tree matched against the path *below* this segment; the rendered element of\n * each is passed to `layout`'s third argument. A slot route with `intercept`\n * set captures a matching URL during client navigation (intercepting routes).\n */\n slots?: Record<string, Route[]>;\n /**\n * Intercepting route marker (Next.js `(.)`, `(..)`, `(...)`). When set, this\n * slot route only matches during client-side (soft) navigation, letting it\n * render an interception (e.g. a modal) over the previous page; a hard load of\n * the same URL renders the real route instead.\n */\n intercept?: boolean;\n}\n\nexport type RouterStatus = \"idle\" | \"loading\" | \"error\" | \"notfound\";\n\nexport interface RouterStateRecord {\n pathname: string;\n search: string;\n hash: string;\n params: Params;\n status: RouterStatus;\n error: Error | null;\n\n [key: string]: unknown;\n}\n\nexport interface NavigateOptions {\n replace?: boolean;\n /** Scroll to the top (or the URL hash) after navigation. Defaults to true. */\n scroll?: boolean;\n}\n\nexport type RouterEventName =\n | \"routeChangeStart\"\n | \"routeChangeComplete\"\n | \"routeChangeError\";\n\n/** Identity helper that keeps route literals fully typed. */\nexport function defineRoutes(routes: Route[]): Route[] {\n return routes;\n}\n"],"mappings":"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","names":["index_exports","__export","AppRouter","DataCache","DomphyApp","NotFoundSignal","PREFETCH_LIFETIME","RedirectSignal","applyHeadTags","buildHref","buildNotFoundTree","buildTree","compareSpecificity","compileRoutes","createApiHandler","createApp","createBrowserHistory","createMemoryHistory","defaultErrorBlock","defaultNotFoundBlock","defineRoutes","getRouter","isRewrite","json","matchPath","matchRoute","matchRouteSuffix","metadataToHeadTags","navLink","notFound","optimizedImage","parseSegment","permanentRedirect","redirect","renderHeadTags","resetScripts","resolveMetadata","rewrite","script","splitPath","urlPartCount","__toCommonJS","parseSegment","part","splitPath","path","urlPartCount","segment","matchRouteSuffix","compiled","pathname","prefixParts","suffix","matchRoute","compileRoutes","routes","walk","nodes","parentSegments","parentChain","parentChainIds","parentId","node","parts","ownSegments","urlSegments","id","chain","chainIds","compareSpecificity","KIND_RANK","a","b","length","i","segmentA","segmentB","rankDifference","matchPath","segments","params","partIndex","isLast","route","buildHref","pattern","value","RedirectSignal","to","permanent","NotFoundSignal","redirect","permanentRedirect","notFound","rewrite","isRewrite","value","METHODS","json","data","init","headers","__spreadProps","__spreadValues","createApiHandler","routes","pairs","apiRoute","compiled","compileRoutes","pair","byNode","request","__async","url","match","matchRoute","route","allowed","method","handler","response","error","RedirectSignal","NotFoundSignal","import_core","resolveMetadata","values","context","__async","resolved","template","value","metadata","key","entry","title","absoluteUrl","url","base","robotsContent","robots","directives","metadataToHeadTags","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","tags","meta","name","content","property","author","icons","openGraph","image","twitter","alternates","language","escapeAttribute","escapeText","renderHeadTags","tag","attributes","MANAGED_ATTRIBUTE","applyHeadTags","element","import_core","import_core","PREFETCH_LIFETIME","DataCache","callback","record","key","keys","entry","prefix","loader","context","revalidate","__async","lifetime","fresh","usableSeed","pending","promise","data","error","thunks","thunk","existing","createBrowserHistory","_a","_b","_c","scrollPositions","index","url","delta","callback","handler","position","MEMORY_ORIGIN","createMemoryHistory","initial","stack","listeners","next","listener","defaultErrorBlock","error","defaultNotFoundBlock","findBoundary","results","status","result","buildTree","input","_a","_b","_c","match","baseContext","retry","defaultError","defaultNotFound","chain","chainIds","segmentData","i","contexts","_","__spreadProps","__spreadValues","errorIndex","notFoundIndex","pendingIndex","inner","wrapLimit","blockIndex","nearestBlockIndex","route","element","layout","fromIndex","predicate","buildNotFoundTree","block","defaultRouter","getRouter","AppRouter","routes","options","DataCache","_a","_b","_c","compileRoutes","defaultNotFoundBlock","error","defaultErrorBlock","createBrowserHistory","key","route","entry","name","slotRoutes","match","url","__async","chain","chainIds","context","results","index","data","NotFoundSignal","chainIndex","soft","compiledSlots","prefixParts","i","urlPartCount","slots","compiled","slotMatch","matchRouteSuffix","__spreadValues","buildTree","search","href","_0","__spreadProps","matchRoute","listener","event","callback","renderPathname","middlewareContext","middleware","result","isRewrite","built","buildNotFoundTree","leaf","baseContext","pending","shell","rest","content","head","metadata","resolveMetadata","renderHeadTags","metadataToHeadTags","e","segmentId","token","RedirectSignal","failure","redirectSignal","promises","settled","allSettled","resolve","interim","dataRecord","applyHeadTags","element","status","_d","position","target","STREAM_SWAP_SCRIPT","HYDRATION_GLOBAL","DomphyApp","routes","options","AppRouter","router","listener","target","__async","style","seeded","_a","_0","url","requestUrl","serverRouter","__spreadProps","__spreadValues","status","redirect","node","data","result","renderHeadTags","metadataToHeadTags","serializeData","_b","shell","rest","encoder","shellNode","open","bootstrap","controller","content","head","contentNode","chunk","createApp","DEFAULT_DEVICE_SIZES","optimizedImage","props","src","alt","width","height","fill","sizes","quality","priority","placeholder","blurDataURL","loader","deviceSizes","part","size","__spreadProps","__spreadValues","event","image","isModifiedClick","event","navLink","props","href","replace","scroll","prefetch","exact","router","_a","getRouter","isActive","pathname","target","prefetched","prefetchOnce","listener","mouseEvent","anchor","node","observer","entries","entry","loadedScripts","resetScripts","whenIdle","callback","idle","script","props","src","strategy","id","async","onLoad","onError","dedupeKey","start","element","part","node","defineRoutes","routes"]}
|