sibujs 4.13.0 → 4.14.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 (107) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.cjs +15 -2
  3. package/dist/browser.js +9 -7
  4. package/dist/build.cjs +880 -281
  5. package/dist/build.d.cts +68 -3
  6. package/dist/build.d.ts +68 -3
  7. package/dist/build.js +88 -30
  8. package/dist/cdn.dev.global.js +12 -12
  9. package/dist/cdn.full.dev.global.js +13 -13
  10. package/dist/cdn.full.global.js +12 -12
  11. package/dist/cdn.global.js +12 -12
  12. package/dist/{chunk-7K7W4AA5.js → chunk-2TTRW2TE.js} +6 -6
  13. package/dist/{chunk-J6FW5TV6.js → chunk-3HEX6QJQ.js} +5 -3
  14. package/dist/chunk-3HZOSMPX.js +90 -0
  15. package/dist/{chunk-GNSRXK34.js → chunk-4FJSAUKB.js} +11 -3
  16. package/dist/{chunk-IV74C2YX.js → chunk-4TQDTWWN.js} +6 -5
  17. package/dist/{chunk-L3QHS4O4.js → chunk-7ILEHTVX.js} +1 -1
  18. package/dist/{chunk-CK5F2IR5.js → chunk-A454RAEK.js} +4 -4
  19. package/dist/{chunk-BRRRVLHQ.js → chunk-AE32RGWX.js} +10 -6
  20. package/dist/{chunk-EXXSN3BW.js → chunk-B3HOT4TK.js} +1 -1
  21. package/dist/{chunk-F4W7WYXY.js → chunk-BKZ5N6NK.js} +8 -6
  22. package/dist/{chunk-MNEITZ27.js → chunk-BNXRWZZV.js} +49 -8
  23. package/dist/chunk-BOYKGGVD.js +2015 -0
  24. package/dist/{chunk-G6366I2A.js → chunk-CCKUNHVU.js} +2 -2
  25. package/dist/{chunk-346BYZL2.js → chunk-CJ7KS3DF.js} +16 -10
  26. package/dist/chunk-CNPT6NKV.js +1859 -0
  27. package/dist/{chunk-ENFRHCMK.js → chunk-F67F77IA.js} +2 -2
  28. package/dist/{chunk-TUCPL2HB.js → chunk-GIJ33UJZ.js} +1 -1
  29. package/dist/chunk-GVAMIU6K.js +195 -0
  30. package/dist/{chunk-HDKDBC6V.js → chunk-HQIAL7F2.js} +8 -6
  31. package/dist/{chunk-ZE5LF44R.js → chunk-JTFQ7IL4.js} +8 -8
  32. package/dist/{chunk-AM6DZLBM.js → chunk-LJMX4SQ7.js} +2 -2
  33. package/dist/{chunk-HVVRXRGO.js → chunk-MIRKTVH4.js} +7 -14
  34. package/dist/{chunk-YJ57VR6Y.js → chunk-N7A6FKWW.js} +5 -3
  35. package/dist/chunk-NT3ZYB5S.js +167 -0
  36. package/dist/{chunk-Z3EZX6DZ.js → chunk-QS6GMWDD.js} +151 -86
  37. package/dist/chunk-R5U7XKVJ.js +16 -0
  38. package/dist/{chunk-3C56VNCK.js → chunk-RVR5NPFL.js} +3 -3
  39. package/dist/{chunk-F2UWOZ6J.js → chunk-RVWJGWCL.js} +2 -2
  40. package/dist/{chunk-NYNYSPK7.js → chunk-S37PZD6I.js} +30 -45
  41. package/dist/{chunk-QV5WEOFD.js → chunk-SVULV7O4.js} +119 -26
  42. package/dist/{chunk-C2FAO6VQ.js → chunk-TLS4NVIB.js} +5 -5
  43. package/dist/{chunk-M25RIH6Y.js → chunk-UUIKJJIK.js} +10 -8
  44. package/dist/chunk-UYTYNCMZ.js +199 -0
  45. package/dist/chunk-VM2U5LEL.js +2596 -0
  46. package/dist/{chunk-24L5RDPS.js → chunk-Y4LUM2XS.js} +8 -6
  47. package/dist/data.cjs +265 -35
  48. package/dist/data.d.cts +31 -1
  49. package/dist/data.d.ts +31 -1
  50. package/dist/data.js +16 -10
  51. package/dist/devtools.cjs +15 -2
  52. package/dist/devtools.js +9 -7
  53. package/dist/{dispose-GEIG2KOF.js → dispose-EIHHHDC7.js} +3 -1
  54. package/dist/ecosystem.cjs +62 -23
  55. package/dist/ecosystem.js +14 -12
  56. package/dist/extras.cjs +3520 -270
  57. package/dist/extras.d.cts +3 -3
  58. package/dist/extras.d.ts +3 -3
  59. package/dist/extras.js +39 -29
  60. package/dist/index.cjs +442 -253
  61. package/dist/index.d.cts +93 -283
  62. package/dist/index.d.ts +93 -283
  63. package/dist/index.js +26 -16
  64. package/dist/motion.cjs +12 -1
  65. package/dist/motion.js +6 -4
  66. package/dist/patterns.cjs +15 -2
  67. package/dist/patterns.js +10 -8
  68. package/dist/performance.cjs +36 -2
  69. package/dist/performance.d.cts +2 -2
  70. package/dist/performance.d.ts +2 -2
  71. package/dist/performance.js +14 -10
  72. package/dist/plugins.cjs +5225 -1807
  73. package/dist/plugins.d.cts +8 -834
  74. package/dist/plugins.d.ts +8 -834
  75. package/dist/plugins.js +64 -2329
  76. package/dist/prerenderServer-MXJEVWA3.js +350 -0
  77. package/dist/renderRoute-DP20XwMS.d.cts +86 -0
  78. package/dist/renderRoute-fxgsm2Ir.d.ts +86 -0
  79. package/dist/routeHead-CE9SV-cH.d.cts +995 -0
  80. package/dist/routeHead-DzVxPviY.d.ts +995 -0
  81. package/dist/{routeMiddleware-B1sp4P7a.d.ts → routeMiddleware-BySbueoE.d.ts} +0 -25
  82. package/dist/{routeMiddleware-CedQTsLK.d.cts → routeMiddleware-CijZD5eW.d.cts} +0 -25
  83. package/dist/ssr-JpGpHnpC.d.cts +841 -0
  84. package/dist/ssr-JpGpHnpC.d.ts +841 -0
  85. package/dist/{ssr-VBM6J5SJ.js → ssr-NECEU4X4.js} +15 -6
  86. package/dist/ssr-dom.cjs +1862 -0
  87. package/dist/ssr-dom.d.cts +341 -0
  88. package/dist/ssr-dom.d.ts +341 -0
  89. package/dist/ssr-dom.js +19 -0
  90. package/dist/ssr.cjs +7630 -2064
  91. package/dist/ssr.d.cts +63 -5
  92. package/dist/ssr.d.ts +63 -5
  93. package/dist/ssr.js +136 -14
  94. package/dist/testing.cjs +6543 -87
  95. package/dist/testing.d.cts +80 -1
  96. package/dist/testing.d.ts +80 -1
  97. package/dist/testing.js +117 -4
  98. package/dist/ui.cjs +36 -2
  99. package/dist/ui.js +17 -14
  100. package/dist/widgets.cjs +14 -1
  101. package/dist/widgets.js +11 -9
  102. package/package.json +9 -2
  103. package/dist/chunk-2F4PSJ5Z.js +0 -765
  104. package/dist/chunk-7XHATCIH.js +0 -121
  105. package/dist/chunk-B36ADEIR.js +0 -21
  106. package/dist/ssr-Db0Sgdu3.d.cts +0 -245
  107. package/dist/ssr-Db0Sgdu3.d.ts +0 -245
