sibujs 4.12.0 → 4.13.1

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 (74) hide show
  1. package/dist/browser.cjs +71 -18
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +6618 -6178
  4. package/dist/build.d.cts +554 -415
  5. package/dist/build.d.ts +554 -415
  6. package/dist/build.js +2091 -1735
  7. package/dist/cdn.dev.global.js +12 -12
  8. package/dist/cdn.full.dev.global.js +13 -13
  9. package/dist/cdn.full.global.js +12 -12
  10. package/dist/cdn.global.js +12 -12
  11. package/dist/{chunk-WFRQ6D7H.js → chunk-22OPSWMF.js} +1 -1
  12. package/dist/{chunk-ZJCHY2IB.js → chunk-2NC56RGY.js} +1 -1
  13. package/dist/{chunk-NB7TFSJE.js → chunk-2O6JJCUR.js} +4 -4
  14. package/dist/{chunk-B2Y5BJSP.js → chunk-4UTGDVSA.js} +70 -16
  15. package/dist/{chunk-NAVLCP4S.js → chunk-5RIBLY2N.js} +4 -4
  16. package/dist/{chunk-T5O2CUHV.js → chunk-5XUGJM3J.js} +1 -1
  17. package/dist/{chunk-HXT2RNH5.js → chunk-ADZHPN2B.js} +1 -1
  18. package/dist/chunk-B36ADEIR.js +21 -0
  19. package/dist/{chunk-DFZL3AX7.js → chunk-C73VBPEF.js} +9 -5
  20. package/dist/{chunk-WH4U2VUE.js → chunk-CPQKWCJ2.js} +13 -5
  21. package/dist/{chunk-LEUEKK4G.js → chunk-EU7T7EB3.js} +2 -2
  22. package/dist/{chunk-QLG5IK7F.js → chunk-G3Z2FEBR.js} +4 -4
  23. package/dist/{chunk-ZPY2UAKM.js → chunk-J4X7ICH4.js} +3 -3
  24. package/dist/{chunk-XX4BRMWF.js → chunk-K4LNUT5L.js} +1 -1
  25. package/dist/{chunk-CI4W6XAU.js → chunk-KC62VURU.js} +3 -3
  26. package/dist/chunk-N5TBYXHW.js +17 -0
  27. package/dist/{chunk-653KGQS2.js → chunk-OIKD7YDY.js} +2 -2
  28. package/dist/{chunk-LYTUTXQP.js → chunk-PBJYCE2Z.js} +46 -4
  29. package/dist/{chunk-EMB5PG7V.js → chunk-QC3NP47A.js} +1 -1
  30. package/dist/{chunk-IHA62NGJ.js → chunk-QKFVMIAV.js} +1 -1
  31. package/dist/{chunk-LXBMVGVB.js → chunk-QZ47OZ25.js} +3 -3
  32. package/dist/{chunk-ZTYCCBU3.js → chunk-VFPLWUT7.js} +44 -26
  33. package/dist/{chunk-RK7EPQPG.js → chunk-YFTBCCVH.js} +1 -1
  34. package/dist/data.cjs +71 -18
  35. package/dist/data.js +5 -5
  36. package/dist/datePicker-DxuxWpgF.d.cts +285 -0
  37. package/dist/datePicker-DxuxWpgF.d.ts +285 -0
  38. package/dist/devtools.cjs +71 -18
  39. package/dist/devtools.js +4 -4
  40. package/dist/ecosystem.cjs +82 -21
  41. package/dist/ecosystem.js +7 -7
  42. package/dist/extras.cjs +131 -23
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +21 -20
  46. package/dist/index.cjs +115 -37
  47. package/dist/index.d.cts +59 -5
  48. package/dist/index.d.ts +59 -5
  49. package/dist/index.js +10 -10
  50. package/dist/motion.cjs +69 -16
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +71 -18
  53. package/dist/patterns.js +5 -5
  54. package/dist/performance.cjs +69 -16
  55. package/dist/performance.js +4 -4
  56. package/dist/plugins.cjs +1421 -996
  57. package/dist/plugins.d.cts +132 -3
  58. package/dist/plugins.d.ts +132 -3
  59. package/dist/plugins.js +262 -11
  60. package/dist/routeMiddleware-B1sp4P7a.d.ts +688 -0
  61. package/dist/routeMiddleware-CedQTsLK.d.cts +688 -0
  62. package/dist/ssr.cjs +3607 -3524
  63. package/dist/ssr.d.cts +20 -671
  64. package/dist/ssr.d.ts +20 -671
  65. package/dist/ssr.js +15 -7
  66. package/dist/testing.cjs +71 -18
  67. package/dist/testing.js +2 -2
  68. package/dist/ui.cjs +78 -18
  69. package/dist/ui.js +8 -7
  70. package/dist/widgets.cjs +1352 -952
  71. package/dist/widgets.d.cts +100 -268
  72. package/dist/widgets.d.ts +100 -268
  73. package/dist/widgets.js +316 -7
  74. package/package.json +9 -1
