@fictjs/ssr 0.26.0 → 0.27.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.
Files changed (41) hide show
  1. package/README.md +169 -52
  2. package/dist/experimental.cjs +1 -1
  3. package/dist/experimental.d.cts +1 -1
  4. package/dist/experimental.d.ts +1 -1
  5. package/dist/experimental.js +1 -1
  6. package/dist/experimental.node.cjs +5 -0
  7. package/dist/experimental.node.d.cts +2 -0
  8. package/dist/experimental.node.d.ts +2 -0
  9. package/dist/experimental.node.js +4 -0
  10. package/dist/fict-stream-runtime.js +1 -1
  11. package/dist/index.cjs +1 -1
  12. package/dist/index.d.cts +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.node.cjs +10 -0
  16. package/dist/index.node.d.cts +2 -0
  17. package/dist/index.node.d.ts +2 -0
  18. package/dist/index.node.js +4 -0
  19. package/dist/node-session-carrier-CTo-1Awq.cjs +8 -0
  20. package/dist/node-session-carrier-ClqRbdoQ.js +12 -0
  21. package/dist/node-session-carrier-ClqRbdoQ.js.map +1 -0
  22. package/dist/render-core-D0nOT_Pe.js +1824 -0
  23. package/dist/render-core-D0nOT_Pe.js.map +1 -0
  24. package/dist/render-core-D_EheVwh.cjs +1863 -0
  25. package/dist/{render-core-BCYvLfHF.d.ts → render-core-KCiJV_SK.d.cts} +22 -1
  26. package/dist/render-core-KCiJV_SK.d.cts.map +1 -0
  27. package/dist/{render-core-BCYvLfHF.d.cts → render-core-KCiJV_SK.d.ts} +22 -1
  28. package/dist/render-core-KCiJV_SK.d.ts.map +1 -0
  29. package/dist/stream-runtime.cjs +1 -1
  30. package/dist/stream-runtime.d.cts +2 -0
  31. package/dist/stream-runtime.d.cts.map +1 -1
  32. package/dist/stream-runtime.d.ts +2 -0
  33. package/dist/stream-runtime.d.ts.map +1 -1
  34. package/dist/stream-runtime.js +1 -1
  35. package/dist/stream-runtime.js.map +1 -1
  36. package/package.json +15 -5
  37. package/dist/render-core-BCYvLfHF.d.cts.map +0 -1
  38. package/dist/render-core-BCYvLfHF.d.ts.map +0 -1
  39. package/dist/render-core-BLLUhkYy.js +0 -969
  40. package/dist/render-core-BLLUhkYy.js.map +0 -1
  41. package/dist/render-core-CWudV9yi.cjs +0 -1008
