@useavalon/avalon 0.1.93-canary.1 → 0.1.94-canary.1

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 CHANGED
@@ -1,4 +1,8 @@
1
1
  export type { Integration, IntegrationConfig, RenderParams as IntegrationRenderParams, RenderResult, } from "@useavalon/core";
2
+ export { ACTION_ERROR_STATUS, ActionError, type ActionErrorOptions, createActionClient, defineAction, isAction, isActionError, } from "./src/actions/define.ts";
3
+ export type { AcceptMode, Action, ActionClient, ActionClientOptions, ActionConfig, ActionContext, ActionErrorCode, ActionNamespace, ActionResult, SerializedActionError, } from "./src/actions/types.ts";
4
+ export type { ActionsTypeGenerationResult } from "./src/build/actions-types-generator.ts";
5
+ export { findActionsEntryInfo, generateActionTypes, getActionsWatchDir, } from "./src/build/actions-types-generator.ts";
2
6
  export type { ExtendedIslandEntry, ExtendedIslandManifest, IslandEntry, IslandManifest, } from "./src/build/island-manifest.ts";
3
7
  export { generateIslandManifest, getIslandBundlePath, loadIslandManifest, } from "./src/build/island-manifest.ts";
4
8
  export type { IslandTypeGeneratorOptions, TypeGenerationResult, } from "./src/build/island-types-generator.ts";
