@async/framework 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +122 -14
- package/{framework.d.ts → browser.d.ts} +118 -4
- package/{framework.js → browser.js} +898 -127
- package/browser.min.js +1 -0
- package/{framework.ts → browser.ts} +899 -128
- package/{framework.umd.js → browser.umd.js} +898 -127
- package/browser.umd.min.js +1 -0
- package/package.json +45 -30
- package/server.d.ts +690 -0
- package/src/app.js +110 -11
- package/src/async-signal.js +32 -4
- package/src/boundary-receiver.js +302 -0
- package/src/browser.js +16 -0
- package/src/component.js +42 -7
- package/src/index.js +6 -2
- package/src/loader.js +42 -10
- package/src/request-context.js +40 -0
- package/src/router.js +15 -2
- package/src/scheduler.js +300 -0
- package/src/server-entry.js +20 -0
- package/src/server-registry.js +97 -0
- package/src/server.js +5 -88
- package/src/signals.js +38 -6
- package/framework.min.js +0 -3820
- package/framework.umd.min.js +0 -3843
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 0.9.0 - 2026-06-17
|
|
6
|
+
|
|
7
|
+
- Added `createBoundaryReceiver(...)` for optional out-of-order boundary patch
|
|
8
|
+
delivery with per-boundary sequence checks, signal/cache effect ordering,
|
|
9
|
+
scheduler flushing, redirects, and destroyed parent-scope filtering.
|
|
10
|
+
|
|
11
|
+
## 0.8.0 - 2026-06-17
|
|
12
|
+
|
|
13
|
+
- Split browser and server entrypoints with `@async/framework/browser`,
|
|
14
|
+
`@async/framework/server`, browser-only CDN bundles, and server-only local
|
|
15
|
+
function registry exports.
|
|
16
|
+
- Added `createRequestContextStore(...)` for Node request-scoped server
|
|
17
|
+
function context using `AsyncLocalStorage`.
|
|
18
|
+
- Added the Layer 1.5 scheduler for deterministic signal binding, lifecycle,
|
|
19
|
+
effect, async, and post-flush phases.
|
|
20
|
+
- Added browser microtask scheduling by default and manual scheduler flushing for
|
|
21
|
+
server render paths.
|
|
22
|
+
- Threaded `this.scheduler` through loader, handler, component, async signal,
|
|
23
|
+
server, router, and partial contexts.
|
|
24
|
+
|
|
3
25
|
## 0.7.0 - 2026-06-17
|
|
4
26
|
|
|
5
27
|
- Added router navigation abort/version guards so stale route partials cannot
|
package/README.md
CHANGED
|
@@ -53,6 +53,8 @@ primitives. It keeps the runtime small and explicit:
|
|
|
53
53
|
- Handlers live in a registry and run through delegated DOM events.
|
|
54
54
|
- Async signals use native `AbortSignal` cancellation and suppress stale async
|
|
55
55
|
completions.
|
|
56
|
+
- A small scheduler batches signal-driven DOM bindings, lifecycle callbacks,
|
|
57
|
+
effects, and async refreshes without adding a render loop.
|
|
56
58
|
- Browser and server cache declarations are structurally split.
|
|
57
59
|
- Boundaries can be swapped out of order and rescanned, which keeps server
|
|
58
60
|
streaming and partial HTML replacement simple.
|
|
@@ -68,7 +70,7 @@ next level on every app.
|
|
|
68
70
|
|
|
69
71
|
| Layer | Name | Requirement | Purpose |
|
|
70
72
|
| --- | --- | --- | --- |
|
|
71
|
-
| 1 | Runtime bootloader | No build. CDN or direct ESM import. | Signals, async signals, handlers, command events, lifecycle pseudo-events, scoped fragments, and boundary swaps. |
|
|
73
|
+
| 1 | Runtime bootloader | No build. CDN or direct ESM import. | Signals, async signals, scheduler, handlers, command events, lifecycle pseudo-events, scoped fragments, and boundary swaps. |
|
|
72
74
|
| 2 | App/server layer | Light server integration. No app compiler required. | `Async.use(...)`, router modes, server function proxy, partial registry, SSR output, browser activation, and split browser/server cache. |
|
|
73
75
|
| 3 | Authoring build | Build step required. | JSX, ESM, and TypeScript authoring that lowers into Layer 1 HTML attributes and Layer 2 registries. |
|
|
74
76
|
| 4 | Chunk and resumability metadata | Build metadata required. | Lazy module manifests, visibility/prefetch hints, resource graphs, and resumability records that the bootloader can consume. |
|
|
@@ -90,18 +92,18 @@ and package lifecycle tooling. Browser consumers import ESM directly.
|
|
|
90
92
|
|
|
91
93
|
## CDN
|
|
92
94
|
|
|
93
|
-
The package ships
|
|
95
|
+
The package ships browser CDN artifacts for UNPKG and can be loaded without a
|
|
94
96
|
build step. Use `@latest` for quick prototypes, and pin an exact version in
|
|
95
97
|
production:
|
|
96
98
|
|
|
97
99
|
| File | Format | Use |
|
|
98
100
|
| --- | --- | --- |
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
101
|
+
| `browser.js` | ESM | Readable browser module bundle |
|
|
102
|
+
| `browser.min.js` | ESM | Compact browser module bundle |
|
|
103
|
+
| `browser.umd.js` | UMD | Readable script-tag/CommonJS-style bundle |
|
|
104
|
+
| `browser.umd.min.js` | UMD | Compact script-tag/CommonJS-style bundle and default CDN file |
|
|
105
|
+
| `browser.ts` | Bundled TypeScript source | TS-aware runtimes and higher-layer tooling |
|
|
106
|
+
| `browser.d.ts` | Type declarations | TypeScript declarations for the browser API |
|
|
105
107
|
|
|
106
108
|
```html
|
|
107
109
|
<main async:container>
|
|
@@ -113,7 +115,7 @@ production:
|
|
|
113
115
|
import {
|
|
114
116
|
Async,
|
|
115
117
|
createSignal
|
|
116
|
-
} from "https://unpkg.com/@async/framework@latest/
|
|
118
|
+
} from "https://unpkg.com/@async/framework@latest/browser.js";
|
|
117
119
|
|
|
118
120
|
Async.use({
|
|
119
121
|
signal: {
|
|
@@ -136,7 +138,7 @@ For a plain script tag, use the UMD bundle. In this UMD-only global form,
|
|
|
136
138
|
call `Async.Loader(...)` directly.
|
|
137
139
|
|
|
138
140
|
```html
|
|
139
|
-
<script src="https://unpkg.com/@async/framework@latest/
|
|
141
|
+
<script src="https://unpkg.com/@async/framework@latest/browser.umd.min.js"></script>
|
|
140
142
|
<script>
|
|
141
143
|
Async.use({
|
|
142
144
|
signal: {
|
|
@@ -159,7 +161,7 @@ You can also use an import map so app code imports `@async/framework` by name:
|
|
|
159
161
|
<script type="importmap">
|
|
160
162
|
{
|
|
161
163
|
"imports": {
|
|
162
|
-
"@async/framework": "https://unpkg.com/@async/framework@latest/
|
|
164
|
+
"@async/framework": "https://unpkg.com/@async/framework@latest/browser.js"
|
|
163
165
|
}
|
|
164
166
|
}
|
|
165
167
|
</script>
|
|
@@ -187,6 +189,10 @@ You can also use an import map so app code imports `@async/framework` by name:
|
|
|
187
189
|
|
|
188
190
|
## Core API
|
|
189
191
|
|
|
192
|
+
For npm consumers, `@async/framework` uses conditional exports: browser-aware
|
|
193
|
+
tooling receives the browser entry, while Node receives the server-capable
|
|
194
|
+
entry. Use explicit subpaths when the target matters.
|
|
195
|
+
|
|
190
196
|
```js
|
|
191
197
|
import {
|
|
192
198
|
Async,
|
|
@@ -204,8 +210,8 @@ import {
|
|
|
204
210
|
createRegistryStore,
|
|
205
211
|
createRouteRegistry,
|
|
206
212
|
createRouter,
|
|
213
|
+
createScheduler,
|
|
207
214
|
createServerProxy,
|
|
208
|
-
createServerRegistry,
|
|
209
215
|
createSignalRegistry,
|
|
210
216
|
defineAttributeConfig,
|
|
211
217
|
defineApp,
|
|
@@ -218,7 +224,16 @@ import {
|
|
|
218
224
|
readSnapshot,
|
|
219
225
|
route,
|
|
220
226
|
signal
|
|
221
|
-
} from "@async/framework";
|
|
227
|
+
} from "@async/framework/browser";
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Server-only APIs live behind the server entry:
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
import {
|
|
234
|
+
createRequestContextStore,
|
|
235
|
+
createServerRegistry
|
|
236
|
+
} from "@async/framework/server";
|
|
222
237
|
```
|
|
223
238
|
|
|
224
239
|
`Loader` is the canonical loader factory. `AsyncLoader` remains as a
|
|
@@ -373,6 +388,49 @@ signals.set("product.title", "Headphones");
|
|
|
373
388
|
|
|
374
389
|
`signal(...)` remains a compatibility alias for `createSignal(...)`.
|
|
375
390
|
|
|
391
|
+
### Scheduler
|
|
392
|
+
|
|
393
|
+
The scheduler is the Layer 1.5 ordering engine. Signal writes are still
|
|
394
|
+
synchronous:
|
|
395
|
+
|
|
396
|
+
```js
|
|
397
|
+
signals.set("count", 3);
|
|
398
|
+
signals.get("count");
|
|
399
|
+
// 3
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
DOM bindings, component lifecycle callbacks, component effects, and async signal
|
|
403
|
+
refreshes are scheduled through deterministic phases:
|
|
404
|
+
|
|
405
|
+
```txt
|
|
406
|
+
binding -> lifecycle -> effect -> async -> post
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Browser runtimes use a microtask scheduler by default. Server runtimes use a
|
|
410
|
+
manual scheduler and drain it during `runtime.render(...)`.
|
|
411
|
+
|
|
412
|
+
```js
|
|
413
|
+
import {
|
|
414
|
+
createScheduler
|
|
415
|
+
} from "@async/framework";
|
|
416
|
+
|
|
417
|
+
const scheduler = createScheduler({
|
|
418
|
+
strategy: "manual"
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
const runtime = Async.start({
|
|
422
|
+
root: document,
|
|
423
|
+
scheduler
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
signals.set("count", 1);
|
|
427
|
+
await scheduler.flush();
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Most apps do not need to call the scheduler directly. It is exposed for tests,
|
|
431
|
+
custom runtimes, streaming receivers, and higher layers that need explicit flush
|
|
432
|
+
boundaries.
|
|
433
|
+
|
|
376
434
|
### Async Signals
|
|
377
435
|
|
|
378
436
|
Async signals add loading state, error state, versions, refresh, and cancel to a
|
|
@@ -401,6 +459,7 @@ The async function context includes:
|
|
|
401
459
|
| `this.id` | Current async signal id |
|
|
402
460
|
| `this.version` | Run version |
|
|
403
461
|
| `this.abort` | Native `AbortSignal` with non-enumerable `cancel(reason?)` |
|
|
462
|
+
| `this.scheduler` | Current runtime scheduler |
|
|
404
463
|
| `this.refresh()` | Start a new run |
|
|
405
464
|
|
|
406
465
|
`this.abort` can be passed directly to `fetch` or to `delay`:
|
|
@@ -619,6 +678,10 @@ Server registries run locally on the server and proxies call an HTTP endpoint
|
|
|
619
678
|
from the browser. Both expose the same dotted call shape.
|
|
620
679
|
|
|
621
680
|
```js
|
|
681
|
+
import {
|
|
682
|
+
createServerRegistry
|
|
683
|
+
} from "@async/framework/server";
|
|
684
|
+
|
|
622
685
|
const server = createServerRegistry({
|
|
623
686
|
"cart.add"(productId, quantity) {
|
|
624
687
|
return {
|
|
@@ -634,6 +697,10 @@ const server = createServerRegistry({
|
|
|
634
697
|
Client proxy:
|
|
635
698
|
|
|
636
699
|
```js
|
|
700
|
+
import {
|
|
701
|
+
createServerProxy
|
|
702
|
+
} from "@async/framework/browser";
|
|
703
|
+
|
|
637
704
|
const server = createServerProxy({
|
|
638
705
|
endpoint: "/__async/server",
|
|
639
706
|
signals,
|
|
@@ -983,6 +1050,47 @@ loader.swap(
|
|
|
983
1050
|
`swap(boundaryId, fragmentOrTemplate)` replaces the boundary contents and
|
|
984
1051
|
rescans the inserted fragment.
|
|
985
1052
|
|
|
1053
|
+
When boundary patches can arrive independently, use `createBoundaryReceiver`.
|
|
1054
|
+
It keeps per-boundary sequence state, applies signal/cache effects before the
|
|
1055
|
+
HTML swap, flushes scheduled bindings, and ignores stale child patches after a
|
|
1056
|
+
parent scope is destroyed.
|
|
1057
|
+
|
|
1058
|
+
```js
|
|
1059
|
+
import { createBoundaryReceiver } from "@async/framework/browser";
|
|
1060
|
+
|
|
1061
|
+
const receiver = createBoundaryReceiver({
|
|
1062
|
+
loader: runtime.loader,
|
|
1063
|
+
signals: runtime.signals,
|
|
1064
|
+
cache: runtime.browser.cache,
|
|
1065
|
+
scheduler: runtime.scheduler,
|
|
1066
|
+
router: runtime.router
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
await receiver.apply({
|
|
1070
|
+
boundary: "product",
|
|
1071
|
+
seq: 1,
|
|
1072
|
+
signals: {
|
|
1073
|
+
product: { title: "Keyboard" }
|
|
1074
|
+
},
|
|
1075
|
+
cache: {
|
|
1076
|
+
browser: {
|
|
1077
|
+
"product:sku-1": { title: "Keyboard" }
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
html: `
|
|
1081
|
+
<article>
|
|
1082
|
+
<h1 signal:text="product.title"></h1>
|
|
1083
|
+
<button type="button" on:click="server.cart.add(productId)">Add</button>
|
|
1084
|
+
</article>
|
|
1085
|
+
`
|
|
1086
|
+
});
|
|
1087
|
+
```
|
|
1088
|
+
|
|
1089
|
+
Sequence numbers are tracked per boundary: `hero` patch `10` can apply before
|
|
1090
|
+
`reviews` patch `2`, while a later `hero` patch `9` is ignored. The receiver
|
|
1091
|
+
does not add transport management, a transaction log, hydration, or component
|
|
1092
|
+
rerendering.
|
|
1093
|
+
|
|
986
1094
|
## Examples
|
|
987
1095
|
|
|
988
1096
|
| Example | Shows |
|
|
@@ -1022,7 +1130,7 @@ pnpm run release:check
|
|
|
1022
1130
|
such as signals, handlers, server functions, partials, routes, and components.
|
|
1023
1131
|
It writes `.async/registry-manifest.json` plus a per-file cache at
|
|
1024
1132
|
`.async/registry-lint-cache.json`, skips generated root bundles such as
|
|
1025
|
-
`
|
|
1133
|
+
`browser.umd.min.js`, and fails only when the same registry type and id are
|
|
1026
1134
|
declared with different normalized content. Duplicate declarations with the
|
|
1027
1135
|
same content are reported as dedupe candidates, not errors.
|
|
1028
1136
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Generated by scripts/build-framework-bundle.js. Do not edit by hand.
|
|
2
|
-
//
|
|
2
|
+
// Browser type declarations for @async/framework/browser.
|
|
3
3
|
|
|
4
4
|
export type RuntimeTarget = "browser" | "server";
|
|
5
5
|
export type RouterMode = "csr" | "spa" | "ssr" | "ssr-spa" | "mpa";
|
|
@@ -40,6 +40,52 @@ export interface TemplateResult {
|
|
|
40
40
|
readonly values: readonly unknown[];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
export type SchedulerStrategy = "microtask" | "manual";
|
|
44
|
+
export type SchedulerPhase = "binding" | "lifecycle" | "effect" | "async" | "post" | string;
|
|
45
|
+
export interface SchedulerJob {
|
|
46
|
+
id: number;
|
|
47
|
+
phase: SchedulerPhase;
|
|
48
|
+
scope?: unknown;
|
|
49
|
+
boundary?: string;
|
|
50
|
+
key?: string;
|
|
51
|
+
canceled: boolean;
|
|
52
|
+
cancel(): void;
|
|
53
|
+
}
|
|
54
|
+
export interface SchedulerOptions {
|
|
55
|
+
strategy?: SchedulerStrategy;
|
|
56
|
+
phases?: SchedulerPhase[];
|
|
57
|
+
maxDepth?: number;
|
|
58
|
+
onError?(error: unknown, job: SchedulerJob): void;
|
|
59
|
+
}
|
|
60
|
+
export interface SchedulerInspection {
|
|
61
|
+
strategy: SchedulerStrategy;
|
|
62
|
+
phases: SchedulerPhase[];
|
|
63
|
+
pending: Record<string, number>;
|
|
64
|
+
scopesDestroyed: number;
|
|
65
|
+
flushing: boolean;
|
|
66
|
+
scheduled: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface Scheduler {
|
|
69
|
+
strategy: SchedulerStrategy;
|
|
70
|
+
phases: SchedulerPhase[];
|
|
71
|
+
batch<T>(fn: () => T): T;
|
|
72
|
+
enqueue(phase: SchedulerPhase, job: () => MaybePromise<unknown>, options?: { scope?: unknown; boundary?: string; key?: string }): Cleanup;
|
|
73
|
+
flush(): Promise<void>;
|
|
74
|
+
flushScope(scope: unknown): Promise<void>;
|
|
75
|
+
afterFlush(job: () => MaybePromise<unknown>, options?: { scope?: unknown; boundary?: string; key?: string }): Cleanup;
|
|
76
|
+
cancelScope(scope: unknown): this;
|
|
77
|
+
markScopeDestroyed(scope: unknown): this;
|
|
78
|
+
isScopeDestroyed(scope: unknown): boolean;
|
|
79
|
+
destroy(): void;
|
|
80
|
+
inspect(): SchedulerInspection;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface RequestContextStore {
|
|
84
|
+
run<T>(context: Record<string, unknown> | undefined, fn: () => T): T;
|
|
85
|
+
get(): Record<string, unknown> | undefined;
|
|
86
|
+
snapshot(): Record<string, unknown>;
|
|
87
|
+
}
|
|
88
|
+
|
|
43
89
|
export interface Signal<T = unknown> {
|
|
44
90
|
readonly kind: "signal";
|
|
45
91
|
value: T;
|
|
@@ -113,6 +159,7 @@ export interface AsyncSignalContext {
|
|
|
113
159
|
router?: Router;
|
|
114
160
|
loader?: LoaderInstance;
|
|
115
161
|
cache?: CacheRegistry;
|
|
162
|
+
scheduler?: Scheduler;
|
|
116
163
|
refresh(): Promise<unknown>;
|
|
117
164
|
}
|
|
118
165
|
|
|
@@ -149,6 +196,7 @@ export interface HandlerContext {
|
|
|
149
196
|
loader?: LoaderInstance;
|
|
150
197
|
router?: Router;
|
|
151
198
|
cache?: CacheRegistry;
|
|
199
|
+
scheduler?: Scheduler;
|
|
152
200
|
event?: Event;
|
|
153
201
|
element?: Element;
|
|
154
202
|
el?: Element;
|
|
@@ -192,6 +240,7 @@ export interface ServerContext {
|
|
|
192
240
|
locals?: unknown;
|
|
193
241
|
abort?: AbortSignal;
|
|
194
242
|
cache?: CacheRegistry;
|
|
243
|
+
scheduler?: Scheduler;
|
|
195
244
|
server: ServerNamespace;
|
|
196
245
|
[key: string]: unknown;
|
|
197
246
|
}
|
|
@@ -216,6 +265,7 @@ export interface ServerProxyOptions {
|
|
|
216
265
|
loader?: LoaderInstance;
|
|
217
266
|
router?: Router;
|
|
218
267
|
cache?: CacheRegistry;
|
|
268
|
+
scheduler?: Scheduler;
|
|
219
269
|
headers?: Record<string, string>;
|
|
220
270
|
}
|
|
221
271
|
|
|
@@ -263,6 +313,7 @@ export interface PartialContext {
|
|
|
263
313
|
browserCache?: CacheRegistry;
|
|
264
314
|
partials: PartialRegistry;
|
|
265
315
|
abort?: AbortSignal;
|
|
316
|
+
scheduler?: Scheduler;
|
|
266
317
|
request?: Request;
|
|
267
318
|
locals?: unknown;
|
|
268
319
|
[key: string]: unknown;
|
|
@@ -315,6 +366,7 @@ export interface RouterOptions {
|
|
|
315
366
|
fetch?: typeof fetch;
|
|
316
367
|
routeEndpoint?: string;
|
|
317
368
|
attributes?: AttributeConfig;
|
|
369
|
+
scheduler?: Scheduler;
|
|
318
370
|
}
|
|
319
371
|
|
|
320
372
|
export interface Router {
|
|
@@ -328,6 +380,7 @@ export interface Router {
|
|
|
328
380
|
server?: ServerNamespace;
|
|
329
381
|
cache?: CacheRegistry;
|
|
330
382
|
partials?: PartialRegistry;
|
|
383
|
+
scheduler: Scheduler;
|
|
331
384
|
attributes: NormalizedAttributeConfig;
|
|
332
385
|
start(): this;
|
|
333
386
|
match(url: string | URL): RouteMatch | null;
|
|
@@ -346,6 +399,7 @@ export interface ComponentContext {
|
|
|
346
399
|
server?: ServerNamespace;
|
|
347
400
|
router?: Router;
|
|
348
401
|
cache?: CacheRegistry;
|
|
402
|
+
scheduler?: Scheduler;
|
|
349
403
|
signal<T = unknown>(initial: T): SignalRef<T>;
|
|
350
404
|
signal<T = unknown>(name: string, initial: T): SignalRef<T>;
|
|
351
405
|
computed<T = unknown>(name: string, fn: (this: ComponentContext) => T): SignalRef<T>;
|
|
@@ -382,6 +436,7 @@ export interface LoaderOptions {
|
|
|
382
436
|
server?: ServerNamespace;
|
|
383
437
|
router?: Router;
|
|
384
438
|
cache?: CacheRegistry;
|
|
439
|
+
scheduler?: Scheduler;
|
|
385
440
|
attributes?: AttributeConfig;
|
|
386
441
|
}
|
|
387
442
|
|
|
@@ -392,6 +447,7 @@ export interface LoaderInstance {
|
|
|
392
447
|
server?: ServerNamespace;
|
|
393
448
|
router?: Router;
|
|
394
449
|
cache?: CacheRegistry;
|
|
450
|
+
scheduler: Scheduler;
|
|
395
451
|
attributes: NormalizedAttributeConfig;
|
|
396
452
|
start(): this;
|
|
397
453
|
scan(rootOrFragment?: Document | Element | DocumentFragment): this;
|
|
@@ -403,6 +459,53 @@ export interface LoaderInstance {
|
|
|
403
459
|
export type AsyncLoaderOptions = LoaderOptions;
|
|
404
460
|
export type AsyncLoaderInstance = LoaderInstance;
|
|
405
461
|
|
|
462
|
+
export interface BoundaryPatch {
|
|
463
|
+
boundary: string;
|
|
464
|
+
seq: number;
|
|
465
|
+
html?: TemplateLike;
|
|
466
|
+
signals?: Record<string, unknown>;
|
|
467
|
+
cache?: { browser?: Record<string, unknown> };
|
|
468
|
+
redirect?: string;
|
|
469
|
+
error?: unknown;
|
|
470
|
+
parentScope?: string;
|
|
471
|
+
scope?: string;
|
|
472
|
+
meta?: Record<string, unknown>;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export type BoundaryApplyResult =
|
|
476
|
+
| { status: "applied"; boundary: string; seq: number }
|
|
477
|
+
| { status: "ignored-stale"; boundary: string; seq: number; lastSeq: number }
|
|
478
|
+
| { status: "ignored-destroyed"; boundary: string; seq: number; parentScope?: string }
|
|
479
|
+
| { status: "redirected"; boundary: string; seq: number; redirect: string }
|
|
480
|
+
| { status: "errored"; boundary: string; seq: number; error: Error };
|
|
481
|
+
|
|
482
|
+
export interface BoundaryReceiverInspection {
|
|
483
|
+
destroyed: boolean;
|
|
484
|
+
boundaries: Record<string, { lastSeq: number; applied: number; ignored: number; errored?: number; lastStatus?: BoundaryApplyResult["status"] }>;
|
|
485
|
+
recent: Array<{ boundary: string; seq: number; status: BoundaryApplyResult["status"]; lastSeq?: number; parentScope?: string; redirect?: string }>;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export interface BoundaryReceiverOptions {
|
|
489
|
+
loader: LoaderInstance;
|
|
490
|
+
signals?: SignalRegistry;
|
|
491
|
+
cache?: CacheRegistry;
|
|
492
|
+
scheduler?: Scheduler;
|
|
493
|
+
router?: Router;
|
|
494
|
+
onApply?(result: BoundaryApplyResult, patch: BoundaryPatch): void;
|
|
495
|
+
onIgnore?(result: BoundaryApplyResult, patch: BoundaryPatch): void;
|
|
496
|
+
onError?(error: Error, result: BoundaryApplyResult, patch: BoundaryPatch): void;
|
|
497
|
+
throwOnError?: boolean;
|
|
498
|
+
recentLimit?: number;
|
|
499
|
+
isScopeDestroyed?(scope: string): boolean;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
export interface BoundaryReceiver {
|
|
503
|
+
apply(patch: BoundaryPatch): Promise<BoundaryApplyResult>;
|
|
504
|
+
inspect(): BoundaryReceiverInspection;
|
|
505
|
+
reset(boundary?: string): this;
|
|
506
|
+
destroy(): void;
|
|
507
|
+
}
|
|
508
|
+
|
|
406
509
|
export interface RegistryStore {
|
|
407
510
|
target: RuntimeTarget;
|
|
408
511
|
register(type: RegistryType, id: string, value: unknown): string;
|
|
@@ -473,6 +576,8 @@ export interface CreateAppOptions extends LoaderOptions {
|
|
|
473
576
|
routeEndpoint?: string;
|
|
474
577
|
request?: Request;
|
|
475
578
|
locals?: unknown;
|
|
579
|
+
requestContext?: RequestContextStore;
|
|
580
|
+
scheduler?: Scheduler;
|
|
476
581
|
}
|
|
477
582
|
|
|
478
583
|
export interface RenderResult {
|
|
@@ -495,6 +600,7 @@ export interface AppRuntime {
|
|
|
495
600
|
browser: { cache: CacheRegistry };
|
|
496
601
|
loader?: LoaderInstance;
|
|
497
602
|
router?: Router;
|
|
603
|
+
scheduler: Scheduler;
|
|
498
604
|
attributes: NormalizedAttributeConfig;
|
|
499
605
|
start(): this;
|
|
500
606
|
use(type: Parameters<AppHub["use"]>[0], entries?: unknown): this;
|
|
@@ -510,6 +616,7 @@ export interface AsyncNamespace extends AppHub {
|
|
|
510
616
|
readSnapshot: typeof readSnapshot;
|
|
511
617
|
attributeName: typeof attributeName;
|
|
512
618
|
defineAttributeConfig: typeof defineAttributeConfig;
|
|
619
|
+
createBoundaryReceiver: typeof createBoundaryReceiver;
|
|
513
620
|
createCacheRegistry: typeof createCacheRegistry;
|
|
514
621
|
defineCache: typeof defineCache;
|
|
515
622
|
component: typeof component;
|
|
@@ -524,10 +631,13 @@ export interface AsyncNamespace extends AppHub {
|
|
|
524
631
|
createRegistryStore: typeof createRegistryStore;
|
|
525
632
|
createRouteRegistry: typeof createRouteRegistry;
|
|
526
633
|
createRouter: typeof createRouter;
|
|
634
|
+
createScheduler: typeof createScheduler;
|
|
527
635
|
defineRoute: typeof defineRoute;
|
|
528
636
|
route: typeof route;
|
|
637
|
+
applyServerResult: typeof applyServerResult;
|
|
529
638
|
createServerProxy: typeof createServerProxy;
|
|
530
|
-
|
|
639
|
+
resolveServerCommandArguments: typeof resolveServerCommandArguments;
|
|
640
|
+
unwrapServerResult: typeof unwrapServerResult;
|
|
531
641
|
computed: typeof computed;
|
|
532
642
|
createSignal: typeof createSignal;
|
|
533
643
|
createSignalRegistry: typeof createSignalRegistry;
|
|
@@ -542,6 +652,7 @@ export declare function defineApp(initial?: AppDefinition): AppHub;
|
|
|
542
652
|
export declare function readSnapshot(root?: Document | Element, options?: { attributes?: AttributeConfig }): { signals?: Record<string, unknown>; cache?: { browser?: Record<string, unknown> } };
|
|
543
653
|
export declare function attributeName(attributes: AttributeConfig | undefined, type: keyof NormalizedAttributeConfig, name: string): string;
|
|
544
654
|
export declare function defineAttributeConfig(config?: AttributeConfig): NormalizedAttributeConfig;
|
|
655
|
+
export declare function createBoundaryReceiver(options: BoundaryReceiverOptions): BoundaryReceiver;
|
|
545
656
|
export declare function createCacheRegistry(initialMap?: Record<string, CacheDefinition | CacheDefinitionOptions>, options?: { now?: () => number; registry?: RegistryStore; type?: "cache.browser" | "cache.server" }): CacheRegistry;
|
|
546
657
|
export declare function defineCache(options?: CacheDefinitionOptions): CacheDefinition;
|
|
547
658
|
export declare function component<TProps extends Record<string, unknown> = Record<string, unknown>>(fn: ComponentFunction<TProps>): ComponentFunction<TProps>;
|
|
@@ -556,11 +667,14 @@ export declare function createPartialRegistry(initialMap?: Record<string, Partia
|
|
|
556
667
|
export declare function createRegistryStore(initial?: AppDefinition, options?: { target?: RuntimeTarget; backing?: unknown }): RegistryStore;
|
|
557
668
|
export declare function createRouteRegistry(initialMap?: Record<string, RouteDefinition | string>, options?: { registry?: RegistryStore; type?: "route" }): RouteRegistry;
|
|
558
669
|
export declare function createRouter(options?: RouterOptions): Router;
|
|
670
|
+
export declare function createScheduler(options?: SchedulerOptions): Scheduler;
|
|
559
671
|
export declare function defineRoute(partial: string, options?: Omit<RouteDefinition, "partial">): RouteDefinition;
|
|
560
672
|
export declare const route: typeof defineRoute;
|
|
673
|
+
export declare function applyServerResult(result: unknown, context?: Record<string, unknown>): Promise<unknown>;
|
|
561
674
|
export declare function createServerProxy(options?: ServerProxyOptions): ServerNamespace;
|
|
562
|
-
export declare function
|
|
563
|
-
export declare function
|
|
675
|
+
export declare function resolveServerCommandArguments(args: Array<{ type: "local"; name: string } | { type: "signal"; path: string }>, context?: Record<string, unknown>): { args: unknown[]; signalValues: Record<string, unknown>; signalPaths: string[] };
|
|
676
|
+
export declare function unwrapServerResult<T = unknown>(result: ServerResult<T>): T | ServerResult<T>;
|
|
677
|
+
export declare function computed<T = unknown>(fn: (this: { signals: SignalRegistry; id: string; server?: ServerNamespace; router?: Router; loader?: LoaderInstance; cache?: CacheRegistry; scheduler?: Scheduler }) => T): ComputedSignal<T>;
|
|
564
678
|
export declare function createSignal<T = unknown>(initial: T): Signal<T>;
|
|
565
679
|
export declare function createSignalRegistry(initialMap?: SignalMap, options?: { registry?: RegistryStore; type?: "signal" }): SignalRegistry;
|
|
566
680
|
export declare function effect(fn: () => unknown): EffectDefinition;
|