@torpor/view 1.0.3 → 1.1.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/ssr.mjs CHANGED
@@ -21,14 +21,124 @@ function formatServerText(value) {
21
21
  return formatText(value).replace(/[&<>]/g, (c) => ESCAPABLE[c]);
22
22
  }
23
23
  //#endregion
24
- //#region src/ssr/$serverAsync.ts
24
+ //#region src/ssr/serverAwaitState.ts
25
25
  /**
26
- * Server no-op for the client-side `$async` getter primitive. Server renders
27
- * are synchronous, so an async value never resolves during SSR — `@await`
26
+ * The sentinel thrown when the render pass hits a boundary state that the
27
+ * collect pass didn't create (or a cursor that ran past the recorded reads).
28
+ * Only this error degrades the boundary; real render errors propagate.
29
+ */
30
+ var ServerAwaitMisaligned = class extends Error {
31
+ constructor() {
32
+ super("Server await render pass did not match the collect pass");
33
+ }
34
+ };
35
+ /** The innermost active server await state, or null outside any. */
36
+ let current = null;
37
+ /**
38
+ * Runs `fn` with `state` as the current server await state. `fn` may be sync
39
+ * or async; the pointer is restored when it settles. Because the pointer is
40
+ * only read synchronously, interleaved async renders restore it correctly.
41
+ */
42
+ async function withServerAwait(state, fn) {
43
+ const previous = current;
44
+ current = state;
45
+ try {
46
+ return await fn();
47
+ } finally {
48
+ current = previous;
49
+ }
50
+ }
51
+ /** The current server await state, or null. Only read synchronously. */
52
+ function currentServerAwait() {
53
+ return current;
54
+ }
55
+ /** Creates a fresh state for one boundary (or component flush root). */
56
+ function newServerAwaitState() {
57
+ return {
58
+ phase: "collect",
59
+ promises: [],
60
+ cursor: 0,
61
+ renderReads: 0,
62
+ clientReads: 0,
63
+ children: /* @__PURE__ */ new Map(),
64
+ counters: /* @__PURE__ */ new Map(),
65
+ degraded: false,
66
+ isRoot: false,
67
+ sentinels: /* @__PURE__ */ new Map()
68
+ };
69
+ }
70
+ /**
71
+ * The occurrence key for a nested boundary call site: `"<id>:<n>"`. The
72
+ * counter lives on the enclosing state and resets each pass, so the collect
73
+ * and render passes derive identical key sequences.
74
+ */
75
+ function childKey(state, id) {
76
+ const n = state.counters.get(id) ?? 0;
77
+ state.counters.set(id, n + 1);
78
+ return `${id}:${n}`;
79
+ }
80
+ /**
81
+ * Server counterpart of the client-side `$async` getter primitive.
82
+ *
83
+ * Without options (the default), this is a no-op stub: server renders are
84
+ * synchronous, an async value never resolves during SSR, and `@await`
28
85
  * boundaries render their `with` branch and never read the getter. The stub
29
86
  * exists so server builds importing `$async` don't emit a dangling import.
87
+ * A read inside a boundary's render pass is still recorded, so the boundary
88
+ * degrades to the `with` branch + client fetch instead of shipping content
89
+ * that would suspend on the client.
90
+ *
91
+ * With `{ source: "server" }` the getter participates in the server's
92
+ * collect/render pass (ASYNC.md → "Server rendering"):
93
+ *
94
+ * - **Collect pass** — calls the thunk (starting the fetch) and records the
95
+ * promise on the enclosing boundary, so sibling reads start in one wave.
96
+ * Returns `undefined`; the speculative pass's output is discarded.
97
+ * - **Render pass** — returns the settled value from the recorded promise at
98
+ * the same position in read order, without calling the thunk again. A
99
+ * rejection is re-thrown here so `@try`/`@error` handles it like any other
100
+ * render error. Running past the recorded reads throws a sentinel that
101
+ * degrades the boundary (the render pass no longer matches the collect
102
+ * pass, so the shipped HTML can't be trusted).
103
+ *
104
+ * Outside any `@await` boundary (including in a `with` branch) a
105
+ * `source: "server"` read returns `undefined` without fetching — the same
106
+ * undefined-then-recover contract the client has for un-boundaried reads.
30
107
  */
31
- function $serverAsync(_fn) {}
108
+ function $serverAsync(fn, options) {
109
+ const state = currentServerAwait();
110
+ if (state === null || state.isRoot || options?.source !== "server") {
111
+ if (state !== null && !state.isRoot && state.phase === "render") state.clientReads++;
112
+ return;
113
+ }
114
+ if (state.phase === "collect") {
115
+ const entry = {
116
+ promise: fn(),
117
+ timeout: options.timeout ?? 5e3
118
+ };
119
+ entry.promise.then((value) => {
120
+ entry.result = {
121
+ ok: true,
122
+ value
123
+ };
124
+ }, (error) => {
125
+ entry.result = {
126
+ ok: false,
127
+ error
128
+ };
129
+ });
130
+ state.promises.push(entry);
131
+ return;
132
+ }
133
+ const index = state.cursor;
134
+ if (index >= state.promises.length) throw new ServerAwaitMisaligned();
135
+ state.cursor++;
136
+ state.renderReads++;
137
+ const result = state.promises[index].result;
138
+ if (result === void 0) throw new ServerAwaitMisaligned();
139
+ if (result.ok) return result.value;
140
+ throw result.error;
141
+ }
32
142
  //#endregion
33
143
  //#region src/ssr/$serverBatch.ts