package/dist/mod.js CHANGED
@@ -1 +1 @@
1
- export{generateIslandManifest,getIslandBundlePath,loadIslandManifest}from"./src/build/island-manifest.js";export{generateIslandTypes,watchAndGenerateTypes}from"./src/build/island-types-generator.js";export{mdxIslandTransform}from"./src/build/mdx-island-transform.js";export{pageIslandTransform}from"./src/build/page-island-transform.js";export{registry as integrationRegistry}from"./src/core/integrations/registry.js";export{registerBuiltinDirectives}from"./src/islands/builtin-directives.js";export{analyzeComponentFile,renderComponentSSROnly}from"./src/islands/component-analysis.js";export{addSvelteSSRCSS,clearSvelteComponentCSS,generateComponentScopeId,getSvelteComponentCSS,getSvelteSSRCSS,getSvelteSSRCSSForHead,getSvelteSSRCSSStats}from"./src/islands/css-utils.js";export{createIslandRegistry,createIslandResolver,createIslandValidator,createIslandWatcher,DEFAULT_DISCOVERY_CONFIG,discoverAllIslands,discoverIslandDirectories,discoverIslandsInDirectory,formatCircularDependency,formatValidationError,formatValidationResult,formatValidationWarning,getDefaultIslandsPath,getQualifiedIslandName,hasDefaultIslandsDirectory,ISLAND_FILE_EXTENSIONS,IslandRegistry,IslandResolver,IslandValidator,IslandWatcher,isIslandsDirectory,isSupportedIslandExtension,parseQualifiedIslandName,validateAllIslands}from"./src/islands/discovery/index.js";export{detectFramework,detectFrameworkFromSrc,resolveIslandPath}from"./src/islands/framework-detection.js";export{getDirective,getRegisteredDirectives,isCustomDirective,registerHydrationDirective,unregisterHydrationDirective}from"./src/islands/hydration-directives.js";export{DEFAULT_PRELOAD_FRAMEWORKS,detectAndLoadIntegration,detectFrameworksFromPageContent,loadIntegration,preloadIntegrations}from"./src/islands/integration-loader.js";export{default as Island,renderIsland}from"./src/islands/island.js";export{clearCache,clearIslandCache,configureCache,getCacheConfig,getCacheStats,invalidateCacheForFile,invalidateCacheForPath,logCacheStats}from"./src/islands/render-cache.js";export{renderToHtml}from"./src/render/ssr.js";export{createNitroCoordinationPlugin,createNitroIntegration,createVirtualModulesPlugin,getAvalonConfig,getViteDevServer,isDevelopmentMode,RESOLVED_VIRTUAL_IDS,VIRTUAL_MODULE_IDS}from"./src/vite-plugin/nitro-integration.js";export{avalon,getLayoutsDir,getNitroConfig,getPagesDir,getResolvedConfig,isNitroEnabled}from"./src/vite-plugin/plugin.js";export async function build(e){throw Error("avalon build() is not available in the published package. Use `vite build` or the Avalon CLI instead.")}export{IslandErrorBoundary,withIslandErrorBoundary}from"./src/components/IslandErrorBoundary.js";export{LayoutErrorBoundary}from"./src/components/LayoutErrorBoundary.js";export*from"./src/layout-system.js";export{clearDiscoveryCache,clearMiddlewareCache,discoverScopedMiddleware,executeScopedMiddleware,getContextValue,getMatchingMiddleware,getMiddlewareCacheSize,hasContextValue,invalidateMiddleware,setContextValue}from"./src/middleware/index.js";export{usePersistentState}from"./src/persistence/use-persistent-state.js";
1
+ export{ACTION_ERROR_STATUS,ActionError,createActionClient,defineAction,isAction,isActionError}from"./src/actions/define.js";export{findActionsEntryInfo,generateActionTypes,getActionsWatchDir}from"./src/build/actions-types-generator.js";export{generateIslandManifest,getIslandBundlePath,loadIslandManifest}from"./src/build/island-manifest.js";export{generateIslandTypes,watchAndGenerateTypes}from"./src/build/island-types-generator.js";export{mdxIslandTransform}from"./src/build/mdx-island-transform.js";export{pageIslandTransform}from"./src/build/page-island-transform.js";export{registry as integrationRegistry}from"./src/core/integrations/registry.js";export{registerBuiltinDirectives}from"./src/islands/builtin-directives.js";export{analyzeComponentFile,renderComponentSSROnly}from"./src/islands/component-analysis.js";export{addSvelteSSRCSS,clearSvelteComponentCSS,generateComponentScopeId,getSvelteComponentCSS,getSvelteSSRCSS,getSvelteSSRCSSForHead,getSvelteSSRCSSStats}from"./src/islands/css-utils.js";export{createIslandRegistry,createIslandResolver,createIslandValidator,createIslandWatcher,DEFAULT_DISCOVERY_CONFIG,discoverAllIslands,discoverIslandDirectories,discoverIslandsInDirectory,formatCircularDependency,formatValidationError,formatValidationResult,formatValidationWarning,getDefaultIslandsPath,getQualifiedIslandName,hasDefaultIslandsDirectory,ISLAND_FILE_EXTENSIONS,IslandRegistry,IslandResolver,IslandValidator,IslandWatcher,isIslandsDirectory,isSupportedIslandExtension,parseQualifiedIslandName,validateAllIslands}from"./src/islands/discovery/index.js";export{detectFramework,detectFrameworkFromSrc,resolveIslandPath}from"./src/islands/framework-detection.js";export{getDirective,getRegisteredDirectives,isCustomDirective,registerHydrationDirective,unregisterHydrationDirective}from"./src/islands/hydration-directives.js";export{DEFAULT_PRELOAD_FRAMEWORKS,detectAndLoadIntegration,detectFrameworksFromPageContent,loadIntegration,preloadIntegrations}from"./src/islands/integration-loader.js";export{default as Island,renderIsland}from"./src/islands/island.js";export{clearCache,clearIslandCache,configureCache,getCacheConfig,getCacheStats,invalidateCacheForFile,invalidateCacheForPath,logCacheStats}from"./src/islands/render-cache.js";export{renderToHtml}from"./src/render/ssr.js";export{createNitroCoordinationPlugin,createNitroIntegration,createVirtualModulesPlugin,getAvalonConfig,getViteDevServer,isDevelopmentMode,RESOLVED_VIRTUAL_IDS,VIRTUAL_MODULE_IDS}from"./src/vite-plugin/nitro-integration.js";export{avalon,getLayoutsDir,getNitroConfig,getPagesDir,getResolvedConfig,isNitroEnabled}from"./src/vite-plugin/plugin.js";export async function build(e){throw Error("avalon build() is not available in the published package. Use `vite build` or the Avalon CLI instead.")}export{IslandErrorBoundary,withIslandErrorBoundary}from"./src/components/IslandErrorBoundary.js";export{LayoutErrorBoundary}from"./src/components/LayoutErrorBoundary.js";export*from"./src/layout-system.js";export{clearDiscoveryCache,clearMiddlewareCache,discoverScopedMiddleware,executeScopedMiddleware,getContextValue,getMatchingMiddleware,getMiddlewareCacheSize,hasContextValue,invalidateMiddleware,setContextValue}from"./src/middleware/index.js";export{usePersistentState}from"./src/persistence/use-persistent-state.js";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Server Actions — typed client proxy.
3
+ *
4
+ * `createActionClient<typeof server>()` returns a Proxy whose property accesses
5
+ * mirror the `server` export. Calling an action POSTs to `/_actions/<name>` and
6
+ * resolves to an {@link ActionResult}. The proxy never throws for action-level
7
+ * failures — network/parse errors also resolve to an error result.
8
+ *
9
+ * This module contains ONLY the fetch proxy (no handler source), so it is safe
10
+ * to include in the browser bundle.
11
+ *
12
+ * @module actions/client
13
+ */
14
+ import type { ActionClient, ActionClientOptions } from "./types.ts";
15
+ /**
16
+ * Creates a typed client proxy for calling server actions.
17
+ *
18
+ * @typeParam T - The `server` export type (for inference).
19
+ * @param options - Optional base URL / custom fetch.
20
+ */
21
+ export declare function createActionClient<T = Record<string, never>>(options?: ActionClientOptions): ActionClient<T>;
@@ -0,0 +1 @@
1
+ import{ActionError as e}from"./define.js";import{parseClientResult as t}from"./serialization.js";async function n(n,r,i,a){let o=`${n}/${i}`;try{let e,n={};return a instanceof FormData?e=a:a!==void 0&&(e=JSON.stringify(a),n[`Content-Type`]=`application/json`),await t(await r(o,{method:`POST`,body:e,headers:n}))}catch(t){return{data:void 0,error:new e({code:`INTERNAL_SERVER_ERROR`,message:t instanceof Error?t.message:`Request failed`,cause:t})}}}export function createActionClient(e={}){let t=(e.baseUrl??`/_actions`).replace(/\/+$/,``),r=e.fetch??globalThis.fetch,i=e=>new Proxy((i=>n(t,r,e,i)),{get(t,n){return typeof n==`string`?i(e?`${e}.${n}`:n):void 0},apply(i,a,o){return n(t,r,e,o[0])}});return i(``)}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Server Actions — public API surface.
3
+ *
4
+ * Exports `defineAction` for declaring type-safe server functions, the
5
+ * `ActionError` class and `isActionError` guard for structured failures, and
6
+ * `createActionClient` for an explicitly-typed client proxy.
7
+ *
8
+ * Importable as `@useavalon/avalon/actions`.
9
+ *
10
+ * @module actions/define
11
+ */
12
+ import { type Action, type ActionConfig, type ActionErrorCode } from "./types.ts";
13
+ /** Maps each {@link ActionErrorCode} to its HTTP status code. */
14
+ export declare const ACTION_ERROR_STATUS: Record<ActionErrorCode, number>;
15
+ /** Options for constructing an {@link ActionError}. */
16
+ export interface ActionErrorOptions {
17
+ code: ActionErrorCode;
18
+ message?: string;
19
+ /** Per-field validation issues (for `BAD_REQUEST`). */
20
+ fields?: Record<string, string[]>;
21
+ /** Underlying cause. */
22
+ cause?: unknown;
23
+ }
24
+ /**
25
+ * A structured error thrown by (or returned from) an action. Carries a stable
26
+ * `code`, the derived HTTP `status`, and optional per-field validation issues.
27
+ */
28
+ export declare class ActionError extends Error {
29
+ readonly code: ActionErrorCode;
30
+ readonly status: number;
31
+ readonly fields?: Record<string, string[]>;
32
+ constructor(options: ActionErrorOptions);
33
+ /** Rebuilds an {@link ActionError} from a serialized wire format + status. */
34
+ static fromStatus(status: number, body: {
35
+ code?: string;
36
+ message?: string;
37
+ fields?: Record<string, string[]>;
38
+ } | undefined): ActionError;
39
+ }
40
+ /** Type guard for {@link ActionError}. */
41
+ export declare function isActionError(value: unknown): value is ActionError;
42
+ /**
43
+ * Defines a type-safe server action.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * export const server = {
48
+ * greet: defineAction({
49
+ * input: z.object({ name: z.string() }),
50
+ * handler: async ({ name }) => `Hello, ${name}!`,
51
+ * }),
52
+ * };
53
+ * ```
54
+ *
55
+ * @param config - The action's input schema, accept mode, and handler.
56
+ * @returns A branded {@link Action} for use under the `server` export.
57
+ */
58
+ export declare function defineAction<TInput, TOutput>(config: ActionConfig<TInput, TOutput>): Action<TInput, Awaited<TOutput>>;
59
+ export { createActionClient } from "./client.ts";
60
+ export { isAction } from "./registry.ts";
61
+ export type { AcceptMode, Action, ActionClient, ActionClientOptions, ActionConfig, ActionContext, ActionErrorCode, ActionNamespace, ActionResult, SerializedActionError, } from "./types.ts";
@@ -0,0 +1 @@
1
+ import{ACTION_MARKER as e}from"./types.js";export const ACTION_ERROR_STATUS={BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_ALLOWED:405,CONFLICT:409,UNSUPPORTED_MEDIA_TYPE:415,INTERNAL_SERVER_ERROR:500};const n=Object.fromEntries(Object.entries(ACTION_ERROR_STATUS).map(([e,t])=>[t,e]));export class ActionError extends Error{code;status;fields;constructor(e){super(e.message??i(e.code),{cause:e.cause}),this.name=`ActionError`,this.code=e.code,this.status=ACTION_ERROR_STATUS[e.code]??500,e.fields&&(this.fields=e.fields)}static fromStatus(e,t){return new ActionError({code:t?.code??n[e]??`INTERNAL_SERVER_ERROR`,message:t?.message,fields:t?.fields})}}function i(e){switch(e){case`BAD_REQUEST`:return`Bad request`;case`UNAUTHORIZED`:return`Unauthorized`;case`FORBIDDEN`:return`Forbidden`;case`NOT_FOUND`:return`Not found`;case`METHOD_NOT_ALLOWED`:return`Method not allowed`;case`CONFLICT`:return`Conflict`;case`UNSUPPORTED_MEDIA_TYPE`:return`Unsupported media type`;default:return`Internal server error`}}export function isActionError(e){return e instanceof ActionError}export function defineAction(t){let n=t.accept??`json`,r=async(e,n)=>await t.handler(e,n);return{[e]:!0,input:t.input,accept:n,handler:r}}export{createActionClient}from"./client.js";export{isAction}from"./registry.js";
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Server Actions — endpoint handler.
3
+ *
4
+ * Factory producing an H3/Nitro handler for `/_actions/:name`. Performs method
5
+ * guarding, action lookup, body parsing, Zod validation, handler execution, and
6
+ * error serialization — returning a JSON `{ data }` or `{ error }` response.
7
+ *
8
+ * @module actions/endpoint
9
+ */
10
+ import type { H3Event } from "h3";
11
+ import type { Action } from "./types.ts";
12
+ /** Options for {@link defineActionHandler}. */
13
+ export interface ActionHandlerOptions {
14
+ /** The flattened action registry (name → Action). */
15
+ registry: Map<string, Action>;
16
+ /** Whether running in development (controls error message exposure). */
17
+ isDev?: boolean;
18
+ }
19
+ /**
20
+ * Creates the action endpoint handler.
21
+ *
22
+ * @param options - Registry and dev flag.
23
+ * @returns An async H3 handler returning a web `Response`.
24
+ */
25
+ export declare function defineActionHandler(options: ActionHandlerOptions): (event: H3Event) => Promise<Response>;
@@ -0,0 +1 @@
1
+ import{ActionError as e}from"./define.js";import{getWebRequest as t,parseRequestInput as n,serializeError as r,zodIssuesToFields as i}from"./serialization.js";const a={"Content-Type":`application/json`};function o(e,t){return new Response(JSON.stringify(e),{status:t,headers:a})}export function defineActionHandler(t){let{registry:a,isDev:s=process.env.NODE_ENV!==`production`}=t;return async t=>{if(u(t).toUpperCase()!==`POST`)return o({error:{code:`METHOD_NOT_ALLOWED`,message:`Method not allowed`}},405);let l=d(t);if(!l)return o({error:{code:`BAD_REQUEST`,message:`Missing action name`}},400);let f=a.get(l);if(!f)return o({error:{code:`NOT_FOUND`,message:`Unknown action: ${l}`}},404);let p;try{p=await n(t,f.accept)}catch(e){let{status:t,body:n}=r(e,s);return o({error:n},t)}let m=p;if(f.input){let e=f.input.safeParse(p);if(!e.success)return o({error:{code:`BAD_REQUEST`,message:`Validation failed`,fields:i(e.error)}},400);m=e.data}let h=c(t);try{return o({data:await f.handler(m,h)},200)}catch(t){t instanceof e||console.error(`[actions] Handler error for`,l,t);let{status:n,body:i}=r(t,s);return o({error:i},n)}}}function c(e){let n=t(e),r=n?.headers??new Headers(e.node?.req?.headers??{}),i=r.get(`cookie`)??``;return{event:e,request:n,headers:r,cookies:{get:e=>l(i,e)}}}function l(e,t){if(e)for(let n of e.split(`;`)){let e=n.indexOf(`=`);if(e!==-1&&n.slice(0,e).trim()===t)return decodeURIComponent(n.slice(e+1).trim())}}function u(e){let n=t(e);return n?n.method:e.node?.req?.method??`GET`}function d(e){let t=e.context?.params;if(t?.name)return decodeURIComponent(String(t.name));let n=f(e),r=/\/_actions\/([^/?]+)/.exec(n);return r?decodeURIComponent(r[1]):void 0}function f(e){if(e.url)return e.url.pathname;let t=e.node?.req?.url;return t?new URL(t,`http://localhost`).pathname:`/`}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Server Actions — registry.
3
+ *
4
+ * Flattens a `server` export (a tree of actions and namespace objects) into a
5
+ * flat lookup map keyed by dotted name (e.g. `user.like`).
6
+ *
7
+ * @module actions/registry
8
+ */
9
+ import { type Action, type ActionNamespace } from "./types.ts";
10
+ /** Narrows an unknown value to an {@link Action} via the brand marker. */
11
+ export declare function isAction(value: unknown): value is Action;
12
+ /**
13
+ * Recursively flattens a `server` export into `Map<dottedName, Action>`.
14
+ *
15
+ * Nested plain objects become namespaces: `{ user: { like } }` yields the key
16
+ * `"user.like"`. Non-action, non-object values are ignored.
17
+ *
18
+ * @param server - The `server` export (or any sub-namespace).
19
+ * @param prefix - Internal accumulator for the dotted key path.
20
+ */
21
+ export declare function flattenActions(server: ActionNamespace | undefined | null, prefix?: string): Map<string, Action>;
@@ -0,0 +1 @@
1
+ import{ACTION_MARKER as e}from"./types.js";export function isAction(t){return typeof t==`object`&&!!t&&t[e]===!0}export function flattenActions(e,n=``){let r=new Map;if(!e||typeof e!=`object`)return r;for(let[i,a]of Object.entries(e)){let e=n?`${n}.${i}`:i;if(isAction(a))r.set(e,a);else if(a&&typeof a==`object`)for(let[t,n]of flattenActions(a,e))r.set(t,n)}return r}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Server Actions — Nitro route entry.
3
+ *
4
+ * Registered as the handler for `/_actions/**` by the Avalon Nitro integration.
5
+ * It statically imports the actions manifest virtual module so the user's action
6
+ * handlers are bundled into the Nitro server output (mirroring the server-islands
7
+ * route — NO `@vite-ignore` dynamic imports).
8
+ *
9
+ * @module actions/route
10
+ */
11
+ declare const handler: (event: import("h3").H3Event) => Promise<Response>;
12
+ export default handler;
@@ -0,0 +1 @@
1
+ import{server as e}from"virtual:avalon-actions-manifest";import{defineActionHandler as t}from"./endpoint.js";import{flattenActions as n}from"./registry.js";const r=t({registry:n(e)});export default r;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Server Actions — request/response serialization.
3
+ *
4
+ * Parses incoming request bodies (JSON or form) into action input, serializes
5
+ * errors into the wire format, and parses client-side responses into an
6
+ * {@link ActionResult}.
7
+ *
8
+ * @module actions/serialization
9
+ */
10
+ import type { H3Event } from "h3";
11
+ import type { z } from "zod";
12
+ import type { AcceptMode, ActionResult, SerializedActionError } from "./types.ts";
13
+ /** Resolves the web-standard Request from an H3 event, when available. */
14
+ export declare function getWebRequest(event: H3Event): Request | undefined;
15
+ /**
16
+ * Parses the request body into raw action input.
17
+ *
18
+ * - `accept: "form"` (or a form content-type) → parses FormData / urlencoded.
19
+ * - otherwise → parses JSON (empty body → `undefined`).
20
+ *
21
+ * @throws {ActionError} `UNSUPPORTED_MEDIA_TYPE` / `BAD_REQUEST` on malformed bodies.
22
+ */
23
+ export declare function parseRequestInput(event: H3Event, accept: AcceptMode): Promise<unknown>;
24
+ /** Builds the `fields` map from a Zod error's issues (Zod v4 uses `.issues`). */
25
+ export declare function zodIssuesToFields(error: z.ZodError): Record<string, string[]>;
26
+ /**
27
+ * Serializes an error into the wire format and its HTTP status. Unexpected
28
+ * (non-ActionError) errors become `INTERNAL_SERVER_ERROR`; their message is
29
+ * included only in development.
30
+ */
31
+ export declare function serializeError(err: unknown, isDev: boolean): {
32
+ status: number;
33
+ body: SerializedActionError;
34
+ };
35
+ /**
36
+ * Parses a fetch Response into an {@link ActionResult}. Used by the client
37
+ * proxy. Never throws — network/parse issues become an error result.
38
+ */
39
+ export declare function parseClientResult<T>(response: Response): Promise<ActionResult<T>>;
@@ -0,0 +1 @@
1
+ import{ActionError as e}from"./define.js";export function getWebRequest(e){let t=e;return t.req&&typeof t.req.text==`function`?t.req:t.web?.request??t.request??void 0}function n(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>r.push(e)),e.on(`end`,()=>t(Buffer.concat(r).toString(`utf8`))),e.on(`error`,n)})}function r(e){let t={};for(let n of new Set(e.keys())){let r=e.getAll(n);t[n]=r.length>1?r:r[0]}return t}function i(e){let t=new URLSearchParams(e),n={};for(let e of new Set(t.keys())){let r=t.getAll(e);n[e]=r.length>1?r:r[0]}return n}export async function parseRequestInput(n,a){let s=getWebRequest(n),c=(s?.headers.get(`content-type`)??n.node?.req?.headers?.[`content-type`]??``).toLowerCase();if(a===`form`||c.includes(`multipart/form-data`)||c.includes(`application/x-www-form-urlencoded`)){if(s&&c.includes(`multipart/form-data`))try{return r(await s.formData())}catch(t){throw new e({code:`BAD_REQUEST`,message:`Invalid form data`,cause:t})}return i(await o(n,s))}let l=await o(n,s);if(l)try{return JSON.parse(l)}catch(t){throw new e({code:`BAD_REQUEST`,message:`Invalid JSON body`,cause:t})}}async function o(e,t){if(t)return await t.text();let r=e.node?.req;if(r?.on)return await n(r);let i=e._body;return i===void 0?``:typeof i==`string`?i:JSON.stringify(i)}export function zodIssuesToFields(e){let t={};for(let n of e.issues){let e=n.path.length>0?n.path.join(`.`):`_`,r=t[e]??[];r.push(n.message),t[e]=r}return t}export function serializeError(t,n){return t instanceof e?{status:t.status,body:{code:t.code,message:t.message,...t.fields?{fields:t.fields}:{}}}:{status:500,body:{code:`INTERNAL_SERVER_ERROR`,message:n&&t instanceof Error?t.message:`Internal server error`}}}export async function parseClientResult(t){let n;try{n=await t.json()}catch{n=void 0}if(t.ok)return{data:n?.data,error:void 0};let r=n?.error;return{data:void 0,error:e.fromStatus(t.status,r)}}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Server Actions — shared types.
3
+ *
4
+ * @module actions/types
5
+ */
6
+ import type { H3Event } from "h3";
7
+ import type { z } from "zod";
8
+ /** Unique marker distinguishing an Action from a plain namespace object. */
9
+ export declare const ACTION_MARKER: unique symbol;
10
+ /**
11
+ * Stable error codes for action failures. Each maps to an HTTP status
12
+ * (see `ACTION_ERROR_STATUS` in `define.ts`).
13
+ */
14
+ export type ActionErrorCode = "BAD_REQUEST" | "UNAUTHORIZED" | "FORBIDDEN" | "NOT_FOUND" | "METHOD_NOT_ALLOWED" | "CONFLICT" | "UNSUPPORTED_MEDIA_TYPE" | "INTERNAL_SERVER_ERROR";
15
+ /** How the endpoint parses the request body for an action. */
16
+ export type AcceptMode = "json" | "form";
17
+ /**
18
+ * Context passed to every action handler. Provides access to the underlying
19
+ * request so handlers can read cookies, headers, and perform auth checks.
20
+ */
21
+ export interface ActionContext {
22
+ /** The raw Nitro/H3 event. */
23
+ event: H3Event;
24
+ /** The web-standard Request, when available on the event. */
25
+ request: Request | undefined;
26
+ /** Minimal cookie accessor (reads from the request `Cookie` header). */
27
+ cookies: {
28
+ get(name: string): string | undefined;
29
+ };
30
+ /** Request headers. */
31
+ headers: Headers;
32
+ }
33
+ /**
34
+ * Configuration accepted by {@link defineAction}.
35
+ *
36
+ * @typeParam TInput - The validated input type (inferred from `input`).
37
+ * @typeParam TOutput - The handler's return type.
38
+ */
39
+ export interface ActionConfig<TInput, TOutput> {
40
+ /** Optional Zod schema validating the input before the handler runs. */
41
+ input?: z.ZodType<TInput>;
42
+ /** Body parsing mode. Defaults to `"json"`. */
43
+ accept?: AcceptMode;
44
+ /** The server-side handler. Receives validated input and a context. */
45
+ handler: (input: TInput, context: ActionContext) => TOutput | Promise<TOutput>;
46
+ }
47
+ /**
48
+ * A defined server action. Branded with {@link ACTION_MARKER} so the registry
49
+ * builder can distinguish actions from namespace objects.
50
+ */
51
+ export interface Action<TInput = unknown, TOutput = unknown> {
52
+ readonly [ACTION_MARKER]: true;
53
+ /** Optional Zod input schema. */
54
+ readonly input?: z.ZodType<TInput>;
55
+ /** Resolved accept mode. */
56
+ readonly accept: AcceptMode;
57
+ /** The handler (always returns a promise once normalized). */
58
+ readonly handler: (input: TInput, context: ActionContext) => Promise<TOutput>;
59
+ }
60
+ /** Wire format for a serialized error. */
61
+ export interface SerializedActionError {
62
+ code: ActionErrorCode;
63
+ message: string;
64
+ /** Per-field validation issues (present for `BAD_REQUEST` validation errors). */
65
+ fields?: Record<string, string[]>;
66
+ }
67
+ /**
68
+ * Discriminated result returned by the client proxy. Exactly one of `data` /
69
+ * `error` is populated. The client never throws for action-level failures.
70
+ */
71
+ export type ActionResult<TOutput, TError = SerializedActionError> = {
72
+ data: TOutput;
73
+ error: undefined;
74
+ } | {
75
+ data: undefined;
76
+ error: TError;
77
+ };
78
+ /** A tree of actions and namespaces, as exported under `server`. */
79
+ export interface ActionNamespace {
80
+ [key: string]: Action<any, any> | ActionNamespace;
81
+ }
82
+ /**
83
+ * Maps a `server` export to its client surface: each {@link Action} becomes an
84
+ * async callable returning an {@link ActionResult}; each namespace maps to a
85
+ * nested client.
86
+ */
87
+ export type ActionClient<T> = {
88
+ [K in keyof T]: T[K] extends Action<infer I, infer O> ? undefined extends I ? (input?: I) => Promise<ActionResult<O>> : (input: I) => Promise<ActionResult<O>> : T[K] extends ActionNamespace ? ActionClient<T[K]> : never;
89
+ };
90
+ /** Options for {@link createActionClient}. */
91
+ export interface ActionClientOptions {
92
+ /**
93
+ * Base URL/path for the actions endpoint. Defaults to `/_actions`.
94
+ * Provide an absolute origin (e.g. `https://api.example.com/_actions`) for
95
+ * cross-origin usage.
96
+ */
97
+ baseUrl?: string;
98
+ /** Optional custom fetch implementation (testing / non-browser runtimes). */
99
+ fetch?: typeof fetch;
100
+ }
@@ -0,0 +1 @@
1
+ export const ACTION_MARKER=Symbol.for(`avalon.action`);
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Server Actions — type generation.
3
+ *
4
+ * Generates an ambient declaration that types the `virtual:avalon/actions`
5
+ * module against the project's `server` export, giving full input/output
6
+ * inference on the `actions` client proxy without manual wiring.
7
+ *
8
+ * Mirrors the island types generator: a pure utility that writes a `.d.ts`.
9
+ *
10
+ * @module build/actions-types-generator
11
+ */
12
+ /** Result of an actions type-generation pass. */
13
+ export interface ActionsTypeGenerationResult {
14
+ /** Whether an actions entry was found and a declaration written. */
15
+ generated: boolean;
16
+ /** The absolute path of the written declaration, when generated. */
17
+ outputPath?: string;
18
+ /** The actions entry directory base (`app` or `src`), when found. */
19
+ base?: "app" | "src";
20
+ }
21
+ /**
22
+ * Locates the actions entry under the project root. Returns the base directory
23
+ * (`app`/`src`) and the entry filename (e.g. `index.ts`), or `undefined`.
24
+ */
25
+ export declare function findActionsEntryInfo(projectRoot: string): {
26
+ base: "app" | "src";
27
+ file: string;
28
+ } | undefined;
29
+ /**
30
+ * Generates `<base>/avalon-actions.d.ts` typing `virtual:avalon/actions` against
31
+ * the project's `server` export. No-op (returns `{ generated: false }`) when no
32
+ * actions entry exists — the loose ambient declaration in `virtual-modules.d.ts`
33
+ * covers that case without producing spurious type errors.
34
+ *
35
+ * @param projectRoot - Absolute path to the project root.
36
+ */
37
+ export declare function generateActionTypes(projectRoot: string): ActionsTypeGenerationResult;
38
+ /** Returns the directory that should be watched for actions entry changes. */
39
+ export declare function getActionsWatchDir(projectRoot: string): string | undefined;
@@ -0,0 +1,7 @@
1
+ import{existsSync as e,readFileSync as t,writeFileSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";const a=[`ts`,`tsx`,`js`,`jsx`,`mts`,`mjs`];export function findActionsEntryInfo(t){for(let n of[`app`,`src`])for(let r of a){let a=`index.${r}`;if(e(i(t,n,`actions`,a)))return{base:n,file:a}}}export function generateActionTypes(r){let a=findActionsEntryInfo(r);if(!a)return{generated:!1};let o=i(r,a.base,`avalon-actions.d.ts`),s=`// AUTO-GENERATED by Avalon — do not edit. Types \`virtual:avalon/actions\`.
2
+ declare module "virtual:avalon/actions" {
3
+ type Server = (typeof import("./actions/index"))["server"];
4
+ export const actions: import("@useavalon/avalon/actions").ActionClient<Server>;
5
+ export default actions;
6
+ }
7
+ `;try{if(e(o)&&t(o,`utf8`)===s)return{generated:!0,outputPath:o,base:a.base}}catch{}try{n(o,s,`utf8`)}catch{return{generated:!1}}return{generated:!0,outputPath:o,base:a.base}}export function getActionsWatchDir(e){let t=findActionsEntryInfo(e);if(t)return r(i(e,t.base,`actions`,t.file))}
@@ -3,8 +3,8 @@ import { z } from "zod";
3
3
  * Supported HTTP methods for API routes
4
4
  */
5
5
  export declare const ApiMethodSchema: z.ZodEnum<{
6
- GET: "GET";
7
6
  POST: "POST";
7
+ GET: "GET";
8
8
  PUT: "PUT";
9
9
  DELETE: "DELETE";
10
10
  PATCH: "PATCH";
@@ -53,7 +53,7 @@ export declare const routingValidators: {
53
53
  siteName?: string;
54
54
  };
55
55
  twitter?: {
56
- card?: "summary" | "app" | "summary_large_image" | "player";
56
+ card?: "app" | "summary" | "summary_large_image" | "player";
57
57
  title?: string;
58
58
  description?: string;
59
59
  image?: string;
@@ -76,7 +76,7 @@ export declare const routingValidators: {
76
76
  siteName?: string;
77
77
  };
78
78
  twitter?: {
79
- card?: "summary" | "app" | "summary_large_image" | "player";
79
+ card?: "app" | "summary" | "summary_large_image" | "player";
80
80
  title?: string;
81
81
  description?: string;
82
82
  image?: string;
@@ -143,7 +143,7 @@ export declare const safeRoutingValidators: {
143
143
  siteName?: string;
144
144
  };
145
145
  twitter?: {
146
- card?: "summary" | "app" | "summary_large_image" | "player";
146
+ card?: "app" | "summary" | "summary_large_image" | "player";
147
147
  title?: string;
148
148
  description?: string;
149
149
  image?: string;
@@ -166,7 +166,7 @@ export declare const safeRoutingValidators: {
166
166
  siteName?: string;
167
167
  };
168
168
  twitter?: {
169
- card?: "summary" | "app" | "summary_large_image" | "player";
169
+ card?: "app" | "summary" | "summary_large_image" | "player";
170
170
  title?: string;
171
171
  description?: string;
172
172
  image?: string;
@@ -77,8 +77,8 @@ export declare const MetadataSchema: z.ZodObject<{
77
77
  }, z.core.$strip>>;
78
78
  twitter: z.ZodOptional<z.ZodObject<{
79
79
  card: z.ZodOptional<z.ZodEnum<{
80
- summary: "summary";
81
80
  app: "app";
81
+ summary: "summary";
82
82
  summary_large_image: "summary_large_image";
83
83
  player: "player";
84
84
  }>>;
@@ -108,8 +108,8 @@ export declare const ResolvedMetadataSchema: z.ZodObject<{
108
108
  }, z.core.$strip>>;
109
109
  twitter: z.ZodOptional<z.ZodObject<{
110
110
  card: z.ZodOptional<z.ZodEnum<{
111
- summary: "summary";
112
111
  app: "app";
112
+ summary: "summary";
113
113
  summary_large_image: "summary_large_image";
114
114
  player: "player";
115
115
  }>>;
@@ -142,8 +142,8 @@ export declare const MetadataChainSchema: z.ZodObject<{
142
142
  }, z.core.$strip>>;
143
143
  twitter: z.ZodOptional<z.ZodObject<{
144
144
  card: z.ZodOptional<z.ZodEnum<{
145
- summary: "summary";
146
145
  app: "app";
146
+ summary: "summary";
147
147
  summary_large_image: "summary_large_image";
148
148
  player: "player";
149
149
  }>>;
@@ -172,8 +172,8 @@ export declare const MetadataChainSchema: z.ZodObject<{
172
172
  }, z.core.$strip>>;
173
173
  twitter: z.ZodOptional<z.ZodObject<{
174
174
  card: z.ZodOptional<z.ZodEnum<{
175
- summary: "summary";
176
175
  app: "app";
176
+ summary: "summary";
177
177
  summary_large_image: "summary_large_image";
178
178
  player: "player";
179
179
  }>>;
@@ -201,8 +201,8 @@ export declare const MetadataChainSchema: z.ZodObject<{
201
201
  }, z.core.$strip>>;
202
202
  twitter: z.ZodOptional<z.ZodObject<{
203
203
  card: z.ZodOptional<z.ZodEnum<{
204
- summary: "summary";
205
204
  app: "app";
205
+ summary: "summary";
206
206
  summary_large_image: "summary_large_image";
207
207
  player: "player";
208
208
  }>>;
@@ -305,8 +305,8 @@ export declare const FileSystemApiRouteSchema: z.ZodObject<{
305
305
  pattern: z.ZodAny;
306
306
  filePath: z.ZodString;
307
307
  methods: z.ZodArray<z.ZodEnum<{
308
- GET: "GET";
309
308
  POST: "POST";
309
+ GET: "GET";
310
310
  PUT: "PUT";
311
311
  DELETE: "DELETE";
312
312
  PATCH: "PATCH";
@@ -79,3 +79,17 @@ declare module "virtual:server-island-integrations" {
79
79
  // Side-effect module that registers framework integrations in the global registry.
80
80
  // No exports — import for side effects only.
81
81
  }
82
+
83
+ declare module "virtual:avalon-actions-manifest" {
84
+ /** The project's `server` export (tree of actions/namespaces), bundled into the Nitro server. */
85
+ export const server: Record<string, unknown>;
86
+ }
87
+
88
+ declare module "virtual:avalon/actions" {
89
+ /**
90
+ * The typed action client proxy. This declaration is overridden by the
91
+ * generated `avalon-actions.d.ts` when an actions entry exists, which types
92
+ * `actions` against the project's `server` export.
93
+ */
94
+ export const actions: Record<string, (input?: unknown) => Promise<unknown>>;
95
+ }
@@ -20,6 +20,7 @@ export declare const VIRTUAL_MODULE_IDS: {
20
20
  readonly RENDERER: "virtual:avalon/renderer";
21
21
  readonly CLIENT_ENTRY: "virtual:avalon/client-entry";
22
22
  readonly INTEGRATION_LOADER: "virtual:avalon/integration-loader";
23
+ readonly ACTIONS: "virtual:avalon/actions";
23
24
  };
24
25
  export declare const RESOLVED_VIRTUAL_IDS: {
25
26
  readonly PAGE_ROUTES: "\0virtual:avalon/page-routes";
@@ -32,6 +33,7 @@ export declare const RESOLVED_VIRTUAL_IDS: {
32
33
  readonly RENDERER: "\0virtual:avalon/renderer";
33
34
  readonly CLIENT_ENTRY: "\0virtual:avalon/client-entry";
34
35
  readonly INTEGRATION_LOADER: "\0virtual:avalon/integration-loader";
36
+ readonly ACTIONS: "\0virtual:avalon/actions";
35
37
  };
36
38
  export interface NitroIntegrationResult {
37
39
  nitroOptions: NitroConfigOutput;
@@ -1,8 +1,10 @@
1
- import{existsSync as e,readdirSync as t,readFileSync as n,rmSync as r}from"node:fs";import{stat as i}from"node:fs/promises";import{createRequire as a}from"node:module";import{dirname as o,join as s,relative as c,resolve as l}from"node:path";import{nitro as u}from"nitro/vite";import{isRunnableDevEnvironment as d}from"vite";import{getUniversalCSSForHead as f}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as p,injectSolidHydrationScriptIfNeeded as m}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as h,discoverScopedMiddleware as g,executeScopedMiddleware as _}from"../middleware/index.js";import{createNitroConfig as v}from"../nitro/config.js";import{createIslandManifestPlugin as y,createNitroBuildPlugin as b,createSourceMapConfig as x,createSourceMapPlugin as S}from"../nitro/index.js";import{collectCssFromModuleGraph as C,injectSsrCss as w}from"../render/collect-css.js";import{generateErrorPage as T,generateFallback404 as E}from"../render/error-pages.js";import{generateComponentId as D}from"../server-islands/manifest.js";import{resolveToRelativePath as O}from"./server-islands-plugin.js";function k(e){let t=P(e),r=Object.entries(t),i=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;i+=`export const serverIslandLoaders = {
1
+ import{existsSync as e,readdirSync as t,readFileSync as n,rmSync as r}from"node:fs";import{stat as i}from"node:fs/promises";import{createRequire as a}from"node:module";import{dirname as o,join as s,relative as c,resolve as l}from"node:path";import{nitro as u}from"nitro/vite";import{isRunnableDevEnvironment as d}from"vite";import{generateActionTypes as f}from"../build/actions-types-generator.js";import{getUniversalCSSForHead as p}from"../islands/universal-css-collector.js";import{getUniversalHeadForInjection as m,injectSolidHydrationScriptIfNeeded as h}from"../islands/universal-head-collector.js";import{clearMiddlewareCache as g,discoverScopedMiddleware as _,executeScopedMiddleware as v}from"../middleware/index.js";import{createNitroConfig as y}from"../nitro/config.js";import{createIslandManifestPlugin as b,createNitroBuildPlugin as x,createSourceMapConfig as S,createSourceMapPlugin as C}from"../nitro/index.js";import{collectCssFromModuleGraph as w,injectSsrCss as T}from"../render/collect-css.js";import{generateErrorPage as E,generateFallback404 as D}from"../render/error-pages.js";import{generateComponentId as O}from"../server-islands/manifest.js";import{resolveToRelativePath as k}from"./server-islands-plugin.js";function A(e){let t=ee(e),r=Object.entries(t),i=`export const serverIslandManifest = ${JSON.stringify(t)};\n\n`;i+=`export const serverIslandLoaders = {
2
2
  `;for(let[e,t]of r)i+=` ${JSON.stringify(e)}: () => import(${JSON.stringify(t)}),\n`;i+=`};
3
3
 
4
- `;let a={};for(let[t,i]of r)if(i.endsWith(`.svelte`))try{let r=n(s(e,i.startsWith(`/`)?i.slice(1):i),`utf8`).match(/<style[^>]*>([\s\S]*?)<\/style>/);r&&(a[t]=r[1].trim())}catch{}return i+=`export const serverIslandCSS = ${JSON.stringify(a)};\n`,i}const A=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,j=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function M(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function N(e,n){let r;try{r=t(e,{withFileTypes:!0})}catch{return}for(let t of r){let r=s(e,t.name);if(t.isDirectory()){if(j.has(t.name))continue;N(r,n)}else if(t.isFile()){if(!/\.(tsx|jsx)$/.test(t.name)||/\.(test|spec)\.[jt]sx$/.test(t.name)||r.includes(`__tests__`))continue;n.push(r)}}}function P(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&N(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}if(!/\bserver\s*[={/>]/.test(i))continue;A.lastIndex=0;let a=A.exec(i);for(;a!==null;a=A.exec(i)){let n=a[1],o=a[2].slice(1,-1);if(!M(i,n))continue;let s=O(o,e,t),c=D(s);c in r||(r[c]=s)}}return r}function F(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function ee(t,n){let r=s(o(a(s(process.cwd(),`package.json`)).resolve(`@useavalon/${t}`)),n);if(n.endsWith(`.ts`)&&!e(r)){let t=r.replace(/\.ts$/,`.js`);if(e(t))return t}return r}export const VIRTUAL_MODULE_IDS={PAGE_ROUTES:`virtual:avalon/page-routes`,PAGE_LOADER:`virtual:avalon/page-loader`,ISLAND_MANIFEST:`virtual:avalon/island-manifest`,RUNTIME_CONFIG:`virtual:avalon/runtime-config`,CONFIG:`virtual:avalon/config`,LAYOUTS:`virtual:avalon/layouts`,ASSETS:`virtual:avalon/assets`,RENDERER:`virtual:avalon/renderer`,CLIENT_ENTRY:`virtual:avalon/client-entry`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`};export const RESOLVED_VIRTUAL_IDS={PAGE_ROUTES:`\0${VIRTUAL_MODULE_IDS.PAGE_ROUTES}`,PAGE_LOADER:`\0${VIRTUAL_MODULE_IDS.PAGE_LOADER}`,ISLAND_MANIFEST:`\0${VIRTUAL_MODULE_IDS.ISLAND_MANIFEST}`,RUNTIME_CONFIG:`\0${VIRTUAL_MODULE_IDS.RUNTIME_CONFIG}`,CONFIG:`\0${VIRTUAL_MODULE_IDS.CONFIG}`,LAYOUTS:`\0${VIRTUAL_MODULE_IDS.LAYOUTS}`,ASSETS:`\0${VIRTUAL_MODULE_IDS.ASSETS}`,RENDERER:`\0${VIRTUAL_MODULE_IDS.RENDERER}`,CLIENT_ENTRY:`\0${VIRTUAL_MODULE_IDS.CLIENT_ENTRY}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`};export function createNitroIntegration(e,t={}){let n=v(t,e),r=process.cwd(),i=F(`src/server-islands/route.ts`),a={preset:n.preset,serverDir:t.serverDir??n.serverDir??`./server`,routeRules:n.routeRules,runtimeConfig:n.runtimeConfig,compatibilityDate:n.compatibilityDate,scanDirs:[`.`],noExternals:[`estree-walker`,/^@useavalon\//,/^estree-util/,/^preact/,/^react/,/^react-dom/,/^vue/,/^@vue\//],handlers:[{route:`/_server-islands/**`,handler:i}],virtual:{"virtual:server-island-manifest":()=>k(r),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>`
5
- import { registry } from "${F(`src/core/integrations/registry.ts`)}";
4
+ `;let a={};for(let[t,i]of r)if(i.endsWith(`.svelte`))try{let r=n(s(e,i.startsWith(`/`)?i.slice(1):i),`utf8`).match(/<style[^>]*>([\s\S]*?)<\/style>/);r&&(a[t]=r[1].trim())}catch{}return i+=`export const serverIslandCSS = ${JSON.stringify(a)};\n`,i}const j=/^[ \t]*import\s+([A-Z]\w*)\s+from\s+(['"][^'"]+['"])/gm,M=new Set([`node_modules`,`dist`,`.output`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`,`.git`]);function N(e,t){return new RegExp(String.raw`<${t}\s[\s\S]*?\bserver\s*[={/>]`).test(e)}function P(e,n){let r;try{r=t(e,{withFileTypes:!0})}catch{return}for(let t of r){let r=s(e,t.name);if(t.isDirectory()){if(M.has(t.name))continue;P(r,n)}else if(t.isFile()){if(!/\.(tsx|jsx)$/.test(t.name)||/\.(test|spec)\.[jt]sx$/.test(t.name)||r.includes(`__tests__`))continue;n.push(r)}}}function ee(t){let r={},i=[];for(let n of[`app`,`src`]){let r=s(t,n);e(r)&&P(r,i)}for(let e of i){let i;try{i=n(e,`utf8`)}catch{continue}if(!/\bserver\s*[={/>]/.test(i))continue;j.lastIndex=0;let a=j.exec(i);for(;a!==null;a=j.exec(i)){let n=a[1],o=a[2].slice(1,-1);if(!N(i,n))continue;let s=k(o,e,t),c=O(s);c in r||(r[c]=s)}}return r}function F(t){let n=[`ts`,`tsx`,`js`,`jsx`,`mts`,`mjs`];for(let r of[`app`,`src`])for(let i of n){let n=`/${r}/actions/index.${i}`;if(e(s(t,n.slice(1))))return n}}function I(e){let t=F(e);return t?`export { server } from ${JSON.stringify(t)};\n`:`export const server = {};
5
+ `}function te(){return[`import { createActionClient } from "@useavalon/avalon/actions";`,`export const actions = createActionClient();`,`export default actions;`,``].join(`
6
+ `)}function L(t){let n=s(o(a(import.meta.url).resolve(`@useavalon/avalon`)),t);if(t.endsWith(`.ts`)&&!e(n)){let t=n.replace(/\.ts$/,`.js`);if(e(t))return t}return n}function ne(t,n){let r=s(o(a(s(process.cwd(),`package.json`)).resolve(`@useavalon/${t}`)),n);if(n.endsWith(`.ts`)&&!e(r)){let t=r.replace(/\.ts$/,`.js`);if(e(t))return t}return r}export const VIRTUAL_MODULE_IDS={PAGE_ROUTES:`virtual:avalon/page-routes`,PAGE_LOADER:`virtual:avalon/page-loader`,ISLAND_MANIFEST:`virtual:avalon/island-manifest`,RUNTIME_CONFIG:`virtual:avalon/runtime-config`,CONFIG:`virtual:avalon/config`,LAYOUTS:`virtual:avalon/layouts`,ASSETS:`virtual:avalon/assets`,RENDERER:`virtual:avalon/renderer`,CLIENT_ENTRY:`virtual:avalon/client-entry`,INTEGRATION_LOADER:`virtual:avalon/integration-loader`,ACTIONS:`virtual:avalon/actions`};export const RESOLVED_VIRTUAL_IDS={PAGE_ROUTES:`\0${VIRTUAL_MODULE_IDS.PAGE_ROUTES}`,PAGE_LOADER:`\0${VIRTUAL_MODULE_IDS.PAGE_LOADER}`,ISLAND_MANIFEST:`\0${VIRTUAL_MODULE_IDS.ISLAND_MANIFEST}`,RUNTIME_CONFIG:`\0${VIRTUAL_MODULE_IDS.RUNTIME_CONFIG}`,CONFIG:`\0${VIRTUAL_MODULE_IDS.CONFIG}`,LAYOUTS:`\0${VIRTUAL_MODULE_IDS.LAYOUTS}`,ASSETS:`\0${VIRTUAL_MODULE_IDS.ASSETS}`,RENDERER:`\0${VIRTUAL_MODULE_IDS.RENDERER}`,CLIENT_ENTRY:`\0${VIRTUAL_MODULE_IDS.CLIENT_ENTRY}`,INTEGRATION_LOADER:`\0${VIRTUAL_MODULE_IDS.INTEGRATION_LOADER}`,ACTIONS:`\0${VIRTUAL_MODULE_IDS.ACTIONS}`};export function createNitroIntegration(e,t={}){let n=y(t,e),r=process.cwd(),i=L(`src/server-islands/route.ts`),a=L(`src/actions/route.ts`),o={preset:n.preset,serverDir:t.serverDir??n.serverDir??`./server`,routeRules:n.routeRules,runtimeConfig:n.runtimeConfig,compatibilityDate:n.compatibilityDate,scanDirs:[`.`],noExternals:[`estree-walker`,/^@useavalon\//,/^estree-util/,/^preact/,/^react/,/^react-dom/,/^vue/,/^@vue\//],handlers:[{route:`/_server-islands/**`,handler:i},{route:`/_actions/**`,handler:a}],virtual:{"virtual:server-island-manifest":()=>A(r),"virtual:avalon-actions-manifest":()=>I(r),"virtual:server-island-key":()=>{let e=process.env.AVALON_KEY??``;return`export const serverIslandKey = ${JSON.stringify(e)};\n`},"virtual:server-island-integrations":()=>`
7
+ import { registry } from "${L(`src/core/integrations/registry.ts`)}";
6
8
  import { solidIntegration } from "@useavalon/solid";
7
9
  import { vueIntegration } from "@useavalon/vue";
8
10
  import { svelteIntegration } from "@useavalon/svelte";
@@ -11,28 +13,28 @@ if (solidIntegration) registry.register(solidIntegration);
11
13
  if (vueIntegration) registry.register(vueIntegration);
12
14
  if (svelteIntegration) registry.register(svelteIntegration);
13
15
  if (litIntegration) registry.register(litIntegration);
14
- `}};t.renderer===!1?a.renderer=!1:n.renderer&&(a.renderer=n.renderer),n.publicRuntimeConfig&&(a.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(a.publicAssets=n.publicAssets),n.compressPublicAssets&&(a.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(a.serverEntry=n.serverEntry);let o=n.traceDeps??[];a.traceDeps=[...new Set([`undici`,...o])],n.prerender&&(a.prerender={routes:[],crawlLinks:!1});let s=u(a),c=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),l=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=b(e,t),f=y(e,{verbose:e.verbose,generatePreloadHints:!0}),p=S(x(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(s)?s:[s],c,l,d,f,p]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,config(e,{command:t}){if(t===`serve`)return{server:{watch:{ignored:[`**/.output/**`,`**/dist/**`,`**/.netlify/**`,`**/.vercel/**`,`**/.cloudflare/**`,`**/.wrangler/**`,`**/.firebase/**`,`**/.amplify-hosting/**`]},fs:{deny:[`.output`,`dist`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`]}}}},configResolved(e){globalThis.__avalonHydrationMode=e.command===`serve`?`entry-client`:`per-island`},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e.config.build?.outDir?s(i,e.config.build.outDir):s(i,`dist`);try{r(a,{recursive:!0,force:!0})}catch{}try{r(s(i,`.output`),{recursive:!0,force:!0})}catch{}let o=!1,c=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||o?(o=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{o=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(o)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await c,n()});let l=null;async function u(){return l||=await g({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),l}function f(){l=null}R(e,t,n,f),u().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let p=e.environments?.ssr,m=!!p&&d(p);m&&L(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_server-islands/`)||!m)return r();try{let{decrypt:r}=await e.ssrLoadModule(F(`src/server-islands/encryption.ts`)),{h:a}=await e.ssrLoadModule(`preact`),o=(await e.ssrLoadModule(`preact-render-to-string`)).default,s=new URL(i,`http://${t.headers.host||`localhost`}`).searchParams.get(`p`)||``;if(!s&&t.method===`POST`&&(s=await new Promise((e,n)=>{let r=[],i=e=>r.push(e),a=()=>{c(),e(Buffer.concat(r).toString(`utf8`))},o=e=>{c(),n(e)},s=setTimeout(()=>{c(),n(Error(`Timed out reading server island request body`))},15e3);function c(){clearTimeout(s),t.off(`data`,i),t.off(`end`,a),t.off(`error`,o)}t.on(`data`,i),t.on(`end`,a),t.on(`error`,o)})),!s){n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Missing encrypted props`);return}let c,l,u;try{let e;if(s.startsWith(`dev.`)){let t=s.slice(4);e=Buffer.from(t,`base64url`).toString(`utf8`)}else e=r(s);let t=JSON.parse(e);t.__island&&(u=t.__island,delete t.__island),t.__src&&(l=t.__src,delete t.__src),c=t}catch{n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Bad Request: decryption failed`);return}if(!l){n.statusCode=404,n.setHeader(`Content-Type`,`text/plain`),n.end(`Component not found (no __src in payload)`);return}let d=(await e.ssrLoadModule(l)).default;if(typeof d!=`function`){n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Module "${l}" does not export a default component function`);return}let f=o(a(d,c));if(u){let e=i.split(`/`)[2]?.split(`?`)[0]||``,t=u.elementId??`si-${e}`,n=u.componentSrc??l,r=JSON.stringify(c),a=u.condition??`on:client`,o=u.framework??`preact`,s=`<script type="module">
15
- import{hydrateServerIsland}from"/@fs${F(`src/client/server-island-hydrate.ts`)}";
16
+ `}};t.renderer===!1?o.renderer=!1:n.renderer&&(o.renderer=n.renderer),n.publicRuntimeConfig&&(o.publicRuntimeConfig=n.publicRuntimeConfig),n.publicAssets&&(o.publicAssets=n.publicAssets),n.compressPublicAssets&&(o.compressPublicAssets=n.compressPublicAssets),n.serverEntry&&(o.serverEntry=n.serverEntry);let s=n.traceDeps??[];o.traceDeps=[...new Set([`undici`,...s])],n.prerender&&(o.prerender={routes:[],crawlLinks:!1});let c=u(o),l=createNitroCoordinationPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),d=createVirtualModulesPlugin({avalonConfig:e,nitroConfig:t,verbose:e.verbose}),f=x(e,t),p=b(e,{verbose:e.verbose,generatePreloadHints:!0}),m=C(S(t.preset??`node_server`,e.isDev));return{nitroOptions:n,plugins:[...Array.isArray(c)?c:[c],l,d,f,p,m]}}export function createNitroCoordinationPlugin(e){let{avalonConfig:t,verbose:n}=e;return{name:`avalon:nitro-coordination`,enforce:`pre`,config(e,{command:t}){if(t===`serve`)return{server:{watch:{ignored:[`**/.output/**`,`**/dist/**`,`**/.netlify/**`,`**/.vercel/**`,`**/.cloudflare/**`,`**/.wrangler/**`,`**/.firebase/**`,`**/.amplify-hosting/**`]},fs:{deny:[`.output`,`dist`,`.netlify`,`.vercel`,`.cloudflare`,`.wrangler`,`.firebase`,`.amplify-hosting`]}}}},configResolved(e){globalThis.__avalonHydrationMode=e.command===`serve`?`entry-client`:`per-island`;try{f(e.root||process.cwd())}catch{}},configureServer(e){globalThis.__viteDevServer=e;let i=e.config.root||process.cwd(),a=e=>{if(e.includes(`/actions/`))try{f(i)}catch{}};e.watcher.on(`add`,a),e.watcher.on(`unlink`,a);let o=e.config.root||process.cwd(),c=e.config.build?.outDir?s(o,e.config.build.outDir):s(o,`dist`);try{r(c,{recursive:!0,force:!0})}catch{}try{r(s(o,`.output`),{recursive:!0,force:!0})}catch{}let l=!1,u=new Promise(t=>{let n=()=>{(e.environments?.nitro)?.devServer?.entry||l?(l=!0,t()):setTimeout(n,50)};setTimeout(n,100),setTimeout(()=>{l=!0,t()},15e3)});e.middlewares.use(async(e,t,n)=>{if(l)return n();let r=e.url||`/`;if(r.startsWith(`/@`)||r.startsWith(`/__`)||/\/[^/]+\.[a-z0-9]+(\?|$)/i.test(r))return n();await u,n()});let p=null;async function m(){return p||=await _({baseDir:`${e.config.root||process.cwd()}/src`,devMode:!1}),p}function h(){p=null}oe(e,t,n,h),m().catch(e=>{console.warn(`[middleware] Failed to discover middleware:`,e)});let g=e.environments?.ssr,v=!!g&&d(g);v&&ae(e,t.integrations,n).catch(e=>{console.error(`[prewarm] Core modules pre-warm failed:`,e)}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_server-islands/`)||!v)return r();try{let{decrypt:r}=await e.ssrLoadModule(L(`src/server-islands/encryption.ts`)),{h:a}=await e.ssrLoadModule(`preact`),o=(await e.ssrLoadModule(`preact-render-to-string`)).default,s=new URL(i,`http://${t.headers.host||`localhost`}`).searchParams.get(`p`)||``;if(!s&&t.method===`POST`&&(s=await new Promise((e,n)=>{let r=[],i=e=>r.push(e),a=()=>{c(),e(Buffer.concat(r).toString(`utf8`))},o=e=>{c(),n(e)},s=setTimeout(()=>{c(),n(Error(`Timed out reading server island request body`))},15e3);function c(){clearTimeout(s),t.off(`data`,i),t.off(`end`,a),t.off(`error`,o)}t.on(`data`,i),t.on(`end`,a),t.on(`error`,o)})),!s){n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Missing encrypted props`);return}let c,l,u;try{let e;if(s.startsWith(`dev.`)){let t=s.slice(4);e=Buffer.from(t,`base64url`).toString(`utf8`)}else e=r(s);let t=JSON.parse(e);t.__island&&(u=t.__island,delete t.__island),t.__src&&(l=t.__src,delete t.__src),c=t}catch{n.statusCode=400,n.setHeader(`Content-Type`,`text/plain`),n.end(`Bad Request: decryption failed`);return}if(!l){n.statusCode=404,n.setHeader(`Content-Type`,`text/plain`),n.end(`Component not found (no __src in payload)`);return}let d=(await e.ssrLoadModule(l)).default;if(typeof d!=`function`){n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Module "${l}" does not export a default component function`);return}let f=o(a(d,c));if(u){let e=i.split(`/`)[2]?.split(`?`)[0]||``,t=u.elementId??`si-${e}`,n=u.componentSrc??l,r=JSON.stringify(c),a=u.condition??`on:client`,o=u.framework??`preact`,s=`<script type="module">
17
+ import{hydrateServerIsland}from"/@fs${L(`src/client/server-island-hydrate.ts`)}";
16
18
  hydrateServerIsland(${JSON.stringify(t)},${JSON.stringify(n)},${r},${JSON.stringify(a)},${JSON.stringify(o)});
17
- <\/script>`;f+=s}n.statusCode=200,n.setHeader(`Content-Type`,`text/html`),n.setHeader(`Cache-Control`,`private, no-store`),n.end(f)}catch(e){console.error(`[server-islands] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Server island render failed: ${e instanceof Error?e.message:String(e)}`)}}),e.middlewares.use(async(r,i,a)=>{if(!m)return a();let o=r.url||`/`;if(o.endsWith(`.html`)&&(o=o.slice(0,-5)||`/`),o===`/index`&&(o=`/`),o.startsWith(`/@`)||o.startsWith(`/__`)||o.startsWith(`/node_modules/`)||o.startsWith(`/src/client/`)||o.startsWith(`/packages/`)||o.includes(`.`)&&!o.endsWith(`/`)||o.startsWith(`/api/`))return a();try{if(await te(e,o,r,i,u,n)||await ne(e,o,t,i))return;let a=await re(e,o,t);if(a){i.statusCode=200,i.setHeader(`Content-Type`,`text/html`),i.end(a);return}await I(e,o,i,t)}catch(e){console.error(`[SSR Error]`,e),i.statusCode=500,i.setHeader(`Content-Type`,`text/html`),i.end(T(e))}})},buildStart(){}}}async function te(e,t,n,r,i,a){let o=performance.now(),s=await i();if(s.length===0)return!1;let c={};for(let[e,t]of Object.entries(n.headers))typeof t==`string`?c[e]=t:Array.isArray(t)&&(c[e]=t.join(`, `));let l=`http://${n.headers.host||`localhost`}${t}`,u=await _({url:l,method:n.method||`GET`,path:t,node:{req:n,res:r},req:new Request(l,{method:n.method||`GET`,headers:c}),context:{}},s,{devMode:!1}),d=performance.now()-o;return d>100&&console.warn(`⚠️ Slow middleware: ${d.toFixed(0)}ms for ${t}`),u?(r.statusCode=u.status,u.headers.forEach((e,t)=>{r.setHeader(t,e)}),r.end(await u.text()),!0):!1}async function I(e,t,n,r){try{let{discoverErrorPages:i,getErrorPageModule:a,generateDefaultErrorPage:o}=await import(`../nitro/error-handler.js`),s=a(404,await i({isDev:r.isDev,pagesDir:r.pagesDir,loadPageModule:async t=>await e.ssrLoadModule(t)}));if(s?.default&&typeof s.default==`function`){let{renderToHtml:e}=await import(`../render/ssr.js`),r=s.default,i=await e({component:()=>r({statusCode:404,message:`Page not found: ${t}`,url:t})},{});n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(i);return}let c=o(404,`Page not found: ${t}`,r.isDev);n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(c)}catch{n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(E(t))}}async function L(e,t,n){let r=performance.now(),i=[{path:F(`src/render/ssr.ts`),assignTo:`ssr`},{path:F(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:F(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:ee(e,`server/renderer.ts`),assignTo:null}))],a=(await Promise.allSettled(i.map(async({path:t,assignTo:n})=>{let r=await e.ssrLoadModule(t);n===`ssr`&&(J=r),n===`layout`&&(Y=r)}))).filter(e=>e.status===`fulfilled`).length,o=performance.now()-r;n&&a>0&&console.log(`🔥 SSR ready in ${o.toFixed(0)}ms (${a}/${i.length} core modules)`)}export function createVirtualModulesPlugin(e){let{avalonConfig:n,nitroConfig:r,verbose:i}=e,a=null,o=s,u=c,d=l,f=process.cwd(),p=[];function m(e){try{let n=t(e,{withFileTypes:!0});for(let t of n){let n=o(e,t.name);if(t.isDirectory()&&t.name!==`node_modules`&&!t.name.startsWith(`.`))m(n);else if(t.isFile()&&t.name.endsWith(`.css`)){let e=u(f,n).replaceAll(`\\`,`/`);p.push(e.startsWith(`/`)?e:`/${e}`)}}}catch{}}function h(){p.length=0;for(let e of r.globalCSS??[])p.push(e.startsWith(`/`)?e:`/${e}`);n.modules&&m(d(f,n.modules.dir)),m(d(f,n.layoutsDir));let e=d(f,n.layoutsDir,`..`);e!==f&&e!==d(f,n.layoutsDir)&&e.startsWith(f)&&m(e)}return n.isDev&&h(),{name:`avalon:nitro-virtual-modules`,enforce:`pre`,resolveId(e){return e===VIRTUAL_MODULE_IDS.PAGE_ROUTES?RESOLVED_VIRTUAL_IDS.PAGE_ROUTES:e===VIRTUAL_MODULE_IDS.PAGE_LOADER?RESOLVED_VIRTUAL_IDS.PAGE_LOADER:e===VIRTUAL_MODULE_IDS.ISLAND_MANIFEST?RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST:e===VIRTUAL_MODULE_IDS.RUNTIME_CONFIG?RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG:e===VIRTUAL_MODULE_IDS.CONFIG?RESOLVED_VIRTUAL_IDS.CONFIG:e===VIRTUAL_MODULE_IDS.LAYOUTS?RESOLVED_VIRTUAL_IDS.LAYOUTS:e===VIRTUAL_MODULE_IDS.ASSETS?RESOLVED_VIRTUAL_IDS.ASSETS:e===VIRTUAL_MODULE_IDS.RENDERER?RESOLVED_VIRTUAL_IDS.RENDERER:e===VIRTUAL_MODULE_IDS.CLIENT_ENTRY?RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY:e===VIRTUAL_MODULE_IDS.INTEGRATION_LOADER?RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await z(n,i):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await B(n,i):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?V():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?H(n,r):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(n,r):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(a||=await U(n,r,p),a):e===RESOLVED_VIRTUAL_IDS.ASSETS?W(r):e===RESOLVED_VIRTUAL_IDS.RENDERER?G(n):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await K(n,r):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(n):null},handleHotUpdate({file:e,server:t}){let n=e.includes(`/pages/`)&&!e.endsWith(`.css`),r=e.includes(`/components/`)&&/\.[tj]sx?$/.test(e),i=(e.includes(`/layouts/`)||e.includes(`_layout`))&&/\.[tj]sx?$/.test(e),o=e.endsWith(`.css`);if(n||r||i||o){if(n){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_ROUTES);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_LOADER);n&&t.moduleGraph.invalidateModule(n)}if(i){a=null,h();let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.LAYOUTS);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY);n&&t.moduleGraph.invalidateModule(n)}setTimeout(()=>{t.ws.send({type:`full-reload`,path:`*`})},500)}if(e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CONFIG);e&&t.moduleGraph.invalidateModule(e)}}}}function R(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(h(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(J=null,Y=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(h(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(h(),r?.())})}async function z(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),r=await n(await t(e.pagesDir,e.modules,process.cwd()),{developmentMode:e.isDev});return`export const pageRoutes = ${JSON.stringify(r,null,2)};\nexport default pageRoutes;\n`}catch{return`export const pageRoutes = [];
19
+ <\/script>`;f+=s}n.statusCode=200,n.setHeader(`Content-Type`,`text/html`),n.setHeader(`Cache-Control`,`private, no-store`),n.end(f)}catch(e){console.error(`[server-islands] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`text/plain`),n.end(`Server island render failed: ${e instanceof Error?e.message:String(e)}`)}}),e.middlewares.use(async(t,n,r)=>{let i=t.url||`/`;if(!i.startsWith(`/_actions/`)||!v)return r();try{let r=F(e.config.root||process.cwd()),[a,o,s]=await Promise.all([e.ssrLoadModule(L(`src/actions/endpoint.ts`)),e.ssrLoadModule(L(`src/actions/registry.ts`)),r?e.ssrLoadModule(r):Promise.resolve({server:{}})]),c=o.flattenActions(s.server),l=a.defineActionHandler({registry:c,isDev:!0}),u=new URL(i,`http://${t.headers.host||`localhost`}`),d=(t.method||`GET`).toUpperCase(),f;d===`POST`&&(f=await new Promise((e,n)=>{let r=[],i=e=>r.push(e),a=()=>{c(),e(Buffer.concat(r).toString(`utf8`))},o=e=>{c(),n(e)},s=setTimeout(()=>{c(),n(Error(`Timed out reading action request body`))},15e3);function c(){clearTimeout(s),t.off(`data`,i),t.off(`end`,a),t.off(`error`,o)}t.on(`data`,i),t.on(`end`,a),t.on(`error`,o)}));let p=await l({url:u,web:{request:new Request(u,{method:d,headers:t.headers,body:f})},context:{}});n.statusCode=p.status,p.headers.forEach((e,t)=>{n.setHeader(t,e)}),n.end(await p.text())}catch(e){console.error(`[actions] Dev handler error:`,e),n.statusCode=500,n.setHeader(`Content-Type`,`application/json`),n.end(JSON.stringify({error:{code:`INTERNAL_SERVER_ERROR`,message:e instanceof Error?e.message:String(e)}}))}}),e.middlewares.use(async(r,i,a)=>{if(!v)return a();let o=r.url||`/`;if(o.endsWith(`.html`)&&(o=o.slice(0,-5)||`/`),o===`/index`&&(o=`/`),o.startsWith(`/@`)||o.startsWith(`/__`)||o.startsWith(`/node_modules/`)||o.startsWith(`/src/client/`)||o.startsWith(`/packages/`)||o.includes(`.`)&&!o.endsWith(`/`)||o.startsWith(`/api/`))return a();try{if(await re(e,o,r,i,m,n)||await se(e,o,t,i))return;let a=await Y(e,o,t);if(a){i.statusCode=200,i.setHeader(`Content-Type`,`text/html`),i.end(a);return}await ie(e,o,i,t)}catch(e){console.error(`[SSR Error]`,e),i.statusCode=500,i.setHeader(`Content-Type`,`text/html`),i.end(E(e))}})},buildStart(){}}}async function re(e,t,n,r,i,a){let o=performance.now(),s=await i();if(s.length===0)return!1;let c={};for(let[e,t]of Object.entries(n.headers))typeof t==`string`?c[e]=t:Array.isArray(t)&&(c[e]=t.join(`, `));let l=`http://${n.headers.host||`localhost`}${t}`,u=await v({url:l,method:n.method||`GET`,path:t,node:{req:n,res:r},req:new Request(l,{method:n.method||`GET`,headers:c}),context:{}},s,{devMode:!1}),d=performance.now()-o;return d>100&&console.warn(`⚠️ Slow middleware: ${d.toFixed(0)}ms for ${t}`),u?(r.statusCode=u.status,u.headers.forEach((e,t)=>{r.setHeader(t,e)}),r.end(await u.text()),!0):!1}async function ie(e,t,n,r){try{let{discoverErrorPages:i,getErrorPageModule:a,generateDefaultErrorPage:o}=await import(`../nitro/error-handler.js`),s=a(404,await i({isDev:r.isDev,pagesDir:r.pagesDir,loadPageModule:async t=>await e.ssrLoadModule(t)}));if(s?.default&&typeof s.default==`function`){let{renderToHtml:e}=await import(`../render/ssr.js`),r=s.default,i=await e({component:()=>r({statusCode:404,message:`Page not found: ${t}`,url:t})},{});n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(i);return}let c=o(404,`Page not found: ${t}`,r.isDev);n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(c)}catch{n.statusCode=404,n.setHeader(`Content-Type`,`text/html`),n.end(D(t))}}async function ae(e,t,n){let r=performance.now(),i=[{path:L(`src/render/ssr.ts`),assignTo:`ssr`},{path:L(`src/core/layout/enhanced-layout-resolver.ts`),assignTo:`layout`},{path:L(`src/middleware/index.ts`),assignTo:null},...t.map(e=>({path:ne(e,`server/renderer.ts`),assignTo:null}))],a=(await Promise.allSettled(i.map(async({path:t,assignTo:n})=>{let r=await e.ssrLoadModule(t);n===`ssr`&&(q=r),n===`layout`&&(J=r)}))).filter(e=>e.status===`fulfilled`).length,o=performance.now()-r;n&&a>0&&console.log(`🔥 SSR ready in ${o.toFixed(0)}ms (${a}/${i.length} core modules)`)}export function createVirtualModulesPlugin(e){let{avalonConfig:n,nitroConfig:r,verbose:i}=e,a=null,o=s,u=c,d=l,f=process.cwd(),p=[];function m(e){try{let n=t(e,{withFileTypes:!0});for(let t of n){let n=o(e,t.name);if(t.isDirectory()&&t.name!==`node_modules`&&!t.name.startsWith(`.`))m(n);else if(t.isFile()&&t.name.endsWith(`.css`)){let e=u(f,n).replaceAll(`\\`,`/`);p.push(e.startsWith(`/`)?e:`/${e}`)}}}catch{}}function h(){p.length=0;for(let e of r.globalCSS??[])p.push(e.startsWith(`/`)?e:`/${e}`);n.modules&&m(d(f,n.modules.dir)),m(d(f,n.layoutsDir));let e=d(f,n.layoutsDir,`..`);e!==f&&e!==d(f,n.layoutsDir)&&e.startsWith(f)&&m(e)}return n.isDev&&h(),{name:`avalon:nitro-virtual-modules`,enforce:`pre`,resolveId(e){return e===VIRTUAL_MODULE_IDS.PAGE_ROUTES?RESOLVED_VIRTUAL_IDS.PAGE_ROUTES:e===VIRTUAL_MODULE_IDS.PAGE_LOADER?RESOLVED_VIRTUAL_IDS.PAGE_LOADER:e===VIRTUAL_MODULE_IDS.ISLAND_MANIFEST?RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST:e===VIRTUAL_MODULE_IDS.RUNTIME_CONFIG?RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG:e===VIRTUAL_MODULE_IDS.CONFIG?RESOLVED_VIRTUAL_IDS.CONFIG:e===VIRTUAL_MODULE_IDS.LAYOUTS?RESOLVED_VIRTUAL_IDS.LAYOUTS:e===VIRTUAL_MODULE_IDS.ASSETS?RESOLVED_VIRTUAL_IDS.ASSETS:e===VIRTUAL_MODULE_IDS.RENDERER?RESOLVED_VIRTUAL_IDS.RENDERER:e===VIRTUAL_MODULE_IDS.CLIENT_ENTRY?RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY:e===VIRTUAL_MODULE_IDS.INTEGRATION_LOADER?RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER:e===VIRTUAL_MODULE_IDS.ACTIONS?RESOLVED_VIRTUAL_IDS.ACTIONS:null},async load(e){return e===RESOLVED_VIRTUAL_IDS.PAGE_ROUTES?await R(n,i):e===RESOLVED_VIRTUAL_IDS.PAGE_LOADER?await z(n,i):e===RESOLVED_VIRTUAL_IDS.ISLAND_MANIFEST?B():e===RESOLVED_VIRTUAL_IDS.RUNTIME_CONFIG?V(n,r):e===RESOLVED_VIRTUAL_IDS.CONFIG?generateConfigModule(n,r):e===RESOLVED_VIRTUAL_IDS.LAYOUTS?(a||=await H(n,r,p),a):e===RESOLVED_VIRTUAL_IDS.ASSETS?U(r):e===RESOLVED_VIRTUAL_IDS.RENDERER?W(n):e===RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY?await G(n,r):e===RESOLVED_VIRTUAL_IDS.INTEGRATION_LOADER?generateIntegrationLoaderModule(n):e===RESOLVED_VIRTUAL_IDS.ACTIONS?te():null},handleHotUpdate({file:e,server:t}){let n=e.includes(`/pages/`)&&!e.endsWith(`.css`),r=e.includes(`/components/`)&&/\.[tj]sx?$/.test(e),i=(e.includes(`/layouts/`)||e.includes(`_layout`))&&/\.[tj]sx?$/.test(e),o=e.endsWith(`.css`);if(n||r||i||o){if(n){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_ROUTES);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.PAGE_LOADER);n&&t.moduleGraph.invalidateModule(n)}if(i){a=null,h();let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.LAYOUTS);e&&t.moduleGraph.invalidateModule(e);let n=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CLIENT_ENTRY);n&&t.moduleGraph.invalidateModule(n)}setTimeout(()=>{t.ws.send({type:`full-reload`,path:`*`})},500)}if(e.includes(`vite.config`)||e.includes(`avalon.config`)||e.includes(`nitro.config`)){let e=t.moduleGraph.getModuleById(RESOLVED_VIRTUAL_IDS.CONFIG);e&&t.moduleGraph.invalidateModule(e)}}}}function oe(e,t,n,r){e.watcher.on(`change`,e=>{e.includes(`_middleware`)&&(g(),r?.()),(e.includes(`/render/`)||e.includes(`/layout/`)||e.includes(`/islands/`))&&(q=null,J=null),(e.includes(`/layouts/`)||e.includes(`_layout`))&&globalThis.__avalonLayoutResolver?.clearCache?.()}),e.watcher.on(`add`,e=>{e.includes(`_middleware`)&&(g(),r?.())}),e.watcher.on(`unlink`,e=>{e.includes(`_middleware`)&&(g(),r?.())})}async function R(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),r=await n(await t(e.pagesDir,e.modules,process.cwd()),{developmentMode:e.isDev});return`export const pageRoutes = ${JSON.stringify(r,null,2)};\nexport default pageRoutes;\n`}catch{return`export const pageRoutes = [];
18
20
  export default pageRoutes;
19
- `}}async function B(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),{relative:r}=await import(`node:path`),i=process.cwd(),a=await n(await t(e.pagesDir,e.modules,i),{developmentMode:e.isDev}),o=[],s=[];for(let e=0;e<a.length;e++){let t=a[e],n=`page_${e}`,c=r(i,t.filePath).replaceAll(`\\`,`/`),l=c.startsWith(`/`)?c:`/${c}`;o.push(`import * as ${n} from '${l}';`),s.push(` { pattern: ${JSON.stringify(t.pattern)}, params: ${JSON.stringify(t.params)}, module: ${n} }`)}return[...o,``,`const routes = [`,s.join(`,
21
+ `}}async function z(e,t){try{let{getAllPageDirs:t}=await import(`./module-discovery.js`),{discoverPageRoutesFromMultipleDirs:n}=await import(`../nitro/route-discovery.js`),{relative:r}=await import(`node:path`),i=process.cwd(),a=await n(await t(e.pagesDir,e.modules,i),{developmentMode:e.isDev}),o=[],s=[];for(let e=0;e<a.length;e++){let t=a[e],n=`page_${e}`,c=r(i,t.filePath).replaceAll(`\\`,`/`),l=c.startsWith(`/`)?c:`/${c}`;o.push(`import * as ${n} from '${l}';`),s.push(` { pattern: ${JSON.stringify(t.pattern)}, params: ${JSON.stringify(t.params)}, module: ${n} }`)}return[...o,``,`const routes = [`,s.join(`,
20
22
  `),`];`,``,`/**`,` * Match a pathname against discovered routes and return the page module.`,` * Uses the same pattern matching as Avalon's route discovery.`,` */`,`export function loadPage(pathname) {`,` const cleanPath = pathname.split('?')[0];`,` for (const route of routes) {`,` if (matchRoute(cleanPath, route.pattern, route.params)) {`,` return route.module;`,` }`,` }`,` return null;`,`}`,``,`function matchRoute(pathname, pattern, paramNames) {`,` // Exact match`,` if (pattern === pathname) return true;`,` // Normalize trailing slashes`,` const normPath = pathname === '/' ? '/' : pathname.replace(/\\/$/, '');`,` const normPattern = pattern === '/' ? '/' : pattern.replace(/\\/$/, '');`,` if (normPath === normPattern) return true;`,` // Dynamic segments: /users/:id matches /users/123`,` if (paramNames.length > 0) {`,` const patternParts = normPattern.split('/');`,` const pathParts = normPath.split('/');`,` if (patternParts.length !== pathParts.length) return false;`,` return patternParts.every((part, i) => part.startsWith(':') || part === pathParts[i]);`,` }`,` return false;`,`}`,``,`export default { loadPage, routes };`,``].join(`
21
23
  `)}catch(e){return console.error(`[page-loader] Failed to generate page loader:`,e),`export function loadPage() { return null; }
22
24
  export default { loadPage, routes: [] };
23
- `}}function V(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
25
+ `}}function B(){return`export const islandManifest = { islands: {}, clientEntry: "", css: [] };
24
26
  export default islandManifest;
25
- `}function H(e,t){let n={avalon:{streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev},...t.runtimeConfig};return`export const runtimeConfig = ${JSON.stringify(n,null,2)};\nexport function useRuntimeConfig() { return runtimeConfig; }\nexport default runtimeConfig;\n`}export function generateConfigModule(e,t){let n=globalThis.__avalonConfig?.isDev??e.isDev,r={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:n,...t.runtimeConfig};return`globalThis.__avalonHydrationMode = "${n?`entry-client`:`per-island`}";\nconst config = ${JSON.stringify(r,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function U(e,t,n){let{getAllLayoutDirs:r}=await import(`./module-discovery.js`),{relative:i,resolve:a}=await import(`node:path`),{stat:o,readFile:c}=await import(`node:fs/promises`),l=process.cwd(),u=await r(e.layoutsDir,e.modules,l),d=[],f=0,p=a(l,e.layoutsDir);for(let{dir:t,prefix:n}of u){let r=s(t,`_layout.tsx`);try{if(!(await o(r)).isFile())continue}catch{continue}let a=i(l,r).replaceAll(`\\`,`/`),c=a.startsWith(`/`)?a:`/${a}`,u=t.startsWith(p),m=u&&!e.modules?`RootLayout`:`Layout_${f}`;d.push({prefix:n,importPath:c,varName:m,isShared:u,filePath:r}),f++}let m=d.filter(e=>e.isShared),h=d.filter(e=>!e.isShared),g=new Map;for(let e of h)try{let t=(await c(e.filePath,`utf8`)).match(/layoutConfig\s*=\s*{[\s\S]*?skipLayouts\s*:\s*\[([^\]]*)\]/)?.[1]??``,n=/['"`]_layout['"`]/.test(t);g.set(e.importPath,n)}catch{g.set(e.importPath,!1)}let _=d.map(e=>`import ${e.varName} from '${e.importPath}';`),v=h.toSorted((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`,n=g.get(e.importPath)??!1,r=t||n;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${r} }`}),y=m.length>0?m[0].varName:`null`,b=JSON.stringify(n);return[`// Auto-generated by Avalon — do not edit`,`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`,`import { getUniversalCSSForHead } from '@useavalon/avalon/islands/universal-css-collector';`,`import { getUniversalHeadForInjection, injectSolidHydrationScriptIfNeeded } from '@useavalon/avalon/islands/universal-head-collector';`,..._,``,`const RootLayoutComponent = ${y};`,`const _cssLinks = ${b};`,``,`const moduleLayouts = [`,v.join(`,
27
+ `}function V(e,t){let n={avalon:{streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:e.isDev},...t.runtimeConfig};return`export const runtimeConfig = ${JSON.stringify(n,null,2)};\nexport function useRuntimeConfig() { return runtimeConfig; }\nexport default runtimeConfig;\n`}export function generateConfigModule(e,t){let n=globalThis.__avalonConfig?.isDev??e.isDev,r={streaming:t.streaming??!0,pagesDir:e.pagesDir,layoutsDir:e.layoutsDir,isDev:n,...t.runtimeConfig};return`globalThis.__avalonHydrationMode = "${n?`entry-client`:`per-island`}";\nconst config = ${JSON.stringify(r,null,2)};\nexport function useAvalonConfig() { return config; }\nexport default config;\n`}async function H(e,t,n){let{getAllLayoutDirs:r}=await import(`./module-discovery.js`),{relative:i,resolve:a}=await import(`node:path`),{stat:o,readFile:c}=await import(`node:fs/promises`),l=process.cwd(),u=await r(e.layoutsDir,e.modules,l),d=[],f=0,p=a(l,e.layoutsDir);for(let{dir:t,prefix:n}of u){let r=s(t,`_layout.tsx`);try{if(!(await o(r)).isFile())continue}catch{continue}let a=i(l,r).replaceAll(`\\`,`/`),c=a.startsWith(`/`)?a:`/${a}`,u=t.startsWith(p),m=u&&!e.modules?`RootLayout`:`Layout_${f}`;d.push({prefix:n,importPath:c,varName:m,isShared:u,filePath:r}),f++}let m=d.filter(e=>e.isShared),h=d.filter(e=>!e.isShared),g=new Map;for(let e of h)try{let t=(await c(e.filePath,`utf8`)).match(/layoutConfig\s*=\s*{[\s\S]*?skipLayouts\s*:\s*\[([^\]]*)\]/)?.[1]??``,n=/['"`]_layout['"`]/.test(t);g.set(e.importPath,n)}catch{g.set(e.importPath,!1)}let _=d.map(e=>`import ${e.varName} from '${e.importPath}';`),v=h.toSorted((e,t)=>t.prefix.length-e.prefix.length).map(e=>{let t=e.prefix===`/`,n=g.get(e.importPath)??!1,r=t||n;return` { prefix: ${JSON.stringify(e.prefix)}, Layout: ${e.varName}, skipRoot: ${r} }`}),y=m.length>0?m[0].varName:`null`,b=JSON.stringify(n);return[`// Auto-generated by Avalon — do not edit`,`import { h } from 'preact';`,`import preactRenderToString from 'preact-render-to-string';`,`import { getUniversalCSSForHead } from '@useavalon/avalon/islands/universal-css-collector';`,`import { getUniversalHeadForInjection, injectSolidHydrationScriptIfNeeded } from '@useavalon/avalon/islands/universal-head-collector';`,..._,``,`const RootLayoutComponent = ${y};`,`const _cssLinks = ${b};`,``,`const moduleLayouts = [`,v.join(`,
26
28
  `),`];`,``,`function getLayoutsForPath(pathname) {`,` for (const entry of moduleLayouts) {`,` if (entry.prefix === '/' ? pathname === '/' : pathname.startsWith(entry.prefix)) {`,` return entry;`,` }`,` }`,` return null;`,`}`,``,`function injectUniversalAssets(html) {`,` // In dev, inject <link> tags for all discovered CSS files.`,` // The ?direct suffix makes Vite return raw CSS (text/css) instead`,` // of a JS module wrapper, so <link rel="stylesheet"> works.`,` if (process.env.NODE_ENV !== 'production' && _cssLinks.length > 0) {`,` var links = _cssLinks.map(function(href) {`,` return '<link rel="stylesheet" href="' + href + '?direct">';`,` }).join('\\n');`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', links + '\\n</head>');`,` }`,` }`,` const universalCSS = getUniversalCSSForHead(true);`,` if (universalCSS && html.includes('</head>')) {`,` html = html.replace('</head>', universalCSS + '\\n</head>');`,` }`,` const universalHead = getUniversalHeadForInjection(true);`,` if (universalHead && html.includes('</head>')) {`,` html = html.replace('</head>', universalHead + '\\n</head>');`,` }`,` html = injectSolidHydrationScriptIfNeeded(html);`,` return html;`,`}`,``,`export async function wrapWithLayouts(pageHtml, pageModule, context, injectAssets) {`,` const pathname = context.url.pathname;`,` const frontmatter = {`,` ...(pageModule.frontmatter || {}),`,` ...(pageModule.metadata || {}),`,` currentPath: pathname,`,` };`,` const pageLayoutConfig = pageModule.layoutConfig;`,` const skipAll = pageLayoutConfig?.skipLayouts?.includes('_layout');`,``,` const layoutEntry = getLayoutsForPath(pathname);`,` const routeInfo = { path: pathname, params: context.params, query: context.url.searchParams };`,` let html;`,``,` if (!layoutEntry || skipAll) {`,` if (RootLayoutComponent && !skipAll) {`,` const rootProps = {`,` children: h('avalon-page', { id: 'app', dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` html = '<!DOCTYPE html>\\n' + preactRenderToString(resolvedRoot);`,` } else {`,` // skipAll is true — page provides its own HTML shell or needs a minimal one`,` if (pageHtml.trimStart().startsWith('<html')) {`,` html = '<!DOCTYPE html>\\n' + pageHtml;`,` } else {`,` const title = String(frontmatter.title || 'Avalon');`,` html = [`,` '<!DOCTYPE html>',`,` '<html lang="en">',`,` '<head>',`,` '<meta charset="utf-8">',`,` '<meta name="viewport" content="width=device-width, initial-scale=1">',`,` '<title>' + title + '</title>',`,` '</head>',`,` '<body>',`,` '<div id="app">' + pageHtml + '</div>',`,` '</body>',`,` '</html>',`,` ].join('\\n');`,` }`,` }`,` } else {`,` const layoutProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: pageHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const layoutResult = layoutEntry.Layout(layoutProps);`,` const resolvedLayout = layoutResult instanceof Promise ? await layoutResult : layoutResult;`,` let wrappedHtml = preactRenderToString(resolvedLayout);`,``,` // If the layout provides its own HTML shell (starts with <html),`,` // skip root wrapping regardless of skipRoot flag — the layout IS the document.`,` const layoutProvidesShell = wrappedHtml.trimStart().startsWith('<html');`,``,` if (!layoutProvidesShell && !layoutEntry.skipRoot && RootLayoutComponent) {`,` const rootProps = {`,` children: h('avalon-page', { dangerouslySetInnerHTML: { __html: wrappedHtml } }),`,` frontmatter,`,` data: {},`,` route: routeInfo,`,` };`,` const rootResult = RootLayoutComponent(rootProps);`,` const resolvedRoot = rootResult instanceof Promise ? await rootResult : rootResult;`,` wrappedHtml = preactRenderToString(resolvedRoot);`,` }`,``,` html = '<!DOCTYPE html>\\n' + wrappedHtml;`,` }`,``,` if (injectAssets) {`,` html = injectAssets(html);`,` }`,` return injectUniversalAssets(html);`,`}`,``,`export default { wrapWithLayouts };`,``].join(`
27
- `)}function W(e){let t=e.clientEntry??`app/entry-client`;return[`// Auto-generated by Avalon — do not edit`,`// @ts-ignore — virtual import resolved by Nitro's Vite assets plugin at build time`,`import clientAssets from '${t.startsWith(`/`)?t:`/${t}`}?assets=client';`,``,`function buildAssetTags() {`,` const cssLinks = (clientAssets?.css ?? [])`,` .filter(attr => {`,` const href = attr.href || '';`,` // The SSR build produces ssr-index-*.css containing all global, reset,`,` // token, and layout CSS module styles. The client build may also emit`,` // entry-client-*.css (a subset) and index-*.css. To avoid duplicates,`,` // prefer ssr-index when it exists; otherwise fall back to the others.`,` var hasSsrIndex = (clientAssets?.css ?? []).some(function(a) { return (a.href || '').includes('ssr-index'); });`,` if (hasSsrIndex) return href.includes('ssr-index');`,` if (href.includes('entry-client') && href.endsWith('.css')) return true;`,` if (/\\/index-[^/]+\\.css$/.test(href)) return true;`,` return false;`,` })`,` .map(attr => '<link rel="stylesheet" href="' + attr.href + '">')`,` .join('\\n');`,` const jsPreloads = (clientAssets?.js ?? [])`,` .map(attr => '<link rel="modulepreload" href="' + attr.href + '">')`,` .join('\\n');`,` const entryScript = clientAssets?.entry`,` ? '<script type="module" src="' + clientAssets.entry + '"><\/script>'`,` : '';`,` return { cssLinks, jsPreloads, entryScript };`,`}`,``,`export function injectAssets(html) {`,` const { cssLinks, jsPreloads, entryScript } = buildAssetTags();`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', cssLinks + '\\n' + jsPreloads + '\\n</head>');`,` }`,` if (html.includes('</body>')) {`,` html = html.replace('</body>', entryScript + '\\n</body>');`,` }`,` return html;`,`}`,``,`export { clientAssets };`,`export default { injectAssets, clientAssets };`,``].join(`
28
- `)}function G(e){let t=Array.isArray(e.integrations)?e.integrations:[],n=[],r=[];for(let e of t){let t=`${e}Integration`;n.push(`import { ${t} } from '@useavalon/${e}';`),r.push(`registry.register(${t});`)}return[`// Auto-generated by Avalon — do not edit`,`import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,`import { registerBuiltinDirectives } from '@useavalon/avalon';`,`import { registry } from '@useavalon/avalon/islands/integration-registry';`,`import avalonConfig from 'virtual:avalon/config';`,`import { loadPage } from 'virtual:avalon/page-loader';`,`import { wrapWithLayouts } from 'virtual:avalon/layouts';`,`import { injectAssets } from 'virtual:avalon/assets';`,...n,``,`// Pre-register framework integrations for SSR`,...r,``,`// Register built-in custom hydration directives (on:delay, on:scroll, etc.)`,`registerBuiltinDirectives();`,``,`// Set hydration mode flag — intentionally duplicated from virtual:avalon/config`,`// for module-load-order resilience (config import may be tree-shaken or deferred).`,`globalThis.__avalonHydrationMode = avalonConfig.isDev ? "entry-client" : "per-island";`,``,`export default createNitroRenderer({`,` avalonConfig,`,` isDev: avalonConfig.isDev,`,` resolvePageRoute: async (pathname) => {`,` const mod = loadPage(pathname);`,` if (!mod || !('default' in mod)) return null;`,` return { filePath: '[virtual:' + pathname + ']', pattern: pathname, params: {} };`,` },`,` loadPageModule: async (filePath) => {`,` const match = filePath.match(/^\\[virtual:(.+)\\]$/);`,` const pathname = match ? match[1] : filePath;`,` const mod = loadPage(pathname);`,` if (mod) return mod;`,` return { default: () => null, metadata: { title: 'Avalon' } };`,` },`,` wrapWithLayouts: (pageHtml, pageModule, context) =>`,` wrapWithLayouts(pageHtml, pageModule, context, injectAssets),`,`});`,``].join(`
29
- `)}async function K(e,t){let{getAllLayoutDirs:n}=await import(`./module-discovery.js`),{readdir:r}=await import(`node:fs/promises`),{relative:i,join:a}=await import(`node:path`),o=process.cwd(),s=await n(e.layoutsDir,e.modules,o),c=[];for(let{dir:e}of s)try{let t=await r(e,{withFileTypes:!0});for(let n of t){if(!n.isFile()||!n.name.endsWith(`.css`))continue;let t=i(o,a(e,n.name)).replaceAll(`\\`,`/`),r=t.startsWith(`/`)?t:`/${t}`;c.push(r)}}catch{}let l=globalThis.__avalonConfig?.isDev??e.isDev?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`,u=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`];(globalThis.__avalonHydrationMode??`entry-client`)===`entry-client`?u.push(`import '${l}';`):u.push(`// Per-island hydration mode — no shared runtime needed`),u.push(``);let d=t.globalCSS??[];for(let e of d){let t=e.startsWith(`/`)?e:`/${e}`;u.push(`// Global CSS`),u.push(`import '${t}';`)}if(d.length>0&&u.push(``),c.length>0){u.push(`// Layout CSS (auto-discovered)`);let e=0;for(let t of c)t.includes(`.module.`)?(u.push(`import _lcss${e} from '${t}';`),e++):u.push(`import '${t}';`)}return u.push(``),u.join(`
29
+ `)}function U(e){let t=e.clientEntry??`app/entry-client`;return[`// Auto-generated by Avalon — do not edit`,`// @ts-ignore — virtual import resolved by Nitro's Vite assets plugin at build time`,`import clientAssets from '${t.startsWith(`/`)?t:`/${t}`}?assets=client';`,``,`function buildAssetTags() {`,` const cssLinks = (clientAssets?.css ?? [])`,` .filter(attr => {`,` const href = attr.href || '';`,` // The SSR build produces ssr-index-*.css containing all global, reset,`,` // token, and layout CSS module styles. The client build may also emit`,` // entry-client-*.css (a subset) and index-*.css. To avoid duplicates,`,` // prefer ssr-index when it exists; otherwise fall back to the others.`,` var hasSsrIndex = (clientAssets?.css ?? []).some(function(a) { return (a.href || '').includes('ssr-index'); });`,` if (hasSsrIndex) return href.includes('ssr-index');`,` if (href.includes('entry-client') && href.endsWith('.css')) return true;`,` if (/\\/index-[^/]+\\.css$/.test(href)) return true;`,` return false;`,` })`,` .map(attr => '<link rel="stylesheet" href="' + attr.href + '">')`,` .join('\\n');`,` const jsPreloads = (clientAssets?.js ?? [])`,` .map(attr => '<link rel="modulepreload" href="' + attr.href + '">')`,` .join('\\n');`,` const entryScript = clientAssets?.entry`,` ? '<script type="module" src="' + clientAssets.entry + '"><\/script>'`,` : '';`,` return { cssLinks, jsPreloads, entryScript };`,`}`,``,`export function injectAssets(html) {`,` const { cssLinks, jsPreloads, entryScript } = buildAssetTags();`,` if (html.includes('</head>')) {`,` html = html.replace('</head>', cssLinks + '\\n' + jsPreloads + '\\n</head>');`,` }`,` if (html.includes('</body>')) {`,` html = html.replace('</body>', entryScript + '\\n</body>');`,` }`,` return html;`,`}`,``,`export { clientAssets };`,`export default { injectAssets, clientAssets };`,``].join(`
30
+ `)}function W(e){let t=Array.isArray(e.integrations)?e.integrations:[],n=[],r=[];for(let e of t){let t=`${e}Integration`;n.push(`import { ${t} } from '@useavalon/${e}';`),r.push(`registry.register(${t});`)}return[`// Auto-generated by Avalon — do not edit`,`import { createNitroRenderer } from '@useavalon/avalon/nitro/renderer';`,`import { registerBuiltinDirectives } from '@useavalon/avalon';`,`import { registry } from '@useavalon/avalon/islands/integration-registry';`,`import avalonConfig from 'virtual:avalon/config';`,`import { loadPage } from 'virtual:avalon/page-loader';`,`import { wrapWithLayouts } from 'virtual:avalon/layouts';`,`import { injectAssets } from 'virtual:avalon/assets';`,...n,``,`// Pre-register framework integrations for SSR`,...r,``,`// Register built-in custom hydration directives (on:delay, on:scroll, etc.)`,`registerBuiltinDirectives();`,``,`// Set hydration mode flag — intentionally duplicated from virtual:avalon/config`,`// for module-load-order resilience (config import may be tree-shaken or deferred).`,`globalThis.__avalonHydrationMode = avalonConfig.isDev ? "entry-client" : "per-island";`,``,`export default createNitroRenderer({`,` avalonConfig,`,` isDev: avalonConfig.isDev,`,` resolvePageRoute: async (pathname) => {`,` const mod = loadPage(pathname);`,` if (!mod || !('default' in mod)) return null;`,` return { filePath: '[virtual:' + pathname + ']', pattern: pathname, params: {} };`,` },`,` loadPageModule: async (filePath) => {`,` const match = filePath.match(/^\\[virtual:(.+)\\]$/);`,` const pathname = match ? match[1] : filePath;`,` const mod = loadPage(pathname);`,` if (mod) return mod;`,` return { default: () => null, metadata: { title: 'Avalon' } };`,` },`,` wrapWithLayouts: (pageHtml, pageModule, context) =>`,` wrapWithLayouts(pageHtml, pageModule, context, injectAssets),`,`});`,``].join(`
31
+ `)}async function G(e,t){let{getAllLayoutDirs:n}=await import(`./module-discovery.js`),{readdir:r}=await import(`node:fs/promises`),{relative:i,join:a}=await import(`node:path`),o=process.cwd(),s=await n(e.layoutsDir,e.modules,o),c=[];for(let{dir:e}of s)try{let t=await r(e,{withFileTypes:!0});for(let n of t){if(!n.isFile()||!n.name.endsWith(`.css`))continue;let t=i(o,a(e,n.name)).replaceAll(`\\`,`/`),r=t.startsWith(`/`)?t:`/${t}`;c.push(r)}}catch{}let l=globalThis.__avalonConfig?.isDev??e.isDev?`@useavalon/avalon/client/main`:`@useavalon/avalon/client/main-slim`,u=[`// Auto-generated by Avalon — do not edit`,`// Island hydration runtime`];(globalThis.__avalonHydrationMode??`entry-client`)===`entry-client`?u.push(`import '${l}';`):u.push(`// Per-island hydration mode — no shared runtime needed`),u.push(``);let d=t.globalCSS??[];for(let e of d){let t=e.startsWith(`/`)?e:`/${e}`;u.push(`// Global CSS`),u.push(`import '${t}';`)}if(d.length>0&&u.push(``),c.length>0){u.push(`// Layout CSS (auto-discovered)`);let e=0;for(let t of c)t.includes(`.module.`)?(u.push(`import _lcss${e} from '${t}';`),e++):u.push(`import '${t}';`)}return u.push(``),u.join(`
30
32
  `)}export function generateIntegrationLoaderModule(e){let t=(e.integrations??[]).map(e=>typeof e==`string`?e:e.name),n={preact:`@useavalon/preact/client`,react:`@useavalon/preact/client`,vue:`@useavalon/vue/client`,svelte:`@useavalon/svelte/client`,solid:`@useavalon/solid/client`,lit:`@useavalon/lit/client`,qwik:`@useavalon/qwik/client`},r={preact:`@useavalon/preact/client/hmr`,react:`@useavalon/react/client/hmr`,vue:`@useavalon/vue/client/hmr`,svelte:`@useavalon/svelte/client/hmr`,solid:`@useavalon/solid/client/hmr`,lit:`@useavalon/lit/client/hmr`,qwik:`@useavalon/qwik/client/hmr`},i=t.includes(`lit`),a=t.includes(`solid`),o=(globalThis.__avalonConfig?.isDev??e.isDev)===!0,s=[`// Auto-generated by Avalon — only includes configured integrations`,``];a&&!o&&(s.push(`// --- Inlined Solid adapter (production) ---`),s.push(`// Eliminates a separate chunk + network request for the Solid client adapter.`),s.push(`// Only imports hydrate/createComponent — no render() fallback (saves ~1-2 KiB).`),s.push(`function _ensureHydrationContext() {`),s.push(` if (!globalThis._$HY) {`),s.push(` globalThis._$HY = { events: [], completed: new WeakSet(), r: {}, fe() {} };`),s.push(` }`),s.push(`}`),s.push(``),s.push(`async function _solidHydrate(container, Component, props) {`),s.push(` if (!container) throw new Error("Container element is required for hydration");`),s.push(` if (!Component || typeof Component !== "function") {`),s.push(` throw new Error("Invalid Solid component: expected function, got " + typeof Component);`),s.push(` }`),s.push(` var el = container;`),s.push(` var renderId = el.dataset.solidRenderId || el.dataset.renderId;`),s.push(` var { hydrate: solidHydrate, createComponent } = await import("solid-js/web");`),s.push(` _ensureHydrationContext();`),s.push(` solidHydrate(function() { return createComponent(Component, props || {}); }, el, { renderId: renderId || "" });`),s.push(`}`),s.push(``),s.push(`var _solidModule = { hydrate: _solidHydrate };`),s.push(``)),s.push(`// --- loadIntegrationModule ---`),s.push(`export async function loadIntegrationModule(framework) {`),s.push(` switch (framework) {`);for(let e of t){let t=n[e];t&&(e===`solid`&&!o?(s.push(` case "solid":`),s.push(` return _solidModule;`)):e===`react`?s.push(` case "react":`):e===`preact`?(s.push(` case "preact":`),s.push(` return import("${t}");`)):(s.push(` case "${e}":`),s.push(` return import("${t}");`)))}t.includes(`react`)&&!t.includes(`preact`)&&s.push(` return import("${n.react}");`),s.push(` default:`),s.push(" throw new Error(`Unknown or unconfigured framework: ${framework}`);"),s.push(` }`),s.push(`}`),s.push(``),s.push(`// --- Lit hydration pre-load (only if Lit is configured) ---`),i?(s.push(`export async function preLitHydration() {`),s.push(` await import("@useavalon/lit/client");`),s.push(`}`)):s.push(`export async function preLitHydration() {}`),s.push(``),s.push(`// --- HMR adapter loader ---`),s.push(`export async function loadHMRAdapter(framework) {`),s.push(` switch (framework) {`);for(let e of t){let t=r[e];t&&(s.push(` case "${e}":`),s.push(` return import("${t}").then(m => m.${e}Adapter);`))}return s.push(` default: return null;`),s.push(` }`),s.push(`}`),s.join(`
31
- `)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const q=`<!--AVALON_STREAM_BOUNDARY-->`;let J=null,Y=null;async function ne(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Q(i,n,e);if(!a)return!1;try{let t=await e.ssrLoadModule(a),n=t.default;if(!n)return!1;let o=t.layoutConfig,s=await C(e,a),c=await Z(i,e),l=[];for(let t of c){let n=await e.ssrLoadModule(t);l.push({file:t,module:n})}for(let t of c){let n=await C(e,t);s.push(...n)}if(l.length===0)return!1;let{render:u}=await e.ssrLoadModule(`preact-render-to-string`),{h:d}=await e.ssrLoadModule(`preact`),h=o?.skipLayouts||[],g=l.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!h.includes(t)}),_=t.frontmatter,v=t.metadata,y={children:null,frontmatter:{..._,...v,currentPath:i},params:{},url:i},b=[],x=[];for(let e of g){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...y,children:d(`div`,null,`test`)}),r=u(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?b.push(e):x.push(e)}catch{x.push(e)}}if(b.length===0)return!1;let{module:S}=b[b.length-1],w=S.default;if(!w||typeof w!=`function`)return!1;let T;try{let e=w({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:q}})});T=u(e instanceof Promise?await e:e)}catch{return!1}let E=T.indexOf(q);if(E===-1)return!1;let D=T.slice(0,E),O=T.slice(E+29),k=D;if(s.length>0){let e=`<style data-avalon-ssr-css>${s.join(`
32
- `)}</style>`;k=D.includes(`</head>`)?D.replace(`</head>`,`${e}\n</head>`):D+e}k.trim().toLowerCase().startsWith(`<!doctype`)||(k=`<!DOCTYPE html>\n${k}`);let A=f(!0);A&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${A}\n</head>`));let j=p(!0);j&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${j}\n</head>`)),k=m(k),r.statusCode=200,r.setHeader(`Content-Type`,`text/html; charset=utf-8`),r.setHeader(`Transfer-Encoding`,`chunked`),r.setHeader(`X-Avalon-Streaming`,`1`),r.flushHeaders(),r.write(k);let M;try{let e=typeof n==`function`?n():n;M=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering page component:`,e),M=`<div>Error rendering page</div>`}if(M.trim().startsWith(`<!DOCTYPE html>`)||M.trim().startsWith(`<html`))return r.end(M),!0;let N=M;for(let{module:e}of x){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:N}})});N=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering wrapper layout:`,e)}}let P=N+O;if(!P.includes(`/src/client/main.js`)&&!P.includes(`/@vite/client`)){let e=P.lastIndexOf(`</body>`);e!==-1&&(P=P.slice(0,e)+`
33
+ `)}export function getViteDevServer(){return globalThis.__viteDevServer}export function getAvalonConfig(){return globalThis.__avalonConfig}export function isDevelopmentMode(){return globalThis.__avalonConfig?.isDev??!0}const K=`<!--AVALON_STREAM_BOUNDARY-->`;let q=null,J=null;async function se(e,t,n,r){if(!n.modules)return!1;let i=t.split(`?`)[0],a=await Q(i,n,e);if(!a)return!1;try{let t=await e.ssrLoadModule(a),n=t.default;if(!n)return!1;let o=t.layoutConfig,s=await w(e,a),c=await Z(i,e),l=[];for(let t of c){let n=await e.ssrLoadModule(t);l.push({file:t,module:n})}for(let t of c){let n=await w(e,t);s.push(...n)}if(l.length===0)return!1;let{render:u}=await e.ssrLoadModule(`preact-render-to-string`),{h:d}=await e.ssrLoadModule(`preact`),f=o?.skipLayouts||[],g=l.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!f.includes(t)}),_=t.frontmatter,v=t.metadata,y={children:null,frontmatter:{..._,...v,currentPath:i},params:{},url:i},b=[],x=[];for(let e of g){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...y,children:d(`div`,null,`test`)}),r=u(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?b.push(e):x.push(e)}catch{x.push(e)}}if(b.length===0)return!1;let{module:S}=b[b.length-1],C=S.default;if(!C||typeof C!=`function`)return!1;let T;try{let e=C({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:K}})});T=u(e instanceof Promise?await e:e)}catch{return!1}let E=T.indexOf(K);if(E===-1)return!1;let D=T.slice(0,E),O=T.slice(E+29),k=D;if(s.length>0){let e=`<style data-avalon-ssr-css>${s.join(`
34
+ `)}</style>`;k=D.includes(`</head>`)?D.replace(`</head>`,`${e}\n</head>`):D+e}k.trim().toLowerCase().startsWith(`<!doctype`)||(k=`<!DOCTYPE html>\n${k}`);let A=p(!0);A&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${A}\n</head>`));let j=m(!0);j&&k.includes(`</head>`)&&(k=k.replace(`</head>`,`${j}\n</head>`)),k=h(k),r.statusCode=200,r.setHeader(`Content-Type`,`text/html; charset=utf-8`),r.setHeader(`Transfer-Encoding`,`chunked`),r.setHeader(`X-Avalon-Streaming`,`1`),r.flushHeaders(),r.write(k);let M;try{let e=typeof n==`function`?n():n;M=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering page component:`,e),M=`<div>Error rendering page</div>`}if(M.trim().startsWith(`<!DOCTYPE html>`)||M.trim().startsWith(`<html`))return r.end(M),!0;let N=M;for(let{module:e}of x){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...y,children:d(`div`,{dangerouslySetInnerHTML:{__html:N}})});N=u(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR Streaming] Error rendering wrapper layout:`,e)}}let P=N+O;if(!P.includes(`/src/client/main.js`)&&!P.includes(`/@vite/client`)){let e=P.lastIndexOf(`</body>`);e!==-1&&(P=P.slice(0,e)+`
33
35
  <script type="module" src="/@vite/client"><\/script>
34
36
  <script type="module" src="/src/client/main.js"><\/script>
35
- `+P.slice(e))}return r.end(P),!0}catch(e){return r.headersSent?(r.end(`<div>Streaming SSR error: ${e.message}</div></body></html>`),!0):!1}}async function re(e,t,n){let r=t.split(`?`)[0],i=await Q(r,n,e);if(!i)return null;try{let t=await e.ssrLoadModule(i),a=t.default;if(!a)return console.warn(`[SSR] Page ${i} has no default export`),null;let o=await C(e,i),s=await Z(r,e),c=[];for(let t of s){let n=await e.ssrLoadModule(t);c.push({file:t,module:n})}for(let t of s){let n=await C(e,t);o.push(...n)}let l;return l=n.modules&&c.length>0?await ie(a,t,c,r,n,e):await ae(a,t,r,n,e),o.length>0&&(l=w(l,o)),l}catch(e){throw console.error(`[SSR] Error rendering ${i}:`,e),e}}async function ie(e,t,n,r,i,a){let{render:o}=await a.ssrLoadModule(`preact-render-to-string`),{h:s}=await a.ssrLoadModule(`preact`),c=t.layoutConfig?.skipLayouts||[],l=n.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!c.includes(t)}),u;try{let t=typeof e==`function`?e():e;u=o(t instanceof Promise?await t:t)}catch(e){console.error(`[SSR] Error rendering page component:`,e),u=`<div>Error rendering page</div>`}if(u.trim().startsWith(`<!DOCTYPE html>`)||u.trim().startsWith(`<html`))return X(u);let d=t.frontmatter,f=t.metadata,p={children:null,frontmatter:{...d,...f,currentPath:r},params:{},url:r},m=[],h=[];for(let e of l){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...p,children:s(`div`,null,`test`)}),r=o(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?m.push(e):h.push(e)}catch{h.push(e)}}let g=u;for(let{module:e}of h){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering wrapper layout:`,e)}}if(m.length>0){let{module:e}=m[m.length-1],t=e.default;if(t&&typeof t==`function`)try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering shell layout:`,e)}}if(g.trim().startsWith(`<!DOCTYPE html>`)||g.trim().startsWith(`<html`))return X(g);let _=t.metadata||{},v=_.title||`Avalon App`,y=_.description||``;return`<!DOCTYPE html>
37
+ `+P.slice(e))}return r.end(P),!0}catch(e){return r.headersSent?(r.end(`<div>Streaming SSR error: ${e.message}</div></body></html>`),!0):!1}}async function Y(e,t,n){let r=t.split(`?`)[0],i=await Q(r,n,e);if(!i)return null;try{let t=await e.ssrLoadModule(i),a=t.default;if(!a)return console.warn(`[SSR] Page ${i} has no default export`),null;let o=await w(e,i),s=await Z(r,e),c=[];for(let t of s){let n=await e.ssrLoadModule(t);c.push({file:t,module:n})}for(let t of s){let n=await w(e,t);o.push(...n)}let l;return l=n.modules&&c.length>0?await ce(a,t,c,r,n,e):await le(a,t,r,n,e),o.length>0&&(l=T(l,o)),l}catch(e){throw console.error(`[SSR] Error rendering ${i}:`,e),e}}async function ce(e,t,n,r,i,a){let{render:o}=await a.ssrLoadModule(`preact-render-to-string`),{h:s}=await a.ssrLoadModule(`preact`),c=t.layoutConfig?.skipLayouts||[],l=n.filter(({file:e})=>{let t=e.split(`/`).pop()?.replace(/\.[^.]+$/,``)||``;return!c.includes(t)}),u;try{let t=typeof e==`function`?e():e;u=o(t instanceof Promise?await t:t)}catch(e){console.error(`[SSR] Error rendering page component:`,e),u=`<div>Error rendering page</div>`}if(u.trim().startsWith(`<!DOCTYPE html>`)||u.trim().startsWith(`<html`))return X(u);let d=t.frontmatter,f=t.metadata,p={children:null,frontmatter:{...d,...f,currentPath:r},params:{},url:r},m=[],h=[];for(let e of l){let t=e.module.default;if(!(!t||typeof t!=`function`))try{let n=t({...p,children:s(`div`,null,`test`)}),r=o(n instanceof Promise?await n:n);r.trim().startsWith(`<html`)||r.includes(`<!DOCTYPE`)?m.push(e):h.push(e)}catch{h.push(e)}}let g=u;for(let{module:e}of h){let t=e.default;if(!(!t||typeof t!=`function`))try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering wrapper layout:`,e)}}if(m.length>0){let{module:e}=m[m.length-1],t=e.default;if(t&&typeof t==`function`)try{let e=t({...p,children:s(`div`,{dangerouslySetInnerHTML:{__html:g}})});g=o(e instanceof Promise?await e:e)}catch(e){console.error(`[SSR] Error rendering shell layout:`,e)}}if(g.trim().startsWith(`<!DOCTYPE html>`)||g.trim().startsWith(`<html`))return X(g);let _=t.metadata||{},v=_.title||`Avalon App`,y=_.description||``;return`<!DOCTYPE html>
36
38
  <html lang="en">
37
39
  <head>
38
40
  <meta charset="utf-8">
@@ -45,12 +47,12 @@ export default islandManifest;
45
47
  ${g}
46
48
  <script type="module" src="/src/client/main.js"><\/script>
47
49
  </body>
48
- </html>`}function X(e){let t=e;if(t.trim().toLowerCase().startsWith(`<!doctype`)||(t=`<!DOCTYPE html>\n${t}`),!t.includes(`data-universal-ssr="true"`)){let e=f(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=p(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t=m(t),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
50
+ </html>`}function X(e){let t=e;if(t.trim().toLowerCase().startsWith(`<!doctype`)||(t=`<!DOCTYPE html>\n${t}`),!t.includes(`data-universal-ssr="true"`)){let e=p(!0);e&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${e}\n</head>`))}let n=m(!0);if(n&&t.includes(`</head>`)&&(t=t.replace(`</head>`,`${n}\n</head>`)),t=h(t),t.includes(`/src/client/main.js`)||t.includes(`/@vite/client`))return t;let r=t.lastIndexOf(`</body>`);return r===-1?t+`
49
51
  <script type="module" src="/@vite/client"><\/script>
50
52
  <script type="module" src="/src/client/main.js"><\/script>`:t.slice(0,r)+`
51
53
  <script type="module" src="/@vite/client"><\/script>
52
54
  <script type="module" src="/src/client/main.js"><\/script>
53
- `+t.slice(r)}async function Z(e,t){let n=t.config.root||process.cwd(),r=globalThis.__avalonConfig,a=`_layout.tsx`,o=[],s=e.split(`/`).filter(Boolean),c=[``];for(let e=0;e<s.length;e++)c.push(`/${s.slice(0,e+1).join(`/`)}`);async function l(e){try{if((await i(e)).isFile()){let t=e.slice(n.length);o.includes(t)||o.push(t)}}catch{}}if(r?.layoutsDir&&await l(`${`${n}/${r.layoutsDir}`}/${a}`),r?.modules){let e=`${n}/${r.modules.dir}`,t=r.modules.layoutsDirName,i=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!i||o.includes(i.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${i}/${t}/${a}`)}let u=`${n}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Q(e,t,n){let r=e;r.endsWith(`/`)&&r!==`/`&&(r=r.slice(0,-1)),r===`/`&&(r=`/index`);let a=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],o=n.config.root||process.cwd();async function s(e){try{if((await i(`${o}/${e}`)).isFile())return`/${e}`}catch{}return null}if(t.modules){let n=t.modules.dir,i=t.modules.pagesDirName,o=e.split(`/`).filter(Boolean),c=o[0]||``,l=[`home`,`root`,`main`,`index`],u,d;if(!c||l.includes(c.toLowerCase()))u=`home`,d=r;else{u=c;let e=o.slice(1);d=e.length>0?`/${e.join(`/`)}`:`/index`}for(let e of a){let t=await s(`${n}/${u}/${i}${d}${e}`);if(t)return t}if(!d.endsWith(`/index`))for(let e of a){let t=await s(`${n}/${u}/${i}${d}/index${e}`);if(t)return t}}let c=t.pagesDir;for(let e of a){let t=await s(`${c}${r}${e}`);if(t)return t}if(!r.endsWith(`/index`))for(let e of a){let t=await s(`${c}${r}/index${e}`);if(t)return t}return null}async function ae(e,t,n,r,i){let a=t.metadata||{};try{J||=await i.ssrLoadModule(F(`src/render/ssr.ts`));let o=J;Y||=await i.ssrLoadModule(F(`src/core/layout/enhanced-layout-resolver.ts`));let s=Y,c={component:()=>typeof e==`function`?e():e,options:{title:a.title||`Avalon App`},frontmatter:t.frontmatter};if(o.renderToHtmlWithLayouts&&s.EnhancedLayoutResolver&&s.EnhancedLayoutResolverUtils)try{let e=i.config.root||process.cwd();if(!globalThis.__avalonLayoutResolver){let t=s.EnhancedLayoutResolver,n=r.layoutsDir||`src/layouts`;globalThis.__avalonLayoutResolver=new t({baseDirectory:`${e}/${n}`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`,`build`],enableWatching:!0,developmentMode:!1,enableCaching:!0,cacheTTL:60*1e3,maxCacheSize:100,enableStreaming:!0,enableErrorBoundaries:!0,enableMetrics:!1,enableDebugInfo:!1,modulesDir:r.modules?`${e}/${r.modules.dir}`:void 0,modulesLayoutsDirName:r.modules?.layoutsDirName})}let t=`http://localhost${n}`,l={params:{},query:{},url:t,request:{method:`GET`,url:t,headers:new Headers}};return await o.renderToHtmlWithLayouts(c,globalThis.__avalonLayoutResolver,l,n,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}if(o.renderToHtml)return await o.renderToHtml(c,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}let o=a.title||`Avalon App`,s=a.description||``,c=``;try{let t=await i.ssrLoadModule(`preact-render-to-string`);t.render&&typeof e==`function`&&(c=t.render(e()))}catch{c=`<p>Loading page: ${$(n)}</p>`}return`<!DOCTYPE html>
55
+ `+t.slice(r)}async function Z(e,t){let n=t.config.root||process.cwd(),r=globalThis.__avalonConfig,a=`_layout.tsx`,o=[],s=e.split(`/`).filter(Boolean),c=[``];for(let e=0;e<s.length;e++)c.push(`/${s.slice(0,e+1).join(`/`)}`);async function l(e){try{if((await i(e)).isFile()){let t=e.slice(n.length);o.includes(t)||o.push(t)}}catch{}}if(r?.layoutsDir&&await l(`${`${n}/${r.layoutsDir}`}/${a}`),r?.modules){let e=`${n}/${r.modules.dir}`,t=r.modules.layoutsDirName,i=s[0]||``,o=[`home`,`root`,`main`,`index`];if(!i||o.includes(i.toLowerCase()))for(let n of o)await l(`${e}/${n}/${t}/${a}`);else await l(`${e}/${i}/${t}/${a}`)}let u=`${n}/src/layouts`;for(let e of c)await l(e===``?`${u}/${a}`:`${u}${e}/${a}`);return o}async function Q(e,t,n){let r=e;r.endsWith(`/`)&&r!==`/`&&(r=r.slice(0,-1)),r===`/`&&(r=`/index`);let a=[`.tsx`,`.ts`,`.jsx`,`.js`,`.mdx`,`.md`],o=n.config.root||process.cwd();async function s(e){try{if((await i(`${o}/${e}`)).isFile())return`/${e}`}catch{}return null}if(t.modules){let n=t.modules.dir,i=t.modules.pagesDirName,o=e.split(`/`).filter(Boolean),c=o[0]||``,l=[`home`,`root`,`main`,`index`],u,d;if(!c||l.includes(c.toLowerCase()))u=`home`,d=r;else{u=c;let e=o.slice(1);d=e.length>0?`/${e.join(`/`)}`:`/index`}for(let e of a){let t=await s(`${n}/${u}/${i}${d}${e}`);if(t)return t}if(!d.endsWith(`/index`))for(let e of a){let t=await s(`${n}/${u}/${i}${d}/index${e}`);if(t)return t}}let c=t.pagesDir;for(let e of a){let t=await s(`${c}${r}${e}`);if(t)return t}if(!r.endsWith(`/index`))for(let e of a){let t=await s(`${c}${r}/index${e}`);if(t)return t}return null}async function le(e,t,n,r,i){let a=t.metadata||{};try{q||=await i.ssrLoadModule(L(`src/render/ssr.ts`));let o=q;J||=await i.ssrLoadModule(L(`src/core/layout/enhanced-layout-resolver.ts`));let s=J,c={component:()=>typeof e==`function`?e():e,options:{title:a.title||`Avalon App`},frontmatter:t.frontmatter};if(o.renderToHtmlWithLayouts&&s.EnhancedLayoutResolver&&s.EnhancedLayoutResolverUtils)try{let e=i.config.root||process.cwd();if(!globalThis.__avalonLayoutResolver){let t=s.EnhancedLayoutResolver,n=r.layoutsDir||`src/layouts`;globalThis.__avalonLayoutResolver=new t({baseDirectory:`${e}/${n}`,filePattern:`_layout.tsx`,excludeDirectories:[`node_modules`,`.git`,`dist`,`build`],enableWatching:!0,developmentMode:!1,enableCaching:!0,cacheTTL:60*1e3,maxCacheSize:100,enableStreaming:!0,enableErrorBoundaries:!0,enableMetrics:!1,enableDebugInfo:!1,modulesDir:r.modules?`${e}/${r.modules.dir}`:void 0,modulesLayoutsDirName:r.modules?.layoutsDirName})}let t=`http://localhost${n}`,l={params:{},query:{},url:t,request:{method:`GET`,url:t,headers:new Headers}};return await o.renderToHtmlWithLayouts(c,globalThis.__avalonLayoutResolver,l,n,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}if(o.renderToHtml)return await o.renderToHtml(c,{title:a.title||`Avalon App`},void 0,{suppressWarnings:!0})}catch{}let o=a.title||`Avalon App`,s=a.description||``,c=``;try{let t=await i.ssrLoadModule(`preact-render-to-string`);t.render&&typeof e==`function`&&(c=t.render(e()))}catch{c=`<p>Loading page: ${$(n)}</p>`}return`<!DOCTYPE html>
54
56
  <html lang="en">
55
57
  <head>
56
58
  <meta charset="utf-8">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useavalon/avalon",
3
- "version": "0.1.93-canary.1",
3
+ "version": "0.1.94-canary.1",
4
4
  "description": "Multi-framework islands architecture for the modern web",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -43,6 +43,10 @@
43
43
  "types": "./dist/mod.d.ts",
44
44
  "default": "./dist/mod.js"
45
45
  },
46
+ "./actions": {
47
+ "types": "./dist/src/actions/define.d.ts",
48
+ "default": "./dist/src/actions/define.js"
49
+ },
46
50
  "./client": {
47
51
  "types": "./dist/src/client/components.d.ts",
48
52
  "default": "./dist/src/client/components.js"
@@ -147,7 +151,7 @@
147
151
  }
148
152
  },
149
153
  "dependencies": {
150
- "@useavalon/core": "^0.1.11-canary.1",
154
+ "@useavalon/core": "^0.1.12-canary.1",
151
155
  "@mdx-js/rollup": "^3.0.0",
152
156
  "h3": "^2.0.1-rc.16",
153
157
  "marked": "^17.0.4",