package/dist/ssr.d.cts CHANGED
@@ -1,689 +1,38 @@
1
+ export { A as ActionFn, a as ActionResult, H as Head, I as ISROptions, L as LoadRemoteModuleOptions, b as LoadWasmOptions, M as MicroApp, c as MicroAppConfig, d as MiddlewareFn, S as SSGOptions, e as SSGResult, f as ScrollRestorationOptions, g as ServiceWorkerState, h as SharedScope, U as UseWorkerFnReturn, i as UseWorkerReturn, W as WasmConfig, j as WasmModuleState, k as WorkerPool, l as clearWasmCache, m as composeMiddleware, n as createAction, o as createISR, p as createMicroApp, q as createMiddlewareChain, r as createSharedScope, s as createWasmBridge, t as createWorkerPool, u as defineRemoteComponent, v as generateStaticSite, w as isWasmCached, x as loadRemoteModule, y as loadWasmModule, z as loadWasmModuleWithOptions, B as preloadWasm, C as scrollRestoration, D as serviceWorker, E as setCanonical, F as setStructuredData, G as wasm, J as worker, K as workerFn } from './routeMiddleware-CedQTsLK.cjs';
1
2
  export { H as HydrateOptions, a as HydrationMismatch, T as TrustedHTML, c as collectStream, d as deserializeState, e as escapeScriptJson, h as hydrate, b as hydrateIslands, f as hydrateProgressively, i as isDangerousMetaRefresh, g as island, r as renderToDocument, j as renderToReadableStream, k as renderToStream, l as renderToString, m as renderToSuspenseStream, n as resetSSRState, s as serializeState, o as ssrSuspense, p as suspenseSwapScript, t as trustHTML } from './ssr-Db0Sgdu3.cjs';
2
- import { C as Component } from './types-CJFViL6Q.cjs';
3
+ import './types-CJFViL6Q.cjs';
3
4
 
4
- interface HeadProps {
5
- title?: string | (() => string);
6
- meta?: Record<string, string | (() => string)>[];
7
- /**
8
- * `<link>` elements to add to `<head>`.
9
- *
10
- * TRUST BOUNDARY for stylesheets: `{ rel: "stylesheet", href }` is the
11
- * framework's explicit API for a stylesheet whose URL is a runtime value.
12
- * The generic writers refuse to let a runtime `href` become an applied
13
- * stylesheet at all (see `utils/elementPolicy.ts`), because a well-formed
14
- * URL is not trusted CSS. Naming it here is the trust decision: first-party
15
- * or pinned URLs only, and a CSP `style-src` as the second layer.
16
- */
17
- link?: Record<string, string>[];
18
- /**
19
- * External scripts to add to `<head>`.
20
- *
21
- * TRUST BOUNDARY: this is the framework's explicit API for loading a script
22
- * whose URL is a runtime value, and naming it here IS the trust decision —
23
- * the URL passes the scheme allowlist, but an allowed `https:` URL is still a
24
- * program that runs with the page's full authority. Pass only URLs you
25
- * control or pin (a first-party path, a CDN URL with `integrity`). The
26
- * generic writers refuse to let a runtime value choose a `<script>` source
27
- * at all; see `docs/architecture/attribute-security.md` § Trust model.
28
- */
29
- script?: Record<string, string>[];
30
- /**
31
- * The document `<base>`.
32
- *
33
- * TRUST BOUNDARY: `href` passes the scheme allowlist, but an allowed `https:`
34
- * base still re-homes every relative URL on the page — relative `<script
35
- * src>`, stylesheets, form actions and `fetch("/api")` alike. Treat it like a
36
- * script URL: first-party values only.
37
- */
38
- base?: {
39
- href?: string;
40
- target?: string;
41
- };
42
- }
43
5
  /**
44
- * Head() manages document <head> tags reactively.
6
+ * Whether this code is running inside the build-time pre-renderer.
45
7
  *
46
- * META SECURITY: each meta entry is committed TRANSACTIONALLY. All of its
47
- * attributes — static and reactive — are resolved into one snapshot, duplicate
48
- * case-insensitive names are rejected, and the assembled snapshot is validated
49
- * against the shared meta-refresh policy before anything reaches the DOM. An
50
- * approved snapshot is then materialised on a fresh `<meta>` element while it is
51
- * still detached and swapped in with a single `replaceWith()`, so no partially
52
- * updated element is ever connected. A snapshot that fails validation withdraws
53
- * the element entirely. See `utils/metaRefresh.ts`; the same policy governs SSR.
8
+ * Use it to skip work that has no meaning at build time — analytics, a
9
+ * websocket, a request to an API that is not reachable from the build machine —
10
+ * so the route still renders its static shell.
54
11
  *
55
- * NATIVE REFRESH DIRECTIVES MUST BE STATIC. A browser processes a meta refresh
56
- * when the element is INSERTED — it records the pending navigation there and
57
- * then, and removing or replacing the element afterwards is not a defined way to
58
- * cancel it. `Head()` therefore never publishes a snapshot whose effective
59
- * `http-equiv` is `refresh` from an entry that contains any reactive attribute,
60
- * even when the destination is allowed: what cannot be withdrawn must not be
61
- * handed over. Static refresh directives work as before, and every other
62
- * reactive meta entry — description, keywords, Open Graph, non-refresh
63
- * `http-equiv` — is unaffected.
64
- *
65
- * Supports dynamic title, meta tags, link tags, and structured data.
66
- * Each instance tracks its own elements and effects for independent cleanup.
12
+ * @returns `true` while a route is being pre-rendered.
67
13
  */