34
144
  function $serverBatch(fn) {
@@ -95,7 +205,183 @@ function $serverUnwrap(object) {
95
205
  function $serverWatch(object) {
96
206
  return object;
97
207
  }
208
+ /**
209
+ * Renders a component's (or a degraded boundary's `with` branch's) markup
210
+ * with a fresh flush root as the enclosing await state, then substitutes any
211
+ * boundary sentinels with their final HTML.
212
+ *
213
+ * Boundaries created during the render stash their lifecycle promise under a
214
+ * sentinel comment and return the sentinel immediately, so the render itself
215
+ * never blocks on a fetch — every `source: "server"` read in the render
216
+ * starts in the same wave. Substitution awaits the stashed promises at the
217
+ * end, which is the only point an async component render actually waits.
218
+ *
219
+ * On the client this has no counterpart: `render` here is the compiled
220
+ * component body closure that the generated component function returns.
221
+ */
222
+ async function serverFlush(render) {
223
+ const state = newServerAwaitState();
224
+ state.isRoot = true;
225
+ return substituteSentinels(await withServerAwait(state, render), state);
226
+ }
227
+ /**
228
+ * Renders a degraded boundary's `with` branch inside its own flush root, so
229
+ * a `with` branch containing its own `@await` boundaries still resolves
230
+ * them, then wraps it in the boundary's hydration markers. The `with` branch
231
+ * must not start server fetches for its own reads — the flush root isn't a
232
+ * recording context.
233
+ */
234
+ async function renderWithBranch(renderWith) {
235
+ const html = await serverFlush(async () => {
236
+ if (renderWith === null) return {
237
+ body: "",
238
+ head: ""
239
+ };
240
+ return renderWith();
241
+ });
242
+ return {
243
+ body: `<![>${html.body}<!]><!>`,
244
+ head: html.head
245
+ };
246
+ }
247
+ /**
248
+ * Replaces every sentinel the state stashed with its boundary's final HTML.
249
+ * Boundary head tags are appended to the head (they hoist into the document
250
+ * head regardless of where the boundary sits in the body). Any sentinel left
251
+ * over means a boundary's state was lost — a bug, not a degradation path, so
252
+ * it throws.
253
+ */
254
+ async function substituteSentinels(result, state) {
255
+ let { body, head } = result;
256
+ for (const [sentinel, promise] of state.sentinels) {
257
+ const html = await promise;
258
+ body = body.split(sentinel).join(html.body);
259
+ head += html.head;
260
+ }
261
+ if (body.includes("<!--t-aw:") || head.includes("<!--t-aw:")) throw new Error("Unsubstituted async boundary sentinel — boundary state was lost");
262
+ return {
263
+ body,
264
+ head
265
+ };
266
+ }
267
+ //#endregion
268
+ //#region src/ssr/runServerAwait.ts
269
+ let sentinelCount = 0;
270
+ function nextSentinel() {
271
+ return `<!--t-aw:${sentinelCount++}-->`;
272
+ }
273
+ /**
274
+ * Renders an `@await` boundary on the server (compiled as `t_await_server`).
275
+ *
276
+ * The generated code calls this for every `@await`, passing the boundary's
277
+ * site id, a closure that renders the content branch, and one that renders
278
+ * the `with` branch. It always returns a `{ body, head }` pair to append:
279
+ *
280
+ * - **Inside a boundary's render pass** — this boundary was already started
281
+ * during the collect pass; its body/head is the finished HTML (awaited if
282
+ * still in flight). A missing entry means the render pass doesn't match
283
+ * the collect pass, which degrades the enclosing boundary.
284
+ * - **Inside a collect pass or a component flush** — start the full
285
+ * lifecycle (collect, settle, render) without blocking the enclosing
286
+ * render, and return a sentinel comment as the body. Sibling reads and
287
+ * nested boundaries keep rendering, so every fetch in the pass starts in
288
+ * one wave. The sentinel is substituted later: by the enclosing boundary's
289
+ * render pass (which re-invokes this helper and awaits the finished HTML),
290
+ * or by the component flush (which replaces top-level sentinels directly).
291
+ *
292
+ * The lifecycle: render content once to start the `source: "server"` fetches
293
+ * (discarding the output), wait for them with a per-getter timeout, then
294
+ * render again with the settled values. The second pass ships wrapped in
295
+ * hydration markers plus a `<!--t-await:...-->` comment carrying the values
296
+ * for the client's `$async` hydration path. Any instability — timeout, a
297
+ * render pass that reads a different set of getters, a client-fetch read —
298
+ * degrades to the `with` branch + client fetch, exactly the pre-`source`
299
+ * behavior.
300
+ *
301
+ * @param id The boundary's site id (unique per `@await` in the component)
302
+ * @param renderContent Renders the content branch (may read `$async` getters)
303
+ * @param renderWith Renders the `with` branch, or null for empty
304
+ */
305
+ function runServerAwait(id, renderContent, renderWith) {
306
+ const parent = currentServerAwait();
307
+ if (parent !== null && parent.phase === "render") {
308
+ const cached = parent.children.get(childKey(parent, id));
309
+ if (cached === void 0) throw new ServerAwaitMisaligned();
310
+ return cached;
311
+ }
312
+ const final = renderBoundary(newServerAwaitState(), renderContent, renderWith);
313
+ const sentinel = nextSentinel();
314
+ if (parent !== null) {
315
+ if (parent.isRoot) parent.sentinels.set(sentinel, final);
316
+ else parent.children.set(childKey(parent, id), final);
317
+ }
318
+ return {
319
+ body: sentinel,
320
+ head: ""
321
+ };
322
+ }
323
+ /**
324
+ * The full lifecycle for one boundary: speculative collect pass, settle, and
325
+ * resolved render pass. Runs concurrently with the enclosing render; the
326
+ * returned promise resolves to the boundary's final HTML.
327
+ */
328
+ async function renderBoundary(state, renderContent, renderWith) {
329
+ await withServerAwait(state, renderContent).catch(() => {});
330
+ if (state.promises.length === 0) return renderWithBranch(renderWith);
331
+ const timeout = Math.max(...state.promises.map((entry) => entry.timeout));
332
+ let degraded = await Promise.race([Promise.all(state.promises.map((entry) => entry.promise.then(() => true, () => true))).then(() => true, () => true), new Promise((resolve) => setTimeout(resolve, timeout, false))]) === false;
333
+ let content;
334
+ if (!degraded) {
335
+ state.phase = "render";
336
+ state.cursor = 0;
337
+ state.renderReads = 0;
338
+ state.clientReads = 0;
339
+ state.counters.clear();
340
+ try {
341
+ content = await withServerAwait(state, renderContent);
342
+ if (state.cursor !== state.promises.length || state.clientReads > 0) degraded = true;
343
+ } catch {
344
+ degraded = true;
345
+ }
346
+ }
347
+ if (degraded || content === void 0) {
348
+ state.degraded = true;
349
+ try {
350
+ return await renderWithBranch(renderWith);
351
+ } catch {
352
+ return {
353
+ body: "<![><!]><!>",
354
+ head: ""
355
+ };
356
+ }
357
+ }
358
+ const values = [];
359
+ for (let i = 0; i < state.cursor; i++) {
360
+ const result = state.promises[i].result;
361
+ if (result === void 0) {
362
+ degraded = true;
363
+ break;
364
+ }
365
+ values.push(result.ok ? result.value : void 0);
366
+ }
367
+ if (degraded) {
368
+ state.degraded = true;
369
+ return renderWithBranch(renderWith);
370
+ }
371
+ return {
372
+ body: `<![>${content.body}<!]><!>${payloadComment(values)}`,
373
+ head: content.head
374
+ };
375
+ }
376
+ /**
377
+ * The `<!--t-await:...-->` comment carrying the boundary's resolved values,
378
+ * in read order, for the client's `$async` hydration path. `-->` inside the
379
+ * JSON is escaped so the comment can't terminate early.
380
+ */
381
+ function payloadComment(values) {
382
+ return `<!--t-await:${JSON.stringify(values).replaceAll("-->", "--\\u003E")}-->`;
383
+ }
98
384
  //#endregion
99
- export { $serverAsync as $async, $serverBatch as $batch, $serverBind as $bind, $serverCache as $cache, $serverOnmount as $onmount, $serverPeek as $peek, $serverPending as $pending, $serverRefresh as $refresh, $serverRun as $run, $serverStream as $stream, $serverUnwrap as $unwrap, $serverWatch as $watch, fromElement, fromServer, fromWebSocket, formatAttributeText as t_attr, buildClasses as t_class, formatServerText as t_fmt, buildStyles as t_style };
385
+ export { $serverAsync as $async, $serverBatch as $batch, $serverBind as $bind, $serverCache as $cache, $serverOnmount as $onmount, $serverPeek as $peek, $serverPending as $pending, $serverRefresh as $refresh, $serverRun as $run, $serverStream as $stream, $serverUnwrap as $unwrap, $serverWatch as $watch, fromElement, fromServer, fromWebSocket, formatAttributeText as t_attr, runServerAwait as t_await_server, buildClasses as t_class, formatServerText as t_fmt, serverFlush as t_server_flush, buildStyles as t_style };
100
386
 
101
387
  //# sourceMappingURL=ssr.mjs.map
package/dist/ssr.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ssr.mjs","names":[],"sources":["../src/render/formatAttributeText.ts","../src/ssr/formatText.ts","../src/ssr/$serverAsync.ts","../src/ssr/$serverBatch.ts","../src/ssr/$serverBind.ts","../src/ssr/$serverCache.ts","../src/ssr/$serverOnmount.ts","../src/ssr/$serverPeek.ts","../src/ssr/$serverPending.ts","../src/ssr/$serverRefresh.ts","../src/ssr/$serverRun.ts","../src/ssr/$serverStream.ts","../src/ssr/$serverUnwrap.ts","../src/ssr/$serverWatch.ts"],"sourcesContent":["export default function formatAttributeText(value: any): string {\n\treturn (value ?? \"\").toString().replaceAll('\"', \"&quot;\");\n}\n","import formatText from \"../render/formatText\";\n\nconst ESCAPABLE: Record<string, string> = {\n\t\"&\": \"&amp;\",\n\t\"<\": \"&lt;\",\n\t\">\": \"&gt;\",\n};\n\n/**\n * Formats a text value for inclusion in server-rendered HTML.\n *\n * Unlike the client version (which assigns to `textContent` and so needs no\n * escaping), the server interpolates values into an HTML string, so the\n * characters that would otherwise be parsed as markup are escaped here.\n */\nexport default function formatServerText(value: any): string {\n\treturn formatText(value).replace(/[&<>]/g, (c) => ESCAPABLE[c]);\n}\n","/**\n * Server no-op for the client-side `$async` getter primitive. Server renders\n * are synchronous, so an async value never resolves during SSR — `@await`\n * boundaries render their `with` branch and never read the getter. The stub\n * exists so server builds importing `$async` don't emit a dangling import.\n */\nexport default function $serverAsync<T>(_fn: () => Promise<T>): T {\n\treturn undefined as T;\n}\n","export default function $serverBatch<T>(fn: () => T): T {\n\treturn fn();\n}\n","/**\n * Server no-op for the client-side `$bind` two-way sync primitive. Two-way\n * binding is a client runtime feature — there are no reactive updates during\n * SSR, so there is nothing to sync. The stub exists so server builds\n * importing `$bind` don't emit a dangling import.\n */\nexport default function $serverBind(\n\t_state: Record<PropertyKey, any>,\n\t_props: Record<PropertyKey, any> | undefined,\n\t..._keys: (string | string[])[]\n): void {}\n","export default function $serverCache<T>(fn: () => T): T {\n\treturn fn();\n}\n","import type Cleanup from \"../types/Cleanup\";\n\nexport default function $serverOnmount(_fn: () => Cleanup | void): void {}\n","export default function $serverPeek<T>(fn: () => T): T {\n\treturn fn();\n}\n","/**\n * Server no-op for the client-side `$pending` query. Nothing is ever pending\n * during a synchronous SSR render, so the query is always `false`. The stub\n * exists so server builds importing `$pending` don't emit a dangling import.\n */\nexport default function $serverPending(_fn: () => any): boolean {\n\treturn false;\n}\n","/**\n * Server no-op for the client-side `$refresh` primitive. A refresh is an\n * imperative action that never runs during SSR. The stub exists so server\n * builds importing `$refresh` don't emit a dangling import.\n */\nexport default function $serverRefresh(_fn: () => any): void {}\n","import type Cleanup from \"../types/Cleanup\";\n\nexport default function $serverRun(_fn: () => Cleanup | void): void {}\n","import type StreamSource from \"../types/StreamSource\";\n\n/**\n * Server stub for `$stream` — external sources are never subscribed to\n * during a server render. The subscription starts when the component is\n * mounted on the client.\n */\nexport default function $serverStream<T>(\n\t_source: StreamSource<T>,\n\t_handler: (value: T) => void,\n\t_options?: { debounce?: number },\n): void {}\n","export default function $serverUnwrap<T extends Record<PropertyKey, any>>(object: T): T {\n\treturn object;\n}\n","export default function $serverWatch<T extends Record<PropertyKey, any>>(object: T): T {\n\treturn object;\n}\n"],"mappings":";;AAAA,SAAwB,oBAAoB,OAAoB;CAC/D,QAAQ,SAAS,GAAA,CAAI,SAAS,CAAC,CAAC,WAAW,MAAK,QAAQ;AACzD;;;ACAA,MAAM,YAAoC;CACzC,KAAK;CACL,KAAK;CACL,KAAK;AACN;;;;;;;;AASA,SAAwB,iBAAiB,OAAoB;CAC5D,OAAO,WAAW,KAAK,CAAC,CAAC,QAAQ,WAAW,MAAM,UAAU,EAAE;AAC/D;;;;;;;;;ACXA,SAAwB,aAAgB,KAA0B,CAElE;;;ACRA,SAAwB,aAAgB,IAAgB;CACvD,OAAO,GAAG;AACX;;;;;;;;;ACIA,SAAwB,YACvB,QACA,QACA,GAAG,OACI,CAAC;;;ACVT,SAAwB,aAAgB,IAAgB;CACvD,OAAO,GAAG;AACX;;;ACAA,SAAwB,eAAe,KAAiC,CAAC;;;ACFzE,SAAwB,YAAe,IAAgB;CACtD,OAAO,GAAG;AACX;;;;;;;;ACGA,SAAwB,eAAe,KAAyB;CAC/D,OAAO;AACR;;;;;;;;ACFA,SAAwB,eAAe,KAAsB,CAAC;;;ACH9D,SAAwB,WAAW,KAAiC,CAAC;;;;;;;;ACKrE,SAAwB,cACvB,SACA,UACA,UACO,CAAC;;;ACXT,SAAwB,cAAkD,QAAc;CACvF,OAAO;AACR;;;ACFA,SAAwB,aAAiD,QAAc;CACtF,OAAO;AACR"}
1
+ {"version":3,"file":"ssr.mjs","names":[],"sources":["../src/render/formatAttributeText.ts","../src/ssr/formatText.ts","../src/ssr/serverAwaitState.ts","../src/ssr/$serverAsync.ts","../src/ssr/$serverBatch.ts","../src/ssr/$serverBind.ts","../src/ssr/$serverCache.ts","../src/ssr/$serverOnmount.ts","../src/ssr/$serverPeek.ts","../src/ssr/$serverPending.ts","../src/ssr/$serverRefresh.ts","../src/ssr/$serverRun.ts","../src/ssr/$serverStream.ts","../src/ssr/$serverUnwrap.ts","../src/ssr/$serverWatch.ts","../src/ssr/serverSentinels.ts","../src/ssr/runServerAwait.ts"],"sourcesContent":["export default function formatAttributeText(value: any): string {\n\treturn (value ?? \"\").toString().replaceAll('\"', \"&quot;\");\n}\n","import formatText from \"../render/formatText\";\n\nconst ESCAPABLE: Record<string, string> = {\n\t\"&\": \"&amp;\",\n\t\"<\": \"&lt;\",\n\t\">\": \"&gt;\",\n};\n\n/**\n * Formats a text value for inclusion in server-rendered HTML.\n *\n * Unlike the client version (which assigns to `textContent` and so needs no\n * escaping), the server interpolates values into an HTML string, so the\n * characters that would otherwise be parsed as markup are escaped here.\n */\nexport default function formatServerText(value: any): string {\n\treturn formatText(value).replace(/[&<>]/g, (c) => ESCAPABLE[c]);\n}\n","/**\n * The per-request state for a `source: \"server\"` async render. Server awaits\n * are orchestrated by `t_server_flush` (the component's render) and\n * `t_await_server` (each `@await` boundary), which coordinate through the\n * module-level `current` pointer:\n *\n * - **Collect phase** — the boundary's content is rendered speculatively (a\n * discarded pass) purely to invoke its getters. Each `source: \"server\"`\n * getter read calls its thunk (starting the fetch) and records the promise\n * here. Sibling reads in the same pass therefore start in one wave, exactly\n * like the client's speculative render.\n * - **Render phase** — after the recorded promises settle, the content is\n * rendered again; getter reads consume the settled values through a cursor\n * in record order. The second pass's output is what ships.\n *\n * `current` is only ever read synchronously (inside a helper's render\n * segments), so concurrent requests interleave safely: each helper captures\n * and restores the pointer around its awaits.\n */\nexport default interface ServerAwaitState {\n\t/** \"collect\" during the speculative pass, \"render\" during the resolved pass. */\n\tphase: \"collect\" | \"render\";\n\n\t/**\n\t * Recorded `source: \"server\"` reads, in read order. Each entry holds the\n\t * promise, its per-getter timeout, and — once settled — the fulfilled\n\t * value or rejection.\n\t */\n\tpromises: ServerPromiseEntry[];\n\n\t/** How many values the render phase has consumed (the payload cursor). */\n\tcursor: number;\n\n\t/**\n\t * `source: \"server\"` reads made during the render pass. Pass 1 and pass 2\n\t * must read the same getters in the same order; a count mismatch at the\n\t * end of pass 2 means the render isn't stable, so the boundary degrades\n\t * to the `with` branch + client fetch.\n\t */\n\trenderReads: number;\n\n\t/**\n\t * Client-fetch `$async` reads made during the render pass (the server\n\t * stub's no-option calls). Any of these would suspend on the client, so a\n\t * boundary that touched one cannot ship resolved content — it degrades.\n\t */\n\tclientReads: number;\n\n\t/**\n\t * Nested boundary states created inside this boundary's collect pass,\n\t * keyed by `\"<site id>:<occurrence>\"`. The render pass re-invokes each\n\t * nested boundary in the same order, so it looks up the state by the same\n\t * key and awaits its final HTML instead of re-fetching.\n\t */\n\tchildren: Map<string, Promise<{ body: string; head: string }>>;\n\n\t/** Per-site occurrence counters, reset at the start of each pass. */\n\tcounters: Map<string, number>;\n\n\t/** Set when the boundary degrades to its `with` branch. */\n\tdegraded: boolean;\n\n\t/**\n\t * True for component flush roots. A flush root is a collect-phase context\n\t * but not a recording one: `source: \"server\"` reads outside any boundary\n\t * don't fetch. Boundaries created directly under the root stash their\n\t * final HTML here, keyed by the sentinel they returned.\n\t */\n\tisRoot: boolean;\n\n\t/**\n\t * Stashed boundary lifecycles keyed by sentinel comment, for substitution\n\t * at the end of the flush (or a degraded `with` branch's render). Only\n\t * used by flush roots.\n\t */\n\tsentinels: Map<string, Promise<{ body: string; head: string }>>;\n}\n\n/**\n * A recorded `source: \"server\"` read: the promise returned by the getter's\n * thunk, and the settled outcome once it arrives.\n */\nexport interface ServerPromiseEntry {\n\tpromise: Promise<any>;\n\ttimeout: number;\n\t/** Set by the settle handler: `{ ok: true, value }` or `{ ok: false, error }`. */\n\tresult?: { ok: true; value: any } | { ok: false; error: any };\n}\n\n/**\n * The sentinel thrown when the render pass hits a boundary state that the\n * collect pass didn't create (or a cursor that ran past the recorded reads).\n * Only this error degrades the boundary; real render errors propagate.\n */\nexport class ServerAwaitMisaligned extends Error {\n\tconstructor() {\n\t\tsuper(\"Server await render pass did not match the collect pass\");\n\t}\n}\n\n/** The innermost active server await state, or null outside any. */\nlet current: ServerAwaitState | null = null;\n\n/**\n * Runs `fn` with `state` as the current server await state. `fn` may be sync\n * or async; the pointer is restored when it settles. Because the pointer is\n * only read synchronously, interleaved async renders restore it correctly.\n */\nexport async function withServerAwait<T>(\n\tstate: ServerAwaitState | null,\n\tfn: () => T | Promise<T>,\n): Promise<T> {\n\tconst previous = current;\n\tcurrent = state;\n\ttry {\n\t\treturn await fn();\n\t} finally {\n\t\tcurrent = previous;\n\t}\n}\n\n/** The current server await state, or null. Only read synchronously. */\nexport function currentServerAwait(): ServerAwaitState | null {\n\treturn current;\n}\n\n/** Creates a fresh state for one boundary (or component flush root). */\nexport function newServerAwaitState(): ServerAwaitState {\n\treturn {\n\t\tphase: \"collect\",\n\t\tpromises: [],\n\t\tcursor: 0,\n\t\trenderReads: 0,\n\t\tclientReads: 0,\n\t\tchildren: new Map(),\n\t\tcounters: new Map(),\n\t\tdegraded: false,\n\t\tisRoot: false,\n\t\tsentinels: new Map(),\n\t};\n}\n\n/**\n * The occurrence key for a nested boundary call site: `\"<id>:<n>\"`. The\n * counter lives on the enclosing state and resets each pass, so the collect\n * and render passes derive identical key sequences.\n */\nexport function childKey(state: ServerAwaitState, id: string): string {\n\tconst n = state.counters.get(id) ?? 0;\n\tstate.counters.set(id, n + 1);\n\treturn `${id}:${n}`;\n}\n","import type AsyncOptions from \"../types/AsyncOptions\";\nimport {\n\tcurrentServerAwait,\n\tServerAwaitMisaligned,\n\ttype ServerPromiseEntry,\n} from \"./serverAwaitState\";\n\n/**\n * Default number of milliseconds a `source: \"server\"` read may take before\n * its boundary degrades to the `with` branch and the client fetches instead\n * (ASYNC.md → \"Server rendering\").\n */\nexport const SERVER_ASYNC_TIMEOUT = 5000;\n\n/**\n * Server counterpart of the client-side `$async` getter primitive.\n *\n * Without options (the default), this is a no-op stub: server renders are\n * synchronous, an async value never resolves during SSR, and `@await`\n * boundaries render their `with` branch and never read the getter. The stub\n * exists so server builds importing `$async` don't emit a dangling import.\n * A read inside a boundary's render pass is still recorded, so the boundary\n * degrades to the `with` branch + client fetch instead of shipping content\n * that would suspend on the client.\n *\n * With `{ source: \"server\" }` the getter participates in the server's\n * collect/render pass (ASYNC.md → \"Server rendering\"):\n *\n * - **Collect pass** — calls the thunk (starting the fetch) and records the\n * promise on the enclosing boundary, so sibling reads start in one wave.\n * Returns `undefined`; the speculative pass's output is discarded.\n * - **Render pass** — returns the settled value from the recorded promise at\n * the same position in read order, without calling the thunk again. A\n * rejection is re-thrown here so `@try`/`@error` handles it like any other\n * render error. Running past the recorded reads throws a sentinel that\n * degrades the boundary (the render pass no longer matches the collect\n * pass, so the shipped HTML can't be trusted).\n *\n * Outside any `@await` boundary (including in a `with` branch) a\n * `source: \"server\"` read returns `undefined` without fetching — the same\n * undefined-then-recover contract the client has for un-boundaried reads.\n */\nexport default function $serverAsync<T>(fn: () => Promise<T>, options?: AsyncOptions): T {\n\tconst state = currentServerAwait();\n\n\tif (state === null || state.isRoot || options?.source !== \"server\") {\n\t\tif (state !== null && !state.isRoot && state.phase === \"render\") {\n\t\t\t// A client-fetch read during a boundary's render pass: the client\n\t\t\t// will suspend on it, so the boundary can't ship resolved content\n\t\t\tstate.clientReads++;\n\t\t}\n\t\treturn undefined as T;\n\t}\n\n\tif (state.phase === \"collect\") {\n\t\tconst entry: ServerPromiseEntry = {\n\t\t\tpromise: fn(),\n\t\t\ttimeout: options.timeout ?? SERVER_ASYNC_TIMEOUT,\n\t\t};\n\t\t// Record the outcome as soon as it settles — this both captures the\n\t\t// value/error for the render pass and consumes the rejection, so a\n\t\t// boundary that degrades (timeout) or a superseded fetch can never\n\t\t// surface as an unhandled rejection\n\t\tentry.promise.then(\n\t\t\t(value) => {\n\t\t\t\tentry.result = { ok: true, value };\n\t\t\t},\n\t\t\t(error) => {\n\t\t\t\tentry.result = { ok: false, error };\n\t\t\t},\n\t\t);\n\t\tstate.promises.push(entry);\n\t\treturn undefined as T;\n\t}\n\n\t// Render pass: consume the recorded read at this position\n\tconst index = state.cursor;\n\tif (index >= state.promises.length) {\n\t\tthrow new ServerAwaitMisaligned();\n\t}\n\tstate.cursor++;\n\tstate.renderReads++;\n\tconst result = state.promises[index].result;\n\tif (result === undefined) {\n\t\t// Not settled — only possible when the boundary already blew its\n\t\t// timeout, which degrades before rendering; treat as misaligned\n\t\tthrow new ServerAwaitMisaligned();\n\t}\n\tif (result.ok) {\n\t\treturn result.value as T;\n\t}\n\tthrow result.error;\n}\n","export default function $serverBatch<T>(fn: () => T): T {\n\treturn fn();\n}\n","/**\n * Server no-op for the client-side `$bind` two-way sync primitive. Two-way\n * binding is a client runtime feature — there are no reactive updates during\n * SSR, so there is nothing to sync. The stub exists so server builds\n * importing `$bind` don't emit a dangling import.\n */\nexport default function $serverBind(\n\t_state: Record<PropertyKey, any>,\n\t_props: Record<PropertyKey, any> | undefined,\n\t..._keys: (string | string[])[]\n): void {}\n","export default function $serverCache<T>(fn: () => T): T {\n\treturn fn();\n}\n","import type Cleanup from \"../types/Cleanup\";\n\nexport default function $serverOnmount(_fn: () => Cleanup | void): void {}\n","export default function $serverPeek<T>(fn: () => T): T {\n\treturn fn();\n}\n","/**\n * Server no-op for the client-side `$pending` query. Nothing is ever pending\n * during a synchronous SSR render, so the query is always `false`. The stub\n * exists so server builds importing `$pending` don't emit a dangling import.\n */\nexport default function $serverPending(_fn: () => any): boolean {\n\treturn false;\n}\n","/**\n * Server no-op for the client-side `$refresh` primitive. A refresh is an\n * imperative action that never runs during SSR. The stub exists so server\n * builds importing `$refresh` don't emit a dangling import.\n */\nexport default function $serverRefresh(_fn: () => any): void {}\n","import type Cleanup from \"../types/Cleanup\";\n\nexport default function $serverRun(_fn: () => Cleanup | void): void {}\n","import type StreamSource from \"../types/StreamSource\";\n\n/**\n * Server stub for `$stream` — external sources are never subscribed to\n * during a server render. The subscription starts when the component is\n * mounted on the client.\n */\nexport default function $serverStream<T>(\n\t_source: StreamSource<T>,\n\t_handler: (value: T) => void,\n\t_options?: { debounce?: number },\n): void {}\n","export default function $serverUnwrap<T extends Record<PropertyKey, any>>(object: T): T {\n\treturn object;\n}\n","export default function $serverWatch<T extends Record<PropertyKey, any>>(object: T): T {\n\treturn object;\n}\n","import { newServerAwaitState, withServerAwait } from \"./serverAwaitState\";\nimport type ServerAwaitState from \"./serverAwaitState\";\n\n/** Comment prefix marking an unsubstituted boundary sentinel. */\nexport const SENTINEL_PREFIX = \"<!--t-aw:\";\n\n/** The body/head pair that server components and boundaries render into. */\nexport interface ServerHtml {\n\tbody: string;\n\thead: string;\n}\n\n/**\n * Renders a component's (or a degraded boundary's `with` branch's) markup\n * with a fresh flush root as the enclosing await state, then substitutes any\n * boundary sentinels with their final HTML.\n *\n * Boundaries created during the render stash their lifecycle promise under a\n * sentinel comment and return the sentinel immediately, so the render itself\n * never blocks on a fetch — every `source: \"server\"` read in the render\n * starts in the same wave. Substitution awaits the stashed promises at the\n * end, which is the only point an async component render actually waits.\n *\n * On the client this has no counterpart: `render` here is the compiled\n * component body closure that the generated component function returns.\n */\nexport async function serverFlush(render: () => Promise<ServerHtml>): Promise<ServerHtml> {\n\tconst state = newServerAwaitState();\n\tstate.isRoot = true;\n\tconst result = await withServerAwait(state, render);\n\treturn substituteSentinels(result, state);\n}\n\n/**\n * Renders a degraded boundary's `with` branch inside its own flush root, so\n * a `with` branch containing its own `@await` boundaries still resolves\n * them, then wraps it in the boundary's hydration markers. The `with` branch\n * must not start server fetches for its own reads — the flush root isn't a\n * recording context.\n */\nexport async function renderWithBranch(\n\trenderWith: (() => Promise<ServerHtml>) | null,\n): Promise<ServerHtml> {\n\tconst html = await serverFlush(async () => {\n\t\tif (renderWith === null) {\n\t\t\treturn { body: \"\", head: \"\" };\n\t\t}\n\t\treturn renderWith();\n\t});\n\treturn { body: `<![>${html.body}<!]><!>`, head: html.head };\n}\n\n/**\n * Replaces every sentinel the state stashed with its boundary's final HTML.\n * Boundary head tags are appended to the head (they hoist into the document\n * head regardless of where the boundary sits in the body). Any sentinel left\n * over means a boundary's state was lost — a bug, not a degradation path, so\n * it throws.\n */\nexport async function substituteSentinels(\n\tresult: ServerHtml,\n\tstate: ServerAwaitState,\n): Promise<ServerHtml> {\n\tlet { body, head } = result;\n\tfor (const [sentinel, promise] of state.sentinels) {\n\t\tconst html = await promise;\n\t\tbody = body.split(sentinel).join(html.body);\n\t\thead += html.head;\n\t}\n\tif (body.includes(SENTINEL_PREFIX) || head.includes(SENTINEL_PREFIX)) {\n\t\tthrow new Error(\"Unsubstituted async boundary sentinel — boundary state was lost\");\n\t}\n\treturn { body, head };\n}\n","import {\n\tchildKey,\n\tcurrentServerAwait,\n\tnewServerAwaitState,\n\tServerAwaitMisaligned,\n\twithServerAwait,\n} from \"./serverAwaitState\";\nimport type ServerAwaitState from \"./serverAwaitState\";\nimport { renderWithBranch } from \"./serverSentinels\";\n\nlet sentinelCount = 0;\n\nfunction nextSentinel(): string {\n\treturn `<!--t-aw:${sentinelCount++}-->`;\n}\n\n/**\n * Renders an `@await` boundary on the server (compiled as `t_await_server`).\n *\n * The generated code calls this for every `@await`, passing the boundary's\n * site id, a closure that renders the content branch, and one that renders\n * the `with` branch. It always returns a `{ body, head }` pair to append:\n *\n * - **Inside a boundary's render pass** — this boundary was already started\n * during the collect pass; its body/head is the finished HTML (awaited if\n * still in flight). A missing entry means the render pass doesn't match\n * the collect pass, which degrades the enclosing boundary.\n * - **Inside a collect pass or a component flush** — start the full\n * lifecycle (collect, settle, render) without blocking the enclosing\n * render, and return a sentinel comment as the body. Sibling reads and\n * nested boundaries keep rendering, so every fetch in the pass starts in\n * one wave. The sentinel is substituted later: by the enclosing boundary's\n * render pass (which re-invokes this helper and awaits the finished HTML),\n * or by the component flush (which replaces top-level sentinels directly).\n *\n * The lifecycle: render content once to start the `source: \"server\"` fetches\n * (discarding the output), wait for them with a per-getter timeout, then\n * render again with the settled values. The second pass ships wrapped in\n * hydration markers plus a `<!--t-await:...-->` comment carrying the values\n * for the client's `$async` hydration path. Any instability — timeout, a\n * render pass that reads a different set of getters, a client-fetch read —\n * degrades to the `with` branch + client fetch, exactly the pre-`source`\n * behavior.\n *\n * @param id The boundary's site id (unique per `@await` in the component)\n * @param renderContent Renders the content branch (may read `$async` getters)\n * @param renderWith Renders the `with` branch, or null for empty\n */\nexport default function runServerAwait(\n\tid: string,\n\trenderContent: () => Promise<{ body: string; head: string }>,\n\trenderWith: (() => Promise<{ body: string; head: string }>) | null,\n): { body: string; head: string } | Promise<{ body: string; head: string }> {\n\tconst parent = currentServerAwait();\n\n\tif (parent !== null && parent.phase === \"render\") {\n\t\t// The enclosing boundary is rendering its resolved pass: this nested\n\t\t// boundary was started during the collect pass, so reuse its result\n\t\tconst cached = parent.children.get(childKey(parent, id));\n\t\tif (cached === undefined) {\n\t\t\tthrow new ServerAwaitMisaligned();\n\t\t}\n\t\treturn cached;\n\t}\n\n\tconst state = newServerAwaitState();\n\tconst final = renderBoundary(state, renderContent, renderWith);\n\n\tconst sentinel = nextSentinel();\n\tif (parent !== null) {\n\t\tif (parent.isRoot) {\n\t\t\t// Top-level boundary: the component flush substitutes the sentinel\n\t\t\tparent.sentinels.set(sentinel, final);\n\t\t} else {\n\t\t\t// Nested boundary: the enclosing boundary's render pass looks this\n\t\t\t// up by occurrence key\n\t\t\tparent.children.set(childKey(parent, id), final);\n\t\t}\n\t}\n\t// The sentinel body is replaced by the finished content; the head tags a\n\t// resolved boundary renders are hoisted when it finishes\n\treturn { body: sentinel, head: \"\" };\n}\n\n/**\n * The full lifecycle for one boundary: speculative collect pass, settle, and\n * resolved render pass. Runs concurrently with the enclosing render; the\n * returned promise resolves to the boundary's final HTML.\n */\nasync function renderBoundary(\n\tstate: ServerAwaitState,\n\trenderContent: () => Promise<{ body: string; head: string }>,\n\trenderWith: (() => Promise<{ body: string; head: string }>) | null,\n): Promise<{ body: string; head: string }> {\n\t// Collect pass: render content speculatively to invoke the getters. Each\n\t// `source: \"server\"` read starts its fetch and is recorded; sibling reads\n\t// in this pass therefore start together. The output is discarded — reads\n\t// return undefined, so user markup that dereferences them may throw, and\n\t// a throw here costs nothing.\n\tawait withServerAwait(state, renderContent).catch(() => {\n\t\t// Expected when unresolved values are dereferenced; fetches already\n\t\t// started. Any other error resurfaces in the render pass below.\n\t});\n\n\tif (state.promises.length === 0) {\n\t\t// No server-source reads: nothing was (or can be) resolved here, so\n\t\t// ship the `with` branch and let the client fetch — the default SSR\n\t\t// behavior for client-fetch getters\n\t\treturn renderWithBranch(renderWith);\n\t}\n\n\t// Settle the recorded fetches. Each getter carries its own timeout; the\n\t// boundary waits for the longest, and a miss degrades the whole boundary\n\t// (content ships only when every read resolved)\n\tconst timeout = Math.max(...state.promises.map((entry) => entry.timeout));\n\tconst settled = await Promise.race([\n\t\tPromise.all(\n\t\t\tstate.promises.map((entry) =>\n\t\t\t\tentry.promise.then(\n\t\t\t\t\t() => true,\n\t\t\t\t\t() => true,\n\t\t\t\t),\n\t\t\t),\n\t\t).then(\n\t\t\t() => true,\n\t\t\t() => true,\n\t\t),\n\t\tnew Promise<false>((resolve) => setTimeout(resolve, timeout, false)),\n\t]);\n\n\t// Render pass: same reads, now consuming settled values through the\n\t// cursor. The pass must replay the collect pass exactly — a different\n\t// read count, an unknown nested boundary, or a client-fetch read all\n\t// mean the content can't be trusted, and the boundary degrades.\n\t//\n\t// A rejection (or any render error) also degrades: the boundary's\n\t// lifecycle runs detached from the enclosing render (which has already\n\t// moved on after the sentinel), so the error can't propagate to the\n\t// emitted `@try` positionally. Instead the with branch ships and the\n\t// client re-runs the getter, rejects there, and its `@try` renders the\n\t// catch branch — the same path a client-fetch error takes.\n\tlet degraded = settled === false;\n\tlet content: { body: string; head: string } | undefined;\n\tif (!degraded) {\n\t\tstate.phase = \"render\";\n\t\tstate.cursor = 0;\n\t\tstate.renderReads = 0;\n\t\tstate.clientReads = 0;\n\t\tstate.counters.clear();\n\t\ttry {\n\t\t\tcontent = await withServerAwait(state, renderContent);\n\t\t\tif (state.cursor !== state.promises.length || state.clientReads > 0) {\n\t\t\t\tdegraded = true;\n\t\t\t}\n\t\t} catch {\n\t\t\tdegraded = true;\n\t\t}\n\t}\n\n\tif (degraded || content === undefined) {\n\t\tstate.degraded = true;\n\t\ttry {\n\t\t\treturn await renderWithBranch(renderWith);\n\t\t} catch {\n\t\t\t// A with-branch render error can't be positioned either; ship an\n\t\t\t// empty boundary rather than failing the whole response\n\t\t\treturn { body: \"<![><!]><!>\", head: \"\" };\n\t\t}\n\t}\n\n\t// Ship the resolved content with the embedded values for hydration.\n\t// Rejections never reach here — the render pass consumes them and\n\t// degrades — but guard anyway so a bad entry can't ship as `undefined`\n\tconst values: any[] = [];\n\tfor (let i = 0; i < state.cursor; i++) {\n\t\tconst result = state.promises[i].result;\n\t\tif (result === undefined) {\n\t\t\tdegraded = true;\n\t\t\tbreak;\n\t\t}\n\t\tvalues.push(result.ok ? result.value : undefined);\n\t}\n\tif (degraded) {\n\t\tstate.degraded = true;\n\t\treturn renderWithBranch(renderWith);\n\t}\n\treturn {\n\t\tbody: `${\"<![>\"}${content.body}${\"<!]><!>\"}${payloadComment(values)}`,\n\t\thead: content.head,\n\t};\n}\n\n/**\n * The `<!--t-await:...-->` comment carrying the boundary's resolved values,\n * in read order, for the client's `$async` hydration path. `-->` inside the\n * JSON is escaped so the comment can't terminate early.\n */\nfunction payloadComment(values: any[]): string {\n\tconst json = JSON.stringify(values).replaceAll(\"-->\", \"--\\\\u003E\");\n\treturn `<!--t-await:${json}-->`;\n}\n"],"mappings":";;AAAA,SAAwB,oBAAoB,OAAoB;CAC/D,QAAQ,SAAS,GAAA,CAAI,SAAS,CAAC,CAAC,WAAW,MAAK,QAAQ;AACzD;;;ACAA,MAAM,YAAoC;CACzC,KAAK;CACL,KAAK;CACL,KAAK;AACN;;;;;;;;AASA,SAAwB,iBAAiB,OAAoB;CAC5D,OAAO,WAAW,KAAK,CAAC,CAAC,QAAQ,WAAW,MAAM,UAAU,EAAE;AAC/D;;;;;;;;AC6EA,IAAa,wBAAb,cAA2C,MAAM;CAChD,cAAc;EACb,MAAM,yDAAyD;CAChE;AACD;;AAGA,IAAI,UAAmC;;;;;;AAOvC,eAAsB,gBACrB,OACA,IACa;CACb,MAAM,WAAW;CACjB,UAAU;CACV,IAAI;EACH,OAAO,MAAM,GAAG;CACjB,UAAU;EACT,UAAU;CACX;AACD;;AAGA,SAAgB,qBAA8C;CAC7D,OAAO;AACR;;AAGA,SAAgB,sBAAwC;CACvD,OAAO;EACN,OAAO;EACP,UAAU,CAAC;EACX,QAAQ;EACR,aAAa;EACb,aAAa;EACb,0BAAU,IAAI,IAAI;EAClB,0BAAU,IAAI,IAAI;EAClB,UAAU;EACV,QAAQ;EACR,2BAAW,IAAI,IAAI;CACpB;AACD;;;;;;AAOA,SAAgB,SAAS,OAAyB,IAAoB;CACrE,MAAM,IAAI,MAAM,SAAS,IAAI,EAAE,KAAK;CACpC,MAAM,SAAS,IAAI,IAAI,IAAI,CAAC;CAC5B,OAAO,GAAG,GAAG,GAAG;AACjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC7GA,SAAwB,aAAgB,IAAsB,SAA2B;CACxF,MAAM,QAAQ,mBAAmB;CAEjC,IAAI,UAAU,QAAQ,MAAM,UAAU,SAAS,WAAW,UAAU;EACnE,IAAI,UAAU,QAAQ,CAAC,MAAM,UAAU,MAAM,UAAU,UAGtD,MAAM;EAEP;CACD;CAEA,IAAI,MAAM,UAAU,WAAW;EAC9B,MAAM,QAA4B;GACjC,SAAS,GAAG;GACZ,SAAS,QAAQ,WAAA;EAClB;EAKA,MAAM,QAAQ,MACZ,UAAU;GACV,MAAM,SAAS;IAAE,IAAI;IAAM;GAAM;EAClC,IACC,UAAU;GACV,MAAM,SAAS;IAAE,IAAI;IAAO;GAAM;EACnC,CACD;EACA,MAAM,SAAS,KAAK,KAAK;EACzB;CACD;CAGA,MAAM,QAAQ,MAAM;CACpB,IAAI,SAAS,MAAM,SAAS,QAC3B,MAAM,IAAI,sBAAsB;CAEjC,MAAM;CACN,MAAM;CACN,MAAM,SAAS,MAAM,SAAS,MAAM,CAAC;CACrC,IAAI,WAAW,KAAA,GAGd,MAAM,IAAI,sBAAsB;CAEjC,IAAI,OAAO,IACV,OAAO,OAAO;CAEf,MAAM,OAAO;AACd;;;AC5FA,SAAwB,aAAgB,IAAgB;CACvD,OAAO,GAAG;AACX;;;;;;;;;ACIA,SAAwB,YACvB,QACA,QACA,GAAG,OACI,CAAC;;;ACVT,SAAwB,aAAgB,IAAgB;CACvD,OAAO,GAAG;AACX;;;ACAA,SAAwB,eAAe,KAAiC,CAAC;;;ACFzE,SAAwB,YAAe,IAAgB;CACtD,OAAO,GAAG;AACX;;;;;;;;ACGA,SAAwB,eAAe,KAAyB;CAC/D,OAAO;AACR;;;;;;;;ACFA,SAAwB,eAAe,KAAsB,CAAC;;;ACH9D,SAAwB,WAAW,KAAiC,CAAC;;;;;;;;ACKrE,SAAwB,cACvB,SACA,UACA,UACO,CAAC;;;ACXT,SAAwB,cAAkD,QAAc;CACvF,OAAO;AACR;;;ACFA,SAAwB,aAAiD,QAAc;CACtF,OAAO;AACR;;;;;;;;;;;;;;;ACwBA,eAAsB,YAAY,QAAwD;CACzF,MAAM,QAAQ,oBAAoB;CAClC,MAAM,SAAS;CAEf,OAAO,oBAAoB,MADN,gBAAgB,OAAO,MAAM,GACf,KAAK;AACzC;;;;;;;;AASA,eAAsB,iBACrB,YACsB;CACtB,MAAM,OAAO,MAAM,YAAY,YAAY;EAC1C,IAAI,eAAe,MAClB,OAAO;GAAE,MAAM;GAAI,MAAM;EAAG;EAE7B,OAAO,WAAW;CACnB,CAAC;CACD,OAAO;EAAE,MAAM,OAAO,KAAK,KAAK;EAAU,MAAM,KAAK;CAAK;AAC3D;;;;;;;;AASA,eAAsB,oBACrB,QACA,OACsB;CACtB,IAAI,EAAE,MAAM,SAAS;CACrB,KAAK,MAAM,CAAC,UAAU,YAAY,MAAM,WAAW;EAClD,MAAM,OAAO,MAAM;EACnB,OAAO,KAAK,MAAM,QAAQ,CAAC,CAAC,KAAK,KAAK,IAAI;EAC1C,QAAQ,KAAK;CACd;CACA,IAAI,KAAK,SAAA,WAAwB,KAAK,KAAK,SAAA,WAAwB,GAClE,MAAM,IAAI,MAAM,iEAAiE;CAElF,OAAO;EAAE;EAAM;CAAK;AACrB;;;AC/DA,IAAI,gBAAgB;AAEpB,SAAS,eAAuB;CAC/B,OAAO,YAAY,gBAAgB;AACpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,SAAwB,eACvB,IACA,eACA,YAC2E;CAC3E,MAAM,SAAS,mBAAmB;CAElC,IAAI,WAAW,QAAQ,OAAO,UAAU,UAAU;EAGjD,MAAM,SAAS,OAAO,SAAS,IAAI,SAAS,QAAQ,EAAE,CAAC;EACvD,IAAI,WAAW,KAAA,GACd,MAAM,IAAI,sBAAsB;EAEjC,OAAO;CACR;CAGA,MAAM,QAAQ,eADA,oBACmB,GAAG,eAAe,UAAU;CAE7D,MAAM,WAAW,aAAa;CAC9B,IAAI,WAAW,MAAM;EACpB,IAAI,OAAO,QAEV,OAAO,UAAU,IAAI,UAAU,KAAK;OAIpC,OAAO,SAAS,IAAI,SAAS,QAAQ,EAAE,GAAG,KAAK;CAEjD;CAGA,OAAO;EAAE,MAAM;EAAU,MAAM;CAAG;AACnC;;;;;;AAOA,eAAe,eACd,OACA,eACA,YAC0C;CAM1C,MAAM,gBAAgB,OAAO,aAAa,CAAC,CAAC,YAAY,CAGxD,CAAC;CAED,IAAI,MAAM,SAAS,WAAW,GAI7B,OAAO,iBAAiB,UAAU;CAMnC,MAAM,UAAU,KAAK,IAAI,GAAG,MAAM,SAAS,KAAK,UAAU,MAAM,OAAO,CAAC;CA2BxE,IAAI,WAAW,MA1BO,QAAQ,KAAK,CAClC,QAAQ,IACP,MAAM,SAAS,KAAK,UACnB,MAAM,QAAQ,WACP,YACA,IACP,CACD,CACD,CAAC,CAAC,WACK,YACA,IACP,GACA,IAAI,SAAgB,YAAY,WAAW,SAAS,SAAS,KAAK,CAAC,CACpE,CAAC,MAa0B;CAC3B,IAAI;CACJ,IAAI,CAAC,UAAU;EACd,MAAM,QAAQ;EACd,MAAM,SAAS;EACf,MAAM,cAAc;EACpB,MAAM,cAAc;EACpB,MAAM,SAAS,MAAM;EACrB,IAAI;GACH,UAAU,MAAM,gBAAgB,OAAO,aAAa;GACpD,IAAI,MAAM,WAAW,MAAM,SAAS,UAAU,MAAM,cAAc,GACjE,WAAW;EAEb,QAAQ;GACP,WAAW;EACZ;CACD;CAEA,IAAI,YAAY,YAAY,KAAA,GAAW;EACtC,MAAM,WAAW;EACjB,IAAI;GACH,OAAO,MAAM,iBAAiB,UAAU;EACzC,QAAQ;GAGP,OAAO;IAAE,MAAM;IAAe,MAAM;GAAG;EACxC;CACD;CAKA,MAAM,SAAgB,CAAC;CACvB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACtC,MAAM,SAAS,MAAM,SAAS,EAAE,CAAC;EACjC,IAAI,WAAW,KAAA,GAAW;GACzB,WAAW;GACX;EACD;EACA,OAAO,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAA,CAAS;CACjD;CACA,IAAI,UAAU;EACb,MAAM,WAAW;EACjB,OAAO,iBAAiB,UAAU;CACnC;CACA,OAAO;EACN,MAAM,OAAY,QAAQ,KAAA,SAAmB,eAAe,MAAM;EAClE,MAAM,QAAQ;CACf;AACD;;;;;;AAOA,SAAS,eAAe,QAAuB;CAE9C,OAAO,eADM,KAAK,UAAU,MAAM,CAAC,CAAC,WAAW,OAAO,WAC7B,EAAE;AAC5B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torpor/view",
3
- "version": "1.0.3",
3
+ "version": "1.1.0",
4
4
  "description": "Torpor's view library, for writing and mounting components",
5
5
  "type": "module",
6
6
  "exports": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"fromWebSocket-B52kN3-W.d.mts","names":[],"sources":["../src/types/ClassValue.ts","../src/render/buildClasses.ts","../src/types/StyleValue.ts","../src/render/buildStyles.ts","../src/types/StreamSource.ts","../src/stream/fromElement.ts","../src/stream/fromServer.ts","../src/stream/fromWebSocket.ts"],"mappings":";;KAAK,sBAEF,6CACA,MAAM;;;iBCAe,aAAa,OAAO,YAAY;;;KCHnD,sBAEF,4CACA,MAAM;;;iBCCe,YAAY,OAAO;;;;;;;;;;;;;;;;;KCYtC,aAAa,MAAM,OAAO,OAAO,eAAe;;;;;;;;;;;;;;KCHhD,mBAAmB,qBAAqB;;;;;;;;;;;iBAYrB,YAAY,UAAU,QAAQ,OACrD,QAAQ,kBACR,eACE,aAAa;;;;;;;;;;;;;;;;;iBCZQ,WAAW,+BAA+B,aAAa;;;;;;;;;;;;;;;;;iBCAvD,cAAc,+BAA+B,aAAa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"fromWebSocket-DeB35Q4w.d.cts","names":[],"sources":["../src/types/ClassValue.ts","../src/render/buildClasses.ts","../src/types/StyleValue.ts","../src/render/buildStyles.ts","../src/types/StreamSource.ts","../src/stream/fromElement.ts","../src/stream/fromServer.ts","../src/stream/fromWebSocket.ts"],"mappings":";;KAAK,sBAEF,6CACA,MAAM;;;iBCAe,aAAa,OAAO,YAAY;;;KCHnD,sBAEF,4CACA,MAAM;;;iBCCe,YAAY,OAAO;;;;;;;;;;;;;;;;;KCYtC,aAAa,MAAM,OAAO,OAAO,eAAe;;;;;;;;;;;;;;KCHhD,mBAAmB,qBAAqB;;;;;;;;;;;iBAYrB,YAAY,UAAU,QAAQ,OACrD,QAAQ,kBACR,eACE,aAAa;;;;;;;;;;;;;;;;;iBCZQ,WAAW,+BAA+B,aAAa;;;;;;;;;;;;;;;;;iBCAvD,cAAc,+BAA+B,aAAa"}