@pyreon/runtime-server 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +20 -7
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +19 -7
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +20 -11
|
@@ -5386,7 +5386,7 @@ var drawChart = (function (exports) {
|
|
|
5386
5386
|
</script>
|
|
5387
5387
|
<script>
|
|
5388
5388
|
/*<!--*/
|
|
5389
|
-
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"
|
|
5389
|
+
const data = {"version":2,"tree":{"name":"root","children":[{"name":"index.js","children":[{"name":"src/index.ts","uid":"8b5feff8-1"}]}],"isRoot":true},"nodeParts":{"8b5feff8-1":{"renderedLength":10969,"gzipLength":3533,"brotliLength":0,"metaUid":"8b5feff8-0"}},"nodeMetas":{"8b5feff8-0":{"id":"/src/index.ts","moduleParts":{"index.js":"8b5feff8-1"},"imported":[{"uid":"8b5feff8-2"},{"uid":"8b5feff8-3"}],"importedBy":[],"isEntry":true},"8b5feff8-2":{"id":"node:async_hooks","moduleParts":{},"imported":[],"importedBy":[{"uid":"8b5feff8-0"}]},"8b5feff8-3":{"id":"@pyreon/core","moduleParts":{},"imported":[],"importedBy":[{"uid":"8b5feff8-0"}]}},"env":{"rollup":"4.23.0"},"options":{"gzip":true,"brotli":false,"sourcemap":false}};
|
|
5390
5390
|
|
|
5391
5391
|
const run = () => {
|
|
5392
5392
|
const width = window.innerWidth;
|
package/lib/index.js
CHANGED
|
@@ -111,8 +111,9 @@ async function streamComponentNode(vnode, enqueue) {
|
|
|
111
111
|
async function streamElementNode(vnode, enqueue) {
|
|
112
112
|
const tag = vnode.type;
|
|
113
113
|
let open = `<${tag}`;
|
|
114
|
-
|
|
115
|
-
|
|
114
|
+
const props = vnode.props;
|
|
115
|
+
for (const key in props) {
|
|
116
|
+
const attr = renderProp(key, props[key]);
|
|
116
117
|
if (attr) open += ` ${attr}`;
|
|
117
118
|
}
|
|
118
119
|
if (isVoidElement(tag)) {
|
|
@@ -177,18 +178,27 @@ async function renderNode(node) {
|
|
|
177
178
|
if (node == null || node === false) return "";
|
|
178
179
|
if (typeof node === "string") return escapeHtml(node);
|
|
179
180
|
if (typeof node === "number" || typeof node === "boolean") return String(node);
|
|
180
|
-
if (Array.isArray(node))
|
|
181
|
+
if (Array.isArray(node)) {
|
|
182
|
+
let html = "";
|
|
183
|
+
for (const child of node) html += await renderNode(child);
|
|
184
|
+
return html;
|
|
185
|
+
}
|
|
181
186
|
const vnode = node;
|
|
182
187
|
if (vnode.type === Fragment) return renderChildren(vnode.children);
|
|
183
188
|
if (vnode.type === ForSymbol) {
|
|
184
189
|
const { each, children } = vnode.props;
|
|
185
|
-
|
|
190
|
+
let forHtml = "<!--pyreon-for-->";
|
|
191
|
+
for (const item of each()) forHtml += await renderNode(children(item));
|
|
192
|
+
forHtml += "<!--/pyreon-for-->";
|
|
193
|
+
return forHtml;
|
|
186
194
|
}
|
|
187
195
|
if (typeof vnode.type === "function") return renderComponent(vnode);
|
|
188
196
|
return renderElement(vnode);
|
|
189
197
|
}
|
|
190
198
|
async function renderChildren(children) {
|
|
191
|
-
|
|
199
|
+
let html = "";
|
|
200
|
+
for (const child of children) html += await renderNode(child);
|
|
201
|
+
return html;
|
|
192
202
|
}
|
|
193
203
|
async function renderComponent(vnode) {
|
|
194
204
|
const { vnode: output } = runWithHooks(vnode.type, mergeChildrenIntoProps(vnode));
|
|
@@ -203,8 +213,9 @@ async function renderComponent(vnode) {
|
|
|
203
213
|
async function renderElement(vnode) {
|
|
204
214
|
const tag = vnode.type;
|
|
205
215
|
let html = `<${tag}`;
|
|
206
|
-
|
|
207
|
-
|
|
216
|
+
const props = vnode.props;
|
|
217
|
+
for (const key in props) {
|
|
218
|
+
const attr = renderProp(key, props[key]);
|
|
208
219
|
if (attr) html += ` ${attr}`;
|
|
209
220
|
}
|
|
210
221
|
if (isVoidElement(tag)) {
|
|
@@ -297,7 +308,9 @@ const ESCAPE_MAP = {
|
|
|
297
308
|
"\"": """,
|
|
298
309
|
"'": "'"
|
|
299
310
|
};
|
|
311
|
+
const NEEDS_ESCAPE_RE = /[&<>"']/;
|
|
300
312
|
function escapeHtml(str) {
|
|
313
|
+
if (!NEEDS_ESCAPE_RE.test(str)) return str;
|
|
301
314
|
return str.replace(/[&<>"']/g, (c) => ESCAPE_MAP[c] ?? c);
|
|
302
315
|
}
|
|
303
316
|
/**
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/runtime-server — SSR/SSG renderer for Pyreon.\n *\n * Walks a VNode tree and produces HTML strings.\n * Signal accessors (reactive getters `() => value`) are called synchronously\n * to snapshot their current value — no effects are set up on the server.\n *\n * Async components (`async function Component()`) are fully supported:\n * renderToString will await them before continuing the tree walk.\n *\n * API:\n * renderToString(vnode) → Promise<string>\n * renderToStream(vnode) → ReadableStream<string>\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { ComponentFn, ForProps, VNode, VNodeChild } from \"@pyreon/core\"\nimport { ForSymbol, Fragment, runWithHooks, Suspense, setContextStackProvider } from \"@pyreon/core\"\n\n// ─── Streaming Suspense context ───────────────────────────────────────────────\n// Tracks in-flight async Suspense boundary resolutions within a single stream.\n\ninterface StreamCtx {\n pending: Promise<void>[]\n nextId: () => number\n mainEnqueue: (s: string) => void\n}\n\nconst _streamCtxAls = new AsyncLocalStorage<StreamCtx>()\n\n// ─── Concurrent SSR context isolation ────────────────────────────────────────\n// Each renderToString call runs in its own ALS store (a fresh empty stack[]).\n// Concurrent requests never share context frames.\n\nconst _contextAls = new AsyncLocalStorage<Map<symbol, unknown>[]>()\nconst _fallbackStack: Map<symbol, unknown>[] = []\n\nsetContextStackProvider(() => _contextAls.getStore() ?? _fallbackStack)\n\n// ─── Store isolation (optional) ───────────────────────────────────────────────\n// A second ALS isolates store registries between concurrent requests.\n// Activated only when the user calls configureStoreIsolation().\n\nconst _storeAls = new AsyncLocalStorage<Map<string, unknown>>()\nlet _storeIsolationActive = false\n\n/**\n * Wire up per-request store isolation.\n * Call once at server startup, passing a `setStoreRegistryProvider` function.\n *\n * @example\n * import { configureStoreIsolation } from \"@pyreon/runtime-server\"\n * configureStoreIsolation(setStoreRegistryProvider)\n */\nexport function configureStoreIsolation(\n setStoreRegistryProvider: (fn: () => Map<string, unknown>) => void,\n): void {\n setStoreRegistryProvider(() => _storeAls.getStore() ?? new Map())\n _storeIsolationActive = true\n}\n\n/** Wrap a function call in a fresh store registry (no-op if isolation not configured). */\nfunction withStoreContext<T>(fn: () => T): T {\n if (!_storeIsolationActive) return fn()\n return _storeAls.run(new Map(), fn)\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/** Render a VNode tree to an HTML string. Supports async component functions. */\nexport async function renderToString(root: VNode | null): Promise<string> {\n if (root === null) return \"\"\n // Each call gets a fresh isolated context stack and (optionally) store registry\n return withStoreContext(() => _contextAls.run([], () => renderNode(root)))\n}\n\n/**\n * Run an async function with a fresh, isolated context stack and store registry.\n * Useful when you need to call Pyreon APIs (e.g. useHead, prefetchLoaderData)\n * outside of renderToString but still want per-request isolation.\n */\nexport function runWithRequestContext<T>(fn: () => Promise<T>): Promise<T> {\n return withStoreContext(() => _contextAls.run([], fn))\n}\n\n/**\n * Render a VNode tree to a Web-standard ReadableStream of HTML chunks.\n *\n * True progressive streaming: HTML is flushed to the client as soon as each\n * node is ready. Synchronous subtrees are enqueued immediately; async component\n * boundaries are awaited in-order and their output is enqueued as it resolves.\n *\n * Suspense boundaries are streamed out-of-order: the fallback is emitted\n * immediately, and the resolved children are sent as a `<template>` + inline\n * swap script once ready — without blocking the rest of the page.\n *\n * Each renderToStream call gets its own isolated ALS context stack.\n */\nexport function renderToStream(root: VNode | null): ReadableStream<string> {\n return new ReadableStream<string>({\n start(controller) {\n const enqueue = (chunk: string) => controller.enqueue(chunk)\n let bid = 0\n const ctx: StreamCtx = {\n pending: [],\n nextId: () => bid++,\n mainEnqueue: enqueue,\n }\n return withStoreContext(() =>\n _contextAls.run([], () =>\n _streamCtxAls\n .run(ctx, async () => {\n await streamNode(root, enqueue)\n // Drain all pending Suspense resolutions (may spawn nested ones)\n while (ctx.pending.length > 0) {\n await Promise.all(ctx.pending.splice(0))\n }\n controller.close()\n })\n .catch((err) => controller.error(err)),\n ),\n )\n },\n })\n}\n\n// ─── Streaming renderer ───────────────────────────────────────────────────────\n\nasync function streamVNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n if (vnode.type === Fragment) {\n for (const child of vnode.children) await streamNode(child, enqueue)\n return\n }\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, children } = vnode.props as unknown as ForProps<unknown>\n enqueue(\"<!--pyreon-for-->\")\n for (const item of each()) await streamNode(children(item) as VNodeChild, enqueue)\n enqueue(\"<!--/pyreon-for-->\")\n return\n }\n\n if (typeof vnode.type === \"function\") {\n await streamComponentNode(vnode, enqueue)\n return\n }\n\n await streamElementNode(vnode, enqueue)\n}\n\nasync function streamComponentNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n if (vnode.type === Suspense) {\n await streamSuspenseBoundary(vnode, enqueue)\n return\n }\n const { vnode: output } = runWithHooks(vnode.type as ComponentFn, mergeChildrenIntoProps(vnode))\n const resolved = output instanceof Promise ? await output : output\n if (resolved !== null) await streamNode(resolved, enqueue)\n}\n\nasync function streamElementNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n const tag = vnode.type as string\n let open = `<${tag}`\n for (const [key, value] of Object.entries(vnode.props)) {\n const attr = renderProp(key, value)\n if (attr) open += ` ${attr}`\n }\n if (isVoidElement(tag)) {\n enqueue(`${open} />`)\n return\n }\n enqueue(`${open}>`)\n for (const child of vnode.children) await streamNode(child, enqueue)\n enqueue(`</${tag}>`)\n}\n\nasync function streamNode(\n node: VNodeChild | null | (() => VNodeChild),\n enqueue: (s: string) => void,\n): Promise<void> {\n if (typeof node === \"function\") {\n return streamNode((node as () => VNodeChild)(), enqueue)\n }\n if (node == null || node === false) return\n if (typeof node === \"string\") {\n enqueue(escapeHtml(node))\n return\n }\n if (typeof node === \"number\" || typeof node === \"boolean\") {\n enqueue(String(node))\n return\n }\n if (Array.isArray(node)) {\n for (const child of node) await streamNode(child, enqueue)\n return\n }\n\n await streamVNode(node as VNode, enqueue)\n}\n\n// Inline swap helper emitted once per stream, before the first <template>\nconst SUSPENSE_SWAP_FN =\n \"<script>function __NS(s,t){var e=document.getElementById(s),l=document.getElementById(t);\" +\n \"if(e&&l){e.replaceWith(l.content.cloneNode(!0));l.remove()}}</script>\"\n\n/**\n * Stream a Suspense boundary: emit fallback immediately, then resolve children\n * asynchronously and emit them as a `<template>` + client-side swap.\n *\n * The actual children HTML is buffered until fully resolved, then emitted to the\n * main stream enqueue so it always arrives after the fallback placeholder.\n */\nasync function streamSuspenseBoundary(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n const ctx = _streamCtxAls.getStore()\n const { fallback, children } = vnode.props as { fallback: VNodeChild; children?: VNodeChild }\n\n // No streaming context (e.g. called from renderToString) — render children inline\n if (!ctx) {\n const { vnode: output } = runWithHooks(Suspense as ComponentFn, vnode.props)\n if (output !== null) await streamNode(output, enqueue)\n return\n }\n\n const id = ctx.nextId()\n const { mainEnqueue } = ctx\n\n // Emit the swap helper function once (before first use)\n if (id === 0) mainEnqueue(SUSPENSE_SWAP_FN)\n\n // Stream the fallback synchronously (no await on children)\n mainEnqueue(`<div id=\"pyreon-s-${id}\">`)\n await streamNode(fallback ?? null, enqueue)\n mainEnqueue(\"</div>\")\n\n // Capture the context store for the async resolution so it inherits context\n const ctxStore = _contextAls.getStore() ?? []\n\n // Queue async resolution — runs in parallel, emits to main stream when done\n // Errors are caught per-boundary so one failing Suspense doesn't abort the stream.\n ctx.pending.push(\n _contextAls.run(ctxStore, async () => {\n try {\n const buf: string[] = []\n await streamNode(children ?? null, (s) => buf.push(s))\n mainEnqueue(`<template id=\"pyreon-t-${id}\">${buf.join(\"\")}</template>`)\n mainEnqueue(`<script>__NS(\"pyreon-s-${id}\",\"pyreon-t-${id}\")</script>`)\n } catch (_err) {\n // Fallback stays visible — no swap script emitted\n }\n }),\n )\n}\n\n// ─── Core renderer ───────────────────────────────────────────────────────────\n\nasync function renderNode(node: VNodeChild | (() => VNodeChild)): Promise<string> {\n // Reactive accessor — call it synchronously (snapshot)\n if (typeof node === \"function\") {\n return renderNode((node as () => VNodeChild)())\n }\n\n if (node == null || node === false) return \"\"\n\n if (typeof node === \"string\") return escapeHtml(node)\n if (typeof node === \"number\" || typeof node === \"boolean\") return String(node)\n\n if (Array.isArray(node)) {\n const parts = await Promise.all(node.map((n) => renderNode(n)))\n return parts.join(\"\")\n }\n\n const vnode = node as VNode\n\n if (vnode.type === Fragment) {\n return renderChildren(vnode.children)\n }\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, children } = vnode.props as unknown as ForProps<unknown>\n const parts = await Promise.all(each().map((item) => renderNode(children(item) as VNodeChild)))\n // Hydration markers so the client can claim existing For-rendered children\n return `<!--pyreon-for-->${parts.join(\"\")}<!--/pyreon-for-->`\n }\n\n if (typeof vnode.type === \"function\") {\n return renderComponent(vnode as VNode & { type: ComponentFn })\n }\n\n return renderElement(vnode)\n}\n\nasync function renderChildren(children: VNodeChild[]): Promise<string> {\n const parts = await Promise.all(children.map((c) => renderNode(c)))\n return parts.join(\"\")\n}\n\nasync function renderComponent(vnode: VNode & { type: ComponentFn }): Promise<string> {\n const { vnode: output } = runWithHooks(vnode.type, mergeChildrenIntoProps(vnode))\n\n // Async component function (async function Component()) — await the promise\n if (output instanceof Promise) {\n const resolved = await output\n if (resolved === null) return \"\"\n return renderNode(resolved)\n }\n\n if (output === null) return \"\"\n return renderNode(output)\n}\n\nasync function renderElement(vnode: VNode): Promise<string> {\n const tag = vnode.type as string\n let html = `<${tag}`\n\n for (const [key, value] of Object.entries(vnode.props)) {\n const attr = renderProp(key, value)\n if (attr) html += ` ${attr}`\n }\n\n if (isVoidElement(tag)) {\n html += \" />\"\n return html\n }\n\n html += \">\"\n\n for (const child of vnode.children) {\n html += await renderNode(child)\n }\n\n html += `</${tag}>`\n return html\n}\n\nconst SSR_URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"poster\", \"cite\", \"data\"])\nconst SSR_UNSAFE_URL_RE = /^\\s*(?:javascript|data):/i\n\nfunction renderPropSkipped(key: string): boolean {\n if (key === \"key\" || key === \"ref\" || key === \"n-show\") return true\n if (key.startsWith(\"n-\")) return true\n if (/^on[A-Z]/.test(key)) return true\n return false\n}\n\nfunction renderPropValue(key: string, value: unknown): string | null {\n if (value === null || value === undefined || value === false) return null\n if (value === true) return escapeHtml(toAttrName(key))\n\n if (key === \"class\") {\n const cls = normalizeClass(value)\n return cls ? `class=\"${escapeHtml(cls)}\"` : null\n }\n\n if (key === \"style\") {\n const style = normalizeStyle(value)\n return style ? `style=\"${escapeHtml(style)}\"` : null\n }\n\n return `${escapeHtml(toAttrName(key))}=\"${escapeHtml(String(value))}\"`\n}\n\nfunction renderProp(key: string, value: unknown): string | null {\n if (renderPropSkipped(key)) return null\n\n if (typeof value === \"function\") {\n return renderProp(key, (value as () => unknown)())\n }\n\n if (SSR_URL_ATTRS.has(key) && typeof value === \"string\" && SSR_UNSAFE_URL_RE.test(value)) {\n return null\n }\n\n return renderPropValue(key, value)\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n])\n\nfunction isVoidElement(tag: string): boolean {\n return VOID_ELEMENTS.has(tag.toLowerCase())\n}\n\n/** camelCase prop → kebab-case HTML attribute (e.g. className → class, htmlFor → for) */\nfunction toAttrName(key: string): string {\n if (key === \"className\") return \"class\"\n if (key === \"htmlFor\") return \"for\"\n return key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)\n}\n\nfunction normalizeClass(value: unknown): string {\n if (typeof value === \"string\") return value\n if (Array.isArray(value)) return value.filter(Boolean).join(\" \")\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v)\n .map(([k]) => k)\n .join(\" \")\n }\n return \"\"\n}\n\nfunction normalizeStyle(value: unknown): string {\n if (typeof value === \"string\") return value\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value as Record<string, unknown>)\n .map(([k, v]) => `${toKebab(k)}: ${v}`)\n .join(\"; \")\n }\n return \"\"\n}\n\nfunction toKebab(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)\n}\n\nconst ESCAPE_MAP: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n}\n\nfunction escapeHtml(str: string): string {\n return str.replace(/[&<>\"']/g, (c) => ESCAPE_MAP[c] ?? c)\n}\n\n/**\n * Merge vnode.children into props.children for component rendering.\n * Matches the behavior of mount.ts and hydrate.ts so components can\n * access children passed via h(Comp, props, child1, child2).\n */\nfunction mergeChildrenIntoProps(vnode: VNode): Record<string, unknown> {\n if (\n vnode.children.length > 0 &&\n (vnode.props as Record<string, unknown>).children === undefined\n ) {\n return {\n ...vnode.props,\n children: vnode.children.length === 1 ? vnode.children[0] : vnode.children,\n }\n }\n return vnode.props as Record<string, unknown>\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pyreon/runtime-server — SSR/SSG renderer for Pyreon.\n *\n * Walks a VNode tree and produces HTML strings.\n * Signal accessors (reactive getters `() => value`) are called synchronously\n * to snapshot their current value — no effects are set up on the server.\n *\n * Async components (`async function Component()`) are fully supported:\n * renderToString will await them before continuing the tree walk.\n *\n * API:\n * renderToString(vnode) → Promise<string>\n * renderToStream(vnode) → ReadableStream<string>\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\"\nimport type { ComponentFn, ForProps, VNode, VNodeChild } from \"@pyreon/core\"\nimport { ForSymbol, Fragment, runWithHooks, Suspense, setContextStackProvider } from \"@pyreon/core\"\n\n// ─── Streaming Suspense context ───────────────────────────────────────────────\n// Tracks in-flight async Suspense boundary resolutions within a single stream.\n\ninterface StreamCtx {\n pending: Promise<void>[]\n nextId: () => number\n mainEnqueue: (s: string) => void\n}\n\nconst _streamCtxAls = new AsyncLocalStorage<StreamCtx>()\n\n// ─── Concurrent SSR context isolation ────────────────────────────────────────\n// Each renderToString call runs in its own ALS store (a fresh empty stack[]).\n// Concurrent requests never share context frames.\n\nconst _contextAls = new AsyncLocalStorage<Map<symbol, unknown>[]>()\nconst _fallbackStack: Map<symbol, unknown>[] = []\n\nsetContextStackProvider(() => _contextAls.getStore() ?? _fallbackStack)\n\n// ─── Store isolation (optional) ───────────────────────────────────────────────\n// A second ALS isolates store registries between concurrent requests.\n// Activated only when the user calls configureStoreIsolation().\n\nconst _storeAls = new AsyncLocalStorage<Map<string, unknown>>()\nlet _storeIsolationActive = false\n\n/**\n * Wire up per-request store isolation.\n * Call once at server startup, passing a `setStoreRegistryProvider` function.\n *\n * @example\n * import { configureStoreIsolation } from \"@pyreon/runtime-server\"\n * configureStoreIsolation(setStoreRegistryProvider)\n */\nexport function configureStoreIsolation(\n setStoreRegistryProvider: (fn: () => Map<string, unknown>) => void,\n): void {\n setStoreRegistryProvider(() => _storeAls.getStore() ?? new Map())\n _storeIsolationActive = true\n}\n\n/** Wrap a function call in a fresh store registry (no-op if isolation not configured). */\nfunction withStoreContext<T>(fn: () => T): T {\n if (!_storeIsolationActive) return fn()\n return _storeAls.run(new Map(), fn)\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/** Render a VNode tree to an HTML string. Supports async component functions. */\nexport async function renderToString(root: VNode | null): Promise<string> {\n if (root === null) return \"\"\n // Each call gets a fresh isolated context stack and (optionally) store registry\n return withStoreContext(() => _contextAls.run([], () => renderNode(root)))\n}\n\n/**\n * Run an async function with a fresh, isolated context stack and store registry.\n * Useful when you need to call Pyreon APIs (e.g. useHead, prefetchLoaderData)\n * outside of renderToString but still want per-request isolation.\n */\nexport function runWithRequestContext<T>(fn: () => Promise<T>): Promise<T> {\n return withStoreContext(() => _contextAls.run([], fn))\n}\n\n/**\n * Render a VNode tree to a Web-standard ReadableStream of HTML chunks.\n *\n * True progressive streaming: HTML is flushed to the client as soon as each\n * node is ready. Synchronous subtrees are enqueued immediately; async component\n * boundaries are awaited in-order and their output is enqueued as it resolves.\n *\n * Suspense boundaries are streamed out-of-order: the fallback is emitted\n * immediately, and the resolved children are sent as a `<template>` + inline\n * swap script once ready — without blocking the rest of the page.\n *\n * Each renderToStream call gets its own isolated ALS context stack.\n */\nexport function renderToStream(root: VNode | null): ReadableStream<string> {\n return new ReadableStream<string>({\n start(controller) {\n const enqueue = (chunk: string) => controller.enqueue(chunk)\n let bid = 0\n const ctx: StreamCtx = {\n pending: [],\n nextId: () => bid++,\n mainEnqueue: enqueue,\n }\n return withStoreContext(() =>\n _contextAls.run([], () =>\n _streamCtxAls\n .run(ctx, async () => {\n await streamNode(root, enqueue)\n // Drain all pending Suspense resolutions (may spawn nested ones)\n while (ctx.pending.length > 0) {\n await Promise.all(ctx.pending.splice(0))\n }\n controller.close()\n })\n .catch((err) => controller.error(err)),\n ),\n )\n },\n })\n}\n\n// ─── Streaming renderer ───────────────────────────────────────────────────────\n\nasync function streamVNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n if (vnode.type === Fragment) {\n for (const child of vnode.children) await streamNode(child, enqueue)\n return\n }\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, children } = vnode.props as unknown as ForProps<unknown>\n enqueue(\"<!--pyreon-for-->\")\n for (const item of each()) await streamNode(children(item) as VNodeChild, enqueue)\n enqueue(\"<!--/pyreon-for-->\")\n return\n }\n\n if (typeof vnode.type === \"function\") {\n await streamComponentNode(vnode, enqueue)\n return\n }\n\n await streamElementNode(vnode, enqueue)\n}\n\nasync function streamComponentNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n if (vnode.type === Suspense) {\n await streamSuspenseBoundary(vnode, enqueue)\n return\n }\n const { vnode: output } = runWithHooks(vnode.type as ComponentFn, mergeChildrenIntoProps(vnode))\n const resolved = output instanceof Promise ? await output : output\n if (resolved !== null) await streamNode(resolved, enqueue)\n}\n\nasync function streamElementNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n const tag = vnode.type as string\n let open = `<${tag}`\n const props = vnode.props as Record<string, unknown>\n for (const key in props) {\n const attr = renderProp(key, props[key])\n if (attr) open += ` ${attr}`\n }\n if (isVoidElement(tag)) {\n enqueue(`${open} />`)\n return\n }\n enqueue(`${open}>`)\n for (const child of vnode.children) await streamNode(child, enqueue)\n enqueue(`</${tag}>`)\n}\n\nasync function streamNode(\n node: VNodeChild | null | (() => VNodeChild),\n enqueue: (s: string) => void,\n): Promise<void> {\n if (typeof node === \"function\") {\n return streamNode((node as () => VNodeChild)(), enqueue)\n }\n if (node == null || node === false) return\n if (typeof node === \"string\") {\n enqueue(escapeHtml(node))\n return\n }\n if (typeof node === \"number\" || typeof node === \"boolean\") {\n enqueue(String(node))\n return\n }\n if (Array.isArray(node)) {\n for (const child of node) await streamNode(child, enqueue)\n return\n }\n\n await streamVNode(node as VNode, enqueue)\n}\n\n// Inline swap helper emitted once per stream, before the first <template>\nconst SUSPENSE_SWAP_FN =\n \"<script>function __NS(s,t){var e=document.getElementById(s),l=document.getElementById(t);\" +\n \"if(e&&l){e.replaceWith(l.content.cloneNode(!0));l.remove()}}</script>\"\n\n/**\n * Stream a Suspense boundary: emit fallback immediately, then resolve children\n * asynchronously and emit them as a `<template>` + client-side swap.\n *\n * The actual children HTML is buffered until fully resolved, then emitted to the\n * main stream enqueue so it always arrives after the fallback placeholder.\n */\nasync function streamSuspenseBoundary(vnode: VNode, enqueue: (s: string) => void): Promise<void> {\n const ctx = _streamCtxAls.getStore()\n const { fallback, children } = vnode.props as { fallback: VNodeChild; children?: VNodeChild }\n\n // No streaming context (e.g. called from renderToString) — render children inline\n if (!ctx) {\n const { vnode: output } = runWithHooks(Suspense as ComponentFn, vnode.props)\n if (output !== null) await streamNode(output, enqueue)\n return\n }\n\n const id = ctx.nextId()\n const { mainEnqueue } = ctx\n\n // Emit the swap helper function once (before first use)\n if (id === 0) mainEnqueue(SUSPENSE_SWAP_FN)\n\n // Stream the fallback synchronously (no await on children)\n mainEnqueue(`<div id=\"pyreon-s-${id}\">`)\n await streamNode(fallback ?? null, enqueue)\n mainEnqueue(\"</div>\")\n\n // Capture the context store for the async resolution so it inherits context\n const ctxStore = _contextAls.getStore() ?? []\n\n // Queue async resolution — runs in parallel, emits to main stream when done\n // Errors are caught per-boundary so one failing Suspense doesn't abort the stream.\n ctx.pending.push(\n _contextAls.run(ctxStore, async () => {\n try {\n const buf: string[] = []\n await streamNode(children ?? null, (s) => buf.push(s))\n mainEnqueue(`<template id=\"pyreon-t-${id}\">${buf.join(\"\")}</template>`)\n mainEnqueue(`<script>__NS(\"pyreon-s-${id}\",\"pyreon-t-${id}\")</script>`)\n } catch (_err) {\n // Fallback stays visible — no swap script emitted\n }\n }),\n )\n}\n\n// ─── Core renderer ───────────────────────────────────────────────────────────\n\nasync function renderNode(node: VNodeChild | (() => VNodeChild)): Promise<string> {\n // Reactive accessor — call it synchronously (snapshot)\n if (typeof node === \"function\") {\n return renderNode((node as () => VNodeChild)())\n }\n\n if (node == null || node === false) return \"\"\n\n if (typeof node === \"string\") return escapeHtml(node)\n if (typeof node === \"number\" || typeof node === \"boolean\") return String(node)\n\n if (Array.isArray(node)) {\n let html = \"\"\n for (const child of node) html += await renderNode(child)\n return html\n }\n\n const vnode = node as VNode\n\n if (vnode.type === Fragment) {\n return renderChildren(vnode.children)\n }\n\n if (vnode.type === (ForSymbol as unknown as string)) {\n const { each, children } = vnode.props as unknown as ForProps<unknown>\n let forHtml = \"<!--pyreon-for-->\"\n for (const item of each()) forHtml += await renderNode(children(item) as VNodeChild)\n forHtml += \"<!--/pyreon-for-->\"\n return forHtml\n }\n\n if (typeof vnode.type === \"function\") {\n return renderComponent(vnode as VNode & { type: ComponentFn })\n }\n\n return renderElement(vnode)\n}\n\nasync function renderChildren(children: VNodeChild[]): Promise<string> {\n let html = \"\"\n for (const child of children) html += await renderNode(child)\n return html\n}\n\nasync function renderComponent(vnode: VNode & { type: ComponentFn }): Promise<string> {\n const { vnode: output } = runWithHooks(vnode.type, mergeChildrenIntoProps(vnode))\n\n // Async component function (async function Component()) — await the promise\n if (output instanceof Promise) {\n const resolved = await output\n if (resolved === null) return \"\"\n return renderNode(resolved)\n }\n\n if (output === null) return \"\"\n return renderNode(output)\n}\n\nasync function renderElement(vnode: VNode): Promise<string> {\n const tag = vnode.type as string\n let html = `<${tag}`\n\n const props = vnode.props as Record<string, unknown>\n for (const key in props) {\n const attr = renderProp(key, props[key])\n if (attr) html += ` ${attr}`\n }\n\n if (isVoidElement(tag)) {\n html += \" />\"\n return html\n }\n\n html += \">\"\n\n for (const child of vnode.children) {\n html += await renderNode(child)\n }\n\n html += `</${tag}>`\n return html\n}\n\nconst SSR_URL_ATTRS = new Set([\"href\", \"src\", \"action\", \"formaction\", \"poster\", \"cite\", \"data\"])\nconst SSR_UNSAFE_URL_RE = /^\\s*(?:javascript|data):/i\n\nfunction renderPropSkipped(key: string): boolean {\n if (key === \"key\" || key === \"ref\" || key === \"n-show\") return true\n if (key.startsWith(\"n-\")) return true\n if (/^on[A-Z]/.test(key)) return true\n return false\n}\n\nfunction renderPropValue(key: string, value: unknown): string | null {\n if (value === null || value === undefined || value === false) return null\n if (value === true) return escapeHtml(toAttrName(key))\n\n if (key === \"class\") {\n const cls = normalizeClass(value)\n return cls ? `class=\"${escapeHtml(cls)}\"` : null\n }\n\n if (key === \"style\") {\n const style = normalizeStyle(value)\n return style ? `style=\"${escapeHtml(style)}\"` : null\n }\n\n return `${escapeHtml(toAttrName(key))}=\"${escapeHtml(String(value))}\"`\n}\n\nfunction renderProp(key: string, value: unknown): string | null {\n if (renderPropSkipped(key)) return null\n\n if (typeof value === \"function\") {\n return renderProp(key, (value as () => unknown)())\n }\n\n if (SSR_URL_ATTRS.has(key) && typeof value === \"string\" && SSR_UNSAFE_URL_RE.test(value)) {\n return null\n }\n\n return renderPropValue(key, value)\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nconst VOID_ELEMENTS = new Set([\n \"area\",\n \"base\",\n \"br\",\n \"col\",\n \"embed\",\n \"hr\",\n \"img\",\n \"input\",\n \"link\",\n \"meta\",\n \"param\",\n \"source\",\n \"track\",\n \"wbr\",\n])\n\nfunction isVoidElement(tag: string): boolean {\n return VOID_ELEMENTS.has(tag.toLowerCase())\n}\n\n/** camelCase prop → kebab-case HTML attribute (e.g. className → class, htmlFor → for) */\nfunction toAttrName(key: string): string {\n if (key === \"className\") return \"class\"\n if (key === \"htmlFor\") return \"for\"\n return key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)\n}\n\nfunction normalizeClass(value: unknown): string {\n if (typeof value === \"string\") return value\n if (Array.isArray(value)) return value.filter(Boolean).join(\" \")\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v)\n .map(([k]) => k)\n .join(\" \")\n }\n return \"\"\n}\n\nfunction normalizeStyle(value: unknown): string {\n if (typeof value === \"string\") return value\n if (typeof value === \"object\" && value !== null) {\n return Object.entries(value as Record<string, unknown>)\n .map(([k, v]) => `${toKebab(k)}: ${v}`)\n .join(\"; \")\n }\n return \"\"\n}\n\nfunction toKebab(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)\n}\n\nconst ESCAPE_MAP: Record<string, string> = {\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n '\"': \""\",\n \"'\": \"'\",\n}\n\n// Fast test — most strings in SSR have no special chars (tag names, class names, etc.)\nconst NEEDS_ESCAPE_RE = /[&<>\"']/\n\nfunction escapeHtml(str: string): string {\n if (!NEEDS_ESCAPE_RE.test(str)) return str\n return str.replace(/[&<>\"']/g, (c) => ESCAPE_MAP[c] ?? c)\n}\n\n/**\n * Merge vnode.children into props.children for component rendering.\n * Matches the behavior of mount.ts and hydrate.ts so components can\n * access children passed via h(Comp, props, child1, child2).\n */\nfunction mergeChildrenIntoProps(vnode: VNode): Record<string, unknown> {\n if (\n vnode.children.length > 0 &&\n (vnode.props as Record<string, unknown>).children === undefined\n ) {\n return {\n ...vnode.props,\n children: vnode.children.length === 1 ? vnode.children[0] : vnode.children,\n }\n }\n return vnode.props as Record<string, unknown>\n}\n"],"mappings":"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"}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -113,8 +113,9 @@ async function streamComponentNode(vnode, enqueue) {
|
|
|
113
113
|
async function streamElementNode(vnode, enqueue) {
|
|
114
114
|
const tag = vnode.type;
|
|
115
115
|
let open = `<${tag}`;
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
const props = vnode.props;
|
|
117
|
+
for (const key in props) {
|
|
118
|
+
const attr = renderProp(key, props[key]);
|
|
118
119
|
if (attr) open += ` ${attr}`;
|
|
119
120
|
}
|
|
120
121
|
if (isVoidElement(tag)) {
|
|
@@ -185,7 +186,11 @@ async function renderNode(node) {
|
|
|
185
186
|
if (node == null || node === false) return "";
|
|
186
187
|
if (typeof node === "string") return escapeHtml(node);
|
|
187
188
|
if (typeof node === "number" || typeof node === "boolean") return String(node);
|
|
188
|
-
if (Array.isArray(node))
|
|
189
|
+
if (Array.isArray(node)) {
|
|
190
|
+
let html = "";
|
|
191
|
+
for (const child of node) html += await renderNode(child);
|
|
192
|
+
return html;
|
|
193
|
+
}
|
|
189
194
|
const vnode = node;
|
|
190
195
|
if (vnode.type === Fragment) return renderChildren(vnode.children);
|
|
191
196
|
if (vnode.type === ForSymbol) {
|
|
@@ -193,13 +198,18 @@ async function renderNode(node) {
|
|
|
193
198
|
each,
|
|
194
199
|
children
|
|
195
200
|
} = vnode.props;
|
|
196
|
-
|
|
201
|
+
let forHtml = "<!--pyreon-for-->";
|
|
202
|
+
for (const item of each()) forHtml += await renderNode(children(item));
|
|
203
|
+
forHtml += "<!--/pyreon-for-->";
|
|
204
|
+
return forHtml;
|
|
197
205
|
}
|
|
198
206
|
if (typeof vnode.type === "function") return renderComponent(vnode);
|
|
199
207
|
return renderElement(vnode);
|
|
200
208
|
}
|
|
201
209
|
async function renderChildren(children) {
|
|
202
|
-
|
|
210
|
+
let html = "";
|
|
211
|
+
for (const child of children) html += await renderNode(child);
|
|
212
|
+
return html;
|
|
203
213
|
}
|
|
204
214
|
async function renderComponent(vnode) {
|
|
205
215
|
const {
|
|
@@ -216,8 +226,9 @@ async function renderComponent(vnode) {
|
|
|
216
226
|
async function renderElement(vnode) {
|
|
217
227
|
const tag = vnode.type;
|
|
218
228
|
let html = `<${tag}`;
|
|
219
|
-
|
|
220
|
-
|
|
229
|
+
const props = vnode.props;
|
|
230
|
+
for (const key in props) {
|
|
231
|
+
const attr = renderProp(key, props[key]);
|
|
221
232
|
if (attr) html += ` ${attr}`;
|
|
222
233
|
}
|
|
223
234
|
if (isVoidElement(tag)) {
|
|
@@ -278,6 +289,7 @@ function toKebab(str) {
|
|
|
278
289
|
return str.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
|
279
290
|
}
|
|
280
291
|
function escapeHtml(str) {
|
|
292
|
+
if (!NEEDS_ESCAPE_RE.test(str)) return str;
|
|
281
293
|
return str.replace(/[&<>"']/g, c => ESCAPE_MAP[c] ?? c);
|
|
282
294
|
}
|
|
283
295
|
/**
|
package/lib/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/runtime-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "SSR/SSG renderer for Pyreon — streaming HTML + static generation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"prepublishOnly": "bun run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@pyreon/core": "^0.
|
|
43
|
-
"@pyreon/reactivity": "^0.
|
|
42
|
+
"@pyreon/core": "^0.3.0",
|
|
43
|
+
"@pyreon/reactivity": "^0.3.0"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
package/src/index.ts
CHANGED
|
@@ -161,8 +161,9 @@ async function streamComponentNode(vnode: VNode, enqueue: (s: string) => void):
|
|
|
161
161
|
async function streamElementNode(vnode: VNode, enqueue: (s: string) => void): Promise<void> {
|
|
162
162
|
const tag = vnode.type as string
|
|
163
163
|
let open = `<${tag}`
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
const props = vnode.props as Record<string, unknown>
|
|
165
|
+
for (const key in props) {
|
|
166
|
+
const attr = renderProp(key, props[key])
|
|
166
167
|
if (attr) open += ` ${attr}`
|
|
167
168
|
}
|
|
168
169
|
if (isVoidElement(tag)) {
|
|
@@ -265,8 +266,9 @@ async function renderNode(node: VNodeChild | (() => VNodeChild)): Promise<string
|
|
|
265
266
|
if (typeof node === "number" || typeof node === "boolean") return String(node)
|
|
266
267
|
|
|
267
268
|
if (Array.isArray(node)) {
|
|
268
|
-
|
|
269
|
-
|
|
269
|
+
let html = ""
|
|
270
|
+
for (const child of node) html += await renderNode(child)
|
|
271
|
+
return html
|
|
270
272
|
}
|
|
271
273
|
|
|
272
274
|
const vnode = node as VNode
|
|
@@ -277,9 +279,10 @@ async function renderNode(node: VNodeChild | (() => VNodeChild)): Promise<string
|
|
|
277
279
|
|
|
278
280
|
if (vnode.type === (ForSymbol as unknown as string)) {
|
|
279
281
|
const { each, children } = vnode.props as unknown as ForProps<unknown>
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
282
|
+
let forHtml = "<!--pyreon-for-->"
|
|
283
|
+
for (const item of each()) forHtml += await renderNode(children(item) as VNodeChild)
|
|
284
|
+
forHtml += "<!--/pyreon-for-->"
|
|
285
|
+
return forHtml
|
|
283
286
|
}
|
|
284
287
|
|
|
285
288
|
if (typeof vnode.type === "function") {
|
|
@@ -290,8 +293,9 @@ async function renderNode(node: VNodeChild | (() => VNodeChild)): Promise<string
|
|
|
290
293
|
}
|
|
291
294
|
|
|
292
295
|
async function renderChildren(children: VNodeChild[]): Promise<string> {
|
|
293
|
-
|
|
294
|
-
|
|
296
|
+
let html = ""
|
|
297
|
+
for (const child of children) html += await renderNode(child)
|
|
298
|
+
return html
|
|
295
299
|
}
|
|
296
300
|
|
|
297
301
|
async function renderComponent(vnode: VNode & { type: ComponentFn }): Promise<string> {
|
|
@@ -312,8 +316,9 @@ async function renderElement(vnode: VNode): Promise<string> {
|
|
|
312
316
|
const tag = vnode.type as string
|
|
313
317
|
let html = `<${tag}`
|
|
314
318
|
|
|
315
|
-
|
|
316
|
-
|
|
319
|
+
const props = vnode.props as Record<string, unknown>
|
|
320
|
+
for (const key in props) {
|
|
321
|
+
const attr = renderProp(key, props[key])
|
|
317
322
|
if (attr) html += ` ${attr}`
|
|
318
323
|
}
|
|
319
324
|
|
|
@@ -437,7 +442,11 @@ const ESCAPE_MAP: Record<string, string> = {
|
|
|
437
442
|
"'": "'",
|
|
438
443
|
}
|
|
439
444
|
|
|
445
|
+
// Fast test — most strings in SSR have no special chars (tag names, class names, etc.)
|
|
446
|
+
const NEEDS_ESCAPE_RE = /[&<>"']/
|
|
447
|
+
|
|
440
448
|
function escapeHtml(str: string): string {
|
|
449
|
+
if (!NEEDS_ESCAPE_RE.test(str)) return str
|
|
441
450
|
return str.replace(/[&<>"']/g, (c) => ESCAPE_MAP[c] ?? c)
|
|
442
451
|
}
|
|
443
452
|
|