68
- declare function Head(props: HeadProps): Comment;
14
+ declare function isPrerendering(): boolean;
69
15
  /**
70
- * Sets structured data (JSON-LD) for SEO.
71
- *
72
- * Security: the serialized JSON is passed through `escapeScriptJsonLocal`
73
- * which unicode-escapes `<`, `>`, `&`, `U+2028`, and `U+2029`. This is
74
- * defense-in-depth: when the element is inserted via `document.createElement`
75
- * + `textContent` the browser will NOT re-parse the body, so `</script>`
76
- * cannot break out of the tag at insertion time. However, tools that
77
- * later serialize `document.head.innerHTML` DO re-parse, and the server
78
- * side of any SSR roundtrip would see the raw text. Escaping here makes
79
- * both paths safe.
80
- */
81
- declare function setStructuredData(data: Record<string, unknown>): void;
82
- /**
83
- * Sets the canonical URL for the page.
84
- */
85
- declare function setCanonical(url: string): void;
86
-
87
- interface UseWorkerReturn<TInput, TOutput> {
88
- post(data: TInput): void;
89
- result: () => TOutput | null;
90
- error: () => Error | null;
91
- loading: () => boolean;
92
- terminate(): void;
93
- }
94
- /**
95
- * worker creates a Web Worker from an inline function and provides
96
- * reactive state for its result, error, and loading status.
97
- *
98
- * The workerFn receives messages via the standard `onmessage` handler
99
- * and should call `postMessage` to send results back. It is serialized
100
- * into a Blob URL, so it must be self-contained (no closures).
101
- *
102
- * **CSP Warning:** This function serializes the provided function via `.toString()`
103
- * and executes it inside a `blob:` URL Worker. This is equivalent to `eval()` and
104
- * is incompatible with strict Content Security Policies that restrict
105
- * `worker-src 'self'` or block `blob:` URLs. Additionally:
106
- * - Minifiers may break captured variable references (closures silently fail).
107
- * - Module-level imports are NOT accessible inside the worker.
108
- * - Never pass user-controlled or dynamically constructed functions — this
109
- * would be equivalent to `eval()` on untrusted input.
16
+ * The route being pre-rendered, or `null` outside the pre-renderer.
110
17
  *
111
- * @param workerFn The function body to run inside the worker.
112
- * It receives `self` as the worker global scope.
113
- * @returns An object with post, result, error, loading, and terminate.
18
+ * @returns The route path, e.g. `"/pricing"`.
114
19
  */
