@useavalon/avalon 0.1.47 → 0.1.49
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/mod.d.ts +48 -49
- package/dist/mod.js +1 -1
- package/dist/src/client/components.d.ts +10 -18
- package/dist/src/client/components.js +1 -1
- package/dist/src/client/custom-directives.d.ts +25 -0
- package/dist/src/client/custom-directives.js +1 -0
- package/dist/src/client/main.js +3 -3
- package/dist/src/components/IslandErrorBoundary.d.ts +48 -9
- package/dist/src/components/IslandErrorBoundary.js +1 -1
- package/dist/src/components/LayoutErrorBoundary.d.ts +75 -10
- package/dist/src/components/LayoutErrorBoundary.js +1 -1
- package/dist/src/islands/builtin-directives.d.ts +15 -0
- package/dist/src/islands/builtin-directives.js +1 -0
- package/dist/src/islands/hydration-directives.d.ts +89 -0
- package/dist/src/islands/hydration-directives.js +1 -0
- package/dist/src/islands/integration-loader.d.ts +2 -2
- package/dist/src/islands/island.d.ts +11 -9
- package/dist/src/islands/island.js +1 -1
- package/dist/src/islands/types.d.ts +4 -2
- package/dist/src/layout-system.d.ts +14 -30
- package/dist/src/layout-system.js +1 -1
- package/dist/src/nitro/config.d.ts +3 -3
- package/dist/src/nitro/renderer.d.ts +18 -5
- package/dist/src/nitro/renderer.js +11 -11
- package/dist/src/persistence/island-state-serializer.d.ts +9 -0
- package/dist/src/persistence/island-state-serializer.js +1 -0
- package/dist/src/persistence/use-persistent-state.d.ts +31 -0
- package/dist/src/persistence/use-persistent-state.js +1 -0
- package/dist/src/prerender/index.d.ts +1 -1
- package/dist/src/prerender/prerender.d.ts +1 -1
- package/dist/src/prerender/prerender.js +1 -1
- package/dist/src/schemas/core.d.ts +2 -2
- package/dist/src/schemas/layout.d.ts +5 -5
- package/dist/src/schemas/layout.js +1 -1
- package/dist/src/schemas/routing/index.d.ts +2 -2
- package/dist/src/schemas/routing.d.ts +4 -4
- package/dist/src/types/island-prop.d.ts +14 -6
- package/dist/src/types/layout.d.ts +11 -19
- package/dist/src/types/layout.js +1 -1
- package/dist/src/vite-plugin/nitro-integration.d.ts +3 -3
- package/dist/src/vite-plugin/nitro-integration.js +14 -14
- package/package.json +2 -2
- package/dist/src/components/LayoutDataErrorBoundary.d.ts +0 -34
- package/dist/src/components/LayoutDataErrorBoundary.js +0 -1
- package/dist/src/components/PersistentIsland.d.ts +0 -36
- package/dist/src/components/PersistentIsland.js +0 -1
- package/dist/src/components/StreamingErrorBoundary.d.ts +0 -42
- package/dist/src/components/StreamingErrorBoundary.js +0 -1
- package/dist/src/components/StreamingLayout.d.ts +0 -83
- package/dist/src/components/StreamingLayout.js +0 -29
- package/dist/src/core/islands/island-persistence.d.ts +0 -74
- package/dist/src/core/islands/island-persistence.js +0 -1
- package/dist/src/core/islands/island-state-serializer.d.ts +0 -53
- package/dist/src/core/islands/island-state-serializer.js +0 -1
- package/dist/src/core/islands/persistent-island-context.d.ts +0 -36
- package/dist/src/core/islands/persistent-island-context.js +0 -1
- package/dist/src/core/islands/use-persistent-state.d.ts +0 -17
- package/dist/src/core/islands/use-persistent-state.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=new Map;export function registerHydrationDirective(t,n){e.has(t)&&console.warn(`[avalon] Hydration directive "${t}" is already registered. Overwriting.`),e.set(t,n)}export function unregisterHydrationDirective(t){return e.delete(t)}export function isCustomDirective(t){return e.has(t)}export function getDirective(t){return e.get(t)}export function getRegisteredDirectives(){return[...e.keys()]}export function serializeDirectiveScript(t){let n=e.get(t);return n?typeof n.script==`string`?n.script:n.script.toString():null}export function clearDirectives(){e.clear()}
|
|
@@ -23,7 +23,7 @@ export declare function detectAndLoadIntegration(src: string): Promise<Integrati
|
|
|
23
23
|
* @param src - The source path to detect framework from
|
|
24
24
|
* @returns The detected framework name
|
|
25
25
|
*/
|
|
26
|
-
export declare function detectFrameworkFromPath(src: string): "
|
|
26
|
+
export declare function detectFrameworkFromPath(src: string): "vue" | "svelte" | "solid" | "preact" | "react" | "lit" | "qwik";
|
|
27
27
|
/**
|
|
28
28
|
* Check if a path is within any islands directory (including nested).
|
|
29
29
|
*
|
|
@@ -66,7 +66,7 @@ export declare function extractNamespaceFromPath(path: string): string;
|
|
|
66
66
|
* @param content - The file content to analyze
|
|
67
67
|
* @returns The detected framework name
|
|
68
68
|
*/
|
|
69
|
-
export declare function detectFrameworkFromContent(src: string, content: string): "
|
|
69
|
+
export declare function detectFrameworkFromContent(src: string, content: string): "vue" | "svelte" | "solid" | "preact" | "react" | "lit" | "qwik";
|
|
70
70
|
/**
|
|
71
71
|
* Get integration for a specific framework, with error handling
|
|
72
72
|
*/
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import type { JSX } from
|
|
2
|
-
import type { ViteDevServer } from
|
|
3
|
-
import type { AnalyzerOptions } from
|
|
4
|
-
import type { Framework } from
|
|
1
|
+
import type { JSX } from "preact";
|
|
2
|
+
import type { ViteDevServer } from "vite";
|
|
3
|
+
import type { AnalyzerOptions } from "../core/components/component-analyzer.ts";
|
|
4
|
+
import type { Framework } from "./types.ts";
|
|
5
5
|
declare global {
|
|
6
6
|
var __viteDevServer: ViteDevServer | undefined;
|
|
7
7
|
}
|
|
8
8
|
/** Supported hydration conditions for island components */
|
|
9
|
-
export type HydrationCondition =
|
|
9
|
+
export type HydrationCondition = "on:visible" | "on:interaction" | "on:idle" | "on:client" | `media:${string}` | `on:${string}`;
|
|
10
10
|
/** Supported framework identifiers (without "unknown") */
|
|
11
|
-
export type FrameworkId = Exclude<Framework,
|
|
11
|
+
export type FrameworkId = Exclude<Framework, "unknown">;
|
|
12
12
|
export interface IslandProps {
|
|
13
13
|
/** Path to the island component (e.g., "/islands/Counter.tsx") */
|
|
14
14
|
src: string;
|
|
15
15
|
/** Hydration condition */
|
|
16
16
|
condition?: HydrationCondition;
|
|
17
|
+
/** Optional argument passed to custom hydration directives */
|
|
18
|
+
conditionArg?: string;
|
|
17
19
|
/** Props to pass to the island component */
|
|
18
20
|
props?: Record<string, unknown>;
|
|
19
21
|
/** Children to render inside the island (for SSR) */
|
|
20
|
-
children?: import(
|
|
22
|
+
children?: import("preact").ComponentChildren;
|
|
21
23
|
/** Whether to render server-side (default: true unless condition is 'on:client') */
|
|
22
24
|
ssr?: boolean;
|
|
23
25
|
/** Framework hint for client hydration */
|
|
@@ -37,7 +39,7 @@ export interface IslandProps {
|
|
|
37
39
|
* Uses custom elements instead of div wrappers for cleaner, more semantic markup.
|
|
38
40
|
* Supports intelligent rendering strategy detection to skip hydration for SSR-only components.
|
|
39
41
|
*/
|
|
40
|
-
export default function Island({ src, condition, props, children, ssr, framework, ssrOnly, renderOptions, hydrationData, }: IslandProps): JSX.Element;
|
|
42
|
+
export default function Island({ src, condition, conditionArg, props, children, ssr, framework, ssrOnly, renderOptions, hydrationData, }: IslandProps): JSX.Element;
|
|
41
43
|
/**
|
|
42
44
|
* Universal renderIsland function – auto-detects framework and handles SSR + hydration.
|
|
43
45
|
*
|
|
@@ -54,4 +56,4 @@ export default function Island({ src, condition, props, children, ssr, framework
|
|
|
54
56
|
* Error isolation: If SSR fails, returns an error placeholder instead of throwing,
|
|
55
57
|
* allowing the page to continue rendering other islands.
|
|
56
58
|
*/
|
|
57
|
-
export declare function renderIsland({ src, condition, props, children, ssr, framework, ssrOnly, renderOptions, component: preloadedComponent, }: IslandProps): Promise<JSX.Element>;
|
|
59
|
+
export declare function renderIsland({ src, condition, conditionArg, props, children, ssr, framework, ssrOnly, renderOptions, component: preloadedComponent, }: IslandProps): Promise<JSX.Element>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as e}from"preact";import{
|
|
1
|
+
import{h as e}from"preact";import{getIslandBundlePath as t}from"../build/island-manifest.js";import{devError as n,devLog as r,devWarn as i,isDev as a,logRenderTiming as o}from"../utils/dev-logger.js";import{analyzeComponentFile as s,renderComponentSSROnly as c}from"./component-analysis.js";import{detectFramework as l}from"./framework-detection.js";import{isCustomDirective as u,serializeDirectiveScript as d}from"./hydration-directives.js";import{detectFrameworkFromPath as f,loadIntegration as p}from"./integration-loader.js";import{addUniversalCSS as m}from"./universal-css-collector.js";import{addUniversalHead as h}from"./universal-head-collector.js";function g(e){return`island-${e.replaceAll(/[^a-zA-Z0-9]/g,`-`)}`}function _(e){let t={};e.renderId&&(t[`data-solid-render-id`]=e.renderId);let n=e.metadata;return n?.tagName&&(t[`data-tag-name`]=n.tagName),t}function v(e,n,r,i,a){let o={"data-condition":n,"data-src":t(e),"data-props":JSON.stringify(r),"data-render-strategy":`hydrate`,..._(i)};if(u(n)){o[`data-custom-directive`]=n;let e=d(n);e&&(o[`data-directive-script`]=e)}return a&&(o[`data-condition-arg`]=a),o}function y(e){return e.startsWith(`<script`)?`script`:e.startsWith(`<style`)?`style`:e.startsWith(`<meta`)?`meta`:e.startsWith(`<link`)?`link`:e.includes(`window._$HY`)||e.includes(`_$HY=`)?`script`:`other`}function b(e){let t=e.match(/<style[^>]*>([\s\S]*?)<\/style>/i);return t?t[1].trim():null}function x(e,t,n,i){if(e.css&&m(e.css,t,n,e.scopeId),e.head){let a=e.head.trim(),o=y(a);if(o===`style`){let o=b(a);o&&(r(`${i} Extracting CSS from head <style> tag`),m(o,t,n,e.scopeId));return}h(e.head,t,n,o)}}function S(t){let{islandId:n,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,conditionArg:c,props:l,hydrationData:u,children:d}=t,f={id:n,"data-framework":i},p=a?{"data-render-strategy":`ssr-only`}:v(o,s,l,u,c);i===`lit`&&r(`🔍 [Island Component] ${o} - Lit hydration data:`,{hydrationDataKeys:Object.keys(u),metadata:u.metadata});let m={...f,...p};return typeof d==`string`?e(`avalon-island`,{...m,dangerouslySetInnerHTML:{__html:d}}):e(`avalon-island`,m,d)}function C(n){let{islandId:r,detectedFramework:i,shouldSkipHydration:a,src:o,condition:s,props:c,hydrationData:l,conditionArg:f}=n;if(a)return e(`avalon-island`,{id:r,"data-render-strategy":`ssr-only`,"data-framework":i});let p={id:r,"data-condition":s,"data-src":t(o),"data-props":JSON.stringify(c),"data-render-strategy":`hydrate`,"data-framework":i,..._(l)};if(u(s)){p[`data-custom-directive`]=s;let e=d(s);e&&(p[`data-directive-script`]=e)}return f&&(p[`data-condition-arg`]=f),e(`avalon-island`,p)}export default function w({src:e,condition:t=`on:client`,conditionArg:n,props:a={},children:o,ssr:s=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},hydrationData:d={}}){let p=g(e),m=l||!!u.forceSSROnly,h=c||f(e),_=o!=null&&o!==``;return r(`🔍 [Island Component] ${e}`,{ssr:s,ssrOnly:l,hasChildren:_,framework:c,condition:t}),s&&_?S({islandId:p,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,conditionArg:n,props:a,hydrationData:d,children:o}):(s&&!_&&m&&i(`${e}: SSR-only component has no rendered content. This may indicate a rendering error.`),C({islandId:p,detectedFramework:h,shouldSkipHydration:m,src:e,condition:t,props:a,hydrationData:d,conditionArg:n}))}function T(r,i){let a=i instanceof Error?i.message:String(i);return n(`🚨 Island SSR failed for ${r}:`,i),i instanceof Error&&i.stack&&n(`Stack trace:`,i.stack),e(`avalon-island`,{id:g(r),"data-src":t(r),"data-ssr-error":a,"data-render-strategy":`client-only`})}async function E({src:e,condition:t,conditionArg:r,props:i,children:o,ssr:s,framework:c,ssrOnly:l,renderOptions:u,component:d}){let f=`🏝️ [${e}]`;if(!s||o)return w({src:e,condition:t,conditionArg:r,props:i,children:o,ssr:s,framework:c,ssrOnly:l,renderOptions:u});let m;try{m=await p(c)}catch(a){return n(`${f} Failed to load ${c} integration:`,a),w({src:e,condition:t,conditionArg:r,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}try{let n=await m.render({component:d??null,props:i,src:e,condition:t,ssrOnly:l,viteServer:globalThis.__viteDevServer,isDev:a()});return x(n,e,c,f),w({src:e,condition:t,conditionArg:r,props:i,children:n.html,ssr:!0,framework:c,ssrOnly:l,renderOptions:u,hydrationData:l?void 0:n.hydrationData})}catch(a){return n(`${f} Fast path SSR failed:`,a),w({src:e,condition:t,conditionArg:r,props:i,ssr:!1,framework:c,ssrOnly:l,renderOptions:u})}}async function D(e,t,n,r){if(t||n.detectScripts===!1)return t;try{let t=await s(e,n);if(t.decision.warnings?.length)for(let e of t.decision.warnings)i(`${r} Analysis warning: ${e}`);return!t.decision.shouldHydrate}catch(e){return i(`${r} Component analysis failed:`,e),t}}async function O(e){return e.endsWith(`.vue`)?`vue`:e.endsWith(`.svelte`)?`svelte`:e.endsWith(`.tsx`)||e.endsWith(`.jsx`)||e.endsWith(`.ts`)||e.endsWith(`.js`)?l(e):`unknown`}async function k(e,t,n,r,i,o,s){let c=await O(e),l=c,u=await(await A(c,o)).render({component:s??null,props:n,src:e,condition:t,ssrOnly:r,viteServer:globalThis.__viteDevServer,isDev:a()});return x(u,e,c,o),w({src:e,condition:t,props:n,children:u.html,ssr:!0,framework:l,ssrOnly:r,renderOptions:i,hydrationData:r?void 0:u.hydrationData})}async function A(e,t){try{r(`${t} Loading integration for framework: ${e}`);let n=await p(e);return r(`${t} ✅ Integration loaded successfully`),n}catch(r){throw n(`${t} Failed to load ${e} integration:`,r),Error(`Failed to load integration for framework '${e}'. Make sure @useavalon/${e} is installed.\nInstall it with: deno add @useavalon/${e}`,{cause:r})}}export async function renderIsland({src:e,condition:t=`on:client`,conditionArg:n,props:r={},children:i,ssr:s=t!==`on:client`,framework:c,ssrOnly:l=!1,renderOptions:u={},component:d}){let f=a()?performance.now():0,p=`🏝️ [${e}]`;try{return l&&!s&&(s=!0),c?await E({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:s,framework:c,ssrOnly:l,renderOptions:u,component:d}):await j({src:e,condition:t,conditionArg:n,props:r,children:i,ssr:s,ssrOnly:l,renderOptions:u,logPrefix:p,component:d})}catch(t){return T(e,t)}finally{a()&&o(e,performance.now()-f)}}async function j(e){let{src:t,condition:i,conditionArg:a,props:o,children:s,ssr:c,ssrOnly:l,renderOptions:u,logPrefix:d,component:f}=e;if(r(`🔍 [renderIsland] ${t} - Starting render (slow path)`,{ssr:c,ssrOnly:l,hasChildren:!!s,condition:i}),await D(t,l,u,d))return M(t,i,o,s,c,u,d);if(!c||s)return w({src:t,condition:i,conditionArg:a,props:o,children:s,ssr:c,renderOptions:u});try{return await k(t,i,o,l,u,d,f)}catch(e){let r=await O(t);return n(`${d} Framework rendering failed:`,e),w({src:t,condition:i,conditionArg:a,props:o,ssr:!1,framework:r,renderOptions:u})}}function M(e,t,r,i,a,o,s){return a&&!i?c({src:e,condition:t,props:r,renderOptions:o}).catch(i=>(n(`${s} SSR failed for SSR-only component:`,i),w({src:e,condition:t,props:r,ssr:!1,ssrOnly:!0,renderOptions:o}))):w({src:e,condition:t,props:r,children:i,ssr:a,ssrOnly:!0,renderOptions:o})}
|
|
@@ -12,8 +12,10 @@ export type Framework = "solid" | "vue" | "svelte" | "preact" | "react" | "lit"
|
|
|
12
12
|
export interface IslandProps {
|
|
13
13
|
/** Path to the island component (e.g., "/islands/Counter.tsx") */
|
|
14
14
|
src: string;
|
|
15
|
-
/** Hydration condition */
|
|
16
|
-
condition?: "on:visible" | "on:interaction" | "on:idle" | "on:client" | `media:${string}`;
|
|
15
|
+
/** Hydration condition (built-in or custom directive name) */
|
|
16
|
+
condition?: "on:visible" | "on:interaction" | "on:idle" | "on:client" | `media:${string}` | `on:${string}`;
|
|
17
|
+
/** Optional argument passed to custom hydration directives */
|
|
18
|
+
conditionArg?: string;
|
|
17
19
|
/** Props to pass to the island component */
|
|
18
20
|
props?: Record<string, unknown>;
|
|
19
21
|
/** Children to render inside the island (for SSR) */
|
|
@@ -4,36 +4,20 @@
|
|
|
4
4
|
* This file provides a comprehensive export index for the entire layout system,
|
|
5
5
|
* making it easy to import all layout-related functionality from a single location.
|
|
6
6
|
*/
|
|
7
|
-
export {
|
|
8
|
-
export
|
|
9
|
-
export {
|
|
10
|
-
export type { LayoutDataLoadingResult,
|
|
11
|
-
export {
|
|
12
|
-
export
|
|
13
|
-
export {
|
|
14
|
-
export type { LayoutConfig } from
|
|
15
|
-
export {
|
|
16
|
-
export
|
|
17
|
-
export {
|
|
18
|
-
export {
|
|
19
|
-
export {
|
|
20
|
-
export {
|
|
21
|
-
export type { IslandState, PersistentIslandProps, PersistentIslandContext } from './schemas/layout.ts';
|
|
22
|
-
export { LayoutErrorBoundary } from './components/LayoutErrorBoundary.tsx';
|
|
23
|
-
export { LayoutDataErrorBoundary } from './components/LayoutDataErrorBoundary.tsx';
|
|
24
|
-
export { IslandErrorBoundary, withIslandErrorBoundary } from './components/IslandErrorBoundary.tsx';
|
|
25
|
-
export { StreamingErrorBoundary, withStreamingErrorBoundary } from './components/StreamingErrorBoundary.tsx';
|
|
26
|
-
export type { LayoutErrorInfo, LayoutErrorBoundaryProps, ErrorRecoveryStrategy } from './schemas/layout.ts';
|
|
27
|
-
export { StreamingLayout, StreamingSuspense, withStreaming, useStreamingState } from './components/StreamingLayout.tsx';
|
|
28
|
-
export type { StreamingLayoutProps, StreamingComponent } from './schemas/layout.ts';
|
|
29
|
-
export { LayoutCacheManager } from './core/layout/layout-cache-manager.ts';
|
|
30
|
-
export type { CacheEntry, CacheStats, CacheConfig, } from './core/layout/layout-cache-manager.ts';
|
|
31
|
-
export type { LayoutContext, LayoutData, LayoutHandler, LayoutProps, LayoutLoader, ResolvedLayout, LayoutCache, EnhancedLayoutContext, LayoutMatcherFunction, LayoutErrorHandler, LayoutRetryFunction, LayoutFallbackRenderer, IslandStateSaver, IslandStateLoader, IslandStateClearer, StreamingReadyCheck, } from './schemas/layout.ts';
|
|
32
|
-
export type { ILayoutDiscovery, ILayoutMatcher, ILayoutComposer, IIslandPersistence, ILayoutErrorRecovery, ILayoutStreaming, IEnhancedLayoutResolver, ILayoutComponent, IPersistentIslandComponent, ILayoutErrorBoundaryComponent, IStreamingLayoutComponent, LayoutModule, PageModule, LayoutResolutionContext, LayoutPerformanceMetrics, LayoutDebugInfo, LayoutEventType, LayoutEventData, LayoutEventHandler, ILayoutEventEmitter, } from './types/layout.ts';
|
|
33
|
-
export { LayoutContextSchema, LayoutDataSchema, LayoutRouteSchema, LayoutHandlerSchema, LayoutPropsSchema, LayoutDiscoveryOptionsSchema, RouteInfoSchema, LayoutRuleSchema, LayoutConfigSchema, IslandStateSchema, PersistentIslandPropsSchema, PersistentIslandContextSchema, LayoutErrorInfoSchema, LayoutErrorBoundaryPropsSchema, ErrorRecoveryStrategySchema, StreamingLayoutPropsSchema, StreamingComponentSchema, ResolvedLayoutSchema, LayoutCacheSchema, EnhancedLayoutContextSchema, } from './schemas/layout.ts';
|
|
34
|
-
export { EnhancedLayoutResolver as LayoutSystem } from './core/layout/enhanced-layout-resolver.ts';
|
|
35
|
-
export { defaultIslandPersistence as defaultPersistence } from './core/islands/island-persistence.ts';
|
|
36
|
-
export { createEnhancedLayoutResolver as createLayoutSystem } from './core/layout/enhanced-layout-resolver.ts';
|
|
7
|
+
export type { EnhancedLayoutResolverOptions } from "./core/layout/enhanced-layout-resolver.ts";
|
|
8
|
+
export { createEnhancedLayoutResolver, EnhancedLayoutResolver, EnhancedLayoutResolverUtils, } from "./core/layout/enhanced-layout-resolver.ts";
|
|
9
|
+
export { LayoutComposer } from "./core/layout/layout-composer.ts";
|
|
10
|
+
export type { LayoutDataLoadingOptions, LayoutDataLoadingResult, } from "./core/layout/layout-data-loader.ts";
|
|
11
|
+
export { defaultLayoutDataLoader, getParentLayoutData, LayoutDataLoader, LayoutDataLoadingError, loadSingleLayoutData, mergeLayoutData, } from "./core/layout/layout-data-loader.ts";
|
|
12
|
+
export { LayoutDiscovery } from "./core/layout/layout-discovery.ts";
|
|
13
|
+
export { BuiltInLayoutRules, LayoutMatcher as LayoutMatcherClass, } from "./core/layout/layout-matcher.ts";
|
|
14
|
+
export type { LayoutConfig, LayoutDiscoveryOptions, LayoutRoute, LayoutRule, RouteInfo, } from "./schemas/layout.ts";
|
|
15
|
+
export type { CacheConfig, CacheEntry, CacheStats, } from "./core/layout/layout-cache-manager.ts";
|
|
16
|
+
export { LayoutCacheManager } from "./core/layout/layout-cache-manager.ts";
|
|
17
|
+
export type { EnhancedLayoutContext, IslandStateClearer, IslandStateLoader, IslandStateSaver, LayoutCache, LayoutContext, LayoutData, LayoutErrorHandler, LayoutFallbackRenderer, LayoutHandler, LayoutLoader, LayoutMatcherFunction, LayoutProps, LayoutRetryFunction, ResolvedLayout, StreamingReadyCheck, } from "./schemas/layout.ts";
|
|
18
|
+
export type { IEnhancedLayoutResolver, IIslandPersistence, ILayoutComponent, ILayoutComposer, ILayoutDiscovery, ILayoutErrorBoundaryComponent, ILayoutErrorRecovery, ILayoutEventEmitter, ILayoutMatcher, ILayoutStreaming, IPersistentIslandComponent, IStreamingLayoutComponent, LayoutDebugInfo, LayoutEventData, LayoutEventHandler, LayoutEventType, LayoutModule, LayoutPerformanceMetrics, LayoutResolutionContext, PageModule, } from "./types/layout.ts";
|
|
19
|
+
export { EnhancedLayoutContextSchema, ErrorRecoveryStrategySchema, IslandStateSchema, LayoutCacheSchema, LayoutConfigSchema, LayoutContextSchema, LayoutDataSchema, LayoutDiscoveryOptionsSchema, LayoutErrorBoundaryPropsSchema, LayoutErrorInfoSchema, LayoutHandlerSchema, LayoutPropsSchema, LayoutRouteSchema, LayoutRuleSchema, PersistentIslandContextSchema, PersistentIslandPropsSchema, ResolvedLayoutSchema, RouteInfoSchema, StreamingComponentSchema, StreamingLayoutPropsSchema, } from "./schemas/layout.ts";
|
|
20
|
+
export { createEnhancedLayoutResolver as createLayoutSystem, EnhancedLayoutResolver as LayoutSystem, } from "./core/layout/enhanced-layout-resolver.ts";
|
|
37
21
|
/**
|
|
38
22
|
* Layout System Version Information
|
|
39
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{
|
|
1
|
+
export{createEnhancedLayoutResolver,EnhancedLayoutResolver,EnhancedLayoutResolverUtils}from"./core/layout/enhanced-layout-resolver.js";export{LayoutComposer}from"./core/layout/layout-composer.js";export{defaultLayoutDataLoader,getParentLayoutData,LayoutDataLoader,LayoutDataLoadingError,loadSingleLayoutData,mergeLayoutData}from"./core/layout/layout-data-loader.js";export{LayoutDiscovery}from"./core/layout/layout-discovery.js";export{BuiltInLayoutRules,LayoutMatcher as LayoutMatcherClass}from"./core/layout/layout-matcher.js";export{LayoutCacheManager}from"./core/layout/layout-cache-manager.js";export{EnhancedLayoutContextSchema,ErrorRecoveryStrategySchema,IslandStateSchema,LayoutCacheSchema,LayoutConfigSchema,LayoutContextSchema,LayoutDataSchema,LayoutDiscoveryOptionsSchema,LayoutErrorBoundaryPropsSchema,LayoutErrorInfoSchema,LayoutHandlerSchema,LayoutPropsSchema,LayoutRouteSchema,LayoutRuleSchema,PersistentIslandContextSchema,PersistentIslandPropsSchema,ResolvedLayoutSchema,RouteInfoSchema,StreamingComponentSchema,StreamingLayoutPropsSchema}from"./schemas/layout.js";export{createEnhancedLayoutResolver as createLayoutSystem,EnhancedLayoutResolver as LayoutSystem}from"./core/layout/enhanced-layout-resolver.js";export const LAYOUT_SYSTEM_VERSION=`1.0.0`;export const LAYOUT_SYSTEM_FEATURES={DISCOVERY:!0,DATA_LOADING:!0,CONDITIONAL_RENDERING:!0,COMPOSITION_CONTROL:!0,PERSISTENT_ISLANDS:!0,ERROR_BOUNDARIES:!0,STREAMING:!0,CACHING:!0,PERFORMANCE_MONITORING:!0,DEBUG_UTILITIES:!0};export const LAYOUT_SYSTEM_DEFAULTS={DISCOVERY:{baseDirectory:`src/pages`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`],enableWatching:!1,developmentMode:!1},CACHING:{enabled:!0,ttl:3e5,maxSize:100,cleanupInterval:6e4},STREAMING:{enabled:!0,priority:`medium`,timeout:5e3},ERROR_BOUNDARIES:{enabled:!0,maxRetries:3,fallbackStrategy:`component`},PERFORMANCE:{monitoring:!0,thresholds:{discoveryTime:100,dataLoadingTime:500,renderingTime:200,totalTime:1e3}}};
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* - `/*.html`, `/*.css`: Short cache with revalidation
|
|
20
20
|
* - `/favicon.ico`: Medium cache (1 day)
|
|
21
21
|
*/
|
|
22
|
-
import type { ResolvedAvalonConfig } from
|
|
22
|
+
import type { ResolvedAvalonConfig } from "../vite-plugin/types.ts";
|
|
23
23
|
/**
|
|
24
24
|
* Cache configuration options for route rules
|
|
25
25
|
*/
|
|
@@ -229,7 +229,7 @@ export interface NitroConfigOutput {
|
|
|
229
229
|
/** Static assets configuration */
|
|
230
230
|
staticAssets?: StaticAssetsConfig;
|
|
231
231
|
/** Prerender configuration for SSG */
|
|
232
|
-
prerender?: AvalonNitroConfig[
|
|
232
|
+
prerender?: AvalonNitroConfig["prerender"];
|
|
233
233
|
}
|
|
234
234
|
/**
|
|
235
235
|
* Avalon-specific runtime configuration stored in Nitro's runtimeConfig
|
|
@@ -264,7 +264,7 @@ export declare function resolvePresetName(preset: string): string;
|
|
|
264
264
|
/**
|
|
265
265
|
* Default Nitro configuration values
|
|
266
266
|
*/
|
|
267
|
-
export declare const DEFAULT_NITRO_CONFIG: Required<Pick<AvalonNitroConfig,
|
|
267
|
+
export declare const DEFAULT_NITRO_CONFIG: Required<Pick<AvalonNitroConfig, "preset" | "serverDir" | "streaming">>;
|
|
268
268
|
/**
|
|
269
269
|
* Creates a Nitro configuration from Avalon plugin config and Nitro-specific options
|
|
270
270
|
*
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
*
|
|
26
26
|
* Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 5.1, 5.3, 9.1, 9.2, 9.3, 9.4, 10.5
|
|
27
27
|
*/
|
|
28
|
-
import type {
|
|
29
|
-
import type {
|
|
28
|
+
import type { H3Event } from "h3";
|
|
29
|
+
import type { AvalonRuntimeConfig, HttpError, NitroRenderContext, PageModule, SSRRenderOptions, SSRRenderResult } from "./types.ts";
|
|
30
30
|
/**
|
|
31
31
|
* Resolved page route information
|
|
32
32
|
*/
|
|
@@ -68,6 +68,17 @@ export interface RenderHandlerOptions {
|
|
|
68
68
|
loadPageModule?: (filePath: string) => Promise<PageModule>;
|
|
69
69
|
/** Custom layout resolver */
|
|
70
70
|
resolveLayouts?: (routePath: string, config: AvalonRuntimeConfig) => Promise<string[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Wrap rendered page HTML with layout components.
|
|
73
|
+
*
|
|
74
|
+
* Called after the page component is rendered to HTML. The function
|
|
75
|
+
* receives the page HTML, page module, and render context, and should
|
|
76
|
+
* return the full HTML document string (including `<!DOCTYPE html>`).
|
|
77
|
+
*
|
|
78
|
+
* When provided, the renderer skips its default HTML shell generation
|
|
79
|
+
* and uses the returned string directly.
|
|
80
|
+
*/
|
|
81
|
+
wrapWithLayouts?: (pageHtml: string, pageModule: PageModule, context: NitroRenderContext) => Promise<string> | string;
|
|
71
82
|
/**
|
|
72
83
|
* Enable custom error pages (404.tsx, 500.tsx, _error.tsx)
|
|
73
84
|
* When enabled, the renderer will look for custom error pages in the pages directory
|
|
@@ -94,7 +105,7 @@ export declare function toRequest(event: H3Event): Request;
|
|
|
94
105
|
/**
|
|
95
106
|
* Gets request headers from an H3 event
|
|
96
107
|
*/
|
|
97
|
-
export declare function getRequestHeaders(
|
|
108
|
+
export declare function getRequestHeaders(_event: H3Event): Headers;
|
|
98
109
|
/**
|
|
99
110
|
* Sets a response header on an H3 event
|
|
100
111
|
*/
|
|
@@ -197,7 +208,7 @@ export declare function processHydrationRequirements(html: string, isDev: boolea
|
|
|
197
208
|
* @param options - Render options
|
|
198
209
|
* @returns SSR render result
|
|
199
210
|
*/
|
|
200
|
-
export declare function renderPage(pageModule: PageModule, context: NitroRenderContext, options?: SSRRenderOptions): Promise<SSRRenderResult>;
|
|
211
|
+
export declare function renderPage(pageModule: PageModule, context: NitroRenderContext, options?: SSRRenderOptions, wrapWithLayouts?: RenderHandlerOptions["wrapWithLayouts"]): Promise<SSRRenderResult>;
|
|
201
212
|
/**
|
|
202
213
|
* Extended streaming options with additional callbacks
|
|
203
214
|
*/
|
|
@@ -280,6 +291,8 @@ export interface NitroCatchAllOptions {
|
|
|
280
291
|
loadPageModule: (filePath: string) => Promise<PageModule>;
|
|
281
292
|
/** Optional layout resolver */
|
|
282
293
|
resolveLayouts?: (routePath: string, config: AvalonRuntimeConfig) => Promise<string[]>;
|
|
294
|
+
/** Wrap rendered page HTML with layout components (same as RenderHandlerOptions) */
|
|
295
|
+
wrapWithLayouts?: RenderHandlerOptions["wrapWithLayouts"];
|
|
283
296
|
/**
|
|
284
297
|
* Enable custom error pages (404.tsx, 500.tsx, _error.tsx)
|
|
285
298
|
* When enabled, the renderer will look for custom error pages in the pages directory
|
|
@@ -339,4 +352,4 @@ export declare function createNitroCatchAllRenderer(options: NitroCatchAllOption
|
|
|
339
352
|
* }
|
|
340
353
|
* ```
|
|
341
354
|
*/
|
|
342
|
-
export { clearMiddlewareCache as clearRendererMiddlewareCache } from
|
|
355
|
+
export { clearMiddlewareCache as clearRendererMiddlewareCache } from "../middleware/index.ts";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{getRequestURL as e}from"h3";import{
|
|
1
|
+
import{getRequestURL as e}from"h3";import{h as t}from"preact";import n from"preact-render-to-string";import{discoverScopedMiddleware as r,executeScopedMiddleware as i}from"../middleware/index.js";import{discoverErrorPages as a,handleRenderError as o}from"./error-handler.js";import{createNotFoundError as s,isHttpError as c}from"./types.js";export function createRenderContext(e,t={}){let n=getRequestURL(e);return{url:n,params:t,query:Object.fromEntries(n.searchParams),request:toRequest(e),event:e}}export function getRequestURL(t){return new URL(e(t).pathname,`http://localhost`)}export function toRequest(e){let t=getRequestURL(e);return new Request(t,{method:e.req.method,headers:getRequestHeaders(e)})}export function getRequestHeaders(e){return new Headers}export function setResponseHeader(e,t,n){e.context.responseHeaders||(e.context.responseHeaders={}),e.context.responseHeaders[t]=n}export function createErrorResponse(e,t){let n=c(e)?e.statusCode:500;if(t){let t=h(e,n);return new Response(t,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}let r=g(n);return new Response(r,{status:n,headers:{"Content-Type":`text/html; charset=utf-8`}})}function h(e,t){return`<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
@@ -117,22 +117,22 @@ import{getRequestURL as e}from"h3";import{createNotFoundError as t,isHttpError a
|
|
|
117
117
|
<p><a href="/">Return to home</a></p>
|
|
118
118
|
</div>
|
|
119
119
|
</body>
|
|
120
|
-
</html>`}function _(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`}[e]||`Error`}function v(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}export function extractIslandMarkers(e){let t=[],n=/<[^>]*data-framework="([^"]+)"[^>]*>/g,r
|
|
121
|
-
`);return e.includes(`</body>`)?e.replace(`</body>`,`${a}\n</body>`):e+a}export function validateHydrationMarkers(e){let t=extractIslandMarkers(e),n=e.match(/data-framework="[^"]+"/g)||[],r=e.match(/data-src="[^"]+"/g)||[],i=e.match(/data-props="[^"]*"/g)||[],a=e.includes(`/src/client/main.js`)||e.includes(`/dist/client.js`)||e.includes(`client/main.js`),o=t.every(e=>e.framework&&e.src),s=t.length===0||o&&a;return{hasFrameworkAttr:n.length>0,hasSrcAttr:r.length>0,hasPropsAttr:i.length>0,islandCount:n.length,islands:t,hasClientScript:a,isValid:s}}export function processHydrationRequirements(e,t){let n=injectHydrationScript(e,t);return{html:n,validation:validateHydrationMarkers(n)}}export async function renderPage(e,t,n={}){try{let
|
|
120
|
+
</html>`}function _(e){return{400:`Bad Request`,401:`Unauthorized`,403:`Forbidden`,404:`Page Not Found`,405:`Method Not Allowed`,500:`Internal Server Error`,502:`Bad Gateway`,503:`Service Unavailable`}[e]||`Error`}function v(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`>`,`>`).replaceAll(`"`,`"`).replaceAll(`'`,`'`)}export function extractIslandMarkers(e){let t=[],n=/<[^>]*data-framework="([^"]+)"[^>]*>/g,r=n.exec(e);for(;r!==null;){let i=r[0],a=r[1],o=/data-src="([^"]+)"/.exec(i),s=o?o[1]:``,c=/data-props="([^"]*)"/.exec(i),l=c?c[1]:void 0,u=/data-hydrate="([^"]+)"/.exec(i),d=u?u[1]:void 0;t.push({framework:a,src:s,props:l,hydrate:d}),r=n.exec(e)}return t}export function ensureHydrationMarkers(e,t){let n=e;return t.framework&&!n.includes(`data-framework=`)&&(n=n.replace(/>/,` data-framework="${t.framework}">`)),t.src&&!n.includes(`data-src=`)&&(n=n.replace(/>/,` data-src="${t.src}">`)),t.props!==void 0&&!n.includes(`data-props=`)&&(n=n.replace(/>/,` data-props="${t.props}">`)),n}export function injectHydrationScript(e,t,n={}){if(!(e.includes(`data-framework=`)||e.includes(`data-src=`))&&!n.forceInject||[`/src/client/main.js`,`/dist/client.js`,`client/main.js`].some(t=>e.includes(t)))return e;let r=n.scriptPath||(t?`/src/client/main.js`:`/dist/client.js`),i=[];i.push(`<script type="module" src="${r}"><\/script>`),n.additionalScripts&&i.push(...n.additionalScripts);let a=i.join(`
|
|
121
|
+
`);return e.includes(`</body>`)?e.replace(`</body>`,`${a}\n</body>`):e+a}export function validateHydrationMarkers(e){let t=extractIslandMarkers(e),n=e.match(/data-framework="[^"]+"/g)||[],r=e.match(/data-src="[^"]+"/g)||[],i=e.match(/data-props="[^"]*"/g)||[],a=e.includes(`/src/client/main.js`)||e.includes(`/dist/client.js`)||e.includes(`client/main.js`),o=t.every(e=>e.framework&&e.src),s=t.length===0||o&&a;return{hasFrameworkAttr:n.length>0,hasSrcAttr:r.length>0,hasPropsAttr:i.length>0,islandCount:n.length,islands:t,hasClientScript:a,isValid:s}}export function processHydrationRequirements(e,t){let n=injectHydrationScript(e,t);return{html:n,validation:validateHydrationMarkers(n)}}export async function renderPage(e,t,n={},r){try{let i={};return e.getServerSideProps&&(i=await e.getServerSideProps(t)),{html:await y(e,i,t,n,r),statusCode:200,headers:{"Content-Type":`text/html; charset=utf-8`}}}catch(e){throw console.error(`[SSR Error]`,e),n.onError&&e instanceof Error&&n.onError(e),e}}async function y(e,r,i,a,o){let s=e.default,c=e.metadata||{},l=process.env.NODE_ENV!==`production`,u;try{let e=s(r);u=e instanceof Promise?await e:e}catch(e){console.error(`[renderer] Error calling page component:`,e),u=t(`div`,null,`Error rendering page`)}let d;try{d=n(u)}catch(e){console.error(`[renderer] Error in preactRenderToString:`,e),d=`<div>Error rendering page</div>`}if(o)return await o(d,e,i);let f=l?`
|
|
122
122
|
<script type="module" src="/src/client/main.js"><\/script>`:``;return`<!DOCTYPE html>
|
|
123
123
|
<html lang="en">
|
|
124
124
|
<head>
|
|
125
125
|
<meta charset="utf-8">
|
|
126
126
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
127
|
-
<title>${v(String(
|
|
128
|
-
${
|
|
127
|
+
<title>${v(String(c.title||`Avalon App`))}</title>
|
|
128
|
+
${c.description?`<meta name="description" content="${v(String(c.description))}">`:``}
|
|
129
129
|
</head>
|
|
130
130
|
<body>
|
|
131
131
|
<div id="app">
|
|
132
|
-
${
|
|
133
|
-
</div>${
|
|
132
|
+
${d}
|
|
133
|
+
</div>${f}
|
|
134
134
|
</body>
|
|
135
|
-
</html>`}export async function renderPageStream(e,t,
|
|
135
|
+
</html>`}export async function renderPageStream(e,t,r={}){let i=new TextEncoder,a=null,o={shellSent:!1,contentSent:!1,closed:!1,error:null},s=r.shellReadyTimeout,c=r.allReadyTimeout,l=null,u=null,d=()=>{l&&=(clearTimeout(l),null),u&&=(clearTimeout(u),null)};function f(e,t,n,r,i,a,o){if(n.error=e,a(),console.error(`[Streaming Error]`,{message:e.message,stack:e.stack,shellSent:n.shellSent,isShellError:t,timestamp:new Date().toISOString()}),t&&o.onShellError&&o.onShellError(e),o.onError&&o.onError(e),!n.closed&&r){if(n.shellSent){let t=C(e);r.enqueue(i.encode(t));let n=S();r.enqueue(i.encode(n))}else{let t=h(e,500);r.enqueue(i.encode(t))}n.closed=!0,r.close()}}async function p(s){a=s;let p={};e.getServerSideProps&&(p=await e.getServerSideProps(t));let m=b(e.metadata||{},t);if(o.closed||(s.enqueue(i.encode(m)),o.shellSent=!0,l&&=(clearTimeout(l),null),r.onShellReady&&r.onShellReady()),c&&c>0&&(u=setTimeout(()=>{!o.contentSent&&!o.closed&&f(Error(`All ready timeout after ${c}ms`),!1,o,a,i,d,r)},c)),!o.closed){let t=e.default;if(t&&typeof t==`function`){let r=t(p);if(r&&typeof r.then==`function`)try{let e=n(await r);s.enqueue(i.encode(` <div id="app">${e}</div>\n`))}catch(t){console.error(`[streaming] Async component error:`,t);let n=x(e,p);s.enqueue(i.encode(n))}else{let t=x(e,p);s.enqueue(i.encode(t))}}else{let t=x(e,p);s.enqueue(i.encode(t))}o.contentSent=!0}if(!o.closed){let e=S();s.enqueue(i.encode(e))}d(),r.onAllReady&&!o.closed&&r.onAllReady(),o.closed||(o.closed=!0,s.close())}return new ReadableStream({async start(e){a=e,s&&s>0&&(l=setTimeout(()=>{!o.shellSent&&!o.closed&&f(Error(`Shell ready timeout after ${s}ms`),!0,o,a,i,d,r)},s));try{await p(e)}catch(e){f(e instanceof Error?e:Error(String(e)),!o.shellSent,o,a,i,d,r)}},cancel(){if(d(),!o.closed&&a){o.closed=!0;try{a.close()}catch{}}}})}function b(e,t){return`<!DOCTYPE html>
|
|
136
136
|
<html lang="en">
|
|
137
137
|
<head>
|
|
138
138
|
<meta charset="utf-8">
|
|
@@ -141,9 +141,9 @@ import{getRequestURL as e}from"h3";import{createNotFoundError as t,isHttpError a
|
|
|
141
141
|
${e.description?`<meta name="description" content="${v(String(e.description))}">`:``}
|
|
142
142
|
</head>
|
|
143
143
|
<body>
|
|
144
|
-
`}function x(e,t){let
|
|
144
|
+
`}function x(e,t){let r=e.default;if(r&&typeof r==`function`)try{let e=r(t);if(e&&typeof e.then==`function`){let e=r.name||`Page`;return` <div id="app" data-page="${v(String(e))}" data-props='${v(JSON.stringify(t))}'>
|
|
145
145
|
<!-- Async component — awaiting hydration -->
|
|
146
|
-
</div>\n`}return` <div id="app">${
|
|
146
|
+
</div>\n`}return` <div id="app">${n(e)}</div>\n`}catch(e){console.error(`[streaming] Error rendering page component:`,e)}let i=e.default?.name||`Page`;return` <div id="app" data-page="${v(String(i))}" data-props='${v(JSON.stringify(t))}'>
|
|
147
147
|
<!-- Component render fallback -->
|
|
148
148
|
</div>\n`}function S(){return` </body>
|
|
149
149
|
</html>`}function C(e){let t=process.env.NODE_ENV!==`production`,n=e.stack?`<pre style="
|
|
@@ -181,4 +181,4 @@ import{getRequestURL as e}from"h3";import{createNotFoundError as t,isHttpError a
|
|
|
181
181
|
</details>
|
|
182
182
|
`:``}
|
|
183
183
|
</div>
|
|
184
|
-
`}export function createStreamingResponse(e,t={}){let n=new Headers({"Content-Type":`text/html; charset=utf-8`,"Transfer-Encoding":`chunked`,...t.headers});return new Response(e,{status:t.status||200,headers:n})}function w(e,t,n){return async()=>(e.value??=await r({baseDir:t,devMode:n}),e.value)}function T(e,t,n){return async(r,i)=>e?
|
|
184
|
+
`}export function createStreamingResponse(e,t={}){let n=new Headers({"Content-Type":`text/html; charset=utf-8`,"Transfer-Encoding":`chunked`,...t.headers});return new Response(e,{status:t.status||200,headers:n})}function w(e,t,n){return async()=>(e.value??=await r({baseDir:t,devMode:n}),e.value)}function T(e,t,n){return async(r,i)=>e?o(r,i,t):createErrorResponse(r,n)}export function createNitroRenderer(e){let{avalonConfig:t,isDev:n=!1,enableCustomErrorPages:r=!0}=e,o={isDev:n,avalonConfig:t,loadPageModule:e.loadPageModule,pagesDir:t.pagesDir};r&&a(o).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let c=w({value:null},t.srcDir||`src`,n),d=T(r,o,n);return async function(r){let a=getRequestURL(r).pathname;try{let o=await i(r,await c(),{devMode:n});if(o)return n&&console.log(`[renderer] Middleware terminated request for ${a}`),o;let u=r.context.route,f=null;if(f=u||(e.resolvePageRoute?await e.resolvePageRoute(a,t.pagesDir):await E(a,t.pagesDir)),!f)return d(s(`Page not found: ${a}`),r);let m=e.loadPageModule?await e.loadPageModule(f.filePath):await D(f.filePath),h=createRenderContext(r,r.context.params||f.params);if(e.resolveLayouts&&(h.layoutContext={layouts:await e.resolveLayouts(a,t)}),t.streaming){let e=await renderPageStream(m,h,{onShellReady:()=>{setResponseHeader(r,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let t=await renderPage(m,h,{},e.wrapWithLayouts),r=injectHydrationScript(t.html,n);return new Response(r,{status:t.statusCode,headers:t.headers})}}catch(e){return console.error(`[Nitro Renderer Error]`,e),d(e instanceof Error?e:Error(String(e)),r)}}}async function E(e,t){return e===`/`||e===``?{filePath:`src/pages/index.tsx`,pattern:`/`,params:{}}:{filePath:`src/pages/${e.replace(/^\//,``).replace(/\/$/,``)}.tsx`,pattern:e,params:{}}}async function D(e){return{default:()=>null,metadata:{title:`Avalon Page`}}}export function createNitroCatchAllRenderer(e){let{avalonConfig:t,isDev:n=!1,loadPageModule:r,resolveLayouts:o,enableCustomErrorPages:c=!0}=e,d={isDev:n,avalonConfig:t,loadPageModule:r,pagesDir:t.pagesDir};c&&a(d).catch(e=>{console.warn(`[renderer] Failed to discover error pages:`,e)});let f=w({value:null},t.srcDir||`src`,n),m=T(c,d,n);return async function(a){let c=getRequestURL(a).pathname;try{let u=await i(a,await f(),{devMode:n});if(u)return n&&console.log(`[renderer] Middleware terminated request for ${c}`),u;let d=a.context.params||{},h=d.slug||c.replace(/^\//,``)||`index`,g=`${t.pagesDir}/${h}.tsx`,_;try{_=await r(g)}catch(e){try{_=await r(`${t.pagesDir}/${h}/index.tsx`)}catch(r){return n&&(console.debug(`[renderer] Page not found: ${g}`,e),console.debug(`[renderer] Index fallback not found: ${t.pagesDir}/${h}/index.tsx`,r)),m(s(`Page not found: ${c}`),a)}}let v=createRenderContext(a,d);if(o&&(v.layoutContext={layouts:await o(c,t)}),t.streaming){let e=await renderPageStream(_,v,{onShellReady:()=>{setResponseHeader(a,`Content-Type`,`text/html; charset=utf-8`)}});return new Response(e,{headers:{"Content-Type":`text/html; charset=utf-8`}})}else{let t=await renderPage(_,v,{},e.wrapWithLayouts),r=injectHydrationScript(t.html,n);return new Response(r,{status:t.statusCode,headers:t.headers})}}catch(e){return console.error(`[Nitro Catch-All Renderer Error]`,e),m(e instanceof Error?e:Error(String(e)),a)}}}export{clearMiddlewareCache as clearRendererMiddlewareCache}from"../middleware/index.js";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { IslandState } from "../schemas/layout.ts";
|
|
2
|
+
export declare function serialize(state: IslandState): string;
|
|
3
|
+
export declare function deserialize(serializedState: string): IslandState;
|
|
4
|
+
export declare function validate(state: IslandState): {
|
|
5
|
+
valid: boolean;
|
|
6
|
+
errors: string[];
|
|
7
|
+
};
|
|
8
|
+
export declare function clone(state: IslandState): IslandState;
|
|
9
|
+
export declare function equals(state1: IslandState, state2: IslandState): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(t){if(t==null)return null;if(t instanceof Date)return{__type:`Date`,__value:t.toISOString()};if(t instanceof RegExp)return{__type:`RegExp`,__value:{source:t.source,flags:t.flags}};if(t instanceof Map)return{__type:`Map`,__value:Array.from(t.entries()).map(([t,n])=>[e(t),e(n)])};if(t instanceof Set)return{__type:`Set`,__value:Array.from(t.values()).map(t=>e(t))};if(typeof t==`function`)return null;if(Array.isArray(t))return t.map(t=>e(t));if(typeof t==`object`){let n={},r=t;for(let t in r)Object.hasOwn(r,t)&&(n[t]=e(r[t]));return n}return t}function t(e,t){if(t&&typeof t==`object`){let e=t;if(e.__type&&e.__value!==void 0)switch(e.__type){case`Date`:return new Date(e.__value);case`RegExp`:{let t=e.__value;return new RegExp(t.source,t.flags)}case`Map`:return new Map(e.__value);case`Set`:return new Set(e.__value);default:return e.__value}}return t}export function serialize(t){try{let n=e(t);return JSON.stringify(n)}catch(e){throw Error(`State serialization failed: ${e instanceof Error?e.message:String(e)}`)}}export function deserialize(e){try{return JSON.parse(e,t)}catch(e){throw Error(`State deserialization failed: ${e instanceof Error?e.message:String(e)}`)}}export function validate(e){let t=[];try{let i=serialize(e),a=new Blob([i]).size;a>5*1024*1024&&t.push(`Serialized state size (${Math.round(a/1024)}KB) exceeds 5MB limit`),deserialize(i)}catch(e){t.push(e instanceof Error?e.message:String(e))}return{valid:t.length===0,errors:t}}export function clone(e){try{return deserialize(serialize(e))}catch{return{...e}}}export function equals(e,t){try{return serialize(e)===serialize(t)}catch{return!1}}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `useState` that survives page navigations.
|
|
3
|
+
*
|
|
4
|
+
* State is serialized to sessionStorage (or localStorage) via
|
|
5
|
+
* {@link serialize}/{@link deserialize}, so Date, Map, Set, and RegExp are preserved.
|
|
6
|
+
* On the server or when storage is unavailable, falls back to in-memory state.
|
|
7
|
+
*
|
|
8
|
+
* @param id - Unique key for this piece of state.
|
|
9
|
+
* @param initialValue - Default value when nothing is stored yet.
|
|
10
|
+
* @param options - Optional `{ storage: 'session' | 'local' }`. Defaults to `'session'`.
|
|
11
|
+
* @returns `[value, setValue, clearValue]` — same shape as `useState` plus a clear function.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { usePersistentState } from '@useavalon/avalon';
|
|
16
|
+
*
|
|
17
|
+
* function Counter() {
|
|
18
|
+
* const [count, setCount, clearCount] = usePersistentState('my-counter', 0);
|
|
19
|
+
* return (
|
|
20
|
+
* <div>
|
|
21
|
+
* <p>{count}</p>
|
|
22
|
+
* <button onClick={() => setCount(c => c + 1)}>+1</button>
|
|
23
|
+
* <button onClick={clearCount}>Reset</button>
|
|
24
|
+
* </div>
|
|
25
|
+
* );
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function usePersistentState<T>(id: string, initialValue: T, options?: {
|
|
30
|
+
storage?: "session" | "local";
|
|
31
|
+
}): [T, (value: T | ((prev: T) => T)) => void, () => void];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{useCallback as e,useEffect as t,useState as n}from"preact/hooks";import{deserialize as r,serialize as i}from"./island-state-serializer.js";export function usePersistentState(a,o,s){let c=s?.storage??`session`,l=`avalon-island:${a}`,[u,d]=n(()=>{if(globalThis.window===void 0)return o;try{let e=(c===`local`?localStorage:sessionStorage).getItem(l);return e===null?o:r(e).v??o}catch{return o}});return t(()=>{if(globalThis.window!==void 0)try{(c===`local`?localStorage:sessionStorage).setItem(l,i({v:u}))}catch{}},[u,l,c]),[u,e(e=>{d(t=>typeof e==`function`?e(t):e)},[]),e(()=>{if(d(o),globalThis.window!==void 0)try{(c===`local`?localStorage:sessionStorage).removeItem(l)}catch{}},[o,l,c])]}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* This approach avoids dependency issues (e.g. undici, platform-specific
|
|
8
8
|
* modules) that occur when importing the server bundle directly.
|
|
9
9
|
*/
|
|
10
|
-
import type { PrerenderConfig } from
|
|
10
|
+
import type { PrerenderConfig } from "./index.ts";
|
|
11
11
|
/**
|
|
12
12
|
* Prerender routes by spawning the built server and fetching each route via HTTP.
|
|
13
13
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{spawn as e}from"node:child_process";import{existsSync as t,mkdirSync as n,writeFileSync as r}from"node:fs";import{dirname as i,join as a,resolve as o}from"node:path";function s(e){let t=[],n=/<a\s[^>]*href=["']([^"'#?]+)/gi,r=n.exec(e);for(;r!==null;){let i=r[1];if(i.startsWith(`/`)&&!i.startsWith(`//`)){if(i.startsWith(`/assets/`)||i.startsWith(`/islands/`)||i.startsWith(`/chunks/`)||i.startsWith(`/_`)||i.match(/\.\w{2,5}$/))continue;t.push(i)}r=n.exec(e)}return[...new Set(t)]}function c(e,t){for(let n of t)if(typeof n==`string`){if(e===n||n.endsWith(`/**`)&&e.startsWith(n.slice(0,-2)))return!0}else if(n instanceof RegExp){if(n.test(e))return!0}else if(typeof n==`function`&&n(e))return!0;return!1}async function l(e,t=15e3){let n=Date.now();for(;Date.now()-n<t;){try{let t=await fetch(`${e}/`);if(t.ok||t.status<500)return}catch{}await new Promise(e=>setTimeout(e,200))}throw Error(`[prerender] Server did not become ready within ${t}ms`)}export async function prerenderRoutes(u){let{serverEntryPath:d,outputDir:f,routes:p=[`/`],crawlLinks:m=!1,ignore:h=[],concurrency:g=4,failOnError:_=!1,autoSubfolderIndex:v=!0,retry:y=3,retryDelay:b=500,port:x=13172}=u,S=o(d);if(!t(S))throw Error(`[prerender] Server entry not found: ${S}`);let C=o(f),w=`http://localhost:${x}`;console.log(`[prerender] Spawning server from ${d} on port ${x}...`);let T=null;try{T=e(`node`,[S],{env:{...process.env,PORT:String(x),NITRO_PORT:String(x),HOST:`127.0.0.1`,NITRO_HOST:`127.0.0.1`,NODE_ENV:`production`},stdio:[`ignore`,`pipe`,`pipe`]}),T.stdout?.on(`data`,e=>{let t=e.toString().trim();t&&console.log(`[prerender:server] ${t}`)}),T.stderr?.on(`data`,e=>{let t=e.toString().trim();t&&console.error(`[prerender:server:err] ${t}`)}),await l(w),console.log(`[prerender] Server ready at ${w}`)}catch(e){T?.kill(`SIGKILL`);let t=e instanceof Error?e.message:String(e);throw Error(`[prerender] Failed to start server: ${t}`)}let E=[],D=[],O=new Set,k=[...p];console.log(`[prerender] Starting with ${k.length} route(s), crawlLinks=${m}`);async function A(e){for(let t=1;t<=y;t++)try{let t=await fetch(`${w}${e}`);return{html:await t.text(),status:t.status}}catch(n){let r=n instanceof Error?n.message:String(n);if(t<y)console.warn(`[prerender] Retry ${t}/${y} for ${e}: ${r}`),await new Promise(e=>setTimeout(e,b));else return console.error(`[prerender] All ${y} attempts failed for ${e}: ${r}`),null}return null}try{for(;k.length>0;){let e=k.splice(0,g);await Promise.all(e.map(async e=>{let t=e.endsWith(`/`)&&e!==`/`?e.slice(0,-1):e;if(O.has(t))return;if(O.add(t),c(t,h)){console.log(`[prerender] ⏭ ${t} (ignored)`);return}let o=await A(t);if(!o){let e=`Failed to fetch ${t} after ${y} attempts`;if(console.error(`[prerender] ❌ ${e}`),D.push({route:t,error:e}),_)throw Error(e);return}if(o.status>=400){let e=`${t} returned ${o.status}`;if(console.error(`[prerender] ❌ ${e}`),D.push({route:t,error:e}),_)throw Error(e);return}let l=v?a(t,`index.html`):`${t}.html`,u=a(C,l);if(n(i(u),{recursive:!0}),r(u,o.html),E.push(t),console.log(`[prerender] ✅ ${t} → ${l}`),m){let e=s(o.html);for(let t of e){let e=t.endsWith(`/`)&&t!==`/`?t.slice(0,-1):t;!O.has(e)&&!c(e,h)&&k.push(e)}}}))}}finally{T&&(console.log(`[prerender] Shutting down server...`),T.kill(`SIGKILL`))}return console.log(`[prerender] Done: ${E.length} page(s) prerendered`+(D.length>0?`, ${D.length} error(s)`:``)),{prerenderedRoutes:E,errors:D}}
|
|
@@ -23,9 +23,9 @@ export declare const ScriptConfigSchema: z.ZodUnion<readonly [z.ZodString, z.Zod
|
|
|
23
23
|
integrity: z.ZodOptional<z.ZodString>;
|
|
24
24
|
nomodule: z.ZodOptional<z.ZodBoolean>;
|
|
25
25
|
referrerpolicy: z.ZodOptional<z.ZodEnum<{
|
|
26
|
+
origin: "origin";
|
|
26
27
|
"no-referrer": "no-referrer";
|
|
27
28
|
"no-referrer-when-downgrade": "no-referrer-when-downgrade";
|
|
28
|
-
origin: "origin";
|
|
29
29
|
"origin-when-cross-origin": "origin-when-cross-origin";
|
|
30
30
|
"same-origin": "same-origin";
|
|
31
31
|
"strict-origin": "strict-origin";
|
|
@@ -53,9 +53,9 @@ export declare const RenderOptionsSchema: z.ZodObject<{
|
|
|
53
53
|
integrity: z.ZodOptional<z.ZodString>;
|
|
54
54
|
nomodule: z.ZodOptional<z.ZodBoolean>;
|
|
55
55
|
referrerpolicy: z.ZodOptional<z.ZodEnum<{
|
|
56
|
+
origin: "origin";
|
|
56
57
|
"no-referrer": "no-referrer";
|
|
57
58
|
"no-referrer-when-downgrade": "no-referrer-when-downgrade";
|
|
58
|
-
origin: "origin";
|
|
59
59
|
"origin-when-cross-origin": "origin-when-cross-origin";
|
|
60
60
|
"same-origin": "same-origin";
|
|
61
61
|
"strict-origin": "strict-origin";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { ComponentChildren } from "preact";
|
|
2
|
+
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* Layout Context Schema - Contains request information and state for layout processing
|
|
5
5
|
*/
|
|
@@ -108,7 +108,7 @@ export declare const PersistentIslandContextSchema: z.ZodObject<{
|
|
|
108
108
|
* Layout Error Info Schema
|
|
109
109
|
*/
|
|
110
110
|
export declare const LayoutErrorInfoSchema: z.ZodObject<{
|
|
111
|
-
layoutPath: z.ZodString
|
|
111
|
+
layoutPath: z.ZodOptional<z.ZodString>;
|
|
112
112
|
errorType: z.ZodEnum<{
|
|
113
113
|
island: "island";
|
|
114
114
|
component: "component";
|
|
@@ -132,10 +132,10 @@ export declare const LayoutErrorBoundaryPropsSchema: z.ZodObject<{
|
|
|
132
132
|
*/
|
|
133
133
|
export declare const ErrorRecoveryStrategySchema: z.ZodObject<{
|
|
134
134
|
type: z.ZodEnum<{
|
|
135
|
-
redirect: "redirect";
|
|
136
|
-
skip: "skip";
|
|
137
135
|
fallback: "fallback";
|
|
138
136
|
retry: "retry";
|
|
137
|
+
skip: "skip";
|
|
138
|
+
redirect: "redirect";
|
|
139
139
|
}>;
|
|
140
140
|
maxRetries: z.ZodOptional<z.ZodNumber>;
|
|
141
141
|
fallbackComponent: z.ZodOptional<z.ZodAny>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as e}from"zod";export const LayoutContextSchema=e.object({request:e.instanceof(Request),params:e.record(e.string(),e.string()),query:e.instanceof(URLSearchParams),state:e.instanceof(Map),middlewareContext:e.any().optional()});export const LayoutDataSchema=e.record(e.string(),e.unknown());export const LayoutRouteSchema=e.object({pattern:e.instanceof(URLPattern),layoutPath:e.string().min(1),priority:e.number().int().min(0),type:e.enum([`root`,`nested`]),depth:e.number().int().min(0)});export const LayoutHandlerSchema=e.object({component:e.any(),loader:e.any().optional(),path:e.string().min(1),priority:e.number().int().min(0)});export const LayoutPropsSchema=e.object({children:e.any(),data:LayoutDataSchema,frontmatter:e.record(e.string(),e.any()).optional(),route:e.object({path:e.string(),params:e.record(e.string(),e.string()),query:e.instanceof(URLSearchParams)})});export const LayoutDiscoveryOptionsSchema=e.object({baseDirectory:e.string().min(1),filePattern:e.string().min(1).optional().default(`_layout.tsx`),excludeDirectories:e.array(e.string()).optional().default([]),enableWatching:e.boolean().optional().default(!1),developmentMode:e.boolean().optional().default(!1)});export const RouteInfoSchema=e.object({path:e.string(),params:e.record(e.string(),e.string()),method:e.string(),headers:e.instanceof(Headers)});export const LayoutRuleSchema=e.object({matches:e.any(),apply:e.boolean(),priority:e.number().int()});export const LayoutConfigSchema=e.object({skipLayouts:e.array(e.string()).optional(),replaceLayout:e.boolean().optional(),onlyLayouts:e.array(e.string()).optional(),customLayout:e.string().optional()});export const IslandStateSchema=e.record(e.string(),e.unknown());export const PersistentIslandPropsSchema=e.object({persistentId:e.string().min(1),children:e.any()});export const PersistentIslandContextSchema=e.object({saveState:e.any(),loadState:e.any(),clearState:e.any()});export const LayoutErrorInfoSchema=e.object({layoutPath:e.string(),errorType:e.enum([`component`,`loader`,`rendering`,`island`]),timestamp:e.number().int().positive(),componentStack:e.string().optional(),errorBoundary:e.string().optional()});export const LayoutErrorBoundaryPropsSchema=e.object({children:e.any(),fallback:e.any(),onError:e.any().optional()});export const ErrorRecoveryStrategySchema=e.object({type:e.enum([`retry`,`fallback`,`skip`,`redirect`]),maxRetries:e.number().int().positive().optional(),fallbackComponent:e.any().optional(),redirectUrl:e.url().optional()});export const StreamingLayoutPropsSchema=e.object({children:e.any(),fallback:e.any().optional(),priority:e.enum([`high`,`medium`,`low`]).default(`medium`)});export const StreamingComponentSchema=e.object({component:e.any(),fallback:e.any(),priority:e.number().int().min(0),isReady:e.any()});export const ResolvedLayoutSchema=e.object({handlers:e.array(LayoutHandlerSchema),dataLoaders:e.array(e.any()),errorBoundaries:e.array(e.any()),streamingComponents:e.array(StreamingComponentSchema),metadata:e.object({totalLayouts:e.number().int().min(0),resolutionTime:e.number().positive(),cacheHit:e.boolean()})});export const LayoutCacheSchema=e.object({resolved:e.instanceof(Map),handlers:e.instanceof(Map),data:e.instanceof(Map),ttl:e.instanceof(Map)});export const EnhancedLayoutContextSchema=LayoutContextSchema.extend({layouts:e.array(LayoutHandlerSchema),parentData:e.array(LayoutDataSchema),islandStates:e.instanceof(Map),streamingEnabled:e.boolean(),errorBoundaries:e.array(e.any())});
|
|
1
|
+
import{z as e}from"zod";export const LayoutContextSchema=e.object({request:e.instanceof(Request),params:e.record(e.string(),e.string()),query:e.instanceof(URLSearchParams),state:e.instanceof(Map),middlewareContext:e.any().optional()});export const LayoutDataSchema=e.record(e.string(),e.unknown());export const LayoutRouteSchema=e.object({pattern:e.instanceof(URLPattern),layoutPath:e.string().min(1),priority:e.number().int().min(0),type:e.enum([`root`,`nested`]),depth:e.number().int().min(0)});export const LayoutHandlerSchema=e.object({component:e.any(),loader:e.any().optional(),path:e.string().min(1),priority:e.number().int().min(0)});export const LayoutPropsSchema=e.object({children:e.any(),data:LayoutDataSchema,frontmatter:e.record(e.string(),e.any()).optional(),route:e.object({path:e.string(),params:e.record(e.string(),e.string()),query:e.instanceof(URLSearchParams)})});export const LayoutDiscoveryOptionsSchema=e.object({baseDirectory:e.string().min(1),filePattern:e.string().min(1).optional().default(`_layout.tsx`),excludeDirectories:e.array(e.string()).optional().default([]),enableWatching:e.boolean().optional().default(!1),developmentMode:e.boolean().optional().default(!1)});export const RouteInfoSchema=e.object({path:e.string(),params:e.record(e.string(),e.string()),method:e.string(),headers:e.instanceof(Headers)});export const LayoutRuleSchema=e.object({matches:e.any(),apply:e.boolean(),priority:e.number().int()});export const LayoutConfigSchema=e.object({skipLayouts:e.array(e.string()).optional(),replaceLayout:e.boolean().optional(),onlyLayouts:e.array(e.string()).optional(),customLayout:e.string().optional()});export const IslandStateSchema=e.record(e.string(),e.unknown());export const PersistentIslandPropsSchema=e.object({persistentId:e.string().min(1),children:e.any()});export const PersistentIslandContextSchema=e.object({saveState:e.any(),loadState:e.any(),clearState:e.any()});export const LayoutErrorInfoSchema=e.object({layoutPath:e.string().optional(),errorType:e.enum([`component`,`loader`,`rendering`,`island`]),timestamp:e.number().int().positive(),componentStack:e.string().optional(),errorBoundary:e.string().optional()});export const LayoutErrorBoundaryPropsSchema=e.object({children:e.any(),fallback:e.any(),onError:e.any().optional()});export const ErrorRecoveryStrategySchema=e.object({type:e.enum([`retry`,`fallback`,`skip`,`redirect`]),maxRetries:e.number().int().positive().optional(),fallbackComponent:e.any().optional(),redirectUrl:e.url().optional()});export const StreamingLayoutPropsSchema=e.object({children:e.any(),fallback:e.any().optional(),priority:e.enum([`high`,`medium`,`low`]).default(`medium`)});export const StreamingComponentSchema=e.object({component:e.any(),fallback:e.any(),priority:e.number().int().min(0),isReady:e.any()});export const ResolvedLayoutSchema=e.object({handlers:e.array(LayoutHandlerSchema),dataLoaders:e.array(e.any()),errorBoundaries:e.array(e.any()),streamingComponents:e.array(StreamingComponentSchema),metadata:e.object({totalLayouts:e.number().int().min(0),resolutionTime:e.number().positive(),cacheHit:e.boolean()})});export const LayoutCacheSchema=e.object({resolved:e.instanceof(Map),handlers:e.instanceof(Map),data:e.instanceof(Map),ttl:e.instanceof(Map)});export const EnhancedLayoutContextSchema=LayoutContextSchema.extend({layouts:e.array(LayoutHandlerSchema),parentData:e.array(LayoutDataSchema),islandStates:e.instanceof(Map),streamingEnabled:e.boolean(),errorBoundaries:e.array(e.any())});
|
|
@@ -3,7 +3,7 @@ export declare const routingValidators: {
|
|
|
3
3
|
readonly fileSystemRoute: (data: unknown) => {
|
|
4
4
|
pattern: any;
|
|
5
5
|
filePath: string;
|
|
6
|
-
routeType: "
|
|
6
|
+
routeType: "group" | "static" | "index" | "dynamic" | "catch-all";
|
|
7
7
|
dynamicSegments: string[];
|
|
8
8
|
priority: number;
|
|
9
9
|
isPrivate: boolean;
|
|
@@ -93,7 +93,7 @@ export declare const safeRoutingValidators: {
|
|
|
93
93
|
readonly fileSystemRoute: (data: unknown) => import("../index.ts").ValidationResult<{
|
|
94
94
|
pattern: any;
|
|
95
95
|
filePath: string;
|
|
96
|
-
routeType: "
|
|
96
|
+
routeType: "group" | "static" | "index" | "dynamic" | "catch-all";
|
|
97
97
|
dynamicSegments: string[];
|
|
98
98
|
priority: number;
|
|
99
99
|
isPrivate: boolean;
|