@sigx/server-renderer 0.1.6 → 0.1.7

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.
Files changed (60) hide show
  1. package/dist/builtin-ssr-directives.d.ts +8 -0
  2. package/dist/builtin-ssr-directives.d.ts.map +1 -0
  3. package/dist/client/hydrate-component.d.ts +32 -0
  4. package/dist/client/hydrate-component.d.ts.map +1 -0
  5. package/dist/client/hydrate-context.d.ts +54 -0
  6. package/dist/client/hydrate-context.d.ts.map +1 -0
  7. package/dist/client/hydrate-core.d.ts +33 -0
  8. package/dist/client/hydrate-core.d.ts.map +1 -0
  9. package/dist/client/index.d.ts +8 -4
  10. package/dist/client/index.d.ts.map +1 -1
  11. package/dist/client/index.js +2 -2
  12. package/dist/client-directives.d.ts +3 -36
  13. package/dist/client-directives.d.ts.map +1 -1
  14. package/dist/client-ggDL-Wx2.js +309 -0
  15. package/dist/client-ggDL-Wx2.js.map +1 -0
  16. package/dist/directive-ssr-types.d.ts +23 -0
  17. package/dist/directive-ssr-types.d.ts.map +1 -0
  18. package/dist/head.d.ts +97 -0
  19. package/dist/head.d.ts.map +1 -0
  20. package/dist/index.d.ts +22 -18
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +7 -3
  23. package/dist/index.js.map +1 -0
  24. package/dist/plugin.d.ts +124 -0
  25. package/dist/plugin.d.ts.map +1 -0
  26. package/dist/server/context.d.ts +52 -59
  27. package/dist/server/context.d.ts.map +1 -1
  28. package/dist/server/index.d.ts +9 -4
  29. package/dist/server/index.d.ts.map +1 -1
  30. package/dist/server/index.js +3 -2
  31. package/dist/server/render-api.d.ts +64 -0
  32. package/dist/server/render-api.d.ts.map +1 -0
  33. package/dist/server/render-core.d.ts +46 -0
  34. package/dist/server/render-core.d.ts.map +1 -0
  35. package/dist/server/streaming.d.ts +24 -0
  36. package/dist/server/streaming.d.ts.map +1 -0
  37. package/dist/server/types.d.ts +40 -0
  38. package/dist/server/types.d.ts.map +1 -0
  39. package/dist/server-UBcHtkm-.js +829 -0
  40. package/dist/server-UBcHtkm-.js.map +1 -0
  41. package/dist/ssr.d.ts +38 -0
  42. package/dist/ssr.d.ts.map +1 -0
  43. package/dist/types-B4Rf1Xot.js +6 -0
  44. package/dist/types-B4Rf1Xot.js.map +1 -0
  45. package/package.json +5 -10
  46. package/dist/client/hydrate.d.ts +0 -24
  47. package/dist/client/hydrate.d.ts.map +0 -1
  48. package/dist/client/registry.d.ts +0 -54
  49. package/dist/client/registry.d.ts.map +0 -1
  50. package/dist/client/types.d.ts +0 -23
  51. package/dist/client/types.d.ts.map +0 -1
  52. package/dist/client-DiLwBAD-.js +0 -541
  53. package/dist/client-DiLwBAD-.js.map +0 -1
  54. package/dist/server/stream.d.ts +0 -62
  55. package/dist/server/stream.d.ts.map +0 -1
  56. package/dist/server-BCOJt2Bi.js +0 -459
  57. package/dist/server-BCOJt2Bi.js.map +0 -1
  58. package/dist/shared/utils.d.ts +0 -9
  59. package/dist/shared/utils.d.ts.map +0 -1
  60. package/src/jsx.d.ts +0 -62
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-UBcHtkm-.js","names":[],"sources":["../src/builtin-ssr-directives.ts","../src/server/context.ts","../src/server/render-core.ts","../src/server/streaming.ts","../src/head.ts","../src/ssr.ts","../src/server/render-api.ts","../src/server/index.ts"],"sourcesContent":["/**\r\n * Built-in directive SSR support — lazy patching.\r\n *\r\n * This module patches `getSSRProps` onto built-in directives (like `show`)\r\n * at runtime, keeping `@sigx/runtime-dom` free of SSR knowledge.\r\n *\r\n * Mirrors Vue 3's `initVShowForSSR()` / `initDirectivesForSSR()` pattern.\r\n *\r\n * @internal\r\n */\r\nimport { show } from '@sigx/runtime-dom';\r\n\r\nlet _initialized = false;\r\n\r\n/**\r\n * Patch `getSSRProps` onto the `show` directive for SSR support.\r\n *\r\n * Called lazily from `initDirectivesForSSR()` — not at import time,\r\n * so tree-shaking can eliminate this in client-only builds.\r\n */\r\nfunction initShowForSSR(): void {\r\n (show as any).getSSRProps = ({ value }: { value: boolean }) => {\r\n if (!value) {\r\n return { style: { display: 'none' } };\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Initialize SSR support for all built-in directives.\r\n *\r\n * Must be called before any SSR rendering occurs.\r\n * Safe to call multiple times — only patches once.\r\n */\r\nexport function initDirectivesForSSR(): void {\r\n if (_initialized) return;\r\n _initialized = true;\r\n initShowForSSR();\r\n}\r\n","/**\r\n * SSR Context — tracks component boundaries and rendering state.\r\n *\r\n * This is the core SSR context, free of any strategy-specific logic (islands, etc.).\r\n * Plugins extend it via the generic `_pluginData` map.\r\n */\r\n\r\nimport type { SSRPlugin } from '../plugin';\r\n\r\n/**\r\n * Core-managed pending async component.\r\n * Created by render-core when streaming mode is active and no plugin overrides.\r\n */\r\nexport interface CorePendingAsync {\r\n /** Component ID */\r\n id: number;\r\n /** Resolves to rendered HTML when ssr.load() completes */\r\n promise: Promise<string>;\r\n}\r\n\r\nexport interface SSRContextOptions {\r\n /**\r\n * Enable streaming mode (default: true)\r\n */\r\n streaming?: boolean;\r\n\r\n /**\r\n * Called when a component's setup() throws during SSR.\r\n *\r\n * Return a fallback HTML string to render in place of the failed component,\r\n * or `null` to use the default error placeholder.\r\n *\r\n * @param error - The error thrown during rendering\r\n * @param componentName - The component's `__name` (or 'Anonymous')\r\n * @param componentId - The numeric component ID assigned by the SSR context\r\n */\r\n onComponentError?: (error: Error, componentName: string, componentId: number) => string | null;\r\n}\r\n\r\nexport interface RenderOptions {\r\n /**\r\n * Custom SSR context (created automatically if not provided)\r\n */\r\n context?: SSRContext;\r\n}\r\n\r\nexport interface SSRContext {\r\n /**\r\n * Unique ID counter for component markers\r\n */\r\n _componentId: number;\r\n\r\n /**\r\n * Stack of component IDs for nested tracking\r\n */\r\n _componentStack: number[];\r\n\r\n /**\r\n * Collected head elements (scripts, styles, etc.)\r\n */\r\n _head: string[];\r\n\r\n /**\r\n * Error callback for component rendering failures\r\n */\r\n _onComponentError?: (error: Error, componentName: string, componentId: number) => string | null;\r\n\r\n /**\r\n * Registered SSR plugins\r\n */\r\n _plugins?: SSRPlugin[];\r\n\r\n /**\r\n * Plugin-specific data storage, keyed by plugin name.\r\n * Plugins store their own state here via `getPluginData` / `setPluginData`.\r\n */\r\n _pluginData: Map<string, any>;\r\n\r\n /**\r\n * Whether streaming mode is active.\r\n * When true, async components default to streaming (placeholder + deferred render)\r\n * instead of blocking. Set by renderStream / renderStreamWithCallbacks.\r\n */\r\n _streaming: boolean;\r\n\r\n /**\r\n * Core-managed pending async components.\r\n * Populated by render-core when async components are streamed without a plugin override.\r\n */\r\n _pendingAsync: CorePendingAsync[];\r\n\r\n /**\r\n * Generate next component ID\r\n */\r\n nextId(): number;\r\n\r\n /**\r\n * Push a component onto the stack\r\n */\r\n pushComponent(id: number): void;\r\n\r\n /**\r\n * Pop the current component from stack\r\n */\r\n popComponent(): number | undefined;\r\n\r\n /**\r\n * Add a head element\r\n */\r\n addHead(html: string): void;\r\n\r\n /**\r\n * Get collected head HTML\r\n */\r\n getHead(): string;\r\n\r\n /**\r\n * Get plugin-specific data by plugin name.\r\n */\r\n getPluginData<T>(pluginName: string): T | undefined;\r\n\r\n /**\r\n * Set plugin-specific data by plugin name.\r\n */\r\n setPluginData<T>(pluginName: string, data: T): void;\r\n}\r\n\r\n/**\r\n * Create a new SSR context for rendering\r\n */\r\nexport function createSSRContext(options: SSRContextOptions = {}): SSRContext {\r\n let componentId = 0;\r\n const componentStack: number[] = [];\r\n const head: string[] = [];\r\n const pluginData = new Map<string, any>();\r\n\r\n return {\r\n _componentId: componentId,\r\n _componentStack: componentStack,\r\n _head: head,\r\n _pluginData: pluginData,\r\n _onComponentError: options.onComponentError,\r\n _streaming: false,\r\n _pendingAsync: [],\r\n\r\n nextId() {\r\n return ++componentId;\r\n },\r\n\r\n pushComponent(id: number) {\r\n componentStack.push(id);\r\n },\r\n\r\n popComponent() {\r\n return componentStack.pop();\r\n },\r\n\r\n addHead(html: string) {\r\n head.push(html);\r\n },\r\n\r\n getHead() {\r\n return head.join('\\n');\r\n },\r\n\r\n getPluginData<T>(pluginName: string): T | undefined {\r\n return pluginData.get(pluginName);\r\n },\r\n\r\n setPluginData<T>(pluginName: string, data: T): void {\r\n pluginData.set(pluginName, data);\r\n }\r\n };\r\n}\r\n","/**\r\n * Core rendering logic for SSR\r\n *\r\n * The async generator `renderToChunks` walks a VNode tree and yields HTML strings.\r\n * Handles text, fragments, host elements, and delegates components to the\r\n * component renderer.\r\n *\r\n * This module is strategy-agnostic. Island-specific logic (signal tracking,\r\n * hydration directives, async streaming) lives in @sigx/ssr-islands and is\r\n * injected through the SSRPlugin hooks.\r\n */\r\n\r\nimport {\r\n VNode,\r\n Fragment,\r\n JSXElement,\r\n ComponentSetupContext,\r\n setCurrentInstance,\r\n signal,\r\n Text,\r\n SlotsObject,\r\n isComponent,\r\n createPropsAccessor,\r\n provideAppContext,\r\n isDirective\r\n} from 'sigx';\r\nimport type { DirectiveDefinition } from 'sigx';\r\nimport { resolveBuiltInDirective } from '@sigx/runtime-dom';\r\nimport type { AppContext } from 'sigx';\r\nimport type { SSRContext } from './context';\r\n\r\n// ============= HTML Utilities =============\r\n\r\nconst ESCAPE: Record<string, string> = {\r\n '&': '&amp;',\r\n '<': '&lt;',\r\n '>': '&gt;',\r\n '\"': '&quot;',\r\n \"'\": '&#39;'\r\n};\r\n\r\nexport function escapeHtml(s: string): string {\r\n return s.replace(/[&<>\"']/g, c => ESCAPE[c]);\r\n}\r\n\r\n/** Cache for camelCase → kebab-case conversions (same properties repeat across elements) */\r\nconst kebabCache: Record<string, string> = {};\r\n\r\n/** Void elements that cannot have children — hoisted to module scope as a Set for O(1) lookup */\r\nconst VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);\r\n\r\nexport function camelToKebab(str: string): string {\r\n // CSS custom properties (--foo) are already kebab-case\r\n if (str.startsWith('--')) return str;\r\n return kebabCache[str] ||= str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\r\n}\r\n\r\n// ============= Style Parsing =============\r\n\r\n/**\r\n * Parse a CSS string into a style object.\r\n *\r\n * Handles edge cases: parens in values (e.g., `linear-gradient(...)`),\r\n * CSS comments, and colons in values.\r\n *\r\n * Adapted from Vue 3's `parseStringStyle` — battle-tested, split-based,\r\n * fast in V8.\r\n */\r\nconst listDelimiterRE = /;(?![^(]*\\))/g;\r\nconst propertyDelimiterRE = /:([^]+)/;\r\nconst styleCommentRE = /\\/\\*[^]*?\\*\\//g;\r\n\r\nexport function parseStringStyle(cssText: string): Record<string, string> {\r\n const ret: Record<string, string> = {};\r\n cssText\r\n .replace(styleCommentRE, '')\r\n .split(listDelimiterRE)\r\n .forEach(item => {\r\n if (item) {\r\n const tmp = item.split(propertyDelimiterRE);\r\n if (tmp.length > 1) {\r\n ret[tmp[0].trim()] = tmp[1].trim();\r\n }\r\n }\r\n });\r\n return ret;\r\n}\r\n\r\n/**\r\n * Serialize a style object to a CSS string.\r\n *\r\n * Uses for...in + string concat (avoids Object.entries/map/join allocations)\r\n * and cached kebab-case conversion.\r\n */\r\nexport function stringifyStyle(style: Record<string, any>): string {\r\n let ret = '';\r\n for (const key in style) {\r\n const value = style[key];\r\n if (value != null && value !== '') {\r\n ret += `${camelToKebab(key)}:${value};`;\r\n }\r\n }\r\n return ret;\r\n}\r\n\r\n/**\r\n * Check if element will render as text content\r\n */\r\nfunction isTextContent(element: JSXElement): boolean {\r\n if (element == null || element === false || element === true) return false;\r\n if (typeof element === 'string' || typeof element === 'number') return true;\r\n const vnode = element as VNode;\r\n return vnode.type === Text;\r\n}\r\n\r\n/**\r\n * Merge style values for SSR (element style + directive SSR style).\r\n * Either value can be an object, string, or undefined.\r\n * String styles are parsed into objects before merging.\r\n */\r\nfunction mergeSSRStyles(elementStyle: any, directiveStyle: any): Record<string, any> {\r\n if (!elementStyle) return directiveStyle;\r\n if (!directiveStyle) return elementStyle;\r\n // Normalize both to objects — parse CSS strings if needed\r\n const a = typeof elementStyle === 'string' ? parseStringStyle(elementStyle)\r\n : (typeof elementStyle === 'object' ? elementStyle : {});\r\n const b = typeof directiveStyle === 'string' ? parseStringStyle(directiveStyle)\r\n : (typeof directiveStyle === 'object' ? directiveStyle : {});\r\n return { ...a, ...b };\r\n}\r\n\r\n/**\r\n * Render element to string chunks (generator for streaming)\r\n * @param element - The JSX element to render\r\n * @param ctx - The SSR context for tracking state\r\n * @param parentCtx - The parent component context for provide/inject\r\n * @param appContext - The app context for app-level provides (from defineApp)\r\n */\r\nexport async function* renderToChunks(\r\n element: JSXElement,\r\n ctx: SSRContext,\r\n parentCtx: ComponentSetupContext | null = null,\r\n appContext: AppContext | null = null\r\n): AsyncGenerator<string> {\r\n if (element == null || element === false || element === true) {\r\n return;\r\n }\r\n\r\n if (typeof element === 'string' || typeof element === 'number') {\r\n yield escapeHtml(String(element));\r\n return;\r\n }\r\n\r\n const vnode = element as VNode;\r\n\r\n if (vnode.type === Text) {\r\n yield escapeHtml(String(vnode.text));\r\n return;\r\n }\r\n\r\n if (vnode.type === Fragment) {\r\n for (const child of vnode.children) {\r\n yield* renderToChunks(child, ctx, parentCtx, appContext);\r\n }\r\n return;\r\n }\r\n\r\n // Handle Components\r\n if (isComponent(vnode.type)) {\r\n const setup = vnode.type.__setup;\r\n const componentName = vnode.type.__name || 'Anonymous';\r\n const allProps = vnode.props || {};\r\n\r\n // Destructure props (filter out framework-internal keys)\r\n const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = allProps;\r\n\r\n const id = ctx.nextId();\r\n ctx.pushComponent(id);\r\n\r\n // Create slots from children\r\n const slots: SlotsObject<any> = {\r\n default: () => children ? (Array.isArray(children) ? children : [children]) : [],\r\n ...slotsFromProps\r\n };\r\n\r\n // Track SSR loads for this component\r\n const ssrLoads: Promise<void>[] = [];\r\n\r\n // Create SSR helper for async data loading\r\n const ssrHelper = {\r\n load(fn: () => Promise<void>): void {\r\n ssrLoads.push(fn());\r\n },\r\n isServer: true,\r\n isHydrating: false\r\n };\r\n\r\n let componentCtx: ComponentSetupContext = {\r\n el: null as any,\r\n signal: signal,\r\n props: createPropsAccessor(propsData),\r\n slots: slots,\r\n emit: () => { },\r\n parent: parentCtx,\r\n onMounted: () => { },\r\n onUnmounted: () => { },\r\n onCreated: () => { },\r\n onUpdated: () => { },\r\n expose: () => { },\r\n renderFn: null,\r\n update: () => { },\r\n ssr: ssrHelper,\r\n _ssrLoads: ssrLoads\r\n };\r\n\r\n // Plugin hook: transformComponentContext\r\n // Allows plugins (e.g., islands) to swap signal fn, filter props, set up tracking, etc.\r\n if (ctx._plugins) {\r\n for (const plugin of ctx._plugins) {\r\n const transformed = plugin.server?.transformComponentContext?.(ctx, vnode, componentCtx);\r\n if (transformed) {\r\n componentCtx = transformed;\r\n }\r\n }\r\n }\r\n\r\n // For ROOT component only (no parent), provide the AppContext\r\n if (!parentCtx && appContext) {\r\n provideAppContext(componentCtx, appContext);\r\n }\r\n\r\n const prev = setCurrentInstance(componentCtx);\r\n try {\r\n // Run setup synchronously — it registers ssr.load() callbacks\r\n let renderFn = setup(componentCtx);\r\n\r\n // Support legacy async setup — await if it returns a promise\r\n if (renderFn && typeof (renderFn as any).then === 'function') {\r\n renderFn = await (renderFn as Promise<any>);\r\n }\r\n\r\n // Check if we have pending ssr.load() calls\r\n if (ssrLoads.length > 0) {\r\n // Plugin hook: handleAsyncSetup\r\n // Plugins can override the async mode.\r\n // Default: 'stream' in streaming mode, 'block' in string mode.\r\n let asyncMode: 'block' | 'stream' | 'skip' = ctx._streaming ? 'stream' : 'block';\r\n let asyncPlaceholder: string | undefined;\r\n let pluginHandled = false;\r\n\r\n if (ctx._plugins) {\r\n for (const plugin of ctx._plugins) {\r\n const result = plugin.server?.handleAsyncSetup?.(id, ssrLoads, renderFn as () => any, ctx);\r\n if (result) {\r\n asyncMode = result.mode;\r\n asyncPlaceholder = result.placeholder;\r\n pluginHandled = true;\r\n break; // First plugin to handle wins\r\n }\r\n }\r\n }\r\n\r\n if (asyncMode === 'stream') {\r\n // Use default placeholder if none provided by plugin\r\n const placeholder = asyncPlaceholder || `<div data-async-placeholder=\"${id}\" style=\"display:contents;\">`;\r\n\r\n // Render placeholder immediately\r\n yield placeholder;\r\n\r\n // Render with initial state (before data loads)\r\n if (renderFn) {\r\n const result = (renderFn as () => any)();\r\n if (result) {\r\n if (Array.isArray(result)) {\r\n for (const item of result) {\r\n yield* renderToChunks(item, ctx, componentCtx, appContext);\r\n }\r\n } else {\r\n yield* renderToChunks(result, ctx, componentCtx, appContext);\r\n }\r\n }\r\n }\r\n\r\n yield `</div>`;\r\n\r\n // If no plugin handled this, core manages the deferred render\r\n if (!pluginHandled) {\r\n const capturedRenderFn = renderFn;\r\n const capturedCtx = ctx;\r\n const capturedAppContext = appContext;\r\n\r\n const deferredRender = (async () => {\r\n await Promise.all(ssrLoads);\r\n\r\n let html = '';\r\n if (capturedRenderFn) {\r\n const result = (capturedRenderFn as () => any)();\r\n if (result) {\r\n html = await renderVNodeToString(result, capturedCtx, capturedAppContext);\r\n }\r\n }\r\n\r\n return html;\r\n })();\r\n\r\n ctx._pendingAsync.push({ id, promise: deferredRender });\r\n }\r\n } else if (asyncMode === 'skip') {\r\n // Plugin says skip — don't render content\r\n } else {\r\n // Default: block — wait for all async loads\r\n await Promise.all(ssrLoads);\r\n\r\n if (renderFn) {\r\n const result = (renderFn as () => any)();\r\n if (result) {\r\n if (Array.isArray(result)) {\r\n for (const item of result) {\r\n yield* renderToChunks(item, ctx, componentCtx, appContext);\r\n }\r\n } else {\r\n yield* renderToChunks(result, ctx, componentCtx, appContext);\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // No async loads — render synchronously\r\n if (renderFn) {\r\n const result = (renderFn as () => any)();\r\n if (result) {\r\n if (Array.isArray(result)) {\r\n for (const item of result) {\r\n yield* renderToChunks(item, ctx, componentCtx, appContext);\r\n }\r\n } else {\r\n yield* renderToChunks(result, ctx, componentCtx, appContext);\r\n }\r\n }\r\n }\r\n }\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e));\r\n let fallbackHtml: string | null = null;\r\n\r\n if (ctx._onComponentError) {\r\n fallbackHtml = ctx._onComponentError(error, componentName, id);\r\n }\r\n\r\n if (fallbackHtml === null || fallbackHtml === undefined) {\r\n fallbackHtml = `<!--ssr-error:${id}-->`;\r\n }\r\n\r\n if (fallbackHtml) {\r\n yield fallbackHtml;\r\n }\r\n\r\n if (process.env.NODE_ENV !== 'production') {\r\n console.error(`Error rendering component ${componentName}:`, e);\r\n }\r\n } finally {\r\n setCurrentInstance(prev || null);\r\n }\r\n\r\n // Collect rendered HTML for plugin post-processing\r\n // Note: For streaming, afterRenderComponent receives empty string\r\n // since chunks were already yielded. Plugins that need to wrap\r\n // content should use transformComponentContext to set up wrapping.\r\n\r\n // Plugin hook: afterRenderComponent\r\n if (ctx._plugins) {\r\n for (const plugin of ctx._plugins) {\r\n const transformed = plugin.server?.afterRenderComponent?.(id, vnode, '', ctx);\r\n if (transformed) {\r\n yield transformed;\r\n }\r\n }\r\n }\r\n\r\n // Emit trailing component marker\r\n yield `<!--$c:${id}-->`;\r\n ctx.popComponent();\r\n return;\r\n }\r\n\r\n // Handle host elements\r\n if (typeof vnode.type === 'string') {\r\n const tagName = vnode.type;\r\n let props = '';\r\n\r\n // Collect SSR props from use:* directive props (getSSRProps hook)\r\n let directiveSSRProps: Record<string, any> | null = null;\r\n if (vnode.props) {\r\n for (const key in vnode.props) {\r\n if (key.startsWith('use:')) {\r\n const propValue = vnode.props[key];\r\n let def: DirectiveDefinition | undefined;\r\n let value: any;\r\n\r\n if (isDirective(propValue)) {\r\n def = propValue;\r\n value = undefined;\r\n } else if (\r\n Array.isArray(propValue) &&\r\n propValue.length >= 1 &&\r\n isDirective(propValue[0])\r\n ) {\r\n def = propValue[0];\r\n value = propValue[1];\r\n } else {\r\n // Try to resolve by name:\r\n // 1. Built-in directives (always available, e.g., 'show')\r\n // 2. App-registered custom directives (via app.directive())\r\n const builtIn = resolveBuiltInDirective(key.slice(4));\r\n if (builtIn) {\r\n def = builtIn;\r\n value = propValue;\r\n } else {\r\n const custom = appContext?.directives.get(key.slice(4));\r\n if (custom) {\r\n def = custom;\r\n value = propValue;\r\n }\r\n }\r\n }\r\n\r\n if (def?.getSSRProps) {\r\n const ssrProps = def.getSSRProps({ value });\r\n if (ssrProps) {\r\n if (!directiveSSRProps) directiveSSRProps = {};\r\n for (const k in ssrProps) {\r\n if (k === 'style' && directiveSSRProps.style) {\r\n directiveSSRProps.style = { ...directiveSSRProps.style, ...ssrProps.style };\r\n } else if (k === 'class' && directiveSSRProps.class) {\r\n directiveSSRProps.class = directiveSSRProps.class + ' ' + ssrProps.class;\r\n } else {\r\n directiveSSRProps[k] = ssrProps[k];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Merge directive SSR props with element props\r\n const allProps = directiveSSRProps\r\n ? { ...vnode.props, ...directiveSSRProps, style: mergeSSRStyles(vnode.props?.style, directiveSSRProps?.style) }\r\n : vnode.props;\r\n\r\n // Serialize props\r\n for (const key in allProps) {\r\n const value = allProps[key];\r\n if (key === 'children' || key === 'key' || key === 'ref') continue;\r\n if (key.startsWith('client:')) continue; // Skip client directives\r\n if (key.startsWith('use:')) continue; // Skip element directives\r\n\r\n if (key === 'style') {\r\n const styleString = typeof value === 'object'\r\n ? stringifyStyle(value)\r\n : String(value);\r\n props += ` style=\"${escapeHtml(styleString)}\"`;\r\n } else if (key === 'className') {\r\n props += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key.startsWith('on')) {\r\n // Skip event listeners on server\r\n } else if (value === true) {\r\n props += ` ${key}`;\r\n } else if (value !== false && value != null) {\r\n props += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n // Void elements\r\n if (VOID_ELEMENTS.has(tagName)) {\r\n yield `<${tagName}${props}>`;\r\n return;\r\n }\r\n\r\n yield `<${tagName}${props}>`;\r\n\r\n // Render children with text boundary markers\r\n // Adjacent text nodes get merged by the browser, so we insert <!--t--> markers\r\n let prevWasText = false;\r\n for (const child of vnode.children) {\r\n const isText = isTextContent(child);\r\n if (isText && prevWasText) {\r\n // Insert marker between adjacent text nodes\r\n yield '<!--t-->';\r\n }\r\n yield* renderToChunks(child, ctx, parentCtx, appContext);\r\n prevWasText = isText;\r\n }\r\n\r\n yield `</${tagName}>`;\r\n }\r\n}\r\n\r\n/**\r\n * Helper to render a VNode to string (for deferred async content)\r\n */\r\nexport async function renderVNodeToString(element: JSXElement, ctx: SSRContext, appContext: AppContext | null = null): Promise<string> {\r\n let result = '';\r\n for await (const chunk of renderToChunks(element, ctx, null, appContext)) {\r\n result += chunk;\r\n }\r\n return result;\r\n}\r\n\r\n// ============= Synchronous String Renderer =============\r\n\r\n/**\r\n * Synchronous render-to-string that avoids async generator overhead.\r\n * Returns null if any async operation is encountered (caller should fall back\r\n * to the async generator path).\r\n *\r\n * For purely synchronous component trees this eliminates thousands of\r\n * microtask/Promise allocations from the AsyncGenerator protocol.\r\n */\r\nexport function renderToStringSync(\r\n element: JSXElement,\r\n ctx: SSRContext,\r\n parentCtx: ComponentSetupContext | null,\r\n appContext: AppContext | null,\r\n buf: string[]\r\n): boolean {\r\n if (element == null || element === false || element === true) {\r\n return true;\r\n }\r\n\r\n if (typeof element === 'string' || typeof element === 'number') {\r\n buf.push(escapeHtml(String(element)));\r\n return true;\r\n }\r\n\r\n const vnode = element as VNode;\r\n\r\n if (vnode.type === Text) {\r\n buf.push(escapeHtml(String(vnode.text)));\r\n return true;\r\n }\r\n\r\n if (vnode.type === Fragment) {\r\n for (const child of vnode.children) {\r\n if (!renderToStringSync(child, ctx, parentCtx, appContext, buf)) return false;\r\n }\r\n return true;\r\n }\r\n\r\n // Handle Components\r\n if (isComponent(vnode.type)) {\r\n const setup = vnode.type.__setup;\r\n const componentName = vnode.type.__name || 'Anonymous';\r\n const allProps = vnode.props || {};\r\n\r\n const { children, slots: slotsFromProps, $models: modelsData, ...propsData } = allProps;\r\n\r\n const id = ctx.nextId();\r\n ctx.pushComponent(id);\r\n\r\n const slots: SlotsObject<any> = {\r\n default: () => children ? (Array.isArray(children) ? children : [children]) : [],\r\n ...slotsFromProps\r\n };\r\n\r\n const ssrLoads: Promise<void>[] = [];\r\n\r\n const ssrHelper = {\r\n load(fn: () => Promise<void>): void {\r\n ssrLoads.push(fn());\r\n },\r\n isServer: true,\r\n isHydrating: false\r\n };\r\n\r\n let componentCtx: ComponentSetupContext = {\r\n el: null as any,\r\n signal: signal,\r\n props: createPropsAccessor(propsData),\r\n slots: slots,\r\n emit: () => { },\r\n parent: parentCtx,\r\n onMounted: () => { },\r\n onUnmounted: () => { },\r\n onCreated: () => { },\r\n onUpdated: () => { },\r\n expose: () => { },\r\n renderFn: null,\r\n update: () => { },\r\n ssr: ssrHelper,\r\n _ssrLoads: ssrLoads\r\n };\r\n\r\n if (ctx._plugins) {\r\n for (const plugin of ctx._plugins) {\r\n const transformed = plugin.server?.transformComponentContext?.(ctx, vnode, componentCtx);\r\n if (transformed) {\r\n componentCtx = transformed;\r\n }\r\n }\r\n }\r\n\r\n if (!parentCtx && appContext) {\r\n provideAppContext(componentCtx, appContext);\r\n }\r\n\r\n const prev = setCurrentInstance(componentCtx);\r\n try {\r\n let renderFn = setup(componentCtx);\r\n\r\n // Bail out if setup is async\r\n if (renderFn && typeof (renderFn as any).then === 'function') {\r\n for (const p of ssrLoads) p.catch(() => {});\r\n setCurrentInstance(prev || null);\r\n ctx.popComponent();\r\n return false;\r\n }\r\n\r\n // Bail out if there are ssr.load() calls\r\n if (ssrLoads.length > 0) {\r\n // Suppress unhandled rejections — the async path will re-run these\r\n for (const p of ssrLoads) p.catch(() => {});\r\n setCurrentInstance(prev || null);\r\n ctx.popComponent();\r\n return false;\r\n }\r\n\r\n if (renderFn) {\r\n const result = (renderFn as () => any)();\r\n if (result) {\r\n if (Array.isArray(result)) {\r\n for (const item of result) {\r\n if (!renderToStringSync(item, ctx, componentCtx, appContext, buf)) {\r\n setCurrentInstance(prev || null);\r\n ctx.popComponent();\r\n return false;\r\n }\r\n }\r\n } else {\r\n if (!renderToStringSync(result, ctx, componentCtx, appContext, buf)) {\r\n setCurrentInstance(prev || null);\r\n ctx.popComponent();\r\n return false;\r\n }\r\n }\r\n }\r\n }\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e));\r\n let fallbackHtml: string | null = null;\r\n\r\n if (ctx._onComponentError) {\r\n fallbackHtml = ctx._onComponentError(error, componentName, id);\r\n }\r\n\r\n if (fallbackHtml === null || fallbackHtml === undefined) {\r\n fallbackHtml = `<!--ssr-error:${id}-->`;\r\n }\r\n\r\n if (fallbackHtml) {\r\n buf.push(fallbackHtml);\r\n }\r\n } finally {\r\n setCurrentInstance(prev || null);\r\n }\r\n\r\n if (ctx._plugins) {\r\n for (const plugin of ctx._plugins) {\r\n const transformed = plugin.server?.afterRenderComponent?.(id, vnode, '', ctx);\r\n if (transformed) {\r\n buf.push(transformed);\r\n }\r\n }\r\n }\r\n\r\n buf.push(`<!--$c:${id}-->`);\r\n ctx.popComponent();\r\n return true;\r\n }\r\n\r\n // Handle host elements\r\n if (typeof vnode.type === 'string') {\r\n const tagName = vnode.type;\r\n let props = '';\r\n\r\n let directiveSSRProps: Record<string, any> | null = null;\r\n if (vnode.props) {\r\n for (const key in vnode.props) {\r\n if (key.startsWith('use:')) {\r\n const propValue = vnode.props[key];\r\n let def: DirectiveDefinition | undefined;\r\n let value: any;\r\n\r\n if (isDirective(propValue)) {\r\n def = propValue;\r\n value = undefined;\r\n } else if (\r\n Array.isArray(propValue) &&\r\n propValue.length >= 1 &&\r\n isDirective(propValue[0])\r\n ) {\r\n def = propValue[0];\r\n value = propValue[1];\r\n } else {\r\n const builtIn = resolveBuiltInDirective(key.slice(4));\r\n if (builtIn) {\r\n def = builtIn;\r\n value = propValue;\r\n } else {\r\n const custom = appContext?.directives.get(key.slice(4));\r\n if (custom) {\r\n def = custom;\r\n value = propValue;\r\n }\r\n }\r\n }\r\n\r\n if (def?.getSSRProps) {\r\n const ssrProps = def.getSSRProps({ value });\r\n if (ssrProps) {\r\n if (!directiveSSRProps) directiveSSRProps = {};\r\n for (const k in ssrProps) {\r\n if (k === 'style' && directiveSSRProps.style) {\r\n directiveSSRProps.style = { ...directiveSSRProps.style, ...ssrProps.style };\r\n } else if (k === 'class' && directiveSSRProps.class) {\r\n directiveSSRProps.class = directiveSSRProps.class + ' ' + ssrProps.class;\r\n } else {\r\n directiveSSRProps[k] = ssrProps[k];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n const allProps = directiveSSRProps\r\n ? { ...vnode.props, ...directiveSSRProps, style: mergeSSRStyles(vnode.props?.style, directiveSSRProps?.style) }\r\n : vnode.props;\r\n\r\n for (const key in allProps) {\r\n const value = allProps[key];\r\n if (key === 'children' || key === 'key' || key === 'ref') continue;\r\n if (key.startsWith('client:')) continue;\r\n if (key.startsWith('use:')) continue;\r\n\r\n if (key === 'style') {\r\n const styleString = typeof value === 'object'\r\n ? stringifyStyle(value)\r\n : String(value);\r\n props += ` style=\"${escapeHtml(styleString)}\"`;\r\n } else if (key === 'className') {\r\n props += ` class=\"${escapeHtml(String(value))}\"`;\r\n } else if (key.startsWith('on')) {\r\n // Skip event listeners on server\r\n } else if (value === true) {\r\n props += ` ${key}`;\r\n } else if (value !== false && value != null) {\r\n props += ` ${key}=\"${escapeHtml(String(value))}\"`;\r\n }\r\n }\r\n\r\n if (VOID_ELEMENTS.has(tagName)) {\r\n buf.push(`<${tagName}${props}>`);\r\n return true;\r\n }\r\n\r\n buf.push(`<${tagName}${props}>`);\r\n\r\n let prevWasText = false;\r\n for (const child of vnode.children) {\r\n const isText = isTextContent(child);\r\n if (isText && prevWasText) {\r\n buf.push('<!--t-->');\r\n }\r\n if (!renderToStringSync(child, ctx, parentCtx, appContext, buf)) return false;\r\n prevWasText = isText;\r\n }\r\n\r\n buf.push(`</${tagName}>`);\r\n return true;\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * Core streaming utilities for async SSR\r\n *\r\n * Provides the client-side `$SIGX_REPLACE` function and replacement script\r\n * generation used by core async streaming. These are strategy-agnostic —\r\n * any async component with `ssr.load()` gets streamed without needing a plugin.\r\n *\r\n * Plugins (e.g., islands) can augment replacements via `onAsyncComponentResolved`.\r\n */\r\n\r\n/**\r\n * Escape a JSON string for safe embedding inside <script> tags.\r\n * Prevents XSS by replacing characters that could break out of the script context.\r\n */\r\nexport function escapeJsonForScript(json: string): string {\r\n return json\r\n .replace(/</g, '\\\\u003c')\r\n .replace(/>/g, '\\\\u003e')\r\n .replace(/\\u2028/g, '\\\\u2028')\r\n .replace(/\\u2029/g, '\\\\u2029');\r\n}\r\n\r\n/**\r\n * Generate the streaming bootstrap script (injected once before any replacements).\r\n * Defines `window.$SIGX_REPLACE` which swaps async placeholders with rendered HTML.\r\n */\r\nexport function generateStreamingScript(): string {\r\n return `\r\n<script>\r\nwindow.$SIGX_REPLACE = function(id, html) {\r\n var placeholder = document.querySelector('[data-async-placeholder=\"' + id + '\"]');\r\n if (placeholder) {\r\n var template = document.createElement('template');\r\n template.innerHTML = html;\r\n placeholder.innerHTML = '';\r\n while (template.content.firstChild) {\r\n placeholder.appendChild(template.content.firstChild);\r\n }\r\n placeholder.dispatchEvent(new CustomEvent('sigx:async-ready', { bubbles: true, detail: { id: id } }));\r\n }\r\n};\r\n</script>`;\r\n}\r\n\r\n/**\r\n * Generate a replacement script for a resolved async component.\r\n */\r\nexport function generateReplacementScript(id: number, html: string, extraScript?: string): string {\r\n const escapedHtml = escapeJsonForScript(JSON.stringify(html));\r\n let script = `<script>$SIGX_REPLACE(${id}, ${escapedHtml});`;\r\n if (extraScript) {\r\n script += extraScript;\r\n }\r\n script += `</script>`;\r\n return script;\r\n}\r\n","/**\r\n * Head management composable for SSR and client-side.\r\n *\r\n * Provides `useHead()` for managing `<head>` elements (title, meta, link, script)\r\n * from within components. Works during SSR (collects into SSRContext._head) and\r\n * on the client (updates DOM directly).\r\n *\r\n * @example\r\n * ```tsx\r\n * import { useHead } from '@sigx/server-renderer/head';\r\n *\r\n * function MyPage(ctx) {\r\n * useHead({\r\n * title: 'My Page',\r\n * meta: [\r\n * { name: 'description', content: 'A great page' },\r\n * { property: 'og:title', content: 'My Page' }\r\n * ],\r\n * link: [\r\n * { rel: 'canonical', href: 'https://example.com/my-page' }\r\n * ]\r\n * });\r\n *\r\n * return () => <div>Page content</div>;\r\n * }\r\n * ```\r\n */\r\n\r\nimport { getCurrentInstance } from 'sigx';\r\n\r\n// ============= Types =============\r\n\r\nexport interface HeadMeta {\r\n name?: string;\r\n property?: string;\r\n 'http-equiv'?: string;\r\n charset?: string;\r\n content?: string;\r\n [key: string]: string | undefined;\r\n}\r\n\r\nexport interface HeadLink {\r\n rel: string;\r\n href?: string;\r\n type?: string;\r\n crossorigin?: string;\r\n [key: string]: string | undefined;\r\n}\r\n\r\nexport interface HeadScript {\r\n src?: string;\r\n type?: string;\r\n async?: boolean;\r\n defer?: boolean;\r\n innerHTML?: string;\r\n [key: string]: string | boolean | undefined;\r\n}\r\n\r\nexport interface HeadConfig {\r\n /** Page title */\r\n title?: string;\r\n /** Title template — use %s as placeholder for the title */\r\n titleTemplate?: string;\r\n /** Meta tags */\r\n meta?: HeadMeta[];\r\n /** Link tags */\r\n link?: HeadLink[];\r\n /** Script tags */\r\n script?: HeadScript[];\r\n /** HTML language attribute */\r\n htmlAttrs?: { lang?: string; dir?: string; [key: string]: string | undefined };\r\n /** Body attributes */\r\n bodyAttrs?: { class?: string; [key: string]: string | undefined };\r\n}\r\n\r\n// ============= SSR Head Collection =============\r\n\r\n// Server-side: head configs are collected during rendering\r\nlet _ssrHeadConfigs: HeadConfig[] = [];\r\nlet _isSSR = false;\r\n\r\n/**\r\n * Enable SSR mode for head management.\r\n * Called by the SSR renderer before rendering starts.\r\n */\r\nexport function enableSSRHead(): void {\r\n _isSSR = true;\r\n _ssrHeadConfigs = [];\r\n}\r\n\r\n/**\r\n * Disable SSR mode and return collected configs.\r\n */\r\nexport function collectSSRHead(): HeadConfig[] {\r\n _isSSR = false;\r\n const configs = _ssrHeadConfigs;\r\n _ssrHeadConfigs = [];\r\n return configs;\r\n}\r\n\r\n/**\r\n * Render collected head configs to an HTML string.\r\n * Deduplicates meta tags by name/property and uses the last title.\r\n */\r\nexport function renderHeadToString(configs: HeadConfig[]): string {\r\n const parts: string[] = [];\r\n const seenMeta = new Map<string, string>();\r\n let finalTitle: string | undefined;\r\n let titleTemplate: string | undefined;\r\n\r\n // Process in order — later configs override earlier ones\r\n for (const config of configs) {\r\n if (config.titleTemplate) {\r\n titleTemplate = config.titleTemplate;\r\n }\r\n if (config.title) {\r\n finalTitle = config.title;\r\n }\r\n\r\n if (config.meta) {\r\n for (const meta of config.meta) {\r\n // Deduplicate by name or property\r\n const key = meta.name ? `name:${meta.name}` :\r\n meta.property ? `property:${meta.property}` :\r\n meta['http-equiv'] ? `http-equiv:${meta['http-equiv']}` :\r\n meta.charset ? 'charset' : null;\r\n\r\n const attrs = Object.entries(meta)\r\n .filter(([, v]) => v !== undefined)\r\n .map(([k, v]) => `${escapeAttr(k)}=\"${escapeAttr(String(v))}\"`)\r\n .join(' ');\r\n\r\n const tag = `<meta ${attrs}>`;\r\n\r\n if (key) {\r\n seenMeta.set(key, tag);\r\n } else {\r\n parts.push(tag);\r\n }\r\n }\r\n }\r\n\r\n if (config.link) {\r\n for (const link of config.link) {\r\n const attrs = Object.entries(link)\r\n .filter(([, v]) => v !== undefined)\r\n .map(([k, v]) => `${escapeAttr(k)}=\"${escapeAttr(String(v))}\"`)\r\n .join(' ');\r\n parts.push(`<link ${attrs}>`);\r\n }\r\n }\r\n\r\n if (config.script) {\r\n for (const script of config.script) {\r\n const { innerHTML, ...rest } = script;\r\n const attrs = Object.entries(rest)\r\n .filter(([, v]) => v !== undefined && v !== false)\r\n .map(([k, v]) => v === true ? escapeAttr(k) : `${escapeAttr(k)}=\"${escapeAttr(String(v))}\"`)\r\n .join(' ');\r\n if (innerHTML) {\r\n parts.push(`<script ${attrs}>${innerHTML}</script>`);\r\n } else {\r\n parts.push(`<script ${attrs}></script>`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n const result: string[] = [];\r\n\r\n // Title first\r\n if (finalTitle) {\r\n const title = titleTemplate\r\n ? titleTemplate.replace('%s', finalTitle)\r\n : finalTitle;\r\n result.push(`<title>${escapeHtml(title)}</title>`);\r\n }\r\n\r\n // Deduplicated meta tags\r\n for (const tag of seenMeta.values()) {\r\n result.push(tag);\r\n }\r\n\r\n // Other parts\r\n result.push(...parts);\r\n\r\n return result.join('\\n');\r\n}\r\n\r\n// ============= Client-side Head Management =============\r\n\r\n/** Track elements managed by useHead for cleanup */\r\nconst _managedElements = new WeakMap<object, HTMLElement[]>();\r\nlet _headToken = 0;\r\n\r\nfunction applyHeadClient(config: HeadConfig): (() => void) {\r\n const managed: HTMLElement[] = [];\r\n const token = ++_headToken;\r\n\r\n if (config.title) {\r\n const title = config.titleTemplate\r\n ? config.titleTemplate.replace('%s', config.title)\r\n : config.title;\r\n document.title = title;\r\n }\r\n\r\n if (config.meta) {\r\n for (const meta of config.meta) {\r\n // Remove existing matching meta\r\n const selector = meta.name ? `meta[name=\"${meta.name}\"]` :\r\n meta.property ? `meta[property=\"${meta.property}\"]` :\r\n meta['http-equiv'] ? `meta[http-equiv=\"${meta['http-equiv']}\"]` : null;\r\n\r\n if (selector) {\r\n const existing = document.querySelector(selector);\r\n if (existing) existing.remove();\r\n }\r\n\r\n const el = document.createElement('meta');\r\n for (const [k, v] of Object.entries(meta)) {\r\n if (v !== undefined) el.setAttribute(k, v);\r\n }\r\n el.setAttribute('data-sigx-head', String(token));\r\n document.head.appendChild(el);\r\n managed.push(el);\r\n }\r\n }\r\n\r\n if (config.link) {\r\n for (const link of config.link) {\r\n const el = document.createElement('link');\r\n for (const [k, v] of Object.entries(link)) {\r\n if (v !== undefined) el.setAttribute(k, v);\r\n }\r\n el.setAttribute('data-sigx-head', String(token));\r\n document.head.appendChild(el);\r\n managed.push(el);\r\n }\r\n }\r\n\r\n if (config.script) {\r\n for (const script of config.script) {\r\n const { innerHTML, ...rest } = script;\r\n const el = document.createElement('script');\r\n for (const [k, v] of Object.entries(rest)) {\r\n if (v === true) el.setAttribute(k, '');\r\n else if (v !== undefined && v !== false) el.setAttribute(k, String(v));\r\n }\r\n if (innerHTML) el.textContent = innerHTML;\r\n el.setAttribute('data-sigx-head', String(token));\r\n document.head.appendChild(el);\r\n managed.push(el);\r\n }\r\n }\r\n\r\n if (config.htmlAttrs) {\r\n for (const [k, v] of Object.entries(config.htmlAttrs)) {\r\n if (v !== undefined) document.documentElement.setAttribute(k, v);\r\n }\r\n }\r\n\r\n if (config.bodyAttrs) {\r\n for (const [k, v] of Object.entries(config.bodyAttrs)) {\r\n if (v !== undefined) document.body.setAttribute(k, v);\r\n }\r\n }\r\n\r\n // Return cleanup function\r\n return () => {\r\n for (const el of managed) {\r\n el.remove();\r\n }\r\n };\r\n}\r\n\r\n// ============= Public API =============\r\n\r\n/**\r\n * Manage `<head>` elements from within a component.\r\n *\r\n * During SSR, collects head configs for later rendering with `renderHeadToString()`.\r\n * On the client, updates the DOM directly. Cleans up on component unmount.\r\n *\r\n * @param config - Head configuration (title, meta, link, script, etc.)\r\n */\r\nexport function useHead(config: HeadConfig): void {\r\n if (_isSSR) {\r\n // Server-side: collect configs\r\n _ssrHeadConfigs.push(config);\r\n return;\r\n }\r\n\r\n // Client-side: apply to DOM and register cleanup\r\n const cleanup = applyHeadClient(config);\r\n\r\n // If we're inside a component setup, register cleanup on unmount\r\n const instance = getCurrentInstance();\r\n if (instance) {\r\n instance.onUnmounted(() => cleanup());\r\n }\r\n}\r\n\r\n// ============= Utilities =============\r\n\r\nfunction escapeHtml(s: string): string {\r\n return s\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;');\r\n}\r\n\r\nfunction escapeAttr(s: string): string {\r\n return s\r\n .replace(/&/g, '&amp;')\r\n .replace(/\"/g, '&quot;');\r\n}\r\n","/**\r\n * SSR Factory\r\n *\r\n * Creates an SSR instance with plugin support.\r\n * Plugins are registered via `.use()` and called at appropriate points\r\n * during server rendering and client hydration.\r\n *\r\n * @example\r\n * ```ts\r\n * import { createSSR } from '@sigx/server-renderer';\r\n * import { islandsPlugin } from '@sigx/ssr-islands';\r\n *\r\n * const ssr = createSSR().use(islandsPlugin());\r\n * const html = await ssr.render(<App />);\r\n * ```\r\n */\r\n\r\nimport type { SSRPlugin } from './plugin';\r\nimport type { JSXElement } from 'sigx';\r\nimport type { App, AppContext } from 'sigx';\r\nimport { SSRContext, createSSRContext, SSRContextOptions, CorePendingAsync } from './server/context';\r\nimport { renderToChunks, renderToStringSync } from './server/render-core';\r\nimport { generateStreamingScript, generateReplacementScript } from './server/streaming';\r\nimport { enableSSRHead, collectSSRHead, renderHeadToString } from './head';\r\nimport type { StreamCallbacks } from './server/types';\r\n\r\n/**\r\n * Check if the input is an App instance (created via defineApp)\r\n */\r\nfunction isApp(input: any): input is App<any> {\r\n return input && typeof input === 'object' && '_rootComponent' in input && '_context' in input;\r\n}\r\n\r\n/**\r\n * Extract the JSX element and optional AppContext from a render input.\r\n */\r\nfunction extractInput(input: JSXElement | App): { element: JSXElement; appContext: AppContext | null } {\r\n if (isApp(input)) {\r\n return { element: input._rootComponent, appContext: input._context };\r\n }\r\n return { element: input, appContext: null };\r\n}\r\n\r\n/**\r\n * Yield all async streaming chunks — core-managed and plugin-managed — interleaved\r\n * so the fastest component streams first regardless of who manages it.\r\n *\r\n * Core-managed: ctx._pendingAsync (from render-core when no plugin overrides)\r\n * Plugin-managed: plugin.server.getStreamingChunks() async generators\r\n *\r\n * Both are raced together using a unified promise race loop.\r\n */\r\nasync function* streamAllAsyncChunks(\r\n ctx: SSRContext,\r\n plugins: SSRPlugin[]\r\n): AsyncGenerator<string> {\r\n type TaggedResult = { index: number; script: string };\r\n\r\n const hasCoreAsync = ctx._pendingAsync.length > 0;\r\n\r\n // Collect plugin streaming generators\r\n const pluginGenerators: AsyncGenerator<string>[] = [];\r\n for (const plugin of plugins) {\r\n const chunks = plugin.server?.getStreamingChunks?.(ctx);\r\n if (chunks) pluginGenerators.push(chunks);\r\n }\r\n\r\n const hasPluginStreaming = pluginGenerators.length > 0;\r\n\r\n // Nothing to stream\r\n if (!hasCoreAsync && !hasPluginStreaming) return;\r\n\r\n // Emit the $SIGX_REPLACE bootstrap script (needed by core replacements)\r\n if (hasCoreAsync) {\r\n yield generateStreamingScript();\r\n }\r\n\r\n // Build tagged promises for core-managed async components\r\n const corePromises: Promise<TaggedResult>[] = ctx._pendingAsync.map(\r\n (pending, index) =>\r\n pending.promise.then(html => {\r\n // Let plugins augment the resolved HTML\r\n let finalHtml = html;\r\n let extraScript = '';\r\n for (const plugin of plugins) {\r\n const result = plugin.server?.onAsyncComponentResolved?.(pending.id, finalHtml, ctx);\r\n if (result) {\r\n if (result.html !== undefined) finalHtml = result.html;\r\n if (result.script) extraScript += result.script;\r\n }\r\n }\r\n return {\r\n index,\r\n script: generateReplacementScript(pending.id, finalHtml, extraScript || undefined)\r\n };\r\n }).catch(error => {\r\n if (process.env.NODE_ENV !== 'production') {\r\n console.error(`Error streaming async component ${pending.id}:`, error);\r\n }\r\n return {\r\n index,\r\n script: generateReplacementScript(\r\n pending.id,\r\n `<div style=\"color:red;\">Error loading component</div>`\r\n )\r\n };\r\n })\r\n );\r\n\r\n const totalCore = corePromises.length;\r\n\r\n // Set up pump pattern for plugin generators so they can be raced alongside core\r\n interface PumpState {\r\n generator: AsyncGenerator<string>;\r\n done: boolean;\r\n }\r\n const pumps: PumpState[] = pluginGenerators.map(g => ({ generator: g, done: false }));\r\n\r\n // Active pump promises, keyed by their slot index (totalCore + i)\r\n const activePumps = new Map<number, Promise<TaggedResult>>();\r\n\r\n function pumpNext(pumpIdx: number): Promise<TaggedResult> {\r\n const slotIndex = totalCore + pumpIdx;\r\n return pumps[pumpIdx].generator.next().then(({ value, done }) => {\r\n if (done) {\r\n pumps[pumpIdx].done = true;\r\n activePumps.delete(slotIndex);\r\n return { index: slotIndex, script: '' };\r\n }\r\n // Re-queue: set new promise for this slot\r\n const nextP = pumpNext(pumpIdx);\r\n activePumps.set(slotIndex, nextP);\r\n return { index: slotIndex, script: value || '' };\r\n });\r\n }\r\n\r\n // Start initial pumps\r\n for (let i = 0; i < pumps.length; i++) {\r\n const slotIndex = totalCore + i;\r\n const p = pumpNext(i);\r\n activePumps.set(slotIndex, p);\r\n }\r\n\r\n // Race loop: core promises + pump promises\r\n const resolvedCore = new Set<number>();\r\n\r\n function getRaceablePromises(): Promise<TaggedResult>[] {\r\n const promises: Promise<TaggedResult>[] = [];\r\n for (let i = 0; i < totalCore; i++) {\r\n if (!resolvedCore.has(i)) promises.push(corePromises[i]);\r\n }\r\n for (const [, p] of activePumps) {\r\n promises.push(p);\r\n }\r\n return promises;\r\n }\r\n\r\n while (true) {\r\n const raceable = getRaceablePromises();\r\n if (raceable.length === 0) break;\r\n\r\n const winner = await Promise.race(raceable);\r\n\r\n if (winner.script) {\r\n yield winner.script;\r\n }\r\n\r\n if (winner.index < totalCore) {\r\n resolvedCore.add(winner.index);\r\n }\r\n // Pump promises auto-re-queue in pumpNext(), so no action needed here\r\n }\r\n}\r\n\r\nexport interface SSRInstance {\r\n /** Register a plugin */\r\n use(plugin: SSRPlugin): SSRInstance;\r\n\r\n /** Render to a complete HTML string */\r\n render(input: JSXElement | App, options?: SSRContextOptions | SSRContext): Promise<string>;\r\n\r\n /** Render to a ReadableStream with streaming support */\r\n renderStream(input: JSXElement | App, options?: SSRContextOptions | SSRContext): ReadableStream<string>;\r\n\r\n /** Render with callbacks for fine-grained streaming control */\r\n renderStreamWithCallbacks(\r\n input: JSXElement | App,\r\n callbacks: StreamCallbacks,\r\n options?: SSRContextOptions | SSRContext\r\n ): Promise<void>;\r\n\r\n /** Create a raw SSRContext with plugins pre-configured */\r\n createContext(options?: SSRContextOptions): SSRContext;\r\n}\r\n\r\n/**\r\n * Create an SSR instance with plugin support.\r\n */\r\nexport function createSSR(): SSRInstance {\r\n const plugins: SSRPlugin[] = [];\r\n\r\n function makeContext(options?: SSRContextOptions | SSRContext): SSRContext {\r\n // Accept an existing SSRContext (has _componentId) or create one from options\r\n const ctx = (options && '_componentId' in options)\r\n ? options as SSRContext\r\n : createSSRContext(options as SSRContextOptions | undefined);\r\n ctx._plugins = plugins;\r\n // Run plugin setup hooks\r\n for (const plugin of plugins) {\r\n plugin.server?.setup?.(ctx);\r\n }\r\n return ctx;\r\n }\r\n\r\n return {\r\n use(plugin: SSRPlugin): SSRInstance {\r\n plugins.push(plugin);\r\n return this;\r\n },\r\n\r\n async render(input, options?) {\r\n const { element, appContext } = extractInput(input);\r\n\r\n // Enable head collection during SSR rendering\r\n enableSSRHead();\r\n\r\n let result = '';\r\n let ctx: SSRContext;\r\n\r\n // Try fast synchronous render path first (works with or without plugins).\r\n // All plugin hooks called during the tree walk are synchronous.\r\n const syncCtx = makeContext(options);\r\n const buf: string[] = [];\r\n const syncOk = renderToStringSync(element, syncCtx, null, appContext, buf);\r\n\r\n if (syncOk) {\r\n result = buf.join('');\r\n ctx = syncCtx;\r\n } else {\r\n // Tree has async operations — fall back to async generator path.\r\n // We need a fresh context since the sync attempt may have partially\r\n // modified plugin state.\r\n ctx = makeContext(options);\r\n for await (const chunk of renderToChunks(element, ctx, null, appContext)) {\r\n result += chunk;\r\n }\r\n }\r\n\r\n // Collect injected HTML from all plugins\r\n for (const plugin of plugins) {\r\n const injected = plugin.server?.getInjectedHTML?.(ctx);\r\n if (injected) {\r\n result += typeof injected === 'string' ? injected : await injected;\r\n }\r\n }\r\n\r\n // Collect streaming chunks (for renderToString, await all)\r\n for (const plugin of plugins) {\r\n const chunks = plugin.server?.getStreamingChunks?.(ctx);\r\n if (chunks) {\r\n for await (const chunk of chunks) {\r\n result += chunk;\r\n }\r\n }\r\n }\r\n\r\n // Collect head elements from useHead() calls during rendering\r\n const headConfigs = collectSSRHead();\r\n if (headConfigs.length > 0) {\r\n ctx.addHead(renderHeadToString(headConfigs));\r\n }\r\n\r\n return result;\r\n },\r\n\r\n renderStream(input, options?) {\r\n const ctx = makeContext(options);\r\n ctx._streaming = true;\r\n const { element, appContext } = extractInput(input);\r\n\r\n return new ReadableStream<string>({\r\n async start(controller) {\r\n try {\r\n // Enable head collection\r\n enableSSRHead();\r\n\r\n // Phase 1: Render the main page (placeholders for async components)\r\n for await (const chunk of renderToChunks(element, ctx, null, appContext)) {\r\n controller.enqueue(chunk);\r\n }\r\n\r\n // Collect head from useHead() calls\r\n const headConfigs = collectSSRHead();\r\n if (headConfigs.length > 0) {\r\n ctx.addHead(renderHeadToString(headConfigs));\r\n }\r\n\r\n // Phase 2: Injected HTML from plugins\r\n for (const plugin of plugins) {\r\n const injected = plugin.server?.getInjectedHTML?.(ctx);\r\n if (injected) {\r\n const html = typeof injected === 'string' ? injected : await injected;\r\n if (html) controller.enqueue(html);\r\n }\r\n }\r\n\r\n // Phase 3: Stream async chunks — core + plugin interleaved\r\n for await (const chunk of streamAllAsyncChunks(ctx, plugins)) {\r\n controller.enqueue(chunk);\r\n }\r\n\r\n // Phase 4: Signal streaming complete\r\n controller.enqueue(\r\n `<script>window.__SIGX_STREAMING_COMPLETE__=true;window.dispatchEvent(new Event('sigx:ready'));</script>`\r\n );\r\n\r\n controller.close();\r\n } catch (error) {\r\n controller.error(error);\r\n }\r\n }\r\n });\r\n },\r\n\r\n async renderStreamWithCallbacks(input, callbacks, options?) {\r\n const ctx = makeContext(options);\r\n ctx._streaming = true;\r\n const { element, appContext } = extractInput(input);\r\n\r\n try {\r\n // Enable head collection\r\n enableSSRHead();\r\n\r\n // Phase 1: Render the shell\r\n let shellHtml = '';\r\n for await (const chunk of renderToChunks(element, ctx, null, appContext)) {\r\n shellHtml += chunk;\r\n }\r\n\r\n // Collect head from useHead() calls\r\n const headConfigs = collectSSRHead();\r\n if (headConfigs.length > 0) {\r\n ctx.addHead(renderHeadToString(headConfigs));\r\n }\r\n\r\n // Phase 2: Append plugin injected HTML to shell\r\n for (const plugin of plugins) {\r\n const injected = plugin.server?.getInjectedHTML?.(ctx);\r\n if (injected) {\r\n shellHtml += typeof injected === 'string' ? injected : await injected;\r\n }\r\n }\r\n\r\n shellHtml += `<script>window.__SIGX_STREAMING_COMPLETE__=true;window.dispatchEvent(new Event('sigx:ready'));</script>`;\r\n\r\n callbacks.onShellReady(shellHtml);\r\n\r\n // Phase 3: Stream async chunks — core + plugin interleaved\r\n for await (const chunk of streamAllAsyncChunks(ctx, plugins)) {\r\n callbacks.onAsyncChunk(chunk);\r\n }\r\n\r\n callbacks.onComplete();\r\n } catch (error) {\r\n callbacks.onError(error as Error);\r\n }\r\n },\r\n\r\n createContext(options?) {\r\n return makeContext(options);\r\n }\r\n };\r\n}\r\n","/**\r\n * Public SSR rendering APIs — convenience wrappers\r\n *\r\n * These delegate to `createSSR()` internally so there is exactly one\r\n * rendering pipeline. When no plugins are registered the plugin hooks\r\n * are simply no-ops, making these equivalent to calling `createSSR()`\r\n * directly — but with a simpler call signature for the common case.\r\n *\r\n * For plugin-driven rendering (islands, streaming async, etc.),\r\n * use `createSSR().use(plugin).render()` from `@sigx/server-renderer`.\r\n *\r\n * Entry points:\r\n * - `renderToString()` — full render to a single string\r\n * - `renderToStream()` — ReadableStream\r\n * - `renderToStreamWithCallbacks()` — callback-based streaming\r\n */\r\n\r\nimport type { JSXElement } from 'sigx';\r\nimport type { App } from 'sigx';\r\nimport type { SSRContext, SSRContextOptions } from './context';\r\nimport { createSSR } from '../ssr';\r\nimport type { StreamCallbacks } from './types';\r\n\r\n// Re-export StreamCallbacks from shared types (avoids circular dependency)\r\nexport type { StreamCallbacks } from './types';\r\n\r\n/** Shared no-plugin instance — created once, reused for all standalone calls. */\r\nconst _defaultSSR = createSSR();\r\n\r\n/**\r\n * Render JSX element or App to a ReadableStream.\r\n *\r\n * Internally delegates to `createSSR().renderStream()`.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Simple usage with JSX\r\n * renderToStream(<App />)\r\n *\r\n * // With App instance for DI/plugins\r\n * const app = defineApp(<App />).use(router);\r\n * renderToStream(app)\r\n * ```\r\n */\r\nexport function renderToStream(input: JSXElement | App, context?: SSRContext): ReadableStream<string> {\r\n return _defaultSSR.renderStream(input, context);\r\n}\r\n\r\n/**\r\n * Render with callbacks for fine-grained streaming control.\r\n *\r\n * Internally delegates to `createSSR().renderStreamWithCallbacks()`.\r\n *\r\n * @example\r\n * ```tsx\r\n * const app = defineApp(<App />).use(router);\r\n * await renderToStreamWithCallbacks(app, callbacks)\r\n * ```\r\n */\r\nexport async function renderToStreamWithCallbacks(\r\n input: JSXElement | App,\r\n callbacks: StreamCallbacks,\r\n context?: SSRContext\r\n): Promise<void> {\r\n return _defaultSSR.renderStreamWithCallbacks(input, callbacks, context);\r\n}\r\n\r\n/**\r\n * Render JSX element or App to string.\r\n *\r\n * Internally delegates to `createSSR().render()`.\r\n *\r\n * @example\r\n * ```tsx\r\n * const html = await renderToString(<App />);\r\n *\r\n * const app = defineApp(<App />).use(router);\r\n * const html = await renderToString(app);\r\n * ```\r\n */\r\nexport async function renderToString(input: JSXElement | App, context?: SSRContext): Promise<string> {\r\n return _defaultSSR.render(input, context);\r\n}\r\n","/**\r\n * @sigx/server-renderer/server\r\n * \r\n * Server-side rendering with streaming support and hydration markers.\r\n * Strategy-agnostic — plugins add islands, Suspense, etc.\r\n */\r\n\r\n// Load SSR type augmentations (SSRHelper, ComponentSetupContext extensions)\r\nimport '../client-directives.js';\r\n\r\n// Load SSR directive type augmentation (adds getSSRProps to DirectiveDefinition)\r\nimport '../directive-ssr-types.js';\r\n\r\n// Patch getSSRProps onto built-in directives (show, etc.)\r\nimport { initDirectivesForSSR } from '../builtin-ssr-directives.js';\r\ninitDirectivesForSSR();\r\n\r\nexport { renderToStream, renderToString, renderToStreamWithCallbacks } from './render-api';\r\nexport { renderVNodeToString } from './render-core';\r\nexport { createSSRContext } from './context';\r\nexport type { SSRContext, SSRContextOptions, RenderOptions, CorePendingAsync } from './context';\r\nexport { generateStreamingScript, generateReplacementScript, escapeJsonForScript } from './streaming';\r\nexport type { SSRSignalFn, StreamCallbacks } from './types';\r\nexport { generateSignalKey } from './types';\r\n"],"mappings":"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"}
package/dist/ssr.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * SSR Factory
3
+ *
4
+ * Creates an SSR instance with plugin support.
5
+ * Plugins are registered via `.use()` and called at appropriate points
6
+ * during server rendering and client hydration.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { createSSR } from '@sigx/server-renderer';
11
+ * import { islandsPlugin } from '@sigx/ssr-islands';
12
+ *
13
+ * const ssr = createSSR().use(islandsPlugin());
14
+ * const html = await ssr.render(<App />);
15
+ * ```
16
+ */
17
+ import type { SSRPlugin } from './plugin';
18
+ import type { JSXElement } from 'sigx';
19
+ import type { App } from 'sigx';
20
+ import { SSRContext, SSRContextOptions } from './server/context';
21
+ import type { StreamCallbacks } from './server/types';
22
+ export interface SSRInstance {
23
+ /** Register a plugin */
24
+ use(plugin: SSRPlugin): SSRInstance;
25
+ /** Render to a complete HTML string */
26
+ render(input: JSXElement | App, options?: SSRContextOptions | SSRContext): Promise<string>;
27
+ /** Render to a ReadableStream with streaming support */
28
+ renderStream(input: JSXElement | App, options?: SSRContextOptions | SSRContext): ReadableStream<string>;
29
+ /** Render with callbacks for fine-grained streaming control */
30
+ renderStreamWithCallbacks(input: JSXElement | App, callbacks: StreamCallbacks, options?: SSRContextOptions | SSRContext): Promise<void>;
31
+ /** Create a raw SSRContext with plugins pre-configured */
32
+ createContext(options?: SSRContextOptions): SSRContext;
33
+ }
34
+ /**
35
+ * Create an SSR instance with plugin support.
36
+ */
37
+ export declare function createSSR(): SSRInstance;
38
+ //# sourceMappingURL=ssr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr.d.ts","sourceRoot":"","sources":["../src/ssr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,KAAK,EAAE,GAAG,EAAc,MAAM,MAAM,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAoB,iBAAiB,EAAoB,MAAM,kBAAkB,CAAC;AAIrG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAsJtD,MAAM,WAAW,WAAW;IACxB,wBAAwB;IACxB,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAEpC,uCAAuC;IACvC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,GAAG,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE3F,wDAAwD;IACxD,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,GAAG,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAExG,+DAA+D;IAC/D,yBAAyB,CACrB,KAAK,EAAE,UAAU,GAAG,GAAG,EACvB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,GACzC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB,0DAA0D;IAC1D,aAAa,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAAC;CAC1D;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,WAAW,CA8KvC"}
@@ -0,0 +1,6 @@
1
+ function generateSignalKey(name, index) {
2
+ return name ?? `$${index}`;
3
+ }
4
+ export { generateSignalKey as t };
5
+
6
+ //# sourceMappingURL=types-B4Rf1Xot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-B4Rf1Xot.js","names":[],"sources":["../src/server/types.ts"],"sourcesContent":["/**\r\n * Shared types for server rendering APIs.\r\n * \r\n * Kept separate to avoid circular imports between ssr.ts and render-api.ts.\r\n */\r\n\r\nimport type { Signal, PrimitiveSignal, Primitive } from 'sigx';\r\n\r\n/**\r\n * SSR-enhanced signal function type.\r\n * Extends the base signal() with an optional `name` parameter used as the\r\n * serialization key for hydration state transfer.\r\n *\r\n * Both `createTrackingSignal` (server/islands) and `createRestoringSignal` (client/hydration)\r\n * use this type and share the same key-generation contract via `generateSignalKey`.\r\n */\r\nexport type SSRSignalFn = {\r\n <T extends Primitive>(initial: T, name?: string): PrimitiveSignal<T>;\r\n <T extends object>(initial: T, name?: string): Signal<T>;\r\n};\r\n\r\n/**\r\n * Generate a stable key for a signal during SSR state tracking/restoration.\r\n *\r\n * Named signals use the provided name; unnamed signals use a positional key (`$0`, `$1`, ...).\r\n * Both server-side tracking (`createTrackingSignal`) and client-side restoration\r\n * (`createRestoringSignal`) MUST use this function to guarantee key parity.\r\n */\r\nexport function generateSignalKey(name: string | undefined, index: number): string {\r\n return name ?? `$${index}`;\r\n}\r\n\r\n/**\r\n * Streaming callbacks interface\r\n */\r\nexport interface StreamCallbacks {\r\n /** Called when the initial shell (synchronous content) is ready */\r\n onShellReady: (html: string) => void;\r\n /** Called for each async chunk (replacement scripts, hydration data) */\r\n onAsyncChunk: (chunk: string) => void;\r\n /** Called when all streaming is complete */\r\n onComplete: () => void;\r\n /** Called on error */\r\n onError: (error: Error) => void;\r\n}\r\n"],"mappings":"AA4BA,SAAgB,kBAAkB,MAA0B,OAAuB;AAC/E,QAAO,QAAQ,IAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sigx/server-renderer",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Server-side rendering and client hydration for SigX",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,14 +17,10 @@
17
17
  "./client": {
18
18
  "import": "./dist/client/index.js",
19
19
  "types": "./dist/client/index.d.ts"
20
- },
21
- "./jsx": {
22
- "types": "./src/jsx.d.ts"
23
20
  }
24
21
  },
25
22
  "files": [
26
- "dist",
27
- "src/jsx.d.ts"
23
+ "dist"
28
24
  ],
29
25
  "keywords": [
30
26
  "sigx",
@@ -32,8 +28,7 @@
32
28
  "server-side-rendering",
33
29
  "server",
34
30
  "renderer",
35
- "hydration",
36
- "islands"
31
+ "hydration"
37
32
  ],
38
33
  "author": "Andreas Ekdahl",
39
34
  "license": "MIT",
@@ -47,12 +42,12 @@
47
42
  "url": "https://github.com/signalxjs/core/issues"
48
43
  },
49
44
  "dependencies": {
50
- "sigx": "^0.1.6"
45
+ "sigx": "^0.1.7"
51
46
  },
52
47
  "devDependencies": {
53
48
  "typescript": "^5.9.3",
54
49
  "vite": "^8.0.0-beta.9",
55
- "@sigx/vite": "^0.1.6"
50
+ "@sigx/vite": "^0.1.7"
56
51
  },
57
52
  "scripts": {
58
53
  "build": "vite build && tsc --emitDeclarationOnly",
@@ -1,24 +0,0 @@
1
- /**
2
- * Client-side hydration for SSR'd content
3
- *
4
- * Hydration attaches the app to existing server-rendered DOM,
5
- * then delegates all updates to the runtime-dom renderer.
6
- */
7
- import { AppContext } from 'sigx';
8
- export type { HydrationOptions } from './types.js';
9
- /**
10
- * Hydrate a server-rendered app.
11
- *
12
- * This walks the existing DOM to attach event handlers, runs component
13
- * setup functions to establish reactivity, then uses runtime-dom for updates.
14
- *
15
- * @param element - The root element/VNode to hydrate
16
- * @param container - The DOM container with SSR content
17
- * @param appContext - The app context for DI (provides, etc.)
18
- */
19
- export declare function hydrate(element: any, container: Element, appContext?: AppContext): void;
20
- /**
21
- * Hydrate islands based on their strategies (selective hydration)
22
- */
23
- export declare function hydrateIslands(): void;
24
- //# sourceMappingURL=hydrate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hydrate.d.ts","sourceRoot":"","sources":["../../src/client/hydrate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAuBH,UAAU,EAEb,MAAM,MAAM,CAAC;AAKd,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA0FnD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI,CAYvF;AA+gBD;;GAEG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAkBrC"}
@@ -1,54 +0,0 @@
1
- /**
2
- * Component Registry for Island Hydration
3
- *
4
- * Components must be registered before they can be hydrated as islands.
5
- */
6
- /**
7
- * Minimal type for component factories used in hydration registry.
8
- * Compatible with ComponentFactory from runtime-core.
9
- */
10
- export interface ComponentFactory {
11
- __setup: Function;
12
- __name?: string;
13
- __async?: boolean;
14
- }
15
- /**
16
- * Register a component for island hydration.
17
- * Components must be registered before hydrateIslands() is called.
18
- *
19
- * @example
20
- * ```ts
21
- * import { registerComponent } from '@sigx/server-renderer/client';
22
- * import { Counter } from './components/Counter';
23
- *
24
- * registerComponent('Counter', Counter);
25
- * ```
26
- */
27
- export declare function registerComponent(name: string, component: ComponentFactory): void;
28
- /**
29
- * Register multiple components at once
30
- *
31
- * @example
32
- * ```ts
33
- * import { registerComponents } from '@sigx/server-renderer/client';
34
- * import * as Components from './components';
35
- *
36
- * registerComponents(Components);
37
- * ```
38
- */
39
- export declare function registerComponents(components: Record<string, ComponentFactory>): void;
40
- /**
41
- * Get a registered component by name
42
- */
43
- export declare function getComponent(name: string): ComponentFactory | undefined;
44
- /**
45
- * Hydration Registry class for more advanced use cases
46
- */
47
- export declare class HydrationRegistry {
48
- private components;
49
- register(name: string, component: ComponentFactory): this;
50
- registerAll(components: Record<string, ComponentFactory>): this;
51
- get(name: string): ComponentFactory | undefined;
52
- has(name: string): boolean;
53
- }
54
- //# sourceMappingURL=registry.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/client/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,QAAQ,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAEjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,IAAI,CAMrF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAEvE;AAID;;GAEG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,UAAU,CAAuC;IAEzD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAKzD,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,IAAI;IAS/D,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAI/C,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CAG7B"}
@@ -1,23 +0,0 @@
1
- /**
2
- * Shared types for client-side hydration
3
- */
4
- export type { VNode } from 'sigx';
5
- /**
6
- * Hydration options
7
- */
8
- export interface HydrationOptions {
9
- recover?: boolean;
10
- onMismatch?: (message: string, node: Node | null, vnode: any) => void;
11
- }
12
- /**
13
- * Island information serialized from server
14
- */
15
- export interface IslandInfo {
16
- strategy: 'load' | 'idle' | 'visible' | 'media' | 'only';
17
- media?: string;
18
- props?: Record<string, any>;
19
- componentId?: string;
20
- /** Captured signal state from async setup for client hydration */
21
- state?: Record<string, any>;
22
- }
23
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,YAAY,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAElC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACzE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B"}