115
- declare function worker<TInput = unknown, TOutput = unknown>(workerFn: (e: MessageEvent<TInput>) => void): UseWorkerReturn<TInput, TOutput>;
116
- interface UseWorkerFnReturn<TArgs extends unknown[], TResult> {
117
- run(...args: TArgs): Promise<TResult>;
118
- loading: () => boolean;
119
- terminate(): void;
120
- }
20
+ declare function prerenderRoute(): string | null;
121
21
  /**
122
- * workerFn wraps a pure function so it runs inside a Web Worker.
22
+ * Make the pre-renderer wait for `promise` before it serializes the page.
23
+ * A no-op in the browser, so it can wrap any data load unconditionally.
123
24
  *
124
- * The function must be self-contained -- it cannot reference variables
125
- * from the outer scope. Arguments are serialized via postMessage.
25
+ * `fetch()` calls are awaited automatically; register anything else the
26
+ * rendered content depends on (a timer, IndexedDB, a worker).
126
27
  *
127
- * **Trust boundary:** the function's source is evaluated in a `blob:` worker,
128
- * which is equivalent to `eval()`. Only a function object is accepted — never
129
- * a string, and never a function built from untrusted input.
130
- *
131
- * @param fn A pure function to execute in a worker thread.
132
- * @returns An object with run, loading, and terminate.
133
- */
134
- declare function workerFn<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => TResult): UseWorkerFnReturn<TArgs, TResult>;
135
- interface WorkerPool<TInput, TOutput> {
136
- execute(data: TInput): Promise<TOutput>;
137
- terminate(): void;
138
- }
139
- /**
140
- * createWorkerPool creates a pool of workers for parallel task execution.
141
- *
142
- * Tasks are distributed across workers using round-robin scheduling.
143
- * Each worker is created from the same inline function.
144
- *
145
- * **Trust boundary:** as with `worker()`, the function's source is evaluated in
146
- * a `blob:` worker. Only a function object is accepted, never a string.
147
- *
148
- * @param workerFn The function body to run inside each worker.
149
- * @param poolSize Number of workers in the pool (defaults to navigator.hardwareConcurrency or 4).
150
- * @returns An object with execute and terminate.
151
- */
152
- declare function createWorkerPool<TInput = unknown, TOutput = unknown>(workerFn: (e: MessageEvent<TInput>) => void, poolSize?: number): WorkerPool<TInput, TOutput>;
153
-
154
- /**
155
- * WebAssembly integration for SibuJS.
156
- * Provides hooks and utilities to load, cache, and use WASM modules
157
- * for performance-critical operations.
158
- */
159
- interface WasmModuleState<T extends object = Record<string, unknown>> {
160
- /** The instantiated WASM module exports, null until loaded */
161
- instance: T | null;
162
- /** Loading state */
163
- loading: boolean;
164
- /** Error if loading failed */
165
- error: Error | null;
166
- /** Whether the module has been loaded successfully */
167
- ready: boolean;
168
- }
169
- /**
170
- * Configuration for the `wasm()` reactive wrapper.
171
- *
172
- * Deliberately the SAME option bag as the underlying `loadWasmModule()`
173
- * primitive rather than a hand-copied subset. The primitive REQUIRES an
174
- * explicit origin policy for URL sources (`allowedOrigins`, or an explicit
175
- * `unsafelyAllowAnyOrigin` opt-in), and the wrapper previously had no way to
176
- * express one — so `wasm("/math.wasm")` could only ever reject, and the public
177
- * convenience API was unusable for its documented primary use case. Extending
178
- * the primitive's type keeps the two from drifting again.
179
- */
180
- interface WasmConfig extends LoadWasmOptions {
181
- }
182
- /**
183
- * Hook to load and use a WebAssembly module reactively.
184
- * Returns reactive state that updates when the module loads.
185
- *
186
- * A URL source needs an explicit origin policy — WASM is compiled code with
187
- * imports into JS memory, so fetching it from an unvetted URL is a supply-chain
188
- * risk equivalent to importing a remote module (CWE-829). Pass `allowedOrigins`,
189
- * or `unsafelyAllowAnyOrigin: true` to opt out deliberately. An `ArrayBuffer` /
190
- * `Uint8Array` source needs neither: the bytes are already in hand.
28
+ * @param promise Work the rendered page depends on.
29
+ * @returns `promise`, unchanged.
191
30
  *
192
31
  * @example
193
32
  * ```ts
194
- * const math = wasm<{ add: (a: number, b: number) => number }>(
195
- * 'https://cdn.example.com/math.wasm',
196
- * { allowedOrigins: ['https://cdn.example.com'] },
197
- * );
198
- * // In reactive context:
199
- * if (math.ready()) {
200
- * const result = math.instance()!.add(1, 2);
201
- * }
202
- * ```
203
- *
204
- * @example Same-origin asset — still an explicit decision.
205
- * ```ts
206
- * const math = wasm('/math.wasm', { allowedOrigins: [location.origin] });
33
+ * const products = prerenderWait(loadProductsFromCache());
207
34
  * ```
208
35
  */