package/README.md CHANGED
@@ -89,11 +89,15 @@ const html = renderToString(() => <App />, {
89
89
 
90
90
  ```typescript
91
91
  // entry-client.tsx
92
+ import { render } from 'fict'
92
93
  import { installResumableLoader } from 'fict/loader'
94
+ import { App } from './App'
93
95
 
94
96
  // Load manifest (production)
95
97
  async function loadManifest() {
96
- const res = await fetch('/fict.manifest.json')
98
+ // Prefer a build-scoped URL. If the manifest has a fixed name, revalidate it
99
+ // instead of allowing it to become stale independently from the HTML.
100
+ const res = await fetch('/fict.manifest.json', { cache: 'no-store' })
97
101
  if (res.ok) {
98
102
  globalThis.__FICT_MANIFEST__ = await res.json()
99
103
  }
@@ -104,6 +108,12 @@ async function init() {
104
108
 
105
109
  installResumableLoader({
106
110
  events: ['click', 'input', 'change', 'submit'],
111
+ onSnapshotIssue: issue => reportSnapshotIssue(issue),
112
+ onSnapshotRejected: () => {
113
+ const root = document.getElementById('app')!
114
+ root.replaceChildren()
115
+ render(() => <App />, root)
116
+ },
107
117
  prefetch: {
108
118
  visibility: true,
109
119
  visibilityMargin: '200px',
@@ -123,18 +133,22 @@ init()
123
133
  QRL is the URL format Fict uses for lazy loading handlers:
124
134
 
125
135
  ```
126
- virtual:fict-handler:/path/to/file.tsx$$__fict_e0#default
127
- │ │
128
- │ └─ Export Name
129
- └─ Handler ID
130
- └─ Source File Path
136
+ virtual:fict-handler:h0123456789abcdef0123456789abcdef$$__fict_e0#default
137
+ │ │
138
+ │ └─ Export Name
139
+ └─ Handler Export
140
+ └─ Opaque Source Identity
131
141
  └─ Virtual Module Prefix
132
142
  ```
133
143
 
144
+ Production identities are checkout-independent and do not contain source paths.
145
+
134
146
  **Representation in HTML:**
135
147
 
136
148
  ```html
137
- <button on:click="virtual:fict-handler:/src/App.tsx$$__fict_e0#default">Click me</button>
149
+ <button on:click="virtual:fict-handler:h0123456789abcdef0123456789abcdef$$__fict_e0#default">
150
+ Click me
151
+ </button>
138
152
  ```
139
153
 
140
154
  ### 2. State Snapshot
@@ -144,10 +158,10 @@ During server-side rendering, component state is serialized into JSON and inject
144
158
  ```html
145
159
  <script id="__FICT_SNAPSHOT__" type="application/json">
146
160
  {
147
- "v": 1,
161
+ "v": 2,
148
162
  "scopes": {
149
- "s1": {
150
- "id": "s1",
163
+ "account_scope:s1": {
164
+ "id": "account_scope:s1",
151
165
  "slots": [
152
166
  [0, "sig", 10], // Index 0: signal, value 10
153
167
  [1, "store", {...}], // Index 1: store
@@ -162,16 +176,25 @@ During server-side rendering, component state is serialized into JSON and inject
162
176
 
163
177
  **Supported Serialization Types:**
164
178
 
165
- | Type | Tag | Description |
166
- | --------- | ------------------------- | -------------------------- |
167
- | Date | `__t: 'd'` | Stored as timestamp |
168
- | Map | `__t: 'm'` | Stored as entries array |
169
- | Set | `__t: 's'` | Stored as array |
170
- | RegExp | `__t: 'r'` | Stored as source + flags |
171
- | undefined | `__t: 'u'` | Special tag |
172
- | NaN | `__t: 'n'` | Special tag |
173
- | Infinity | `__t: '+i'` / `__t: '-i'` | Positive/Negative Infinity |
174
- | BigInt | `__t: 'b'` | Stored as string |
179
+ | Type / shape | Tag | Preserved detail |
180
+ | ----------------------------- | --------------------------- | ------------------------------------------------- |
181
+ | Date | `__t: 'd'` | Timestamp or invalid-date marker |
182
+ | Map / Set | `__t: 'm'` / `__t: 's'` | Recursively encoded entries/items |
183
+ | RegExp | `__t: 'r'` | Source, flags, and `lastIndex` |
184
+ | Global/well-known Symbol | `__t: 'sym'` | Symbol registry kind and name |
185
+ | Special object representation | `__t: 'o'` | Symbol keys, null prototype, or literal `__t` key |
186
+ | Array hole | `__t: 'h'` | Distinguishes a hole from `undefined` |
187
+ | undefined / NaN / negative 0 | `__t: 'u'` / `'n'` / `'-0'` | Values JSON cannot represent faithfully |
188
+ | Infinity | `__t: '+i'` / `__t: '-i'` | Positive/negative infinity |
189
+ | BigInt | `__t: 'b'` | Decimal string |
190
+ | Shared/circular reference | `__t: 'ref'` | Path to an already encoded object |
191
+
192
+ Schema v2 escapes plain objects that themselves contain `__t`, so literal user
193
+ data cannot be confused with a serialization marker. Unsupported object shapes
194
+ and functions stored inside value-bearing containers fail serialization rather
195
+ than being silently corrupted. Function-valued component-prop properties and
196
+ function-valued raw slots are intentionally omitted by the existing compiler
197
+ ABI.
175
198
 
176
199
  ### 3. Scope Registration
177
200
 
@@ -179,14 +202,31 @@ Each resumable component instance has a unique scope ID:
179
202
 
180
203
  ```html
181
204
  <fict-host
182
- data-fict-s="s1" <!-- scope ID -->
205
+ data-fict-s="account_scope:s1" <!-- scope ID -->
183
206
  data-fict-h="/assets/index.js#__fict_r0" <!-- resume handler -->
184
- data-fict-t="Counter@file:///src/App.tsx" <!-- Component Type -->
207
+ data-fict-t="Counter@fict:module:m0123456789abcdef0123456789abcdef" <!-- Component Type -->
185
208
  >
186
209
  ...
187
210
  </fict-host>
188
211
  ```
189
212
 
213
+ Every SSR render receives an automatic unique namespace for these host and
214
+ snapshot scope IDs. For deterministic cached output, or when fragments from
215
+ multiple services can share a document, pass a stable `scopeIdentifierPrefix`
216
+ that is unique within the final document:
217
+
218
+ ```typescript
219
+ renderToString(() => <App />, {
220
+ scopeIdentifierPrefix: 'account_scope',
221
+ })
222
+ ```
223
+
224
+ This option is shared by string, document, Web Stream, pipeable, async-string,
225
+ and partial render entry points. It does not affect Suspense patch IDs; use
226
+ `streamIdentifierPrefix` for those. Reusing a scope prefix in one document can
227
+ make loader state ambiguous. Prefixes accept 1-128 ASCII letters, digits, `_`,
228
+ `.`, `:`, or `-`, but may not contain `--`.
229
+
190
230
  ### 4. Automatic Handler Extraction
191
231
 
192
232
  The Fict compiler supports two ways to extract handlers:
@@ -261,6 +301,17 @@ should use Fict's render-provided document/ownerDocument paths; set `exposeGloba
261
301
  legacy code that still reads DOM globals during server render. That compatibility mode is restored
262
302
  on `dispose()`, but it is not concurrency-safe while overlapping renders are active.
263
303
 
304
+ ### renderToStringAsync
305
+
306
+ ```typescript
307
+ function renderToStringAsync(view: () => FictNode, options?: RenderToStringOptions): Promise<string>
308
+ ```
309
+
310
+ Waits until all Suspense boundaries have resolved, then serializes their final content. Its output
311
+ options and defaults match `renderToString`; in particular, it returns the rendered container's
312
+ children unless `fullDocument` or `includeContainer` is requested. Use `renderToString` when a
313
+ synchronous fallback shell is desired instead.
314
+
264
315
  ### renderToDocument
265
316
 
266
317
  ```typescript
@@ -316,6 +367,23 @@ Trusted Types deployments should use this external observer runtime. The patch
316
367
  runtime moves `<template>` content with DOM APIs (`content` + `insertBefore`) and
317
368
  does not call `innerHTML`, `insertAdjacentHTML`, `eval`, or `Function`.
318
369
 
370
+ Each shell stream receives an automatic unique namespace for its Suspense patch
371
+ identifiers. When independently cached fragments or streams from multiple
372
+ services can be composed into one document, pass a stable
373
+ `streamIdentifierPrefix` that is unique within that final document:
374
+
375
+ ```typescript
376
+ renderToStream(() => <App />, {
377
+ mode: 'shell',
378
+ streamIdentifierPrefix: 'account_shell',
379
+ })
380
+ ```
381
+
382
+ The prefix only affects streaming patch identifiers; resumable scope IDs are
383
+ unchanged. Reusing a prefix for two live streams in the same document can make
384
+ their patches ambiguous. Prefixes accept 1-128 ASCII letters, digits, `_`, `.`,
385
+ `:`, or `-`, but may not contain `--`.
386
+
319
387
  ### renderToPipeableStream
320
388
 
321
389
  Node.js-style stream variant (compatible with `pipe()`).
@@ -372,21 +440,47 @@ interface ResumableLoaderOptions {
372
440
  document?: Document
373
441
  snapshotScriptId?: string
374
442
  events?: string[] // Default: DelegatedEvents
443
+ snapshotMigrations?: Record<number, SnapshotMigration>
375
444
  onSnapshotIssue?: (issue: SnapshotIssue) => void
445
+ onSnapshotRejected?: (issue: SnapshotIssue) => void | Promise<void>
376
446
  prefetch?: PrefetchStrategy | false
377
447
  }
378
448
 
449
+ type SnapshotMigration = (
450
+ snapshot: Record<string, unknown>,
451
+ context: SnapshotMigrationContext,
452
+ ) => unknown
453
+
454
+ interface SnapshotMigrationContext {
455
+ fromVersion: number
456
+ toVersion: number
457
+ source: string
458
+ }
459
+
379
460
  interface SnapshotIssue {
380
461
  code:
381
462
  | 'snapshot_parse_error'
382
463
  | 'snapshot_invalid_shape'
383
464
  | 'snapshot_unsupported_version'
465
+ | 'snapshot_migration_failed'
466
+ | 'snapshot_fallback_failed'
384
467
  | 'scope_snapshot_missing'
468
+ | 'resume_import_failed'
469
+ | 'resume_function_missing'
470
+ | 'resume_failed'
471
+ | 'handler_import_failed'
472
+ | 'handler_missing'
473
+ | 'handler_failed'
385
474
  message: string
386
475
  source: string
387
476
  expectedVersion: number
388
477
  actualVersion?: number
389
478
  scopeId?: string
479
+ qrl?: string
480
+ url?: string
481
+ exportName?: string
482
+ eventType?: string
483
+ error?: unknown
390
484
  }
391
485
 
392
486
  interface PrefetchStrategy {
@@ -395,8 +489,23 @@ interface PrefetchStrategy {
395
489
  hover?: boolean // Default: true
396
490
  hoverDelay?: number // Default: 50
397
491
  }
492
+
493
+ type LegacySnapshotFormat = 'raw-props' | 'encoded-props'
494
+ const UNVERSIONED_SNAPSHOT_MIGRATION_KEY = 0
495
+ function createLegacySnapshotMigration(format: LegacySnapshotFormat): SnapshotMigration
398
496
  ```
399
497
 
498
+ The current writer emits v2. Missing `v` and v1 fail closed unless the
499
+ application explicitly selects the matching historical writer dialect. The
500
+ loader cannot infer whether v1 `{ "__t": "u" }` bytes mean literal data or an
501
+ encoded `undefined` value. See the
502
+ [SSR / Resume Stability Contract](../../docs/ssr-resume-stability-contract.md)
503
+ for the version map and migration examples.
504
+
505
+ `onSnapshotIssue` is telemetry-only. `onSnapshotRejected` runs once after the
506
+ loader disengages; the application must mount the CSR root. Fict does not mount
507
+ CSR automatically, and it does not route QRL failures to an ErrorBoundary.
508
+
400
509
  ## Architecture Design
401
510
 
402
511
  ### Build Time
@@ -417,26 +526,12 @@ interface PrefetchStrategy {
417
526
 
418
527
  **Generated Code Structure:**
419
528
 
420
- ```javascript
421
- // Main bundle
422
- const __fict_r0 = (scopeId, host) => {
423
- // Resume Function: Restore state + Bind reactivity
424
- const scope = __fictGetSSRScope(scopeId)
425
- let count = __fictRestoreSignal(scope, 0)
426
-
427
- $effect(() => {
428
- /* Bind DOM update */
429
- })
430
- }
431
-
432
- __fictRegisterResume('__fict_r0', __fict_r0)
433
-
434
- // Handler chunk (separate file)
435
- export default (scopeId, event, el) => {
436
- const [count] = __fictUseLexicalScope(scopeId, ['count'])
437
- count++ // Trigger signal update
438
- }
439
- ```
529
+ The exact generated ABI is compiler-owned and may change while resumability is
530
+ Preview. Conceptually, the main bundle registers a resume function that restores
531
+ the scope and reconnects reactive bindings. Each extracted handler chunk exports
532
+ the function named by its QRL; the loader restores the lexical scope before it
533
+ invokes that handler. Use compiler fixture output and package tests—not copied
534
+ generated snippets—as the compatibility source of truth.
440
535
 
441
536
  ### Runtime
442
537
 
@@ -470,12 +565,20 @@ Generated detailed `fict.manifest.json` during production build, mapping virtual
470
565
 
471
566
  ```json
472
567
  {
473
- "virtual:fict-handler:/src/App.tsx$$__fict_e0": "/assets/handler-e0-abc123.js",
474
- "virtual:fict-handler:/src/App.tsx$$__fict_e1": "/assets/handler-e1-def456.js",
475
- "file:///src/App.tsx": "/assets/index-xyz789.js"
568
+ "fict:module:m0123456789abcdef0123456789abcdef": "/assets/index-xyz789.js",
569
+ "virtual:fict-handler:h0123456789abcdef0123456789abcdef$$__fict_e0": "/assets/handler-e0-abc123.js",
570
+ "virtual:fict-handler:h0123456789abcdef0123456789abcdef$$__fict_e1": "/assets/handler-e1-def456.js"
476
571
  }
477
572
  ```
478
573
 
574
+ Only modules that own a resumable QRL are listed. Physical filenames and
575
+ unrelated Rollup modules are deliberately excluded.
576
+
577
+ Treat the manifest, SSR server, HTML snapshots, client loader, QRL chunks, and
578
+ external stream runtime as one build. Prefer a build-scoped manifest URL. If a
579
+ fixed `/fict.manifest.json` is unavoidable, serve it with `no-store` or mandatory
580
+ revalidation; do not let it use stale-while-revalidate independently from HTML.
581
+
479
582
  ## Integration with Vite
480
583
 
481
584
  ## Partial Prerendering
@@ -486,6 +589,8 @@ Generated detailed `fict.manifest.json` during production build, mapping virtual
486
589
  2. **Deferred phase**: deliver `stream` patches for resolved Suspense boundaries.
487
590
 
488
591
  This keeps shell TTFB low while still allowing server-resolved dynamic islands.
592
+ The shell and every deferred patch must come from the same build and snapshot
593
+ schema; never combine a cached shell with a newer server's patch stream.
489
594
 
490
595
  ## Edge Runtime
491
596
 
@@ -706,13 +811,25 @@ console.log(__fictGetResume('__fict_r0')) // Should return function
706
811
 
707
812
  **Solution:**
708
813
 
709
- ```typescript
710
- // Use lazy initialization
711
- let data = $state(null) // Initial null
712
- onMount(async () => {
713
- data = await fetchData() // Fetch on client
714
- })
715
- ```
814
+ ```tsx
815
+ // Serialize only lightweight state, then load details from a resumable client interaction.
816
+ let data = $state(null)
817
+
818
+ return (
819
+ <button
820
+ onClick$={async () => {
821
+ data = await fetchData(itemId)
822
+ }}
823
+ >
824
+ Load details
825
+ </button>
826
+ )
827
+ ```
828
+
829
+ `onMount` is synchronous and also runs during server rendering. Do not use an async `onMount`
830
+ callback for client bootstrapping: returned promises are not awaited, and a cleanup resolved from a
831
+ promise is not registered. If data must load automatically on the client, use an explicit
832
+ client-only/CSR bootstrap instead.
716
833
 
717
834
  ### Debugging Tips
718
835
 
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-CWudV9yi.cjs");
2
+ const require_render_core = require("./render-core-D_EheVwh.cjs");
3
3
  exports.renderToPartial = require_render_core.renderToPartial;
@@ -1,2 +1,2 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-BCYvLfHF.cjs";
1
+ import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.cjs";
2
2
  export { type PartialPrerenderResult, renderToPartial };
@@ -1,2 +1,2 @@
1
- import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-BCYvLfHF.js";
1
+ import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.js";
2
2
  export { type PartialPrerenderResult, renderToPartial };
@@ -1,2 +1,2 @@
1
- import { r as renderToPartial } from "./render-core-BLLUhkYy.js";
1
+ import { r as renderToPartial } from "./render-core-D0nOT_Pe.js";
2
2
  export { renderToPartial };
@@ -0,0 +1,5 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_render_core = require("./render-core-D_EheVwh.cjs");
3
+ require("./node-session-carrier-CTo-1Awq.cjs");
4
+ require("./experimental.cjs");
5
+ exports.renderToPartial = require_render_core.renderToPartial;
@@ -0,0 +1,2 @@
1
+ import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.cjs";
2
+ export { type PartialPrerenderResult, renderToPartial };
@@ -0,0 +1,2 @@
1
+ import { l as renderToPartial, t as PartialPrerenderResult } from "./render-core-KCiJV_SK.js";
2
+ export { type PartialPrerenderResult, renderToPartial };
@@ -0,0 +1,4 @@
1
+ import { r as renderToPartial } from "./render-core-D0nOT_Pe.js";
2
+ import "./node-session-carrier-ClqRbdoQ.js";
3
+ import "./experimental.js";
4
+ export { renderToPartial };
@@ -1 +1 @@
1
- (function(){if(window.__FICT_STREAM)return;var cache=new Map();function find(id){var hit=cache.get(id);if(hit)return hit;var start=null,end=null;var w=document.createTreeWalker(document,NodeFilter.SHOW_COMMENT);while(w.nextNode()){var n=w.currentNode;var d=n.data;if(d==="fict:suspense-start:"+id)start=n;else if(d==="fict:suspense-end:"+id)end=n;if(start&&end)break;}if(start&&end){hit={start:start,end:end};cache.set(id,hit);}return hit;}function apply(id){var tpl=document.querySelector('template[data-fict-suspense="' + id + '"]');if(!tpl)return;var b=find(id);if(!b)return;var node=b.start.nextSibling;while(node&&node!==b.end){var next=node.nextSibling;node.parentNode&&node.parentNode.removeChild(node);node=next;}b.end.parentNode&&b.end.parentNode.insertBefore(tpl.content,b.end);tpl.parentNode&&tpl.parentNode.removeChild(tpl);}window.__FICT_STREAM={apply:apply};function scan(root){var list=(root&&root.querySelectorAll?root:document).querySelectorAll("template[data-fict-suspense]");for(var i=0;i<list.length;i++){apply(list[i].getAttribute("data-fict-suspense"));}}if(typeof MutationObserver==="function"){new MutationObserver(function(muts){for(var i=0;i<muts.length;i++){for(var j=0;j<muts[i].addedNodes.length;j++){var n=muts[i].addedNodes[j];if(n.nodeType===1){if(n.matches&&n.matches("template[data-fict-suspense]"))apply(n.getAttribute("data-fict-suspense"));scan(n);}}}}).observe(document.documentElement||document,{childList:true,subtree:true});}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){scan(document);},{once:true});}else{scan(document);}})();
1
+ (function(){var runtime=window.__FICT_STREAM;function walk(root,visit){var stack=[root];while(stack.length){var node=stack.pop();if(visit(node)===false)return false;var container=node.nodeType===1&&node.localName==="template"&&node.content?node.content:node;for(var child=container.lastChild;child;child=child.previousSibling)stack.push(child);}return true;}if(!runtime||typeof runtime.apply!=="function"){var cache=new Map();function findTemplate(id){var tpl=null;walk(document,function(n){if(n.nodeType===1&&n.localName==="template"&&n.content&&n.getAttribute("data-fict-suspense")===id){tpl=n;return false;}});return tpl;}function find(id){var hit=cache.get(id);if(hit)return hit;var startMarker="fict:suspense-start:"+id,endMarker="fict:suspense-end:"+id;walk(document,function(n){if(n.nodeType!==8||n.data!==startMarker)return;var end=n.nextSibling;while(end&&(end.nodeType!==8||end.data!==endMarker))end=end.nextSibling;if(end){hit={start:n,end:end};return false;}});if(hit)cache.set(id,hit);return hit;}function apply(id){if(typeof id!=="string"||!id)return;var tpl=findTemplate(id);if(!tpl)return;var b=find(id);if(!b)return;var parent=b.start.parentNode;if(!parent||b.end.parentNode!==parent)return;var cursor=b.start.nextSibling;while(cursor&&cursor!==b.end)cursor=cursor.nextSibling;if(cursor!==b.end)return;var content=tpl.content;var ns=tpl.getAttribute("data-fict-patch-namespace");if(ns){var tag=ns==="svg"?"svg":ns==="mathml"?"math":null;var wrapper=content.firstElementChild;if(!tag||!wrapper||wrapper.localName!==tag)return;var fragment=document.createDocumentFragment();while(wrapper.firstChild)fragment.appendChild(wrapper.firstChild);content=fragment;}var node=b.start.nextSibling;while(node&&node!==b.end){var next=node.nextSibling;node.parentNode&&node.parentNode.removeChild(node);node=next;}parent.insertBefore(content,b.end);tpl.parentNode&&tpl.parentNode.removeChild(tpl);}runtime={apply:apply};window.__FICT_STREAM=runtime;}if(runtime.observerInstalled)return;runtime.observerInstalled=true;function scan(root){var ids=[];walk(root,function(n){if(n.nodeType===1&&n.localName==="template"&&n.content&&n.hasAttribute("data-fict-suspense")){var id=n.getAttribute("data-fict-suspense");if(id)ids.push(id);}});for(var i=0;i<ids.length;i++)runtime.apply(ids[i]);}if(typeof MutationObserver==="function"){new MutationObserver(function(muts){for(var i=0;i<muts.length;i++){for(var j=0;j<muts[i].addedNodes.length;j++){var n=muts[i].addedNodes[j];if(n.nodeType===1)scan(n);}}}).observe(document.documentElement||document,{childList:true,subtree:true});}if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",function(){scan(document);},{once:true});}else{scan(document);}})();
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_render_core = require("./render-core-CWudV9yi.cjs");
2
+ const require_render_core = require("./render-core-D_EheVwh.cjs");
3
3
  exports.createSSRDocument = require_render_core.createSSRDocument;
4
4
  exports.renderToDocument = require_render_core.renderToDocument;
5
5
  exports.renderToPipeableStream = require_render_core.renderToPipeableStream;
package/dist/index.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-BCYvLfHF.cjs";
1
+ import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.cjs";
2
2
  export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-BCYvLfHF.js";
1
+ import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.js";
2
2
  export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as renderToStream, i as renderToPipeableStream, n as renderToDocument, o as renderToString, s as renderToStringAsync, t as createSSRDocument } from "./render-core-BLLUhkYy.js";
1
+ import { a as renderToStream, i as renderToPipeableStream, n as renderToDocument, o as renderToString, s as renderToStringAsync, t as createSSRDocument } from "./render-core-D0nOT_Pe.js";
2
2
  export { createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -0,0 +1,10 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_render_core = require("./render-core-D_EheVwh.cjs");
3
+ require("./index.cjs");
4
+ require("./node-session-carrier-CTo-1Awq.cjs");
5
+ exports.createSSRDocument = require_render_core.createSSRDocument;
6
+ exports.renderToDocument = require_render_core.renderToDocument;
7
+ exports.renderToPipeableStream = require_render_core.renderToPipeableStream;
8
+ exports.renderToStream = require_render_core.renderToStream;
9
+ exports.renderToString = require_render_core.renderToString;
10
+ exports.renderToStringAsync = require_render_core.renderToStringAsync;
@@ -0,0 +1,2 @@
1
+ import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.cjs";
2
+ export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -0,0 +1,2 @@
1
+ import { a as RenderToStringOptions, c as renderToDocument, d as renderToStream, f as renderToString, i as RenderToStreamOptions, n as PipeableStream, o as SSRDom, p as renderToStringAsync, r as RenderToDocumentResult, s as createSSRDocument, u as renderToPipeableStream } from "./render-core-KCiJV_SK.js";
2
+ export { type PipeableStream, type RenderToDocumentResult, type RenderToStreamOptions, type RenderToStringOptions, type SSRDom, createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -0,0 +1,4 @@
1
+ import { a as renderToStream, i as renderToPipeableStream, n as renderToDocument, o as renderToString, s as renderToStringAsync, t as createSSRDocument } from "./render-core-D0nOT_Pe.js";
2
+ import "./index.js";
3
+ import "./node-session-carrier-ClqRbdoQ.js";
4
+ export { createSSRDocument, renderToDocument, renderToPipeableStream, renderToStream, renderToString, renderToStringAsync };
@@ -0,0 +1,8 @@
1
+ let _fictjs_runtime_internal = require("@fictjs/runtime/internal");
2
+ //#region src/node-session-carrier.ts
3
+ const sessionStorage = new (require("node:async_hooks")).AsyncLocalStorage();
4
+ (0, _fictjs_runtime_internal.__fictInstallSSRSessionCarrier)({
5
+ getStore: () => sessionStorage.getStore(),
6
+ run: (session, fn) => sessionStorage.run(session, fn)
7
+ });
8
+ //#endregion
@@ -0,0 +1,12 @@
1
+ import { __fictInstallSSRSessionCarrier } from "@fictjs/runtime/internal";
2
+ import { AsyncLocalStorage } from "node:async_hooks";
3
+ //#region src/node-session-carrier.ts
4
+ const sessionStorage = new AsyncLocalStorage();
5
+ __fictInstallSSRSessionCarrier({
6
+ getStore: () => sessionStorage.getStore(),
7
+ run: (session, fn) => sessionStorage.run(session, fn)
8
+ });
9
+ //#endregion
10
+ export {};
11
+
12
+ //# sourceMappingURL=node-session-carrier-ClqRbdoQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-session-carrier-ClqRbdoQ.js","names":[],"sources":["../src/node-session-carrier.ts"],"sourcesContent":["import { AsyncLocalStorage } from 'node:async_hooks'\n\nimport { __fictInstallSSRSessionCarrier, type FictSSRSession } from '@fictjs/runtime/internal'\n\nconst sessionStorage = new AsyncLocalStorage<FictSSRSession>()\n\n__fictInstallSSRSessionCarrier({\n getStore: () => sessionStorage.getStore(),\n run: (session, fn) => sessionStorage.run(session, fn),\n})\n"],"mappings":";;;AAIA,MAAM,iBAAiB,IAAI,kBAAkC;AAE7D,+BAA+B;CAC7B,gBAAgB,eAAe,SAAS;CACxC,MAAM,SAAS,OAAO,eAAe,IAAI,SAAS,EAAE;AACtD,CAAC"}