@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/index.d.cts CHANGED
@@ -108,7 +108,9 @@ interface RouteContext<TData = unknown> {
108
108
  headers?: Headers;
109
109
  }
110
110
  type PageBlock<TData = unknown> = (context: RouteContext<TData>) => DomphyElement;
111
- type LayoutBlock<TData = unknown> = (children: DomphyElement, context: RouteContext<TData>) => DomphyElement;
111
+ type LayoutBlock<TData = unknown> = (children: DomphyElement, context: RouteContext<TData>,
112
+ /** Rendered parallel-route slots declared on this segment, keyed by slot name. */
113
+ slots: Record<string, DomphyElement>) => DomphyElement;
112
114
  type LoadingBlock = (context: RouteContext) => DomphyElement;
113
115
  type ErrorBlock = (error: Error, retry: () => void) => DomphyElement;
114
116
  type NotFoundBlock = () => DomphyElement;
@@ -169,6 +171,20 @@ interface Route {
169
171
  /** Use a 308 redirect on the server when `redirect` is set. */
170
172
  permanent?: boolean;
171
173
  children?: Route[];
174
+ /**
175
+ * Parallel routes (Next.js `@slot` folders). Each slot is an independent route
176
+ * tree matched against the path *below* this segment; the rendered element of
177
+ * each is passed to `layout`'s third argument. A slot route with `intercept`
178
+ * set captures a matching URL during client navigation (intercepting routes).
179
+ */
180
+ slots?: Record<string, Route[]>;
181
+ /**
182
+ * Intercepting route marker (Next.js `(.)`, `(..)`, `(...)`). When set, this
183
+ * slot route only matches during client-side (soft) navigation, letting it
184
+ * render an interception (e.g. a modal) over the previous page; a hard load of
185
+ * the same URL renders the real route instead.
186
+ */
187
+ intercept?: boolean;
172
188
  }
173
189
  type RouterStatus = "idle" | "loading" | "error" | "notfound";