209
- declare function wasm<T extends object = Record<string, unknown>>(source: string | ArrayBuffer | Uint8Array, config?: WasmConfig): {
210
- instance: () => T | null;
211
- loading: () => boolean;
212
- error: () => Error | null;
213
- ready: () => boolean;
214
- reload: () => Promise<void>;
215
- };
216
- /**
217
- * Load and instantiate a WebAssembly module.
218
- * Supports loading from URL, ArrayBuffer, or Uint8Array.
219
- *
220
- * Caching: keyed by `cacheKey` (or, for a URL source, the URL itself). A keyed
221
- * load is memoized as a **singleton instance** — every caller with the same key
222
- * receives the *same* `WebAssembly.Instance`, which shares one linear memory and
223
- * mutable globals. This is intentional (load-once / reuse), but it means callers
224
- * that need isolated state must use distinct cache keys, or pass a non-URL source
225
- * with no `cacheKey` (which instantiates fresh every call). Compiled modules are
226
- * immutable and always safe to share.
227
- */
228
- interface LoadWasmOptions {
229
- imports?: WebAssembly.Imports;
230
- cacheKey?: string;
231
- allowedOrigins?: string[];
232
- /** Required when source is a URL and allowedOrigins is empty. WASM is
233
- * compiled code with imports into JS memory — fetching from any URL is
234
- * a supply-chain risk equivalent to remote module import (CWE-829). */
235
- unsafelyAllowAnyOrigin?: boolean;
236
- }
237
- /**
238
- * Load and instantiate a WebAssembly module — **positional/legacy form**.
239
- *
240
- * The second parameter is always `WebAssembly.Imports` and the third is always
241
- * the cache key. There is no structural guessing, so a module namespace legally
242
- * named `imports` or `cacheKey` is passed through unharmed.
243
- *
244
- * It previously accepted `WebAssembly.Imports | LoadWasmOptions` and decided
245
- * between them at runtime by probing for `allowedOrigins` /
246
- * `unsafelyAllowAnyOrigin`. That discriminator was unsound in both directions:
247
- * an options bag carrying only `imports`/`cacheKey` was read as an import
248
- * namespace (so `cacheKey` was dropped and the documented keyed-singleton
249
- * guarantee silently did not hold), while a genuine namespace *named*
250
- * `allowedOrigins` would have been read as options. No structural test can
251
- * separate the two, because both are plain objects with caller-chosen keys — so
252
- * the union was removed rather than re-guessed.
253
- *
254
- * For anything beyond imports and a cache key — notably the origin policy a URL
255
- * source requires — use {@link loadWasmModuleWithOptions}.
256
- *
257
- * @see loadWasmModuleWithOptions
258
- */
259
- declare function loadWasmModule(source: string | ArrayBuffer | Uint8Array, imports?: WebAssembly.Imports, cacheKey?: string): Promise<WebAssembly.Instance>;
260
- /**
261
- * Load and instantiate a WebAssembly module — **options form**.
262
- *
263
- * Unambiguous by construction: options live in their own parameter, so a WASM
264
- * module namespace named `imports`, `cacheKey`, or `allowedOrigins` is just a
265
- * namespace and nothing has to be inferred from object shape.
266
- *
267
- * This is the form to use for a URL source, since the origin policy
268
- * (`allowedOrigins`, or an explicit `unsafelyAllowAnyOrigin`) can only be
269
- * expressed here.
270
- *
271
- * @example
272
- * ```ts
273
- * const instance = await loadWasmModuleWithOptions("https://cdn.example.com/math.wasm", {
274
- * allowedOrigins: ["https://cdn.example.com"],
275
- * imports: { env: { log: console.log } },
276
- * cacheKey: "math",
277
- * });
278
- * ```
279
- */
280
- declare function loadWasmModuleWithOptions(source: string | ArrayBuffer | Uint8Array, opts?: LoadWasmOptions): Promise<WebAssembly.Instance>;
281
- /**
282
- * Preload and compile a WASM module without instantiating it.
283
- * The compiled module is cached for instant instantiation later.
284
- */
285
- declare function preloadWasm(url: string, options?: {
286
- allowedOrigins?: string[];
287
- unsafelyAllowAnyOrigin?: boolean;
288
- }): Promise<void>;
289
- /**
290
- * Create a type-safe bridge to a WASM module with automatic memory management.
291
- * Provides helpers for passing strings and arrays between JS and WASM.
292
- */
293
- declare function createWasmBridge<T extends object>(instance: WebAssembly.Instance): {
294
- exports: T;
295
- memory: WebAssembly.Memory;
296
- /** Allocate bytes in WASM memory (requires WASM to export malloc) */
297
- alloc: (size: number) => number;
298
- /** Free allocated memory (requires WASM to export free) */
299
- free: (ptr: number) => void;
300
- /** Write a string to WASM memory, returns pointer */
301
- writeString: (str: string) => {
302
- ptr: number;
303
- len: number;
304
- };
305
- /** Read a string from WASM memory */
306
- readString: (ptr: number, len: number) => string;
307
- /** Write a typed array to WASM memory, returns pointer */
308
- writeArray: (arr: ArrayLike<number>) => {
309
- ptr: number;
310
- len: number;
311
- };
312
- /** Read a Float64Array from WASM memory */
313
- readF64Array: (ptr: number, len: number) => Float64Array;
314
- };
315
- /**
316
- * Invalidate the module, instance, and in-flight WASM cache generations.
317
- *
318
- * CONTRACT: work already started may still resolve to the callers that started
319
- * it, but must never repopulate the caches after the clear. A load in flight
320
- * across this call therefore still returns its instance to whoever awaited it,
321
- * while the cache stays empty and the next load for that key compiles and
322
- * instantiates afresh.
323
- *
324
- * This is an invalidation BARRIER, not a `Map.clear()`: emptying the maps alone
325
- * would let the invalidated work write its results straight back in.
326
- */
327
- declare function clearWasmCache(): void;
328
- /**
329
- * Check if a WASM module is cached.
330
- */
331
- declare function isWasmCached(key: string): boolean;
332
-
333
- interface MicroAppConfig {
334
- /** Unique name for this micro-frontend instance */
335
- name: string;
336
- /** Optional host element to mount into. Defaults to a new div. */
337
- container?: HTMLElement;
338
- /** If true, use Shadow DOM for style isolation */
339
- shadow?: boolean;
340
- }
341
- interface MicroApp {
342
- /** Mount a component into this micro-app container */
343
- mount(component: () => HTMLElement): void;
344
- /** Unmount the currently rendered component and clean up */
345
- unmount(): void;
346
- /** The outer host element */
347
- element: HTMLElement;
348
- }
349
- interface SharedScope<T extends object> {
350
- /** Get the current value for a key */
351
- get<K extends keyof T>(key: K): T[K];
352
- /** Set a value for a key, notifying all subscribers */
353
- set<K extends keyof T>(key: K, value: T[K]): void;
354
- /** Subscribe to changes on a specific key. Returns an unsubscribe function. */
355
- subscribe<K extends keyof T>(key: K, callback: (value: T[K]) => void): () => void;
356
- }
357
- /**
358
- * Creates an isolated micro-frontend container.
359
- *
360
- * Each micro-app gets its own DOM boundary. When `shadow: true` is set the
361
- * component renders inside a Shadow DOM root so its styles are fully isolated
362
- * from the host page.
363
- *
364
- * @example
365
- * ```ts
366
- * const app = createMicroApp({ name: "widget", shadow: true });
367
- * document.body.appendChild(app.element);
368
- *
369
- * app.mount(() => div("Hello from micro-app!"));
370
- *
371
- * // Later, tear it down:
372
- * app.unmount();
373
- * ```
374
- */
375
- declare function createMicroApp(config: MicroAppConfig): MicroApp;
376
- /**
377
- * Dynamically load a remote ES module by URL.
378
- *
379
- * Modules are cached by URL so repeated calls with the same URL return the
380
- * same promise without issuing another network request.
381
- *
382
- * An origin policy is REQUIRED: importing a remote module is remote code
383
- * execution, so the call is refused unless you either restrict it with
384
- * `allowedOrigins` or opt out deliberately with `unsafelyAllowAnyOrigin`
385
- * (CWE-829).
386
- *
387
- * @example
388
- * ```ts
389
- * const charts = await loadRemoteModule("https://cdn.example.com/charts.js", {
390
- * allowedOrigins: ["https://cdn.example.com"],
391
- * });
392
- * const el = charts.BarChart({ data: [1, 2, 3] });
393
- * ```
394
- */
395
- interface LoadRemoteModuleOptions {
396
- allowedOrigins?: string[];
397
- /** Required when allowedOrigins is empty. Forces a deliberate decision
398
- * to import code from any URL — equivalent to remote eval (CWE-829). */
399
- unsafelyAllowAnyOrigin?: boolean;
400
- }
401
- declare function loadRemoteModule(url: string, optionsOrAllowedOrigins?: string[] | LoadRemoteModuleOptions): Promise<unknown>;
402
- /**
403
- * Loads the remote module whose `default` export is the component. Its root may
404
- * be any `Element` — an SVG root included — using the public `Component` type
405
- * rather than a private `() => HTMLElement` that forced a cast.
406
- */
407
- type RemoteLoader<R extends Element = HTMLElement> = () => Promise<{
408
- default: Component<void, R>;
409
- }>;
410
- /**
411
- * Register a remote component that loads on demand.
412
- *
413
- * Returns a component factory function. On first call it shows a loading
414
- * placeholder, fetches the remote module, then swaps in the real component.
415
- * Subsequent calls render instantly from the cached module.
416
- *
417
- * The load is owner-scoped: if the container is disposed before the module
418
- * arrives, the module is still cached (it is shared and expensive to fetch) but
419
- * the component is NOT instantiated and nothing is written into the dead
420
- * container.
421
- *
422
- * @example
423
- * ```ts
424
- * const RemoteHeader = defineRemoteComponent(
425
- * "remote-header",
426
- * () =>
427
- * loadRemoteModule("https://cdn.example.com/header.js", {
428
- * allowedOrigins: ["https://cdn.example.com"],
429
- * })
430
- * );
431
- *
432
- * // Use it like any local component
433
- * document.body.appendChild(RemoteHeader());
434
- * ```
435
- */
436
- declare function defineRemoteComponent<R extends Element = HTMLElement>(name: string, loader: RemoteLoader<R>): Component<void, R | HTMLElement>;
437
- /**
438
- * Create a shared state scope that enables communication between independent
439
- * micro-frontend instances.
440
- *
441
- * Each key in the scope can be read, written, and subscribed to independently.
442
- * This is intentionally kept simpler than a full global store so micro-apps
443
- * can share data with minimal coupling.
444
- *
445
- * @example
446
- * ```ts
447
- * const shared = createSharedScope({ user: null, theme: "light" });
448
- *
449
- * // Micro-app A sets a value
450
- * shared.set("user", { name: "Alice" });
451
- *
452
- * // Micro-app B subscribes to changes
453
- * const unsub = shared.subscribe("user", (user) => {
454
- * console.log("User changed:", user);
455
- * });
456
- *
457
- * // Later
458
- * unsub();
459
- * ```
460
- */
461
- declare function createSharedScope<T extends object>(initialState: T): SharedScope<T>;
462
-
463
- interface ServiceWorkerState {
464
- registration: () => ServiceWorkerRegistration | null;
465
- isReady: () => boolean;
466
- isUpdateAvailable: () => boolean;
467
- error: () => Error | null;
468
- update: () => Promise<void>;
469
- unregister: () => Promise<boolean>;
470
- }
471
- /**
472
- * serviceWorker registers and manages a service worker.
473
- *
474
- * TRUST BOUNDARY: `scriptUrl` is CODE. A service worker runs with authority
475
- * over every page in its scope and persists across reloads, so this is the
476
- * strongest code-loading primitive in the framework. The browser enforces
477
- * same-origin, a secure context and a JavaScript MIME type — it does NOT
478
- * protect against a same-origin URL that serves attacker-influenced content
479
- * (a JSONP endpoint, an upload directory). Pass only a literal path to a worker
480
- * script you ship; never a value derived from the URL, storage or an API
481
- * response.
482
- *
483
- * LIFECYCLE CONTRACT
484
- * ------------------
485
- * Registration is asynchronous and `unregister()` can be called at any point
486
- * during it, so this tracks four distinct situations rather than one boolean:
487
- *
488
- * registering register() in flight, nothing to unregister yet
489
- * active registration adopted, listeners attached
490
- * unregister asked requested before the registration resolved — the arriving
491
- * registration is unregistered rather than adopted, so the
492
- * browser never keeps a worker SibuJS has forgotten
493
- * unregistered terminal, and only entered once unregister() actually
494
- * RETURNED TRUE
495
- *
496
- * The last point is the important one. `ServiceWorkerRegistration.unregister()`
497
- * returns `false` when the browser declined — the worker is still installed and
498
- * still controlling pages. Treating that as teardown (detaching listeners,
499
- * dropping the registration) left the wrapper permanently blind to a worker
500
- * that was very much alive: no update tracking, no registration, no way back.
501
- * A failed unregister therefore changes nothing.
502
- */
503
- declare function serviceWorker(scriptUrl: string, options?: RegistrationOptions): ServiceWorkerState;
504
-
505
- interface SSGOptions {
506
- routes: string[];
507
- renderFn: (path: string) => Promise<string>;
508
- outDir?: string;
509
- }
510
- interface SSGResult {
511
- pages: Array<{
512
- path: string;
513
- html: string;
514
- }>;
515
- errors: Array<{
516
- path: string;
517
- error: Error;
518
- }>;
519
- }
520
- /**
521
- * Generate a static site by iterating over routes and collecting rendered HTML.
522
- * This is a pure async function — it does NOT write files, only returns results.
523
- */
524
- declare function generateStaticSite(options: SSGOptions): Promise<SSGResult>;
525
-
526
- interface ISROptions<T> {
527
- revalidateAfter: number;
528
- fetcher: (ctx?: {
529
- signal: AbortSignal;
530
- }) => Promise<T>;
531
- initialData?: T;
532
- }
533
- /**
534
- * Creates an Incremental Static Regeneration (ISR) resource.
535
- * Data is fetched initially, then automatically revalidated once it goes stale.
536
- *
537
- * `isStale()` is a reactive signal: it flips to `true` when `revalidateAfter`
538
- * elapses since the last successful fetch (effects re-run at that moment), stays
539
- * `true` while a revalidation is pending or after one fails, and returns to
540
- * `false` when a revalidation succeeds.
541
- *
542
- * `revalidate()` called while a revalidation is running joins it instead of
543
- * starting another: the fetcher runs once, and every caller's promise settles
544
- * — resolving, or rejecting with the same error — when that fetch does.
545
- *
546
- * @throws RangeError when `revalidateAfter` is not a positive finite number.
547
- */
548
- declare function createISR<T>(options: ISROptions<T>): {
549
- data: () => T | undefined;
550
- isStale: () => boolean;
551
- revalidate: () => Promise<void>;
552
- dispose: () => void;
553
- };
554
-
555
- type ActionFn<T = unknown> = (data: FormData | Record<string, unknown>) => Promise<T>;
556
- interface ActionResult<T> {
557
- data: () => T | undefined;
558
- error: () => Error | undefined;
559
- loading: () => boolean;
560
- submit: (data: FormData | Record<string, unknown>) => Promise<T>;
561
- }
562
- /**
563
- * Creates a managed action for handling POST/PUT/DELETE-style mutations.
564
- * Provides reactive loading, error, and data state via signal.
565
- * State updates are batched to avoid redundant notifications.
566
- */
567
- declare function createAction<T>(actionFn: ActionFn<T>): ActionResult<T>;
568
-
569
- interface ScrollRestorationOptions {
570
- /**
571
- * `"auto"` (default) manages history-entry identity and restores the
572
- * destination on `popstate`. It tags the entry the page started on, tags each
573
- * entry you announce with `onNavigation()`, saves the outgoing position, and
574
- * takes over `history.scrollRestoration` so the browser does not restore in
575
- * parallel.
576
- *
577
- * What auto mode CANNOT do is notice a `history.pushState` it was not told
578
- * about — no library can, short of monkey-patching `history` globally. Entries
579
- * created without `onNavigation()` carry no identity and are simply not
580
- * restored (a safe no-op, not a wrong position).
581
- *
582
- * `"manual"` attaches no listener, claims no native restoration, and tags
583
- * nothing — you call `save()` / `restore()` yourself.
584
- */
585
- mode?: "auto" | "manual";
586
- /**
587
- * Identifies the entry the user is currently on. Called once at construction
588
- * to seed the current entry, and consulted as a fallback when nothing has
589
- * been saved yet.
590
- *
591
- * Point it at whatever your app treats as a history identity — e.g.
592
- * `() => router.location().key`. Pathname alone is usually wrong: `?page=2`
593
- * and `#section` are distinct scroll positions to a user.
594
- */
595
- getKey?: () => string | null;
596
- /**
597
- * History-state property used to tag entries so a `popstate` can name its
598
- * DESTINATION. `popstate` reports the state of the entry being restored, and
599
- * that is the only reliable way to know where the user just landed.
600
- */
601
- stateKey?: string;
602
- }
603
- /**
604
- * Manages scroll position saving and restoration keyed by route/key.
605
- *
606
- * AUTO MODE
607
- * ---------
608
- * `"auto"` previously attached a `popstate` listener that only ever called
609
- * `save()` — so the documented "save/restore on popstate" behaviour was half
610
- * implemented, and going Back never returned the viewport anywhere. The whole
611
- * point of the feature was the half that was missing.
612
- *
613
- * A real restore needs to know WHICH entry the user landed on, so auto mode
614
- * tags history entries with their key (`stateKey`) and the `popstate` handler
615
- * reads that tag off `event.state`. On each pop it:
616
- *
617
- * 1. saves the position of the entry being LEFT (unless it is also the
618
- * destination — a same-key pop is not a departure, and saving there would
619
- * overwrite the stored position with the current one, destroying exactly
620
- * the value about to be restored)
621
- * 2. restores the destination's saved position, if one exists
622
- *
623
- * An unknown or absent destination key is a safe SibuJS no-op: no guessed
624
- * position is applied. Note this is not a hand-off to the browser — auto mode
625
- * leases `history.scrollRestoration` to `"manual"` while active, so nothing
626
- * else is restoring either. The viewport simply stays where the engine left it.
627
- *
628
- * WHAT "AUTO" MEANS, EXACTLY
629
- * --------------------------
630
- * Reacting to `popstate` automatically is not enough on its own: the handler
631
- * can only restore an entry that HAS an identity, and originally nothing ever
632
- * gave one to the entry the page started on. The first Back a user pressed
633
- * therefore restored nothing. Auto mode now owns identity as well as reaction:
634
- *
635
- * - the INITIAL entry is tagged at construction, and
636
- * - `onNavigation(key)` tags each entry the application creates.
637
- *
638
- * That second half is an explicit hook rather than magic, and deliberately so:
639
- * a library cannot observe arbitrary `history.pushState` calls without patching
640
- * `history` globally, which would surprise every other consumer of it. So the
641
- * honest contract is:
642
- *
643
- * > Auto mode restores any entry it was given identity for, and never guesses
644
- * > about entries it was not told about.
645
- *
646
- * Auto mode also leases `history.scrollRestoration = "manual"` while active, so
647
- * the browser is not restoring the viewport at the same time SibuJS is. The
648
- * previous value is restored when the last controller is disposed.
649
- */
650
- declare function scrollRestoration(options?: ScrollRestorationOptions): {
651
- save: (key: string) => void;
652
- restore: (key: string) => void;
653
- /**
654
- * Tell auto mode that the application created a new history entry.
655
- *
656
- * Records the outgoing entry's position, tags the new entry with `key`, and
657
- * makes it current. Call it immediately after your `pushState` (before any
658
- * scrolling), so the position captured is the one the user is leaving.
659
- */
660
- onNavigation: (key: string) => void;
661
- getPosition: (key: string) => {
662
- x: number;
663
- y: number;
664
- } | undefined;
665
- dispose: () => void;
666
- };
667
-
668
- type MiddlewareFn = (context: {
669
- path: string;
670
- params: Record<string, string>;
671
- }, next: () => void | Promise<void>) => void | Promise<void>;
672
- /**
673
- * Composes multiple middleware functions into a single middleware.
674
- * Each middleware must call next() to proceed to the next one.
675
- */
676
- declare function composeMiddleware(...fns: MiddlewareFn[]): MiddlewareFn;
677
- /**
678
- * Creates a middleware chain with a builder API.
679
- * Use `use()` to add middleware, and `run()` to execute the chain.
680
- */
681
- declare function createMiddlewareChain(): {
682
- use: (fn: MiddlewareFn) => void;
683
- run: (context: {
684
- path: string;
685
- params: Record<string, string>;
686
- }) => Promise<void>;
687
- };
36
+ declare function prerenderWait<T extends PromiseLike<unknown>>(promise: T): T;
688
37
 
689
- export { type ActionFn, type ActionResult, Head, type ISROptions, type LoadRemoteModuleOptions, type LoadWasmOptions, type MicroApp, type MicroAppConfig, type MiddlewareFn, type SSGOptions, type SSGResult, type ScrollRestorationOptions, type ServiceWorkerState, type SharedScope, type UseWorkerFnReturn, type UseWorkerReturn, type WasmConfig, type WasmModuleState, type WorkerPool, clearWasmCache, composeMiddleware, createAction, createISR, createMicroApp, createMiddlewareChain, createSharedScope, createWasmBridge, createWorkerPool, defineRemoteComponent, generateStaticSite, isWasmCached, loadRemoteModule, loadWasmModule, loadWasmModuleWithOptions, preloadWasm, scrollRestoration, serviceWorker, setCanonical, setStructuredData, wasm, worker, workerFn };
38
+ export { isPrerendering, prerenderRoute, prerenderWait };