@sigx/server-renderer 0.1.6 → 0.1.8
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/builtin-ssr-directives.d.ts +8 -0
- package/dist/builtin-ssr-directives.d.ts.map +1 -0
- package/dist/client/hydrate-component.d.ts +32 -0
- package/dist/client/hydrate-component.d.ts.map +1 -0
- package/dist/client/hydrate-context.d.ts +54 -0
- package/dist/client/hydrate-context.d.ts.map +1 -0
- package/dist/client/hydrate-core.d.ts +33 -0
- package/dist/client/hydrate-core.d.ts.map +1 -0
- package/dist/client/index.d.ts +8 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client-directives.d.ts +3 -36
- package/dist/client-directives.d.ts.map +1 -1
- package/dist/client-ggDL-Wx2.js +309 -0
- package/dist/client-ggDL-Wx2.js.map +1 -0
- package/dist/directive-ssr-types.d.ts +23 -0
- package/dist/directive-ssr-types.d.ts.map +1 -0
- package/dist/head.d.ts +97 -0
- package/dist/head.d.ts.map +1 -0
- package/dist/index.d.ts +22 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +124 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/server/context.d.ts +52 -59
- package/dist/server/context.d.ts.map +1 -1
- package/dist/server/index.d.ts +9 -4
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +3 -2
- package/dist/server/render-api.d.ts +64 -0
- package/dist/server/render-api.d.ts.map +1 -0
- package/dist/server/render-core.d.ts +46 -0
- package/dist/server/render-core.d.ts.map +1 -0
- package/dist/server/streaming.d.ts +24 -0
- package/dist/server/streaming.d.ts.map +1 -0
- package/dist/server/types.d.ts +40 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server-UBcHtkm-.js +829 -0
- package/dist/server-UBcHtkm-.js.map +1 -0
- package/dist/ssr.d.ts +38 -0
- package/dist/ssr.d.ts.map +1 -0
- package/dist/types-B4Rf1Xot.js +6 -0
- package/dist/types-B4Rf1Xot.js.map +1 -0
- package/package.json +5 -10
- package/dist/client/hydrate.d.ts +0 -24
- package/dist/client/hydrate.d.ts.map +0 -1
- package/dist/client/registry.d.ts +0 -54
- package/dist/client/registry.d.ts.map +0 -1
- package/dist/client/types.d.ts +0 -23
- package/dist/client/types.d.ts.map +0 -1
- package/dist/client-DiLwBAD-.js +0 -541
- package/dist/client-DiLwBAD-.js.map +0 -1
- package/dist/server/stream.d.ts +0 -62
- package/dist/server/stream.d.ts.map +0 -1
- package/dist/server-BCOJt2Bi.js +0 -459
- package/dist/server-BCOJt2Bi.js.map +0 -1
- package/dist/shared/utils.d.ts +0 -9
- package/dist/shared/utils.d.ts.map +0 -1
- package/src/jsx.d.ts +0 -62
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initialize SSR support for all built-in directives.
|
|
3
|
+
*
|
|
4
|
+
* Must be called before any SSR rendering occurs.
|
|
5
|
+
* Safe to call multiple times — only patches once.
|
|
6
|
+
*/
|
|
7
|
+
export declare function initDirectivesForSSR(): void;
|
|
8
|
+
//# sourceMappingURL=builtin-ssr-directives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-ssr-directives.d.ts","sourceRoot":"","sources":["../src/builtin-ssr-directives.ts"],"names":[],"mappings":"AA4BA;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAI3C"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component hydration logic — strategy-agnostic
|
|
3
|
+
*
|
|
4
|
+
* Handles running component setup, creating reactive effects,
|
|
5
|
+
* and restoring server state for hydrated components.
|
|
6
|
+
* Does not depend on islands or any specific SSR strategy.
|
|
7
|
+
*/
|
|
8
|
+
import { VNode } from 'sigx';
|
|
9
|
+
/**
|
|
10
|
+
* Minimal type for component factories used in hydration.
|
|
11
|
+
* Compatible with ComponentFactory from runtime-core.
|
|
12
|
+
*/
|
|
13
|
+
export interface ComponentFactory {
|
|
14
|
+
__setup: Function;
|
|
15
|
+
__name?: string;
|
|
16
|
+
__async?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Hydrate a component - run setup and create reactive effect
|
|
20
|
+
*
|
|
21
|
+
* With trailing markers, the structure is: <content><!--$c:id-->
|
|
22
|
+
* - dom points to start of content
|
|
23
|
+
* - trailingMarker (if provided) is the anchor at the end
|
|
24
|
+
*
|
|
25
|
+
* @param vnode - The VNode to hydrate
|
|
26
|
+
* @param dom - The DOM node to start from (content starts here)
|
|
27
|
+
* @param parent - The parent node
|
|
28
|
+
* @param serverState - Optional state captured from server for async components
|
|
29
|
+
* @param trailingMarker - Optional trailing marker comment (the component anchor)
|
|
30
|
+
*/
|
|
31
|
+
export declare function hydrateComponent(vnode: VNode, dom: Node | null, parent: Node, serverState?: Record<string, any>, trailingMarker?: Comment | null): Node | null;
|
|
32
|
+
//# sourceMappingURL=hydrate-component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrate-component.d.ts","sourceRoot":"","sources":["../../src/client/hydrate-component.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACH,KAAK,EAiBR,MAAM,MAAM,CAAC;AAQd;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAwL9J"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hydration context and state management
|
|
3
|
+
*
|
|
4
|
+
* Manages server state restoration, app context tracking,
|
|
5
|
+
* client plugin registration, and the SSR context extension for components.
|
|
6
|
+
*
|
|
7
|
+
* Strategy-specific concerns (island data, async hydration) are handled
|
|
8
|
+
* by plugins registered via `registerClientPlugin()`.
|
|
9
|
+
*/
|
|
10
|
+
import { VNode } from 'sigx';
|
|
11
|
+
import type { AppContext } from 'sigx';
|
|
12
|
+
import type { SSRPlugin } from '../plugin';
|
|
13
|
+
import type { SSRSignalFn } from '../server/types';
|
|
14
|
+
export interface InternalVNode extends VNode {
|
|
15
|
+
_subTree?: VNode;
|
|
16
|
+
_effect?: any;
|
|
17
|
+
_componentProps?: any;
|
|
18
|
+
_slots?: any;
|
|
19
|
+
}
|
|
20
|
+
export type { SSRSignalFn };
|
|
21
|
+
/**
|
|
22
|
+
* Register a client-side SSR plugin.
|
|
23
|
+
* Plugins are called during hydration to intercept component processing,
|
|
24
|
+
* skip default hydration walk, or run post-hydration logic.
|
|
25
|
+
*/
|
|
26
|
+
export declare function registerClientPlugin(plugin: SSRPlugin): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get all registered client-side plugins.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getClientPlugins(): SSRPlugin[];
|
|
31
|
+
/**
|
|
32
|
+
* Clear all registered client plugins (useful for testing).
|
|
33
|
+
*/
|
|
34
|
+
export declare function clearClientPlugins(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Set server state that should be used for the next component mount.
|
|
37
|
+
* Used internally when mounting async components after streaming.
|
|
38
|
+
*/
|
|
39
|
+
export declare function setPendingServerState(state: Record<string, any> | null): void;
|
|
40
|
+
/** Get the current app context for deferred hydration */
|
|
41
|
+
export declare function getCurrentAppContext(): AppContext | null;
|
|
42
|
+
/** Set the current app context during hydration */
|
|
43
|
+
export declare function setCurrentAppContext(ctx: AppContext | null): void;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a signal function that restores state from server-captured values.
|
|
46
|
+
* Used during hydration of async components to avoid re-fetching data.
|
|
47
|
+
* Supports both primitive and object signals.
|
|
48
|
+
*/
|
|
49
|
+
export declare function createRestoringSignal(serverState: Record<string, any>): SSRSignalFn;
|
|
50
|
+
/**
|
|
51
|
+
* Normalize any element to VNode
|
|
52
|
+
*/
|
|
53
|
+
export declare function normalizeElement(element: any): VNode | null;
|
|
54
|
+
//# sourceMappingURL=hydrate-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrate-context.d.ts","sourceRoot":"","sources":["../../src/client/hydrate-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACH,KAAK,EAIR,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAKnD,MAAM,WAAW,aAAc,SAAQ,KAAK;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,MAAM,CAAC,EAAE,GAAG,CAAC;CAChB;AAGD,YAAY,EAAE,WAAW,EAAE,CAAC;AAgB5B;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,SAAS,EAAE,CAE9C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAID;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAE7E;AAED,yDAAyD;AACzD,wBAAgB,oBAAoB,IAAI,UAAU,GAAG,IAAI,CAExD;AAED,mDAAmD;AACnD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAEjE;AAID;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,WAAW,CA0BnF;AAID;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,GAAG,GAAG,KAAK,GAAG,IAAI,CAiB3D"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core hydration logic — strategy-agnostic
|
|
3
|
+
*
|
|
4
|
+
* Walks existing server-rendered DOM and attaches event handlers,
|
|
5
|
+
* creates reactive effects, and delegates components to the component hydrator.
|
|
6
|
+
*
|
|
7
|
+
* Plugins registered via `registerClientPlugin()` can intercept component
|
|
8
|
+
* hydration (e.g., for deferred/island-based hydration strategies).
|
|
9
|
+
*/
|
|
10
|
+
import { VNode } from 'sigx';
|
|
11
|
+
import type { AppContext } from 'sigx';
|
|
12
|
+
/**
|
|
13
|
+
* Hydrate a server-rendered app.
|
|
14
|
+
*
|
|
15
|
+
* This walks the existing DOM to attach event handlers, runs component
|
|
16
|
+
* setup functions to establish reactivity, then uses runtime-dom for updates.
|
|
17
|
+
*
|
|
18
|
+
* Registered client plugins are called at appropriate points:
|
|
19
|
+
* - `beforeHydrate`: before the DOM walk (return false to skip it entirely)
|
|
20
|
+
* - `hydrateComponent`: for each component (return { next } to handle it)
|
|
21
|
+
* - `afterHydrate`: after the DOM walk completes
|
|
22
|
+
*
|
|
23
|
+
* @param element - The root element/VNode to hydrate
|
|
24
|
+
* @param container - The DOM container with SSR content
|
|
25
|
+
* @param appContext - The app context for DI (provides, etc.)
|
|
26
|
+
*/
|
|
27
|
+
export declare function hydrate(element: any, container: Element, appContext?: AppContext): void;
|
|
28
|
+
/**
|
|
29
|
+
* Hydrate a VNode against existing DOM
|
|
30
|
+
* This only attaches event handlers and refs - no DOM creation
|
|
31
|
+
*/
|
|
32
|
+
export declare function hydrateNode(vnode: VNode, dom: Node | null, parent: Node): Node | null;
|
|
33
|
+
//# sourceMappingURL=hydrate-core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrate-core.d.ts","sourceRoot":"","sources":["../../src/client/hydrate-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACH,KAAK,EAOR,MAAM,MAAM,CAAC;AACd,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAIvC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CA6BvF;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CA+HrF"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @sigx/server-renderer/client
|
|
3
3
|
*
|
|
4
|
-
* Client-side hydration
|
|
4
|
+
* Client-side hydration — strategy-agnostic core.
|
|
5
|
+
* Plugin-based extension for islands, resumable SSR, etc.
|
|
5
6
|
*/
|
|
6
7
|
import '../client-directives.js';
|
|
8
|
+
import './hydrate-context';
|
|
7
9
|
export { ssrClientPlugin, type HydrateFn } from './plugin.js';
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export type {
|
|
10
|
+
export { hydrate, hydrateNode } from './hydrate-core';
|
|
11
|
+
export { hydrateComponent } from './hydrate-component';
|
|
12
|
+
export type { ComponentFactory } from './hydrate-component';
|
|
13
|
+
export { registerClientPlugin, getClientPlugins, clearClientPlugins, setPendingServerState, getCurrentAppContext, setCurrentAppContext, createRestoringSignal } from './hydrate-context';
|
|
14
|
+
export type { SSRSignalFn, InternalVNode } from './hydrate-context';
|
|
11
15
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,yBAAyB,CAAC;AAGjC,OAAO,mBAAmB,CAAC;AAG3B,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,EACH,oBAAoB,EACpB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/client/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as
|
|
2
|
-
export {
|
|
1
|
+
import { a as clearClientPlugins, c as getCurrentAppContext, d as setPendingServerState, i as hydrateComponent, l as registerClientPlugin, n as hydrate, o as createRestoringSignal, r as hydrateNode, s as getClientPlugins, t as ssrClientPlugin, u as setCurrentAppContext } from "../client-ggDL-Wx2.js";
|
|
2
|
+
export { clearClientPlugins, createRestoringSignal, getClientPlugins, getCurrentAppContext, hydrate, hydrateComponent, hydrateNode, registerClientPlugin, setCurrentAppContext, setPendingServerState, ssrClientPlugin };
|
|
@@ -1,40 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* SSR type augmentations for runtime-core.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Extends ComponentSetupContext with SSR-specific fields (`ssr`, `_serverState`, etc.).
|
|
5
|
+
* Client hydration directive types (client:*) live in @sigx/ssr-islands.
|
|
5
6
|
*/
|
|
6
|
-
/**
|
|
7
|
-
* Client hydration directive props
|
|
8
|
-
*/
|
|
9
|
-
export interface ClientDirectives {
|
|
10
|
-
/**
|
|
11
|
-
* Hydrate this component immediately when the page loads.
|
|
12
|
-
* Use for critical interactive components above the fold.
|
|
13
|
-
*/
|
|
14
|
-
'client:load'?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Hydrate this component during browser idle time (requestIdleCallback).
|
|
17
|
-
* Use for non-critical components that don't need immediate interactivity.
|
|
18
|
-
*/
|
|
19
|
-
'client:idle'?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Hydrate this component when it enters the viewport (IntersectionObserver).
|
|
22
|
-
* Use for below-the-fold components to improve initial load performance.
|
|
23
|
-
*/
|
|
24
|
-
'client:visible'?: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Hydrate this component when the media query matches.
|
|
27
|
-
* Pass the media query string as the value.
|
|
28
|
-
* @example <Sidebar client:media="(min-width: 768px)" />
|
|
29
|
-
*/
|
|
30
|
-
'client:media'?: string;
|
|
31
|
-
/**
|
|
32
|
-
* Skip server rendering entirely; only render on client.
|
|
33
|
-
* Use for components that cannot run on the server (e.g., use browser APIs).
|
|
34
|
-
* A placeholder will be rendered on the server.
|
|
35
|
-
*/
|
|
36
|
-
'client:only'?: boolean;
|
|
37
|
-
}
|
|
38
7
|
/**
|
|
39
8
|
* SSR helper object for async data loading.
|
|
40
9
|
* Provides clean async data loading that works seamlessly across server and client.
|
|
@@ -71,8 +40,6 @@ export interface SSRHelper {
|
|
|
71
40
|
readonly isHydrating: boolean;
|
|
72
41
|
}
|
|
73
42
|
declare module '@sigx/runtime-core' {
|
|
74
|
-
interface ComponentAttributeExtensions extends ClientDirectives {
|
|
75
|
-
}
|
|
76
43
|
interface ComponentSetupContext {
|
|
77
44
|
/**
|
|
78
45
|
* SSR helper for async data loading.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-directives.d.ts","sourceRoot":"","sources":["../src/client-directives.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"client-directives.d.ts","sourceRoot":"","sources":["../src/client-directives.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACtB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAEpC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CACjC;AAGD,OAAO,QAAQ,oBAAoB,CAAC;IAEhC,UAAU,qBAAqB;QAC3B;;;WAGG;QACH,GAAG,EAAE,SAAS,CAAC;QAEf;;WAEG;QACH,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAE5B;;WAEG;QACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAEnC;;WAEG;QACH,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;KAC/B;CACJ"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import { t as generateSignalKey } from "./types-B4Rf1Xot.js";
|
|
2
|
+
import { Fragment, Text, createEmit, createPropsAccessor, createSlots, effect, filterClientDirectives, getCurrentInstance, isComponent, isModel, mount, normalizeSubTree, onElementMounted, patch, patchDirective, patchProp, provideAppContext, registerContextExtension, render, setCurrentInstance, signal } from "sigx";
|
|
3
|
+
var _pendingServerState = null;
|
|
4
|
+
var _currentAppContext = null;
|
|
5
|
+
var _clientPlugins = [];
|
|
6
|
+
function registerClientPlugin(plugin) {
|
|
7
|
+
_clientPlugins.push(plugin);
|
|
8
|
+
}
|
|
9
|
+
function getClientPlugins() {
|
|
10
|
+
return _clientPlugins;
|
|
11
|
+
}
|
|
12
|
+
function clearClientPlugins() {
|
|
13
|
+
_clientPlugins = [];
|
|
14
|
+
}
|
|
15
|
+
function setPendingServerState(state) {
|
|
16
|
+
_pendingServerState = state;
|
|
17
|
+
}
|
|
18
|
+
function getCurrentAppContext() {
|
|
19
|
+
return _currentAppContext;
|
|
20
|
+
}
|
|
21
|
+
function setCurrentAppContext(ctx) {
|
|
22
|
+
_currentAppContext = ctx;
|
|
23
|
+
}
|
|
24
|
+
function createRestoringSignal(serverState) {
|
|
25
|
+
let signalIndex = 0;
|
|
26
|
+
let hasWarnedPositional = false;
|
|
27
|
+
return function restoringSignal(initial, name) {
|
|
28
|
+
const key = generateSignalKey(name, signalIndex++);
|
|
29
|
+
if (process.env.NODE_ENV !== "production" && !name && !hasWarnedPositional) {
|
|
30
|
+
hasWarnedPositional = true;
|
|
31
|
+
console.warn(`[SSR Hydration] Signal restored without a name — using positional key "${key}". If signal declaration order differs between server and client builds, state will be silently mismatched. Use named signals: signal(value, "name")`);
|
|
32
|
+
}
|
|
33
|
+
if (key in serverState) return signal(serverState[key]);
|
|
34
|
+
return signal(initial);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function normalizeElement(element) {
|
|
38
|
+
if (element == null || element === true || element === false) return null;
|
|
39
|
+
if (typeof element === "string" || typeof element === "number") return {
|
|
40
|
+
type: Text,
|
|
41
|
+
props: {},
|
|
42
|
+
key: null,
|
|
43
|
+
children: [],
|
|
44
|
+
dom: null,
|
|
45
|
+
text: element
|
|
46
|
+
};
|
|
47
|
+
return element;
|
|
48
|
+
}
|
|
49
|
+
registerContextExtension((ctx) => {
|
|
50
|
+
const serverState = _pendingServerState;
|
|
51
|
+
if (serverState) {
|
|
52
|
+
ctx._serverState = serverState;
|
|
53
|
+
_pendingServerState = null;
|
|
54
|
+
ctx.signal = createRestoringSignal(serverState);
|
|
55
|
+
ctx.ssr = {
|
|
56
|
+
load: (_fn) => {},
|
|
57
|
+
isServer: false,
|
|
58
|
+
isHydrating: true
|
|
59
|
+
};
|
|
60
|
+
} else if (ctx._serverState) ctx.ssr = {
|
|
61
|
+
load: (_fn) => {},
|
|
62
|
+
isServer: false,
|
|
63
|
+
isHydrating: true
|
|
64
|
+
};
|
|
65
|
+
else ctx.ssr = {
|
|
66
|
+
load: (fn) => {
|
|
67
|
+
fn().catch((err) => console.error("[SSR] load error:", err));
|
|
68
|
+
},
|
|
69
|
+
isServer: false,
|
|
70
|
+
isHydrating: false
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
function hydrateComponent(vnode, dom, parent, serverState, trailingMarker) {
|
|
74
|
+
const componentFactory = vnode.type;
|
|
75
|
+
const setup = componentFactory.__setup;
|
|
76
|
+
const componentName = componentFactory.__name || "Anonymous";
|
|
77
|
+
let anchor = trailingMarker || null;
|
|
78
|
+
if (!anchor) {
|
|
79
|
+
let current = dom;
|
|
80
|
+
while (current) {
|
|
81
|
+
if (current.nodeType === Node.COMMENT_NODE) {
|
|
82
|
+
const text = current.data;
|
|
83
|
+
if (text.startsWith("$c:")) {
|
|
84
|
+
anchor = current;
|
|
85
|
+
parseInt(text.slice(3), 10);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
current = current.nextSibling;
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
const text = anchor.data;
|
|
93
|
+
if (text.startsWith("$c:")) parseInt(text.slice(3), 10);
|
|
94
|
+
}
|
|
95
|
+
const internalVNode = vnode;
|
|
96
|
+
const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = filterClientDirectives(vnode.props || {});
|
|
97
|
+
const propsWithModels = { ...propsData };
|
|
98
|
+
if (modelsData) for (const modelKey in modelsData) {
|
|
99
|
+
const modelValue = modelsData[modelKey];
|
|
100
|
+
if (isModel(modelValue)) propsWithModels[modelKey] = modelValue;
|
|
101
|
+
}
|
|
102
|
+
const reactiveProps = signal(propsWithModels);
|
|
103
|
+
internalVNode._componentProps = reactiveProps;
|
|
104
|
+
const slots = createSlots(children, slotsFromProps);
|
|
105
|
+
internalVNode._slots = slots;
|
|
106
|
+
const mountHooks = [];
|
|
107
|
+
const unmountHooks = [];
|
|
108
|
+
const createdHooks = [];
|
|
109
|
+
const updatedHooks = [];
|
|
110
|
+
const parentInstance = getCurrentInstance();
|
|
111
|
+
const signalFn = serverState ? createRestoringSignal(serverState) : signal;
|
|
112
|
+
const ssrHelper = {
|
|
113
|
+
load(_fn) {},
|
|
114
|
+
isServer: false,
|
|
115
|
+
isHydrating: !!serverState
|
|
116
|
+
};
|
|
117
|
+
const componentCtx = {
|
|
118
|
+
el: parent,
|
|
119
|
+
signal: signalFn,
|
|
120
|
+
props: createPropsAccessor(reactiveProps),
|
|
121
|
+
slots,
|
|
122
|
+
emit: createEmit(reactiveProps),
|
|
123
|
+
parent: parentInstance,
|
|
124
|
+
onMounted: (fn) => {
|
|
125
|
+
mountHooks.push(fn);
|
|
126
|
+
},
|
|
127
|
+
onUnmounted: (fn) => {
|
|
128
|
+
unmountHooks.push(fn);
|
|
129
|
+
},
|
|
130
|
+
onCreated: (fn) => {
|
|
131
|
+
createdHooks.push(fn);
|
|
132
|
+
},
|
|
133
|
+
onUpdated: (fn) => {
|
|
134
|
+
updatedHooks.push(fn);
|
|
135
|
+
},
|
|
136
|
+
expose: () => {},
|
|
137
|
+
renderFn: null,
|
|
138
|
+
update: () => {},
|
|
139
|
+
ssr: ssrHelper,
|
|
140
|
+
_serverState: serverState
|
|
141
|
+
};
|
|
142
|
+
if (!parentInstance && getCurrentAppContext()) provideAppContext(componentCtx, getCurrentAppContext());
|
|
143
|
+
const prev = setCurrentInstance(componentCtx);
|
|
144
|
+
let renderFn;
|
|
145
|
+
try {
|
|
146
|
+
renderFn = setup(componentCtx);
|
|
147
|
+
} catch (err) {
|
|
148
|
+
if (process.env.NODE_ENV !== "production") console.error(`Error hydrating component ${componentName}:`, err);
|
|
149
|
+
} finally {
|
|
150
|
+
setCurrentInstance(prev);
|
|
151
|
+
}
|
|
152
|
+
let endDom = dom;
|
|
153
|
+
if (renderFn) {
|
|
154
|
+
componentCtx.renderFn = renderFn;
|
|
155
|
+
let isFirstRender = true;
|
|
156
|
+
const componentEffect = effect(() => {
|
|
157
|
+
const prevInstance = setCurrentInstance(componentCtx);
|
|
158
|
+
try {
|
|
159
|
+
const subTreeResult = componentCtx.renderFn();
|
|
160
|
+
const prevSubTree = internalVNode._subTree;
|
|
161
|
+
if (subTreeResult == null) {
|
|
162
|
+
if (isFirstRender) isFirstRender = false;
|
|
163
|
+
else if (prevSubTree && prevSubTree.dom) {
|
|
164
|
+
const patchContainer = prevSubTree.dom.parentNode || parent;
|
|
165
|
+
const emptyNode = normalizeSubTree(null);
|
|
166
|
+
patch(prevSubTree, emptyNode, patchContainer);
|
|
167
|
+
internalVNode._subTree = emptyNode;
|
|
168
|
+
}
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const subTree = normalizeSubTree(subTreeResult);
|
|
172
|
+
if (isFirstRender) {
|
|
173
|
+
isFirstRender = false;
|
|
174
|
+
endDom = hydrateNode(subTree, dom, parent);
|
|
175
|
+
internalVNode._subTree = subTree;
|
|
176
|
+
} else {
|
|
177
|
+
if (prevSubTree) patch(prevSubTree, subTree, prevSubTree.dom?.parentNode || parent);
|
|
178
|
+
else mount(subTree, parent, anchor || null);
|
|
179
|
+
internalVNode._subTree = subTree;
|
|
180
|
+
}
|
|
181
|
+
} finally {
|
|
182
|
+
setCurrentInstance(prevInstance);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
internalVNode._effect = componentEffect;
|
|
186
|
+
componentCtx.update = () => componentEffect();
|
|
187
|
+
}
|
|
188
|
+
vnode.dom = anchor || endDom;
|
|
189
|
+
const mountCtx = { el: parent };
|
|
190
|
+
createdHooks.forEach((hook) => hook());
|
|
191
|
+
mountHooks.forEach((hook) => hook(mountCtx));
|
|
192
|
+
vnode.cleanup = () => {
|
|
193
|
+
unmountHooks.forEach((hook) => hook(mountCtx));
|
|
194
|
+
};
|
|
195
|
+
return anchor ? anchor.nextSibling : endDom;
|
|
196
|
+
}
|
|
197
|
+
function hydrate(element, container, appContext) {
|
|
198
|
+
const vnode = normalizeElement(element);
|
|
199
|
+
if (!vnode) return;
|
|
200
|
+
setCurrentAppContext(appContext ?? null);
|
|
201
|
+
const plugins = getClientPlugins();
|
|
202
|
+
for (const plugin of plugins) if (plugin.client?.beforeHydrate?.(container) === false) {
|
|
203
|
+
container._vnode = vnode;
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
hydrateNode(vnode, container.firstChild, container);
|
|
207
|
+
for (const plugin of plugins) plugin.client?.afterHydrate?.(container);
|
|
208
|
+
container._vnode = vnode;
|
|
209
|
+
}
|
|
210
|
+
function hydrateNode(vnode, dom, parent) {
|
|
211
|
+
if (!vnode) return dom;
|
|
212
|
+
const isComponentVNode = isComponent(vnode.type);
|
|
213
|
+
const isTextVNode = vnode.type === Text;
|
|
214
|
+
while (dom && dom.nodeType === Node.COMMENT_NODE) {
|
|
215
|
+
if (isComponentVNode) {
|
|
216
|
+
if (dom.data.startsWith("$c:")) break;
|
|
217
|
+
}
|
|
218
|
+
if (isTextVNode && dom.data === "t") {
|
|
219
|
+
const emptyText = document.createTextNode("");
|
|
220
|
+
parent.replaceChild(emptyText, dom);
|
|
221
|
+
dom = emptyText;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
dom = dom.nextSibling;
|
|
225
|
+
}
|
|
226
|
+
if (vnode.type === Text) {
|
|
227
|
+
if (dom && dom.nodeType === Node.TEXT_NODE) {
|
|
228
|
+
vnode.dom = dom;
|
|
229
|
+
return dom.nextSibling;
|
|
230
|
+
}
|
|
231
|
+
const textNode = document.createTextNode(String(vnode.text ?? ""));
|
|
232
|
+
if (dom) parent.insertBefore(textNode, dom);
|
|
233
|
+
else parent.appendChild(textNode);
|
|
234
|
+
vnode.dom = textNode;
|
|
235
|
+
return dom;
|
|
236
|
+
}
|
|
237
|
+
if (vnode.type === Fragment) {
|
|
238
|
+
let current = dom;
|
|
239
|
+
for (const child of vnode.children) current = hydrateNode(child, current, parent);
|
|
240
|
+
return current;
|
|
241
|
+
}
|
|
242
|
+
if (isComponent(vnode.type)) {
|
|
243
|
+
const plugins = getClientPlugins();
|
|
244
|
+
for (const plugin of plugins) {
|
|
245
|
+
const result = plugin.client?.hydrateComponent?.(vnode, dom, parent);
|
|
246
|
+
if (result !== void 0) return result;
|
|
247
|
+
}
|
|
248
|
+
return hydrateComponent(vnode, dom, parent);
|
|
249
|
+
}
|
|
250
|
+
if (typeof vnode.type === "string") {
|
|
251
|
+
if (!dom || dom.nodeType !== Node.ELEMENT_NODE) {
|
|
252
|
+
if (process.env.NODE_ENV !== "production") console.warn("[Hydrate] Expected element but got:", dom);
|
|
253
|
+
return dom;
|
|
254
|
+
}
|
|
255
|
+
const el = dom;
|
|
256
|
+
vnode.dom = el;
|
|
257
|
+
if (vnode.props) {
|
|
258
|
+
let hasDirectives = false;
|
|
259
|
+
for (const key in vnode.props) {
|
|
260
|
+
if (key === "children" || key === "key") continue;
|
|
261
|
+
if (key.startsWith("client:")) continue;
|
|
262
|
+
if (key.charCodeAt(0) === 117 && key.startsWith("use:")) {
|
|
263
|
+
patchDirective(el, key.slice(4), null, vnode.props[key], getCurrentAppContext());
|
|
264
|
+
hasDirectives = true;
|
|
265
|
+
} else patchProp(el, key, null, vnode.props[key]);
|
|
266
|
+
}
|
|
267
|
+
if (hasDirectives) onElementMounted(el);
|
|
268
|
+
if (vnode.props.ref) {
|
|
269
|
+
if (typeof vnode.props.ref === "function") vnode.props.ref(el);
|
|
270
|
+
else if (typeof vnode.props.ref === "object") vnode.props.ref.current = el;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
let childDom = el.firstChild;
|
|
274
|
+
for (const child of vnode.children) childDom = hydrateNode(child, childDom, el);
|
|
275
|
+
if (vnode.type === "select" && vnode.props) fixSelectValue(el, vnode.props);
|
|
276
|
+
return el.nextSibling;
|
|
277
|
+
}
|
|
278
|
+
return dom;
|
|
279
|
+
}
|
|
280
|
+
function fixSelectValue(dom, props) {
|
|
281
|
+
if (dom.tagName === "SELECT" && "value" in props) {
|
|
282
|
+
const val = props.value;
|
|
283
|
+
if (dom.multiple) {
|
|
284
|
+
const options = dom.options;
|
|
285
|
+
const valArray = Array.isArray(val) ? val : [val];
|
|
286
|
+
for (let i = 0; i < options.length; i++) options[i].selected = valArray.includes(options[i].value);
|
|
287
|
+
} else dom.value = String(val);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const ssrClientPlugin = {
|
|
291
|
+
name: "@sigx/server-renderer/client",
|
|
292
|
+
install(app) {
|
|
293
|
+
app.hydrate = function(container) {
|
|
294
|
+
const resolvedContainer = typeof container === "string" ? document.querySelector(container) : container;
|
|
295
|
+
if (!resolvedContainer) throw new Error(`[ssrClientPlugin] Cannot find container: ${container}. Make sure the element exists in the DOM before calling hydrate().`);
|
|
296
|
+
const rootComponent = app._rootComponent;
|
|
297
|
+
if (!rootComponent) throw new Error("[ssrClientPlugin] No root component found on app. Make sure you created the app with defineApp(<Component />).");
|
|
298
|
+
const hasSSRContent = resolvedContainer.firstElementChild !== null || resolvedContainer.firstChild !== null && resolvedContainer.firstChild.nodeType !== Node.COMMENT_NODE;
|
|
299
|
+
const appContext = app._context;
|
|
300
|
+
if (hasSSRContent) hydrate(rootComponent, resolvedContainer, appContext);
|
|
301
|
+
else render(rootComponent, resolvedContainer, appContext);
|
|
302
|
+
resolvedContainer._app = app;
|
|
303
|
+
return app;
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
export { clearClientPlugins as a, getCurrentAppContext as c, setPendingServerState as d, hydrateComponent as i, registerClientPlugin as l, hydrate as n, createRestoringSignal as o, hydrateNode as r, getClientPlugins as s, ssrClientPlugin as t, setCurrentAppContext as u };
|
|
308
|
+
|
|
309
|
+
//# sourceMappingURL=client-ggDL-Wx2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-ggDL-Wx2.js","names":[],"sources":["../src/client/hydrate-context.ts","../src/client/hydrate-component.ts","../src/client/hydrate-core.ts","../src/client/plugin.ts"],"sourcesContent":["/**\r\n * Hydration context and state management\r\n *\r\n * Manages server state restoration, app context tracking,\r\n * client plugin registration, and the SSR context extension for components.\r\n *\r\n * Strategy-specific concerns (island data, async hydration) are handled\r\n * by plugins registered via `registerClientPlugin()`.\r\n */\r\n\r\nimport {\r\n VNode,\r\n signal,\r\n Text,\r\n registerContextExtension\r\n} from 'sigx';\r\nimport type { AppContext } from 'sigx';\r\nimport type { SSRPlugin } from '../plugin';\r\nimport type { SSRSignalFn } from '../server/types';\r\nimport { generateSignalKey } from '../server/types';\r\n\r\n// ============= Internal Types =============\r\n\r\nexport interface InternalVNode extends VNode {\r\n _subTree?: VNode;\r\n _effect?: any;\r\n _componentProps?: any;\r\n _slots?: any;\r\n}\r\n\r\n// Re-export SSRSignalFn from shared types so existing consumers work\r\nexport type { SSRSignalFn };\r\n\r\n// ============= Module State =============\r\n\r\n// Track server state for async components being mounted after streaming\r\nlet _pendingServerState: Record<string, any> | null = null;\r\n\r\n// Track current app context during hydration for DI\r\n// Used for deferred hydration callbacks\r\nlet _currentAppContext: AppContext | null = null;\r\n\r\n// Registered client-side SSR plugins\r\nlet _clientPlugins: SSRPlugin[] = [];\r\n\r\n// ============= Client Plugin Registry =============\r\n\r\n/**\r\n * Register a client-side SSR plugin.\r\n * Plugins are called during hydration to intercept component processing,\r\n * skip default hydration walk, or run post-hydration logic.\r\n */\r\nexport function registerClientPlugin(plugin: SSRPlugin): void {\r\n _clientPlugins.push(plugin);\r\n}\r\n\r\n/**\r\n * Get all registered client-side plugins.\r\n */\r\nexport function getClientPlugins(): SSRPlugin[] {\r\n return _clientPlugins;\r\n}\r\n\r\n/**\r\n * Clear all registered client plugins (useful for testing).\r\n */\r\nexport function clearClientPlugins(): void {\r\n _clientPlugins = [];\r\n}\r\n\r\n// ============= State Accessors =============\r\n\r\n/**\r\n * Set server state that should be used for the next component mount.\r\n * Used internally when mounting async components after streaming.\r\n */\r\nexport function setPendingServerState(state: Record<string, any> | null): void {\r\n _pendingServerState = state;\r\n}\r\n\r\n/** Get the current app context for deferred hydration */\r\nexport function getCurrentAppContext(): AppContext | null {\r\n return _currentAppContext;\r\n}\r\n\r\n/** Set the current app context during hydration */\r\nexport function setCurrentAppContext(ctx: AppContext | null): void {\r\n _currentAppContext = ctx;\r\n}\r\n\r\n// ============= Signal Restoration =============\r\n\r\n/**\r\n * Creates a signal function that restores state from server-captured values.\r\n * Used during hydration of async components to avoid re-fetching data.\r\n * Supports both primitive and object signals.\r\n */\r\nexport function createRestoringSignal(serverState: Record<string, any>): SSRSignalFn {\r\n let signalIndex = 0;\r\n let hasWarnedPositional = false;\r\n\r\n return function restoringSignal(initial: any, name?: string): any {\r\n // Generate a stable key for this signal (must match server-side)\r\n const key = generateSignalKey(name, signalIndex++);\r\n\r\n // Dev warning: positional keys are fragile\r\n if (process.env.NODE_ENV !== 'production' && !name && !hasWarnedPositional) {\r\n hasWarnedPositional = true;\r\n console.warn(\r\n `[SSR Hydration] Signal restored without a name — using positional key \"${key}\". ` +\r\n `If signal declaration order differs between server and client builds, ` +\r\n `state will be silently mismatched. Use named signals: signal(value, \"name\")`\r\n );\r\n }\r\n\r\n // Check if we have server state for this signal\r\n if (key in serverState) {\r\n return signal(serverState[key]);\r\n }\r\n\r\n // No server state, use initial value\r\n return signal(initial as any);\r\n } as SSRSignalFn;\r\n}\r\n\r\n// ============= Element Normalization =============\r\n\r\n/**\r\n * Normalize any element to VNode\r\n */\r\nexport function normalizeElement(element: any): VNode | null {\r\n if (element == null || element === true || element === false) {\r\n return null;\r\n }\r\n\r\n if (typeof element === 'string' || typeof element === 'number') {\r\n return {\r\n type: Text,\r\n props: {},\r\n key: null,\r\n children: [],\r\n dom: null,\r\n text: element\r\n };\r\n }\r\n\r\n return element as VNode;\r\n}\r\n\r\n// ============= Context Extension Registration =============\r\n\r\n/**\r\n * Register the SSR context extension for all components.\r\n * This provides the `ssr` object with a no-op `load()` for client-side rendering.\r\n * Also handles server state restoration for async streamed components.\r\n */\r\nregisterContextExtension((ctx: any) => {\r\n // Check if we have pending server state (from async streaming)\r\n const serverState = _pendingServerState;\r\n if (serverState) {\r\n ctx._serverState = serverState;\r\n _pendingServerState = null; // Clear after use\r\n\r\n // Override signal function to use restoring signal\r\n ctx.signal = createRestoringSignal(serverState);\r\n\r\n // ssr.load() should be a no-op since we have restored state\r\n ctx.ssr = {\r\n load: (_fn: () => Promise<void>) => {\r\n // Skip - using restored server state\r\n },\r\n isServer: false,\r\n isHydrating: true\r\n };\r\n } else if (ctx._serverState) {\r\n // Already has server state (from hydration)\r\n ctx.ssr = {\r\n load: (_fn: () => Promise<void>) => {\r\n // Skip - using restored server state\r\n },\r\n isServer: false,\r\n isHydrating: true\r\n };\r\n } else {\r\n // Default client-side ssr helper - runs async functions for client-side navigation\r\n ctx.ssr = {\r\n load: (fn: () => Promise<void>) => {\r\n // On client-side navigation (not hydration), execute the async function\r\n fn().catch(err => console.error('[SSR] load error:', err));\r\n },\r\n isServer: false,\r\n isHydrating: false\r\n };\r\n }\r\n});\r\n","/**\r\n * Component hydration logic — strategy-agnostic\r\n *\r\n * Handles running component setup, creating reactive effects,\r\n * and restoring server state for hydrated components.\r\n * Does not depend on islands or any specific SSR strategy.\r\n */\r\n\r\nimport {\r\n VNode,\r\n ComponentSetupContext,\r\n setCurrentInstance,\r\n getCurrentInstance,\r\n signal,\r\n SlotsObject,\r\n createPropsAccessor,\r\n createSlots,\r\n normalizeSubTree,\r\n effect,\r\n patch,\r\n mount,\r\n patchProp,\r\n filterClientDirectives,\r\n createEmit,\r\n provideAppContext,\r\n isModel\r\n} from 'sigx';\r\nimport {\r\n InternalVNode,\r\n createRestoringSignal,\r\n getCurrentAppContext\r\n} from './hydrate-context';\r\nimport { hydrateNode } from './hydrate-core';\r\n\r\n/**\r\n * Minimal type for component factories used in hydration.\r\n * Compatible with ComponentFactory from runtime-core.\r\n */\r\nexport interface ComponentFactory {\r\n __setup: Function;\r\n __name?: string;\r\n __async?: boolean;\r\n}\r\n\r\n/**\r\n * Hydrate a component - run setup and create reactive effect\r\n *\r\n * With trailing markers, the structure is: <content><!--$c:id-->\r\n * - dom points to start of content\r\n * - trailingMarker (if provided) is the anchor at the end\r\n *\r\n * @param vnode - The VNode to hydrate\r\n * @param dom - The DOM node to start from (content starts here)\r\n * @param parent - The parent node\r\n * @param serverState - Optional state captured from server for async components\r\n * @param trailingMarker - Optional trailing marker comment (the component anchor)\r\n */\r\nexport function hydrateComponent(vnode: VNode, dom: Node | null, parent: Node, serverState?: Record<string, any>, trailingMarker?: Comment | null): Node | null {\r\n const componentFactory = vnode.type as unknown as ComponentFactory;\r\n const setup = componentFactory.__setup;\r\n const componentName = componentFactory.__name || 'Anonymous';\r\n\r\n // With trailing markers, find the marker if not provided\r\n let anchor: Comment | null = trailingMarker || null;\r\n let componentId: number | null = null;\r\n\r\n if (!anchor) {\r\n // Find trailing marker by traversing forward\r\n let current: Node | null = dom;\r\n while (current) {\r\n if (current.nodeType === Node.COMMENT_NODE) {\r\n const text = (current as Comment).data;\r\n if (text.startsWith('$c:')) {\r\n anchor = current as Comment;\r\n componentId = parseInt(text.slice(3), 10);\r\n break;\r\n }\r\n }\r\n current = current.nextSibling;\r\n }\r\n } else {\r\n // Extract component ID from provided marker\r\n const text = anchor.data;\r\n if (text.startsWith('$c:')) {\r\n componentId = parseInt(text.slice(3), 10);\r\n }\r\n }\r\n\r\n const internalVNode = vnode as InternalVNode;\r\n const initialProps = vnode.props || {};\r\n const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = filterClientDirectives(initialProps);\r\n\r\n // Merge Model<T> objects directly into props for unified access: props.model.value\r\n const propsWithModels = { ...propsData };\r\n if (modelsData) {\r\n for (const modelKey in modelsData) {\r\n const modelValue = modelsData[modelKey];\r\n if (isModel(modelValue)) {\r\n propsWithModels[modelKey] = modelValue;\r\n }\r\n }\r\n }\r\n\r\n // Create reactive props\r\n const reactiveProps = signal(propsWithModels);\r\n internalVNode._componentProps = reactiveProps;\r\n\r\n // Create slots\r\n const slots = createSlots(children, slotsFromProps);\r\n internalVNode._slots = slots;\r\n\r\n const mountHooks: ((ctx: any) => void)[] = [];\r\n const unmountHooks: ((ctx: any) => void)[] = [];\r\n const createdHooks: (() => void)[] = [];\r\n const updatedHooks: (() => void)[] = [];\r\n\r\n const parentInstance = getCurrentInstance();\r\n\r\n // Use restoring signal when we have server state to restore\r\n const signalFn = serverState\r\n ? createRestoringSignal(serverState)\r\n : signal;\r\n\r\n // Create SSR helper for client-side\r\n // When hydrating with server state, ssr.load() is a no-op (data already restored)\r\n const hasServerState = !!serverState;\r\n const ssrHelper = {\r\n load(_fn: () => Promise<void>): void {\r\n // No-op on client when hydrating - signal state was restored from server\r\n },\r\n isServer: false,\r\n isHydrating: hasServerState\r\n };\r\n\r\n const componentCtx: ComponentSetupContext = {\r\n el: parent as HTMLElement,\r\n signal: signalFn as typeof signal,\r\n props: createPropsAccessor(reactiveProps),\r\n slots: slots,\r\n emit: createEmit(reactiveProps),\r\n parent: parentInstance,\r\n onMounted: (fn) => { mountHooks.push(fn); },\r\n onUnmounted: (fn) => { unmountHooks.push(fn); },\r\n onCreated: (fn) => { createdHooks.push(fn); },\r\n onUpdated: (fn) => { updatedHooks.push(fn); },\r\n expose: () => { },\r\n renderFn: null,\r\n update: () => { },\r\n ssr: ssrHelper,\r\n _serverState: serverState\r\n };\r\n\r\n // For ROOT component only (no parent), provide the AppContext\r\n if (!parentInstance && getCurrentAppContext()) {\r\n provideAppContext(componentCtx, getCurrentAppContext()!);\r\n }\r\n\r\n const prev = setCurrentInstance(componentCtx);\r\n let renderFn: (() => any) | undefined;\r\n\r\n try {\r\n renderFn = setup(componentCtx);\r\n } catch (err) {\r\n if (process.env.NODE_ENV !== 'production') {\r\n console.error(`Error hydrating component ${componentName}:`, err);\r\n }\r\n } finally {\r\n setCurrentInstance(prev);\r\n }\r\n\r\n // Track where the component's DOM starts\r\n let endDom: Node | null = dom;\r\n\r\n if (renderFn) {\r\n componentCtx.renderFn = renderFn;\r\n let isFirstRender = true;\r\n\r\n // Create reactive effect - on first run, hydrate; on subsequent, use render()\r\n const componentEffect = effect(() => {\r\n const prevInstance = setCurrentInstance(componentCtx);\r\n try {\r\n const subTreeResult = componentCtx.renderFn!();\r\n const prevSubTree = internalVNode._subTree;\r\n\r\n // Handle null/undefined renders (e.g., conditional components like Modal)\r\n if (subTreeResult == null) {\r\n if (isFirstRender) {\r\n // First render returned null - SSR didn't render content, nothing to hydrate\r\n isFirstRender = false;\r\n } else if (prevSubTree && prevSubTree.dom) {\r\n // Had content before, now returning null - unmount the previous subtree\r\n const patchContainer = prevSubTree.dom.parentNode as Element || parent;\r\n const emptyNode = normalizeSubTree(null);\r\n patch(prevSubTree, emptyNode, patchContainer);\r\n internalVNode._subTree = emptyNode;\r\n }\r\n return;\r\n }\r\n\r\n const subTree = normalizeSubTree(subTreeResult);\r\n\r\n if (isFirstRender) {\r\n // First render - hydrate against existing DOM\r\n isFirstRender = false;\r\n endDom = hydrateNode(subTree, dom, parent);\r\n internalVNode._subTree = subTree;\r\n } else {\r\n // Subsequent renders - use patch directly like runtime-core does\r\n if (prevSubTree) {\r\n const patchContainer = prevSubTree.dom?.parentNode as Element || parent;\r\n patch(prevSubTree, subTree, patchContainer);\r\n } else {\r\n // No previous subtree - mount fresh using the component's anchor\r\n mount(subTree, parent as Element, anchor || null);\r\n }\r\n internalVNode._subTree = subTree;\r\n }\r\n } finally {\r\n setCurrentInstance(prevInstance);\r\n }\r\n });\r\n\r\n internalVNode._effect = componentEffect;\r\n componentCtx.update = () => componentEffect();\r\n }\r\n\r\n // Use trailing anchor comment as the component's dom reference\r\n vnode.dom = anchor || endDom;\r\n\r\n // Run mount hooks\r\n const mountCtx = { el: parent as Element };\r\n createdHooks.forEach(hook => hook());\r\n mountHooks.forEach(hook => hook(mountCtx));\r\n\r\n // Store cleanup\r\n vnode.cleanup = () => {\r\n unmountHooks.forEach(hook => hook(mountCtx));\r\n };\r\n\r\n // With trailing markers, the anchor IS the end - return next sibling\r\n return anchor ? anchor.nextSibling : endDom;\r\n}\r\n","/**\r\n * Core hydration logic — strategy-agnostic\r\n *\r\n * Walks existing server-rendered DOM and attaches event handlers,\r\n * creates reactive effects, and delegates components to the component hydrator.\r\n *\r\n * Plugins registered via `registerClientPlugin()` can intercept component\r\n * hydration (e.g., for deferred/island-based hydration strategies).\r\n */\r\n\r\nimport {\r\n VNode,\r\n Fragment,\r\n Text,\r\n isComponent,\r\n patchProp,\r\n patchDirective,\r\n onElementMounted\r\n} from 'sigx';\r\nimport type { AppContext } from 'sigx';\r\nimport { normalizeElement, setCurrentAppContext, getCurrentAppContext, getClientPlugins } from './hydrate-context';\r\nimport { hydrateComponent } from './hydrate-component';\r\n\r\n/**\r\n * Hydrate a server-rendered app.\r\n *\r\n * This walks the existing DOM to attach event handlers, runs component\r\n * setup functions to establish reactivity, then uses runtime-dom for updates.\r\n *\r\n * Registered client plugins are called at appropriate points:\r\n * - `beforeHydrate`: before the DOM walk (return false to skip it entirely)\r\n * - `hydrateComponent`: for each component (return { next } to handle it)\r\n * - `afterHydrate`: after the DOM walk completes\r\n *\r\n * @param element - The root element/VNode to hydrate\r\n * @param container - The DOM container with SSR content\r\n * @param appContext - The app context for DI (provides, etc.)\r\n */\r\nexport function hydrate(element: any, container: Element, appContext?: AppContext): void {\r\n const vnode = normalizeElement(element);\r\n if (!vnode) return;\r\n\r\n // Store app context for component hydration (DI needs this)\r\n setCurrentAppContext(appContext ?? null);\r\n\r\n const plugins = getClientPlugins();\r\n\r\n // Let plugins intercept before the DOM walk\r\n for (const plugin of plugins) {\r\n const result = plugin.client?.beforeHydrate?.(container);\r\n if (result === false) {\r\n // Plugin opted out of the default DOM walk (e.g., resumable SSR)\r\n (container as any)._vnode = vnode;\r\n return;\r\n }\r\n }\r\n\r\n // Walk existing DOM, attach handlers, and mount components\r\n hydrateNode(vnode, container.firstChild, container);\r\n\r\n // Post-hydration hooks\r\n for (const plugin of plugins) {\r\n plugin.client?.afterHydrate?.(container);\r\n }\r\n\r\n // Store vnode on container for potential future use\r\n (container as any)._vnode = vnode;\r\n}\r\n\r\n/**\r\n * Hydrate a VNode against existing DOM\r\n * This only attaches event handlers and refs - no DOM creation\r\n */\r\nexport function hydrateNode(vnode: VNode, dom: Node | null, parent: Node): Node | null {\r\n if (!vnode) return dom;\r\n\r\n // Skip comment nodes (<!--t--> text separators and <!--$c:N--> component markers).\r\n // Component markers are only meaningful when the VNode itself is a component —\r\n // for element/text/fragment VNodes, all comments are just SSR artifacts to skip past.\r\n const isComponentVNode = isComponent(vnode.type);\r\n const isTextVNode = vnode.type === Text;\r\n while (dom && dom.nodeType === Node.COMMENT_NODE) {\r\n if (isComponentVNode) {\r\n const commentText = (dom as Comment).data;\r\n // Stop at component markers — the component hydrator needs them for boundaries\r\n if (commentText.startsWith('$c:')) {\r\n break;\r\n }\r\n }\r\n // When a text VNode hits a <!--t--> separator, the SSR may have omitted the\r\n // preceding empty text (e.g. \"\" + \" · Logout\" → <!--t--> · Logout).\r\n // Replace the comment with an empty text node so this VNode can attach to it,\r\n // preserving the boundary for the next text VNode.\r\n if (isTextVNode && (dom as Comment).data === 't') {\r\n const emptyText = document.createTextNode('');\r\n parent.replaceChild(emptyText, dom);\r\n dom = emptyText;\r\n break;\r\n }\r\n dom = dom.nextSibling;\r\n }\r\n\r\n if (vnode.type === Text) {\r\n if (dom && dom.nodeType === Node.TEXT_NODE) {\r\n vnode.dom = dom;\r\n return dom.nextSibling;\r\n }\r\n // Hydration mismatch: expected a text node but got something else.\r\n // Create a fresh text node and insert it so the VNode has a valid DOM ref.\r\n const textNode = document.createTextNode(String(vnode.text ?? ''));\r\n if (dom) {\r\n parent.insertBefore(textNode, dom);\r\n } else {\r\n parent.appendChild(textNode);\r\n }\r\n vnode.dom = textNode;\r\n return dom;\r\n }\r\n\r\n if (vnode.type === Fragment) {\r\n let current = dom;\r\n for (const child of vnode.children) {\r\n current = hydrateNode(child, current, parent);\r\n }\r\n return current;\r\n }\r\n\r\n if (isComponent(vnode.type)) {\r\n // Let plugins intercept component hydration (e.g., islands scheduling)\r\n const plugins = getClientPlugins();\r\n for (const plugin of plugins) {\r\n const result = plugin.client?.hydrateComponent?.(vnode, dom, parent);\r\n if (result !== undefined) {\r\n // Plugin handled this component — return the next DOM node\r\n return result;\r\n }\r\n }\r\n\r\n // No plugin handled it — hydrate immediately\r\n return hydrateComponent(vnode, dom, parent);\r\n }\r\n\r\n if (typeof vnode.type === 'string') {\r\n if (!dom || dom.nodeType !== Node.ELEMENT_NODE) {\r\n if (process.env.NODE_ENV !== 'production') {\r\n console.warn('[Hydrate] Expected element but got:', dom);\r\n }\r\n return dom;\r\n }\r\n\r\n const el = dom as Element;\r\n vnode.dom = el;\r\n\r\n // Attach event handlers and props using patchProp from runtime-dom\r\n if (vnode.props) {\r\n let hasDirectives = false;\r\n for (const key in vnode.props) {\r\n if (key === 'children' || key === 'key') continue;\r\n if (key.startsWith('client:')) continue;\r\n\r\n if (key.charCodeAt(0) === 117 /* 'u' */ && key.startsWith('use:')) {\r\n // Route use:* directive props through patchDirective\r\n patchDirective(el, key.slice(4), null, vnode.props[key], getCurrentAppContext());\r\n hasDirectives = true;\r\n } else {\r\n // Use patchProp for consistent prop handling (events, refs, etc.)\r\n patchProp(el, key, null, vnode.props[key]);\r\n }\r\n }\r\n\r\n // Fire mounted hooks for directives (element is already in DOM during hydration)\r\n if (hasDirectives) {\r\n onElementMounted(el);\r\n }\r\n\r\n // Handle ref - patchProp skips refs, so we handle them here\r\n if (vnode.props.ref) {\r\n if (typeof vnode.props.ref === 'function') {\r\n vnode.props.ref(el);\r\n } else if (typeof vnode.props.ref === 'object') {\r\n vnode.props.ref.current = el;\r\n }\r\n }\r\n }\r\n\r\n // Hydrate children\r\n let childDom: Node | null = el.firstChild;\r\n for (const child of vnode.children) {\r\n childDom = hydrateNode(child, childDom, el);\r\n }\r\n\r\n // Fix select value after children are hydrated\r\n if (vnode.type === 'select' && vnode.props) {\r\n fixSelectValue(el as HTMLElement, vnode.props);\r\n }\r\n\r\n return el.nextSibling;\r\n }\r\n\r\n return dom;\r\n}\r\n\r\n/**\r\n * Fix select element value after hydrating children.\r\n * This is needed because <select>.value only works after <option> children exist in DOM.\r\n */\r\nfunction fixSelectValue(dom: HTMLElement, props: any) {\r\n if (dom.tagName === 'SELECT' && 'value' in props) {\r\n const val = props.value;\r\n if ((dom as HTMLSelectElement).multiple) {\r\n const options = (dom as HTMLSelectElement).options;\r\n const valArray = Array.isArray(val) ? val : [val];\r\n for (let i = 0; i < options.length; i++) {\r\n options[i].selected = valArray.includes(options[i].value);\r\n }\r\n } else {\r\n (dom as HTMLSelectElement).value = String(val);\r\n }\r\n }\r\n}\r\n","/**\r\n * SSR Client Plugin\r\n * \r\n * Provides app.hydrate() method for client-side hydration of server-rendered HTML.\r\n * This plugin follows the same pattern as the router plugin.\r\n */\r\n\r\nimport type { Plugin, App, AppContext } from '@sigx/runtime-core';\r\nimport { render } from 'sigx';\r\nimport { hydrate as hydrateImpl } from './hydrate-core';\r\n\r\n// ============================================================================\r\n// Type Augmentation\r\n// ============================================================================\r\n\r\n/**\r\n * Hydrate function signature - matches MountFn pattern\r\n */\r\nexport type HydrateFn<TContainer = any> = (\r\n element: any,\r\n container: TContainer,\r\n appContext: AppContext\r\n) => (() => void) | void;\r\n\r\ndeclare module '@sigx/runtime-core' {\r\n interface App<TContainer = any> {\r\n /**\r\n * Hydrate the app from server-rendered HTML.\r\n * \r\n * Unlike mount() which creates new DOM, hydrate() attaches to existing\r\n * server-rendered DOM, adding event handlers and establishing reactivity.\r\n * \r\n * @example\r\n * ```tsx\r\n * import { defineApp } from 'sigx';\r\n * import { ssrClientPlugin } from '@sigx/server-renderer/client';\r\n * \r\n * const app = defineApp(<App />);\r\n * app.use(router)\r\n * .use(ssrClientPlugin)\r\n * .hydrate(document.getElementById('app')!);\r\n * ```\r\n */\r\n hydrate(container: TContainer): App<TContainer>;\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Plugin Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * SSR Client Plugin\r\n * \r\n * Adds the hydrate() method to the app instance for client-side hydration.\r\n * Also registers the SSR context extension for all components.\r\n * \r\n * @example\r\n * ```tsx\r\n * import { defineApp } from 'sigx';\r\n * import { ssrClientPlugin } from '@sigx/server-renderer/client';\r\n * \r\n * const app = defineApp(<App />);\r\n * app.use(ssrClientPlugin)\r\n * .use(router)\r\n * .hydrate('#app');\r\n * ```\r\n */\r\nexport const ssrClientPlugin: Plugin = {\r\n name: '@sigx/server-renderer/client',\r\n\r\n install(app: App) {\r\n // Add hydrate method to the app instance\r\n (app as any).hydrate = function(container: Element | string): App {\r\n // Resolve container if string selector\r\n const resolvedContainer = typeof container === 'string'\r\n ? document.querySelector(container)\r\n : container;\r\n\r\n if (!resolvedContainer) {\r\n throw new Error(\r\n `[ssrClientPlugin] Cannot find container: ${container}. ` +\r\n 'Make sure the element exists in the DOM before calling hydrate().'\r\n );\r\n }\r\n\r\n // Get the root component from the app\r\n const rootComponent = (app as any)._rootComponent;\r\n \r\n if (!rootComponent) {\r\n throw new Error(\r\n '[ssrClientPlugin] No root component found on app. ' +\r\n 'Make sure you created the app with defineApp(<Component />).'\r\n );\r\n }\r\n\r\n // Check if there's actual SSR content to hydrate\r\n // If container is empty or only has comments, fall back to client-side render\r\n const hasSSRContent = resolvedContainer.firstElementChild !== null ||\r\n (resolvedContainer.firstChild !== null && \r\n resolvedContainer.firstChild.nodeType !== Node.COMMENT_NODE);\r\n\r\n // Get app context for passing to render (needed for inject() to work)\r\n const appContext = (app as any)._context;\r\n\r\n if (hasSSRContent) {\r\n // Perform hydration with app context for DI\r\n hydrateImpl(rootComponent, resolvedContainer, appContext);\r\n } else {\r\n // No SSR content - fall back to client-side render (dev mode)\r\n render(rootComponent, resolvedContainer, appContext);\r\n }\r\n\r\n // Store container on the vnode for potential unmount\r\n (resolvedContainer as any)._app = app;\r\n\r\n return app;\r\n };\r\n }\r\n};\r\n"],"mappings":"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"}
|