174
190
  interface RouterStateRecord {
@@ -247,11 +263,24 @@ declare const PREFETCH_LIFETIME = 30000;
247
263
  declare class DataCache {
248
264
  private entries;
249
265
  private inflight;
266
+ private notifier;
267
+ /** Stale entries served this render, queued for background refetch after commit. */
268
+ private pending;
269
+ /**
270
+ * Subscribes to background revalidation. Fires with the entry key once a
271
+ * stale-while-revalidate refetch lands fresh data, so the router can re-render
272
+ * the route that served the stale value.
273
+ */
274
+ onRevalidated(callback: (key: string) => void): () => void;
250
275
  /** Seeds entries (from SSR payloads) that satisfy the next load exactly once. */
251
276
  seed(record: Record<string, unknown>): void;
252
277
  snapshot(keys: string[]): Record<string, unknown>;
253
278
  invalidate(prefix?: string): void;
254
279
  load(key: string, loader: Loader, context: LoaderContext, revalidate: number | undefined): Promise<unknown>;
280
+ /** Starts the background refetch for every stale entry served by the last render. */
281
+ flushRevalidations(): void;
282
+ /** Background refetch for stale-while-revalidate; updates the entry and notifies on success. */
283
+ private revalidate;
255
284
  /** Runs the loader ahead of navigation and stores the result as a one-shot entry. */
256
285
  prefetch(key: string, loader: Loader, context: LoaderContext, revalidate: number | undefined): Promise<void>;
257
286
  }
@@ -280,6 +309,10 @@ interface RouteMatch {
280
309
  }
281
310
  declare function parseSegment(part: string): PatternSegment;
282
311
  declare function splitPath(path: string): string[];
312
+ /** Number of URL parts a route path contributes (route groups don't count). */
313
+ declare function urlPartCount(path: string): number;
314
+ /** Matches `pathname` after dropping the first `prefixParts` URL parts (slot/intercept matching). */
315
+ declare function matchRouteSuffix(compiled: CompiledRoute[], pathname: string, prefixParts: number): RouteMatch | null;
283
316
  /** Flattens a route tree into a list of routable endpoints. */
284
317
  declare function compileRoutes(routes: Route[]): CompiledRoute[];
285
318
  /** Static segments win over dynamic, dynamic over catch-all — same priority order as Next.js. */
@@ -323,6 +356,10 @@ declare class AppRouter {
323
356
  private navigationToken;
324
357
  private releaseHistory;
325
358
  private currentMatch;
359
+ /** Cache keys backing the current render, used to drive stale-while-revalidate re-renders. */
360
+ private currentRenderKeys;
361
+ /** Per-route compiled parallel-route slots: hard (no interception) and soft (with). */
362
+ private slotCompiled;
326
363
  /** Metadata resolved for the current route, exposed for server rendering. */
327
364
  metadata: ResolvedMetadata;
328
365
  /** The last redirect followed during a transition, exposed for server rendering. */
@@ -333,6 +370,13 @@ declare class AppRouter {
333
370
  /** Loader data of the latest render keyed by cache key, used for SSR payloads. */
334
371
  lastData: Record<string, unknown>;
335
372
  constructor(routes: Route[], options?: RouterOptions);
373
+ /** Precompiles parallel-route slots for every segment (recursively). */
374
+ private compileSlots;
375
+ /** Runs a match's loaders and returns one result per chain segment (no loading UI). */
376
+ private loadMatch;
377
+ /** Renders the parallel-route slots declared on chain segment `chainIndex`. */
378
+ private renderSlots;
379
+ private onRevalidated;
336
380
  /** Renders the current URL and starts listening to history navigation. */
337
381
  start(): Promise<void>;
338
382
  destroy(): void;
@@ -351,6 +395,22 @@ declare class AppRouter {
351
395
  addEventListener(event: RouterEventName, callback: (...args: unknown[]) => void): () => void;
352
396
  /** The match rendered by the latest completed transition, null when no route matched. */
353
397
  getMatch(): RouteMatch | null;
398
+ /**
399
+ * Two-phase server render for streaming SSR: returns the shell (layouts +
400
+ * loading fallbacks) synchronously, plus a promise for the resolved content,
401
+ * head and loader data once the loaders settle. The caller streams the shell
402
+ * first for a fast TTFB, then the content chunk when `rest` resolves.
403
+ */
404
+ renderStream(url: URL): Promise<{
405
+ shell: DomphyElement;
406
+ status: number;
407
+ redirect: string | null;
408
+ rest: Promise<{
409
+ content: DomphyElement;
410
+ data: Record<string, unknown>;
411
+ head: string;
412
+ }>;
413
+ }>;
354
414
  private cacheKey;
355
415
  private loaderContext;
356
416
  /** Core navigation pipeline: middleware -> match -> loaders -> tree -> history/scroll. */
@@ -370,6 +430,18 @@ interface AppOptions extends Omit<RouterOptions, "history" | "headers"> {
370
430
  interface RenderToStringOptions {
371
431
  headers?: Headers;
372
432
  }
433
+ interface RenderToStreamOptions extends RenderToStringOptions {
434
+ /** Extra HTML for `<head>` (charset, viewport, fonts, a CSS link…), sent in the first flush. */
435
+ head?: string;
436
+ /** Markup appended before `</body>`, typically the client bundle `<script>` that calls `hydrate()`. */
437
+ bootstrap?: string;
438
+ }
439
+ interface StreamResult {
440
+ /** A web `ReadableStream` of UTF-8 bytes: the shell flushes first, content follows. */
441
+ stream: ReadableStream<Uint8Array>;
442
+ status: number;
443
+ redirect?: string;
444
+ }
373
445
  interface SSRResult {
374
446
  /** Body markup of the app root, ready to place inside the mount element. */
375
447
  html: string;
@@ -408,6 +480,13 @@ declare class DomphyApp {
408
480
  destroy(): void;
409
481
  /** Server rendering: runs middleware and loaders for `url`, returns markup + CSS + head. */
410
482
  renderToString(url: string | URL, options?: RenderToStringOptions): Promise<SSRResult>;
483
+ /**
484
+ * Streaming server render. Flushes the shell (layouts + loading fallbacks)
485
+ * immediately for a fast TTFB, then streams the resolved content, head and
486
+ * hydration data once loaders settle. The content arrives in `<template>`s
487
+ * that an inline script swaps into place; the client then calls `hydrate`.
488
+ */
489
+ renderToStream(url: string | URL, options?: RenderToStreamOptions): Promise<StreamResult>;
411
490
  }
412
491
  declare function createApp(routes: Route[], options?: AppOptions): DomphyApp;
413
492
 
@@ -520,6 +599,8 @@ interface BuildTreeInput {
520
599
  retry: () => void;
521
600
  defaultError: ErrorBlock;
522
601
  defaultNotFound: NotFoundBlock;
602
+ /** Rendered parallel-route slots per chain index, passed to that segment's layout. */
603
+ slots?: Record<number, Record<string, DomphyElement>>;
523
604
  }
524
605
  interface BuiltTree {
525
606
  element: DomphyElement;
@@ -538,4 +619,4 @@ declare function buildTree(input: BuildTreeInput): BuiltTree;
538
619
  /** Wraps a bare not-found block with the root layouts of a match-less render. */
539
620
  declare function buildNotFoundTree(block: NotFoundBlock): BuiltTree;
540
621
 
541
- export { type AlternatesMetadata, type ApiContext, type ApiMethodHandler, type ApiRoute, type AppOptions, AppRouter, type BuildTreeInput, type BuiltTree, type CompiledRoute, DataCache, DomphyApp, type ErrorBlock, type HeadTag, type HistoryAdapter, type HttpMethod, type IconsMetadata, type ImageLoader, type ImageLoaderInput, type LayoutBlock, type Loader, type LoaderContext, type LoadingBlock, type Metadata, type MetadataTitle, type MetadataValue, type Middleware, type MiddlewareContext, type NavLinkProps, type NavigateOptions, type NotFoundBlock, NotFoundSignal, type OpenGraphImage, type OpenGraphMetadata, type OptimizedImageProps, PREFETCH_LIFETIME, type PageBlock, type Params, type PatternSegment, RedirectSignal, type RenderToStringOptions, type ResolvedMetadata, type RewriteResult, type RobotsMetadata, type Route, type RouteContext, type RouteMatch, type RouterEventName, type RouterOptions, type RouterStateRecord, type RouterStatus, type SSRResult, type ScriptProps, type SegmentKind, type SegmentResult, type SegmentStatus, type TwitterMetadata, 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 };
622
+ export { type AlternatesMetadata, type ApiContext, type ApiMethodHandler, type ApiRoute, type AppOptions, AppRouter, type BuildTreeInput, type BuiltTree, type CompiledRoute, DataCache, DomphyApp, type ErrorBlock, type HeadTag, type HistoryAdapter, type HttpMethod, type IconsMetadata, type ImageLoader, type ImageLoaderInput, type LayoutBlock, type Loader, type LoaderContext, type LoadingBlock, type Metadata, type MetadataTitle, type MetadataValue, type Middleware, type MiddlewareContext, type NavLinkProps, type NavigateOptions, type NotFoundBlock, NotFoundSignal, type OpenGraphImage, type OpenGraphMetadata, type OptimizedImageProps, PREFETCH_LIFETIME, type PageBlock, type Params, type PatternSegment, RedirectSignal, type RenderToStreamOptions, type RenderToStringOptions, type ResolvedMetadata, type RewriteResult, type RobotsMetadata, type Route, type RouteContext, type RouteMatch, type RouterEventName, type RouterOptions, type RouterStateRecord, type RouterStatus, type SSRResult, type ScriptProps, type SegmentKind, type SegmentResult, type SegmentStatus, type StreamResult, type TwitterMetadata, 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 };
package/dist/index.d.ts CHANGED
@@ -108,7 +108,9 @@ interface RouteContext<TData = unknown> {
108
108
  headers?: Headers;
109
109
  }
110
110
  type PageBlock<TData = unknown> = (context: RouteContext<TData>) => DomphyElement;
111
- type LayoutBlock<TData = unknown> = (children: DomphyElement, context: RouteContext<TData>) => DomphyElement;
111
+ type LayoutBlock<TData = unknown> = (children: DomphyElement, context: RouteContext<TData>,
112
+ /** Rendered parallel-route slots declared on this segment, keyed by slot name. */
113
+ slots: Record<string, DomphyElement>) => DomphyElement;
112
114
  type LoadingBlock = (context: RouteContext) => DomphyElement;
113
115
  type ErrorBlock = (error: Error, retry: () => void) => DomphyElement;
114
116
  type NotFoundBlock = () => DomphyElement;
@@ -169,6 +171,20 @@ interface Route {
169
171
  /** Use a 308 redirect on the server when `redirect` is set. */
170
172
  permanent?: boolean;
171
173
  children?: Route[];
174
+ /**
175
+ * Parallel routes (Next.js `@slot` folders). Each slot is an independent route
176
+ * tree matched against the path *below* this segment; the rendered element of
177
+ * each is passed to `layout`'s third argument. A slot route with `intercept`
178
+ * set captures a matching URL during client navigation (intercepting routes).
179
+ */
180
+ slots?: Record<string, Route[]>;
181
+ /**
182
+ * Intercepting route marker (Next.js `(.)`, `(..)`, `(...)`). When set, this
183
+ * slot route only matches during client-side (soft) navigation, letting it
184
+ * render an interception (e.g. a modal) over the previous page; a hard load of
185
+ * the same URL renders the real route instead.
186
+ */
187
+ intercept?: boolean;
172
188
  }
173
189
  type RouterStatus = "idle" | "loading" | "error" | "notfound";
174
190
  interface RouterStateRecord {
@@ -247,11 +263,24 @@ declare const PREFETCH_LIFETIME = 30000;
247
263
  declare class DataCache {
248
264
  private entries;
249
265
  private inflight;
266
+ private notifier;
267
+ /** Stale entries served this render, queued for background refetch after commit. */
268
+ private pending;
269
+ /**
270
+ * Subscribes to background revalidation. Fires with the entry key once a
271
+ * stale-while-revalidate refetch lands fresh data, so the router can re-render
272
+ * the route that served the stale value.
273
+ */
274
+ onRevalidated(callback: (key: string) => void): () => void;
250
275
  /** Seeds entries (from SSR payloads) that satisfy the next load exactly once. */
251
276
  seed(record: Record<string, unknown>): void;
252
277
  snapshot(keys: string[]): Record<string, unknown>;
253
278
  invalidate(prefix?: string): void;
254
279
  load(key: string, loader: Loader, context: LoaderContext, revalidate: number | undefined): Promise<unknown>;
280
+ /** Starts the background refetch for every stale entry served by the last render. */
281
+ flushRevalidations(): void;
282
+ /** Background refetch for stale-while-revalidate; updates the entry and notifies on success. */
283
+ private revalidate;
255
284
  /** Runs the loader ahead of navigation and stores the result as a one-shot entry. */
256
285
  prefetch(key: string, loader: Loader, context: LoaderContext, revalidate: number | undefined): Promise<void>;
257
286
  }
@@ -280,6 +309,10 @@ interface RouteMatch {
280
309
  }
281
310
  declare function parseSegment(part: string): PatternSegment;
282
311
  declare function splitPath(path: string): string[];
312
+ /** Number of URL parts a route path contributes (route groups don't count). */
313
+ declare function urlPartCount(path: string): number;
314
+ /** Matches `pathname` after dropping the first `prefixParts` URL parts (slot/intercept matching). */
315
+ declare function matchRouteSuffix(compiled: CompiledRoute[], pathname: string, prefixParts: number): RouteMatch | null;
283
316
  /** Flattens a route tree into a list of routable endpoints. */
284
317
  declare function compileRoutes(routes: Route[]): CompiledRoute[];
285
318
  /** Static segments win over dynamic, dynamic over catch-all — same priority order as Next.js. */
@@ -323,6 +356,10 @@ declare class AppRouter {
323
356
  private navigationToken;
324
357
  private releaseHistory;
325
358
  private currentMatch;
359
+ /** Cache keys backing the current render, used to drive stale-while-revalidate re-renders. */
360
+ private currentRenderKeys;
361
+ /** Per-route compiled parallel-route slots: hard (no interception) and soft (with). */
362
+ private slotCompiled;
326
363
  /** Metadata resolved for the current route, exposed for server rendering. */
327
364
  metadata: ResolvedMetadata;
328
365
  /** The last redirect followed during a transition, exposed for server rendering. */
@@ -333,6 +370,13 @@ declare class AppRouter {
333
370
  /** Loader data of the latest render keyed by cache key, used for SSR payloads. */
334
371
  lastData: Record<string, unknown>;
335
372
  constructor(routes: Route[], options?: RouterOptions);
373
+ /** Precompiles parallel-route slots for every segment (recursively). */
374
+ private compileSlots;
375
+ /** Runs a match's loaders and returns one result per chain segment (no loading UI). */
376
+ private loadMatch;
377
+ /** Renders the parallel-route slots declared on chain segment `chainIndex`. */
378
+ private renderSlots;
379
+ private onRevalidated;
336
380
  /** Renders the current URL and starts listening to history navigation. */
337
381
  start(): Promise<void>;
338
382
  destroy(): void;
@@ -351,6 +395,22 @@ declare class AppRouter {
351
395
  addEventListener(event: RouterEventName, callback: (...args: unknown[]) => void): () => void;
352
396
  /** The match rendered by the latest completed transition, null when no route matched. */
353
397
  getMatch(): RouteMatch | null;
398
+ /**
399
+ * Two-phase server render for streaming SSR: returns the shell (layouts +
400
+ * loading fallbacks) synchronously, plus a promise for the resolved content,
401
+ * head and loader data once the loaders settle. The caller streams the shell
402
+ * first for a fast TTFB, then the content chunk when `rest` resolves.
403
+ */
404
+ renderStream(url: URL): Promise<{
405
+ shell: DomphyElement;
406
+ status: number;
407
+ redirect: string | null;
408
+ rest: Promise<{
409
+ content: DomphyElement;
410
+ data: Record<string, unknown>;
411
+ head: string;
412
+ }>;
413
+ }>;
354
414
  private cacheKey;
355
415
  private loaderContext;
356
416
  /** Core navigation pipeline: middleware -> match -> loaders -> tree -> history/scroll. */
@@ -370,6 +430,18 @@ interface AppOptions extends Omit<RouterOptions, "history" | "headers"> {
370
430
  interface RenderToStringOptions {
371
431
  headers?: Headers;
372
432
  }
433
+ interface RenderToStreamOptions extends RenderToStringOptions {
434
+ /** Extra HTML for `<head>` (charset, viewport, fonts, a CSS link…), sent in the first flush. */
435
+ head?: string;
436
+ /** Markup appended before `</body>`, typically the client bundle `<script>` that calls `hydrate()`. */
437
+ bootstrap?: string;
438
+ }
439
+ interface StreamResult {
440
+ /** A web `ReadableStream` of UTF-8 bytes: the shell flushes first, content follows. */
441
+ stream: ReadableStream<Uint8Array>;
442
+ status: number;
443
+ redirect?: string;
444
+ }
373
445
  interface SSRResult {
374
446
  /** Body markup of the app root, ready to place inside the mount element. */
375
447
  html: string;
@@ -408,6 +480,13 @@ declare class DomphyApp {
408
480
  destroy(): void;
409
481
  /** Server rendering: runs middleware and loaders for `url`, returns markup + CSS + head. */
410
482
  renderToString(url: string | URL, options?: RenderToStringOptions): Promise<SSRResult>;
483
+ /**
484
+ * Streaming server render. Flushes the shell (layouts + loading fallbacks)
485
+ * immediately for a fast TTFB, then streams the resolved content, head and
486
+ * hydration data once loaders settle. The content arrives in `<template>`s
487
+ * that an inline script swaps into place; the client then calls `hydrate`.
488
+ */
489
+ renderToStream(url: string | URL, options?: RenderToStreamOptions): Promise<StreamResult>;
411
490
  }
412
491
  declare function createApp(routes: Route[], options?: AppOptions): DomphyApp;
413
492
 
@@ -520,6 +599,8 @@ interface BuildTreeInput {
520
599
  retry: () => void;
521
600
  defaultError: ErrorBlock;
522
601
  defaultNotFound: NotFoundBlock;
602
+ /** Rendered parallel-route slots per chain index, passed to that segment's layout. */
603
+ slots?: Record<number, Record<string, DomphyElement>>;
523
604
  }
524
605
  interface BuiltTree {
525
606
  element: DomphyElement;
@@ -538,4 +619,4 @@ declare function buildTree(input: BuildTreeInput): BuiltTree;
538
619
  /** Wraps a bare not-found block with the root layouts of a match-less render. */
539
620
  declare function buildNotFoundTree(block: NotFoundBlock): BuiltTree;
540
621
 
541
- export { type AlternatesMetadata, type ApiContext, type ApiMethodHandler, type ApiRoute, type AppOptions, AppRouter, type BuildTreeInput, type BuiltTree, type CompiledRoute, DataCache, DomphyApp, type ErrorBlock, type HeadTag, type HistoryAdapter, type HttpMethod, type IconsMetadata, type ImageLoader, type ImageLoaderInput, type LayoutBlock, type Loader, type LoaderContext, type LoadingBlock, type Metadata, type MetadataTitle, type MetadataValue, type Middleware, type MiddlewareContext, type NavLinkProps, type NavigateOptions, type NotFoundBlock, NotFoundSignal, type OpenGraphImage, type OpenGraphMetadata, type OptimizedImageProps, PREFETCH_LIFETIME, type PageBlock, type Params, type PatternSegment, RedirectSignal, type RenderToStringOptions, type ResolvedMetadata, type RewriteResult, type RobotsMetadata, type Route, type RouteContext, type RouteMatch, type RouterEventName, type RouterOptions, type RouterStateRecord, type RouterStatus, type SSRResult, type ScriptProps, type SegmentKind, type SegmentResult, type SegmentStatus, type TwitterMetadata, 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 };
622
+ export { type AlternatesMetadata, type ApiContext, type ApiMethodHandler, type ApiRoute, type AppOptions, AppRouter, type BuildTreeInput, type BuiltTree, type CompiledRoute, DataCache, DomphyApp, type ErrorBlock, type HeadTag, type HistoryAdapter, type HttpMethod, type IconsMetadata, type ImageLoader, type ImageLoaderInput, type LayoutBlock, type Loader, type LoaderContext, type LoadingBlock, type Metadata, type MetadataTitle, type MetadataValue, type Middleware, type MiddlewareContext, type NavLinkProps, type NavigateOptions, type NotFoundBlock, NotFoundSignal, type OpenGraphImage, type OpenGraphMetadata, type OptimizedImageProps, PREFETCH_LIFETIME, type PageBlock, type Params, type PatternSegment, RedirectSignal, type RenderToStreamOptions, type RenderToStringOptions, type ResolvedMetadata, type RewriteResult, type RobotsMetadata, type Route, type RouteContext, type RouteMatch, type RouterEventName, type RouterOptions, type RouterStateRecord, type RouterStatus, type SSRResult, type ScriptProps, type SegmentKind, type SegmentResult, type SegmentStatus, type StreamResult, type TwitterMetadata, 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 };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- var ie=Object.defineProperty,se=Object.defineProperties;var ae=Object.getOwnPropertyDescriptors;var K=Object.getOwnPropertySymbols;var le=Object.prototype.hasOwnProperty,ce=Object.prototype.propertyIsEnumerable;var z=(r,e,t)=>e in r?ie(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,x=(r,e)=>{for(var t in e||(e={}))le.call(e,t)&&z(r,t,e[t]);if(K)for(var t of K(e))ce.call(e,t)&&z(r,t,e[t]);return r},b=(r,e)=>se(r,ae(e));var R=(r,e,t)=>new Promise((n,o)=>{var i=l=>{try{a(t.next(l))}catch(p){o(p)}},s=l=>{try{a(t.throw(l))}catch(p){o(p)}},a=l=>l.done?n(l.value):Promise.resolve(l.value).then(i,s);a((t=t.apply(r,e)).next())});function W(r){return r.startsWith("(")&&r.endsWith(")")?{kind:"group",value:r.slice(1,-1)}:r.startsWith("[[...")&&r.endsWith("]]")?{kind:"optional-catchall",value:r.slice(5,-2)}:r.startsWith("[...")&&r.endsWith("]")?{kind:"catchall",value:r.slice(4,-1)}:r.startsWith("[")&&r.endsWith("]")?{kind:"dynamic",value:r.slice(1,-1)}:{kind:"static",value:r}}function D(r){return r.split("/").filter(e=>e.length>0)}function I(r){let e=[];function t(n,o,i,s,a){for(let l of n){let p=D(l.path),d=p.map(W),c=[...o,...d.filter(g=>g.kind!=="group")],h=`${a}/${p.join("/")}`.replace(/\/+/g,"/"),m=[...i,l],f=[...s,h===""?"/":h];(l.page||l.redirect)&&e.push({id:h===""?"/":h,segments:c,chain:m,chainIds:f}),l.children&&t(l.children,c,m,f,h)}}return t(r,[],[],[],""),e.sort(ue),e}var q={static:0,dynamic:1,catchall:2,"optional-catchall":3,group:0};function ue(r,e){let t=Math.max(r.segments.length,e.segments.length);for(let n=0;n<t;n++){let o=r.segments[n],i=e.segments[n];if(!o)return-1;if(!i)return 1;let s=q[o.kind]-q[i.kind];if(s!==0)return s}return 0}function de(r,e){let t=D(e).map(i=>decodeURIComponent(i)),n={},o=0;for(let i=0;i<r.length;i++){let s=r[i],a=i===r.length-1;if(s.kind==="static"){if(t[o]!==s.value)return null;o++;continue}if(s.kind==="dynamic"){if(o>=t.length)return null;n[s.value]=t[o],o++;continue}if(s.kind==="catchall")return!a||o>=t.length?null:(n[s.value]=t.slice(o),n);if(s.kind==="optional-catchall")return a?(n[s.value]=t.slice(o),n):null}return o!==t.length?null:n}function T(r,e){for(let t of r){let n=de(t.segments,e);if(n)return{route:t,params:n,pathname:e}}return null}function ke(r,e={}){return`/${D(r).map(W).filter(n=>n.kind!=="group").flatMap(n=>{if(n.kind==="static")return[n.value];let o=e[n.value];if(o===void 0){if(n.kind==="optional-catchall")return[];throw new Error(`Missing param "${n.value}" for pattern "${r}".`)}return(Array.isArray(o)?o:[o]).map(s=>encodeURIComponent(s))}).join("/")}`}var E=class extends Error{constructor(e,t){super(`Redirect to ${e}`),this.name="RedirectSignal",this.to=e,this.permanent=t}},S=class extends Error{constructor(){super("Not found"),this.name="NotFoundSignal"}};function Se(r){throw new E(r,!1)}function Me(r){throw new E(r,!0)}function Te(){throw new S}function Pe(r){return{__domphyRewrite:r}}function N(r){return typeof r=="object"&&r!==null&&typeof r.__domphyRewrite=="string"}var pe=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];function C(r,e={}){let t=new Headers(e.headers);return t.has("content-type")||t.set("content-type","application/json; charset=utf-8"),new Response(JSON.stringify(r),b(x({},e),{headers:t}))}function Ce(r){let e=r.map(o=>({apiRoute:o,routeNode:{path:o.path,page:()=>({div:""})}})),t=I(e.map(o=>o.routeNode)),n=new Map(e.map(o=>[o.routeNode,o.apiRoute]));return o=>R(null,null,function*(){let i=new URL(o.url),s=T(t,i.pathname);if(!s)return C({error:"Not Found"},{status:404});let a=n.get(s.route.chain[s.route.chain.length-1]),l=pe.filter(c=>a[c]),p=o.method.toUpperCase(),d=a[p];if(!d&&p==="HEAD"&&a.GET&&(d=a.GET),!d&&p==="OPTIONS")return new Response(null,{status:204,headers:{allow:l.join(", ")}});if(!d)return C({error:"Method Not Allowed"},{status:405,headers:{allow:l.join(", ")}});try{let c=yield d(o,{params:s.params});return p==="HEAD"?new Response(null,{status:c.status,headers:c.headers}):c}catch(c){return c instanceof E?new Response(null,{status:c.permanent?308:307,headers:{location:c.to}}):c instanceof S?C({error:"Not Found"},{status:404}):C({error:"Internal Server Error"},{status:500})}})}import{ElementNode as j}from"@domphy/core";function Y(r,e){return R(this,null,function*(){let t={},n=null;for(let o of r){if(!o)continue;let i=typeof o=="function"?yield o(e):o;for(let a of Object.keys(i)){if(a==="title")continue;let l=i[a];l!==void 0&&(t[a]=l)}let s=i.title;if(s!==void 0){if(typeof s=="string"){t.title=n?n.replace("%s",s):s;continue}s.absolute!==void 0?t.title=s.absolute:s.default!==void 0&&(t.title=n?n.replace("%s",s.default):s.default),s.template!==void 0&&(n=s.template)}}return t})}function P(r,e){return!e||/^[a-z][a-z0-9+.-]*:/i.test(r)?r:new URL(r,e).toString()}function he(r){if(typeof r=="string")return r;let e=[];return e.push(r.index===!1?"noindex":"index"),e.push(r.follow===!1?"nofollow":"follow"),r.noarchive&&e.push("noarchive"),r.nosnippet&&e.push("nosnippet"),r.noimageindex&&e.push("noimageindex"),e.join(", ")}function A(r){var l,p,d,c,h,m,f,g,w,k,v;let e=[],t=r.metadataBase,n=(u,y)=>{y!==void 0&&e.push({tag:"meta",attributes:{name:u,content:y}})},o=(u,y)=>{y!==void 0&&e.push({tag:"meta",attributes:{property:u,content:y}})};r.title!==void 0&&e.push({tag:"title",attributes:{},content:r.title}),n("description",r.description),n("application-name",r.applicationName),n("generator",r.generator),n("keywords",(l=r.keywords)==null?void 0:l.join(", ")),n("referrer",r.referrer),n("theme-color",r.themeColor),n("color-scheme",r.colorScheme),n("viewport",r.viewport),r.robots!==void 0&&n("robots",he(r.robots));for(let u of(p=r.authors)!=null?p:[])n("author",u.name),u.url&&e.push({tag:"link",attributes:{rel:"author",href:u.url}});if(r.icons!==void 0){let u=typeof r.icons=="string"?{icon:r.icons}:r.icons;u.icon&&e.push({tag:"link",attributes:{rel:"icon",href:u.icon}}),u.shortcut&&e.push({tag:"link",attributes:{rel:"shortcut icon",href:u.shortcut}}),u.apple&&e.push({tag:"link",attributes:{rel:"apple-touch-icon",href:u.apple}})}let i=r.openGraph;if(i){o("og:title",(d=i.title)!=null?d:r.title),o("og:description",(c=i.description)!=null?c:r.description),o("og:url",i.url?P(i.url,t):void 0),o("og:site_name",i.siteName),o("og:type",i.type),o("og:locale",i.locale);for(let u of(h=i.images)!=null?h:[]){let y=typeof u=="string"?{url:u}:u;o("og:image",P(y.url,t)),y.width!==void 0&&o("og:image:width",String(y.width)),y.height!==void 0&&o("og:image:height",String(y.height)),y.alt!==void 0&&o("og:image:alt",y.alt)}}let s=r.twitter;if(s){n("twitter:card",(m=s.card)!=null?m:"summary"),n("twitter:title",(f=s.title)!=null?f:r.title),n("twitter:description",(g=s.description)!=null?g:r.description),n("twitter:site",s.site),n("twitter:creator",s.creator);for(let u of(w=s.images)!=null?w:[])n("twitter:image",P(u,t))}let a=r.alternates;if(a){a.canonical&&e.push({tag:"link",attributes:{rel:"canonical",href:P(a.canonical,t)}});for(let u of Object.keys((k=a.languages)!=null?k:{}))e.push({tag:"link",attributes:{rel:"alternate",hreflang:u,href:P(a.languages[u],t)}})}for(let u of Object.keys((v=r.other)!=null?v:{}))n(u,r.other[u]);return e}function me(r){return r.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;")}function fe(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;")}function J(r){return r.map(e=>{var n;let t=Object.keys(e.attributes).map(o=>` ${o}="${me(e.attributes[o])}"`).join("");return e.tag==="title"?`<title>${fe((n=e.content)!=null?n:"")}</title>`:`<${e.tag}${t}>`}).join(`
2
- `)}var V="data-domphy-head";function B(r){var e;if(typeof document!="undefined"){for(let t of Array.from(document.head.querySelectorAll(`[${V}]`)))t.remove();for(let t of r){if(t.tag==="title"){document.title=(e=t.content)!=null?e:"";continue}let n=document.createElement(t.tag);for(let o of Object.keys(t.attributes))n.setAttribute(o,t.attributes[o]);n.setAttribute(V,""),document.head.appendChild(n)}}}import{Notifier as ge,RecordState as ye,toState as we}from"@domphy/core";var Be=3e4,O=class{constructor(){this.entries=new Map;this.inflight=new Map}seed(e){for(let t of Object.keys(e))this.entries.set(t,{data:e[t],timestamp:Date.now(),consumable:!0})}snapshot(e){let t={};for(let n of e){let o=this.entries.get(n);o&&(t[n]=o.data)}return t}invalidate(e){if(e===void 0){this.entries.clear();return}for(let t of this.entries.keys())t.startsWith(e)&&this.entries.delete(t)}load(e,t,n,o){return R(this,null,function*(){let i=this.entries.get(e);if(i){let l=o!==void 0?o*1e3:0,p=Date.now()-i.timestamp<=l,d=i.consumable&&Date.now()-i.timestamp<=3e4;if(p||d)return i.consumable&&!p&&this.entries.delete(e),i.data;this.entries.delete(e)}let s=this.inflight.get(e);if(s)return s;let a=Promise.resolve(t(n)).then(l=>(this.inflight.delete(e),o!==void 0&&o>0&&this.entries.set(e,{data:l,timestamp:Date.now(),consumable:!1}),l),l=>{throw this.inflight.delete(e),l});return this.inflight.set(e,a),a})}prefetch(e,t,n,o){return R(this,null,function*(){if(o!==void 0){yield this.load(e,t,n,o);return}let i=this.entries.get(e);if(i&&Date.now()-i.timestamp<=3e4||this.inflight.has(e))return;let s=yield t(n);this.entries.set(e,{data:s,timestamp:Date.now(),consumable:!0})})}};function Z(){var t,n,o;let r=new Map,e=(n=(t=window.history.state)==null?void 0:t.__domphyIndex)!=null?n:0;return((o=window.history.state)==null?void 0:o.__domphyIndex)===void 0&&window.history.replaceState({__domphyIndex:e},""),"scrollRestoration"in window.history&&(window.history.scrollRestoration="manual"),{url:()=>new URL(window.location.href),push:i=>{e++,window.history.pushState({__domphyIndex:e},"",i)},replace:i=>{window.history.replaceState({__domphyIndex:e},"",i)},go:i=>window.history.go(i),listen:i=>{let s=()=>{var a,l;e=(l=(a=window.history.state)==null?void 0:a.__domphyIndex)!=null?l:0,i(new URL(window.location.href))};return window.addEventListener("popstate",s),()=>window.removeEventListener("popstate",s)},saveScroll:i=>r.set(e,i),readScroll:()=>{var i;return(i=r.get(e))!=null?i:null}}}var X="http://localhost";function Fe(r="/"){let e=[r],t=0,n=new Set;return{url:()=>new URL(e[t],X),push:o=>{e.splice(t+1),e.push(o),t++},replace:o=>{e[t]=o},go:o=>{let i=Math.min(Math.max(t+o,0),e.length-1);if(i===t)return;t=i;let s=new URL(e[t],X);for(let a of n)a(s)},listen:o=>(n.add(o),()=>n.delete(o))}}function Q(r){return{div:[{h2:"Application error"},{p:r.message}]}}function ee(){return{div:[{h2:"404"},{p:"This page could not be found."}]}}function _(r,e){return r.findIndex(t=>t.status===e)}function F(r){var v;let{match:e,baseContext:t,results:n,retry:o,defaultError:i,defaultNotFound:s}=r,{chain:a,chainIds:l}=e.route,p={};for(let u=0;u<a.length;u++)p[l[u]]=(v=n[u])==null?void 0:v.data;let d=a.map((u,y)=>{var M;return b(x({},t),{data:(M=n[y])==null?void 0:M.data,segmentData:p})}),c=_(n,"error"),h=_(n,"notfound"),m=_(n,"pending"),f,g,w;if(c!==-1){let u=U(a,c,M=>!!M.error);f=(u===-1?i:a[u].error)(n[c].error,o),f._key=`${l[Math.max(u,0)]}:error`,g=Math.min(u,c-1),w="error"}else if(h!==-1){let u=U(a,h,M=>!!M.notFound);f=(u===-1?s:a[u].notFound)(),f._key=`${l[Math.max(u,0)]}:notfound`,g=Math.min(u,h-1),w="notfound"}else if(m!==-1){let u=U(a,m,y=>!!y.loading);if(u===-1)return{element:{div:""},status:"loading"};f=a[u].loading(d[u]),f._key=`${l[u]}:loading`,g=Math.min(u,m-1),w="loading"}else f=a[a.length-1].page(d[a.length-1]),f._key=`${e.route.id}:page`,g=a.length-1,w="idle";let k=f;for(let u=g;u>=0;u--){let y=a[u].layout;y&&(k=y(k,d[u]),k._key===void 0&&(k._key=`${l[u]}:layout`))}return{element:k,status:w}}function U(r,e,t){for(let n=e;n>=0;n--)if(t(r[n]))return n;return-1}function te(r){let e=r();return e._key===void 0&&(e._key="app:notfound"),{element:e,status:"notfound"}}var L=null;function re(){if(!L)throw new Error("No router created yet. Call createApp() or new AppRouter() first.");return L}var H=class{constructor(e,t={}){this.events=new ge;this.cache=new O;this.navigationToken=0;this.releaseHistory=null;this.currentMatch=null;this.metadata={};this.lastRedirect=null;this.lastData={};var n,o,i;this.routes=I(e),this.middleware=(n=t.middleware)!=null?n:[],this.notFoundBlock=(o=t.notFound)!=null?o:ee,this.errorBlock=(i=t.error)!=null?i:(s=>Q(s)),this.headers=t.headers,this.history=t.history!==void 0?t.history:typeof window!="undefined"?Z():null,this.state=new ye({pathname:"/",search:"",hash:"",params:{},status:"idle",error:null}),this.tree=we({div:""}),L=this}start(){return R(this,null,function*(){this.history&&!this.releaseHistory&&(this.releaseHistory=this.history.listen(t=>{this.transition(t,{fromHistory:!0})}));let e=this.history?this.history.url():new URL("/","http://localhost");yield this.transition(e,{initial:!0})})}destroy(){var e;(e=this.releaseHistory)==null||e.call(this),this.releaseHistory=null,L===this&&(L=null)}currentUrl(){if(this.history)return this.history.url();let e=this.state.get("search");return new URL(`${this.state.get("pathname")}${e}`,"http://localhost")}resolve(e){return new URL(e,this.currentUrl())}navigate(n){return R(this,arguments,function*(e,t={}){let o=this.resolve(e);if(typeof window!="undefined"&&o.origin!==this.currentUrl().origin){window.location.assign(o.href);return}yield this.transition(o,t)})}push(e,t={}){return this.navigate(e,t)}replace(e,t={}){return this.navigate(e,b(x({},t),{replace:!0}))}back(){var e;(e=this.history)==null||e.go(-1)}forward(){var e;(e=this.history)==null||e.go(1)}refresh(){return R(this,null,function*(){this.cache.invalidate(),yield this.transition(this.currentUrl(),{replace:!0,scroll:!1})})}prefetch(e){return R(this,null,function*(){try{let t=this.resolve(e),n=T(this.routes,t.pathname);if(!n)return;let o=this.loaderContext(t,n);yield Promise.all(n.route.chain.map((i,s)=>{if(!i.loader)return Promise.resolve();let a=this.cacheKey(n.route.chainIds[s],t);return this.cache.prefetch(a,i.loader,o,i.revalidate)}))}catch(t){}})}searchParams(e){return new URLSearchParams(this.state.get("search",e))}addEventListener(e,t){return this.events.addListener(e,t)}getMatch(){return this.currentMatch}cacheKey(e,t){return`${e}|${t.pathname}${t.search}`}loaderContext(e,t){return{pathname:t.pathname,url:e.pathname+e.search,params:t.params,searchParams:e.searchParams,headers:this.headers}}transition(n){return R(this,arguments,function*(e,t={}){var s,a;let o=++this.navigationToken,i=e.pathname+e.search+e.hash;t.fromHistory||(this.lastRedirect=null),this.events.notify("routeChangeStart",i),this.saveScroll();try{let l=e.pathname,p={url:e,pathname:e.pathname,searchParams:e.searchParams,headers:this.headers};for(let c of this.middleware){let h=yield c(p);N(h)&&(l=h.__domphyRewrite)}if(o!==this.navigationToken)return;let d=T(this.routes,l);if(d){let c=d.route.chain[d.route.chain.length-1];if(c.redirect)throw new E(c.redirect,(s=c.permanent)!=null?s:!1);for(let h of d.route.chain)for(let m of(a=h.middleware)!=null?a:[]){let f=yield m(p);if(N(f)){yield this.transition(new URL(f.__domphyRewrite,e),t);return}}if(o!==this.navigationToken)return;yield this.renderMatch(e,d,o,t)}else yield this.renderNotFound(e,o,t)}catch(l){if(o!==this.navigationToken)return;if(l instanceof E){yield this.transition(this.resolve(l.to),b(x({},t),{replace:!0})),this.lastRedirect={to:l.to,permanent:l.permanent};return}if(l instanceof S){yield this.renderNotFound(e,o,t);return}let p=l instanceof Error?l:new Error(String(l));this.tree.set(this.errorBlock(p,()=>{this.refresh()})),this.state.set("status","error"),this.state.set("error",p),this.events.notify("routeChangeError",p,i);return}o===this.navigationToken&&this.events.notify("routeChangeComplete",i)})}renderMatch(e,t,n,o){return R(this,null,function*(){let{chain:i,chainIds:s}=t.route,a=this.loaderContext(e,t),l=i.map(()=>({status:"pending"})),p=null,d=i.map((g,w)=>{if(!g.loader)return l[w]={status:"success",data:void 0},Promise.resolve();let k=this.cacheKey(s[w],e);return this.cache.load(k,g.loader,a,g.revalidate).then(v=>{l[w]={status:"success",data:v}},v=>{v instanceof E?p=p!=null?p:v:v instanceof S?l[w]={status:"notfound"}:l[w]={status:"error",error:v instanceof Error?v:new Error(String(v))}})}),c=!1,h=Promise.all(d).then(()=>{c=!0});if(yield new Promise(g=>setTimeout(g,0)),!c&&i.some(g=>g.loading)){let g=F({match:t,baseContext:this.baseContext(e,t),results:l.map(w=>x({},w)),retry:()=>{this.refresh()},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock});n===this.navigationToken&&g.status==="loading"&&(this.state.set("status","loading"),this.tree.set(g.element))}if(yield h,n!==this.navigationToken)return;if(p)throw p;let m=F({match:t,baseContext:this.baseContext(e,t),results:l,retry:()=>{this.refresh()},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock}),f={};i.forEach((g,w)=>{g.loader&&l[w].status==="success"&&(f[this.cacheKey(s[w],e)]=l[w].data)}),this.lastData=f,this.currentMatch=t,yield this.applyMetadata(t,a),n===this.navigationToken&&this.commit(e,t,m.element,m.status,o)})}renderNotFound(e,t,n){return R(this,null,function*(){let o=te(this.notFoundBlock);this.currentMatch=null,this.metadata={},B([]),t===this.navigationToken&&this.commit(e,null,o.element,"notfound",n)})}baseContext(e,t){return{pathname:t.pathname,url:e.pathname+e.search,params:t.params,searchParams:e.searchParams,hash:e.hash,headers:this.headers}}applyMetadata(e,t){return R(this,null,function*(){try{this.metadata=yield Y(e.route.chain.map(n=>n.metadata),t)}catch(n){this.metadata={}}B(A(this.metadata))})}commit(e,t,n,o,i){var s;if(this.history&&!i.fromHistory&&!i.initial){let a=e.pathname+e.search+e.hash;i.replace?this.history.replace(a):this.history.push(a)}this.state.set("pathname",e.pathname),this.state.set("search",e.search),this.state.set("hash",e.hash),this.state.set("params",(s=t==null?void 0:t.params)!=null?s:{}),this.state.set("error",null),this.state.set("status",o),this.tree.set(n),this.restoreScroll(e,i)}saveScroll(){var e,t;typeof window!="undefined"&&((t=(e=this.history)==null?void 0:e.saveScroll)==null||t.call(e,{x:window.scrollX,y:window.scrollY}))}restoreScroll(e,t){var n,o,i,s;if(!(typeof window=="undefined"||t.scroll===!1||t.initial)){if(t.fromHistory){let a=(o=(n=this.history)==null?void 0:n.readScroll)==null?void 0:o.call(n);window.scrollTo((i=a==null?void 0:a.x)!=null?i:0,(s=a==null?void 0:a.y)!=null?s:0);return}if(e.hash){let a=document.getElementById(e.hash.slice(1));if(a){a.scrollIntoView();return}}window.scrollTo(0,0)}}};var ne="__DOMPHY_APP_DATA__",$=class{constructor(e,t={}){this.node=null;this.routes=e,this.options=t,this.router=new H(e,t)}element(){let e=this.router;return{div:t=>[e.tree.get(t)],style:{display:"contents"}}}render(e){return R(this,null,function*(){return yield this.router.start(),this.node=new j(this.element()),this.node.render(e),this.node})}hydrate(e,t){return R(this,null,function*(){let n=globalThis[ne];return n&&typeof n=="object"&&this.router.cache.seed(n),yield this.router.start(),this.node=new j(this.element()),this.node.mount(e,t),this.node})}destroy(){var e;(e=this.node)==null||e.remove(),this.node=null,this.router.destroy()}renderToString(n){return R(this,arguments,function*(e,t={}){let o=typeof e=="string"?new URL(e,"http://localhost"):e,i=new H(this.routes,b(x({},this.options),{history:null,headers:t.headers}));yield i.transition(o,{initial:!0});let s=i.state.get("status"),a=i.lastRedirect,l=new j({div:[i.tree.get()],style:{display:"contents"}}),p=i.lastData,d={html:l.generateHTML(),css:l.generateCSS(),head:J(A(i.metadata)),status:a?a.permanent?308:307:s==="notfound"?404:200,redirect:a==null?void 0:a.to,data:p,bootstrapScript:`<script>window.${ne} = ${Re(p)};</script>`};return i.destroy(),d})}};function Re(r){return JSON.stringify(r).replace(/</g,"\\u003c")}function rt(r,e={}){return new $(r,e)}var ve=[640,750,828,1080,1200,1920,2048,3840];function it(r){let{src:e,alt:t="",width:n,height:o,fill:i=!1,sizes:s,quality:a=75,priority:l=!1,placeholder:p="empty",blurDataURL:d,loader:c,deviceSizes:h=ve}=r,m={src:c?c({src:e,width:n!=null?n:h[h.length-1],quality:a}):e,alt:t,loading:l?"eager":"lazy",decoding:"async",fetchPriority:l?"high":"auto",style:{}};return c&&(m.srcSet=h.map(f=>`${c({src:e,width:f,quality:a})} ${f}w`).join(", "),s&&(m.sizes=s)),n!==void 0&&(m.width=n),o!==void 0&&(m.height=o),i&&(m.style=b(x({},m.style),{position:"absolute",inset:"0",width:"100%",height:"100%",objectFit:"cover"})),p==="blur"&&d&&(m.style=b(x({},m.style),{backgroundImage:`url("${d}")`,backgroundSize:"cover",backgroundPosition:"center"}),m.onLoad=f=>{let g=f.target;g.style.backgroundImage=""}),m}function xe(r){return r.defaultPrevented||r.button!==0||r.metaKey||r.ctrlKey||r.shiftKey||r.altKey}function ct(r){let{href:e,replace:t=!1,scroll:n=!0,prefetch:o="hover",exact:i=!1}=r,s=()=>{var d;return(d=r.router)!=null?d:re()},a=d=>{let c=new URL(e,"http://localhost").pathname;return i||c==="/"?d===c:d===c||d.startsWith(`${c}/`)},l=!1,p=()=>{l||(l=!0,s().prefetch(e))};return{href:e,ariaCurrent:d=>a(s().state.get("pathname",d))?"page":null,dataActive:d=>a(s().state.get("pathname",d))?"":null,onClick:d=>{let c=d,h=c.currentTarget;xe(c)||h.target&&h.target!=="_self"||h.hasAttribute("download")||new URL(h.href,window.location.href).origin===window.location.origin&&(c.preventDefault(),s().navigate(e,{replace:t,scroll:n}))},onMouseEnter:()=>{o==="hover"&&p()},onFocus:()=>{o==="hover"&&p()},_onMount:d=>{if(o!=="visible")return;if(typeof IntersectionObserver=="undefined"){p();return}let c=new IntersectionObserver(h=>{h.some(m=>m.isIntersecting)&&(p(),c.disconnect())});c.observe(d.domElement),d.setMetadata("navLinkObserver",c)},_onRemove:d=>{let c=d.getMetadata("navLinkObserver");c==null||c.disconnect()}}}var G=new Set;function dt(){G.clear()}function oe(r){let e=globalThis.requestIdleCallback;e?e(r):setTimeout(r,0)}function pt(r){let{src:e,strategy:t="afterInteractive",id:n,async:o=!0,onLoad:i,onError:s}=r,a=n!=null?n:e,l=d=>{G.has(a)||(G.add(a),d.src=e)},p={script:"",async:o,onLoad:()=>i==null?void 0:i(),onError:()=>s==null?void 0:s(),_onMount:d=>{let c=d.domElement;if(t==="afterInteractive"){l(c);return}document.readyState==="complete"?oe(()=>l(c)):window.addEventListener("load",()=>oe(()=>l(c)),{once:!0})}};return n!==void 0&&(p.id=n),p}function mt(r){return r}export{H as AppRouter,O as DataCache,$ as DomphyApp,S as NotFoundSignal,Be as PREFETCH_LIFETIME,E as RedirectSignal,B as applyHeadTags,ke as buildHref,te as buildNotFoundTree,F as buildTree,ue as compareSpecificity,I as compileRoutes,Ce as createApiHandler,rt as createApp,Z as createBrowserHistory,Fe as createMemoryHistory,Q as defaultErrorBlock,ee as defaultNotFoundBlock,mt as defineRoutes,re as getRouter,N as isRewrite,C as json,de as matchPath,T as matchRoute,A as metadataToHeadTags,ct as navLink,Te as notFound,it as optimizedImage,W as parseSegment,Me as permanentRedirect,Se as redirect,J as renderHeadTags,dt as resetScripts,Y as resolveMetadata,Pe as rewrite,pt as script,D as splitPath};
1
+ var ut=Object.defineProperty,ht=Object.defineProperties;var pt=Object.getOwnPropertyDescriptors;var X=Object.getOwnPropertySymbols;var mt=Object.prototype.hasOwnProperty,ft=Object.prototype.propertyIsEnumerable;var Z=(r,t,e)=>t in r?ut(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e,S=(r,t)=>{for(var e in t||(t={}))mt.call(t,e)&&Z(r,e,t[e]);if(X)for(var e of X(t))ft.call(t,e)&&Z(r,e,t[e]);return r},k=(r,t)=>ht(r,pt(t));var y=(r,t,e)=>new Promise((o,n)=>{var i=l=>{try{a(e.next(l))}catch(u){n(u)}},s=l=>{try{a(e.throw(l))}catch(u){n(u)}},a=l=>l.done?o(l.value):Promise.resolve(l.value).then(i,s);a((e=e.apply(r,t)).next())});function j(r){return r.startsWith("(")&&r.endsWith(")")?{kind:"group",value:r.slice(1,-1)}:r.startsWith("[[...")&&r.endsWith("]]")?{kind:"optional-catchall",value:r.slice(5,-2)}:r.startsWith("[...")&&r.endsWith("]")?{kind:"catchall",value:r.slice(4,-1)}:r.startsWith("[")&&r.endsWith("]")?{kind:"dynamic",value:r.slice(1,-1)}:{kind:"static",value:r}}function D(r){return r.split("/").filter(t=>t.length>0)}function tt(r){return D(r).map(j).filter(t=>t.kind!=="group").length}function et(r,t,e){let o=`/${D(t).slice(e).join("/")}`;return L(r,o)}function C(r){let t=[];function e(o,n,i,s,a){for(let l of o){let u=D(l.path),c=u.map(j),d=[...n,...c.filter(w=>w.kind!=="group")],h=`${a}/${u.join("/")}`.replace(/\/+/g,"/"),m=[...i,l],f=[...s,h===""?"/":h];(l.page||l.redirect)&&t.push({id:h===""?"/":h,segments:d,chain:m,chainIds:f}),l.children&&e(l.children,d,m,f,h)}}return e(r,[],[],[],""),t.sort(gt),t}var Q={static:0,dynamic:1,catchall:2,"optional-catchall":3,group:0};function gt(r,t){let e=Math.max(r.segments.length,t.segments.length);for(let o=0;o<e;o++){let n=r.segments[o],i=t.segments[o];if(!n)return-1;if(!i)return 1;let s=Q[n.kind]-Q[i.kind];if(s!==0)return s}return 0}function yt(r,t){let e=D(t).map(i=>decodeURIComponent(i)),o={},n=0;for(let i=0;i<r.length;i++){let s=r[i],a=i===r.length-1;if(s.kind==="static"){if(e[n]!==s.value)return null;n++;continue}if(s.kind==="dynamic"){if(n>=e.length)return null;o[s.value]=e[n],n++;continue}if(s.kind==="catchall")return!a||n>=e.length?null:(o[s.value]=e.slice(n),o);if(s.kind==="optional-catchall")return a?(o[s.value]=e.slice(n),o):null}return n!==e.length?null:o}function L(r,t){for(let e of r){let o=yt(e.segments,t);if(o)return{route:e,params:o,pathname:t}}return null}function Ct(r,t={}){return`/${D(r).map(j).filter(o=>o.kind!=="group").flatMap(o=>{if(o.kind==="static")return[o.value];let n=t[o.value];if(n===void 0){if(o.kind==="optional-catchall")return[];throw new Error(`Missing param "${o.value}" for pattern "${r}".`)}return(Array.isArray(n)?n:[n]).map(s=>encodeURIComponent(s))}).join("/")}`}var M=class extends Error{constructor(t,e){super(`Redirect to ${t}`),this.name="RedirectSignal",this.to=t,this.permanent=e}},P=class extends Error{constructor(){super("Not found"),this.name="NotFoundSignal"}};function It(r){throw new M(r,!1)}function Dt(r){throw new M(r,!0)}function At(){throw new P}function Ot(r){return{__domphyRewrite:r}}function U(r){return typeof r=="object"&&r!==null&&typeof r.__domphyRewrite=="string"}var Rt=["GET","POST","PUT","PATCH","DELETE","HEAD","OPTIONS"];function _(r,t={}){let e=new Headers(t.headers);return e.has("content-type")||e.set("content-type","application/json; charset=utf-8"),new Response(JSON.stringify(r),k(S({},t),{headers:e}))}function _t(r){let t=r.map(n=>({apiRoute:n,routeNode:{path:n.path,page:()=>({div:""})}})),e=C(t.map(n=>n.routeNode)),o=new Map(t.map(n=>[n.routeNode,n.apiRoute]));return n=>y(null,null,function*(){let i=new URL(n.url),s=L(e,i.pathname);if(!s)return _({error:"Not Found"},{status:404});let a=o.get(s.route.chain[s.route.chain.length-1]),l=Rt.filter(d=>a[d]),u=n.method.toUpperCase(),c=a[u];if(!c&&u==="HEAD"&&a.GET&&(c=a.GET),!c&&u==="OPTIONS")return new Response(null,{status:204,headers:{allow:l.join(", ")}});if(!c)return _({error:"Method Not Allowed"},{status:405,headers:{allow:l.join(", ")}});try{let d=yield c(n,{params:s.params});return u==="HEAD"?new Response(null,{status:d.status,headers:d.headers}):d}catch(d){return d instanceof M?new Response(null,{status:d.permanent?308:307,headers:{location:d.to}}):d instanceof P?_({error:"Not Found"},{status:404}):_({error:"Internal Server Error"},{status:500})}})}import{ElementNode as N}from"@domphy/core";function K(r,t){return y(this,null,function*(){let e={},o=null;for(let n of r){if(!n)continue;let i=typeof n=="function"?yield n(t):n;for(let a of Object.keys(i)){if(a==="title")continue;let l=i[a];l!==void 0&&(e[a]=l)}let s=i.title;if(s!==void 0){if(typeof s=="string"){e.title=o?o.replace("%s",s):s;continue}s.absolute!==void 0?e.title=s.absolute:s.default!==void 0&&(e.title=o?o.replace("%s",s.default):s.default),s.template!==void 0&&(o=s.template)}}return e})}function A(r,t){return!t||/^[a-z][a-z0-9+.-]*:/i.test(r)?r:new URL(r,t).toString()}function wt(r){if(typeof r=="string")return r;let t=[];return t.push(r.index===!1?"noindex":"index"),t.push(r.follow===!1?"nofollow":"follow"),r.noarchive&&t.push("noarchive"),r.nosnippet&&t.push("nosnippet"),r.noimageindex&&t.push("noimageindex"),t.join(", ")}function O(r){var l,u,c,d,h,m,f,w,v,b,x;let t=[],e=r.metadataBase,o=(p,R)=>{R!==void 0&&t.push({tag:"meta",attributes:{name:p,content:R}})},n=(p,R)=>{R!==void 0&&t.push({tag:"meta",attributes:{property:p,content:R}})};r.title!==void 0&&t.push({tag:"title",attributes:{},content:r.title}),o("description",r.description),o("application-name",r.applicationName),o("generator",r.generator),o("keywords",(l=r.keywords)==null?void 0:l.join(", ")),o("referrer",r.referrer),o("theme-color",r.themeColor),o("color-scheme",r.colorScheme),o("viewport",r.viewport),r.robots!==void 0&&o("robots",wt(r.robots));for(let p of(u=r.authors)!=null?u:[])o("author",p.name),p.url&&t.push({tag:"link",attributes:{rel:"author",href:p.url}});if(r.icons!==void 0){let p=typeof r.icons=="string"?{icon:r.icons}:r.icons;p.icon&&t.push({tag:"link",attributes:{rel:"icon",href:p.icon}}),p.shortcut&&t.push({tag:"link",attributes:{rel:"shortcut icon",href:p.shortcut}}),p.apple&&t.push({tag:"link",attributes:{rel:"apple-touch-icon",href:p.apple}})}let i=r.openGraph;if(i){n("og:title",(c=i.title)!=null?c:r.title),n("og:description",(d=i.description)!=null?d:r.description),n("og:url",i.url?A(i.url,e):void 0),n("og:site_name",i.siteName),n("og:type",i.type),n("og:locale",i.locale);for(let p of(h=i.images)!=null?h:[]){let R=typeof p=="string"?{url:p}:p;n("og:image",A(R.url,e)),R.width!==void 0&&n("og:image:width",String(R.width)),R.height!==void 0&&n("og:image:height",String(R.height)),R.alt!==void 0&&n("og:image:alt",R.alt)}}let s=r.twitter;if(s){o("twitter:card",(m=s.card)!=null?m:"summary"),o("twitter:title",(f=s.title)!=null?f:r.title),o("twitter:description",(w=s.description)!=null?w:r.description),o("twitter:site",s.site),o("twitter:creator",s.creator);for(let p of(v=s.images)!=null?v:[])o("twitter:image",A(p,e))}let a=r.alternates;if(a){a.canonical&&t.push({tag:"link",attributes:{rel:"canonical",href:A(a.canonical,e)}});for(let p of Object.keys((b=a.languages)!=null?b:{}))t.push({tag:"link",attributes:{rel:"alternate",hreflang:p,href:A(a.languages[p],e)}})}for(let p of Object.keys((x=r.other)!=null?x:{}))o(p,r.other[p]);return t}function vt(r){return r.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;")}function xt(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;")}function F(r){return r.map(t=>{var o;let e=Object.keys(t.attributes).map(n=>` ${n}="${vt(t.attributes[n])}"`).join("");return t.tag==="title"?`<title>${xt((o=t.content)!=null?o:"")}</title>`:`<${t.tag}${e}>`}).join(`
2
+ `)}var rt="data-domphy-head";function G(r){var t;if(typeof document!="undefined"){for(let e of Array.from(document.head.querySelectorAll(`[${rt}]`)))e.remove();for(let e of r){if(e.tag==="title"){document.title=(t=e.content)!=null?t:"";continue}let o=document.createElement(e.tag);for(let n of Object.keys(e.attributes))o.setAttribute(n,e.attributes[n]);o.setAttribute(rt,""),document.head.appendChild(o)}}}import{Notifier as St,RecordState as kt,toState as Et}from"@domphy/core";import{Notifier as bt}from"@domphy/core";var nt=3e4,$=class{constructor(){this.entries=new Map;this.inflight=new Map;this.notifier=new bt;this.pending=new Map}onRevalidated(t){return this.notifier.addListener("revalidated",t)}seed(t){for(let e of Object.keys(t))this.entries.set(e,{data:t[e],timestamp:Date.now(),consumable:!0})}snapshot(t){let e={};for(let o of t){let n=this.entries.get(o);n&&(e[o]=n.data)}return e}invalidate(t){if(t===void 0){this.entries.clear();return}for(let e of this.entries.keys())e.startsWith(t)&&this.entries.delete(e)}load(t,e,o,n){return y(this,null,function*(){let i=this.entries.get(t);if(i){let l=n!==void 0?n*1e3:0,u=Date.now()-i.timestamp<=l,c=i.consumable&&Date.now()-i.timestamp<=nt;if(u||c)return i.consumable&&!u&&this.entries.delete(t),i.data;if(n!==void 0&&n>0)return this.pending.set(t,()=>this.revalidate(t,e,o)),i.data;this.entries.delete(t)}let s=this.inflight.get(t);if(s)return s;let a=Promise.resolve(e(o)).then(l=>(this.inflight.delete(t),n!==void 0&&n>0&&this.entries.set(t,{data:l,timestamp:Date.now(),consumable:!1}),l),l=>{throw this.inflight.delete(t),l});return this.inflight.set(t,a),a})}flushRevalidations(){if(this.pending.size===0)return;let t=[...this.pending.values()];this.pending.clear();for(let e of t)e()}revalidate(t,e,o){if(this.inflight.has(t))return;let n=Promise.resolve(e(o)).then(i=>(this.inflight.delete(t),this.entries.set(t,{data:i,timestamp:Date.now(),consumable:!1}),this.notifier.notify("revalidated",t),i),i=>{throw this.inflight.delete(t),i});n.catch(()=>{}),this.inflight.set(t,n)}prefetch(t,e,o,n){return y(this,null,function*(){if(n!==void 0){yield this.load(t,e,o,n);return}let i=this.entries.get(t);if(i&&Date.now()-i.timestamp<=nt||this.inflight.has(t))return;let s=yield e(o);this.entries.set(t,{data:s,timestamp:Date.now(),consumable:!0})})}};function it(){var e,o,n;let r=new Map,t=(o=(e=window.history.state)==null?void 0:e.__domphyIndex)!=null?o:0;return((n=window.history.state)==null?void 0:n.__domphyIndex)===void 0&&window.history.replaceState({__domphyIndex:t},""),"scrollRestoration"in window.history&&(window.history.scrollRestoration="manual"),{url:()=>new URL(window.location.href),push:i=>{t++,window.history.pushState({__domphyIndex:t},"",i)},replace:i=>{window.history.replaceState({__domphyIndex:t},"",i)},go:i=>window.history.go(i),listen:i=>{let s=()=>{var a,l;t=(l=(a=window.history.state)==null?void 0:a.__domphyIndex)!=null?l:0,i(new URL(window.location.href))};return window.addEventListener("popstate",s),()=>window.removeEventListener("popstate",s)},saveScroll:i=>r.set(t,i),readScroll:()=>{var i;return(i=r.get(t))!=null?i:null}}}var ot="http://localhost";function Wt(r="/"){let t=[r],e=0,o=new Set;return{url:()=>new URL(t[e],ot),push:n=>{t.splice(e+1),t.push(n),e++},replace:n=>{t[e]=n},go:n=>{let i=Math.min(Math.max(e+n,0),t.length-1);if(i===e)return;e=i;let s=new URL(t[e],ot);for(let a of o)a(s)},listen:n=>(o.add(n),()=>o.delete(n))}}function st(r){return{div:[{h2:"Application error"},{p:r.message}]}}function at(){return{div:[{h2:"404"},{p:"This page could not be found."}]}}function q(r,t){return r.findIndex(e=>e.status===t)}function H(r){var x,p,R;let{match:t,baseContext:e,results:o,retry:n,defaultError:i,defaultNotFound:s}=r,{chain:a,chainIds:l}=t.route,u={};for(let g=0;g<a.length;g++)u[l[g]]=(x=o[g])==null?void 0:x.data;let c=a.map((g,E)=>{var T;return k(S({},e),{data:(T=o[E])==null?void 0:T.data,segmentData:u})}),d=q(o,"error"),h=q(o,"notfound"),m=q(o,"pending"),f,w,v;if(d!==-1){let g=z(a,d,T=>!!T.error);f=(g===-1?i:a[g].error)(o[d].error,n),f._key=`${l[Math.max(g,0)]}:error`,w=Math.min(g,d-1),v="error"}else if(h!==-1){let g=z(a,h,T=>!!T.notFound);f=(g===-1?s:a[g].notFound)(),f._key=`${l[Math.max(g,0)]}:notfound`,w=Math.min(g,h-1),v="notfound"}else if(m!==-1){let g=z(a,m,E=>!!E.loading);if(g===-1)return{element:{div:""},status:"loading"};f=a[g].loading(c[g]),f._key=`${l[g]}:loading`,w=Math.min(g,m-1),v="loading"}else f=a[a.length-1].page(c[a.length-1]),f._key=`${t.route.id}:page`,w=a.length-1,v="idle";let b=f;for(let g=w;g>=0;g--){let E=a[g].layout;E&&(b=E(b,c[g],(R=(p=r.slots)==null?void 0:p[g])!=null?R:{}),b._key===void 0&&(b._key=`${l[g]}:layout`))}return{element:b,status:v}}function z(r,t,e){for(let o=t;o>=0;o--)if(e(r[o]))return o;return-1}function W(r){let t=r();return t._key===void 0&&(t._key="app:notfound"),{element:t,status:"notfound"}}var B=null;function lt(){if(!B)throw new Error("No router created yet. Call createApp() or new AppRouter() first.");return B}var I=class{constructor(t,e={}){this.events=new St;this.cache=new $;this.navigationToken=0;this.releaseHistory=null;this.currentMatch=null;this.currentRenderKeys=new Set;this.slotCompiled=new Map;this.metadata={};this.lastRedirect=null;this.lastData={};var o,n,i;this.routes=C(t),this.compileSlots(t),this.middleware=(o=e.middleware)!=null?o:[],this.notFoundBlock=(n=e.notFound)!=null?n:at,this.errorBlock=(i=e.error)!=null?i:(s=>st(s)),this.headers=e.headers,this.history=e.history!==void 0?e.history:typeof window!="undefined"?it():null,this.state=new kt({pathname:"/",search:"",hash:"",params:{},status:"idle",error:null}),this.tree=Et({div:""}),this.cache.onRevalidated(s=>this.onRevalidated(s)),B=this}compileSlots(t){for(let e of t){if(e.slots){let o={};for(let n of Object.keys(e.slots)){let i=e.slots[n];o[n]={soft:C(i),hard:C(i.filter(s=>!s.intercept))},this.compileSlots(i)}this.slotCompiled.set(e,o)}e.children&&this.compileSlots(e.children)}}loadMatch(t,e){return y(this,null,function*(){let{chain:o,chainIds:n}=t.route,i=this.loaderContext(e,t),s=o.map(()=>({status:"pending"}));return yield Promise.all(o.map((a,l)=>{if(!a.loader)return s[l]={status:"success",data:void 0},Promise.resolve();let u=this.cacheKey(n[l],e);return this.cache.load(u,a.loader,i,a.revalidate).then(c=>{s[l]={status:"success",data:c}},c=>{c instanceof P?s[l]={status:"notfound"}:s[l]={status:"error",error:c instanceof Error?c:new Error(String(c))}})})),s})}renderSlots(t,e,o,n){return y(this,null,function*(){let i=e.route.chain[t],s=this.slotCompiled.get(i);if(!s)return{};let a=0;for(let u=0;u<=t;u++)a+=tt(e.route.chain[u].path);let l={};for(let u of Object.keys(s)){let c=n?s[u].soft:s[u].hard,d=et(c,o.pathname,a);if(!d)continue;d.pathname=o.pathname,d.params=S(S({},e.params),d.params);let h=yield this.loadMatch(d,o);l[u]=H({match:d,baseContext:this.baseContext(o,d),results:h,retry:()=>{this.refresh()},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock}).element}return l})}onRevalidated(t){!this.history||!this.currentRenderKeys.has(t)||this.transition(this.currentUrl(),{replace:!0,scroll:!1,fromHistory:!0})}start(){return y(this,null,function*(){this.history&&!this.releaseHistory&&(this.releaseHistory=this.history.listen(e=>{this.transition(e,{fromHistory:!0})}));let t=this.history?this.history.url():new URL("/","http://localhost");yield this.transition(t,{initial:!0})})}destroy(){var t;(t=this.releaseHistory)==null||t.call(this),this.releaseHistory=null,B===this&&(B=null)}currentUrl(){if(this.history)return this.history.url();let t=this.state.get("search");return new URL(`${this.state.get("pathname")}${t}`,"http://localhost")}resolve(t){return new URL(t,this.currentUrl())}navigate(o){return y(this,arguments,function*(t,e={}){let n=this.resolve(t);if(typeof window!="undefined"&&n.origin!==this.currentUrl().origin){window.location.assign(n.href);return}yield this.transition(n,e)})}push(t,e={}){return this.navigate(t,e)}replace(t,e={}){return this.navigate(t,k(S({},e),{replace:!0}))}back(){var t;(t=this.history)==null||t.go(-1)}forward(){var t;(t=this.history)==null||t.go(1)}refresh(){return y(this,null,function*(){this.cache.invalidate(),yield this.transition(this.currentUrl(),{replace:!0,scroll:!1})})}prefetch(t){return y(this,null,function*(){try{let e=this.resolve(t),o=L(this.routes,e.pathname);if(!o)return;let n=this.loaderContext(e,o);yield Promise.all(o.route.chain.map((i,s)=>{if(!i.loader)return Promise.resolve();let a=this.cacheKey(o.route.chainIds[s],e);return this.cache.prefetch(a,i.loader,n,i.revalidate)}))}catch(e){}})}searchParams(t){return new URLSearchParams(this.state.get("search",t))}addEventListener(t,e){return this.events.addListener(t,e)}getMatch(){return this.currentMatch}renderStream(t){return y(this,null,function*(){let e=t.pathname,o={url:t,pathname:t.pathname,searchParams:t.searchParams,headers:this.headers};for(let c of this.middleware){let d=yield c(o);U(d)&&(e=d.__domphyRewrite)}let n=L(this.routes,e);if(!n){let c=W(this.notFoundBlock);return{shell:c.element,status:404,redirect:null,rest:Promise.resolve({content:c.element,data:{},head:""})}}let i=n.route.chain[n.route.chain.length-1];if(i.redirect)return{shell:{div:""},status:i.permanent?308:307,redirect:i.redirect,rest:Promise.resolve({content:{div:""},data:{},head:""})};let s=this.baseContext(t,n),a=n.route.chain.map(c=>c.loader?{status:"pending"}:{status:"success",data:void 0}),l=H({match:n,baseContext:s,results:a,retry:()=>{},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock}).element,u=y(this,null,function*(){let c=yield this.loadMatch(n,t),d={};yield Promise.all(n.route.chain.map((w,v)=>y(this,null,function*(){this.slotCompiled.has(w)&&(d[v]=yield this.renderSlots(v,n,t,!1))})));let h=H({match:n,baseContext:s,results:c,retry:()=>{},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock,slots:d}).element,m={};n.route.chain.forEach((w,v)=>{w.loader&&c[v].status==="success"&&(m[this.cacheKey(n.route.chainIds[v],t)]=c[v].data)});let f="";try{let w=yield K(n.route.chain.map(v=>v.metadata),this.loaderContext(t,n));f=F(O(w))}catch(w){f=""}return{content:h,data:m,head:f}});return{shell:l,status:200,redirect:null,rest:u}})}cacheKey(t,e){return`${t}|${e.pathname}${e.search}`}loaderContext(t,e){return{pathname:e.pathname,url:t.pathname+t.search,params:e.params,searchParams:t.searchParams,headers:this.headers}}transition(o){return y(this,arguments,function*(t,e={}){var s,a;let n=++this.navigationToken,i=t.pathname+t.search+t.hash;e.fromHistory||(this.lastRedirect=null),this.events.notify("routeChangeStart",i),this.saveScroll();try{let l=t.pathname,u={url:t,pathname:t.pathname,searchParams:t.searchParams,headers:this.headers};for(let d of this.middleware){let h=yield d(u);U(h)&&(l=h.__domphyRewrite)}if(n!==this.navigationToken)return;let c=L(this.routes,l);if(c){let d=c.route.chain[c.route.chain.length-1];if(d.redirect)throw new M(d.redirect,(s=d.permanent)!=null?s:!1);for(let h of c.route.chain)for(let m of(a=h.middleware)!=null?a:[]){let f=yield m(u);if(U(f)){yield this.transition(new URL(f.__domphyRewrite,t),e);return}}if(n!==this.navigationToken)return;yield this.renderMatch(t,c,n,e)}else yield this.renderNotFound(t,n,e)}catch(l){if(n!==this.navigationToken)return;if(l instanceof M){yield this.transition(this.resolve(l.to),k(S({},e),{replace:!0})),this.lastRedirect={to:l.to,permanent:l.permanent};return}if(l instanceof P){yield this.renderNotFound(t,n,e);return}let u=l instanceof Error?l:new Error(String(l));this.tree.set(this.errorBlock(u,()=>{this.refresh()})),this.state.set("status","error"),this.state.set("error",u),this.events.notify("routeChangeError",u,i);return}n===this.navigationToken&&this.events.notify("routeChangeComplete",i)})}renderMatch(t,e,o,n){return y(this,null,function*(){let{chain:i,chainIds:s}=e.route,a=this.loaderContext(t,e),l=i.map(()=>({status:"pending"})),u=null,c=i.map((b,x)=>{if(!b.loader)return l[x]={status:"success",data:void 0},Promise.resolve();let p=this.cacheKey(s[x],t);return this.cache.load(p,b.loader,a,b.revalidate).then(R=>{l[x]={status:"success",data:R}},R=>{R instanceof M?u=u!=null?u:R:R instanceof P?l[x]={status:"notfound"}:l[x]={status:"error",error:R instanceof Error?R:new Error(String(R))}})}),d=!1,h=Promise.all(c).then(()=>{d=!0});if(yield new Promise(b=>setTimeout(b,0)),!d&&i.some(b=>b.loading)){let b=H({match:e,baseContext:this.baseContext(t,e),results:l.map(x=>S({},x)),retry:()=>{this.refresh()},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock});o===this.navigationToken&&b.status==="loading"&&(this.state.set("status","loading"),this.tree.set(b.element))}if(yield h,o!==this.navigationToken)return;if(u)throw u;let m=!n.initial,f={};if(yield Promise.all(i.map((b,x)=>y(this,null,function*(){this.slotCompiled.has(b)&&(f[x]=yield this.renderSlots(x,e,t,m))}))),o!==this.navigationToken)return;let w=H({match:e,baseContext:this.baseContext(t,e),results:l,retry:()=>{this.refresh()},defaultError:this.errorBlock,defaultNotFound:this.notFoundBlock,slots:f}),v={};i.forEach((b,x)=>{b.loader&&l[x].status==="success"&&(v[this.cacheKey(s[x],t)]=l[x].data)}),this.lastData=v,this.currentRenderKeys=new Set(Object.keys(v)),this.currentMatch=e,yield this.applyMetadata(e,a),o===this.navigationToken&&(this.commit(t,e,w.element,w.status,n),this.cache.flushRevalidations())})}renderNotFound(t,e,o){return y(this,null,function*(){let n=W(this.notFoundBlock);this.currentMatch=null,this.metadata={},G([]),e===this.navigationToken&&this.commit(t,null,n.element,"notfound",o)})}baseContext(t,e){return{pathname:e.pathname,url:t.pathname+t.search,params:e.params,searchParams:t.searchParams,hash:t.hash,headers:this.headers}}applyMetadata(t,e){return y(this,null,function*(){try{this.metadata=yield K(t.route.chain.map(o=>o.metadata),e)}catch(o){this.metadata={}}G(O(this.metadata))})}commit(t,e,o,n,i){var s;if(this.history&&!i.fromHistory&&!i.initial){let a=t.pathname+t.search+t.hash;i.replace?this.history.replace(a):this.history.push(a)}this.state.set("pathname",t.pathname),this.state.set("search",t.search),this.state.set("hash",t.hash),this.state.set("params",(s=e==null?void 0:e.params)!=null?s:{}),this.state.set("error",null),this.state.set("status",n),this.tree.set(o),this.restoreScroll(t,i)}saveScroll(){var t,e;typeof window!="undefined"&&((e=(t=this.history)==null?void 0:t.saveScroll)==null||e.call(t,{x:window.scrollX,y:window.scrollY}))}restoreScroll(t,e){var o,n,i,s;if(!(typeof window=="undefined"||e.scroll===!1||e.initial)){if(e.fromHistory){let a=(n=(o=this.history)==null?void 0:o.readScroll)==null?void 0:n.call(o);window.scrollTo((i=a==null?void 0:a.x)!=null?i:0,(s=a==null?void 0:a.y)!=null?s:0);return}if(t.hash){let a=document.getElementById(t.hash.slice(1));if(a){a.scrollIntoView();return}}window.scrollTo(0,0)}}};var Mt="(function(){var h=document.getElementById('domphy-head');if(h){document.head.appendChild(h.content.cloneNode(true));h.remove();}var c=document.getElementById('domphy-content'),a=document.getElementById('domphy-app');if(c&&a){a.replaceChildren(c.content.cloneNode(true));c.remove();}})();",V="__DOMPHY_APP_DATA__",Y=class{constructor(t,e={}){this.node=null;this.routes=t,this.options=e,this.router=new I(t,e)}element(){let t=this.router;return{div:e=>[t.tree.get(e)],style:{display:"contents"}}}render(t){return y(this,null,function*(){return yield this.router.start(),this.node=new N(this.element()),this.node.render(t),this.node})}hydrate(t,e){return y(this,null,function*(){let o=globalThis[V];return o&&typeof o=="object"&&this.router.cache.seed(o),yield this.router.start(),this.node=new N(this.element()),this.node.mount(t,e),this.node})}destroy(){var t;(t=this.node)==null||t.remove(),this.node=null,this.router.destroy()}renderToString(o){return y(this,arguments,function*(t,e={}){let n=typeof t=="string"?new URL(t,"http://localhost"):t,i=new I(this.routes,k(S({},this.options),{history:null,headers:e.headers}));yield i.transition(n,{initial:!0});let s=i.state.get("status"),a=i.lastRedirect,l=new N({div:[i.tree.get()],style:{display:"contents"}}),u=i.lastData,c={html:l.generateHTML(),css:l.generateCSS(),head:F(O(i.metadata)),status:a?a.permanent?308:307:s==="notfound"?404:200,redirect:a==null?void 0:a.to,data:u,bootstrapScript:`<script>window.${V} = ${ct(u)};</script>`};return i.destroy(),c})}renderToStream(o){return y(this,arguments,function*(t,e={}){var w,v;let n=typeof t=="string"?new URL(t,"http://localhost"):t,i=new I(this.routes,k(S({},this.options),{history:null,headers:e.headers})),{shell:s,status:a,redirect:l,rest:u}=yield i.renderStream(n),c=new TextEncoder,d=new N({div:[s],style:{display:"contents"}}),h=`<!DOCTYPE html><html><head>${(w=e.head)!=null?w:""}<style id="domphy-style">${d.generateCSS()}</style></head><body><div id="domphy-app">${d.generateHTML()}</div>`,m=(v=e.bootstrap)!=null?v:"";return{stream:new ReadableStream({start(x){return y(this,null,function*(){x.enqueue(c.encode(h));let{content:p,data:R,head:g}=yield u,E=new N({div:[p],style:{display:"contents"}}),T=`<style>${E.generateCSS()}</style><template id="domphy-head">${g}</template><template id="domphy-content">${E.generateHTML()}</template><script>${Mt}</script><script>window.${V} = ${ct(R)};</script>${m}</body></html>`;x.enqueue(c.encode(T)),x.close(),i.destroy()})}}),status:a,redirect:l!=null?l:void 0}})}};function ct(r){return JSON.stringify(r).replace(/</g,"\\u003c")}function ce(r,t={}){return new Y(r,t)}var Pt=[640,750,828,1080,1200,1920,2048,3840];function he(r){let{src:t,alt:e="",width:o,height:n,fill:i=!1,sizes:s,quality:a=75,priority:l=!1,placeholder:u="empty",blurDataURL:c,loader:d,deviceSizes:h=Pt}=r,m={src:d?d({src:t,width:o!=null?o:h[h.length-1],quality:a}):t,alt:e,loading:l?"eager":"lazy",decoding:"async",fetchPriority:l?"high":"auto",style:{}};return d&&(m.srcSet=h.map(f=>`${d({src:t,width:f,quality:a})} ${f}w`).join(", "),s&&(m.sizes=s)),o!==void 0&&(m.width=o),n!==void 0&&(m.height=n),i&&(m.style=k(S({},m.style),{position:"absolute",inset:"0",width:"100%",height:"100%",objectFit:"cover"})),u==="blur"&&c&&(m.style=k(S({},m.style),{backgroundImage:`url("${c}")`,backgroundSize:"cover",backgroundPosition:"center"}),m.onLoad=f=>{let w=f.target;w.style.backgroundImage=""}),m}function Tt(r){return r.defaultPrevented||r.button!==0||r.metaKey||r.ctrlKey||r.shiftKey||r.altKey}function ge(r){let{href:t,replace:e=!1,scroll:o=!0,prefetch:n="hover",exact:i=!1}=r,s=()=>{var c;return(c=r.router)!=null?c:lt()},a=c=>{let d=new URL(t,"http://localhost").pathname;return i||d==="/"?c===d:c===d||c.startsWith(`${d}/`)},l=!1,u=()=>{l||(l=!0,s().prefetch(t))};return{href:t,ariaCurrent:c=>a(s().state.get("pathname",c))?"page":null,dataActive:c=>a(s().state.get("pathname",c))?"":null,onClick:c=>{let d=c,h=d.currentTarget;Tt(d)||h.target&&h.target!=="_self"||h.hasAttribute("download")||new URL(h.href,window.location.href).origin===window.location.origin&&(d.preventDefault(),s().navigate(t,{replace:e,scroll:o}))},onMouseEnter:()=>{n==="hover"&&u()},onFocus:()=>{n==="hover"&&u()},_onMount:c=>{if(n!=="visible")return;if(typeof IntersectionObserver=="undefined"){u();return}let d=new IntersectionObserver(h=>{h.some(m=>m.isIntersecting)&&(u(),d.disconnect())});d.observe(c.domElement),c.setMetadata("navLinkObserver",d)},_onRemove:c=>{let d=c.getMetadata("navLinkObserver");d==null||d.disconnect()}}}var J=new Set;function Re(){J.clear()}function dt(r){let t=globalThis.requestIdleCallback;t?t(r):setTimeout(r,0)}function we(r){let{src:t,strategy:e="afterInteractive",id:o,async:n=!0,onLoad:i,onError:s}=r,a=o!=null?o:t,l=c=>{J.has(a)||(J.add(a),c.src=t)},u={script:"",async:n,onLoad:()=>i==null?void 0:i(),onError:()=>s==null?void 0:s(),_onMount:c=>{let d=c.domElement;if(e==="afterInteractive"){l(d);return}document.readyState==="complete"?dt(()=>l(d)):window.addEventListener("load",()=>dt(()=>l(d)),{once:!0})}};return o!==void 0&&(u.id=o),u}function xe(r){return r}export{I as AppRouter,$ as DataCache,Y as DomphyApp,P as NotFoundSignal,nt as PREFETCH_LIFETIME,M as RedirectSignal,G as applyHeadTags,Ct as buildHref,W as buildNotFoundTree,H as buildTree,gt as compareSpecificity,C as compileRoutes,_t as createApiHandler,ce as createApp,it as createBrowserHistory,Wt as createMemoryHistory,st as defaultErrorBlock,at as defaultNotFoundBlock,xe as defineRoutes,lt as getRouter,U as isRewrite,_ as json,yt as matchPath,L as matchRoute,et as matchRouteSuffix,O as metadataToHeadTags,ge as navLink,At as notFound,he as optimizedImage,j as parseSegment,Dt as permanentRedirect,It as redirect,F as renderHeadTags,Re as resetScripts,K as resolveMetadata,Ot as rewrite,we as script,D as splitPath,tt as urlPartCount};
3
3
  //# sourceMappingURL=index.js.map