@spfn/core 0.3.0-beta.26 → 0.3.0-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/state/index.d.ts +58 -10
- package/dist/state/index.js +62 -11
- package/dist/state/index.js.map +1 -1
- package/package.json +1 -1
- package/src/state/README.md +93 -19
package/dist/state/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ interface StateShape {
|
|
|
21
21
|
data: TSchema | undefined;
|
|
22
22
|
input: TSchema | undefined;
|
|
23
23
|
read: boolean;
|
|
24
|
+
/** Who the callbacks' `principal` is, from `.principal<P>()`; `unknown` until declared. */
|
|
25
|
+
principal: unknown;
|
|
24
26
|
}
|
|
25
27
|
/** The shape of `defineState(id)` before any call. */
|
|
26
28
|
interface EmptyStateShape extends StateShape {
|
|
@@ -30,6 +32,7 @@ interface EmptyStateShape extends StateShape {
|
|
|
30
32
|
data: undefined;
|
|
31
33
|
input: undefined;
|
|
32
34
|
read: false;
|
|
35
|
+
principal: unknown;
|
|
33
36
|
}
|
|
34
37
|
/** `T` with the fields of `U` replaced. */
|
|
35
38
|
type WithShape<T extends StateShape, U extends Partial<StateShape>> = {
|
|
@@ -57,22 +60,38 @@ type StateResult<T extends StateShape> = T['data'] extends TSchema ? {
|
|
|
57
60
|
type StateSnapshot<T extends StateShape> = Simplify<{
|
|
58
61
|
at: string;
|
|
59
62
|
} & StateResult<T>>;
|
|
60
|
-
/**
|
|
63
|
+
/**
|
|
64
|
+
* What `.canRead()` decides on. `principal` may be `undefined`: at SSE connect
|
|
65
|
+
* it is what `resolvePrincipal` returned.
|
|
66
|
+
*/
|
|
61
67
|
type PermissionContext<T extends StateShape> = T['key'] extends TObject ? {
|
|
62
68
|
subject: string;
|
|
63
|
-
principal:
|
|
69
|
+
principal: T['principal'] | undefined;
|
|
64
70
|
key: Static<T['key']>;
|
|
65
71
|
} : {
|
|
66
72
|
subject: string;
|
|
67
|
-
principal:
|
|
73
|
+
principal: T['principal'] | undefined;
|
|
68
74
|
};
|
|
69
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* What `.canWrite()` decides on. Only the write route asks it, and with
|
|
77
|
+
* `.principal()` declared that route refuses a request whose `auth` is
|
|
78
|
+
* `undefined` or `null` (401).
|
|
79
|
+
*/
|
|
80
|
+
type WritePermissionContext<T extends StateShape> = Simplify<Omit<PermissionContext<T>, 'principal'> & {
|
|
81
|
+
principal: T['principal'];
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* What `read()` receives. A shared state's value does not depend on the
|
|
85
|
+
* subject, so it gets none. `principal` may be `undefined`: the change
|
|
86
|
+
* signal's re-read has no request.
|
|
87
|
+
*/
|
|
70
88
|
type ReadContext<T extends StateShape> = T['key'] extends TObject ? T['shared'] extends true ? {
|
|
71
|
-
principal:
|
|
89
|
+
principal: T['principal'] | undefined;
|
|
72
90
|
key: Static<T['key']>;
|
|
73
91
|
} : PermissionContext<T> : PermissionContext<T>;
|
|
74
|
-
/** What `write()` receives: the read context
|
|
75
|
-
type WriteContext<T extends StateShape, I extends TSchema> = Simplify<ReadContext<T> & {
|
|
92
|
+
/** What `write()` receives: the read context, the write route's principal and the validated input. */
|
|
93
|
+
type WriteContext<T extends StateShape, I extends TSchema> = Simplify<Omit<ReadContext<T>, 'principal'> & {
|
|
94
|
+
principal: T['principal'];
|
|
76
95
|
input: Static<I>;
|
|
77
96
|
}>;
|
|
78
97
|
/** The payload of `state.changed.emit()`: exactly what names the value to re-read. */
|
|
@@ -137,6 +156,8 @@ interface StateDefinition {
|
|
|
137
156
|
id: string;
|
|
138
157
|
key?: TObject;
|
|
139
158
|
shared: boolean;
|
|
159
|
+
/** Whether `.principal()` was declared: the write route then refuses a request whose `auth` is `undefined` or `null`. */
|
|
160
|
+
principal: boolean;
|
|
140
161
|
value?: TSchema;
|
|
141
162
|
data?: TSchema;
|
|
142
163
|
middlewares: (MiddlewareHandler | NamedMiddleware<string>)[];
|
|
@@ -204,6 +225,15 @@ declare class StateBuilder<TId extends string, T extends StateShape> {
|
|
|
204
225
|
data<D extends TSchema>(schema: D): StateBuilder<TId, WithShape<T, {
|
|
205
226
|
data: D;
|
|
206
227
|
}>>;
|
|
228
|
+
/**
|
|
229
|
+
* Declare who the callbacks' `principal` is — what the app's auth
|
|
230
|
+
* middleware sets as `c.get('auth')`. Type-only, but for one rule: the write
|
|
231
|
+
* route refuses a request without a principal (401), so `.canWrite()` and
|
|
232
|
+
* `.write()` receive `P`; `.read()` and `.canRead()` receive `P | undefined`.
|
|
233
|
+
*/
|
|
234
|
+
principal<P>(): StateBuilder<TId, WithShape<T, {
|
|
235
|
+
principal: P;
|
|
236
|
+
}>>;
|
|
207
237
|
/**
|
|
208
238
|
* Middleware for the two per-state routes, `get<Id>State` / `put<Id>State`.
|
|
209
239
|
* Not authorization: the snapshot and the SSE stream cannot run it, so a
|
|
@@ -217,7 +247,7 @@ declare class StateBuilder<TId extends string, T extends StateShape> {
|
|
|
217
247
|
/** Who may read. Required on a keyed state; checked on HTTP and at SSE connect. */
|
|
218
248
|
canRead(predicate: (ctx: PermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>;
|
|
219
249
|
/** Who may write. Absent → `canRead` decides. */
|
|
220
|
-
canWrite(predicate: (ctx:
|
|
250
|
+
canWrite(predicate: (ctx: WritePermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>;
|
|
221
251
|
/** The only source of a value. Required. */
|
|
222
252
|
read(fn: (ctx: ReadContext<T>) => StateResult<T> | Promise<StateResult<T>>): StateBuilder<TId, WithShape<T, {
|
|
223
253
|
read: true;
|
|
@@ -294,6 +324,19 @@ declare function defineState<TId extends string>(id: TId): StateBuilder<TId, Emp
|
|
|
294
324
|
|
|
295
325
|
/** Who a request is for. `null` answers 401. */
|
|
296
326
|
type SubjectResolver = (c: Context) => string | null;
|
|
327
|
+
/**
|
|
328
|
+
* What the router gives the snapshot route `GET <path>` alone. A per-state
|
|
329
|
+
* route keeps its own state's `.use()` / `.skip()` / `.contract()`, and the
|
|
330
|
+
* SSE stream runs none of them.
|
|
331
|
+
*/
|
|
332
|
+
interface SnapshotRouteOptions {
|
|
333
|
+
/** Middleware for the snapshot route only. Not authorization: the stream never runs it (see README). */
|
|
334
|
+
use?: (MiddlewareHandler | NamedMiddleware<string>)[];
|
|
335
|
+
/** Server-level named middlewares the snapshot route skips; `'*'` skips every one. */
|
|
336
|
+
skip?: string[] | '*';
|
|
337
|
+
/** Publishes the snapshot route in the contract; the response schema is derived. */
|
|
338
|
+
contract?: StateContract;
|
|
339
|
+
}
|
|
297
340
|
/** What the browser cannot read from a type: every state, in declaration order, its key fields and whether it has a write. */
|
|
298
341
|
type StatesManifest = Record<string, {
|
|
299
342
|
key: string[];
|
|
@@ -308,7 +351,12 @@ type StatesManifest = Record<string, {
|
|
|
308
351
|
* subscribes each state's change signal — once, here.
|
|
309
352
|
*/
|
|
310
353
|
|
|
311
|
-
|
|
354
|
+
/**
|
|
355
|
+
* Where the router mounts, whom a request is for, and the snapshot route's own
|
|
356
|
+
* `use` / `skip` / `contract` (`SnapshotRouteOptions`) — those reach `GET <path>`
|
|
357
|
+
* only, never a per-state route or the SSE stream.
|
|
358
|
+
*/
|
|
359
|
+
interface StateRouterOptions extends SnapshotRouteOptions {
|
|
312
360
|
/**
|
|
313
361
|
* Where the routes are mounted: `GET <path>`, `GET|PUT <path>/<id>`.
|
|
314
362
|
* @default '/state'
|
|
@@ -392,4 +440,4 @@ type InferStateInput<R extends StateRouter<any>, TId extends string> = Shape<Sta
|
|
|
392
440
|
*/
|
|
393
441
|
declare function defineStateRouter<S extends Record<string, RoutableState>>(states: S, options?: StateRouterOptions): StateRouter<S>;
|
|
394
442
|
|
|
395
|
-
export { type ChangedPayload, type GrantTarget, type InferStateInput, type InferStateKey, type InferStateValue, type PermissionContext, type ReadContext, type RevokeTarget, type RoutableState, StateBuilder, type StateContract, type StateEvents, type StateFrame, type StateKey, type StateResult, type StateRouter, type StateRouterOptions, type StateRoutes, type StateShape, type StateSnapshot, type StateValue, type StateWriteOptions, type StatesManifest, type StatesSnapshot, type SubjectResolver, type WriteContext, defineState, defineStateRouter };
|
|
443
|
+
export { type ChangedPayload, type GrantTarget, type InferStateInput, type InferStateKey, type InferStateValue, type PermissionContext, type ReadContext, type RevokeTarget, type RoutableState, type SnapshotRouteOptions, StateBuilder, type StateContract, type StateEvents, type StateFrame, type StateKey, type StateResult, type StateRouter, type StateRouterOptions, type StateRoutes, type StateShape, type StateSnapshot, type StateValue, type StateWriteOptions, type StatesManifest, type StatesSnapshot, type SubjectResolver, type WriteContext, type WritePermissionContext, defineState, defineStateRouter };
|
package/dist/state/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Type, Kind } from '@sinclair/typebox';
|
|
2
2
|
import { Value } from '@sinclair/typebox/value';
|
|
3
|
+
import { getTransactionContext, onAfterCommit } from '@spfn/core/db';
|
|
3
4
|
import { defineEvent } from '@spfn/core/event';
|
|
4
5
|
import { logger } from '@spfn/core/logger';
|
|
5
6
|
import { defineRouter, route } from '@spfn/core/route';
|
|
@@ -83,7 +84,12 @@ function toFrame(def, snapshot, subject, key) {
|
|
|
83
84
|
}
|
|
84
85
|
async function readAndPublish(def, event, subject, key, principal) {
|
|
85
86
|
const snapshot = await readSnapshot(def, readContext(def, subject, principal, key));
|
|
86
|
-
|
|
87
|
+
const frame = toFrame(def, snapshot, subject, key);
|
|
88
|
+
if (getTransactionContext()) {
|
|
89
|
+
onAfterCommit(() => event.emit(frame));
|
|
90
|
+
} else {
|
|
91
|
+
await event.emit(frame);
|
|
92
|
+
}
|
|
87
93
|
return snapshot;
|
|
88
94
|
}
|
|
89
95
|
function framePayloadSchema(def) {
|
|
@@ -154,7 +160,7 @@ async function onSignal(state, payload) {
|
|
|
154
160
|
try {
|
|
155
161
|
await readAndPublish(state._definition, state._event, subject, key, void 0);
|
|
156
162
|
} catch (error) {
|
|
157
|
-
stateLogger.warn(`State "${state.id}" could not be re-read on its change signal; no frame was sent`, {
|
|
163
|
+
stateLogger.warn(`State "${state.id}" could not be re-read or published on its change signal; no frame was sent`, {
|
|
158
164
|
state: state.id,
|
|
159
165
|
error: error instanceof Error ? error.message : String(error)
|
|
160
166
|
});
|
|
@@ -207,6 +213,16 @@ var StateBuilder = class _StateBuilder {
|
|
|
207
213
|
this.assertOnce("data", !!this._definition.data);
|
|
208
214
|
return this.with({ data: schema });
|
|
209
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Declare who the callbacks' `principal` is — what the app's auth
|
|
218
|
+
* middleware sets as `c.get('auth')`. Type-only, but for one rule: the write
|
|
219
|
+
* route refuses a request without a principal (401), so `.canWrite()` and
|
|
220
|
+
* `.write()` receive `P`; `.read()` and `.canRead()` receive `P | undefined`.
|
|
221
|
+
*/
|
|
222
|
+
principal() {
|
|
223
|
+
this.assertOnce("principal", this._definition.principal);
|
|
224
|
+
return this.with({ principal: true });
|
|
225
|
+
}
|
|
210
226
|
/**
|
|
211
227
|
* Middleware for the two per-state routes, `get<Id>State` / `put<Id>State`.
|
|
212
228
|
* Not authorization: the snapshot and the SSE stream cannot run it, so a
|
|
@@ -371,7 +387,7 @@ function defineState(id) {
|
|
|
371
387
|
`defineState("${id}"): a state id must match ${STATE_ID}. It becomes part of the route names get<Id>State / put<Id>State and of the event name state.<id>.changed. Use a lowerCamel identifier, e.g. "myState".`
|
|
372
388
|
);
|
|
373
389
|
}
|
|
374
|
-
return new StateBuilder(id, { id, shared: false, middlewares: [] });
|
|
390
|
+
return new StateBuilder(id, { id, shared: false, principal: false, middlewares: [] });
|
|
375
391
|
}
|
|
376
392
|
var defaultSubject = (c) => c.get("auth")?.userId ?? null;
|
|
377
393
|
function stateRouteName(method, id) {
|
|
@@ -384,19 +400,30 @@ function requireSubject(c, resolveSubject) {
|
|
|
384
400
|
}
|
|
385
401
|
return subject;
|
|
386
402
|
}
|
|
403
|
+
function writePrincipal(def, c) {
|
|
404
|
+
const principal = c.get("auth");
|
|
405
|
+
if (def.principal && principal == null) {
|
|
406
|
+
throw new UnauthorizedError({
|
|
407
|
+
message: `State "${def.id}" declares .principal(), and this request carries none`
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
return principal;
|
|
411
|
+
}
|
|
387
412
|
async function assertPermitted(def, can, ctx) {
|
|
388
413
|
const predicate = can === "canWrite" ? def.canWrite ?? def.canRead : def.canRead;
|
|
389
414
|
if (predicate && !await predicate(ctx)) {
|
|
390
415
|
throw new ForbiddenError({ message: `${can === "canWrite" ? "Writing" : "Reading"} state "${def.id}" is not permitted` });
|
|
391
416
|
}
|
|
392
417
|
}
|
|
393
|
-
function
|
|
418
|
+
function resultSchema2(def) {
|
|
394
419
|
return Type.Object({
|
|
395
|
-
at: Type.String(),
|
|
396
420
|
value: def.value,
|
|
397
421
|
...def.data ? { data: def.data } : {}
|
|
398
422
|
});
|
|
399
423
|
}
|
|
424
|
+
function responseSchema(def) {
|
|
425
|
+
return Type.Object({ at: Type.String(), ...resultSchema2(def).properties });
|
|
426
|
+
}
|
|
400
427
|
function routeContract(def, write) {
|
|
401
428
|
if (!def.contract) {
|
|
402
429
|
return void 0;
|
|
@@ -431,7 +458,7 @@ function writeRoute(state, path, resolveSubject) {
|
|
|
431
458
|
const write = def.write;
|
|
432
459
|
return stateRoute(def, "put", `${path}/${def.id}`, { body: write.input, ...keyInput(def) }).handler(async (c) => {
|
|
433
460
|
const subject = requireSubject(c.raw, resolveSubject);
|
|
434
|
-
const principal = c.raw
|
|
461
|
+
const principal = writePrincipal(def, c.raw);
|
|
435
462
|
const { body, query } = await c.data();
|
|
436
463
|
const key = def.key ? pickKey(def.key, query) : void 0;
|
|
437
464
|
await assertPermitted(def, "canWrite", permissionContext(def, subject, principal, key));
|
|
@@ -465,8 +492,22 @@ function stateManifest(states) {
|
|
|
465
492
|
write: state._definition.write !== void 0
|
|
466
493
|
}]));
|
|
467
494
|
}
|
|
468
|
-
function
|
|
469
|
-
|
|
495
|
+
function snapshotResponseSchema(states) {
|
|
496
|
+
const manifestEntry = Type.Object({ key: Type.Array(Type.String()), write: Type.Boolean() });
|
|
497
|
+
return Type.Object({
|
|
498
|
+
at: Type.String(),
|
|
499
|
+
states: Type.Object(Object.fromEntries(states.map((state) => [state.id, Type.Optional(resultSchema2(state._definition))]))),
|
|
500
|
+
manifest: Type.Object(Object.fromEntries(states.map((state) => [state.id, manifestEntry])))
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
function snapshotBuilder(states, path, options) {
|
|
504
|
+
const builder = route.get(path).input({ query: snapshotQuery(states) });
|
|
505
|
+
const used = options.use?.length ? builder.use(options.use) : builder;
|
|
506
|
+
const skipped = options.skip ? used.skip(options.skip) : used;
|
|
507
|
+
return options.contract ? skipped.contract(stripUndefined({ ...options.contract, response: snapshotResponseSchema(states) })) : skipped;
|
|
508
|
+
}
|
|
509
|
+
function snapshotRoute(states, manifest, path, resolveSubject, options = {}) {
|
|
510
|
+
return snapshotBuilder(states, path, options).handler(async (c) => {
|
|
470
511
|
const subject = requireSubject(c.raw, resolveSubject);
|
|
471
512
|
const principal = c.raw.get("auth");
|
|
472
513
|
const { query } = await c.data();
|
|
@@ -486,17 +527,19 @@ function defineStateRouter(states, options = {}) {
|
|
|
486
527
|
const list = Object.values(states);
|
|
487
528
|
assertPath(path);
|
|
488
529
|
list.forEach(assertRoutable);
|
|
530
|
+
assertSnapshotMiddlewareIsNotAuthorization(list, options);
|
|
489
531
|
assertDistinctIds(list);
|
|
490
532
|
list.forEach((state) => assertNotRouted(state, path));
|
|
491
533
|
list.forEach((state) => bindState(state._definition, path));
|
|
492
534
|
list.forEach(subscribeChangeSignals);
|
|
493
535
|
return {
|
|
494
|
-
router: defineRouter(deriveRoutes(list, path, options
|
|
536
|
+
router: defineRouter(deriveRoutes(list, path, options)),
|
|
495
537
|
events: Object.fromEntries(list.map((state) => [stateEventName(state.id), state._event])),
|
|
496
538
|
states
|
|
497
539
|
};
|
|
498
540
|
}
|
|
499
|
-
function deriveRoutes(states, path,
|
|
541
|
+
function deriveRoutes(states, path, options) {
|
|
542
|
+
const resolveSubject = options.subject ?? defaultSubject;
|
|
500
543
|
const routes = {};
|
|
501
544
|
for (const state of states) {
|
|
502
545
|
routes[stateRouteName("get", state.id)] = readRoute(state, path, resolveSubject);
|
|
@@ -504,7 +547,7 @@ function deriveRoutes(states, path, resolveSubject) {
|
|
|
504
547
|
routes[stateRouteName("put", state.id)] = writeRoute(state, path, resolveSubject);
|
|
505
548
|
}
|
|
506
549
|
}
|
|
507
|
-
routes.getStates = snapshotRoute(states, stateManifest(states), path, resolveSubject);
|
|
550
|
+
routes.getStates = snapshotRoute(states, stateManifest(states), path, resolveSubject, options);
|
|
508
551
|
return routes;
|
|
509
552
|
}
|
|
510
553
|
function assertPath(path) {
|
|
@@ -543,6 +586,14 @@ function assertMiddlewareIsNotAuthorization(state) {
|
|
|
543
586
|
);
|
|
544
587
|
}
|
|
545
588
|
}
|
|
589
|
+
function assertSnapshotMiddlewareIsNotAuthorization(states, options) {
|
|
590
|
+
const unguarded = states.find((state) => !state._definition.canRead);
|
|
591
|
+
if (((options.use?.length ?? 0) > 0 || options.skip) && unguarded) {
|
|
592
|
+
throw new Error(
|
|
593
|
+
`defineStateRouter: the router gives the snapshot route use or skip, but state "${unguarded.id}" declares no .canRead(). The snapshot's middleware never reaches the SSE stream, which serves the same state, so it cannot authorize. Authorization belongs in .canRead(); a state readable by every subject declares .canRead(() => true) to say so.`
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
546
597
|
function assertChangedBy(state, event) {
|
|
547
598
|
const payload = event.schema;
|
|
548
599
|
const signal = changedPayloadSchema(state._definition);
|
package/dist/state/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/state/state-binding.ts","../../src/state/state-event.ts","../../src/state/state-builder.ts","../../src/state/state-routes.ts","../../src/state/state-router.ts"],"names":["Type","Value"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * State Binding\n *\n * What a state router fixes for each state it groups, keyed by the builder's\n * definition — one per builder instance, so an intermediate builder is never\n * bound: the router's path (a state belongs to one router) and the schema\n * every `read()` result is checked against, built once here rather than per\n * request.\n */\n\nimport { Type, type TObject } from '@sinclair/typebox';\nimport type { StateDefinition } from './types';\n\nexport interface StateBinding\n{\n path: string;\n resultSchema: TObject;\n}\n\nconst bindings = new WeakMap<Readonly<StateDefinition>, StateBinding>();\n\n/** `{ value, data }` exactly as declared: `data` when `.data()` is, and nothing else. */\nfunction resultSchema(def: StateDefinition): TObject\n{\n return Type.Object(\n {\n value: def.value!,\n ...(def.data ? { data: def.data } : {}),\n },\n { additionalProperties: false },\n );\n}\n\n/** Bind a state to the router at `path`. */\nexport function bindState(def: Readonly<StateDefinition>, path: string): void\n{\n bindings.set(def, { path, resultSchema: resultSchema(def) });\n}\n\n/** The binding of a state, `undefined` until a router groups that builder. */\nexport function stateBinding(def: Readonly<StateDefinition>): StateBinding | undefined\n{\n return bindings.get(def);\n}\n","/**\n * State Event\n *\n * The two events a state derives: the change signal the app emits\n * (`state.changed`, in-process) and the SSE event the browser receives\n * (`state.<id>.changed`). Between them sits the one rule of the module — a\n * value is only ever what `read()` returned, re-read here, never computed from\n * the signal.\n */\n\nimport { Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { defineEvent } from '@spfn/core/event';\nimport type { EventDef, FramePredicate, SubscribePredicate } from '@spfn/core/event';\nimport { logger } from '@spfn/core/logger';\nimport { stateBinding, type StateBinding } from './state-binding';\nimport type { RoutableState, StateCallContext, StateDefinition } from './types';\n\nconst stateLogger = logger.child('@spfn/core:state');\n\n/** `{ at, value, data? }` as a response and a frame carry it. */\nexport interface Snapshot\n{\n at: string;\n value: unknown;\n data?: unknown;\n}\n\ntype Key = Record<string, string>;\n\ntype FramePayload = Snapshot & { key?: Key; subject?: string };\n\n/** The wire name of a state's SSE event. */\nexport function stateEventName(id: string): string\n{\n return `state.${id}.changed`;\n}\n\n/**\n * The key fields of `keySchema` taken from `source`, or `undefined` when any\n * is absent. Key fields are strings by construction (`.key()` refuses others),\n * so a query value and a payload field compare as they are.\n */\nexport function pickKey(keySchema: TObject, source: Record<string, unknown>): Key | undefined\n{\n const key: Key = {};\n\n for (const field of Object.keys(keySchema.properties))\n {\n const value = source[field];\n if (typeof value !== 'string')\n {\n return undefined;\n }\n key[field] = value;\n }\n\n return key;\n}\n\n/** What `read()` receives: a shared state's value does not depend on the subject, so it gets none. */\nexport function readContext(def: StateDefinition, subject: string | undefined, principal: unknown, key?: Key): StateCallContext\n{\n if (!def.key)\n {\n return { subject, principal };\n }\n\n return def.shared ? { principal, key } : { subject, principal, key };\n}\n\n/** What `.canRead()` / `.canWrite()` receive. */\nexport function permissionContext(def: StateDefinition, subject: string, principal: unknown, key?: Key): StateCallContext\n{\n return def.key ? { subject, principal, key } : { subject, principal };\n}\n\n/**\n * The router binding of a state, or a refusal: an unrouted builder has no\n * subscriber for its signal and no schema to check a read against.\n */\nexport function requireBinding(def: StateDefinition, what: string): StateBinding\n{\n const binding = stateBinding(def);\n\n if (!binding)\n {\n throw new Error(\n `State \"${def.id}\" is in no defineStateRouter, so ${what} reaches nothing. `\n + 'The router subscribes the change signal and checks every read, and every builder call returns a new '\n + 'builder — an earlier one is never routed. Group the state with defineStateRouter and export the builder '\n + 'instance you grouped.',\n );\n }\n\n return binding;\n}\n\n/** Refuse a `read()` result that is not what the state declares, naming the state, never the value. */\nfunction assertResult(def: StateDefinition, binding: StateBinding, result: unknown): asserts result is Omit<Snapshot, 'at'>\n{\n const error = Value.Errors(binding.resultSchema, result).First();\n\n if (error)\n {\n throw new Error(\n `State \"${def.id}\" read() returned a result its declaration does not allow: ${error.path || '(root)'} ${error.message}. `\n + 'Every response and frame is checked against .value() and .data(), so a client never receives a value the '\n + 'contract does not describe. Return { value'\n + `${def.data ? ', data' : ''} } as declared.`,\n );\n }\n}\n\n/**\n * Read the current value and check it against the declaration. `at` is taken\n * before `read()` starts, so a frame is never stamped later than the data it\n * carries.\n */\nexport async function readSnapshot(def: StateDefinition, ctx: StateCallContext, at = new Date().toISOString()): Promise<Snapshot>\n{\n const binding = requireBinding(def, 'a read');\n const result = await def.read!(ctx);\n assertResult(def, binding, result);\n\n return { at, ...result };\n}\n\n/**\n * The frame for a snapshot. A copy: the response keeps the snapshot itself, so\n * neither a handler mutating what it returned nor a subscriber mutating the\n * payload changes the other.\n */\nfunction toFrame(def: StateDefinition, snapshot: Snapshot, subject: string | undefined, key: Key | undefined): FramePayload\n{\n const frame: FramePayload = structuredClone(snapshot);\n\n if (def.key)\n {\n frame.key = { ...key };\n }\n\n if (!(def.key && def.shared))\n {\n frame.subject = subject;\n }\n\n return frame;\n}\n\n/** Read the value for one subject and key, send it as one frame, and return the snapshot. */\nexport async function readAndPublish(\n def: StateDefinition,\n event: EventDef<any>,\n subject: string | undefined,\n key: Key | undefined,\n principal: unknown,\n): Promise<Snapshot>\n{\n const snapshot = await readSnapshot(def, readContext(def, subject, principal, key));\n await event.emit(toFrame(def, snapshot, subject, key));\n\n return snapshot;\n}\n\n// ============================================================================\n// The derived SSE event\n// ============================================================================\n\nfunction framePayloadSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n at: Type.String(),\n value: def.value ?? Type.Unknown(),\n ...(def.data ? { data: def.data } : {}),\n ...(def.key ? { key: def.key } : {}),\n ...(def.key && def.shared ? {} : { subject: Type.String() }),\n });\n}\n\n/**\n * `canRead` translated to the connect: the connection declares its key in the\n * connect query. A key field absent from it denies, without asking `canRead` —\n * there is no key to ask about.\n */\nfunction subscribePredicate(def: StateDefinition): SubscribePredicate\n{\n return async ({ subject, principal, request }) =>\n {\n if (!def.key)\n {\n return def.canRead ? def.canRead({ subject, principal }) : true;\n }\n\n const key = pickKey(def.key, request.query);\n\n return key !== undefined && def.canRead !== undefined && def.canRead({ subject, principal, key });\n };\n}\n\n/**\n * A frame reaches a connection on the key it declared, and only its own\n * subject's value unless shared. Never a connection without a subject: on a\n * stream without auth `canSubscribe` is never asked, so `canRead` would be\n * skipped.\n */\nfunction framePredicate(def: StateDefinition): FramePredicate<FramePayload>\n{\n const fields = def.key ? Object.keys(def.key.properties) : [];\n\n return (payload, { subject, request }) =>\n subject !== undefined\n && fields.every(field => payload.key?.[field] === request.query[field])\n && (payload.subject === undefined || payload.subject === subject);\n}\n\n/** The SSE event `state.<id>.changed`, its permissions and contract set once, here. */\nexport function createStateEvent(def: StateDefinition): EventDef<any>\n{\n const event = defineEvent(stateEventName(def.id), framePayloadSchema(def))\n .canSubscribe(subscribePredicate(def))\n .filter(framePredicate(def) as FramePredicate<unknown>);\n\n if (def.contract)\n {\n const { since, deprecatedIn, removedIn } = def.contract;\n event.contract({\n since,\n ...(deprecatedIn ? { deprecatedIn } : {}),\n ...(removedIn ? { removedIn } : {}),\n });\n }\n\n return event;\n}\n\n// ============================================================================\n// The change signal\n// ============================================================================\n\n/**\n * What a change signal must name: keyless `subject`; keyed the key fields, and\n * `subject` unless shared. Always a fresh object, never `def.key` itself: a key\n * declared `additionalProperties: false` would otherwise refuse every\n * `.changedBy()` payload carrying one more field. Extra fields are ignored.\n */\nexport function changedPayloadSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n ...def.key?.properties,\n ...(def.key && def.shared ? {} : { subject: Type.String() }),\n });\n}\n\nfunction assertChangedPayload(def: StateDefinition, schema: TSchema, payload: unknown): void\n{\n const error = Value.Errors(schema, payload).First();\n\n if (error)\n {\n throw new Error(\n `${def.id}.changed.emit() refused its payload: ${error.path || '(root)'} ${error.message}. `\n + 'The module re-reads exactly the subject and key the payload names, so a missing field cannot be guessed. '\n + `Pass ${def.key ? 'every key field' : 'the subject'}${def.key && !def.shared ? ' and the subject' : ''}.`,\n );\n }\n}\n\n/**\n * The change signal `state.changed`: a plain in-process event whose `emit`\n * refuses a builder no router grouped, and validates its payload, since the\n * module reads the state the payload names.\n */\nexport function createChangedSignal(def: StateDefinition): EventDef<any>\n{\n const schema = changedPayloadSchema(def);\n const event = defineEvent(`state.${def.id}.signal`, schema);\n const emit = event.emit;\n\n event.emit = (async (payload: unknown) =>\n {\n requireBinding(def, `${def.id}.changed.emit()`);\n assertChangedPayload(def, schema, payload);\n await emit(payload as Record<string, unknown>);\n }) as EventDef<any>['emit'];\n\n return event;\n}\n\n/** Subject and key a signal payload names; a shared state's names no subject. */\nfunction signalTarget(def: StateDefinition, payload: Record<string, unknown>): { subject?: string; key?: Key }\n{\n const subject = def.key && def.shared ? undefined : payload.subject as string;\n\n return { subject, key: def.key ? pickKey(def.key, payload) : undefined };\n}\n\n/**\n * Re-read and publish for one signal. A `read()` that throws or returns an\n * undeclared result sends nothing and is logged — the signal came after a\n * commit the app already made, so there is nobody to throw to.\n */\nasync function onSignal(state: RoutableState, payload: Record<string, unknown>): Promise<void>\n{\n const { subject, key } = signalTarget(state._definition, payload);\n\n try\n {\n await readAndPublish(state._definition, state._event, subject, key, undefined);\n }\n catch (error)\n {\n stateLogger.warn(`State \"${state.id}\" could not be re-read on its change signal; no frame was sent`, {\n state: state.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\n/**\n * A `.changedBy()` event's payload, checked as the state's own `emit` checks\n * its signal. The app emitted it, so a payload missing a field is logged and\n * skipped rather than thrown.\n */\nasync function onChangedBy(state: RoutableState, event: EventDef<any>, schema: TObject, payload: unknown): Promise<void>\n{\n const error = Value.Errors(schema, payload).First();\n\n if (error)\n {\n stateLogger.warn(`State \"${state.id}\" skipped an \"${event.name}\" payload that names no value to re-read`, {\n state: state.id,\n event: event.name,\n error: `${error.path || '(root)'} ${error.message}`,\n });\n\n return;\n }\n\n await onSignal(state, payload as Record<string, unknown>);\n}\n\n/**\n * Re-read and publish on every signal of `state` and every event it lists in\n * `.changedBy()`, on the pod that emitted it only. A `.changedBy()` event in an\n * event router is cached, so a plain subscriber would re-read on every pod and\n * each would send its own frame; the derived state event is cached too, so the\n * emitting pod's one frame already reaches every pod. The `changed` signal\n * needs no such option: it is in no event router and never cached.\n */\nexport function subscribeChangeSignals(state: RoutableState): void\n{\n const schema = changedPayloadSchema(state._definition);\n\n state.changed.subscribe(payload => onSignal(state, payload));\n state._definition.changedBy?.forEach(event =>\n event.subscribe(payload => onChangedBy(state, event, schema, payload), { localOnly: true }));\n}\n","/**\n * State Builder\n *\n * `defineState(id)` starts an immutable builder: every call returns a new one,\n * order is free and there is no terminal method. `defineStateRouter` reads\n * what a builder declared and derives its routes and SSE event from it.\n */\n\nimport { Kind, Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport type { MiddlewareHandler } from 'hono';\nimport type { EventDef } from '@spfn/core/event';\nimport type { NamedMiddleware } from '@spfn/core/route';\nimport { createChangedSignal, createStateEvent, pickKey, readAndPublish, requireBinding } from './state-event';\nimport type {\n ChangedPayload,\n EmptyStateShape,\n GrantTarget,\n PermissionContext,\n ReadContext,\n RevokeTarget,\n StateContract,\n StateDefinition,\n StateFrame,\n StatePredicate,\n StateReader,\n StateResult,\n StateShape,\n StateWriteOptions,\n StateWriter,\n WithShape,\n WriteContext,\n} from './types';\n\n/** A state id becomes part of a route name (`get<Id>State`) and of an event name (`state.<id>.changed`). */\nconst STATE_ID = /^[a-z][a-zA-Z0-9]*$/;\n\n/**\n * Query names the SSE stream reads itself. Key fields share the connect query\n * with them, so a key field under one of these names would be read as both.\n */\nconst RESERVED_KEY_FIELDS = ['events', 'token'];\n\n/**\n * A server-owned value declared once. See the module README.\n */\nexport class StateBuilder<TId extends string, T extends StateShape>\n{\n /** Type inference helper: what this builder declared. Never set at runtime. */\n declare readonly _types: T;\n\n private changedSignal?: EventDef<any>;\n private stateEvent?: EventDef<any>;\n\n constructor(\n readonly id: TId,\n readonly _definition: Readonly<StateDefinition>,\n )\n {\n }\n\n /**\n * Declare the key: one value per key (and per subject, unless `shared`).\n * Fields are required strings: they travel as query parameters.\n */\n key<K extends TObject, S extends boolean = false>(\n schema: K,\n options: { shared?: S } = {},\n ): StateBuilder<TId, WithShape<T, { key: K; shared: S }>>\n {\n this.assertOnce('key', !!this._definition.key);\n assertKeySchema(this.id, schema);\n\n return this.with({ key: schema, shared: options.shared === true });\n }\n\n /** Declare the value schema. Required. */\n value<V extends TSchema>(schema: V): StateBuilder<TId, WithShape<T, { value: V }>>\n {\n this.assertOnce('value', !!this._definition.value);\n\n return this.with({ value: schema });\n }\n\n /** Declare data attached to the value. Optional. */\n data<D extends TSchema>(schema: D): StateBuilder<TId, WithShape<T, { data: D }>>\n {\n this.assertOnce('data', !!this._definition.data);\n\n return this.with({ data: schema });\n }\n\n /**\n * Middleware for the two per-state routes, `get<Id>State` / `put<Id>State`.\n * Not authorization: the snapshot and the SSE stream cannot run it, so a\n * state with `.use()` must declare `.canRead()`. Calls add up.\n */\n use(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): StateBuilder<TId, T>\n {\n return this.with({ middlewares: [...this._definition.middlewares, ...middlewares] });\n }\n\n /** Server-level named middlewares the two per-state routes skip. Calls add up; `'*'` wins. Needs `.canRead()`, as `.use()`. */\n skip(middlewareNames: string[] | '*'): StateBuilder<TId, T>\n {\n const current = this._definition.skipMiddlewares ?? [];\n const skipMiddlewares = current === '*' || middlewareNames === '*'\n ? '*'\n : [...current, ...middlewareNames];\n\n return this.with({ skipMiddlewares });\n }\n\n /** Publish the read route, the write route and the event in the contract. */\n contract(contract: StateContract): StateBuilder<TId, T>\n {\n this.assertOnce('contract', !!this._definition.contract);\n\n return this.with({ contract });\n }\n\n /** Who may read. Required on a keyed state; checked on HTTP and at SSE connect. */\n canRead(predicate: (ctx: PermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>\n {\n this.assertOnce('canRead', !!this._definition.canRead);\n\n return this.with({ canRead: predicate as StatePredicate });\n }\n\n /** Who may write. Absent → `canRead` decides. */\n canWrite(predicate: (ctx: PermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>\n {\n this.assertOnce('canWrite', !!this._definition.canWrite);\n\n return this.with({ canWrite: predicate as StatePredicate });\n }\n\n /** The only source of a value. Required. */\n read(\n fn: (ctx: ReadContext<T>) => StateResult<T> | Promise<StateResult<T>>,\n ): StateBuilder<TId, WithShape<T, { read: true }>>\n {\n this.assertOnce('read', !!this._definition.read);\n\n return this.with({ read: fn as StateReader });\n }\n\n /**\n * Derive `PUT <path>/<id>`. `fn` runs the command; the value the route\n * answers and broadcasts is re-read afterwards, never taken from `input`.\n */\n write<I extends TSchema>(\n input: I,\n fn: (ctx: WriteContext<T, I>) => void | Promise<void>,\n options: StateWriteOptions = {},\n ): StateBuilder<TId, WithShape<T, { input: I }>>\n {\n this.assertOnce('write', !!this._definition.write);\n\n return this.with({ write: { input, fn: fn as StateWriter, options } });\n }\n\n /**\n * Domain events whose payload names a changed value of this state, treated\n * like `changed.emit` with that payload: keyless `subject`, keyed the key\n * fields and `subject`, shared the key fields. The router subscribes them\n * and refuses one whose payload schema lacks a field.\n */\n changedBy(events: EventDef<any>[]): StateBuilder<TId, T>\n {\n this.assertOnce('changedBy', !!this._definition.changedBy);\n\n return this.with({ changedBy: [...events] });\n }\n\n /**\n * The change signal. Emit it after the change is committed; the module\n * re-reads the value and sends the frame. Refused on a builder no router\n * grouped — export the instance you passed to `defineStateRouter`.\n */\n get changed(): EventDef<ChangedPayload<T>>\n {\n this.changedSignal ??= createChangedSignal(this._definition);\n\n return this.changedSignal;\n }\n\n /** Internal: the SSE event `state.<id>.changed` (`defineStateRouter(...).events`). */\n get _event(): EventDef<StateFrame<T>>\n {\n this.stateEvent ??= createStateEvent(this._definition);\n\n return this.stateEvent;\n }\n\n /**\n * Activate the state's event on `subject`'s open connections and send it\n * the current value at once. On a keyed state only the connections that\n * declared `key` are opened. Does not consult `canRead`.\n */\n async grant(target: GrantTarget<T>): Promise<void>\n {\n const { subject, key } = target as { subject: string; key?: Record<string, string> };\n requireBinding(this._definition, `${this.id}.grant()`);\n this.assertGrantKey(key);\n const declared = this.declaredKey('grant', key);\n await this._event.grant(subject, declared && { query: declared });\n await readAndPublish(this._definition, this._event, subject, declared, undefined);\n }\n\n /**\n * Deactivate the state's event on `subject`'s open connections: on a keyed\n * state those that declared `key`, or every one when no key is given.\n */\n async revoke(target: RevokeTarget<T>): Promise<void>\n {\n const { subject, key } = target as { subject: string; key?: Record<string, string> };\n const declared = this.declaredKey('revoke', key);\n await this._event.revoke(subject, declared && { query: declared });\n }\n\n /** A keyed grant opens one key: without it there is no key to open and no value to send. */\n private assertGrantKey(key: Record<string, string> | undefined): void\n {\n if (this._definition.key && !key)\n {\n throw new Error(\n `State \"${this.id}\" .grant() was called without a key. `\n + 'A keyed grant opens exactly one key — every connection of the subject on any key would otherwise be '\n + 'opened, including keys canRead refused. Pass { subject, key }.',\n );\n }\n }\n\n /**\n * The declared key fields of `key`, checked against `.key()`: an empty or\n * partial key would match every connection of the subject. A field the\n * declaration does not name is dropped, never matched on — so the check\n * runs on a fresh object of the declared fields, never `.key()` itself: a\n * key declared `additionalProperties: false` would otherwise refuse it.\n * The fresh object keeps `.key()`'s `required`, and a key that still picks\n * to nothing is refused: `undefined` here would mean every connection.\n */\n private declaredKey(method: 'grant' | 'revoke', key: Record<string, string> | undefined): Record<string, string> | undefined\n {\n const schema = this._definition.key;\n if (!schema || key === undefined)\n {\n return undefined;\n }\n\n const error = Value.Errors({ ...Type.Object(schema.properties), required: schema.required }, key).First();\n if (error)\n {\n this.refuseKey(method, `${error.path || '(root)'} ${error.message}`);\n }\n\n return pickKey(schema, key) ?? this.refuseKey(method, '(root) a declared key field is missing or not a string');\n }\n\n private refuseKey(method: 'grant' | 'revoke', reason: string): never\n {\n throw new Error(\n `State \"${this.id}\" .${method}() refused its key: ${reason}. `\n + `A keyed ${method} reaches exactly the connections on one key, so every key field must be named.`,\n );\n }\n\n private with(changes: Partial<StateDefinition>): StateBuilder<TId, any>\n {\n return new StateBuilder(this.id, { ...this._definition, ...changes });\n }\n\n private assertOnce(method: string, declared: boolean): void\n {\n if (declared)\n {\n throw new Error(\n `State \"${this.id}\" already declares .${method}(). `\n + 'A state is declared once, so a second declaration would silently replace the first. '\n + `Declare .${method}() once.`,\n );\n }\n }\n}\n\n/**\n * Refuse a key the module could not carry: it must be an object of required\n * string fields, none named like a query parameter the SSE stream reads.\n */\nfunction assertKeySchema(id: string, schema: TSchema): void\n{\n if (schema[Kind] !== 'Object')\n {\n throw new Error(\n `State \"${id}\" .key() takes an object schema, got ${String(schema[Kind])}. `\n + 'Each key field becomes a named query parameter and a field of the frame\\'s key. '\n + 'Wrap the field: .key(Type.Object({ workspaceId: Type.String() })).',\n );\n }\n\n const fields = Object.entries((schema as TObject).properties);\n\n if (fields.length === 0)\n {\n throw new Error(\n `State \"${id}\" .key() declares no field. A key with no field names nothing to read by. `\n + 'Drop .key() for one value per subject.',\n );\n }\n\n fields.forEach(([field, fieldSchema]) => assertKeyField(id, schema as TObject, field, fieldSchema));\n}\n\nfunction assertKeyField(id: string, schema: TObject, field: string, fieldSchema: TSchema): void\n{\n if (RESERVED_KEY_FIELDS.includes(field))\n {\n throw new Error(\n `State \"${id}\" key field \"${field}\" is reserved. `\n + `The SSE stream reads ${RESERVED_KEY_FIELDS.map(name => `\"${name}\"`).join(' and ')} from the connect query `\n + 'that also carries the key, so the field would be read as both. Rename the field.',\n );\n }\n\n if (fieldSchema.type !== 'string' || !(schema.required ?? []).includes(field))\n {\n throw new Error(\n `State \"${id}\" key field \"${field}\" is not a required string. `\n + 'A key travels as a query parameter, which is always a string, and the SSE filter compares it with the '\n + 'connect query as one — a number would never match, and a missing field names no value. '\n + `Declare it ${field}: Type.String().`,\n );\n }\n}\n\n/**\n * Declare a server-owned state.\n *\n * @example\n * ```typescript\n * export const consent = defineState('consent')\n * .value(Type.Union([Type.Literal('pending'), Type.Literal('agreed')]))\n * .read(({ subject }) => consents.current(subject));\n * ```\n */\nexport function defineState<TId extends string>(id: TId): StateBuilder<TId, EmptyStateShape>\n{\n if (!STATE_ID.test(id))\n {\n throw new Error(\n `defineState(\"${id}\"): a state id must match ${STATE_ID}. `\n + 'It becomes part of the route names get<Id>State / put<Id>State and of the event name state.<id>.changed. '\n + 'Use a lowerCamel identifier, e.g. \"myState\".',\n );\n }\n\n return new StateBuilder(id, { id, shared: false, middlewares: [] });\n}\n","/**\n * State Routes\n *\n * The read, write and snapshot routes a state router derives. They are\n * ordinary `RouteDef`s registered through `registerRoutes`, so a state's\n * `.use()` middleware runs inside the route's own chain after the app's\n * global middleware.\n */\n\nimport { Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport type { Context } from 'hono';\nimport { ForbiddenError, UnauthorizedError } from '@spfn/core/errors';\nimport { route } from '@spfn/core/route';\nimport type { RouteContract, RouteDef, RouteInput } from '@spfn/core/route';\nimport {\n permissionContext,\n pickKey,\n readAndPublish,\n readContext,\n readSnapshot,\n} from './state-event';\nimport type { RoutableState, StateCallContext, StateDefinition } from './types';\n\n/** Who a request is for. `null` answers 401. */\nexport type SubjectResolver = (c: Context) => string | null;\n\n/** The SSE `getSubject` default: the `userId` the app's auth middleware set. */\nexport const defaultSubject: SubjectResolver = c =>\n (c.get('auth') as Record<string, string> | undefined)?.userId ?? null;\n\ntype Key = Record<string, string>;\n\n/** `get<Id>State` / `put<Id>State`. */\nexport function stateRouteName(method: 'get' | 'put', id: string): string\n{\n return `${method}${id[0].toUpperCase()}${id.slice(1)}State`;\n}\n\nfunction requireSubject(c: Context, resolveSubject: SubjectResolver): string\n{\n const subject = resolveSubject(c);\n\n if (!subject)\n {\n throw new UnauthorizedError({ message: 'A state is read for a subject, and this request carries none' });\n }\n\n return subject;\n}\n\nasync function assertPermitted(def: StateDefinition, can: 'canRead' | 'canWrite', ctx: StateCallContext): Promise<void>\n{\n const predicate = can === 'canWrite' ? def.canWrite ?? def.canRead : def.canRead;\n\n if (predicate && !await predicate(ctx))\n {\n throw new ForbiddenError({ message: `${can === 'canWrite' ? 'Writing' : 'Reading'} state \"${def.id}\" is not permitted` });\n }\n}\n\nfunction responseSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n at: Type.String(),\n value: def.value!,\n ...(def.data ? { data: def.data } : {}),\n });\n}\n\n/**\n * The route contract, or none when the state declares no `.contract()`. A\n * write's own version markers win over the state's, field by field.\n */\nfunction routeContract(def: StateDefinition, write: boolean): RouteContract | undefined\n{\n if (!def.contract)\n {\n return undefined;\n }\n\n const own = write ? stripUndefined(def.write!.options) : {};\n\n return stripUndefined({ ...def.contract, ...own, response: responseSchema(def) }) as RouteContract;\n}\n\nfunction stripUndefined<T extends object>(value: T): Partial<T>\n{\n return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined)) as Partial<T>;\n}\n\n/** `route.<method>(path)` with the state's input, middleware, skips and contract. */\nfunction stateRoute(def: StateDefinition, method: 'get' | 'put', path: string, input: RouteInput)\n{\n const contract = routeContract(def, method === 'put');\n const builder = route[method](path).input(input).use(def.middlewares);\n const skipped = def.skipMiddlewares ? builder.skip(def.skipMiddlewares) : builder;\n\n return contract ? skipped.contract(contract) : skipped;\n}\n\nfunction keyInput(def: StateDefinition): { query?: TObject }\n{\n return def.key ? { query: def.key } : {};\n}\n\n/** `GET <path>/<id>`: subject → key → `canRead` → `at` → `read()`. */\nexport function readRoute(state: RoutableState, path: string, resolveSubject: SubjectResolver): RouteDef<any, any, any>\n{\n const def = state._definition;\n\n return stateRoute(def, 'get', `${path}/${def.id}`, keyInput(def)).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = c.raw.get('auth');\n const key = def.key ? pickKey(def.key, (await c.data()).query) : undefined;\n await assertPermitted(def, 'canRead', permissionContext(def, subject, principal, key));\n\n return readSnapshot(def, readContext(def, subject, principal, key));\n });\n}\n\n/** `PUT <path>/<id>`: subject → key → `canWrite ?? canRead` → `write()` → `at` → `read()` → one frame. */\nexport function writeRoute(state: RoutableState, path: string, resolveSubject: SubjectResolver): RouteDef<any, any, any>\n{\n const def = state._definition;\n const write = def.write!;\n\n return stateRoute(def, 'put', `${path}/${def.id}`, { body: write.input, ...keyInput(def) }).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = c.raw.get('auth');\n const { body, query } = await c.data();\n const key = def.key ? pickKey(def.key, query) : undefined;\n await assertPermitted(def, 'canWrite', permissionContext(def, subject, principal, key));\n await write.fn({ ...readContext(def, subject, principal, key), input: body });\n\n return readAndPublish(def, state._event, subject, key, principal);\n });\n}\n\n/**\n * The snapshot's query: every key field of every keyed state, each optional —\n * a state whose key is incomplete is left out, not refused.\n */\nfunction snapshotQuery(states: RoutableState[]): TObject\n{\n const fields: Record<string, TSchema> = {};\n\n for (const state of states)\n {\n for (const [field, schema] of Object.entries(state._definition.key?.properties ?? {}))\n {\n fields[field] = Type.Optional(schema);\n }\n }\n\n return Type.Object(fields);\n}\n\n/** One state's entry in the snapshot, or `undefined` when its key is incomplete or `canRead` refuses. */\nasync function snapshotEntry(def: StateDefinition, subject: string, principal: unknown, query: Record<string, unknown>, at: string)\n{\n const key: Key | undefined = def.key ? pickKey(def.key, query) : undefined;\n\n if (def.key && !key)\n {\n return undefined;\n }\n\n if (def.canRead && !await def.canRead(permissionContext(def, subject, principal, key)))\n {\n return undefined;\n }\n\n const { value, data } = await readSnapshot(def, readContext(def, subject, principal, key), at);\n\n return def.data ? { value, data } : { value };\n}\n\n/** What the browser cannot read from a type: every state, in declaration order, its key fields and whether it has a write. */\nexport type StatesManifest = Record<string, { key: string[]; write: boolean }>;\n\n/** The snapshot's `manifest`. It is static: the router builds it once and every snapshot answers the same object. */\nexport function stateManifest(states: RoutableState[]): StatesManifest\n{\n return Object.fromEntries(states.map(state => [state.id, {\n key: Object.keys(state._definition.key?.properties ?? {}),\n write: state._definition.write !== undefined,\n }]));\n}\n\n/**\n * `GET <path>`: one `at`, then every readable state in declaration order, and\n * the router's `manifest`. A `read()` that throws fails it all.\n */\nexport function snapshotRoute(states: RoutableState[], manifest: StatesManifest, path: string, resolveSubject: SubjectResolver): RouteDef<any, any, any>\n{\n return route.get(path).input({ query: snapshotQuery(states) }).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = c.raw.get('auth');\n const { query } = await c.data();\n const at = new Date().toISOString();\n const entries = await Promise.all(states.map(state => snapshotEntry(state._definition, subject, principal, query, at)));\n\n return {\n at,\n states: Object.fromEntries(states\n .map((state, index) => [state.id, entries[index]])\n .filter(([, entry]) => entry !== undefined)),\n manifest,\n };\n });\n}\n","/**\n * State Router\n *\n * Groups states, derives their routes into one `Router` the app mounts with\n * `.packages()`, collects their SSE events for the app's event router, and\n * subscribes each state's change signal — once, here.\n */\n\nimport type { Static, TObject, TSchema } from '@sinclair/typebox';\nimport type { EventDef } from '@spfn/core/event';\nimport { defineRouter } from '@spfn/core/route';\nimport type { RouteDef, Router } from '@spfn/core/route';\nimport { bindState, stateBinding } from './state-binding';\nimport { changedPayloadSchema, stateEventName, subscribeChangeSignals } from './state-event';\nimport { defaultSubject, readRoute, snapshotRoute, stateManifest, stateRouteName, writeRoute } from './state-routes';\nimport type { SubjectResolver } from './state-routes';\nimport type { RoutableState, StateFrame, StateKey, StateResult, StateSnapshot, StateValue } from './types';\n\nexport interface StateRouterOptions\n{\n /**\n * Where the routes are mounted: `GET <path>`, `GET|PUT <path>/<id>`.\n * @default '/state'\n */\n path?: string;\n\n /**\n * Who an HTTP request is for. `null` answers 401.\n * @default (c) => c.get('auth')?.userId ?? null\n */\n subject?: SubjectResolver;\n}\n\ntype Shape<S extends RoutableState> = S['_types'];\n\ntype KeyQuery<S extends RoutableState> = Shape<S>['key'] extends TObject ? { query: Shape<S>['key'] } : {};\n\ntype ReadRoutes<S extends Record<string, RoutableState>> = {\n [K in keyof S as `get${Capitalize<S[K]['id']>}State`]: RouteDef<KeyQuery<S[K]>, {}, StateSnapshot<Shape<S[K]>>>;\n};\n\ntype WriteInput<S extends RoutableState> = KeyQuery<S> & { body: Shape<S>['input'] };\n\ntype WriteRoutes<S extends Record<string, RoutableState>> = {\n [K in keyof S as Shape<S[K]>['input'] extends TSchema ? `put${Capitalize<S[K]['id']>}State` : never]: RouteDef<WriteInput<S[K]>, {}, StateSnapshot<Shape<S[K]>>>;\n};\n\n/**\n * What `GET <path>` answers: every state the subject may read and whose key\n * the query carries, and the manifest of every state — its key fields and\n * whether it has a write — in declaration order.\n */\nexport type StatesSnapshot<S extends Record<string, RoutableState>> = {\n at: string;\n states: { [K in keyof S as S[K]['id']]?: StateResult<Shape<S[K]>> };\n manifest: { [K in keyof S as S[K]['id']]: { key: string[]; write: boolean } };\n};\n\n/** The routes one state router derives, typed for `createApi` and the route map. */\nexport type StateRoutes<S extends Record<string, RoutableState>> = ReadRoutes<S> & WriteRoutes<S> & {\n getStates: RouteDef<{ query: TObject }, {}, StatesSnapshot<S>>;\n};\n\n/** The SSE events, keyed by their wire names, for the app's `defineEventRouter`. */\nexport type StateEvents<S extends Record<string, RoutableState>> = {\n [K in keyof S as `state.${S[K]['id']}.changed`]: EventDef<StateFrame<Shape<S[K]>>>;\n};\n\nexport interface StateRouter<S extends Record<string, RoutableState>>\n{\n /** The derived routes. Mount with `appRouter.packages([states.router])`. */\n router: Router<StateRoutes<S>>;\n\n /** The derived SSE events. Spread into `defineEventRouter({ ...appEvents, ...states.events })`. */\n events: StateEvents<S>;\n\n /** The declarations, as given. */\n states: S;\n}\n\ntype StateById<R extends StateRouter<any>, TId extends string> = Extract<R['states'][keyof R['states']], { id: TId }>;\n\n/** The value type of state `TId` of a state router. */\nexport type InferStateValue<R extends StateRouter<any>, TId extends string> = StateValue<Shape<StateById<R, TId>>>;\n\n/** The key type of state `TId`, `undefined` when it is keyless. */\nexport type InferStateKey<R extends StateRouter<any>, TId extends string> = StateKey<Shape<StateById<R, TId>>>;\n\n/** The write input of state `TId`, `never` when it declares no `.write()`. */\nexport type InferStateInput<R extends StateRouter<any>, TId extends string> =\n Shape<StateById<R, TId>>['input'] extends TSchema ? Static<Shape<StateById<R, TId>>['input']> : never;\n\n/**\n * Group states, derive their routes and SSE events, and subscribe their change\n * signals.\n *\n * @example\n * ```typescript\n * export const states = defineStateRouter({ consent, runtime, member });\n *\n * // server.config.ts\n * // .routes(appRouter.packages([states.router]))\n * // .events(defineEventRouter({ ...appEvents, ...states.events }), { auth: { enabled: true } })\n * ```\n */\nexport function defineStateRouter<S extends Record<string, RoutableState>>(\n states: S,\n options: StateRouterOptions = {},\n): StateRouter<S>\n{\n const path = options.path ?? '/state';\n const list = Object.values(states);\n\n assertPath(path);\n list.forEach(assertRoutable);\n assertDistinctIds(list);\n list.forEach(state => assertNotRouted(state, path));\n\n list.forEach(state => bindState(state._definition, path));\n list.forEach(subscribeChangeSignals);\n\n return {\n router: defineRouter(deriveRoutes(list, path, options.subject ?? defaultSubject)) as Router<StateRoutes<S>>,\n events: Object.fromEntries(list.map(state => [stateEventName(state.id), state._event])) as StateEvents<S>,\n states,\n };\n}\n\nfunction deriveRoutes(states: RoutableState[], path: string, resolveSubject: SubjectResolver): Record<string, RouteDef<any, any, any>>\n{\n const routes: Record<string, RouteDef<any, any, any>> = {};\n\n for (const state of states)\n {\n routes[stateRouteName('get', state.id)] = readRoute(state, path, resolveSubject);\n\n if (state._definition.write)\n {\n routes[stateRouteName('put', state.id)] = writeRoute(state, path, resolveSubject);\n }\n }\n\n routes.getStates = snapshotRoute(states, stateManifest(states), path, resolveSubject);\n\n return routes;\n}\n\nfunction assertPath(path: string): void\n{\n if (!path.startsWith('/') || (path.length > 1 && path.endsWith('/')))\n {\n throw new Error(\n `defineStateRouter(..., { path: \"${path}\" }) is not an absolute path without a trailing slash. `\n + 'The routes are mounted at <path> and <path>/<id>. Write it as \"/state\".',\n );\n }\n}\n\n/** Refuse a state the router could not serve, naming it. */\nfunction assertRoutable(state: RoutableState): void\n{\n const def = state._definition;\n const missing = !def.value ? '.value()' : !def.read ? '.read()' : undefined;\n\n if (missing)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" declares no ${missing}. `\n + 'A state answers with the value its read returns, so both are required. '\n + `Add ${missing} to defineState('${state.id}').`,\n );\n }\n\n if (def.key && !def.canRead)\n {\n throw new Error(\n `defineStateRouter: keyed state \"${state.id}\" declares no .canRead(). `\n + 'The key comes from the request, so without it any subject could read any key. '\n + 'Add .canRead(({ subject, key }) => ...).',\n );\n }\n\n assertMiddlewareIsNotAuthorization(state);\n def.changedBy?.forEach(event => assertChangedBy(state, event));\n\n if (def.write && !def.contract && def.write.options.since)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" gives .write(..., { since: '${def.write.options.since}' }) `\n + 'but declares no .contract(), so there is nothing to fall back from: the write route would have a version '\n + 'but no auth profile, and the read route and the event would not be contracted at all. '\n + 'Add .contract({ since, ... }) to the state, or drop since from the write.',\n );\n }\n}\n\n/**\n * `.use()` / `.skip()` reach the two per-state routes only: the snapshot and\n * the SSE stream cannot run HTTP middleware. A guard there would hold on one\n * route and leak through the others, so authorization must be `canRead`.\n */\nfunction assertMiddlewareIsNotAuthorization(state: RoutableState): void\n{\n const def = state._definition;\n\n if ((def.middlewares.length > 0 || def.skipMiddlewares) && !def.canRead)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" declares .use() or .skip() but no .canRead(). `\n + `Middleware reaches only ${stateRouteName('get', state.id)} / ${stateRouteName('put', state.id)} — never the `\n + 'snapshot route or the SSE stream — so it cannot authorize. Authorization belongs in .canRead(), which is '\n + 'enforced on the read route, the snapshot and the stream. A state that needs middleware only for, say, rate '\n + 'limiting declares .canRead(() => true) to say so.',\n );\n }\n}\n\n/** A `.changedBy()` event must carry every field the state's change signal names, as a required property. */\nfunction assertChangedBy(state: RoutableState, event: EventDef<any>): void\n{\n const payload = event.schema as TObject | undefined;\n const signal = changedPayloadSchema(state._definition);\n const missing = Object.keys(signal.properties).find(field =>\n !payload?.properties?.[field] || !(payload.required ?? []).includes(field));\n\n if (missing)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" lists event \"${event.name}\" in .changedBy(), but its payload schema `\n + `has no required field \"${missing}\". Its payload is read like ${state.id}.changed.emit(), which names `\n + `${Object.keys(signal.properties).join(', ')}. Add the field to the event, or emit ${state.id}.changed instead.`,\n );\n }\n}\n\nfunction assertDistinctIds(states: RoutableState[]): void\n{\n const seen = new Set<string>();\n\n for (const state of states)\n {\n if (seen.has(state.id))\n {\n throw new Error(\n `defineStateRouter: two states have the id \"${state.id}\". `\n + `Both would derive the routes ${stateRouteName('get', state.id)} and the event `\n + `${stateEventName(state.id)}, and one would shadow the other. Rename one.`,\n );\n }\n seen.add(state.id);\n }\n}\n\nfunction assertNotRouted(state: RoutableState, path: string): void\n{\n const other = stateBinding(state._definition)?.path;\n\n if (other !== undefined)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" is already in another state router (path ${other}, this one ${path}). `\n + 'Each router subscribes the state\\'s change signal, so every change would be read and sent twice. '\n + 'Group each state in one router.',\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/state/state-binding.ts","../../src/state/state-event.ts","../../src/state/state-builder.ts","../../src/state/state-routes.ts","../../src/state/state-router.ts"],"names":["Type","Value","resultSchema"],"mappings":";;;;;;;;;AAmBA,IAAM,QAAA,uBAAe,OAAA,EAAiD;AAGtE,SAAS,aAAa,GAAA,EACtB;AACI,EAAA,OAAO,IAAA,CAAK,MAAA;AAAA,IACR;AAAA,MACI,OAAO,GAAA,CAAI,KAAA;AAAA,MACX,GAAI,IAAI,IAAA,GAAO,EAAE,MAAM,GAAA,CAAI,IAAA,KAAS;AAAC,KACzC;AAAA,IACA,EAAE,sBAAsB,KAAA;AAAM,GAClC;AACJ;AAGO,SAAS,SAAA,CAAU,KAAgC,IAAA,EAC1D;AACI,EAAA,QAAA,CAAS,GAAA,CAAI,KAAK,EAAE,IAAA,EAAM,cAAc,YAAA,CAAa,GAAG,GAAG,CAAA;AAC/D;AAGO,SAAS,aAAa,GAAA,EAC7B;AACI,EAAA,OAAO,QAAA,CAAS,IAAI,GAAG,CAAA;AAC3B;;;ACxBA,IAAM,WAAA,GAAc,MAAA,CAAO,KAAA,CAAM,kBAAkB,CAAA;AAe5C,SAAS,eAAe,EAAA,EAC/B;AACI,EAAA,OAAO,SAAS,EAAE,CAAA,QAAA,CAAA;AACtB;AAOO,SAAS,OAAA,CAAQ,WAAoB,MAAA,EAC5C;AACI,EAAA,MAAM,MAAW,EAAC;AAElB,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA,EACpD;AACI,IAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,IAAA,IAAI,OAAO,UAAU,QAAA,EACrB;AACI,MAAA,OAAO,MAAA;AAAA,IACX;AACA,IAAA,GAAA,CAAI,KAAK,CAAA,GAAI,KAAA;AAAA,EACjB;AAEA,EAAA,OAAO,GAAA;AACX;AAGO,SAAS,WAAA,CAAY,GAAA,EAAsB,OAAA,EAA6B,SAAA,EAAoB,GAAA,EACnG;AACI,EAAA,IAAI,CAAC,IAAI,GAAA,EACT;AACI,IAAA,OAAO,EAAE,SAAS,SAAA,EAAU;AAAA,EAChC;AAEA,EAAA,OAAO,GAAA,CAAI,SAAS,EAAE,SAAA,EAAW,KAAI,GAAI,EAAE,OAAA,EAAS,SAAA,EAAW,GAAA,EAAI;AACvE;AAGO,SAAS,iBAAA,CAAkB,GAAA,EAAsB,OAAA,EAAiB,SAAA,EAAoB,GAAA,EAC7F;AACI,EAAA,OAAO,GAAA,CAAI,MAAM,EAAE,OAAA,EAAS,WAAW,GAAA,EAAI,GAAI,EAAE,OAAA,EAAS,SAAA,EAAU;AACxE;AAMO,SAAS,cAAA,CAAe,KAAsB,IAAA,EACrD;AACI,EAAA,MAAM,OAAA,GAAU,aAAa,GAAG,CAAA;AAEhC,EAAA,IAAI,CAAC,OAAA,EACL;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,OAAA,EAAU,GAAA,CAAI,EAAE,CAAA,iCAAA,EAAoC,IAAI,CAAA,wPAAA;AAAA,KAI5D;AAAA,EACJ;AAEA,EAAA,OAAO,OAAA;AACX;AAGA,SAAS,YAAA,CAAa,GAAA,EAAsB,OAAA,EAAuB,MAAA,EACnE;AACI,EAAA,MAAM,QAAQ,KAAA,CAAM,MAAA,CAAO,QAAQ,YAAA,EAAc,MAAM,EAAE,KAAA,EAAM;AAE/D,EAAA,IAAI,KAAA,EACJ;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,OAAA,EAAU,GAAA,CAAI,EAAE,CAAA,2DAAA,EAA8D,MAAM,IAAA,IAAQ,QAAQ,CAAA,CAAA,EAAI,KAAA,CAAM,OAAO,CAAA,qJAAA,EAGhH,GAAA,CAAI,IAAA,GAAO,WAAW,EAAE,CAAA,eAAA;AAAA,KACjC;AAAA,EACJ;AACJ;AAOA,eAAsB,YAAA,CAAa,KAAsB,GAAA,EAAuB,EAAA,GAAA,qBAAS,IAAA,EAAK,EAAE,aAAY,EAC5G;AACI,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,GAAA,EAAK,QAAQ,CAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,CAAM,GAAG,CAAA;AAClC,EAAA,YAAA,CAAa,GAAA,EAAK,SAAS,MAAM,CAAA;AAEjC,EAAA,OAAO,EAAE,EAAA,EAAI,GAAG,MAAA,EAAO;AAC3B;AAOA,SAAS,OAAA,CAAQ,GAAA,EAAsB,QAAA,EAAoB,OAAA,EAA6B,GAAA,EACxF;AACI,EAAA,MAAM,KAAA,GAAsB,gBAAgB,QAAQ,CAAA;AAEpD,EAAA,IAAI,IAAI,GAAA,EACR;AACI,IAAA,KAAA,CAAM,GAAA,GAAM,EAAE,GAAG,GAAA,EAAI;AAAA,EACzB;AAEA,EAAA,IAAI,EAAE,GAAA,CAAI,GAAA,IAAO,GAAA,CAAI,MAAA,CAAA,EACrB;AACI,IAAA,KAAA,CAAM,OAAA,GAAU,OAAA;AAAA,EACpB;AAEA,EAAA,OAAO,KAAA;AACX;AAaA,eAAsB,cAAA,CAClB,GAAA,EACA,KAAA,EACA,OAAA,EACA,KACA,SAAA,EAEJ;AACI,EAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,GAAA,EAAK,YAAY,GAAA,EAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAC,CAAA;AAClF,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,EAAK,QAAA,EAAU,SAAS,GAAG,CAAA;AAEjD,EAAA,IAAI,uBAAsB,EAC1B;AACI,IAAA,aAAA,CAAc,MAAM,KAAA,CAAM,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,EACzC,CAAA,MAEA;AACI,IAAA,MAAM,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,EAC1B;AAEA,EAAA,OAAO,QAAA;AACX;AAMA,SAAS,mBAAmB,GAAA,EAC5B;AACI,EAAA,OAAOA,KAAK,MAAA,CAAO;AAAA,IACf,EAAA,EAAIA,KAAK,MAAA,EAAO;AAAA,IAChB,KAAA,EAAO,GAAA,CAAI,KAAA,IAASA,IAAAA,CAAK,OAAA,EAAQ;AAAA,IACjC,GAAI,IAAI,IAAA,GAAO,EAAE,MAAM,GAAA,CAAI,IAAA,KAAS,EAAC;AAAA,IACrC,GAAI,IAAI,GAAA,GAAM,EAAE,KAAK,GAAA,CAAI,GAAA,KAAQ,EAAC;AAAA,IAClC,GAAI,GAAA,CAAI,GAAA,IAAO,GAAA,CAAI,MAAA,GAAS,EAAC,GAAI,EAAE,OAAA,EAASA,IAAAA,CAAK,MAAA,EAAO;AAAE,GAC7D,CAAA;AACL;AAOA,SAAS,mBAAmB,GAAA,EAC5B;AACI,EAAA,OAAO,OAAO,EAAE,OAAA,EAAS,SAAA,EAAW,SAAQ,KAC5C;AACI,IAAA,IAAI,CAAC,IAAI,GAAA,EACT;AACI,MAAA,OAAO,GAAA,CAAI,UAAU,GAAA,CAAI,OAAA,CAAQ,EAAE,OAAA,EAAS,SAAA,EAAW,CAAA,GAAI,IAAA;AAAA,IAC/D;AAEA,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,QAAQ,KAAK,CAAA;AAE1C,IAAA,OAAO,GAAA,KAAQ,MAAA,IAAa,GAAA,CAAI,OAAA,KAAY,MAAA,IAAa,GAAA,CAAI,OAAA,CAAQ,EAAE,OAAA,EAAS,SAAA,EAAW,GAAA,EAAK,CAAA;AAAA,EACpG,CAAA;AACJ;AAQA,SAAS,eAAe,GAAA,EACxB;AACI,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,GAAM,MAAA,CAAO,KAAK,GAAA,CAAI,GAAA,CAAI,UAAU,CAAA,GAAI,EAAC;AAE5D,EAAA,OAAO,CAAC,OAAA,EAAS,EAAE,OAAA,EAAS,OAAA,OACxB,OAAA,KAAY,MAAA,IACT,MAAA,CAAO,KAAA,CAAM,CAAA,KAAA,KAAS,OAAA,CAAQ,MAAM,KAAK,CAAA,KAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAC,MAClE,OAAA,CAAQ,OAAA,KAAY,MAAA,IAAa,OAAA,CAAQ,OAAA,KAAY,OAAA,CAAA;AACjE;AAGO,SAAS,iBAAiB,GAAA,EACjC;AACI,EAAA,MAAM,QAAQ,WAAA,CAAY,cAAA,CAAe,IAAI,EAAE,CAAA,EAAG,mBAAmB,GAAG,CAAC,CAAA,CACpE,YAAA,CAAa,mBAAmB,GAAG,CAAC,EACpC,MAAA,CAAO,cAAA,CAAe,GAAG,CAA4B,CAAA;AAE1D,EAAA,IAAI,IAAI,QAAA,EACR;AACI,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,SAAA,KAAc,GAAA,CAAI,QAAA;AAC/C,IAAA,KAAA,CAAM,QAAA,CAAS;AAAA,MACX,KAAA;AAAA,MACA,GAAI,YAAA,GAAe,EAAE,YAAA,KAAiB,EAAC;AAAA,MACvC,GAAI,SAAA,GAAY,EAAE,SAAA,KAAc;AAAC,KACpC,CAAA;AAAA,EACL;AAEA,EAAA,OAAO,KAAA;AACX;AAYO,SAAS,qBAAqB,GAAA,EACrC;AACI,EAAA,OAAOA,KAAK,MAAA,CAAO;AAAA,IACf,GAAG,IAAI,GAAA,EAAK,UAAA;AAAA,IACZ,GAAI,GAAA,CAAI,GAAA,IAAO,GAAA,CAAI,MAAA,GAAS,EAAC,GAAI,EAAE,OAAA,EAASA,IAAAA,CAAK,MAAA,EAAO;AAAE,GAC7D,CAAA;AACL;AAEA,SAAS,oBAAA,CAAqB,GAAA,EAAsB,MAAA,EAAiB,OAAA,EACrE;AACI,EAAA,MAAM,QAAQ,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,OAAO,EAAE,KAAA,EAAM;AAElD,EAAA,IAAI,KAAA,EACJ;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,EAAG,IAAI,EAAE,CAAA,qCAAA,EAAwC,MAAM,IAAA,IAAQ,QAAQ,CAAA,CAAA,EAAI,KAAA,CAAM,OAAO,CAAA,gHAAA,EAE9E,IAAI,GAAA,GAAM,iBAAA,GAAoB,aAAa,CAAA,EAAG,GAAA,CAAI,OAAO,CAAC,GAAA,CAAI,MAAA,GAAS,kBAAA,GAAqB,EAAE,CAAA,CAAA;AAAA,KAC5G;AAAA,EACJ;AACJ;AAOO,SAAS,oBAAoB,GAAA,EACpC;AACI,EAAA,MAAM,MAAA,GAAS,qBAAqB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAQ,WAAA,CAAY,CAAA,MAAA,EAAS,GAAA,CAAI,EAAE,WAAW,MAAM,CAAA;AAC1D,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AAEnB,EAAA,KAAA,CAAM,IAAA,IAAQ,OAAO,OAAA,KACrB;AACI,IAAA,cAAA,CAAe,GAAA,EAAK,CAAA,EAAG,GAAA,CAAI,EAAE,CAAA,eAAA,CAAiB,CAAA;AAC9C,IAAA,oBAAA,CAAqB,GAAA,EAAK,QAAQ,OAAO,CAAA;AACzC,IAAA,MAAM,KAAK,OAAkC,CAAA;AAAA,EACjD,CAAA,CAAA;AAEA,EAAA,OAAO,KAAA;AACX;AAGA,SAAS,YAAA,CAAa,KAAsB,OAAA,EAC5C;AACI,EAAA,MAAM,UAAU,GAAA,CAAI,GAAA,IAAO,GAAA,CAAI,MAAA,GAAS,SAAY,OAAA,CAAQ,OAAA;AAE5D,EAAA,OAAO,EAAE,OAAA,EAAS,GAAA,EAAK,GAAA,CAAI,GAAA,GAAM,QAAQ,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA,GAAI,MAAA,EAAU;AAC3E;AAOA,eAAe,QAAA,CAAS,OAAsB,OAAA,EAC9C;AACI,EAAA,MAAM,EAAE,OAAA,EAAS,GAAA,KAAQ,YAAA,CAAa,KAAA,CAAM,aAAa,OAAO,CAAA;AAEhE,EAAA,IACA;AACI,IAAA,MAAM,eAAe,KAAA,CAAM,WAAA,EAAa,MAAM,MAAA,EAAQ,OAAA,EAAS,KAAK,MAAS,CAAA;AAAA,EACjF,SACO,KAAA,EACP;AACI,IAAA,WAAA,CAAY,IAAA,CAAK,CAAA,OAAA,EAAU,KAAA,CAAM,EAAE,CAAA,2EAAA,CAAA,EAA+E;AAAA,MAC9G,OAAO,KAAA,CAAM,EAAA;AAAA,MACb,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAAA,KAC/D,CAAA;AAAA,EACL;AACJ;AAOA,eAAe,WAAA,CAAY,KAAA,EAAsB,KAAA,EAAsB,MAAA,EAAiB,OAAA,EACxF;AACI,EAAA,MAAM,QAAQ,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,OAAO,EAAE,KAAA,EAAM;AAElD,EAAA,IAAI,KAAA,EACJ;AACI,IAAA,WAAA,CAAY,KAAK,CAAA,OAAA,EAAU,KAAA,CAAM,EAAE,CAAA,cAAA,EAAiB,KAAA,CAAM,IAAI,CAAA,wCAAA,CAAA,EAA4C;AAAA,MACtG,OAAO,KAAA,CAAM,EAAA;AAAA,MACb,OAAO,KAAA,CAAM,IAAA;AAAA,MACb,OAAO,CAAA,EAAG,KAAA,CAAM,QAAQ,QAAQ,CAAA,CAAA,EAAI,MAAM,OAAO,CAAA;AAAA,KACpD,CAAA;AAED,IAAA;AAAA,EACJ;AAEA,EAAA,MAAM,QAAA,CAAS,OAAO,OAAkC,CAAA;AAC5D;AAUO,SAAS,uBAAuB,KAAA,EACvC;AACI,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,KAAA,CAAM,WAAW,CAAA;AAErD,EAAA,KAAA,CAAM,QAAQ,SAAA,CAAU,CAAA,OAAA,KAAW,QAAA,CAAS,KAAA,EAAO,OAAO,CAAC,CAAA;AAC3D,EAAA,KAAA,CAAM,YAAY,SAAA,EAAW,OAAA,CAAQ,CAAA,KAAA,KACjC,KAAA,CAAM,UAAU,CAAA,OAAA,KAAW,WAAA,CAAY,KAAA,EAAO,KAAA,EAAO,QAAQ,OAAO,CAAA,EAAG,EAAE,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AACnG;;;ACrVA,IAAM,QAAA,GAAW,qBAAA;AAMjB,IAAM,mBAAA,GAAsB,CAAC,QAAA,EAAU,OAAO,CAAA;AAKvC,IAAM,YAAA,GAAN,MAAM,aAAA,CACb;AAAA,EAOI,WAAA,CACa,IACA,WAAA,EAEb;AAHa,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACA,IAAA,IAAA,CAAA,WAAA,GAAA,WAAA;AAAA,EAGb;AAAA,EARQ,aAAA;AAAA,EACA,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaR,GAAA,CACI,MAAA,EACA,OAAA,GAA0B,EAAC,EAE/B;AACI,IAAA,IAAA,CAAK,WAAW,KAAA,EAAO,CAAC,CAAC,IAAA,CAAK,YAAY,GAAG,CAAA;AAC7C,IAAA,eAAA,CAAgB,IAAA,CAAK,IAAI,MAAM,CAAA;AAE/B,IAAA,OAAO,IAAA,CAAK,KAAK,EAAE,GAAA,EAAK,QAAQ,MAAA,EAAQ,OAAA,CAAQ,MAAA,KAAW,IAAA,EAAM,CAAA;AAAA,EACrE;AAAA;AAAA,EAGA,MAAyB,MAAA,EACzB;AACI,IAAA,IAAA,CAAK,WAAW,OAAA,EAAS,CAAC,CAAC,IAAA,CAAK,YAAY,KAAK,CAAA;AAEjD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,KAAA,EAAO,QAAQ,CAAA;AAAA,EACtC;AAAA;AAAA,EAGA,KAAwB,MAAA,EACxB;AACI,IAAA,IAAA,CAAK,WAAW,MAAA,EAAQ,CAAC,CAAC,IAAA,CAAK,YAAY,IAAI,CAAA;AAE/C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,IAAA,EAAM,QAAQ,CAAA;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAA,GACA;AACI,IAAA,IAAA,CAAK,UAAA,CAAW,WAAA,EAAa,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA;AAEvD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,WAAA,EACJ;AACI,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,WAAA,EAAa,CAAC,GAAG,IAAA,CAAK,WAAA,CAAY,WAAA,EAAa,GAAG,WAAW,CAAA,EAAG,CAAA;AAAA,EACvF;AAAA;AAAA,EAGA,KAAK,eAAA,EACL;AACI,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,CAAY,eAAA,IAAmB,EAAC;AACrD,IAAA,MAAM,eAAA,GAAkB,OAAA,KAAY,GAAA,IAAO,eAAA,KAAoB,GAAA,GACzD,MACA,CAAC,GAAG,OAAA,EAAS,GAAG,eAAe,CAAA;AAErC,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,eAAA,EAAiB,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,SAAS,QAAA,EACT;AACI,IAAA,IAAA,CAAK,WAAW,UAAA,EAAY,CAAC,CAAC,IAAA,CAAK,YAAY,QAAQ,CAAA;AAEvD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,CAAA;AAAA,EACjC;AAAA;AAAA,EAGA,QAAQ,SAAA,EACR;AACI,IAAA,IAAA,CAAK,WAAW,SAAA,EAAW,CAAC,CAAC,IAAA,CAAK,YAAY,OAAO,CAAA;AAErD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,OAAA,EAAS,WAA6B,CAAA;AAAA,EAC7D;AAAA;AAAA,EAGA,SAAS,SAAA,EACT;AACI,IAAA,IAAA,CAAK,WAAW,UAAA,EAAY,CAAC,CAAC,IAAA,CAAK,YAAY,QAAQ,CAAA;AAEvD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,WAA6B,CAAA;AAAA,EAC9D;AAAA;AAAA,EAGA,KACI,EAAA,EAEJ;AACI,IAAA,IAAA,CAAK,WAAW,MAAA,EAAQ,CAAC,CAAC,IAAA,CAAK,YAAY,IAAI,CAAA;AAE/C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,EAAE,IAAA,EAAM,IAAmB,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAA,CACI,KAAA,EACA,EAAA,EACA,OAAA,GAA6B,EAAC,EAElC;AACI,IAAA,IAAA,CAAK,WAAW,OAAA,EAAS,CAAC,CAAC,IAAA,CAAK,YAAY,KAAK,CAAA;AAEjD,IAAA,OAAO,IAAA,CAAK,KAAK,EAAE,KAAA,EAAO,EAAE,KAAA,EAAO,EAAA,EAAuB,OAAA,EAAQ,EAAG,CAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,MAAA,EACV;AACI,IAAA,IAAA,CAAK,WAAW,WAAA,EAAa,CAAC,CAAC,IAAA,CAAK,YAAY,SAAS,CAAA;AAEzD,IAAA,OAAO,IAAA,CAAK,KAAK,EAAE,SAAA,EAAW,CAAC,GAAG,MAAM,GAAG,CAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,OAAA,GACJ;AACI,IAAA,IAAA,CAAK,aAAA,KAAkB,mBAAA,CAAoB,IAAA,CAAK,WAAW,CAAA;AAE3D,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EAChB;AAAA;AAAA,EAGA,IAAI,MAAA,GACJ;AACI,IAAA,IAAA,CAAK,UAAA,KAAe,gBAAA,CAAiB,IAAA,CAAK,WAAW,CAAA;AAErD,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,MAAM,MAAA,EACZ;AACI,IAAA,MAAM,EAAE,OAAA,EAAS,GAAA,EAAI,GAAI,MAAA;AACzB,IAAA,cAAA,CAAe,IAAA,CAAK,WAAA,EAAa,CAAA,EAAG,IAAA,CAAK,EAAE,CAAA,QAAA,CAAU,CAAA;AACrD,IAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AACvB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,OAAA,EAAS,GAAG,CAAA;AAC9C,IAAA,MAAM,IAAA,CAAK,OAAO,KAAA,CAAM,OAAA,EAAS,YAAY,EAAE,KAAA,EAAO,UAAU,CAAA;AAChE,IAAA,MAAM,eAAe,IAAA,CAAK,WAAA,EAAa,KAAK,MAAA,EAAQ,OAAA,EAAS,UAAU,MAAS,CAAA;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,MAAA,EACb;AACI,IAAA,MAAM,EAAE,OAAA,EAAS,GAAA,EAAI,GAAI,MAAA;AACzB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,QAAA,EAAU,GAAG,CAAA;AAC/C,IAAA,MAAM,IAAA,CAAK,OAAO,MAAA,CAAO,OAAA,EAAS,YAAY,EAAE,KAAA,EAAO,UAAU,CAAA;AAAA,EACrE;AAAA;AAAA,EAGQ,eAAe,GAAA,EACvB;AACI,IAAA,IAAI,IAAA,CAAK,WAAA,CAAY,GAAA,IAAO,CAAC,GAAA,EAC7B;AACI,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,CAAA,OAAA,EAAU,KAAK,EAAE,CAAA,4MAAA;AAAA,OAGrB;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,WAAA,CAAY,QAA4B,GAAA,EAChD;AACI,IAAA,MAAM,MAAA,GAAS,KAAK,WAAA,CAAY,GAAA;AAChC,IAAA,IAAI,CAAC,MAAA,IAAU,GAAA,KAAQ,MAAA,EACvB;AACI,MAAA,OAAO,MAAA;AAAA,IACX;AAEA,IAAA,MAAM,QAAQC,KAAAA,CAAM,MAAA,CAAO,EAAE,GAAGD,KAAK,MAAA,CAAO,MAAA,CAAO,UAAU,CAAA,EAAG,UAAU,MAAA,CAAO,QAAA,EAAS,EAAG,GAAG,EAAE,KAAA,EAAM;AACxG,IAAA,IAAI,KAAA,EACJ;AACI,MAAA,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA,EAAG,KAAA,CAAM,QAAQ,QAAQ,CAAA,CAAA,EAAI,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,IACvE;AAEA,IAAA,OAAO,QAAQ,MAAA,EAAQ,GAAG,KAAK,IAAA,CAAK,SAAA,CAAU,QAAQ,wDAAwD,CAAA;AAAA,EAClH;AAAA,EAEQ,SAAA,CAAU,QAA4B,MAAA,EAC9C;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,OAAA,EAAU,KAAK,EAAE,CAAA,GAAA,EAAM,MAAM,CAAA,oBAAA,EAAuB,MAAM,aAC7C,MAAM,CAAA,8EAAA;AAAA,KACvB;AAAA,EACJ;AAAA,EAEQ,KAAK,OAAA,EACb;AACI,IAAA,OAAO,IAAI,aAAA,CAAa,IAAA,CAAK,EAAA,EAAI,EAAE,GAAG,IAAA,CAAK,WAAA,EAAa,GAAG,OAAA,EAAS,CAAA;AAAA,EACxE;AAAA,EAEQ,UAAA,CAAW,QAAgB,QAAA,EACnC;AACI,IAAA,IAAI,QAAA,EACJ;AACI,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,UAAU,IAAA,CAAK,EAAE,CAAA,oBAAA,EAAuB,MAAM,oGAEhC,MAAM,CAAA,QAAA;AAAA,OACxB;AAAA,IACJ;AAAA,EACJ;AACJ;AAMA,SAAS,eAAA,CAAgB,IAAY,MAAA,EACrC;AACI,EAAA,IAAI,MAAA,CAAO,IAAI,CAAA,KAAM,QAAA,EACrB;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,UAAU,EAAE,CAAA,qCAAA,EAAwC,OAAO,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA,mJAAA;AAAA,KAG5E;AAAA,EACJ;AAEA,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,OAAA,CAAS,MAAA,CAAmB,UAAU,CAAA;AAE5D,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EACtB;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,UAAU,EAAE,CAAA,gHAAA;AAAA,KAEhB;AAAA,EACJ;AAEA,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAC,KAAA,EAAO,WAAW,CAAA,KAAM,cAAA,CAAe,EAAA,EAAI,MAAA,EAAmB,KAAA,EAAO,WAAW,CAAC,CAAA;AACtG;AAEA,SAAS,cAAA,CAAe,EAAA,EAAY,MAAA,EAAiB,KAAA,EAAe,WAAA,EACpE;AACI,EAAA,IAAI,mBAAA,CAAoB,QAAA,CAAS,KAAK,CAAA,EACtC;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,OAAA,EAAU,EAAE,CAAA,aAAA,EAAgB,KAAK,uCACP,mBAAA,CAAoB,GAAA,CAAI,CAAA,IAAA,KAAQ,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,OAAO,CAAC,CAAA,wGAAA;AAAA,KAExF;AAAA,EACJ;AAEA,EAAA,IAAI,WAAA,CAAY,IAAA,KAAS,QAAA,IAAY,CAAA,CAAE,MAAA,CAAO,YAAY,EAAC,EAAG,QAAA,CAAS,KAAK,CAAA,EAC5E;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,OAAA,EAAU,EAAE,CAAA,aAAA,EAAgB,KAAK,4OAGjB,KAAK,CAAA,gBAAA;AAAA,KACzB;AAAA,EACJ;AACJ;AAYO,SAAS,YAAgC,EAAA,EAChD;AACI,EAAA,IAAI,CAAC,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EACrB;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,aAAA,EAAgB,EAAE,CAAA,0BAAA,EAA6B,QAAQ,CAAA,uJAAA;AAAA,KAG3D;AAAA,EACJ;AAEA,EAAA,OAAO,IAAI,YAAA,CAAa,EAAA,EAAI,EAAE,EAAA,EAAI,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,EAAC,EAAG,CAAA;AACxF;ACzVO,IAAM,iBAAkC,CAAA,CAAA,KAC1C,CAAA,CAAE,GAAA,CAAI,MAAM,GAA0C,MAAA,IAAU,IAAA;AAK9D,SAAS,cAAA,CAAe,QAAuB,EAAA,EACtD;AACI,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,EAAA,CAAG,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,EAAA,CAAG,KAAA,CAAM,CAAC,CAAC,CAAA,KAAA,CAAA;AACxD;AAEA,SAAS,cAAA,CAAe,GAAY,cAAA,EACpC;AACI,EAAA,MAAM,OAAA,GAAU,eAAe,CAAC,CAAA;AAEhC,EAAA,IAAI,CAAC,OAAA,EACL;AACI,IAAA,MAAM,IAAI,iBAAA,CAAkB,EAAE,OAAA,EAAS,gEAAgE,CAAA;AAAA,EAC3G;AAEA,EAAA,OAAO,OAAA;AACX;AAOA,SAAS,cAAA,CAAe,KAAsB,CAAA,EAC9C;AACI,EAAA,MAAM,SAAA,GAAY,CAAA,CAAE,GAAA,CAAI,MAAM,CAAA;AAE9B,EAAA,IAAI,GAAA,CAAI,SAAA,IAAa,SAAA,IAAa,IAAA,EAClC;AACI,IAAA,MAAM,IAAI,iBAAA,CAAkB;AAAA,MACxB,OAAA,EAAS,CAAA,OAAA,EAAU,GAAA,CAAI,EAAE,CAAA,sDAAA;AAAA,KAC5B,CAAA;AAAA,EACL;AAEA,EAAA,OAAO,SAAA;AACX;AAEA,eAAe,eAAA,CAAgB,GAAA,EAAsB,GAAA,EAA6B,GAAA,EAClF;AACI,EAAA,MAAM,YAAY,GAAA,KAAQ,UAAA,GAAa,IAAI,QAAA,IAAY,GAAA,CAAI,UAAU,GAAA,CAAI,OAAA;AAEzE,EAAA,IAAI,SAAA,IAAa,CAAC,MAAM,SAAA,CAAU,GAAG,CAAA,EACrC;AACI,IAAA,MAAM,IAAI,cAAA,CAAe,EAAE,OAAA,EAAS,CAAA,EAAG,GAAA,KAAQ,UAAA,GAAa,SAAA,GAAY,SAAS,CAAA,QAAA,EAAW,GAAA,CAAI,EAAE,sBAAsB,CAAA;AAAA,EAC5H;AACJ;AAGA,SAASE,cAAa,GAAA,EACtB;AACI,EAAA,OAAOF,KAAK,MAAA,CAAO;AAAA,IACf,OAAO,GAAA,CAAI,KAAA;AAAA,IACX,GAAI,IAAI,IAAA,GAAO,EAAE,MAAM,GAAA,CAAI,IAAA,KAAS;AAAC,GACxC,CAAA;AACL;AAEA,SAAS,eAAe,GAAA,EACxB;AACI,EAAA,OAAOA,IAAAA,CAAK,MAAA,CAAO,EAAE,EAAA,EAAIA,IAAAA,CAAK,MAAA,EAAO,EAAG,GAAGE,aAAAA,CAAa,GAAG,CAAA,CAAE,UAAA,EAAY,CAAA;AAC7E;AAMA,SAAS,aAAA,CAAc,KAAsB,KAAA,EAC7C;AACI,EAAA,IAAI,CAAC,IAAI,QAAA,EACT;AACI,IAAA,OAAO,MAAA;AAAA,EACX;AAEA,EAAA,MAAM,MAAM,KAAA,GAAQ,cAAA,CAAe,IAAI,KAAA,CAAO,OAAO,IAAI,EAAC;AAE1D,EAAA,OAAO,cAAA,CAAe,EAAE,GAAG,GAAA,CAAI,QAAA,EAAU,GAAG,GAAA,EAAK,QAAA,EAAU,cAAA,CAAe,GAAG,CAAA,EAAG,CAAA;AACpF;AAEA,SAAS,eAAiC,KAAA,EAC1C;AACI,EAAA,OAAO,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,KAAU,MAAS,CAAC,CAAA;AAC9F;AAGA,SAAS,UAAA,CAAW,GAAA,EAAsB,MAAA,EAAuB,IAAA,EAAc,KAAA,EAC/E;AACI,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,GAAA,EAAK,MAAA,KAAW,KAAK,CAAA;AACpD,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,MAAM,CAAA,CAAE,IAAI,CAAA,CAAE,KAAA,CAAM,KAAK,CAAA,CAAE,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AACpE,EAAA,MAAM,UAAU,GAAA,CAAI,eAAA,GAAkB,QAAQ,IAAA,CAAK,GAAA,CAAI,eAAe,CAAA,GAAI,OAAA;AAE1E,EAAA,OAAO,QAAA,GAAW,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,GAAI,OAAA;AACnD;AAEA,SAAS,SAAS,GAAA,EAClB;AACI,EAAA,OAAO,IAAI,GAAA,GAAM,EAAE,OAAO,GAAA,CAAI,GAAA,KAAQ,EAAC;AAC3C;AAGO,SAAS,SAAA,CAAU,KAAA,EAAsB,IAAA,EAAc,cAAA,EAC9D;AACI,EAAA,MAAM,MAAM,KAAA,CAAM,WAAA;AAElB,EAAA,OAAO,UAAA,CAAW,GAAA,EAAK,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,EAAE,CAAA,CAAA,EAAI,SAAS,GAAG,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA,KACjF;AACI,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,CAAA,CAAE,GAAA,EAAK,cAAc,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA;AAClC,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAA,CAAM,MAAM,CAAA,CAAE,IAAA,EAAK,EAAG,KAAK,CAAA,GAAI,MAAA;AACjE,IAAA,MAAM,eAAA,CAAgB,KAAK,SAAA,EAAW,iBAAA,CAAkB,KAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAC,CAAA;AAErF,IAAA,OAAO,aAAa,GAAA,EAAK,WAAA,CAAY,KAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAC,CAAA;AAAA,EACtE,CAAC,CAAA;AACL;AAGO,SAAS,UAAA,CAAW,KAAA,EAAsB,IAAA,EAAc,cAAA,EAC/D;AACI,EAAA,MAAM,MAAM,KAAA,CAAM,WAAA;AAClB,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAElB,EAAA,OAAO,UAAA,CAAW,KAAK,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,EAAE,CAAA,CAAA,EAAI,EAAE,MAAM,KAAA,CAAM,KAAA,EAAO,GAAG,QAAA,CAAS,GAAG,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA,KAC3G;AACI,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,CAAA,CAAE,GAAA,EAAK,cAAc,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,GAAA,EAAK,CAAA,CAAE,GAAG,CAAA;AAC3C,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,EAAE,IAAA,EAAK;AACrC,IAAA,MAAM,MAAM,GAAA,CAAI,GAAA,GAAM,QAAQ,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA,GAAI,MAAA;AAChD,IAAA,MAAM,eAAA,CAAgB,KAAK,UAAA,EAAY,iBAAA,CAAkB,KAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAC,CAAA;AACtF,IAAA,MAAM,KAAA,CAAM,EAAA,CAAG,EAAE,GAAG,WAAA,CAAY,GAAA,EAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAA,EAAG,KAAA,EAAO,IAAA,EAAM,CAAA;AAE5E,IAAA,OAAO,eAAe,GAAA,EAAK,KAAA,CAAM,MAAA,EAAQ,OAAA,EAAS,KAAK,SAAS,CAAA;AAAA,EACpE,CAAC,CAAA;AACL;AAMA,SAAS,cAAc,MAAA,EACvB;AACI,EAAA,MAAM,SAAkC,EAAC;AAEzC,EAAA,KAAA,MAAW,SAAS,MAAA,EACpB;AACI,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,CAAA,IAAK,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,GAAA,EAAK,UAAA,IAAc,EAAE,CAAA,EACpF;AACI,MAAA,MAAA,CAAO,KAAK,CAAA,GAAIF,IAAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,IACxC;AAAA,EACJ;AAEA,EAAA,OAAOA,IAAAA,CAAK,OAAO,MAAM,CAAA;AAC7B;AAGA,eAAe,aAAA,CAAc,GAAA,EAAsB,OAAA,EAAiB,SAAA,EAAoB,OAAgC,EAAA,EACxH;AACI,EAAA,MAAM,MAAuB,GAAA,CAAI,GAAA,GAAM,QAAQ,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA,GAAI,MAAA;AAEjE,EAAA,IAAI,GAAA,CAAI,GAAA,IAAO,CAAC,GAAA,EAChB;AACI,IAAA,OAAO,MAAA;AAAA,EACX;AAEA,EAAA,IAAI,GAAA,CAAI,OAAA,IAAW,CAAC,MAAM,GAAA,CAAI,OAAA,CAAQ,iBAAA,CAAkB,GAAA,EAAK,OAAA,EAAS,SAAA,EAAW,GAAG,CAAC,CAAA,EACrF;AACI,IAAA,OAAO,MAAA;AAAA,EACX;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,YAAA,CAAa,GAAA,EAAK,WAAA,CAAY,GAAA,EAAK,OAAA,EAAS,SAAA,EAAW,GAAG,GAAG,EAAE,CAAA;AAE7F,EAAA,OAAO,IAAI,IAAA,GAAO,EAAE,OAAO,IAAA,EAAK,GAAI,EAAE,KAAA,EAAM;AAChD;AAuBO,SAAS,cAAc,MAAA,EAC9B;AACI,EAAA,OAAO,OAAO,WAAA,CAAY,MAAA,CAAO,IAAI,CAAA,KAAA,KAAS,CAAC,MAAM,EAAA,EAAI;AAAA,IACrD,GAAA,EAAK,OAAO,IAAA,CAAK,KAAA,CAAM,YAAY,GAAA,EAAK,UAAA,IAAc,EAAE,CAAA;AAAA,IACxD,KAAA,EAAO,KAAA,CAAM,WAAA,CAAY,KAAA,KAAU;AAAA,GACtC,CAAC,CAAC,CAAA;AACP;AAOA,SAAS,uBAAuB,MAAA,EAChC;AACI,EAAA,MAAM,aAAA,GAAgBA,IAAAA,CAAK,MAAA,CAAO,EAAE,KAAKA,IAAAA,CAAK,KAAA,CAAMA,IAAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,KAAA,EAAOA,IAAAA,CAAK,OAAA,IAAW,CAAA;AAE3F,EAAA,OAAOA,KAAK,MAAA,CAAO;AAAA,IACf,EAAA,EAAIA,KAAK,MAAA,EAAO;AAAA,IAChB,MAAA,EAAQA,KAAK,MAAA,CAAO,MAAA,CAAO,YAAY,MAAA,CAAO,GAAA,CAAI,WAAS,CAAC,KAAA,CAAM,IAAIA,IAAAA,CAAK,QAAA,CAASE,cAAa,KAAA,CAAM,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAAA,IACvH,QAAA,EAAUF,IAAAA,CAAK,MAAA,CAAO,MAAA,CAAO,YAAY,MAAA,CAAO,GAAA,CAAI,CAAA,KAAA,KAAS,CAAC,KAAA,CAAM,EAAA,EAAI,aAAa,CAAC,CAAC,CAAC;AAAA,GAC3F,CAAA;AACL;AAQA,SAAS,eAAA,CAAgB,MAAA,EAAyB,IAAA,EAAc,OAAA,EAChE;AACI,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,CAAE,KAAA,CAAM,EAAE,KAAA,EAAO,aAAA,CAAc,MAAM,CAAA,EAAG,CAAA;AACtE,EAAA,MAAM,IAAA,GAAO,QAAQ,GAAA,EAAK,MAAA,GAAS,QAAQ,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,GAAI,OAAA;AAC9D,EAAA,MAAM,UAAU,OAAA,CAAQ,IAAA,GAAO,KAAK,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,GAAI,IAAA;AAEzD,EAAA,OAAO,OAAA,CAAQ,QAAA,GACT,OAAA,CAAQ,QAAA,CAAS,eAAe,EAAE,GAAG,OAAA,CAAQ,QAAA,EAAU,UAAU,sBAAA,CAAuB,MAAM,CAAA,EAAG,CAAkB,CAAA,GACnH,OAAA;AACV;AAMO,SAAS,cACZ,MAAA,EACA,QAAA,EACA,MACA,cAAA,EACA,OAAA,GAAgC,EAAC,EAErC;AACI,EAAA,OAAO,gBAAgB,MAAA,EAAQ,IAAA,EAAM,OAAO,CAAA,CAAE,OAAA,CAAQ,OAAO,CAAA,KAC7D;AACI,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,CAAA,CAAE,GAAA,EAAK,cAAc,CAAA;AACpD,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,GAAA,CAAI,GAAA,CAAI,MAAM,CAAA;AAClC,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,EAAE,IAAA,EAAK;AAC/B,IAAA,MAAM,EAAA,GAAA,iBAAK,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAClC,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA,CAAI,OAAO,GAAA,CAAI,CAAA,KAAA,KAAS,aAAA,CAAc,KAAA,CAAM,aAAa,OAAA,EAAS,SAAA,EAAW,KAAA,EAAO,EAAE,CAAC,CAAC,CAAA;AAEtH,IAAA,OAAO;AAAA,MACH,EAAA;AAAA,MACA,MAAA,EAAQ,MAAA,CAAO,WAAA,CAAY,MAAA,CACtB,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,KAAU,CAAC,KAAA,CAAM,EAAA,EAAI,OAAA,CAAQ,KAAK,CAAC,CAAC,CAAA,CAChD,MAAA,CAAO,CAAC,GAAG,KAAK,CAAA,KAAM,KAAA,KAAU,MAAS,CAAC,CAAA;AAAA,MAC/C;AAAA,KACJ;AAAA,EACJ,CAAC,CAAA;AACL;;;ACvLO,SAAS,iBAAA,CACZ,MAAA,EACA,OAAA,GAA8B,EAAC,EAEnC;AACI,EAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,QAAA;AAC7B,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA;AAEjC,EAAA,UAAA,CAAW,IAAI,CAAA;AACf,EAAA,IAAA,CAAK,QAAQ,cAAc,CAAA;AAC3B,EAAA,0CAAA,CAA2C,MAAM,OAAO,CAAA;AACxD,EAAA,iBAAA,CAAkB,IAAI,CAAA;AACtB,EAAA,IAAA,CAAK,OAAA,CAAQ,CAAA,KAAA,KAAS,eAAA,CAAgB,KAAA,EAAO,IAAI,CAAC,CAAA;AAElD,EAAA,IAAA,CAAK,QAAQ,CAAA,KAAA,KAAS,SAAA,CAAU,KAAA,CAAM,WAAA,EAAa,IAAI,CAAC,CAAA;AACxD,EAAA,IAAA,CAAK,QAAQ,sBAAsB,CAAA;AAEnC,EAAA,OAAO;AAAA,IACH,QAAQ,YAAA,CAAa,YAAA,CAAa,IAAA,EAAM,IAAA,EAAM,OAAO,CAAC,CAAA;AAAA,IACtD,MAAA,EAAQ,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,IAAI,CAAA,KAAA,KAAS,CAAC,cAAA,CAAe,KAAA,CAAM,EAAE,CAAA,EAAG,KAAA,CAAM,MAAM,CAAC,CAAC,CAAA;AAAA,IACtF;AAAA,GACJ;AACJ;AAEA,SAAS,YAAA,CAAa,MAAA,EAAyB,IAAA,EAAc,OAAA,EAC7D;AACI,EAAA,MAAM,cAAA,GAAiB,QAAQ,OAAA,IAAW,cAAA;AAC1C,EAAA,MAAM,SAAkD,EAAC;AAEzD,EAAA,KAAA,MAAW,SAAS,MAAA,EACpB;AACI,IAAA,MAAA,CAAO,cAAA,CAAe,OAAO,KAAA,CAAM,EAAE,CAAC,CAAA,GAAI,SAAA,CAAU,KAAA,EAAO,IAAA,EAAM,cAAc,CAAA;AAE/E,IAAA,IAAI,KAAA,CAAM,YAAY,KAAA,EACtB;AACI,MAAA,MAAA,CAAO,cAAA,CAAe,OAAO,KAAA,CAAM,EAAE,CAAC,CAAA,GAAI,UAAA,CAAW,KAAA,EAAO,IAAA,EAAM,cAAc,CAAA;AAAA,IACpF;AAAA,EACJ;AAEA,EAAA,MAAA,CAAO,SAAA,GAAY,cAAc,MAAA,EAAQ,aAAA,CAAc,MAAM,CAAA,EAAG,IAAA,EAAM,gBAAgB,OAAO,CAAA;AAE7F,EAAA,OAAO,MAAA;AACX;AAEA,SAAS,WAAW,IAAA,EACpB;AACI,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,IAAM,IAAA,CAAK,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAClE;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,mCAAmC,IAAI,CAAA,8HAAA;AAAA,KAE3C;AAAA,EACJ;AACJ;AAGA,SAAS,eAAe,KAAA,EACxB;AACI,EAAA,MAAM,MAAM,KAAA,CAAM,WAAA;AAClB,EAAA,MAAM,OAAA,GAAU,CAAC,GAAA,CAAI,KAAA,GAAQ,aAAa,CAAC,GAAA,CAAI,OAAO,SAAA,GAAY,MAAA;AAElE,EAAA,IAAI,OAAA,EACJ;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,0BAAA,EAA6B,MAAM,EAAE,CAAA,cAAA,EAAiB,OAAO,CAAA,6EAAA,EAEpD,OAAO,CAAA,iBAAA,EAAoB,KAAA,CAAM,EAAE,CAAA,GAAA;AAAA,KAChD;AAAA,EACJ;AAEA,EAAA,IAAI,GAAA,CAAI,GAAA,IAAO,CAAC,GAAA,CAAI,OAAA,EACpB;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,gCAAA,EAAmC,MAAM,EAAE,CAAA,gJAAA;AAAA,KAG/C;AAAA,EACJ;AAEA,EAAA,kCAAA,CAAmC,KAAK,CAAA;AACxC,EAAA,GAAA,CAAI,WAAW,OAAA,CAAQ,CAAA,KAAA,KAAS,eAAA,CAAgB,KAAA,EAAO,KAAK,CAAC,CAAA;AAE7D,EAAA,IAAI,GAAA,CAAI,SAAS,CAAC,GAAA,CAAI,YAAY,GAAA,CAAI,KAAA,CAAM,QAAQ,KAAA,EACpD;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,6BAA6B,KAAA,CAAM,EAAE,iCAAiC,GAAA,CAAI,KAAA,CAAM,QAAQ,KAAK,CAAA,6QAAA;AAAA,KAIjG;AAAA,EACJ;AACJ;AAOA,SAAS,mCAAmC,KAAA,EAC5C;AACI,EAAA,MAAM,MAAM,KAAA,CAAM,WAAA;AAElB,EAAA,IAAA,CAAK,GAAA,CAAI,YAAY,MAAA,GAAS,CAAA,IAAK,IAAI,eAAA,KAAoB,CAAC,IAAI,OAAA,EAChE;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,0BAAA,EAA6B,KAAA,CAAM,EAAE,CAAA,wEAAA,EACR,eAAe,KAAA,EAAO,KAAA,CAAM,EAAE,CAAC,CAAA,GAAA,EAAM,cAAA,CAAe,KAAA,EAAO,KAAA,CAAM,EAAE,CAAC,CAAA,4RAAA;AAAA,KAIrG;AAAA,EACJ;AACJ;AAOA,SAAS,0CAAA,CAA2C,QAAyB,OAAA,EAC7E;AACI,EAAA,MAAM,YAAY,MAAA,CAAO,IAAA,CAAK,WAAS,CAAC,KAAA,CAAM,YAAY,OAAO,CAAA;AAEjE,EAAA,IAAA,CAAA,CAAM,QAAQ,GAAA,EAAK,MAAA,IAAU,KAAK,CAAA,IAAK,OAAA,CAAQ,SAAS,SAAA,EACxD;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,+EAAA,EAAkF,UAAU,EAAE,CAAA,sPAAA;AAAA,KAIlG;AAAA,EACJ;AACJ;AAGA,SAAS,eAAA,CAAgB,OAAsB,KAAA,EAC/C;AACI,EAAA,MAAM,UAAU,KAAA,CAAM,MAAA;AACtB,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,KAAA,CAAM,WAAW,CAAA;AACrD,EAAA,MAAM,OAAA,GAAU,OAAO,IAAA,CAAK,MAAA,CAAO,UAAU,CAAA,CAAE,IAAA,CAAK,WAChD,CAAC,OAAA,EAAS,aAAa,KAAK,CAAA,IAAK,EAAE,OAAA,CAAQ,QAAA,IAAY,EAAC,EAAG,QAAA,CAAS,KAAK,CAAC,CAAA;AAE9E,EAAA,IAAI,OAAA,EACJ;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,0BAAA,EAA6B,MAAM,EAAE,CAAA,eAAA,EAAkB,MAAM,IAAI,CAAA,iEAAA,EACrC,OAAO,CAAA,4BAAA,EAA+B,KAAA,CAAM,EAAE,gCACrE,MAAA,CAAO,IAAA,CAAK,OAAO,UAAU,CAAA,CAAE,KAAK,IAAI,CAAC,CAAA,sCAAA,EAAyC,KAAA,CAAM,EAAE,CAAA,iBAAA;AAAA,KACnG;AAAA,EACJ;AACJ;AAEA,SAAS,kBAAkB,MAAA,EAC3B;AACI,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAE7B,EAAA,KAAA,MAAW,SAAS,MAAA,EACpB;AACI,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EACrB;AACI,MAAA,MAAM,IAAI,KAAA;AAAA,QACN,CAAA,2CAAA,EAA8C,KAAA,CAAM,EAAE,CAAA,gCAAA,EACpB,cAAA,CAAe,KAAA,EAAO,KAAA,CAAM,EAAE,CAAC,CAAA,eAAA,EAC5D,cAAA,CAAe,KAAA,CAAM,EAAE,CAAC,CAAA,6CAAA;AAAA,OACjC;AAAA,IACJ;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,MAAM,EAAE,CAAA;AAAA,EACrB;AACJ;AAEA,SAAS,eAAA,CAAgB,OAAsB,IAAA,EAC/C;AACI,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,WAAW,CAAA,EAAG,IAAA;AAE/C,EAAA,IAAI,UAAU,MAAA,EACd;AACI,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,6BAA6B,KAAA,CAAM,EAAE,CAAA,2CAAA,EAA8C,KAAK,cAAc,IAAI,CAAA,kIAAA;AAAA,KAG9G;AAAA,EACJ;AACJ","file":"index.js","sourcesContent":["/**\n * State Binding\n *\n * What a state router fixes for each state it groups, keyed by the builder's\n * definition — one per builder instance, so an intermediate builder is never\n * bound: the router's path (a state belongs to one router) and the schema\n * every `read()` result is checked against, built once here rather than per\n * request.\n */\n\nimport { Type, type TObject } from '@sinclair/typebox';\nimport type { StateDefinition } from './types';\n\nexport interface StateBinding\n{\n path: string;\n resultSchema: TObject;\n}\n\nconst bindings = new WeakMap<Readonly<StateDefinition>, StateBinding>();\n\n/** `{ value, data }` exactly as declared: `data` when `.data()` is, and nothing else. */\nfunction resultSchema(def: StateDefinition): TObject\n{\n return Type.Object(\n {\n value: def.value!,\n ...(def.data ? { data: def.data } : {}),\n },\n { additionalProperties: false },\n );\n}\n\n/** Bind a state to the router at `path`. */\nexport function bindState(def: Readonly<StateDefinition>, path: string): void\n{\n bindings.set(def, { path, resultSchema: resultSchema(def) });\n}\n\n/** The binding of a state, `undefined` until a router groups that builder. */\nexport function stateBinding(def: Readonly<StateDefinition>): StateBinding | undefined\n{\n return bindings.get(def);\n}\n","/**\n * State Event\n *\n * The two events a state derives: the change signal the app emits\n * (`state.changed`, in-process) and the SSE event the browser receives\n * (`state.<id>.changed`). Between them sits the one rule of the module — a\n * value is only ever what `read()` returned, re-read here, never computed from\n * the signal.\n */\n\nimport { Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { getTransactionContext, onAfterCommit } from '@spfn/core/db';\nimport { defineEvent } from '@spfn/core/event';\nimport type { EventDef, FramePredicate, SubscribePredicate } from '@spfn/core/event';\nimport { logger } from '@spfn/core/logger';\nimport { stateBinding, type StateBinding } from './state-binding';\nimport type { RoutableState, StateCallContext, StateDefinition } from './types';\n\nconst stateLogger = logger.child('@spfn/core:state');\n\n/** `{ at, value, data? }` as a response and a frame carry it. */\nexport interface Snapshot\n{\n at: string;\n value: unknown;\n data?: unknown;\n}\n\ntype Key = Record<string, string>;\n\ntype FramePayload = Snapshot & { key?: Key; subject?: string };\n\n/** The wire name of a state's SSE event. */\nexport function stateEventName(id: string): string\n{\n return `state.${id}.changed`;\n}\n\n/**\n * The key fields of `keySchema` taken from `source`, or `undefined` when any\n * is absent. Key fields are strings by construction (`.key()` refuses others),\n * so a query value and a payload field compare as they are.\n */\nexport function pickKey(keySchema: TObject, source: Record<string, unknown>): Key | undefined\n{\n const key: Key = {};\n\n for (const field of Object.keys(keySchema.properties))\n {\n const value = source[field];\n if (typeof value !== 'string')\n {\n return undefined;\n }\n key[field] = value;\n }\n\n return key;\n}\n\n/** What `read()` receives: a shared state's value does not depend on the subject, so it gets none. */\nexport function readContext(def: StateDefinition, subject: string | undefined, principal: unknown, key?: Key): StateCallContext\n{\n if (!def.key)\n {\n return { subject, principal };\n }\n\n return def.shared ? { principal, key } : { subject, principal, key };\n}\n\n/** What `.canRead()` / `.canWrite()` receive. */\nexport function permissionContext(def: StateDefinition, subject: string, principal: unknown, key?: Key): StateCallContext\n{\n return def.key ? { subject, principal, key } : { subject, principal };\n}\n\n/**\n * The router binding of a state, or a refusal: an unrouted builder has no\n * subscriber for its signal and no schema to check a read against.\n */\nexport function requireBinding(def: StateDefinition, what: string): StateBinding\n{\n const binding = stateBinding(def);\n\n if (!binding)\n {\n throw new Error(\n `State \"${def.id}\" is in no defineStateRouter, so ${what} reaches nothing. `\n + 'The router subscribes the change signal and checks every read, and every builder call returns a new '\n + 'builder — an earlier one is never routed. Group the state with defineStateRouter and export the builder '\n + 'instance you grouped.',\n );\n }\n\n return binding;\n}\n\n/** Refuse a `read()` result that is not what the state declares, naming the state, never the value. */\nfunction assertResult(def: StateDefinition, binding: StateBinding, result: unknown): asserts result is Omit<Snapshot, 'at'>\n{\n const error = Value.Errors(binding.resultSchema, result).First();\n\n if (error)\n {\n throw new Error(\n `State \"${def.id}\" read() returned a result its declaration does not allow: ${error.path || '(root)'} ${error.message}. `\n + 'Every response and frame is checked against .value() and .data(), so a client never receives a value the '\n + 'contract does not describe. Return { value'\n + `${def.data ? ', data' : ''} } as declared.`,\n );\n }\n}\n\n/**\n * Read the current value and check it against the declaration. `at` is taken\n * before `read()` starts, so a frame is never stamped later than the data it\n * carries.\n */\nexport async function readSnapshot(def: StateDefinition, ctx: StateCallContext, at = new Date().toISOString()): Promise<Snapshot>\n{\n const binding = requireBinding(def, 'a read');\n const result = await def.read!(ctx);\n assertResult(def, binding, result);\n\n return { at, ...result };\n}\n\n/**\n * The frame for a snapshot. A copy: the response keeps the snapshot itself, so\n * neither a handler mutating what it returned nor a subscriber mutating the\n * payload changes the other.\n */\nfunction toFrame(def: StateDefinition, snapshot: Snapshot, subject: string | undefined, key: Key | undefined): FramePayload\n{\n const frame: FramePayload = structuredClone(snapshot);\n\n if (def.key)\n {\n frame.key = { ...key };\n }\n\n if (!(def.key && def.shared))\n {\n frame.subject = subject;\n }\n\n return frame;\n}\n\n/**\n * Read the value for one subject and key, send it as one frame, and return the\n * snapshot. Inside a transaction the frame is published after the root\n * transaction commits, and never when the root rolls back; it still carries the\n * value read inside it. A nested transaction (a savepoint) that rolls back\n * while the root commits still publishes the frame read inside it, because\n * after-commit callbacks belong to the root: emit the signal from the outer\n * transaction, or after it, when an inner one may roll back. Outside a\n * transaction the frame is sent here and awaited, so an emit that throws fails\n * the caller — `onAfterCommit` would only log it.\n */\nexport async function readAndPublish(\n def: StateDefinition,\n event: EventDef<any>,\n subject: string | undefined,\n key: Key | undefined,\n principal: unknown,\n): Promise<Snapshot>\n{\n const snapshot = await readSnapshot(def, readContext(def, subject, principal, key));\n const frame = toFrame(def, snapshot, subject, key);\n\n if (getTransactionContext())\n {\n onAfterCommit(() => event.emit(frame));\n }\n else\n {\n await event.emit(frame);\n }\n\n return snapshot;\n}\n\n// ============================================================================\n// The derived SSE event\n// ============================================================================\n\nfunction framePayloadSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n at: Type.String(),\n value: def.value ?? Type.Unknown(),\n ...(def.data ? { data: def.data } : {}),\n ...(def.key ? { key: def.key } : {}),\n ...(def.key && def.shared ? {} : { subject: Type.String() }),\n });\n}\n\n/**\n * `canRead` translated to the connect: the connection declares its key in the\n * connect query. A key field absent from it denies, without asking `canRead` —\n * there is no key to ask about.\n */\nfunction subscribePredicate(def: StateDefinition): SubscribePredicate\n{\n return async ({ subject, principal, request }) =>\n {\n if (!def.key)\n {\n return def.canRead ? def.canRead({ subject, principal }) : true;\n }\n\n const key = pickKey(def.key, request.query);\n\n return key !== undefined && def.canRead !== undefined && def.canRead({ subject, principal, key });\n };\n}\n\n/**\n * A frame reaches a connection on the key it declared, and only its own\n * subject's value unless shared. Never a connection without a subject: on a\n * stream without auth `canSubscribe` is never asked, so `canRead` would be\n * skipped.\n */\nfunction framePredicate(def: StateDefinition): FramePredicate<FramePayload>\n{\n const fields = def.key ? Object.keys(def.key.properties) : [];\n\n return (payload, { subject, request }) =>\n subject !== undefined\n && fields.every(field => payload.key?.[field] === request.query[field])\n && (payload.subject === undefined || payload.subject === subject);\n}\n\n/** The SSE event `state.<id>.changed`, its permissions and contract set once, here. */\nexport function createStateEvent(def: StateDefinition): EventDef<any>\n{\n const event = defineEvent(stateEventName(def.id), framePayloadSchema(def))\n .canSubscribe(subscribePredicate(def))\n .filter(framePredicate(def) as FramePredicate<unknown>);\n\n if (def.contract)\n {\n const { since, deprecatedIn, removedIn } = def.contract;\n event.contract({\n since,\n ...(deprecatedIn ? { deprecatedIn } : {}),\n ...(removedIn ? { removedIn } : {}),\n });\n }\n\n return event;\n}\n\n// ============================================================================\n// The change signal\n// ============================================================================\n\n/**\n * What a change signal must name: keyless `subject`; keyed the key fields, and\n * `subject` unless shared. Always a fresh object, never `def.key` itself: a key\n * declared `additionalProperties: false` would otherwise refuse every\n * `.changedBy()` payload carrying one more field. Extra fields are ignored.\n */\nexport function changedPayloadSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n ...def.key?.properties,\n ...(def.key && def.shared ? {} : { subject: Type.String() }),\n });\n}\n\nfunction assertChangedPayload(def: StateDefinition, schema: TSchema, payload: unknown): void\n{\n const error = Value.Errors(schema, payload).First();\n\n if (error)\n {\n throw new Error(\n `${def.id}.changed.emit() refused its payload: ${error.path || '(root)'} ${error.message}. `\n + 'The module re-reads exactly the subject and key the payload names, so a missing field cannot be guessed. '\n + `Pass ${def.key ? 'every key field' : 'the subject'}${def.key && !def.shared ? ' and the subject' : ''}.`,\n );\n }\n}\n\n/**\n * The change signal `state.changed`: a plain in-process event whose `emit`\n * refuses a builder no router grouped, and validates its payload, since the\n * module reads the state the payload names.\n */\nexport function createChangedSignal(def: StateDefinition): EventDef<any>\n{\n const schema = changedPayloadSchema(def);\n const event = defineEvent(`state.${def.id}.signal`, schema);\n const emit = event.emit;\n\n event.emit = (async (payload: unknown) =>\n {\n requireBinding(def, `${def.id}.changed.emit()`);\n assertChangedPayload(def, schema, payload);\n await emit(payload as Record<string, unknown>);\n }) as EventDef<any>['emit'];\n\n return event;\n}\n\n/** Subject and key a signal payload names; a shared state's names no subject. */\nfunction signalTarget(def: StateDefinition, payload: Record<string, unknown>): { subject?: string; key?: Key }\n{\n const subject = def.key && def.shared ? undefined : payload.subject as string;\n\n return { subject, key: def.key ? pickKey(def.key, payload) : undefined };\n}\n\n/**\n * Re-read and publish for one signal. A `read()` that throws or returns an\n * undeclared result sends nothing and is logged — the signal came after a\n * commit the app already made, so there is nobody to throw to.\n */\nasync function onSignal(state: RoutableState, payload: Record<string, unknown>): Promise<void>\n{\n const { subject, key } = signalTarget(state._definition, payload);\n\n try\n {\n await readAndPublish(state._definition, state._event, subject, key, undefined);\n }\n catch (error)\n {\n stateLogger.warn(`State \"${state.id}\" could not be re-read or published on its change signal; no frame was sent`, {\n state: state.id,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\n/**\n * A `.changedBy()` event's payload, checked as the state's own `emit` checks\n * its signal. The app emitted it, so a payload missing a field is logged and\n * skipped rather than thrown.\n */\nasync function onChangedBy(state: RoutableState, event: EventDef<any>, schema: TObject, payload: unknown): Promise<void>\n{\n const error = Value.Errors(schema, payload).First();\n\n if (error)\n {\n stateLogger.warn(`State \"${state.id}\" skipped an \"${event.name}\" payload that names no value to re-read`, {\n state: state.id,\n event: event.name,\n error: `${error.path || '(root)'} ${error.message}`,\n });\n\n return;\n }\n\n await onSignal(state, payload as Record<string, unknown>);\n}\n\n/**\n * Re-read and publish on every signal of `state` and every event it lists in\n * `.changedBy()`, on the pod that emitted it only. A `.changedBy()` event in an\n * event router is cached, so a plain subscriber would re-read on every pod and\n * each would send its own frame; the derived state event is cached too, so the\n * emitting pod's one frame already reaches every pod. The `changed` signal\n * needs no such option: it is in no event router and never cached.\n */\nexport function subscribeChangeSignals(state: RoutableState): void\n{\n const schema = changedPayloadSchema(state._definition);\n\n state.changed.subscribe(payload => onSignal(state, payload));\n state._definition.changedBy?.forEach(event =>\n event.subscribe(payload => onChangedBy(state, event, schema, payload), { localOnly: true }));\n}\n","/**\n * State Builder\n *\n * `defineState(id)` starts an immutable builder: every call returns a new one,\n * order is free and there is no terminal method. `defineStateRouter` reads\n * what a builder declared and derives its routes and SSE event from it.\n */\n\nimport { Kind, Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport type { MiddlewareHandler } from 'hono';\nimport type { EventDef } from '@spfn/core/event';\nimport type { NamedMiddleware } from '@spfn/core/route';\nimport { createChangedSignal, createStateEvent, pickKey, readAndPublish, requireBinding } from './state-event';\nimport type {\n ChangedPayload,\n EmptyStateShape,\n GrantTarget,\n PermissionContext,\n ReadContext,\n RevokeTarget,\n StateContract,\n StateDefinition,\n StateFrame,\n StatePredicate,\n StateReader,\n StateResult,\n StateShape,\n StateWriteOptions,\n StateWriter,\n WithShape,\n WriteContext,\n WritePermissionContext,\n} from './types';\n\n/** A state id becomes part of a route name (`get<Id>State`) and of an event name (`state.<id>.changed`). */\nconst STATE_ID = /^[a-z][a-zA-Z0-9]*$/;\n\n/**\n * Query names the SSE stream reads itself. Key fields share the connect query\n * with them, so a key field under one of these names would be read as both.\n */\nconst RESERVED_KEY_FIELDS = ['events', 'token'];\n\n/**\n * A server-owned value declared once. See the module README.\n */\nexport class StateBuilder<TId extends string, T extends StateShape>\n{\n /** Type inference helper: what this builder declared. Never set at runtime. */\n declare readonly _types: T;\n\n private changedSignal?: EventDef<any>;\n private stateEvent?: EventDef<any>;\n\n constructor(\n readonly id: TId,\n readonly _definition: Readonly<StateDefinition>,\n )\n {\n }\n\n /**\n * Declare the key: one value per key (and per subject, unless `shared`).\n * Fields are required strings: they travel as query parameters.\n */\n key<K extends TObject, S extends boolean = false>(\n schema: K,\n options: { shared?: S } = {},\n ): StateBuilder<TId, WithShape<T, { key: K; shared: S }>>\n {\n this.assertOnce('key', !!this._definition.key);\n assertKeySchema(this.id, schema);\n\n return this.with({ key: schema, shared: options.shared === true });\n }\n\n /** Declare the value schema. Required. */\n value<V extends TSchema>(schema: V): StateBuilder<TId, WithShape<T, { value: V }>>\n {\n this.assertOnce('value', !!this._definition.value);\n\n return this.with({ value: schema });\n }\n\n /** Declare data attached to the value. Optional. */\n data<D extends TSchema>(schema: D): StateBuilder<TId, WithShape<T, { data: D }>>\n {\n this.assertOnce('data', !!this._definition.data);\n\n return this.with({ data: schema });\n }\n\n /**\n * Declare who the callbacks' `principal` is — what the app's auth\n * middleware sets as `c.get('auth')`. Type-only, but for one rule: the write\n * route refuses a request without a principal (401), so `.canWrite()` and\n * `.write()` receive `P`; `.read()` and `.canRead()` receive `P | undefined`.\n */\n principal<P>(): StateBuilder<TId, WithShape<T, { principal: P }>>\n {\n this.assertOnce('principal', this._definition.principal);\n\n return this.with({ principal: true });\n }\n\n /**\n * Middleware for the two per-state routes, `get<Id>State` / `put<Id>State`.\n * Not authorization: the snapshot and the SSE stream cannot run it, so a\n * state with `.use()` must declare `.canRead()`. Calls add up.\n */\n use(middlewares: (MiddlewareHandler | NamedMiddleware<string>)[]): StateBuilder<TId, T>\n {\n return this.with({ middlewares: [...this._definition.middlewares, ...middlewares] });\n }\n\n /** Server-level named middlewares the two per-state routes skip. Calls add up; `'*'` wins. Needs `.canRead()`, as `.use()`. */\n skip(middlewareNames: string[] | '*'): StateBuilder<TId, T>\n {\n const current = this._definition.skipMiddlewares ?? [];\n const skipMiddlewares = current === '*' || middlewareNames === '*'\n ? '*'\n : [...current, ...middlewareNames];\n\n return this.with({ skipMiddlewares });\n }\n\n /** Publish the read route, the write route and the event in the contract. */\n contract(contract: StateContract): StateBuilder<TId, T>\n {\n this.assertOnce('contract', !!this._definition.contract);\n\n return this.with({ contract });\n }\n\n /** Who may read. Required on a keyed state; checked on HTTP and at SSE connect. */\n canRead(predicate: (ctx: PermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>\n {\n this.assertOnce('canRead', !!this._definition.canRead);\n\n return this.with({ canRead: predicate as StatePredicate });\n }\n\n /** Who may write. Absent → `canRead` decides. */\n canWrite(predicate: (ctx: WritePermissionContext<T>) => boolean | Promise<boolean>): StateBuilder<TId, T>\n {\n this.assertOnce('canWrite', !!this._definition.canWrite);\n\n return this.with({ canWrite: predicate as StatePredicate });\n }\n\n /** The only source of a value. Required. */\n read(\n fn: (ctx: ReadContext<T>) => StateResult<T> | Promise<StateResult<T>>,\n ): StateBuilder<TId, WithShape<T, { read: true }>>\n {\n this.assertOnce('read', !!this._definition.read);\n\n return this.with({ read: fn as StateReader });\n }\n\n /**\n * Derive `PUT <path>/<id>`. `fn` runs the command; the value the route\n * answers and broadcasts is re-read afterwards, never taken from `input`.\n */\n write<I extends TSchema>(\n input: I,\n fn: (ctx: WriteContext<T, I>) => void | Promise<void>,\n options: StateWriteOptions = {},\n ): StateBuilder<TId, WithShape<T, { input: I }>>\n {\n this.assertOnce('write', !!this._definition.write);\n\n return this.with({ write: { input, fn: fn as StateWriter, options } });\n }\n\n /**\n * Domain events whose payload names a changed value of this state, treated\n * like `changed.emit` with that payload: keyless `subject`, keyed the key\n * fields and `subject`, shared the key fields. The router subscribes them\n * and refuses one whose payload schema lacks a field.\n */\n changedBy(events: EventDef<any>[]): StateBuilder<TId, T>\n {\n this.assertOnce('changedBy', !!this._definition.changedBy);\n\n return this.with({ changedBy: [...events] });\n }\n\n /**\n * The change signal. Emit it after the change is committed; the module\n * re-reads the value and sends the frame. Refused on a builder no router\n * grouped — export the instance you passed to `defineStateRouter`.\n */\n get changed(): EventDef<ChangedPayload<T>>\n {\n this.changedSignal ??= createChangedSignal(this._definition);\n\n return this.changedSignal;\n }\n\n /** Internal: the SSE event `state.<id>.changed` (`defineStateRouter(...).events`). */\n get _event(): EventDef<StateFrame<T>>\n {\n this.stateEvent ??= createStateEvent(this._definition);\n\n return this.stateEvent;\n }\n\n /**\n * Activate the state's event on `subject`'s open connections and send it\n * the current value at once. On a keyed state only the connections that\n * declared `key` are opened. Does not consult `canRead`.\n */\n async grant(target: GrantTarget<T>): Promise<void>\n {\n const { subject, key } = target as { subject: string; key?: Record<string, string> };\n requireBinding(this._definition, `${this.id}.grant()`);\n this.assertGrantKey(key);\n const declared = this.declaredKey('grant', key);\n await this._event.grant(subject, declared && { query: declared });\n await readAndPublish(this._definition, this._event, subject, declared, undefined);\n }\n\n /**\n * Deactivate the state's event on `subject`'s open connections: on a keyed\n * state those that declared `key`, or every one when no key is given.\n */\n async revoke(target: RevokeTarget<T>): Promise<void>\n {\n const { subject, key } = target as { subject: string; key?: Record<string, string> };\n const declared = this.declaredKey('revoke', key);\n await this._event.revoke(subject, declared && { query: declared });\n }\n\n /** A keyed grant opens one key: without it there is no key to open and no value to send. */\n private assertGrantKey(key: Record<string, string> | undefined): void\n {\n if (this._definition.key && !key)\n {\n throw new Error(\n `State \"${this.id}\" .grant() was called without a key. `\n + 'A keyed grant opens exactly one key — every connection of the subject on any key would otherwise be '\n + 'opened, including keys canRead refused. Pass { subject, key }.',\n );\n }\n }\n\n /**\n * The declared key fields of `key`, checked against `.key()`: an empty or\n * partial key would match every connection of the subject. A field the\n * declaration does not name is dropped, never matched on — so the check\n * runs on a fresh object of the declared fields, never `.key()` itself: a\n * key declared `additionalProperties: false` would otherwise refuse it.\n * The fresh object keeps `.key()`'s `required`, and a key that still picks\n * to nothing is refused: `undefined` here would mean every connection.\n */\n private declaredKey(method: 'grant' | 'revoke', key: Record<string, string> | undefined): Record<string, string> | undefined\n {\n const schema = this._definition.key;\n if (!schema || key === undefined)\n {\n return undefined;\n }\n\n const error = Value.Errors({ ...Type.Object(schema.properties), required: schema.required }, key).First();\n if (error)\n {\n this.refuseKey(method, `${error.path || '(root)'} ${error.message}`);\n }\n\n return pickKey(schema, key) ?? this.refuseKey(method, '(root) a declared key field is missing or not a string');\n }\n\n private refuseKey(method: 'grant' | 'revoke', reason: string): never\n {\n throw new Error(\n `State \"${this.id}\" .${method}() refused its key: ${reason}. `\n + `A keyed ${method} reaches exactly the connections on one key, so every key field must be named.`,\n );\n }\n\n private with(changes: Partial<StateDefinition>): StateBuilder<TId, any>\n {\n return new StateBuilder(this.id, { ...this._definition, ...changes });\n }\n\n private assertOnce(method: string, declared: boolean): void\n {\n if (declared)\n {\n throw new Error(\n `State \"${this.id}\" already declares .${method}(). `\n + 'A state is declared once, so a second declaration would silently replace the first. '\n + `Declare .${method}() once.`,\n );\n }\n }\n}\n\n/**\n * Refuse a key the module could not carry: it must be an object of required\n * string fields, none named like a query parameter the SSE stream reads.\n */\nfunction assertKeySchema(id: string, schema: TSchema): void\n{\n if (schema[Kind] !== 'Object')\n {\n throw new Error(\n `State \"${id}\" .key() takes an object schema, got ${String(schema[Kind])}. `\n + 'Each key field becomes a named query parameter and a field of the frame\\'s key. '\n + 'Wrap the field: .key(Type.Object({ workspaceId: Type.String() })).',\n );\n }\n\n const fields = Object.entries((schema as TObject).properties);\n\n if (fields.length === 0)\n {\n throw new Error(\n `State \"${id}\" .key() declares no field. A key with no field names nothing to read by. `\n + 'Drop .key() for one value per subject.',\n );\n }\n\n fields.forEach(([field, fieldSchema]) => assertKeyField(id, schema as TObject, field, fieldSchema));\n}\n\nfunction assertKeyField(id: string, schema: TObject, field: string, fieldSchema: TSchema): void\n{\n if (RESERVED_KEY_FIELDS.includes(field))\n {\n throw new Error(\n `State \"${id}\" key field \"${field}\" is reserved. `\n + `The SSE stream reads ${RESERVED_KEY_FIELDS.map(name => `\"${name}\"`).join(' and ')} from the connect query `\n + 'that also carries the key, so the field would be read as both. Rename the field.',\n );\n }\n\n if (fieldSchema.type !== 'string' || !(schema.required ?? []).includes(field))\n {\n throw new Error(\n `State \"${id}\" key field \"${field}\" is not a required string. `\n + 'A key travels as a query parameter, which is always a string, and the SSE filter compares it with the '\n + 'connect query as one — a number would never match, and a missing field names no value. '\n + `Declare it ${field}: Type.String().`,\n );\n }\n}\n\n/**\n * Declare a server-owned state.\n *\n * @example\n * ```typescript\n * export const consent = defineState('consent')\n * .value(Type.Union([Type.Literal('pending'), Type.Literal('agreed')]))\n * .read(({ subject }) => consents.current(subject));\n * ```\n */\nexport function defineState<TId extends string>(id: TId): StateBuilder<TId, EmptyStateShape>\n{\n if (!STATE_ID.test(id))\n {\n throw new Error(\n `defineState(\"${id}\"): a state id must match ${STATE_ID}. `\n + 'It becomes part of the route names get<Id>State / put<Id>State and of the event name state.<id>.changed. '\n + 'Use a lowerCamel identifier, e.g. \"myState\".',\n );\n }\n\n return new StateBuilder(id, { id, shared: false, principal: false, middlewares: [] });\n}\n","/**\n * State Routes\n *\n * The read, write and snapshot routes a state router derives. They are\n * ordinary `RouteDef`s registered through `registerRoutes`, so a state's\n * `.use()` middleware runs inside the route's own chain after the app's\n * global middleware.\n */\n\nimport { Type, type TObject, type TSchema } from '@sinclair/typebox';\nimport type { Context, MiddlewareHandler } from 'hono';\nimport { ForbiddenError, UnauthorizedError } from '@spfn/core/errors';\nimport { route } from '@spfn/core/route';\nimport type { NamedMiddleware, RouteContract, RouteDef, RouteInput } from '@spfn/core/route';\nimport {\n permissionContext,\n pickKey,\n readAndPublish,\n readContext,\n readSnapshot,\n} from './state-event';\nimport type { RoutableState, StateCallContext, StateContract, StateDefinition } from './types';\n\n/** Who a request is for. `null` answers 401. */\nexport type SubjectResolver = (c: Context) => string | null;\n\n/** The SSE `getSubject` default: the `userId` the app's auth middleware set. */\nexport const defaultSubject: SubjectResolver = c =>\n (c.get('auth') as Record<string, string> | undefined)?.userId ?? null;\n\ntype Key = Record<string, string>;\n\n/** `get<Id>State` / `put<Id>State`. */\nexport function stateRouteName(method: 'get' | 'put', id: string): string\n{\n return `${method}${id[0].toUpperCase()}${id.slice(1)}State`;\n}\n\nfunction requireSubject(c: Context, resolveSubject: SubjectResolver): string\n{\n const subject = resolveSubject(c);\n\n if (!subject)\n {\n throw new UnauthorizedError({ message: 'A state is read for a subject, and this request carries none' });\n }\n\n return subject;\n}\n\n/**\n * The write route's principal, `c.get('auth')`. A state that declared\n * `.principal()` types `canWrite` / `write` without `undefined`, so a request\n * whose `auth` is `undefined` or `null` is refused here, before either runs.\n */\nfunction writePrincipal(def: StateDefinition, c: Context): unknown\n{\n const principal = c.get('auth');\n\n if (def.principal && principal == null)\n {\n throw new UnauthorizedError({\n message: `State \"${def.id}\" declares .principal(), and this request carries none`,\n });\n }\n\n return principal;\n}\n\nasync function assertPermitted(def: StateDefinition, can: 'canRead' | 'canWrite', ctx: StateCallContext): Promise<void>\n{\n const predicate = can === 'canWrite' ? def.canWrite ?? def.canRead : def.canRead;\n\n if (predicate && !await predicate(ctx))\n {\n throw new ForbiddenError({ message: `${can === 'canWrite' ? 'Writing' : 'Reading'} state \"${def.id}\" is not permitted` });\n }\n}\n\n/** `{ value, data? }` as declared: one state's response without `at`, and its entry in the snapshot. */\nfunction resultSchema(def: StateDefinition): TObject\n{\n return Type.Object({\n value: def.value!,\n ...(def.data ? { data: def.data } : {}),\n });\n}\n\nfunction responseSchema(def: StateDefinition): TObject\n{\n return Type.Object({ at: Type.String(), ...resultSchema(def).properties });\n}\n\n/**\n * The route contract, or none when the state declares no `.contract()`. A\n * write's own version markers win over the state's, field by field.\n */\nfunction routeContract(def: StateDefinition, write: boolean): RouteContract | undefined\n{\n if (!def.contract)\n {\n return undefined;\n }\n\n const own = write ? stripUndefined(def.write!.options) : {};\n\n return stripUndefined({ ...def.contract, ...own, response: responseSchema(def) }) as RouteContract;\n}\n\nfunction stripUndefined<T extends object>(value: T): Partial<T>\n{\n return Object.fromEntries(Object.entries(value).filter(([, field]) => field !== undefined)) as Partial<T>;\n}\n\n/** `route.<method>(path)` with the state's input, middleware, skips and contract. */\nfunction stateRoute(def: StateDefinition, method: 'get' | 'put', path: string, input: RouteInput)\n{\n const contract = routeContract(def, method === 'put');\n const builder = route[method](path).input(input).use(def.middlewares);\n const skipped = def.skipMiddlewares ? builder.skip(def.skipMiddlewares) : builder;\n\n return contract ? skipped.contract(contract) : skipped;\n}\n\nfunction keyInput(def: StateDefinition): { query?: TObject }\n{\n return def.key ? { query: def.key } : {};\n}\n\n/** `GET <path>/<id>`: subject → key → `canRead` → `at` → `read()`. */\nexport function readRoute(state: RoutableState, path: string, resolveSubject: SubjectResolver): RouteDef<any, any, any>\n{\n const def = state._definition;\n\n return stateRoute(def, 'get', `${path}/${def.id}`, keyInput(def)).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = c.raw.get('auth');\n const key = def.key ? pickKey(def.key, (await c.data()).query) : undefined;\n await assertPermitted(def, 'canRead', permissionContext(def, subject, principal, key));\n\n return readSnapshot(def, readContext(def, subject, principal, key));\n });\n}\n\n/** `PUT <path>/<id>`: subject → principal (with `.principal()`) → key → `canWrite ?? canRead` → `write()` → `at` → `read()` → one frame. */\nexport function writeRoute(state: RoutableState, path: string, resolveSubject: SubjectResolver): RouteDef<any, any, any>\n{\n const def = state._definition;\n const write = def.write!;\n\n return stateRoute(def, 'put', `${path}/${def.id}`, { body: write.input, ...keyInput(def) }).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = writePrincipal(def, c.raw);\n const { body, query } = await c.data();\n const key = def.key ? pickKey(def.key, query) : undefined;\n await assertPermitted(def, 'canWrite', permissionContext(def, subject, principal, key));\n await write.fn({ ...readContext(def, subject, principal, key), input: body });\n\n return readAndPublish(def, state._event, subject, key, principal);\n });\n}\n\n/**\n * The snapshot's query: every key field of every keyed state, each optional —\n * a state whose key is incomplete is left out, not refused.\n */\nfunction snapshotQuery(states: RoutableState[]): TObject\n{\n const fields: Record<string, TSchema> = {};\n\n for (const state of states)\n {\n for (const [field, schema] of Object.entries(state._definition.key?.properties ?? {}))\n {\n fields[field] = Type.Optional(schema);\n }\n }\n\n return Type.Object(fields);\n}\n\n/** One state's entry in the snapshot, or `undefined` when its key is incomplete or `canRead` refuses. */\nasync function snapshotEntry(def: StateDefinition, subject: string, principal: unknown, query: Record<string, unknown>, at: string)\n{\n const key: Key | undefined = def.key ? pickKey(def.key, query) : undefined;\n\n if (def.key && !key)\n {\n return undefined;\n }\n\n if (def.canRead && !await def.canRead(permissionContext(def, subject, principal, key)))\n {\n return undefined;\n }\n\n const { value, data } = await readSnapshot(def, readContext(def, subject, principal, key), at);\n\n return def.data ? { value, data } : { value };\n}\n\n/**\n * What the router gives the snapshot route `GET <path>` alone. A per-state\n * route keeps its own state's `.use()` / `.skip()` / `.contract()`, and the\n * SSE stream runs none of them.\n */\nexport interface SnapshotRouteOptions\n{\n /** Middleware for the snapshot route only. Not authorization: the stream never runs it (see README). */\n use?: (MiddlewareHandler | NamedMiddleware<string>)[];\n\n /** Server-level named middlewares the snapshot route skips; `'*'` skips every one. */\n skip?: string[] | '*';\n\n /** Publishes the snapshot route in the contract; the response schema is derived. */\n contract?: StateContract;\n}\n\n/** What the browser cannot read from a type: every state, in declaration order, its key fields and whether it has a write. */\nexport type StatesManifest = Record<string, { key: string[]; write: boolean }>;\n\n/** The snapshot's `manifest`. It is static: the router builds it once and every snapshot answers the same object. */\nexport function stateManifest(states: RoutableState[]): StatesManifest\n{\n return Object.fromEntries(states.map(state => [state.id, {\n key: Object.keys(state._definition.key?.properties ?? {}),\n write: state._definition.write !== undefined,\n }]));\n}\n\n/**\n * The snapshot's response: `at`, one optional `{ value, data? }` per state and\n * one required manifest entry per state, in declaration order. Fresh objects,\n * so no per-state schema is touched.\n */\nfunction snapshotResponseSchema(states: RoutableState[]): TObject\n{\n const manifestEntry = Type.Object({ key: Type.Array(Type.String()), write: Type.Boolean() });\n\n return Type.Object({\n at: Type.String(),\n states: Type.Object(Object.fromEntries(states.map(state => [state.id, Type.Optional(resultSchema(state._definition))]))),\n manifest: Type.Object(Object.fromEntries(states.map(state => [state.id, manifestEntry]))),\n });\n}\n\n/**\n * `route.get(path)` with the router's snapshot options. Each is applied only\n * when given — an empty `use` counts as not given — so a router without them\n * derives the route it always did. The\n * contract is built here, once, when the router is built.\n */\nfunction snapshotBuilder(states: RoutableState[], path: string, options: SnapshotRouteOptions)\n{\n const builder = route.get(path).input({ query: snapshotQuery(states) });\n const used = options.use?.length ? builder.use(options.use) : builder;\n const skipped = options.skip ? used.skip(options.skip) : used;\n\n return options.contract\n ? skipped.contract(stripUndefined({ ...options.contract, response: snapshotResponseSchema(states) }) as RouteContract)\n : skipped;\n}\n\n/**\n * `GET <path>`: one `at`, then every readable state in declaration order, and\n * the router's `manifest`. A `read()` that throws fails it all.\n */\nexport function snapshotRoute(\n states: RoutableState[],\n manifest: StatesManifest,\n path: string,\n resolveSubject: SubjectResolver,\n options: SnapshotRouteOptions = {},\n): RouteDef<any, any, any>\n{\n return snapshotBuilder(states, path, options).handler(async (c) =>\n {\n const subject = requireSubject(c.raw, resolveSubject);\n const principal = c.raw.get('auth');\n const { query } = await c.data();\n const at = new Date().toISOString();\n const entries = await Promise.all(states.map(state => snapshotEntry(state._definition, subject, principal, query, at)));\n\n return {\n at,\n states: Object.fromEntries(states\n .map((state, index) => [state.id, entries[index]])\n .filter(([, entry]) => entry !== undefined)),\n manifest,\n };\n });\n}\n","/**\n * State Router\n *\n * Groups states, derives their routes into one `Router` the app mounts with\n * `.packages()`, collects their SSE events for the app's event router, and\n * subscribes each state's change signal — once, here.\n */\n\nimport type { Static, TObject, TSchema } from '@sinclair/typebox';\nimport type { EventDef } from '@spfn/core/event';\nimport { defineRouter } from '@spfn/core/route';\nimport type { RouteDef, Router } from '@spfn/core/route';\nimport { bindState, stateBinding } from './state-binding';\nimport { changedPayloadSchema, stateEventName, subscribeChangeSignals } from './state-event';\nimport { defaultSubject, readRoute, snapshotRoute, stateManifest, stateRouteName, writeRoute } from './state-routes';\nimport type { SnapshotRouteOptions, SubjectResolver } from './state-routes';\nimport type { RoutableState, StateFrame, StateKey, StateResult, StateSnapshot, StateValue } from './types';\n\n/**\n * Where the router mounts, whom a request is for, and the snapshot route's own\n * `use` / `skip` / `contract` (`SnapshotRouteOptions`) — those reach `GET <path>`\n * only, never a per-state route or the SSE stream.\n */\nexport interface StateRouterOptions extends SnapshotRouteOptions\n{\n /**\n * Where the routes are mounted: `GET <path>`, `GET|PUT <path>/<id>`.\n * @default '/state'\n */\n path?: string;\n\n /**\n * Who an HTTP request is for. `null` answers 401.\n * @default (c) => c.get('auth')?.userId ?? null\n */\n subject?: SubjectResolver;\n}\n\ntype Shape<S extends RoutableState> = S['_types'];\n\ntype KeyQuery<S extends RoutableState> = Shape<S>['key'] extends TObject ? { query: Shape<S>['key'] } : {};\n\ntype ReadRoutes<S extends Record<string, RoutableState>> = {\n [K in keyof S as `get${Capitalize<S[K]['id']>}State`]: RouteDef<KeyQuery<S[K]>, {}, StateSnapshot<Shape<S[K]>>>;\n};\n\ntype WriteInput<S extends RoutableState> = KeyQuery<S> & { body: Shape<S>['input'] };\n\ntype WriteRoutes<S extends Record<string, RoutableState>> = {\n [K in keyof S as Shape<S[K]>['input'] extends TSchema ? `put${Capitalize<S[K]['id']>}State` : never]: RouteDef<WriteInput<S[K]>, {}, StateSnapshot<Shape<S[K]>>>;\n};\n\n/**\n * What `GET <path>` answers: every state the subject may read and whose key\n * the query carries, and the manifest of every state — its key fields and\n * whether it has a write — in declaration order.\n */\nexport type StatesSnapshot<S extends Record<string, RoutableState>> = {\n at: string;\n states: { [K in keyof S as S[K]['id']]?: StateResult<Shape<S[K]>> };\n manifest: { [K in keyof S as S[K]['id']]: { key: string[]; write: boolean } };\n};\n\n/** The routes one state router derives, typed for `createApi` and the route map. */\nexport type StateRoutes<S extends Record<string, RoutableState>> = ReadRoutes<S> & WriteRoutes<S> & {\n getStates: RouteDef<{ query: TObject }, {}, StatesSnapshot<S>>;\n};\n\n/** The SSE events, keyed by their wire names, for the app's `defineEventRouter`. */\nexport type StateEvents<S extends Record<string, RoutableState>> = {\n [K in keyof S as `state.${S[K]['id']}.changed`]: EventDef<StateFrame<Shape<S[K]>>>;\n};\n\nexport interface StateRouter<S extends Record<string, RoutableState>>\n{\n /** The derived routes. Mount with `appRouter.packages([states.router])`. */\n router: Router<StateRoutes<S>>;\n\n /** The derived SSE events. Spread into `defineEventRouter({ ...appEvents, ...states.events })`. */\n events: StateEvents<S>;\n\n /** The declarations, as given. */\n states: S;\n}\n\ntype StateById<R extends StateRouter<any>, TId extends string> = Extract<R['states'][keyof R['states']], { id: TId }>;\n\n/** The value type of state `TId` of a state router. */\nexport type InferStateValue<R extends StateRouter<any>, TId extends string> = StateValue<Shape<StateById<R, TId>>>;\n\n/** The key type of state `TId`, `undefined` when it is keyless. */\nexport type InferStateKey<R extends StateRouter<any>, TId extends string> = StateKey<Shape<StateById<R, TId>>>;\n\n/** The write input of state `TId`, `never` when it declares no `.write()`. */\nexport type InferStateInput<R extends StateRouter<any>, TId extends string> =\n Shape<StateById<R, TId>>['input'] extends TSchema ? Static<Shape<StateById<R, TId>>['input']> : never;\n\n/**\n * Group states, derive their routes and SSE events, and subscribe their change\n * signals.\n *\n * @example\n * ```typescript\n * export const states = defineStateRouter({ consent, runtime, member });\n *\n * // server.config.ts\n * // .routes(appRouter.packages([states.router]))\n * // .events(defineEventRouter({ ...appEvents, ...states.events }), { auth: { enabled: true } })\n * ```\n */\nexport function defineStateRouter<S extends Record<string, RoutableState>>(\n states: S,\n options: StateRouterOptions = {},\n): StateRouter<S>\n{\n const path = options.path ?? '/state';\n const list = Object.values(states);\n\n assertPath(path);\n list.forEach(assertRoutable);\n assertSnapshotMiddlewareIsNotAuthorization(list, options);\n assertDistinctIds(list);\n list.forEach(state => assertNotRouted(state, path));\n\n list.forEach(state => bindState(state._definition, path));\n list.forEach(subscribeChangeSignals);\n\n return {\n router: defineRouter(deriveRoutes(list, path, options)) as Router<StateRoutes<S>>,\n events: Object.fromEntries(list.map(state => [stateEventName(state.id), state._event])) as StateEvents<S>,\n states,\n };\n}\n\nfunction deriveRoutes(states: RoutableState[], path: string, options: StateRouterOptions): Record<string, RouteDef<any, any, any>>\n{\n const resolveSubject = options.subject ?? defaultSubject;\n const routes: Record<string, RouteDef<any, any, any>> = {};\n\n for (const state of states)\n {\n routes[stateRouteName('get', state.id)] = readRoute(state, path, resolveSubject);\n\n if (state._definition.write)\n {\n routes[stateRouteName('put', state.id)] = writeRoute(state, path, resolveSubject);\n }\n }\n\n routes.getStates = snapshotRoute(states, stateManifest(states), path, resolveSubject, options);\n\n return routes;\n}\n\nfunction assertPath(path: string): void\n{\n if (!path.startsWith('/') || (path.length > 1 && path.endsWith('/')))\n {\n throw new Error(\n `defineStateRouter(..., { path: \"${path}\" }) is not an absolute path without a trailing slash. `\n + 'The routes are mounted at <path> and <path>/<id>. Write it as \"/state\".',\n );\n }\n}\n\n/** Refuse a state the router could not serve, naming it. */\nfunction assertRoutable(state: RoutableState): void\n{\n const def = state._definition;\n const missing = !def.value ? '.value()' : !def.read ? '.read()' : undefined;\n\n if (missing)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" declares no ${missing}. `\n + 'A state answers with the value its read returns, so both are required. '\n + `Add ${missing} to defineState('${state.id}').`,\n );\n }\n\n if (def.key && !def.canRead)\n {\n throw new Error(\n `defineStateRouter: keyed state \"${state.id}\" declares no .canRead(). `\n + 'The key comes from the request, so without it any subject could read any key. '\n + 'Add .canRead(({ subject, key }) => ...).',\n );\n }\n\n assertMiddlewareIsNotAuthorization(state);\n def.changedBy?.forEach(event => assertChangedBy(state, event));\n\n if (def.write && !def.contract && def.write.options.since)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" gives .write(..., { since: '${def.write.options.since}' }) `\n + 'but declares no .contract(), so there is nothing to fall back from: the write route would have a version '\n + 'but no auth profile, and the read route and the event would not be contracted at all. '\n + 'Add .contract({ since, ... }) to the state, or drop since from the write.',\n );\n }\n}\n\n/**\n * `.use()` / `.skip()` reach the two per-state routes only: the snapshot and\n * the SSE stream cannot run HTTP middleware. A guard there would hold on one\n * route and leak through the others, so authorization must be `canRead`.\n */\nfunction assertMiddlewareIsNotAuthorization(state: RoutableState): void\n{\n const def = state._definition;\n\n if ((def.middlewares.length > 0 || def.skipMiddlewares) && !def.canRead)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" declares .use() or .skip() but no .canRead(). `\n + `Middleware reaches only ${stateRouteName('get', state.id)} / ${stateRouteName('put', state.id)} — never the `\n + 'snapshot route or the SSE stream — so it cannot authorize. Authorization belongs in .canRead(), which is '\n + 'enforced on the read route, the snapshot and the stream. A state that needs middleware only for, say, rate '\n + 'limiting declares .canRead(() => true) to say so.',\n );\n }\n}\n\n/**\n * The router's `use` / `skip` reach the snapshot route only — never the SSE\n * stream, which serves the same states — so, as for a state's own `.use()`,\n * every state must authorize with `canRead`. A `contract` alone runs nothing.\n */\nfunction assertSnapshotMiddlewareIsNotAuthorization(states: RoutableState[], options: StateRouterOptions): void\n{\n const unguarded = states.find(state => !state._definition.canRead);\n\n if (((options.use?.length ?? 0) > 0 || options.skip) && unguarded)\n {\n throw new Error(\n `defineStateRouter: the router gives the snapshot route use or skip, but state \"${unguarded.id}\" declares no `\n + '.canRead(). The snapshot\\'s middleware never reaches the SSE stream, which serves the same state, so it '\n + 'cannot authorize. Authorization belongs in .canRead(); a state readable by every subject declares '\n + '.canRead(() => true) to say so.',\n );\n }\n}\n\n/** A `.changedBy()` event must carry every field the state's change signal names, as a required property. */\nfunction assertChangedBy(state: RoutableState, event: EventDef<any>): void\n{\n const payload = event.schema as TObject | undefined;\n const signal = changedPayloadSchema(state._definition);\n const missing = Object.keys(signal.properties).find(field =>\n !payload?.properties?.[field] || !(payload.required ?? []).includes(field));\n\n if (missing)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" lists event \"${event.name}\" in .changedBy(), but its payload schema `\n + `has no required field \"${missing}\". Its payload is read like ${state.id}.changed.emit(), which names `\n + `${Object.keys(signal.properties).join(', ')}. Add the field to the event, or emit ${state.id}.changed instead.`,\n );\n }\n}\n\nfunction assertDistinctIds(states: RoutableState[]): void\n{\n const seen = new Set<string>();\n\n for (const state of states)\n {\n if (seen.has(state.id))\n {\n throw new Error(\n `defineStateRouter: two states have the id \"${state.id}\". `\n + `Both would derive the routes ${stateRouteName('get', state.id)} and the event `\n + `${stateEventName(state.id)}, and one would shadow the other. Rename one.`,\n );\n }\n seen.add(state.id);\n }\n}\n\nfunction assertNotRouted(state: RoutableState, path: string): void\n{\n const other = stateBinding(state._definition)?.path;\n\n if (other !== undefined)\n {\n throw new Error(\n `defineStateRouter: state \"${state.id}\" is already in another state router (path ${other}, this one ${path}). `\n + 'Each router subscribes the state\\'s change signal, so every change would be read and sent twice. '\n + 'Group each state in one router.',\n );\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spfn/core",
|
|
3
|
-
"version": "0.3.0-beta.
|
|
3
|
+
"version": "0.3.0-beta.27",
|
|
4
4
|
"description": "Full-stack TypeScript backend for Next.js: file-based typed routes, Drizzle entities and repositories, PostgreSQL transactions and a generated end-to-end client, in one fixed vertical slice per feature",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
package/src/state/README.md
CHANGED
|
@@ -34,11 +34,11 @@ import type { states } from '@/server/states';
|
|
|
34
34
|
From `@spfn/core/state`:
|
|
35
35
|
|
|
36
36
|
- Builder: `defineState(id)` → `StateBuilder`
|
|
37
|
-
- Router: `defineStateRouter(states, { path?, subject? })` → `StateRouter`
|
|
38
|
-
- Types: `StateBuilder`, `StateRouter`, `StateRouterOptions`, `StateRoutes`, `StateEvents`,
|
|
37
|
+
- Router: `defineStateRouter(states, { path?, subject?, use?, skip?, contract? })` → `StateRouter`
|
|
38
|
+
- Types: `StateBuilder`, `StateRouter`, `StateRouterOptions`, `SnapshotRouteOptions`, `StateRoutes`, `StateEvents`,
|
|
39
39
|
`StatesSnapshot`, `StatesManifest`, `SubjectResolver`, `InferStateValue`, `InferStateKey`, `InferStateInput`,
|
|
40
40
|
`StateShape`, `StateValue`, `StateKey`, `StateResult`, `StateSnapshot`, `StateFrame`,
|
|
41
|
-
`ReadContext`, `PermissionContext`, `WriteContext`, `ChangedPayload`, `GrantTarget`,
|
|
41
|
+
`ReadContext`, `PermissionContext`, `WritePermissionContext`, `WriteContext`, `ChangedPayload`, `GrantTarget`,
|
|
42
42
|
`RevokeTarget`, `StateContract`, `StateWriteOptions`, `RoutableState`
|
|
43
43
|
|
|
44
44
|
`StateBuilder` methods — immutable, every call returns a new builder, order free, no terminal
|
|
@@ -49,10 +49,11 @@ method:
|
|
|
49
49
|
| `.key(schema, { shared? })` | Key fields: one value per key. `shared: true` — the value does not depend on the subject | a non-object schema; a field that is not a required `Type.String()`; a field named `events` or `token`; a second call |
|
|
50
50
|
| `.value(schema)` | The value. Required | a second call |
|
|
51
51
|
| `.data(schema)` | Data attached to the value. Optional | a second call |
|
|
52
|
+
| `.principal<P>()` | Type-only: who the callbacks' `principal` is — what the app's auth middleware sets as `c.get('auth')`. The write route then refuses a request whose `auth` is `undefined` or `null` (401) | a second call |
|
|
52
53
|
| `.use(mws)` / `.skip(names)` | Middleware for the two per-state routes, `get<Id>State` / `put<Id>State`; calls add up. **Not authorization** — the snapshot and the SSE stream cannot run it; authorize with `.canRead()` (see [Permissions](#permissions)) | at `defineStateRouter`, when the state declares no `.canRead()` |
|
|
53
54
|
| `.contract({ since, auth?, requiresSession?, deprecatedIn?, removedIn? })` | Publishes the read route, the write route and the event | a second call |
|
|
54
55
|
| `.canRead(fn)` | `({ subject, principal, key? }) => boolean \| Promise<boolean>`. Required on a keyed state | a second call |
|
|
55
|
-
| `.canWrite(fn)` | Same shape. Absent → `canRead` decides | a second call |
|
|
56
|
+
| `.canWrite(fn)` | Same shape; `principal` without `undefined` (below). Absent → `canRead` decides | a second call |
|
|
56
57
|
| `.read(fn)` | The only source of a value. Required. Returns `{ value }`, or `{ value, data }` with `.data` — checked against the declaration on every path | a second call |
|
|
57
58
|
| `.write(input, fn, { since?, deprecatedIn?, removedIn? })` | Derives the write route. `fn` gets the read context plus `input` and returns nothing | a second call |
|
|
58
59
|
| `.changedBy(events)` | Domain events whose payload is read like the change signal's (see [The change signal](#the-change-signal)) | a second call; at `defineStateRouter`, an event whose payload schema lacks a required field |
|
|
@@ -63,9 +64,48 @@ keyed state only, and required there), `.revoke({ subject, key? })`, `.id`.
|
|
|
63
64
|
`StateRouter`: `.router` (a `Router` from `defineRouter`), `.events` (`Record` of the SSE
|
|
64
65
|
events keyed by wire name), `.states` (the declarations as given).
|
|
65
66
|
|
|
67
|
+
`defineStateRouter` options:
|
|
68
|
+
|
|
69
|
+
| Option | Effect |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| `path` | Where the routes are mounted, default `/state` |
|
|
72
|
+
| `subject` | Who an HTTP request is for, default `c => c.get('auth')?.userId ?? null` |
|
|
73
|
+
| `use` | Middleware for the snapshot route `GET <path>` only. **Not authorization**; refused when a state declares no `.canRead()`. An empty `use` is not a middleware and is not refused |
|
|
74
|
+
| `skip` | Server-level named middlewares the snapshot route skips; `'*'` skips every one. Refused like `use` |
|
|
75
|
+
| `contract` | `{ since, auth?, requiresSession?, deprecatedIn?, removedIn? }` — publishes the snapshot route; its response schema is derived |
|
|
76
|
+
|
|
77
|
+
`use`, `skip` and `contract` reach the snapshot route only. A per-state route keeps exactly its
|
|
78
|
+
own state's `.use()` / `.skip()` / `.contract()`; nothing is merged either way. A server that
|
|
79
|
+
gates every request behind a named middleware (say `'requirements'`: "finish your onboarding")
|
|
80
|
+
lets the onboarding states `.skip(['requirements'])` and the router `skip: ['requirements']`, so
|
|
81
|
+
the shell's first snapshot is served to exactly the people it routes. The router does not infer
|
|
82
|
+
the snapshot's skips from its states'.
|
|
83
|
+
|
|
66
84
|
The types of `.read()`, `.write()`, `.canRead()` and `.canWrite()` contexts and of `R` are
|
|
67
85
|
computed from the schemas declared *before* the call — runtime order is free, but declare
|
|
68
|
-
`.key()`, `.value()` and `.
|
|
86
|
+
`.key()`, `.value()`, `.data()` and `.principal()` first to have the functions checked against them.
|
|
87
|
+
|
|
88
|
+
`principal` in each callback, with `.principal<P>()` declared:
|
|
89
|
+
|
|
90
|
+
| Context | `principal` | Why |
|
|
91
|
+
| --- | --- | --- |
|
|
92
|
+
| `ReadContext` (`.read`) | `P \| undefined` | the change signal's re-read has no request, so none |
|
|
93
|
+
| `PermissionContext` (`.canRead`) | `P \| undefined` | SSE connect passes what `resolvePrincipal` returned, possibly `undefined` |
|
|
94
|
+
| `WritePermissionContext` (`.canWrite`) | `P` | asked on `PUT <path>/<id>` only, which refuses a request whose `auth` is `undefined` or `null` |
|
|
95
|
+
| `WriteContext` (`.write`) | `P` | the same route |
|
|
96
|
+
|
|
97
|
+
Without `.principal()` every one is `unknown`. `defineState<AuthContext>('consent')` is not the
|
|
98
|
+
form: an explicit type argument would default the id to `string` and lose the route-name
|
|
99
|
+
literals. Nor is a router option: the router cannot retype callbacks declared before it.
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
export const consent = defineState('consent')
|
|
103
|
+
.principal<AuthContext>()
|
|
104
|
+
.value(Consent)
|
|
105
|
+
.canWrite(({ principal }) => principal.user.verified) // AuthContext
|
|
106
|
+
.read(({ subject }) => consentService.current(subject))
|
|
107
|
+
.write(Input, ({ principal, input }) => consentService.record(principal.user.email, input));
|
|
108
|
+
```
|
|
69
109
|
|
|
70
110
|
---
|
|
71
111
|
|
|
@@ -160,7 +200,8 @@ Route names are `get<Id>State` / `put<Id>State` with the id's first letter upper
|
|
|
160
200
|
id must match `^[a-z][a-zA-Z0-9]*$` — `defineState` refuses another.
|
|
161
201
|
|
|
162
202
|
`defineStateRouter` refuses, naming the state: no `.value()` or `.read()`; a keyed state
|
|
163
|
-
without `.canRead()`; a state with `.use()` or `.skip()` but no `.canRead()`; a
|
|
203
|
+
without `.canRead()`; a state with `.use()` or `.skip()` but no `.canRead()`; a router `use`
|
|
204
|
+
or `skip` while any state declares no `.canRead()` (the first such state is named); a
|
|
164
205
|
`.changedBy()` event whose payload schema lacks a field the signal needs; two states with one
|
|
165
206
|
id; a `.write(…, { since })` on a state without `.contract()`; a state already grouped by
|
|
166
207
|
another router (each router subscribes the change signal, so every change would be read and
|
|
@@ -173,12 +214,17 @@ sent twice). A builder without `.value()` or
|
|
|
173
214
|
|
|
174
215
|
The subject comes from `options.subject(c)`, default `c.get('auth')?.userId ?? null` — the
|
|
175
216
|
SSE `getSubject` default. No subject → `UnauthorizedError` (401). The principal on HTTP is
|
|
176
|
-
`c.get('auth')` as the app's middleware set it.
|
|
217
|
+
`c.get('auth')` as the app's middleware set it. A state that declared `.principal()` refuses a
|
|
218
|
+
write whose request's `auth` is `undefined` or `null` with `UnauthorizedError` (401), after the subject and before
|
|
219
|
+
`canWrite`; the read and snapshot routes never refuse on a missing principal.
|
|
177
220
|
|
|
178
221
|
- **Read** `GET <path>/<id>`: subject → key (query, validated) → `canRead` (false → 403) →
|
|
179
222
|
`at` → `read()` → `{ at, value, data }`.
|
|
180
|
-
- **Write** `PUT <path>/<id>`: subject →
|
|
181
|
-
called) → `write({ …, input })` → `at` →
|
|
223
|
+
- **Write** `PUT <path>/<id>`: subject → principal (whose `auth` is `undefined` or `null` → 401) → key →
|
|
224
|
+
`canWrite ?? canRead` (false → 403, `write` not called) → `write({ …, input })` → `at` →
|
|
225
|
+
`read()` → one SSE frame → `{ at, value, data }`.
|
|
226
|
+
When the handler runs inside a transaction (`.use([Transactional()])`), the frame is
|
|
227
|
+
published after that transaction commits (see [Frames and transactions](#frames-and-transactions)).
|
|
182
228
|
A `write` that throws propagates; nothing is read and no frame is sent. The input is a
|
|
183
229
|
command, never the value: what the route answers is re-read.
|
|
184
230
|
- **Snapshot** `GET <path>`: subject → one `at` → for each state, in declaration order: a keyed
|
|
@@ -196,15 +242,17 @@ A result that does not match fails the read, write and snapshot routes with an `
|
|
|
196
242
|
naming the state and the first validation message, never the value; on the change signal it
|
|
197
243
|
is logged at warn and sends nothing; `grant` rejects with the same error and sends nothing.
|
|
198
244
|
|
|
199
|
-
A write
|
|
200
|
-
|
|
201
|
-
the next signal or read brings the client up to date.
|
|
245
|
+
A write whose `read()` then fails — it threw or returned an undeclared result — answers 500
|
|
246
|
+
and sends no frame. Without a transaction the write has already committed: there is no value
|
|
247
|
+
to report, and the next signal or read brings the client up to date. Under
|
|
248
|
+
`.use([Transactional()])` the failed read rolls the write back with it, so nothing changed.
|
|
202
249
|
|
|
203
250
|
The derived routes are ordinary `RouteDef`s registered by `registerRoutes`, so `.use()`
|
|
204
251
|
middleware runs inside the route's own chain, after the app's global middleware — it sees the
|
|
205
|
-
`auth` the app set.
|
|
206
|
-
|
|
207
|
-
|
|
252
|
+
`auth` the app set. A state's `.use()` / `.skip()` / `.contract()` reach its two per-state
|
|
253
|
+
routes only; the router's `use` / `skip` / `contract` reach the snapshot route only. The SSE
|
|
254
|
+
stream runs neither. That is why `.use()` / `.skip()` — the state's and the router's — require
|
|
255
|
+
`.canRead()`: a guard in middleware would hold on one route and leak through the others and the
|
|
208
256
|
stream. A state that needs middleware only for, say, rate limiting declares
|
|
209
257
|
`.canRead(() => true)` to say so.
|
|
210
258
|
|
|
@@ -213,8 +261,10 @@ stream. A state that needs middleware only for, say, rate limiting declares
|
|
|
213
261
|
## The change signal
|
|
214
262
|
|
|
215
263
|
The app emits `state.changed` **after the commit** that changed the value — from
|
|
216
|
-
`onAfterCommit` (`@spfn/core/db`), not inside the transaction.
|
|
217
|
-
|
|
264
|
+
`onAfterCommit` (`@spfn/core/db`), not inside the transaction. An emit made inside a
|
|
265
|
+
transaction anyway reads there and sends its frame at the commit (see
|
|
266
|
+
[Frames and transactions](#frames-and-transactions)). The module never reads on its own: no
|
|
267
|
+
polling, no database trigger. On each signal it reads and sends one frame:
|
|
218
268
|
|
|
219
269
|
| State | Read | Frame |
|
|
220
270
|
| --- | --- | --- |
|
|
@@ -257,6 +307,27 @@ module attaches nothing to the event — no `canSubscribe`, no `filter`; it only
|
|
|
257
307
|
`read()`'s result is copied into the frame, so neither a handler mutating what it returned nor
|
|
258
308
|
a subscriber mutating the payload changes the other.
|
|
259
309
|
|
|
310
|
+
### Frames and transactions
|
|
311
|
+
|
|
312
|
+
Every frame — of the write route, of the change signal and of `grant` — is sent by one rule:
|
|
313
|
+
|
|
314
|
+
| Where the read ran | Frame |
|
|
315
|
+
| --- | --- |
|
|
316
|
+
| outside a transaction | emitted at once and awaited; an emit that throws fails the write or `grant`; on the change signal it is logged at warn and `changed.emit` resolves |
|
|
317
|
+
| inside a transaction | queued with `onAfterCommit` and published after the root transaction commits; never when the root rolls back |
|
|
318
|
+
|
|
319
|
+
- The frame carries the value read inside the transaction, with that read's `at`; nothing is
|
|
320
|
+
read again after the commit. The response is the same snapshot.
|
|
321
|
+
- So a `changed.emit` or a `grant` made inside a transaction is deferred to its commit, like a
|
|
322
|
+
write.
|
|
323
|
+
- The queue belongs to the root transaction: a `Transactional()` nested in an outer
|
|
324
|
+
`runInTransaction` publishes at the outer commit.
|
|
325
|
+
- A nested transaction (a savepoint) that rolls back while the root commits still publishes
|
|
326
|
+
the frame read inside it, because after-commit callbacks belong to the root; emit the signal
|
|
327
|
+
from the outer transaction, or after it, when an inner one may roll back.
|
|
328
|
+
- A deferred emit runs outside the transaction context; an error it throws is logged by the
|
|
329
|
+
transaction runner and reaches nobody.
|
|
330
|
+
|
|
260
331
|
---
|
|
261
332
|
|
|
262
333
|
## Permissions
|
|
@@ -266,7 +337,7 @@ a subscriber mutating the payload changes the other.
|
|
|
266
337
|
| `canRead` | `GET <path>/<id>` | 403 |
|
|
267
338
|
| `canRead` | `GET <path>` | that state omitted |
|
|
268
339
|
| `canRead` | SSE connect (`canSubscribe`), with the key from the connect query | that event in `connected.deniedEvents` |
|
|
269
|
-
| `canWrite ?? canRead` | `PUT <path>/<id>` | 403 |
|
|
340
|
+
| `canWrite ?? canRead` | `PUT <path>/<id>` | 403; with `.principal()` declared, a request whose `auth` is `undefined` or `null` is 401 before it is asked |
|
|
270
341
|
|
|
271
342
|
On SSE the connection declares its key in the connect query —
|
|
272
343
|
`/events/stream?events=state.runtime.changed&workspaceId=w1&token=…`. The module sets each
|
|
@@ -342,7 +413,10 @@ change" by the client (implemented in the client half). There is no version coun
|
|
|
342
413
|
- the SSE event `state.<id>.changed` with `since` / `deprecatedIn` / `removedIn`.
|
|
343
414
|
|
|
344
415
|
A state without `.contract()` appears nowhere, like a route without one. The snapshot route is
|
|
345
|
-
|
|
416
|
+
contracted by the router's own `contract` option, never by a state's: response
|
|
417
|
+
`{ at, states: { [id]?: { value, data? } }, manifest: { [id]: { key: string[], write: boolean } } }`,
|
|
418
|
+
each `states` entry optional and each `manifest` entry required, in declaration order — built
|
|
419
|
+
once when the router is built. Without that option it appears nowhere. A `value` literal removed later is `response.type-changed` on the read
|
|
346
420
|
operation and `event.payload.type-changed` on the event, as any route and event.
|
|
347
421
|
|
|
348
422
|
---
|