@@ -1,121 +0,0 @@
1
- import {
2
- __require,
3
- devWarn
4
- } from "./chunk-NYNYSPK7.js";
5
-
6
- // src/core/ssr-context.ts
7
- var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
8
- function detectSSRShared() {
9
- let detected = null;
10
- try {
11
- if (typeof process !== "undefined" && process.versions && process.versions.node) {
12
- let mod = null;
13
- const getBuiltin = process.getBuiltinModule;
14
- if (typeof getBuiltin === "function") {
15
- mod = getBuiltin("node:async_hooks");
16
- } else if (typeof __require === "function") {
17
- mod = __require("async_hooks");
18
- }
19
- if (mod) detected = new mod.AsyncLocalStorage();
20
- }
21
- } catch {
22
- detected = null;
23
- }
24
- return {
25
- als: detected,
26
- fallbackStore: { ssr: false, suspenseIdCounter: 0, locale: void 0 },
27
- fallbackDepth: 0
28
- };
29
- }
30
- var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
31
- var als = _shared.als;
32
- var fallbackStore = _shared.fallbackStore;
33
- _shared.fallbackDepth ?? (_shared.fallbackDepth = 0);
34
- var _alsWarned = false;
35
- function warnMissingAsyncLocalStorage() {
36
- if (_alsWarned || als) return;
37
- const isNode = typeof process !== "undefined" && !!process.versions?.node;
38
- if (!isNode) return;
39
- _alsWarned = true;
40
- const version = process.versions.node;
41
- devWarn(
42
- `SSR request isolation is UNAVAILABLE on this runtime (Node ${version}). AsyncLocalStorage could not be loaded, so concurrent requests share one SSR store: request state and the query cache can bleed between them. Node >= 22.3 is required for isolated SSR under ESM; the CommonJS build works on older versions. A fully synchronous render is unaffected.`
43
- );
44
- }
45
- function getSSRStore() {
46
- if (als) {
47
- const s = als.getStore();
48
- if (s) return s;
49
- }
50
- return fallbackStore;
51
- }
52
- function getRequestStore() {
53
- if (als) return als.getStore() ?? null;
54
- return _shared.fallbackDepth > 0 ? fallbackStore : null;
55
- }
56
- function isSSR() {
57
- return getSSRStore().ssr;
58
- }
59
- function getRequestScopedCache(name) {
60
- if (!isSSR()) return null;
61
- const store = getSSRStore();
62
- const caches = store.caches ?? (store.caches = /* @__PURE__ */ new Map());
63
- let c = caches.get(name);
64
- if (!c) {
65
- c = /* @__PURE__ */ new Map();
66
- caches.set(name, c);
67
- }
68
- return c;
69
- }
70
- function enableSSR() {
71
- getSSRStore().ssr = true;
72
- }
73
- function disableSSR() {
74
- getSSRStore().ssr = false;
75
- }
76
- function runInSSRContext(fn) {
77
- const store = { ssr: true, suspenseIdCounter: 0, idCounter: 0, locale: void 0 };
78
- if (als) {
79
- return als.run(store, fn);
80
- }
81
- warnMissingAsyncLocalStorage();
82
- const prevSSR = fallbackStore.ssr;
83
- const prevCounter = fallbackStore.suspenseIdCounter;
84
- const prevIdCounter = fallbackStore.idCounter;
85
- const prevLocale = fallbackStore.locale;
86
- fallbackStore.ssr = true;
87
- fallbackStore.suspenseIdCounter = 0;
88
- fallbackStore.idCounter = 0;
89
- fallbackStore.locale = void 0;
90
- _shared.fallbackDepth++;
91
- try {
92
- return fn();
93
- } finally {
94
- _shared.fallbackDepth--;
95
- fallbackStore.ssr = prevSSR;
96
- fallbackStore.suspenseIdCounter = prevCounter;
97
- fallbackStore.idCounter = prevIdCounter;
98
- fallbackStore.locale = prevLocale;
99
- }
100
- }
101
- function withSSR(fn) {
102
- const store = getSSRStore();
103
- const wasSSR = store.ssr;
104
- store.ssr = true;
105
- try {
106
- return fn();
107
- } finally {
108
- if (!wasSSR) store.ssr = false;
109
- }
110
- }
111
-
112
- export {
113
- getSSRStore,
114
- getRequestStore,
115
- isSSR,
116
- getRequestScopedCache,
117
- enableSSR,
118
- disableSSR,
119
- runInSSRContext,
120
- withSSR
121
- };
@@ -1,21 +0,0 @@
1
- // src/utils/prerenderHook.ts
2
- var HOST_KEY = /* @__PURE__ */ Symbol.for("sibujs.prerender.v1");
3
- function host() {
4
- return globalThis[HOST_KEY];
5
- }
6
- function isPrerendering() {
7
- return host() !== void 0;
8
- }
9
- function prerenderRoute() {
10
- return host()?.route ?? null;
11
- }
12
- function prerenderWait(promise) {
13
- host()?.wait(promise);
14
- return promise;
15
- }
16
-
17
- export {
18
- isPrerendering,
19
- prerenderRoute,
20
- prerenderWait
21
- };
@@ -1,245 +0,0 @@
1
- /**
2
- * Converts an element tree to an HTML string for server-side rendering.
3
- * HTML, SVG and MathML elements are serialized; SVG and MathML keep the case
4
- * of their tag and attribute names and their `xlink:` / `xml:` prefixes.
5
- *
6
- * Security: attribute names are validated, `on*` handlers are dropped,
7
- * URL-bearing attributes are routed through `sanitizeUrl`, attribute
8
- * values are escaped against both `"` and `'`, and an SVG animation may not
9
- * target a URL or handler attribute. `<script>` and `<style>` tags are
10
- * stripped from the serialized output.
11
- */
12
- declare function renderToString(element: HTMLElement | DocumentFragment | Node): string;
13
- interface HydrateOptions {
14
- /**
15
- * Enable dev-mode hydration diagnostics. When true, the walker
16
- * compares the server-rendered tree against the client tree and
17
- * logs the first tag mismatch, attribute difference, or child count
18
- * mismatch to the console. Disabled by default.
19
- */
20
- diagnostics?: boolean;
21
- /**
22
- * Called for each detected mismatch instead of the default console
23
- * warning. Useful for routing diagnostics to a telemetry system.
24
- */
25
- onMismatch?: (report: HydrationMismatch) => void;
26
- }
27
- interface HydrationMismatch {
28
- kind: "tag" | "attribute" | "child-count" | "text";
29
- path: string;
30
- serverValue: string;
31
- clientValue: string;
32
- message: string;
33
- }
34
- /**
35
- * Activates a server-rendered SibuJS application by building the live client
36
- * tree and **replacing** the inert server-rendered subtree with it.
37
- *
38
- * SibuJS uses replacement hydration rather than DOM adoption: the server markup
39
- * is discarded, not attached to. It is not the case that listeners and bindings
40
- * are wired onto the existing server nodes — reactive bindings belong to the
41
- * nodes `component()` produced, and adopting server nodes would leave the
42
- * visible DOM permanently frozen.
43
- *
44
- * Consequences worth knowing before deploying SSR:
45
- *
46
- * - DOM node identity is not preserved.
47
- * - Pre-hydration user input, checkbox state, and focus are discarded.
48
- * - Conversely, partial-adoption mismatch bugs are avoided by this design —
49
- * the client tree is always authoritative.
50
- *
51
- * Re-hydrating the same container disposes the previous client tree first.
52
- *
53
- * When `options.diagnostics` is true, the walker reports the first
54
- * server/client mismatch it finds. This is a dev-mode tool — pass
55
- * `diagnostics: false` (or omit it) in production.
56
- *
57
- * @see docs/architecture/hydration.md
58
- */
59
- declare function hydrate(component: () => HTMLElement, container: HTMLElement, options?: HydrateOptions): void;
60
- /**
61
- * Branded type for raw HTML that has been explicitly marked as trusted.
62
- * Use `trustHTML()` to create a value of this type. This prevents
63
- * accidental injection of unsanitized user input into `headExtra`.
64
- */
65
- type TrustedHTML = string & {
66
- readonly __brand: "TrustedHTML";
67
- };
68
- /**
69
- * Mark an HTML string as trusted for use in contexts that accept raw HTML
70
- * (e.g. `renderToDocument({ headExtra })`). Only call this on
71
- * developer-controlled strings — never on user input.
72
- *
73
- * @example
74
- * ```ts
75
- * const extra = trustHTML('<link rel="preconnect" href="https://fonts.googleapis.com">');
76
- * renderToDocument(App, { headExtra: extra });
77
- * ```
78
- */
79
- declare function trustHTML(html: string): TrustedHTML;
80
- /**
81
- * Should this meta entry be dropped entirely?
82
- *
83
- * Delegates to the SHARED meta-refresh policy. This used to be a private copy
84
- * of four `includes()` checks that happened to match the client's private copy
85
- * — two implementations of one rule, so a fix to either would silently diverge
86
- * from the other. The exported name is kept for back-compat; the policy is no
87
- * longer local.
88
- *
89
- * Returns true for a forbidden refresh directive AND for an entry carrying
90
- * duplicate case-insensitive attribute names, since there the value validated
91
- * would not be the value the browser ends up honouring.
92
- */
93
- declare function isDangerousMetaRefresh(metaProps: Record<string, string>): boolean;
94
- /**
95
- * Renders a component to a full HTML document string.
96
- *
97
- * `headExtra` requires a `TrustedHTML` value created via `trustHTML()`.
98
- * This prevents accidental injection of unsanitized user input.
99
- *
100
- * Security: meta/link/bodyAttrs keys are validated against
101
- * `SAFE_ATTR_NAME` (rejecting crafted keys that would break out of the
102
- * attribute context). URL attributes in meta/link/scripts/bodyAttrs pass
103
- * through `sanitizeUrl`. The page `title` is HTML-escaped.
104
- */
105
- declare function renderToDocument(component: () => HTMLElement, options?: {
106
- title?: string;
107
- meta?: Record<string, string>[];
108
- links?: Record<string, string>[];
109
- /**
110
- * External script URLs appended to `<body>`. Each passes the scheme
111
- * allowlist; an allowed URL is still code that runs with the page's
112
- * authority, so this option is an explicit trust decision — first-party
113
- * or pinned URLs only, never request-derived values.
114
- */
115
- scripts?: string[];
116
- bodyAttrs?: Record<string, string>;
117
- /**
118
- * Raw HTML injected into `<head>`. Must be wrapped in `trustHTML()`
119
- * to confirm the content is developer-controlled.
120
- */
121
- headExtra?: TrustedHTML;
122
- }): string;
123
- /**
124
- * Renders a component tree to an async iterable of HTML chunks.
125
- * Enables progressive server-side rendering — the consumer can write
126
- * each chunk to a response stream as it becomes available.
127
- *
128
- * Same security posture as `renderToString`.
129
- */
130
- declare function renderToStream(element: HTMLElement | DocumentFragment | Node): AsyncGenerator<string>;
131
- /**
132
- * Collects the full output of renderToStream into a string.
133
- */
134
- declare function collectStream(stream: AsyncGenerator<string> | AsyncIterable<string>): Promise<string>;
135
- /**
136
- * Renders a component tree to a Web `ReadableStream<string>`.
137
- *
138
- * Uses pull-based backpressure — chunks are produced on demand.
139
- *
140
- * **Environment.** Supported on SibuJS's declared Node runtime (`>=22.3.0`) and
141
- * on any other environment providing both the Web Streams API *and* a DOM
142
- * implementation. Streaming SSR requires the same server DOM as every other
143
- * SibuJS SSR API: this function takes real `Node` objects and walks them, so a
144
- * DOM-less runtime cannot produce the input, let alone render it. Do not read
145
- * "returns a Web stream" as "runs anywhere Web streams exist".
146
- *
147
- * **Semantics.** Suspense boundaries encountered during the walk are resolved
148
- * as a batch before the affected chunk is emitted — the shell is not flushed
149
- * ahead of individually-completing boundaries. See
150
- * `docs/architecture/ssr.md` for the precise streaming and failure semantics.
151
- */
152
- declare function renderToReadableStream(element: HTMLElement | DocumentFragment | Node): ReadableStream<string>;
153
- declare function island(id: string, component: () => HTMLElement): HTMLElement;
154
- declare function hydrateIslands(container: HTMLElement, islands: Record<string, () => HTMLElement>): void;
155
- /**
156
- * Progressively hydrate islands only when they enter the viewport.
157
- * Uses IntersectionObserver to defer hydration of off-screen islands,
158
- * reducing initial JavaScript execution cost.
159
- *
160
- * Returns a cleanup function that disconnects all observers.
161
- */
162
- declare function hydrateProgressively(container: HTMLElement, islands: Record<string, () => HTMLElement>, options?: IntersectionObserverInit): () => void;
163
- /**
164
- * Reset SSR state between requests. Call at the start of each SSR render
165
- * to prevent ID drift in long-lived server processes.
166
- *
167
- * When running inside `runInSSRContext`, each request already owns its
168
- * own counter via AsyncLocalStorage — this hook only touches the
169
- * module-global fallback used outside that context.
170
- */
171
- declare function resetSSRState(): void;
172
- /**
173
- * Create a suspense boundary for SSR streaming.
174
- * Renders fallback HTML inline and returns a promise for the resolved content.
175
- *
176
- * The returned element contains the fallback UI with a `data-sibu-suspense-id`
177
- * marker. The promise resolves to `{ id, html }` once async content is ready.
178
- *
179
- * The promise never rejects. Any failure to produce the content HTML — the
180
- * content factory throwing synchronously, its promise rejecting, the timeout,
181
- * or rendering the resolved element throwing — resolves it with the fallback
182
- * HTML, so the stream still produces a deterministic swap payload.
183
- */
184
- declare function ssrSuspense(props: {
185
- fallback: () => HTMLElement;
186
- content: () => Promise<HTMLElement>;
187
- /** Milliseconds before the content promise is rejected. Defaults to 30000. */
188
- timeoutMs?: number;
189
- }): {
190
- element: HTMLElement;
191
- promise: Promise<{
192
- id: string;
193
- html: string;
194
- }>;
195
- };
196
- /**
197
- * Generate an inline script that swaps a suspense fallback with resolved content.
198
- *
199
- * Security: the `id` is validated against a strict allowlist. Values that
200
- * do not match throw, so an attacker-controlled id cannot inject context
201
- * breakers into the selector or the JS string. `ssrSuspense()`'s internal
202
- * generator always produces allowlist-safe ids.
203
- */
204
- declare function suspenseSwapScript(id: string, nonce?: string): string;
205
- /**
206
- * Renders a component tree with suspense boundaries as a stream.
207
- * Yields the main tree HTML first (including fallback content for suspended
208
- * boundaries), then flushes resolved content with inline swap scripts.
209
- *
210
- * Supports an optional `nonce` that is propagated to the resolved-content
211
- * swap scripts so the stream works with strict CSP.
212
- */
213
- declare function renderToSuspenseStream(element: HTMLElement | DocumentFragment | Node, pendingBoundaries?: Promise<{
214
- id: string;
215
- html: string;
216
- }>[], options?: {
217
- nonce?: string;
218
- }): AsyncGenerator<string>;
219
- /**
220
- * Escape a JSON string for safe embedding inside a `<script>` tag. This
221
- * goes beyond the usual `</script>` concern:
222
- *
223
- * - `<`, `>`, `&` are unicode-escaped so nothing inside a string literal
224
- * can close the script tag or start a new one.
225
- * - `U+2028` (LINE SEPARATOR) and `U+2029` (PARAGRAPH SEPARATOR) are
226
- * unicode-escaped. Before ES2019 these were illegal inside a JS string
227
- * literal, so including them verbatim would cause a SyntaxError on
228
- * older engines and could break out of string context.
229
- */
230
- declare function escapeScriptJson(json: string): string;
231
- declare function serializeState(state: Record<string, unknown>, nonce?: string, options?: {
232
- maxBytes?: number;
233
- }): string;
234
- /**
235
- * Retrieve state that was embedded by `serializeState()` during SSR.
236
- *
237
- * When a `validate` function is provided, it acts as a type guard —
238
- * only data that passes validation is returned. This prevents
239
- * tampered SSR payloads from being trusted by the client.
240
- *
241
- * @param validate Optional type guard to verify data integrity
242
- */
243
- declare function deserializeState<T = Record<string, unknown>>(validate?: (data: unknown) => data is T): T | undefined;
244
-
245
- export { type HydrateOptions as H, type TrustedHTML as T, type HydrationMismatch as a, hydrateIslands as b, collectStream as c, deserializeState as d, escapeScriptJson as e, hydrateProgressively as f, island as g, hydrate as h, isDangerousMetaRefresh as i, renderToReadableStream as j, renderToStream as k, renderToString as l, renderToSuspenseStream as m, resetSSRState as n, ssrSuspense as o, suspenseSwapScript as p, renderToDocument as r, serializeState as s, trustHTML as t };
@@ -1,245 +0,0 @@
1
- /**
2
- * Converts an element tree to an HTML string for server-side rendering.
3
- * HTML, SVG and MathML elements are serialized; SVG and MathML keep the case
4
- * of their tag and attribute names and their `xlink:` / `xml:` prefixes.
5
- *
6
- * Security: attribute names are validated, `on*` handlers are dropped,
7
- * URL-bearing attributes are routed through `sanitizeUrl`, attribute
8
- * values are escaped against both `"` and `'`, and an SVG animation may not
9
- * target a URL or handler attribute. `<script>` and `<style>` tags are
10
- * stripped from the serialized output.
11
- */
12
- declare function renderToString(element: HTMLElement | DocumentFragment | Node): string;
13
- interface HydrateOptions {
14
- /**
15
- * Enable dev-mode hydration diagnostics. When true, the walker
16
- * compares the server-rendered tree against the client tree and
17
- * logs the first tag mismatch, attribute difference, or child count
18
- * mismatch to the console. Disabled by default.
19
- */
20
- diagnostics?: boolean;
21
- /**
22
- * Called for each detected mismatch instead of the default console
23
- * warning. Useful for routing diagnostics to a telemetry system.
24
- */
25
- onMismatch?: (report: HydrationMismatch) => void;
26
- }
27
- interface HydrationMismatch {
28
- kind: "tag" | "attribute" | "child-count" | "text";
29
- path: string;
30
- serverValue: string;
31
- clientValue: string;
32
- message: string;
33
- }
34
- /**
35
- * Activates a server-rendered SibuJS application by building the live client
36
- * tree and **replacing** the inert server-rendered subtree with it.
37
- *
38
- * SibuJS uses replacement hydration rather than DOM adoption: the server markup
39
- * is discarded, not attached to. It is not the case that listeners and bindings
40
- * are wired onto the existing server nodes — reactive bindings belong to the
41
- * nodes `component()` produced, and adopting server nodes would leave the
42
- * visible DOM permanently frozen.
43
- *
44
- * Consequences worth knowing before deploying SSR:
45
- *
46
- * - DOM node identity is not preserved.
47
- * - Pre-hydration user input, checkbox state, and focus are discarded.
48
- * - Conversely, partial-adoption mismatch bugs are avoided by this design —
49
- * the client tree is always authoritative.
50
- *
51
- * Re-hydrating the same container disposes the previous client tree first.
52
- *
53
- * When `options.diagnostics` is true, the walker reports the first
54
- * server/client mismatch it finds. This is a dev-mode tool — pass
55
- * `diagnostics: false` (or omit it) in production.
56
- *
57
- * @see docs/architecture/hydration.md
58
- */
59
- declare function hydrate(component: () => HTMLElement, container: HTMLElement, options?: HydrateOptions): void;
60
- /**
61
- * Branded type for raw HTML that has been explicitly marked as trusted.
62
- * Use `trustHTML()` to create a value of this type. This prevents
63
- * accidental injection of unsanitized user input into `headExtra`.
64
- */
65
- type TrustedHTML = string & {
66
- readonly __brand: "TrustedHTML";
67
- };
68
- /**
69
- * Mark an HTML string as trusted for use in contexts that accept raw HTML
70
- * (e.g. `renderToDocument({ headExtra })`). Only call this on
71
- * developer-controlled strings — never on user input.
72
- *
73
- * @example
74
- * ```ts
75
- * const extra = trustHTML('<link rel="preconnect" href="https://fonts.googleapis.com">');
76
- * renderToDocument(App, { headExtra: extra });
77
- * ```
78
- */
79
- declare function trustHTML(html: string): TrustedHTML;
80
- /**
81
- * Should this meta entry be dropped entirely?
82
- *
83
- * Delegates to the SHARED meta-refresh policy. This used to be a private copy
84
- * of four `includes()` checks that happened to match the client's private copy
85
- * — two implementations of one rule, so a fix to either would silently diverge
86
- * from the other. The exported name is kept for back-compat; the policy is no
87
- * longer local.
88
- *
89
- * Returns true for a forbidden refresh directive AND for an entry carrying
90
- * duplicate case-insensitive attribute names, since there the value validated
91
- * would not be the value the browser ends up honouring.
92
- */
93
- declare function isDangerousMetaRefresh(metaProps: Record<string, string>): boolean;
94
- /**
95
- * Renders a component to a full HTML document string.
96
- *
97
- * `headExtra` requires a `TrustedHTML` value created via `trustHTML()`.
98
- * This prevents accidental injection of unsanitized user input.
99
- *
100
- * Security: meta/link/bodyAttrs keys are validated against
101
- * `SAFE_ATTR_NAME` (rejecting crafted keys that would break out of the
102
- * attribute context). URL attributes in meta/link/scripts/bodyAttrs pass
103
- * through `sanitizeUrl`. The page `title` is HTML-escaped.
104
- */
105
- declare function renderToDocument(component: () => HTMLElement, options?: {
106
- title?: string;
107
- meta?: Record<string, string>[];
108
- links?: Record<string, string>[];
109
- /**
110
- * External script URLs appended to `<body>`. Each passes the scheme
111
- * allowlist; an allowed URL is still code that runs with the page's
112
- * authority, so this option is an explicit trust decision — first-party
113
- * or pinned URLs only, never request-derived values.
114
- */
115
- scripts?: string[];
116
- bodyAttrs?: Record<string, string>;
117
- /**
118
- * Raw HTML injected into `<head>`. Must be wrapped in `trustHTML()`
119
- * to confirm the content is developer-controlled.
120
- */
121
- headExtra?: TrustedHTML;
122
- }): string;
123
- /**
124
- * Renders a component tree to an async iterable of HTML chunks.
125
- * Enables progressive server-side rendering — the consumer can write
126
- * each chunk to a response stream as it becomes available.
127
- *
128
- * Same security posture as `renderToString`.
129
- */
130
- declare function renderToStream(element: HTMLElement | DocumentFragment | Node): AsyncGenerator<string>;
131
- /**
132
- * Collects the full output of renderToStream into a string.
133
- */
134
- declare function collectStream(stream: AsyncGenerator<string> | AsyncIterable<string>): Promise<string>;
135
- /**
136
- * Renders a component tree to a Web `ReadableStream<string>`.
137
- *
138
- * Uses pull-based backpressure — chunks are produced on demand.
139
- *
140
- * **Environment.** Supported on SibuJS's declared Node runtime (`>=22.3.0`) and
141
- * on any other environment providing both the Web Streams API *and* a DOM
142
- * implementation. Streaming SSR requires the same server DOM as every other
143
- * SibuJS SSR API: this function takes real `Node` objects and walks them, so a
144
- * DOM-less runtime cannot produce the input, let alone render it. Do not read
145
- * "returns a Web stream" as "runs anywhere Web streams exist".
146
- *
147
- * **Semantics.** Suspense boundaries encountered during the walk are resolved
148
- * as a batch before the affected chunk is emitted — the shell is not flushed
149
- * ahead of individually-completing boundaries. See
150
- * `docs/architecture/ssr.md` for the precise streaming and failure semantics.
151
- */
152
- declare function renderToReadableStream(element: HTMLElement | DocumentFragment | Node): ReadableStream<string>;
153
- declare function island(id: string, component: () => HTMLElement): HTMLElement;
154
- declare function hydrateIslands(container: HTMLElement, islands: Record<string, () => HTMLElement>): void;
155
- /**
156
- * Progressively hydrate islands only when they enter the viewport.
157
- * Uses IntersectionObserver to defer hydration of off-screen islands,
158
- * reducing initial JavaScript execution cost.
159
- *
160
- * Returns a cleanup function that disconnects all observers.
161
- */
162
- declare function hydrateProgressively(container: HTMLElement, islands: Record<string, () => HTMLElement>, options?: IntersectionObserverInit): () => void;
163
- /**
164
- * Reset SSR state between requests. Call at the start of each SSR render
165
- * to prevent ID drift in long-lived server processes.
166
- *
167
- * When running inside `runInSSRContext`, each request already owns its
168
- * own counter via AsyncLocalStorage — this hook only touches the
169
- * module-global fallback used outside that context.
170
- */
171
- declare function resetSSRState(): void;
172
- /**
173
- * Create a suspense boundary for SSR streaming.
174
- * Renders fallback HTML inline and returns a promise for the resolved content.
175
- *
176
- * The returned element contains the fallback UI with a `data-sibu-suspense-id`
177
- * marker. The promise resolves to `{ id, html }` once async content is ready.
178
- *
179
- * The promise never rejects. Any failure to produce the content HTML — the
180
- * content factory throwing synchronously, its promise rejecting, the timeout,
181
- * or rendering the resolved element throwing — resolves it with the fallback
182
- * HTML, so the stream still produces a deterministic swap payload.
183
- */
184
- declare function ssrSuspense(props: {
185
- fallback: () => HTMLElement;
186
- content: () => Promise<HTMLElement>;
187
- /** Milliseconds before the content promise is rejected. Defaults to 30000. */
188
- timeoutMs?: number;
189
- }): {
190
- element: HTMLElement;
191
- promise: Promise<{
192
- id: string;
193
- html: string;
194
- }>;
195
- };
196
- /**
197
- * Generate an inline script that swaps a suspense fallback with resolved content.
198
- *
199
- * Security: the `id` is validated against a strict allowlist. Values that
200
- * do not match throw, so an attacker-controlled id cannot inject context
201
- * breakers into the selector or the JS string. `ssrSuspense()`'s internal
202
- * generator always produces allowlist-safe ids.
203
- */
204
- declare function suspenseSwapScript(id: string, nonce?: string): string;
205
- /**
206
- * Renders a component tree with suspense boundaries as a stream.
207
- * Yields the main tree HTML first (including fallback content for suspended
208
- * boundaries), then flushes resolved content with inline swap scripts.
209
- *
210
- * Supports an optional `nonce` that is propagated to the resolved-content
211
- * swap scripts so the stream works with strict CSP.
212
- */
213
- declare function renderToSuspenseStream(element: HTMLElement | DocumentFragment | Node, pendingBoundaries?: Promise<{
214
- id: string;
215
- html: string;
216
- }>[], options?: {
217
- nonce?: string;
218
- }): AsyncGenerator<string>;
219
- /**
220
- * Escape a JSON string for safe embedding inside a `<script>` tag. This
221
- * goes beyond the usual `</script>` concern:
222
- *
223
- * - `<`, `>`, `&` are unicode-escaped so nothing inside a string literal
224
- * can close the script tag or start a new one.
225
- * - `U+2028` (LINE SEPARATOR) and `U+2029` (PARAGRAPH SEPARATOR) are
226
- * unicode-escaped. Before ES2019 these were illegal inside a JS string
227
- * literal, so including them verbatim would cause a SyntaxError on
228
- * older engines and could break out of string context.
229
- */
230
- declare function escapeScriptJson(json: string): string;
231
- declare function serializeState(state: Record<string, unknown>, nonce?: string, options?: {
232
- maxBytes?: number;
233
- }): string;
234
- /**
235
- * Retrieve state that was embedded by `serializeState()` during SSR.
236
- *
237
- * When a `validate` function is provided, it acts as a type guard —
238
- * only data that passes validation is returned. This prevents
239
- * tampered SSR payloads from being trusted by the client.
240
- *
241
- * @param validate Optional type guard to verify data integrity
242
- */
243
- declare function deserializeState<T = Record<string, unknown>>(validate?: (data: unknown) => data is T): T | undefined;
244
-
245
- export { type HydrateOptions as H, type TrustedHTML as T, type HydrationMismatch as a, hydrateIslands as b, collectStream as c, deserializeState as d, escapeScriptJson as e, hydrateProgressively as f, island as g, hydrate as h, isDangerousMetaRefresh as i, renderToReadableStream as j, renderToStream as k, renderToString as l, renderToSuspenseStream as m, resetSSRState as n, ssrSuspense as o, suspenseSwapScript as p, renderToDocument as r, serializeState as s, trustHTML as t };