@elurjs/core 3.6.2 → 3.7.0-beta.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/dist/lib/async.cjs +1 -1
- package/dist/lib/async.js +1 -1
- package/dist/lib/component.cjs +1 -2
- package/dist/lib/component.js +2 -66
- package/dist/lib/context.cjs +1 -1
- package/dist/lib/context.js +35 -23
- package/dist/lib/devtools.cjs +1 -1
- package/dist/lib/devtools.js +1 -1
- package/dist/lib/elur/async.cjs +1 -1
- package/dist/lib/elur/async.cjs.map +1 -1
- package/dist/lib/elur/async.js +1 -1
- package/dist/lib/elur/component.cjs +1 -2
- package/dist/lib/elur/component.d.cts +1 -17
- package/dist/lib/elur/component.d.ts +1 -17
- package/dist/lib/elur/component.js +2 -66
- package/dist/lib/elur/context.cjs +1 -1
- package/dist/lib/elur/context.cjs.map +1 -1
- package/dist/lib/elur/context.d.cts +5 -0
- package/dist/lib/elur/context.d.ts +5 -0
- package/dist/lib/elur/context.js +35 -23
- package/dist/lib/elur/context.js.map +1 -1
- package/dist/lib/elur/devtools.cjs +1 -1
- package/dist/lib/elur/devtools.cjs.map +1 -1
- package/dist/lib/elur/devtools.js +1 -1
- package/dist/lib/elur/form.cjs +1 -1
- package/dist/lib/elur/form.cjs.map +1 -1
- package/dist/lib/elur/form.js +1 -1
- package/dist/lib/elur/hydrate/index.cjs +1 -2
- package/dist/lib/elur/hydrate/index.d.cts +1 -13
- package/dist/lib/elur/hydrate/index.d.ts +1 -13
- package/dist/lib/elur/hydrate/index.js +2 -410
- package/dist/lib/elur/lifecycle.cjs +1 -1
- package/dist/lib/elur/lifecycle.cjs.map +1 -1
- package/dist/lib/elur/lifecycle.d.cts +27 -0
- package/dist/lib/elur/lifecycle.d.ts +27 -0
- package/dist/lib/elur/lifecycle.js +4 -0
- package/dist/lib/elur/lifecycle.js.map +1 -1
- package/dist/lib/elur/next/component.d.cts +281 -0
- package/dist/lib/elur/next/component.d.ts +281 -0
- package/dist/lib/elur/next/dom-write.d.cts +18 -0
- package/dist/lib/elur/next/dom-write.d.ts +18 -0
- package/dist/lib/elur/next/hydrate.d.cts +14 -0
- package/dist/lib/elur/next/hydrate.d.ts +14 -0
- package/dist/lib/elur/next/keyed-diff.d.cts +46 -0
- package/dist/lib/elur/next/keyed-diff.d.ts +46 -0
- package/dist/lib/elur/next/mount-helpers.d.cts +25 -0
- package/dist/lib/elur/next/mount-helpers.d.ts +25 -0
- package/dist/lib/elur/next/mount.d.cts +29 -0
- package/dist/lib/elur/next/mount.d.ts +29 -0
- package/dist/lib/elur/next/node-binding.d.cts +6 -0
- package/dist/lib/elur/next/node-binding.d.ts +6 -0
- package/dist/lib/elur/next/reactivity.d.cts +193 -0
- package/dist/lib/elur/next/reactivity.d.ts +193 -0
- package/dist/lib/elur/next-2/component.cjs +2 -0
- package/dist/lib/elur/next-2/component.cjs.map +1 -0
- package/dist/lib/elur/next-2/component.d.cts +283 -0
- package/dist/lib/elur/next-2/component.d.ts +283 -0
- package/dist/lib/elur/next-2/component.js +340 -0
- package/dist/lib/elur/next-2/component.js.map +1 -0
- package/dist/lib/elur/next-2/dom-write.cjs +2 -0
- package/dist/lib/elur/next-2/dom-write.cjs.map +1 -0
- package/dist/lib/elur/next-2/dom-write.d.cts +18 -0
- package/dist/lib/elur/next-2/dom-write.d.ts +18 -0
- package/dist/lib/elur/next-2/dom-write.js +31 -0
- package/dist/lib/elur/next-2/dom-write.js.map +1 -0
- package/dist/lib/elur/next-2/hydrate.cjs +2 -0
- package/dist/lib/elur/next-2/hydrate.cjs.map +1 -0
- package/dist/lib/elur/next-2/hydrate.d.cts +30 -0
- package/dist/lib/elur/next-2/hydrate.d.ts +30 -0
- package/dist/lib/elur/next-2/hydrate.js +449 -0
- package/dist/lib/elur/next-2/hydrate.js.map +1 -0
- package/dist/lib/elur/next-2/keyed-diff.cjs +2 -0
- package/dist/lib/elur/next-2/keyed-diff.cjs.map +1 -0
- package/dist/lib/elur/next-2/keyed-diff.d.cts +79 -0
- package/dist/lib/elur/next-2/keyed-diff.d.ts +79 -0
- package/dist/lib/elur/next-2/keyed-diff.js +208 -0
- package/dist/lib/elur/next-2/keyed-diff.js.map +1 -0
- package/dist/lib/elur/next-2/mount-helpers.cjs +2 -0
- package/dist/lib/elur/next-2/mount-helpers.cjs.map +1 -0
- package/dist/lib/elur/next-2/mount-helpers.d.cts +25 -0
- package/dist/lib/elur/next-2/mount-helpers.d.ts +25 -0
- package/dist/lib/elur/next-2/mount-helpers.js +87 -0
- package/dist/lib/elur/next-2/mount-helpers.js.map +1 -0
- package/dist/lib/elur/next-2/mount.cjs +2 -0
- package/dist/lib/elur/next-2/mount.cjs.map +1 -0
- package/dist/lib/elur/next-2/mount.d.cts +29 -0
- package/dist/lib/elur/next-2/mount.d.ts +29 -0
- package/dist/lib/elur/next-2/mount.js +34 -0
- package/dist/lib/elur/next-2/mount.js.map +1 -0
- package/dist/lib/elur/next-2/node-binding.cjs +2 -0
- package/dist/lib/elur/next-2/node-binding.cjs.map +1 -0
- package/dist/lib/elur/next-2/node-binding.d.cts +6 -0
- package/dist/lib/elur/next-2/node-binding.d.ts +6 -0
- package/dist/lib/elur/next-2/node-binding.js +130 -0
- package/dist/lib/elur/next-2/node-binding.js.map +1 -0
- package/dist/lib/elur/next-2/reactivity.cjs +2 -0
- package/dist/lib/elur/next-2/reactivity.cjs.map +1 -0
- package/dist/lib/elur/next-2/reactivity.d.cts +220 -0
- package/dist/lib/elur/next-2/reactivity.d.ts +220 -0
- package/dist/lib/elur/next-2/reactivity.js +614 -0
- package/dist/lib/elur/next-2/reactivity.js.map +1 -0
- package/dist/lib/elur/next-2/scheduler.cjs +2 -0
- package/dist/lib/elur/next-2/scheduler.cjs.map +1 -0
- package/dist/lib/elur/next-2/scheduler.d.cts +23 -0
- package/dist/lib/elur/next-2/scheduler.d.ts +23 -0
- package/dist/lib/elur/next-2/scheduler.js +26 -0
- package/dist/lib/elur/next-2/scheduler.js.map +1 -0
- package/dist/lib/elur/plugins.cjs +1 -1
- package/dist/lib/elur/plugins.cjs.map +1 -1
- package/dist/lib/elur/plugins.js +1 -1
- package/dist/lib/elur/reactivity.cjs +1 -2
- package/dist/lib/elur/reactivity.d.cts +1 -67
- package/dist/lib/elur/reactivity.d.ts +1 -67
- package/dist/lib/elur/reactivity.js +2 -218
- package/dist/lib/elur/router.cjs +1 -1
- package/dist/lib/elur/router.cjs.map +1 -1
- package/dist/lib/elur/router.js +1 -1
- package/dist/lib/elur/server/index.cjs +1 -1
- package/dist/lib/elur/server/index.cjs.map +1 -1
- package/dist/lib/elur/server/index.js +175 -107
- package/dist/lib/elur/server/index.js.map +1 -1
- package/dist/lib/elur/store.cjs +1 -1
- package/dist/lib/elur/store.cjs.map +1 -1
- package/dist/lib/elur/store.js +1 -1
- package/dist/lib/elur/template/bindings.cjs +1 -1
- package/dist/lib/elur/template/bindings.cjs.map +1 -1
- package/dist/lib/elur/template/bindings.js +98 -84
- package/dist/lib/elur/template/bindings.js.map +1 -1
- package/dist/lib/elur/template/dom-write.d.cts +1 -5
- package/dist/lib/elur/template/dom-write.d.ts +1 -5
- package/dist/lib/elur/template/error-boundary.cjs +1 -1
- package/dist/lib/elur/template/error-boundary.cjs.map +1 -1
- package/dist/lib/elur/template/error-boundary.js +56 -50
- package/dist/lib/elur/template/error-boundary.js.map +1 -1
- package/dist/lib/elur/template/html.cjs +1 -1
- package/dist/lib/elur/template/html.cjs.map +1 -1
- package/dist/lib/elur/template/html.js +40 -37
- package/dist/lib/elur/template/html.js.map +1 -1
- package/dist/lib/elur/template/index.cjs +1 -1
- package/dist/lib/elur/template/index.d.cts +2 -1
- package/dist/lib/elur/template/index.d.ts +2 -1
- package/dist/lib/elur/template/index.js +13 -12
- package/dist/lib/elur/template/keyed-diff.d.cts +1 -32
- package/dist/lib/elur/template/keyed-diff.d.ts +1 -32
- package/dist/lib/elur/template/keyed.cjs +1 -1
- package/dist/lib/elur/template/keyed.cjs.map +1 -1
- package/dist/lib/elur/template/keyed.d.cts +10 -2
- package/dist/lib/elur/template/keyed.d.ts +10 -2
- package/dist/lib/elur/template/keyed.js +12 -1
- package/dist/lib/elur/template/keyed.js.map +1 -1
- package/dist/lib/elur/template/mount-helpers.d.cts +1 -29
- package/dist/lib/elur/template/mount-helpers.d.ts +1 -29
- package/dist/lib/elur/template/node-binding.d.cts +1 -6
- package/dist/lib/elur/template/node-binding.d.ts +1 -6
- package/dist/lib/elur/template/portal.cjs +1 -1
- package/dist/lib/elur/template/portal.cjs.map +1 -1
- package/dist/lib/elur/template/portal.js +1 -1
- package/dist/lib/elur/template/transitions.cjs +1 -1
- package/dist/lib/elur/template/transitions.cjs.map +1 -1
- package/dist/lib/elur/template/transitions.js +2 -2
- package/dist/lib/elur/template/types.cjs +1 -1
- package/dist/lib/elur/template/types.cjs.map +1 -1
- package/dist/lib/elur/template/types.d.cts +55 -0
- package/dist/lib/elur/template/types.d.ts +55 -0
- package/dist/lib/elur/template/types.js +5 -1
- package/dist/lib/elur/template/types.js.map +1 -1
- package/dist/lib/elur.cjs +1 -1
- package/dist/lib/elur.js +2 -2
- package/dist/lib/form.cjs +1 -1
- package/dist/lib/form.js +1 -1
- package/dist/lib/hydrate.cjs +1 -2
- package/dist/lib/hydrate.js +2 -410
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.js +2 -2
- package/dist/lib/lifecycle.cjs +1 -1
- package/dist/lib/lifecycle.js +4 -0
- package/dist/lib/plugins.cjs +1 -1
- package/dist/lib/plugins.js +1 -1
- package/dist/lib/router.cjs +1 -1
- package/dist/lib/router.js +1 -1
- package/dist/lib/server.cjs +1 -1
- package/dist/lib/server.js +175 -107
- package/dist/lib/signals.cjs +1 -2
- package/dist/lib/signals.js +2 -218
- package/dist/lib/store.cjs +1 -1
- package/dist/lib/store.js +1 -1
- package/dist/lib/template.cjs +1 -1
- package/dist/lib/template.js +13 -12
- package/package.json +7 -9
- package/dist/lib/elur/component.cjs.map +0 -1
- package/dist/lib/elur/component.js.map +0 -1
- package/dist/lib/elur/hydrate/index.cjs.map +0 -1
- package/dist/lib/elur/hydrate/index.js.map +0 -1
- package/dist/lib/elur/reactivity.cjs.map +0 -1
- package/dist/lib/elur/reactivity.js.map +0 -1
- package/dist/lib/elur/template/dom-write.cjs +0 -2
- package/dist/lib/elur/template/dom-write.cjs.map +0 -1
- package/dist/lib/elur/template/dom-write.js +0 -16
- package/dist/lib/elur/template/dom-write.js.map +0 -1
- package/dist/lib/elur/template/keyed-diff.cjs +0 -2
- package/dist/lib/elur/template/keyed-diff.cjs.map +0 -1
- package/dist/lib/elur/template/keyed-diff.js +0 -100
- package/dist/lib/elur/template/keyed-diff.js.map +0 -1
- package/dist/lib/elur/template/mount-helpers.cjs +0 -2
- package/dist/lib/elur/template/mount-helpers.cjs.map +0 -1
- package/dist/lib/elur/template/mount-helpers.js +0 -132
- package/dist/lib/elur/template/mount-helpers.js.map +0 -1
- package/dist/lib/elur/template/node-binding.cjs +0 -2
- package/dist/lib/elur/template/node-binding.cjs.map +0 -1
- package/dist/lib/elur/template/node-binding.js +0 -95
- package/dist/lib/elur/template/node-binding.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.cjs","names":[],"sources":["../../src/elur/server/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { _popComponentContext, _pushComponentContext, _setContextScopeResolver } from \"../context.js\";\nimport { isElurComponent, type ElurComponent } from \"../lifecycle.js\";\nimport {\n isKeyedList,\n isElurTemplate,\n ELUR_RENDER_PROTOCOL,\n ELUR_TEMPLATE_DESCRIPTOR,\n type ServerRenderProtocolContext,\n type TemplateBindingContext,\n type TemplateDescriptor,\n} from \"../template/types.js\";\nimport { sanitizeUrl } from \"../template/sanitize.js\";\nimport { normalizeRepeatKey, serializeRepeatKey } from \"../template/keyed.js\";\n\n// Local guards avoid sharing the same minified import binding name with\n// callback parameters in the same module (esbuild bug with shared chunks).\nconst isTemplate = isElurTemplate;\nconst isKeyed = isKeyedList;\n\nexport interface RenderErrorInfo {\n /** Binding index inside the descriptor (or -1 for root/component errors). */\n index: number;\n /** Binding context where the error occurred. */\n context: \"node\" | \"attribute\" | \"event\" | \"root\" | \"component\";\n /** The original error. */\n cause: unknown;\n /** Debug name of the component when the error happened inside one. */\n component?: string;\n}\n\nexport interface ServerRenderOptions {\n markers?: \"none\" | \"hydration\";\n signal?: AbortSignal;\n context?: unknown;\n onError?: (error: unknown, info: RenderErrorInfo) => void;\n}\n\n/** A fragment of the rendered markup, streamed incrementally by `renderToChunks`. */\nexport interface RenderChunk {\n type: \"markup\" | \"boundary-start\" | \"boundary-end\" | \"error\" | \"done\";\n value: string;\n index: number;\n}\n\ninterface RenderState {\n markers: boolean;\n signal?: AbortSignal;\n context?: unknown;\n onError?: (error: unknown, info: RenderErrorInfo) => void;\n}\n\nconst renderContext = new AsyncLocalStorage<Map<unknown, unknown>[]>();\n_setContextScopeResolver(() => renderContext.getStore());\n\nexport interface ServerRenderScope {\n /** Abort signal that cancels all renders created through this scope. */\n readonly signal: AbortSignal;\n /** Renders a value to a full string, sharing this scope's context isolation. */\n render(value: unknown, options?: { markers?: boolean }): Promise<string>;\n /** Streams a value as incremental chunks, sharing this scope's context isolation. */\n renderToChunks(value: unknown, options?: { markers?: boolean }): AsyncIterable<RenderChunk>;\n /** Aborts every render running inside this scope. */\n abort(reason?: unknown): void;\n}\n\n/**\n * Creates an explicit server render scope: a per-render isolation unit that\n * keeps component context, markers and abort state private. Concurrent renders\n * created from the same scope never share `provide`/`inject` state.\n */\nexport function createServerRenderScope(options: Omit<ServerRenderOptions, \"signal\"> = {}): ServerRenderScope {\n const controller = new AbortController();\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n context: options.context,\n onError: options.onError,\n };\n const run = <T>(fn: () => Promise<T> | T): Promise<T> => Promise.resolve(renderContext.run([], fn));\n return {\n signal: controller.signal,\n async render(value, opts): Promise<string> {\n const scoped: RenderState = { ...state, markers: opts?.markers ?? state.markers, signal: controller.signal };\n let out = \"\";\n await run(() => {\n return (async () => {\n for await (const chunk of renderValueChunks(value, scoped)) {\n out += chunk.value;\n }\n })();\n });\n return out;\n },\n renderToChunks(value, opts): AsyncIterable<RenderChunk> {\n const scoped: RenderState = { ...state, markers: opts?.markers ?? state.markers, signal: controller.signal };\n return streamChunks(value, scoped);\n },\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n };\n}\n\n/**\n * Streams chunks produced inside an AsyncLocalStorage scope, preserving\n * per-render context isolation while yielding incrementally.\n */\nfunction streamChunks(value: unknown, state: RenderState): AsyncIterable<RenderChunk> {\n return {\n async *[Symbol.asyncIterator]() {\n const queue: RenderChunk[] = [];\n const waiters: Array<() => void> = [];\n let producerDone = false;\n let producerError: unknown;\n const wake = () => {\n const waiter = waiters.shift();\n waiter?.();\n };\n\n const task = renderContext.run([], async () => {\n try {\n for await (const chunk of renderValueChunks(value, state)) {\n queue.push(chunk);\n wake();\n }\n } catch (error) {\n producerError = error;\n } finally {\n producerDone = true;\n wake();\n }\n });\n\n while (true) {\n while (queue.length === 0) {\n if (producerDone) break;\n await new Promise<void>((resolve) => waiters.push(resolve));\n }\n if (queue.length === 0) break;\n const chunk = queue.shift()!;\n if (chunk) yield chunk;\n }\n if (producerError) {\n yield { type: \"error\", value: producerError instanceof Error ? producerError.message : String(producerError), index: -1 };\n throw producerError;\n }\n yield { type: \"done\", value: \"\", index: -1 };\n await task;\n },\n };\n}\n\nexport async function renderToString(value: unknown, options: ServerRenderOptions = {}): Promise<string> {\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n signal: options.signal,\n context: options.context,\n onError: options.onError,\n };\n let out = \"\";\n await Promise.resolve(\n renderContext.run([], async () => {\n for await (const chunk of renderValueChunks(value, state)) {\n out += chunk.value;\n }\n }),\n );\n return out;\n}\n\nexport function renderToChunks(\n value: unknown,\n options: ServerRenderOptions = {},\n): AsyncIterable<RenderChunk> {\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n signal: options.signal,\n context: options.context,\n onError: options.onError,\n };\n return streamChunks(value, state);\n}\n\nasync function* renderValueChunks(value: unknown, state: RenderState): AsyncGenerator<RenderChunk> {\n checkAbort(state);\n if (value instanceof Promise) {\n yield* renderValueChunks(await value, state);\n return;\n }\n if (value === null || value === undefined || value === false || value === true) return;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"bigint\") {\n yield { type: \"markup\", value: escapeText(String(value)), index: -1 };\n return;\n }\n if (Array.isArray(value)) {\n const resolved = await Promise.all(value.map((item) => resolveBindingValue(item)));\n checkAbort(state);\n for (const item of resolved) {\n if (state.markers) yield { type: \"markup\", value: \"<!--elur-ai-->\", index: -1 };\n yield* renderValueChunks(item, state);\n if (state.markers) yield { type: \"markup\", value: \"<!--elur-aiend-->\", index: -1 };\n }\n return;\n }\n if ((typeof value === \"object\" || typeof value === \"function\") && value !== null) {\n const protocol = (value as Record<PropertyKey, unknown>)[ELUR_RENDER_PROTOCOL] as\n | { renderServer?: (context: ServerRenderProtocolContext) => string | Promise<string> }\n | undefined;\n if (protocol?.renderServer) {\n const output = await protocol.renderServer({\n markers: state.markers,\n signal: state.signal,\n context: state.context,\n render: (nested, options) => renderValue(nested, {\n ...state,\n markers: options?.markers ?? state.markers,\n }),\n });\n checkAbort(state);\n yield { type: \"markup\", value: output, index: -1 };\n return;\n }\n }\n if (isElurComponent(value)) {\n yield* renderComponentChunks(value, state);\n return;\n }\n if (isKeyed(value)) {\n if (!state.markers) {\n const rendered = await Promise.all(\n value.items.map((item, index) => renderValue(value.renderFn(item, index), state)),\n );\n yield { type: \"markup\", value: rendered.join(\"\"), index: -1 };\n return;\n }\n const seen = new Set<string>();\n for (let index = 0; index < value.items.length; index++) {\n const item = value.items[index];\n const key = normalizeRepeatKey(value.keyFn(item, index), index);\n const serialized = serializeRepeatKey(key);\n if (seen.has(serialized)) {\n console.warn(\n `[elur] repeat(): duplicate key \"${key}\" during server render. ` +\n \"Keys must be unique; entries after the first will leak during hydration.\",\n );\n }\n seen.add(serialized);\n yield { type: \"markup\", value: `<!--elur-ki:${serialized}-->`, index: -1 };\n yield* renderValueChunks(value.renderFn(item, index), state);\n yield { type: \"markup\", value: \"<!--elur-ke-->\", index: -1 };\n }\n return;\n }\n if (isTemplate(value)) {\n const descriptor = value[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throw new TypeError(\"[elur] Template does not support server rendering\");\n yield* renderDescriptorChunks(descriptor, state);\n return;\n }\n yield { type: \"markup\", value: escapeText(String(value)), index: -1 };\n}\n\nasync function* renderComponentChunks(component: ElurComponent, state: RenderState): AsyncGenerator<RenderChunk> {\n _pushComponentContext();\n const info: RenderErrorInfo = {\n index: -1,\n context: \"component\",\n cause: undefined,\n component: component._debugName,\n };\n try {\n try {\n component.onInit?.();\n component.onServerRender?.();\n } catch (error) {\n if (component.onError) component.onError(error);\n else throw error;\n }\n try {\n yield* renderValueChunks(component.render(), state);\n } catch (error) {\n if (component.onError) {\n component.onError(error);\n return;\n }\n throw error;\n }\n } catch (error) {\n state.onError?.(error, { ...info, cause: error });\n throw error;\n } finally {\n _popComponentContext();\n }\n}\n\nasync function* renderDescriptorChunks(descriptor: TemplateDescriptor, state: RenderState): AsyncGenerator<RenderChunk> {\n const skipLeading = new Uint8Array(descriptor.strings.length);\n\n for (let index = 0; index < descriptor.strings.length; index++) {\n if (state.signal?.aborted) throw state.signal.reason ?? new DOMException(\"Render aborted\", \"AbortError\");\n let staticPart = descriptor.strings[index];\n if (skipLeading[index] === 1 && (staticPart[0] === '\"' || staticPart[0] === \"'\")) {\n staticPart = staticPart.slice(1);\n }\n if (index >= descriptor.contexts.length) {\n yield { type: \"markup\", value: staticPart, index };\n continue;\n }\n\n const context = descriptor.contexts[index];\n const value = descriptor.values[index];\n if (context.type === \"node\") {\n yield { type: \"markup\", value: staticPart, index };\n if (state.markers) yield { type: \"boundary-start\", value: `<!--elur-${index}-->`, index };\n try {\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n yield* renderValueChunks(resolved, state);\n } catch (error) {\n state.onError?.(error, { index, context: \"node\", cause: error });\n throw error;\n }\n if (state.markers) yield { type: \"boundary-end\", value: `<!--elur-end-${index}-->`, index };\n continue;\n }\n\n const cut = bindingCut(context);\n const prefix = staticPart.slice(0, -cut);\n if (context.hadOpenQuote) skipLeading[index + 1] = 1;\n if (context.type === \"event\") {\n if (state.markers) {\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n yield { type: \"markup\", value: `${prefix}${separator}data-elur-e-${index}=\"${escapeAttribute(context.eventName)}\"`, index };\n } else {\n yield { type: \"markup\", value: prefix.replace(/\\s+$/, \"\"), index };\n }\n continue;\n }\n\n yield { type: \"markup\", value: prefix, index };\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n if (context.attrName !== \"ref\" && resolved !== null && resolved !== undefined && resolved !== false) {\n const serialized = context.url ? sanitizeUrl(String(resolved)) : String(resolved);\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n yield { type: \"markup\", value: `${separator}${context.attrName}=\"${escapeAttribute(serialized)}\"`, index };\n }\n if (state.markers) yield { type: \"markup\", value: ` data-elur-a-${index}=\"${escapeAttribute(context.attrName)}\"`, index };\n }\n}\n\nasync function renderValue(value: unknown, state: RenderState): Promise<string> {\n let out = \"\";\n for await (const chunk of renderValueChunks(value, state)) {\n out += chunk.value;\n }\n return out;\n}\n\nfunction checkAbort(state: RenderState): void {\n if (state.signal?.aborted) throw state.signal.reason ?? new DOMException(\"Render aborted\", \"AbortError\");\n}\n\nasync function resolveBindingValue(value: unknown): Promise<unknown> {\n const resolved = typeof value === \"function\" ? (value as () => unknown)() : value;\n return resolved instanceof Promise ? await resolved : resolved;\n}\n\nfunction bindingCut(context: Exclude<TemplateBindingContext, { type: \"node\" }>): number {\n if (context.type === \"event\") {\n const full = context.modifiers.length\n ? `${context.eventName}.${context.modifiers.join(\".\")}`\n : context.eventName;\n return `@${full}=`.length + (context.hadOpenQuote ? 1 : 0);\n }\n return `${context.attrName}=`.length + (context.hadOpenQuote ? 1 : 0);\n}\n\nfunction escapeText(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeText(value).replace(/\"/g, \""\");\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.cjs","names":[],"sources":["../../src/elur/server/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { _popComponentContext, _pushComponentContext, _setContextScopeResolver } from \"../context.js\";\nimport { isElurComponent, type ElurComponent } from \"../lifecycle.js\";\nimport {\n isKeyedList,\n isElurTemplate,\n ELUR_RENDER_PROTOCOL,\n ELUR_TEMPLATE_DESCRIPTOR,\n type ServerRenderProtocolContext,\n type SsrEmit,\n type TemplateBindingContext,\n type TemplateDescriptor,\n} from \"../template/types.js\";\nimport { sanitizeUrl } from \"../template/sanitize.js\";\nimport { normalizeRepeatKey, serializeRepeatKey } from \"../template/keyed.js\";\nimport { Signal, untrack } from \"../reactivity.js\";\nimport { isDerivedBinding } from \"../template/types.js\";\n\n// Local guards avoid sharing the same minified import binding name with\n// callback parameters in the same module (esbuild bug with shared chunks).\nconst isTemplate = isElurTemplate;\nconst isKeyed = isKeyedList;\n\nexport interface RenderErrorInfo {\n /** Binding index inside the descriptor (or -1 for root/component errors). */\n index: number;\n /** Binding context where the error occurred. */\n context: \"node\" | \"attribute\" | \"event\" | \"root\" | \"component\";\n /** The original error. */\n cause: unknown;\n /** Debug name of the component when the error happened inside one. */\n component?: string;\n}\n\nexport interface ServerRenderOptions {\n markers?: \"none\" | \"hydration\";\n signal?: AbortSignal;\n context?: unknown;\n onError?: (error: unknown, info: RenderErrorInfo) => void;\n}\n\n/** A fragment of the rendered markup, streamed incrementally by `renderToChunks`. */\nexport interface RenderChunk {\n type: \"markup\" | \"boundary-start\" | \"boundary-end\" | \"error\" | \"done\";\n value: string;\n index: number;\n}\n\ninterface RenderState {\n markers: boolean;\n signal?: AbortSignal;\n context?: unknown;\n onError?: (error: unknown, info: RenderErrorInfo) => void;\n}\n\nconst renderContext = new AsyncLocalStorage<Map<unknown, unknown>[]>();\n_setContextScopeResolver(() => renderContext.getStore());\n\nexport interface ServerRenderScope {\n /** Abort signal that cancels all renders created through this scope. */\n readonly signal: AbortSignal;\n /** Renders a value to a full string, sharing this scope's context isolation. */\n render(value: unknown, options?: { markers?: boolean }): Promise<string>;\n /** Streams a value as incremental chunks, sharing this scope's context isolation. */\n renderToChunks(value: unknown, options?: { markers?: boolean }): AsyncIterable<RenderChunk>;\n /** Aborts every render running inside this scope. */\n abort(reason?: unknown): void;\n}\n\n/**\n * Creates an explicit server render scope: a per-render isolation unit that\n * keeps component context, markers and abort state private. Concurrent renders\n * created from the same scope never share `provide`/`inject` state.\n */\nexport function createServerRenderScope(options: Omit<ServerRenderOptions, \"signal\"> = {}): ServerRenderScope {\n const controller = new AbortController();\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n context: options.context,\n onError: options.onError,\n };\n const run = <T>(fn: () => Promise<T> | T): Promise<T> => Promise.resolve(renderContext.run([], fn));\n return {\n signal: controller.signal,\n async render(value, opts): Promise<string> {\n const scoped: RenderState = { ...state, markers: opts?.markers ?? state.markers, signal: controller.signal };\n let out = \"\";\n await run(() => {\n return (async () => {\n for await (const chunk of renderValueChunks(value, scoped)) {\n out += chunk.value;\n }\n })();\n });\n return out;\n },\n renderToChunks(value, opts): AsyncIterable<RenderChunk> {\n const scoped: RenderState = { ...state, markers: opts?.markers ?? state.markers, signal: controller.signal };\n return streamChunks(value, scoped);\n },\n abort(reason?: unknown): void {\n controller.abort(reason);\n },\n };\n}\n\n/**\n * Streams chunks produced inside an AsyncLocalStorage scope, preserving\n * per-render context isolation while yielding incrementally.\n */\nfunction streamChunks(value: unknown, state: RenderState): AsyncIterable<RenderChunk> {\n return {\n async *[Symbol.asyncIterator]() {\n const queue: RenderChunk[] = [];\n const waiters: Array<() => void> = [];\n let producerDone = false;\n let producerError: unknown;\n const wake = () => {\n const waiter = waiters.shift();\n waiter?.();\n };\n\n const task = renderContext.run([], async () => {\n try {\n for await (const chunk of renderValueChunks(value, state)) {\n queue.push(chunk);\n wake();\n }\n } catch (error) {\n producerError = error;\n } finally {\n producerDone = true;\n wake();\n }\n });\n\n while (true) {\n while (queue.length === 0) {\n if (producerDone) break;\n await new Promise<void>((resolve) => waiters.push(resolve));\n }\n if (queue.length === 0) break;\n const chunk = queue.shift()!;\n if (chunk) yield chunk;\n }\n if (producerError) {\n yield { type: \"error\", value: producerError instanceof Error ? producerError.message : String(producerError), index: -1 };\n throw producerError;\n }\n yield { type: \"done\", value: \"\", index: -1 };\n await task;\n },\n };\n}\n\nexport async function renderToString(value: unknown, options: ServerRenderOptions = {}): Promise<string> {\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n signal: options.signal,\n context: options.context,\n onError: options.onError,\n };\n let out = \"\";\n await Promise.resolve(\n renderContext.run([], async () => {\n for await (const chunk of renderValueChunks(value, state)) {\n out += chunk.value;\n }\n }),\n );\n return out;\n}\n\nexport function renderToChunks(\n value: unknown,\n options: ServerRenderOptions = {},\n): AsyncIterable<RenderChunk> {\n const state: RenderState = {\n markers: options.markers === \"hydration\",\n signal: options.signal,\n context: options.context,\n onError: options.onError,\n };\n return streamChunks(value, state);\n}\n\nasync function* renderValueChunks(value: unknown, state: RenderState): AsyncGenerator<RenderChunk> {\n checkAbort(state);\n if (value instanceof Promise) {\n yield* renderValueChunks(await value, state);\n return;\n }\n if (value === null || value === undefined || value === false || value === true) return;\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"bigint\") {\n yield { type: \"markup\", value: escapeText(String(value)), index: -1 };\n return;\n }\n if (Array.isArray(value)) {\n const resolved = await Promise.all(value.map((item) => resolveBindingValue(item)));\n checkAbort(state);\n for (const item of resolved) {\n if (state.markers) yield { type: \"markup\", value: \"<!--elur-ai-->\", index: -1 };\n yield* renderValueChunks(item, state);\n if (state.markers) yield { type: \"markup\", value: \"<!--elur-aiend-->\", index: -1 };\n }\n return;\n }\n if ((typeof value === \"object\" || typeof value === \"function\") && value !== null) {\n const protocol = (value as Record<PropertyKey, unknown>)[ELUR_RENDER_PROTOCOL] as\n | { renderServer?: (context: ServerRenderProtocolContext) => string | Promise<string> }\n | undefined;\n if (protocol?.renderServer) {\n const output = await protocol.renderServer({\n markers: state.markers,\n signal: state.signal,\n context: state.context,\n render: (nested, options) => renderValue(nested, {\n ...state,\n markers: options?.markers ?? state.markers,\n }),\n });\n checkAbort(state);\n yield { type: \"markup\", value: output, index: -1 };\n return;\n }\n }\n if (isElurComponent(value)) {\n yield* renderComponentChunks(value, state);\n return;\n }\n if (isKeyed(value)) {\n if (!state.markers) {\n const rendered = await Promise.all(\n value.items.map((item, index) => renderValue(value.renderFn(item, index), state)),\n );\n yield { type: \"markup\", value: rendered.join(\"\"), index: -1 };\n return;\n }\n const seen = new Set<string>();\n for (let index = 0; index < value.items.length; index++) {\n const item = value.items[index];\n const key = normalizeRepeatKey(value.keyFn(item, index), index);\n const serialized = serializeRepeatKey(key);\n if (seen.has(serialized)) {\n console.warn(\n `[elur] repeat(): duplicate key \"${key}\" during server render. ` +\n \"Keys must be unique; entries after the first will leak during hydration.\",\n );\n }\n seen.add(serialized);\n yield { type: \"markup\", value: `<!--elur-ki:${serialized}-->`, index: -1 };\n yield* renderValueChunks(value.renderFn(item, index), state);\n yield { type: \"markup\", value: \"<!--elur-ke-->\", index: -1 };\n }\n return;\n }\n if (isTemplate(value)) {\n const descriptor = value[ELUR_TEMPLATE_DESCRIPTOR];\n if (!descriptor) throw new TypeError(\"[elur] Template does not support server rendering\");\n yield* renderDescriptorChunks(descriptor, state);\n return;\n }\n yield { type: \"markup\", value: escapeText(String(value)), index: -1 };\n}\n\nasync function* renderComponentChunks(component: ElurComponent, state: RenderState): AsyncGenerator<RenderChunk> {\n _pushComponentContext();\n const info: RenderErrorInfo = {\n index: -1,\n context: \"component\",\n cause: undefined,\n component: component._debugName,\n };\n try {\n try {\n component.onInit?.();\n component.onServerRender?.();\n } catch (error) {\n if (component.onError) component.onError(error);\n else throw error;\n }\n try {\n yield* renderValueChunks(component.render(), state);\n } catch (error) {\n if (component.onError) {\n component.onError(error);\n return;\n }\n throw error;\n }\n } catch (error) {\n state.onError?.(error, { ...info, cause: error });\n throw error;\n } finally {\n _popComponentContext();\n }\n}\n\n// C.12 fase 2: emit ops para el renderer SSR especializado (descriptor.ssr).\n// Replican exactamente la semántica del intérprete genérico — los strings\n// llegan pre-cortados desde el codegen (bindingCut/skipLeading en build).\nfunction makeSsrEmit(state: RenderState, compiledHydrate: boolean): SsrEmit {\n return {\n m: (value) => ({ type: \"markup\", value, index: -1 }),\n node: async function* (index, value) {\n if (state.markers) yield { type: \"boundary-start\", value: `<!--elur-${index}-->`, index };\n try {\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n yield* renderValueChunks(resolved, state);\n } catch (error) {\n state.onError?.(error, { index, context: \"node\", cause: error });\n throw error;\n }\n if (state.markers) yield { type: \"boundary-end\", value: `<!--elur-end-${index}-->`, index };\n },\n attr: async (prefix, index, attrName, url, _executable, value) => {\n const chunks: RenderChunk[] = [{ type: \"markup\", value: prefix, index }];\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n if (attrName !== \"ref\" && resolved !== null && resolved !== undefined && resolved !== false) {\n const serialized = url ? sanitizeUrl(String(resolved)) : String(resolved);\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n chunks.push({ type: \"markup\", value: `${separator}${attrName}=\"${escapeAttribute(serialized)}\"`, index });\n }\n if (state.markers && !compiledHydrate) {\n chunks.push({ type: \"markup\", value: ` data-elur-a-${index}=\"${escapeAttribute(attrName)}\"`, index });\n }\n return chunks;\n },\n event: (index, prefix, eventName) => {\n if (state.markers && !compiledHydrate) {\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n return { type: \"markup\", value: `${prefix}${separator}data-elur-e-${index}=\"${escapeAttribute(eventName)}\"`, index };\n }\n return { type: \"markup\", value: prefix.replace(/\\s+$/, \"\"), index };\n },\n };\n}\n\nasync function* renderDescriptorChunks(descriptor: TemplateDescriptor, state: RenderState): AsyncGenerator<RenderChunk> {\n // C.13: templates con hidratación compilada no necesitan `data-elur-*`\n // en el HTML — el cliente localiza los elementos por access paths.\n // Los `<!--elur-N-->` siguen emitiéndose (boundaries dinámicas).\n const compiledHydrate = descriptor.hydrate !== undefined;\n // C.12 fase 2: el artefacto compilado trae su propio renderer SSR —\n // mismo HTML, secuencia especializada en vez del loop intérprete.\n if (descriptor.ssr) {\n yield* descriptor.ssr(makeSsrEmit(state, compiledHydrate), descriptor.values);\n return;\n }\n const skipLeading = new Uint8Array(descriptor.strings.length);\n\n for (let index = 0; index < descriptor.strings.length; index++) {\n if (state.signal?.aborted) throw state.signal.reason ?? new DOMException(\"Render aborted\", \"AbortError\");\n let staticPart = descriptor.strings[index];\n if (skipLeading[index] === 1 && (staticPart[0] === '\"' || staticPart[0] === \"'\")) {\n staticPart = staticPart.slice(1);\n }\n if (index >= descriptor.contexts.length) {\n yield { type: \"markup\", value: staticPart, index };\n continue;\n }\n\n const context = descriptor.contexts[index];\n const value = descriptor.values[index];\n if (context.type === \"node\") {\n yield { type: \"markup\", value: staticPart, index };\n if (state.markers) yield { type: \"boundary-start\", value: `<!--elur-${index}-->`, index };\n try {\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n yield* renderValueChunks(resolved, state);\n } catch (error) {\n state.onError?.(error, { index, context: \"node\", cause: error });\n throw error;\n }\n if (state.markers) yield { type: \"boundary-end\", value: `<!--elur-end-${index}-->`, index };\n continue;\n }\n\n const cut = bindingCut(context);\n const prefix = staticPart.slice(0, -cut);\n if (context.hadOpenQuote) skipLeading[index + 1] = 1;\n if (context.type === \"event\") {\n if (state.markers && !compiledHydrate) {\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n yield { type: \"markup\", value: `${prefix}${separator}data-elur-e-${index}=\"${escapeAttribute(context.eventName)}\"`, index };\n } else {\n yield { type: \"markup\", value: prefix.replace(/\\s+$/, \"\"), index };\n }\n continue;\n }\n\n yield { type: \"markup\", value: prefix, index };\n const resolved = await resolveBindingValue(value);\n checkAbort(state);\n if (context.attrName !== \"ref\" && resolved !== null && resolved !== undefined && resolved !== false) {\n const serialized = context.url ? sanitizeUrl(String(resolved)) : String(resolved);\n const separator = /\\s$/.test(prefix) ? \"\" : \" \";\n yield { type: \"markup\", value: `${separator}${context.attrName}=\"${escapeAttribute(serialized)}\"`, index };\n }\n if (state.markers && !compiledHydrate) yield { type: \"markup\", value: ` data-elur-a-${index}=\"${escapeAttribute(context.attrName)}\"`, index };\n }\n}\n\nasync function renderValue(value: unknown, state: RenderState): Promise<string> {\n let out = \"\";\n for await (const chunk of renderValueChunks(value, state)) {\n out += chunk.value;\n }\n return out;\n}\n\nfunction checkAbort(state: RenderState): void {\n if (state.signal?.aborted) throw state.signal.reason ?? new DOMException(\"Render aborted\", \"AbortError\");\n}\n\nasync function resolveBindingValue(value: unknown): Promise<unknown> {\n // C.6 T1: la señal viaja como valor — SSR la resuelve a su lectura actual.\n if (value instanceof Signal) return value.peek();\n // C.7 T2: el pack derivado se resuelve evaluando el getter untracked —\n // SSR no crea suscripciones y no debe contaminar un consumidor activo.\n if (isDerivedBinding(value)) return untrack(value.get);\n const resolved = typeof value === \"function\" ? (value as () => unknown)() : value;\n return resolved instanceof Promise ? await resolved : resolved;\n}\n\nfunction bindingCut(context: Exclude<TemplateBindingContext, { type: \"node\" }>): number {\n if (context.type === \"event\") {\n const full = context.modifiers.length\n ? `${context.eventName}.${context.modifiers.join(\".\")}`\n : context.eventName;\n return `@${full}=`.length + (context.hadOpenQuote ? 1 : 0);\n }\n return `${context.attrName}=`.length + (context.hadOpenQuote ? 1 : 0);\n}\n\nfunction escapeText(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeText(value).replace(/\"/g, \""\");\n}"],"mappings":"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"}
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { Signal as e, untrack as t } from "./elur/next-2/reactivity.js";
|
|
2
|
+
import { ELUR_RENDER_PROTOCOL as n, ELUR_TEMPLATE_DESCRIPTOR as r, isDerivedBinding as i, isElurTemplate as a, isKeyedList as o } from "./elur/template/types.js";
|
|
3
|
+
import { isElurComponent as s } from "./lifecycle.js";
|
|
4
|
+
import { _popComponentContext as c, _pushComponentContext as l, _setContextScopeResolver as u } from "./context.js";
|
|
5
|
+
import { normalizeRepeatKey as d, serializeRepeatKey as f } from "./elur/template/keyed.js";
|
|
6
|
+
import { sanitizeUrl as p } from "./elur/template/sanitize.js";
|
|
7
|
+
import { AsyncLocalStorage as m } from "node:async_hooks";
|
|
7
8
|
//#region src/elur/server/index.ts
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
function
|
|
9
|
+
var h = a, g = o, _ = new m();
|
|
10
|
+
u(() => _.getStore());
|
|
11
|
+
function v(e = {}) {
|
|
11
12
|
let t = new AbortController(), n = {
|
|
12
13
|
markers: e.markers === "hydration",
|
|
13
14
|
context: e.context,
|
|
14
15
|
onError: e.onError
|
|
15
|
-
}, r = (e) => Promise.resolve(
|
|
16
|
+
}, r = (e) => Promise.resolve(_.run([], e));
|
|
16
17
|
return {
|
|
17
18
|
signal: t.signal,
|
|
18
19
|
async render(e, i) {
|
|
@@ -22,11 +23,11 @@ function h(e = {}) {
|
|
|
22
23
|
signal: t.signal
|
|
23
24
|
}, o = "";
|
|
24
25
|
return await r(() => (async () => {
|
|
25
|
-
for await (let t of
|
|
26
|
+
for await (let t of S(e, a)) o += t.value;
|
|
26
27
|
})()), o;
|
|
27
28
|
},
|
|
28
29
|
renderToChunks(e, r) {
|
|
29
|
-
return
|
|
30
|
+
return y(e, {
|
|
30
31
|
...n,
|
|
31
32
|
markers: r?.markers ?? n.markers,
|
|
32
33
|
signal: t.signal
|
|
@@ -37,13 +38,13 @@ function h(e = {}) {
|
|
|
37
38
|
}
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
|
-
function
|
|
41
|
+
function y(e, t) {
|
|
41
42
|
return { async *[Symbol.asyncIterator]() {
|
|
42
43
|
let n = [], r = [], i = !1, a, o = () => {
|
|
43
44
|
r.shift()?.();
|
|
44
|
-
}, s =
|
|
45
|
+
}, s = _.run([], async () => {
|
|
45
46
|
try {
|
|
46
|
-
for await (let r of
|
|
47
|
+
for await (let r of S(e, t)) n.push(r), o();
|
|
47
48
|
} catch (e) {
|
|
48
49
|
a = e;
|
|
49
50
|
} finally {
|
|
@@ -68,66 +69,66 @@ function g(e, t) {
|
|
|
68
69
|
}, await s;
|
|
69
70
|
} };
|
|
70
71
|
}
|
|
71
|
-
async function
|
|
72
|
+
async function b(e, t = {}) {
|
|
72
73
|
let n = {
|
|
73
74
|
markers: t.markers === "hydration",
|
|
74
75
|
signal: t.signal,
|
|
75
76
|
context: t.context,
|
|
76
77
|
onError: t.onError
|
|
77
78
|
}, r = "";
|
|
78
|
-
return await Promise.resolve(
|
|
79
|
-
for await (let t of
|
|
79
|
+
return await Promise.resolve(_.run([], async () => {
|
|
80
|
+
for await (let t of S(e, n)) r += t.value;
|
|
80
81
|
})), r;
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
return
|
|
83
|
+
function x(e, t = {}) {
|
|
84
|
+
return y(e, {
|
|
84
85
|
markers: t.markers === "hydration",
|
|
85
86
|
signal: t.signal,
|
|
86
87
|
context: t.context,
|
|
87
88
|
onError: t.onError
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
|
-
async function*
|
|
91
|
-
if (
|
|
92
|
-
yield*
|
|
91
|
+
async function* S(e, t) {
|
|
92
|
+
if (D(t), e instanceof Promise) {
|
|
93
|
+
yield* S(await e, t);
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
|
-
if (!(
|
|
96
|
-
if (typeof
|
|
96
|
+
if (!(e == null || e === !1 || e === !0)) {
|
|
97
|
+
if (typeof e == "string" || typeof e == "number" || typeof e == "bigint") {
|
|
97
98
|
yield {
|
|
98
99
|
type: "markup",
|
|
99
|
-
value:
|
|
100
|
+
value: A(String(e)),
|
|
100
101
|
index: -1
|
|
101
102
|
};
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
|
-
if (Array.isArray(
|
|
105
|
-
let
|
|
106
|
-
|
|
107
|
-
for (let
|
|
105
|
+
if (Array.isArray(e)) {
|
|
106
|
+
let n = await Promise.all(e.map((e) => O(e)));
|
|
107
|
+
D(t);
|
|
108
|
+
for (let e of n) t.markers && (yield {
|
|
108
109
|
type: "markup",
|
|
109
110
|
value: "<!--elur-ai-->",
|
|
110
111
|
index: -1
|
|
111
|
-
}), yield*
|
|
112
|
+
}), yield* S(e, t), t.markers && (yield {
|
|
112
113
|
type: "markup",
|
|
113
114
|
value: "<!--elur-aiend-->",
|
|
114
115
|
index: -1
|
|
115
116
|
});
|
|
116
117
|
return;
|
|
117
118
|
}
|
|
118
|
-
if ((typeof
|
|
119
|
-
let
|
|
120
|
-
if (
|
|
121
|
-
let e = await
|
|
122
|
-
markers:
|
|
123
|
-
signal:
|
|
124
|
-
context:
|
|
125
|
-
render: (e,
|
|
126
|
-
...
|
|
127
|
-
markers:
|
|
119
|
+
if ((typeof e == "object" || typeof e == "function") && e !== null) {
|
|
120
|
+
let r = e[n];
|
|
121
|
+
if (r?.renderServer) {
|
|
122
|
+
let e = await r.renderServer({
|
|
123
|
+
markers: t.markers,
|
|
124
|
+
signal: t.signal,
|
|
125
|
+
context: t.context,
|
|
126
|
+
render: (e, n) => E(e, {
|
|
127
|
+
...t,
|
|
128
|
+
markers: n?.markers ?? t.markers
|
|
128
129
|
})
|
|
129
130
|
});
|
|
130
|
-
|
|
131
|
+
D(t), yield {
|
|
131
132
|
type: "markup",
|
|
132
133
|
value: e,
|
|
133
134
|
index: -1
|
|
@@ -135,27 +136,27 @@ async function* y(n, r) {
|
|
|
135
136
|
return;
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
|
-
if (
|
|
139
|
-
yield*
|
|
139
|
+
if (s(e)) {
|
|
140
|
+
yield* C(e, t);
|
|
140
141
|
return;
|
|
141
142
|
}
|
|
142
|
-
if (
|
|
143
|
-
if (!
|
|
143
|
+
if (g(e)) {
|
|
144
|
+
if (!t.markers) {
|
|
144
145
|
yield {
|
|
145
146
|
type: "markup",
|
|
146
|
-
value: (await Promise.all(
|
|
147
|
+
value: (await Promise.all(e.items.map((n, r) => E(e.renderFn(n, r), t)))).join(""),
|
|
147
148
|
index: -1
|
|
148
149
|
};
|
|
149
150
|
return;
|
|
150
151
|
}
|
|
151
|
-
let
|
|
152
|
-
for (let
|
|
153
|
-
let i =
|
|
154
|
-
|
|
152
|
+
let n = /* @__PURE__ */ new Set();
|
|
153
|
+
for (let r = 0; r < e.items.length; r++) {
|
|
154
|
+
let i = e.items[r], a = d(e.keyFn(i, r), r), o = f(a);
|
|
155
|
+
n.has(o) && console.warn(`[elur] repeat(): duplicate key "${a}" during server render. Keys must be unique; entries after the first will leak during hydration.`), n.add(o), yield {
|
|
155
156
|
type: "markup",
|
|
156
157
|
value: `<!--elur-ki:${o}-->`,
|
|
157
158
|
index: -1
|
|
158
|
-
}, yield*
|
|
159
|
+
}, yield* S(e.renderFn(i, r), t), yield {
|
|
159
160
|
type: "markup",
|
|
160
161
|
value: "<!--elur-ke-->",
|
|
161
162
|
index: -1
|
|
@@ -163,21 +164,21 @@ async function* y(n, r) {
|
|
|
163
164
|
}
|
|
164
165
|
return;
|
|
165
166
|
}
|
|
166
|
-
if (
|
|
167
|
-
let
|
|
168
|
-
if (!
|
|
169
|
-
yield*
|
|
167
|
+
if (h(e)) {
|
|
168
|
+
let n = e[r];
|
|
169
|
+
if (!n) throw TypeError("[elur] Template does not support server rendering");
|
|
170
|
+
yield* T(n, t);
|
|
170
171
|
return;
|
|
171
172
|
}
|
|
172
173
|
yield {
|
|
173
174
|
type: "markup",
|
|
174
|
-
value:
|
|
175
|
+
value: A(String(e)),
|
|
175
176
|
index: -1
|
|
176
177
|
};
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
|
-
async function*
|
|
180
|
-
|
|
180
|
+
async function* C(e, t) {
|
|
181
|
+
l();
|
|
181
182
|
let n = {
|
|
182
183
|
index: -1,
|
|
183
184
|
context: "component",
|
|
@@ -192,7 +193,7 @@ async function* b(e, t) {
|
|
|
192
193
|
else throw t;
|
|
193
194
|
}
|
|
194
195
|
try {
|
|
195
|
-
yield*
|
|
196
|
+
yield* S(e.render(), t);
|
|
196
197
|
} catch (t) {
|
|
197
198
|
if (e.onError) {
|
|
198
199
|
e.onError(t);
|
|
@@ -206,106 +207,173 @@ async function* b(e, t) {
|
|
|
206
207
|
cause: e
|
|
207
208
|
}), e;
|
|
208
209
|
} finally {
|
|
209
|
-
|
|
210
|
+
c();
|
|
210
211
|
}
|
|
211
212
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
213
|
+
function w(e, t) {
|
|
214
|
+
return {
|
|
215
|
+
m: (e) => ({
|
|
216
|
+
type: "markup",
|
|
217
|
+
value: e,
|
|
218
|
+
index: -1
|
|
219
|
+
}),
|
|
220
|
+
node: async function* (t, n) {
|
|
221
|
+
e.markers && (yield {
|
|
222
|
+
type: "boundary-start",
|
|
223
|
+
value: `<!--elur-${t}-->`,
|
|
224
|
+
index: t
|
|
225
|
+
});
|
|
226
|
+
try {
|
|
227
|
+
let t = await O(n);
|
|
228
|
+
D(e), yield* S(t, e);
|
|
229
|
+
} catch (n) {
|
|
230
|
+
throw e.onError?.(n, {
|
|
231
|
+
index: t,
|
|
232
|
+
context: "node",
|
|
233
|
+
cause: n
|
|
234
|
+
}), n;
|
|
235
|
+
}
|
|
236
|
+
e.markers && (yield {
|
|
237
|
+
type: "boundary-end",
|
|
238
|
+
value: `<!--elur-end-${t}-->`,
|
|
239
|
+
index: t
|
|
240
|
+
});
|
|
241
|
+
},
|
|
242
|
+
attr: async (n, r, i, a, o, s) => {
|
|
243
|
+
let c = [{
|
|
244
|
+
type: "markup",
|
|
245
|
+
value: n,
|
|
246
|
+
index: r
|
|
247
|
+
}], l = await O(s);
|
|
248
|
+
if (D(e), i !== "ref" && l != null && l !== !1) {
|
|
249
|
+
let e = a ? p(String(l)) : String(l), t = /\s$/.test(n) ? "" : " ";
|
|
250
|
+
c.push({
|
|
251
|
+
type: "markup",
|
|
252
|
+
value: `${t}${i}="${j(e)}"`,
|
|
253
|
+
index: r
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return e.markers && !t && c.push({
|
|
257
|
+
type: "markup",
|
|
258
|
+
value: ` data-elur-a-${r}="${j(i)}"`,
|
|
259
|
+
index: r
|
|
260
|
+
}), c;
|
|
261
|
+
},
|
|
262
|
+
event: (n, r, i) => e.markers && !t ? {
|
|
263
|
+
type: "markup",
|
|
264
|
+
value: `${r}${/\s$/.test(r) ? "" : " "}data-elur-e-${n}="${j(i)}"`,
|
|
265
|
+
index: n
|
|
266
|
+
} : {
|
|
267
|
+
type: "markup",
|
|
268
|
+
value: r.replace(/\s+$/, ""),
|
|
269
|
+
index: n
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
async function* T(e, t) {
|
|
274
|
+
let n = e.hydrate !== void 0;
|
|
275
|
+
if (e.ssr) {
|
|
276
|
+
yield* e.ssr(w(t, n), e.values);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
let r = new Uint8Array(e.strings.length);
|
|
280
|
+
for (let i = 0; i < e.strings.length; i++) {
|
|
215
281
|
if (t.signal?.aborted) throw t.signal.reason ?? new DOMException("Render aborted", "AbortError");
|
|
216
|
-
let
|
|
217
|
-
if (
|
|
282
|
+
let a = e.strings[i];
|
|
283
|
+
if (r[i] === 1 && (a[0] === "\"" || a[0] === "'") && (a = a.slice(1)), i >= e.contexts.length) {
|
|
218
284
|
yield {
|
|
219
285
|
type: "markup",
|
|
220
|
-
value:
|
|
221
|
-
index:
|
|
286
|
+
value: a,
|
|
287
|
+
index: i
|
|
222
288
|
};
|
|
223
289
|
continue;
|
|
224
290
|
}
|
|
225
|
-
let
|
|
226
|
-
if (
|
|
291
|
+
let o = e.contexts[i], s = e.values[i];
|
|
292
|
+
if (o.type === "node") {
|
|
227
293
|
yield {
|
|
228
294
|
type: "markup",
|
|
229
|
-
value:
|
|
230
|
-
index:
|
|
295
|
+
value: a,
|
|
296
|
+
index: i
|
|
231
297
|
}, t.markers && (yield {
|
|
232
298
|
type: "boundary-start",
|
|
233
|
-
value: `<!--elur-${
|
|
234
|
-
index:
|
|
299
|
+
value: `<!--elur-${i}-->`,
|
|
300
|
+
index: i
|
|
235
301
|
});
|
|
236
302
|
try {
|
|
237
|
-
let e = await
|
|
238
|
-
|
|
303
|
+
let e = await O(s);
|
|
304
|
+
D(t), yield* S(e, t);
|
|
239
305
|
} catch (e) {
|
|
240
306
|
throw t.onError?.(e, {
|
|
241
|
-
index:
|
|
307
|
+
index: i,
|
|
242
308
|
context: "node",
|
|
243
309
|
cause: e
|
|
244
310
|
}), e;
|
|
245
311
|
}
|
|
246
312
|
t.markers && (yield {
|
|
247
313
|
type: "boundary-end",
|
|
248
|
-
value: `<!--elur-end-${
|
|
249
|
-
index:
|
|
314
|
+
value: `<!--elur-end-${i}-->`,
|
|
315
|
+
index: i
|
|
250
316
|
});
|
|
251
317
|
continue;
|
|
252
318
|
}
|
|
253
|
-
let
|
|
254
|
-
if (
|
|
255
|
-
t.markers ? yield {
|
|
319
|
+
let c = k(o), l = a.slice(0, -c);
|
|
320
|
+
if (o.hadOpenQuote && (r[i + 1] = 1), o.type === "event") {
|
|
321
|
+
t.markers && !n ? yield {
|
|
256
322
|
type: "markup",
|
|
257
|
-
value: `${
|
|
258
|
-
index:
|
|
323
|
+
value: `${l}${/\s$/.test(l) ? "" : " "}data-elur-e-${i}="${j(o.eventName)}"`,
|
|
324
|
+
index: i
|
|
259
325
|
} : yield {
|
|
260
326
|
type: "markup",
|
|
261
|
-
value:
|
|
262
|
-
index:
|
|
327
|
+
value: l.replace(/\s+$/, ""),
|
|
328
|
+
index: i
|
|
263
329
|
};
|
|
264
330
|
continue;
|
|
265
331
|
}
|
|
266
332
|
yield {
|
|
267
333
|
type: "markup",
|
|
268
|
-
value:
|
|
269
|
-
index:
|
|
334
|
+
value: l,
|
|
335
|
+
index: i
|
|
270
336
|
};
|
|
271
|
-
let
|
|
272
|
-
if (
|
|
273
|
-
let e =
|
|
337
|
+
let u = await O(s);
|
|
338
|
+
if (D(t), o.attrName !== "ref" && u != null && u !== !1) {
|
|
339
|
+
let e = o.url ? p(String(u)) : String(u);
|
|
274
340
|
yield {
|
|
275
341
|
type: "markup",
|
|
276
|
-
value: `${/\s$/.test(
|
|
277
|
-
index:
|
|
342
|
+
value: `${/\s$/.test(l) ? "" : " "}${o.attrName}="${j(e)}"`,
|
|
343
|
+
index: i
|
|
278
344
|
};
|
|
279
345
|
}
|
|
280
|
-
t.markers && (yield {
|
|
346
|
+
t.markers && !n && (yield {
|
|
281
347
|
type: "markup",
|
|
282
|
-
value: ` data-elur-a-${
|
|
283
|
-
index:
|
|
348
|
+
value: ` data-elur-a-${i}="${j(o.attrName)}"`,
|
|
349
|
+
index: i
|
|
284
350
|
});
|
|
285
351
|
}
|
|
286
352
|
}
|
|
287
|
-
async function
|
|
353
|
+
async function E(e, t) {
|
|
288
354
|
let n = "";
|
|
289
|
-
for await (let r of
|
|
355
|
+
for await (let r of S(e, t)) n += r.value;
|
|
290
356
|
return n;
|
|
291
357
|
}
|
|
292
|
-
function
|
|
358
|
+
function D(e) {
|
|
293
359
|
if (e.signal?.aborted) throw e.signal.reason ?? new DOMException("Render aborted", "AbortError");
|
|
294
360
|
}
|
|
295
|
-
async function
|
|
296
|
-
|
|
297
|
-
|
|
361
|
+
async function O(n) {
|
|
362
|
+
if (n instanceof e) return n.peek();
|
|
363
|
+
if (i(n)) return t(n.get);
|
|
364
|
+
let r = typeof n == "function" ? n() : n;
|
|
365
|
+
return r instanceof Promise ? await r : r;
|
|
298
366
|
}
|
|
299
|
-
function
|
|
367
|
+
function k(e) {
|
|
300
368
|
return e.type === "event" ? `@${e.modifiers.length ? `${e.eventName}.${e.modifiers.join(".")}` : e.eventName}=`.length + +!!e.hadOpenQuote : `${e.attrName}=`.length + +!!e.hadOpenQuote;
|
|
301
369
|
}
|
|
302
|
-
function
|
|
370
|
+
function A(e) {
|
|
303
371
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
304
372
|
}
|
|
305
|
-
function
|
|
306
|
-
return
|
|
373
|
+
function j(e) {
|
|
374
|
+
return A(e).replace(/"/g, """);
|
|
307
375
|
}
|
|
308
376
|
//#endregion
|
|
309
|
-
export {
|
|
377
|
+
export { v as createServerRenderScope, x as renderToChunks, b as renderToString };
|
|
310
378
|
|
|
311
379
|
//# sourceMappingURL=server.js.map
|