@almadar/core 10.96.0 → 10.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/dist/builders.d.ts +5 -4
- package/dist/builders.js +60 -34
- package/dist/builders.js.map +1 -1
- package/dist/bus-BGDM3Xot.d.ts +565 -0
- package/dist/domain-Ds_7wZIL.d.ts +16213 -0
- package/dist/{effect-Bw8T4qh5.d.ts → effect-CW_IT0Jn.d.ts} +59 -4
- package/dist/{entityAccess-DfoXs9mc.d.ts → entityAccess-BLpOMojb.d.ts} +3 -3
- package/dist/{expression-WfTp2arD.d.ts → expression-DRwzVnMu.d.ts} +5 -1
- package/dist/factory/index.d.ts +5 -5
- package/dist/factory/index.js +22 -0
- package/dist/factory/index.js.map +1 -1
- package/dist/factory-runtime/index.d.ts +5 -4
- package/dist/factory-runtime/index.js +176 -34
- package/dist/factory-runtime/index.js.map +1 -1
- package/dist/fixtures.d.ts +45 -0
- package/dist/fixtures.js +693 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/{index-CN16-h3i.d.ts → index-CHHuux4I.d.ts} +9 -375
- package/dist/index.d.ts +19 -15
- package/dist/index.js +9070 -44
- package/dist/index.js.map +1 -1
- package/dist/mock/index.d.ts +6 -5
- package/dist/mock/index.js +14 -0
- package/dist/mock/index.js.map +1 -1
- package/dist/patterns/component-mapping.json +1 -1
- package/dist/patterns/event-contracts.json +1 -1
- package/dist/patterns/index.d.ts +12 -8
- package/dist/patterns/index.js +15 -4
- package/dist/patterns/index.js.map +1 -1
- package/dist/patterns/patterns-registry.json +1 -1
- package/dist/patterns/registry.json +1 -1
- package/dist/{schema-DPpES4qj.d.ts → schema-BVjtoRYf.d.ts} +2134 -23608
- package/dist/state-machine/index.d.ts +1 -1
- package/dist/themes/index.d.ts +19 -0
- package/dist/themes/index.js +9251 -0
- package/dist/themes/index.js.map +1 -0
- package/dist/{trait-DXXRrRMP.d.ts → trait-C9lr222u.d.ts} +26 -26
- package/dist/types/index.d.ts +8 -6
- package/dist/types/index.js +208 -41
- package/dist/types/index.js.map +1 -1
- package/dist/{types-BMaTUGyk.d.ts → types-BoyvM79n.d.ts} +2 -2
- package/fixtures/events-wire/cascade-emitted-events/request.json +9 -0
- package/fixtures/events-wire/cascade-emitted-events/response.json +30 -0
- package/fixtures/events-wire/client-effects-by-trait/request.json +4 -0
- package/fixtures/events-wire/client-effects-by-trait/response.json +52 -0
- package/fixtures/events-wire/effect-results/request.json +9 -0
- package/fixtures/events-wire/effect-results/response.json +42 -0
- package/fixtures/events-wire/effect-results-every-kind/request.json +9 -0
- package/fixtures/events-wire/effect-results-every-kind/response.json +70 -0
- package/fixtures/events-wire/guard-rejected/request.json +6 -0
- package/fixtures/events-wire/guard-rejected/response.json +11 -0
- package/fixtures/events-wire/live-push/live-push.json +12 -0
- package/fixtures/events-wire/live-push/request.json +9 -0
- package/fixtures/events-wire/live-push/response.json +33 -0
- package/fixtures/events-wire/navigate-1/request.json +5 -0
- package/fixtures/events-wire/navigate-1/response.json +16 -0
- package/fixtures/events-wire/navigate-2/request.json +8 -0
- package/fixtures/events-wire/navigate-2/response.json +19 -0
- package/fixtures/events-wire/navigate-3/request.json +8 -0
- package/fixtures/events-wire/navigate-3/response.json +22 -0
- package/fixtures/events-wire/navigate-back/request.json +5 -0
- package/fixtures/events-wire/navigate-back/response.json +15 -0
- package/fixtures/events-wire/render-ui-3/request.json +5 -0
- package/fixtures/events-wire/render-ui-3/response.json +20 -0
- package/fixtures/events-wire/render-ui-4/request.json +5 -0
- package/fixtures/events-wire/render-ui-4/response.json +41 -0
- package/fixtures/events-wire/render-ui-5/request.json +9 -0
- package/fixtures/events-wire/render-ui-5/response.json +52 -0
- package/fixtures/events-wire/render-ui-clear/request.json +5 -0
- package/fixtures/events-wire/render-ui-clear/response.json +27 -0
- package/fixtures/events-wire/sse-stream/request.json +9 -0
- package/fixtures/events-wire/sse-stream/response.json +79 -0
- package/fixtures/events-wire/sse-stream/stream.json +131 -0
- package/fixtures/events-wire/stateless-traits/request.json +27 -0
- package/fixtures/events-wire/stateless-traits/response.json +15 -0
- package/fixtures/theme-tokens/every-key.json +43 -0
- package/package.json +18 -3
- package/themes/almadar-website.json +207 -0
- package/themes/almadar.json +203 -0
- package/themes/atelier.json +459 -0
- package/themes/bloomberg-dense.json +459 -0
- package/themes/clay.json +445 -0
- package/themes/comic.json +457 -0
- package/themes/corporate.json +445 -0
- package/themes/game-adventure.json +229 -0
- package/themes/game-rpg.json +230 -0
- package/themes/game-sci-fi.json +229 -0
- package/themes/game-ui-pack.json +230 -0
- package/themes/gazette.json +445 -0
- package/themes/glass.json +445 -0
- package/themes/kiosk.json +441 -0
- package/themes/linear-clean.json +459 -0
- package/themes/minimalist.json +445 -0
- package/themes/neon.json +445 -0
- package/themes/notion-editorial.json +459 -0
- package/themes/prism.json +203 -0
- package/themes/retro.json +445 -0
- package/themes/terminal.json +457 -0
- package/themes/trait-wars.json +493 -0
- package/themes/wireframe.json +445 -0
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
import { F as FieldValue, S as ServerReportedEffect, N as NamespacedEffectName, g as EntityRow, d as OrbitalId, T as TraitId, b as EventId, h as PatternConfig, i as ResolvedPatternProps, A as AnyPatternConfig } from './effect-CW_IT0Jn.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { a as EventPayloadValue, b as EventPayload } from './expression-DRwzVnMu.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Authenticated user context — what `@user.x` resolves against.
|
|
7
|
+
*
|
|
8
|
+
* The canonical shape for the `user` binding root, shared by both execution
|
|
9
|
+
* paths: the JS interpreter resolves `@user.id` through
|
|
10
|
+
* `EvaluationContext.user`, and the compiled shell emits `user?.id` against the
|
|
11
|
+
* `UserContext` its `@app/shared` re-exports from here.
|
|
12
|
+
*
|
|
13
|
+
* `id` is the field the behavior library reads for ownership scoping and `role`
|
|
14
|
+
* the field it reads for capability gating. Auth providers that name the subject
|
|
15
|
+
* `uid` must normalize at their boundary — {@link normalizeUserContext} does that.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/** Authenticated user / agent identity behind `@user.x` bindings. */
|
|
21
|
+
interface UserContext {
|
|
22
|
+
/** Stable subject identifier. `@user.id` — the ownership key. */
|
|
23
|
+
id: string;
|
|
24
|
+
/** `@user.email` */
|
|
25
|
+
email?: string;
|
|
26
|
+
/** `@user.name` — display name. */
|
|
27
|
+
name?: string;
|
|
28
|
+
/** `@user.role` — single role string, compared against a policy's allowed list. */
|
|
29
|
+
role?: string;
|
|
30
|
+
/** `@user.permissions` — fine-grained capability strings. */
|
|
31
|
+
permissions?: string[];
|
|
32
|
+
/** Additional provider claims, readable as `@user.<claim>`. */
|
|
33
|
+
[key: string]: FieldValue | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The identity of an unauthenticated viewer. A resolvable object rather than
|
|
37
|
+
* `undefined` so a role predicate evaluates to a definite `false` instead of
|
|
38
|
+
* comparing against nothing.
|
|
39
|
+
*/
|
|
40
|
+
declare const ANONYMOUS_USER: UserContext;
|
|
41
|
+
/** Provider-shaped identity claims, before normalization. */
|
|
42
|
+
interface RawUserClaims {
|
|
43
|
+
id?: string;
|
|
44
|
+
uid?: string;
|
|
45
|
+
email?: string | null;
|
|
46
|
+
name?: string;
|
|
47
|
+
displayName?: string | null;
|
|
48
|
+
role?: string;
|
|
49
|
+
permissions?: string[];
|
|
50
|
+
[key: string]: FieldValue | undefined;
|
|
51
|
+
}
|
|
52
|
+
/** Zod twin of `RawUserClaims` — the wire shape of `OrbitalEventRequest.user`. */
|
|
53
|
+
declare const RawUserClaimsSchema: z.ZodType<RawUserClaims>;
|
|
54
|
+
/**
|
|
55
|
+
* Normalize provider claims into a {@link UserContext}.
|
|
56
|
+
*
|
|
57
|
+
* Firebase (and most OIDC providers) name the subject `uid` and the display name
|
|
58
|
+
* `displayName`, while every `.lolo` behavior reads `@user.id` / `@user.name`.
|
|
59
|
+
* Without this normalization `@user.id` is `undefined` against a fully
|
|
60
|
+
* authenticated request and every ownership filter silently matches no rows.
|
|
61
|
+
* `uid` is preserved so `@user.uid` keeps working.
|
|
62
|
+
*
|
|
63
|
+
* Returns `undefined` for absent or subject-less claims so callers can
|
|
64
|
+
* distinguish "no auth ran" from "anonymous"; use {@link ANONYMOUS_USER} where a
|
|
65
|
+
* definite identity is required.
|
|
66
|
+
*/
|
|
67
|
+
declare function normalizeUserContext(claims: RawUserClaims | null | undefined): UserContext | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Turn a row of an app's `[identity]` entity into a viewer.
|
|
70
|
+
*
|
|
71
|
+
* There is no separate persona shape: an identity row IS the persona
|
|
72
|
+
* (`Almadar_LOLO_Identity.md` §4.3), so this only guards the one field the
|
|
73
|
+
* behavior library requires — a non-empty string `id` — and passes every other
|
|
74
|
+
* declared field through as a `@user.<field>` claim. Rows without a usable id
|
|
75
|
+
* yield `undefined` rather than a persona nobody can own rows as.
|
|
76
|
+
*/
|
|
77
|
+
declare function personaFromIdentityRow(row: Record<string, FieldValue | undefined>): UserContext | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* The viewer a host presents when nothing named one.
|
|
80
|
+
*
|
|
81
|
+
* Without this, `@user` is `Null` in headless verify and preview, so every
|
|
82
|
+
* `viewerName: @user.name` binding renders blank and the account menu never
|
|
83
|
+
* appears — an app that cannot say who you are. Worse, an ownership filter that
|
|
84
|
+
* works and one that is broken both render an empty table.
|
|
85
|
+
*
|
|
86
|
+
* `role` is deliberately EMPTY, not a guess. A default of `admin` would silently
|
|
87
|
+
* flip which branch renders at the 38 `@user.role` comparisons in the corpus;
|
|
88
|
+
* an empty role matches no literal, exactly as `Null` did, so this fixes
|
|
89
|
+
* "undefined at runtime" without changing a single guard outcome.
|
|
90
|
+
*/
|
|
91
|
+
declare const DEFAULT_VIEWER: UserContext;
|
|
92
|
+
/**
|
|
93
|
+
* The viewer to present an app as when nothing named one.
|
|
94
|
+
*
|
|
95
|
+
* `DEFAULT_VIEWER` is synthetic — `viewer-1` is in no app's roster — so under it
|
|
96
|
+
* every ownership predicate (`@entity.<owner> == @user.id`) matches zero rows and
|
|
97
|
+
* a correctly-scoped app renders empty tables everywhere. That is indistinguishable
|
|
98
|
+
* on screen from a broken filter, which is exactly the failure DEFAULT_VIEWER's own
|
|
99
|
+
* comment warns about.
|
|
100
|
+
*
|
|
101
|
+
* So when the app declares an `[identity]` roster, the default viewer is a REAL
|
|
102
|
+
* member of it. `DEFAULT_VIEWER` remains the fallback for apps that declare no
|
|
103
|
+
* identity entity, where there is nobody to be.
|
|
104
|
+
*
|
|
105
|
+
* Both execution paths share this rule; the Rust twin is
|
|
106
|
+
* `orbital-core::runtime::persona::resolve_default_viewer`.
|
|
107
|
+
*/
|
|
108
|
+
declare function resolveDefaultViewer(roster: readonly UserContext[]): UserContext;
|
|
109
|
+
/** Look a persona up in a roster by id, or by role when no id matches. */
|
|
110
|
+
declare function findPersonaInRoster(roster: readonly UserContext[], idOrRole: string): UserContext | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Resolve a persona spec — a bare id/role (`Person Id 3`, `moderator`) or a full
|
|
113
|
+
* JSON `UserContext` — into a viewer. This is the `ALMADAR_PERSONA` contract,
|
|
114
|
+
* shared by every host that presents an app as somebody.
|
|
115
|
+
*
|
|
116
|
+
* The roster is the app's OWN declared personas — the seeded rows of its
|
|
117
|
+
* `[identity]` entity (`Almadar_LOLO_Identity.md` §4.3) — supplied by the host
|
|
118
|
+
* that has them in hand (the runtime's live store on the interpreter path, the
|
|
119
|
+
* schema-derived seed rows on the compiled path). There is no global roster:
|
|
120
|
+
* an app without an `[identity]` entity resolves only JSON-form specs.
|
|
121
|
+
*
|
|
122
|
+
* Throws on anything unresolvable rather than returning `undefined`: "no persona"
|
|
123
|
+
* and "persona silently ignored" look identical on screen, so a bad spec must
|
|
124
|
+
* fail at boot instead of rendering as nobody.
|
|
125
|
+
*/
|
|
126
|
+
declare function resolvePersonaSpec(spec: string, roster: readonly UserContext[]): UserContext;
|
|
127
|
+
/**
|
|
128
|
+
* Marks a bearer token as a mocked dev identity rather than a real ID token.
|
|
129
|
+
* The prefix is deliberately unmistakable: a server accepts these ONLY behind an
|
|
130
|
+
* explicit dev opt-in, so a production deployment rejects them like any other
|
|
131
|
+
* malformed token.
|
|
132
|
+
*/
|
|
133
|
+
declare const DEV_TOKEN_PREFIX = "almadar-dev.";
|
|
134
|
+
/**
|
|
135
|
+
* Encode a viewer as a dev bearer token.
|
|
136
|
+
*
|
|
137
|
+
* Carries the WHOLE identity, not just the subject: real Firebase claims have no
|
|
138
|
+
* `role`, so a server that only reads `uid` leaves every `@user.role` gate inert
|
|
139
|
+
* even for a signed-in user. URI-encoded JSON keeps the token header-safe (no
|
|
140
|
+
* spaces or delimiters) and works unchanged in Node and the browser.
|
|
141
|
+
*/
|
|
142
|
+
declare function encodeDevIdentityToken(user: UserContext): string;
|
|
143
|
+
/**
|
|
144
|
+
* Decode a dev bearer token back into a viewer, or `undefined` if it is not one
|
|
145
|
+
* / is malformed — callers fail closed rather than inventing an identity.
|
|
146
|
+
*/
|
|
147
|
+
declare function decodeDevIdentityToken(token: string): UserContext | undefined;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Server-side effect result — the wire shape a server-executed effect
|
|
151
|
+
* (`SERVER_REPORTED_EFFECTS` in `effect.ts`) reports back to the client,
|
|
152
|
+
* closing the circuit on `OrbitalEventResponse.effectResults`.
|
|
153
|
+
*
|
|
154
|
+
* Promoted from `@almadar/runtime`'s `ServerEffectHandlers.ts` (the JS
|
|
155
|
+
* interpreter's own definition, canonical per `CLAUDE.md`'s "converge on
|
|
156
|
+
* the TypeScript implementation" ruling) so `@almadar/core` owns the one
|
|
157
|
+
* shape both execution paths report against.
|
|
158
|
+
*
|
|
159
|
+
* @packageDocumentation
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Result entry recorded for each effect invocation. Mirrors the server
|
|
164
|
+
* runtime's `EffectResult`. Callers who want telemetry pass an array that
|
|
165
|
+
* the factory appends to; otherwise it's unused.
|
|
166
|
+
*/
|
|
167
|
+
interface ServerBatchSummary {
|
|
168
|
+
operations: EntityRow[];
|
|
169
|
+
completedCount: number;
|
|
170
|
+
totalCount: number;
|
|
171
|
+
}
|
|
172
|
+
/** Zod twin of `ServerBatchSummary`. */
|
|
173
|
+
declare const ServerBatchSummarySchema: z.ZodType<ServerBatchSummary>;
|
|
174
|
+
interface ServerEffectResult {
|
|
175
|
+
/**
|
|
176
|
+
* The reported effect's head (`SERVER_REPORTED_EFFECTS`, derived from the
|
|
177
|
+
* effect union in `effect.ts`), or `"substrate"` — the one wire grouping
|
|
178
|
+
* for the namespaced operators (`trace/*`, `memory/*`, `session/*`,
|
|
179
|
+
* `behavior/*`, `compose/*`), whose head rides `name`.
|
|
180
|
+
*/
|
|
181
|
+
effect: ServerReportedEffect | "substrate";
|
|
182
|
+
action?: string;
|
|
183
|
+
entityType?: string;
|
|
184
|
+
/** The invoked namespaced operator (e.g. `"memory/store"`), set only on `effect: "substrate"`. */
|
|
185
|
+
name?: NamespacedEffectName;
|
|
186
|
+
/** Entity row for CRUD/set/swap, the batch summary for `persist batch`, the raw service/substrate result. */
|
|
187
|
+
data?: EntityRow | ServerBatchSummary | EventPayloadValue;
|
|
188
|
+
success: boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Set when a persist failed because an access policy rejected it or the
|
|
191
|
+
* write resolved no row key — mirrors `OrbitalServerRuntime.EffectResult`
|
|
192
|
+
* so the offline-preview and real-server persist paths report the same
|
|
193
|
+
* denial discriminator to the verification trace.
|
|
194
|
+
*/
|
|
195
|
+
denied?: true;
|
|
196
|
+
error?: string;
|
|
197
|
+
/** Coded failure reason for a persist that resolved no target row. */
|
|
198
|
+
code?: "not-found" | "no-row-key";
|
|
199
|
+
}
|
|
200
|
+
/** Zod twin of `ServerEffectResult`. */
|
|
201
|
+
declare const ServerEffectResultSchema: z.ZodType<ServerEffectResult>;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Declared event key. A trait's event names (INIT, SAVE, CLOSE,
|
|
205
|
+
* CONFIRM_REMOVE, ...) flow through the orbital schema and the UI as
|
|
206
|
+
* strings; this alias marks "this string is a declared event key, not
|
|
207
|
+
* arbitrary text."
|
|
208
|
+
*
|
|
209
|
+
* Component props typed as `EventKey` are detected by the pattern-sync
|
|
210
|
+
* tool (`tools/almadar-pattern-sync/parser.ts`) via a TS-type lookup and
|
|
211
|
+
* marked as `kind: "event"` in the patterns registry
|
|
212
|
+
* (`@almadar/patterns`). Consumers of the registry — the Rust compiler's
|
|
213
|
+
* inline phase and the `@almadar/runtime` preprocess — read that marker
|
|
214
|
+
* to apply call-site `events: { OLD: NEW }` renames to render-ui trees
|
|
215
|
+
* without name-matching heuristics.
|
|
216
|
+
*
|
|
217
|
+
* Plain alias over `string`. Not branded because event keys originate
|
|
218
|
+
* from user data at runtime (orb schema literals, bus emits), so cast
|
|
219
|
+
* friction would buy nothing. The value of the alias is at the type
|
|
220
|
+
* surface — it's a marker the pattern-sync tool can find via
|
|
221
|
+
* `getSymbolAtLocation`.
|
|
222
|
+
*/
|
|
223
|
+
type EventKey = string;
|
|
224
|
+
/**
|
|
225
|
+
* Phantom-typed brand for declarative bus-emit props on UI components.
|
|
226
|
+
*
|
|
227
|
+
* Used by component authors to BOTH mark a prop as a bus-event reference
|
|
228
|
+
* AND document the payload shape that the component will fire onto the
|
|
229
|
+
* bus when that prop is bound. Authors write:
|
|
230
|
+
*
|
|
231
|
+
* // Tabs.tsx
|
|
232
|
+
* export interface TabsProps {
|
|
233
|
+
* tabChangeEvent?: EventEmit<{ tabId: string }>;
|
|
234
|
+
* }
|
|
235
|
+
*
|
|
236
|
+
* Consumers see only the structural `string` (no UX impact: passing a
|
|
237
|
+
* literal `"TAB_CHANGED"` keeps working). The phantom `P` parameter
|
|
238
|
+
* carries the bus-payload schema at the type level for pattern-sync to
|
|
239
|
+
* extract.
|
|
240
|
+
*
|
|
241
|
+
* Pattern-sync (`tools/almadar-pattern-sync/parser.ts`) detects this
|
|
242
|
+
* brand via TS type-lookup (mirrors how it detects `EventKey`) and
|
|
243
|
+
* writes two registry fields per prop:
|
|
244
|
+
* - `kind: "event-ref"` — the discriminant rules read in lolo / orb
|
|
245
|
+
* validator to know "this prop's string value is a bus event name."
|
|
246
|
+
* - `emitPayloadSchema` — the structural shape of `P`, serialized as
|
|
247
|
+
* the same JSON-Schema-shaped record Almadar uses for trait
|
|
248
|
+
* `payloadSchema`. Validator rules cross-check this against the
|
|
249
|
+
* trait's declared `emits { EVENT { ... } }` payload to catch mismatches
|
|
250
|
+
* at parse / validate time instead of runtime.
|
|
251
|
+
*
|
|
252
|
+
* Example payload bus emission inside the component (no wrapper —
|
|
253
|
+
* `EventEmit<P>` erases to `string`):
|
|
254
|
+
*
|
|
255
|
+
* if (tabChangeEvent) eventBus.emit(`UI:${tabChangeEvent}`, { tabId });
|
|
256
|
+
*
|
|
257
|
+
* The brand is structurally an unused optional readonly property; TS
|
|
258
|
+
* never asks for it at construction, so authors and consumers never
|
|
259
|
+
* see it.
|
|
260
|
+
*/
|
|
261
|
+
type EventEmit<P> = string & {
|
|
262
|
+
readonly __emitPayload?: P;
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* Phantom-typed brand for declarative bus-listen props on UI components.
|
|
266
|
+
*
|
|
267
|
+
* Mirror of `EventEmit<P>`. Used by future patterns where a UI component
|
|
268
|
+
* subscribes to a bus event and forwards its payload upward via prop
|
|
269
|
+
* (e.g. an editor pattern that listens for `EXTERNAL_RESET` and exposes
|
|
270
|
+
* the consumed payload to the parent). Pattern-sync detects this brand
|
|
271
|
+
* the same way as `EventEmit<P>` and writes:
|
|
272
|
+
* - `kind: "event-listen"` (or a sub-discriminant of `event-ref`)
|
|
273
|
+
* - `listenPayloadSchema` with the structural shape of `P`
|
|
274
|
+
*
|
|
275
|
+
* Validator rules use this to verify the trait the prop is bound to
|
|
276
|
+
* actually emits a payload of the expected shape.
|
|
277
|
+
*
|
|
278
|
+
* Reserved for symmetry; no @almadar/ui component uses it as of this
|
|
279
|
+
* commit. Add usages incrementally as patterns require them.
|
|
280
|
+
*/
|
|
281
|
+
type EventListen<P> = string & {
|
|
282
|
+
readonly __listenPayload?: P;
|
|
283
|
+
};
|
|
284
|
+
/**
|
|
285
|
+
* Identifies the origin of a bus event. Used by cross-trait listeners to
|
|
286
|
+
* filter emits from specific orbitals, traits, transitions, or ticks.
|
|
287
|
+
*
|
|
288
|
+
* `transition` and `tick` are optional runtime-internal details; most
|
|
289
|
+
* consumers only care about `orbital` and `trait`.
|
|
290
|
+
*/
|
|
291
|
+
interface BusEventSource {
|
|
292
|
+
orbital?: string;
|
|
293
|
+
/** V4 dual-carry id sibling of `orbital` — stable across an orbital rename. */
|
|
294
|
+
orbitalId?: OrbitalId;
|
|
295
|
+
trait?: string;
|
|
296
|
+
/** V4 dual-carry id sibling of `trait` — stable across a trait rename. */
|
|
297
|
+
traitId?: TraitId;
|
|
298
|
+
/** V4 dual-carry id of the emitted event — stable across an event rename. */
|
|
299
|
+
eventId?: EventId;
|
|
300
|
+
transition?: string;
|
|
301
|
+
tick?: string;
|
|
302
|
+
/**
|
|
303
|
+
* True when the orbital bridge re-broadcasts an event onto the bus
|
|
304
|
+
* (any source — both echoes of the dispatched event and server-side
|
|
305
|
+
* cascade emits via `(emit X)` / `fetch.emit.success`). Cross-trait
|
|
306
|
+
* listeners filter on this flag so the click-time qualified emit
|
|
307
|
+
* (which has no `fromBridge`) doesn't double-fire alongside the
|
|
308
|
+
* post-server bridge confirmation. See `dispatched` for the narrower
|
|
309
|
+
* "echo of the just-dispatched event" signal.
|
|
310
|
+
*/
|
|
311
|
+
fromBridge?: boolean;
|
|
312
|
+
/**
|
|
313
|
+
* True ONLY for bridge echoes the receiving tab already processed, so
|
|
314
|
+
* the originating trait's self-subscription skips them instead of
|
|
315
|
+
* re-dispatching its own echo (infinite loop / double execution).
|
|
316
|
+
* Set by path 1 of useOrbitalBridge (compiled shell — echo of the
|
|
317
|
+
* just-dispatched event; server-side cascade emits there carry
|
|
318
|
+
* `fromBridge: true` but NOT `dispatched`, so they still reach the
|
|
319
|
+
* source trait's transition handler, e.g. `loading -> browsing` on a
|
|
320
|
+
* fetch's `emit.success`) and by ServerBridge (runtime path — stamped
|
|
321
|
+
* on exactly one response-cascade echo per event the dispatch delivered
|
|
322
|
+
* locally on the bare key, `stampLocallyDeliveredEchoes`; server-only
|
|
323
|
+
* results stay unstamped). Cross-trait `listens` never filter on this
|
|
324
|
+
* flag, so their delivery is unaffected. Push-leg events from OTHER
|
|
325
|
+
* tabs (multiplayer) are never stamped.
|
|
326
|
+
*/
|
|
327
|
+
dispatched?: boolean;
|
|
328
|
+
/**
|
|
329
|
+
* The client that originated the dispatch whose effects emitted this
|
|
330
|
+
* event (from `OrbitalEventRequest.clientId`); absent for headless
|
|
331
|
+
* dispatches (ticks, circuit-router probes, walkers). The server-side
|
|
332
|
+
* listens fan-out skips client-originated cascade emits — under dual
|
|
333
|
+
* execution the originating client relays every cascade hop through the
|
|
334
|
+
* bridge itself, so the server dispatching the same hop double-ran it
|
|
335
|
+
* (one Send persisted two rows). Headless topology keeps the fan-out:
|
|
336
|
+
* there is no client to drive the circuit.
|
|
337
|
+
*/
|
|
338
|
+
originClientId?: string;
|
|
339
|
+
}
|
|
340
|
+
/** Zod twin of `BusEventSource`. */
|
|
341
|
+
declare const BusEventSourceSchema: z.ZodType<BusEventSource, z.ZodTypeDef, object>;
|
|
342
|
+
/**
|
|
343
|
+
* An event flowing on the bus.
|
|
344
|
+
*
|
|
345
|
+
* The `source` field is structured so cross-trait listeners can match
|
|
346
|
+
* `event.source?.orbital === 'X' && event.source?.trait === 'Y'` without
|
|
347
|
+
* parsing a delimiter.
|
|
348
|
+
*/
|
|
349
|
+
interface BusEvent {
|
|
350
|
+
/** Event type identifier (e.g., 'CartItemLoaded', 'TASK_COMPLETED') */
|
|
351
|
+
type: EventKey;
|
|
352
|
+
/** Optional structured payload */
|
|
353
|
+
payload?: EventPayload;
|
|
354
|
+
/** Timestamp when the event was emitted */
|
|
355
|
+
timestamp: number;
|
|
356
|
+
/** Optional origin info for filtering */
|
|
357
|
+
source?: BusEventSource;
|
|
358
|
+
}
|
|
359
|
+
/** Bus event listener callback. */
|
|
360
|
+
type BusEventListener = (event: BusEvent) => void;
|
|
361
|
+
/** Returned by `on()` / `once()` to detach a listener. */
|
|
362
|
+
type Unsubscribe = () => void;
|
|
363
|
+
/**
|
|
364
|
+
* One event a transition's effects emitted, carried back to the client to
|
|
365
|
+
* re-dispatch (in order) so the state machine advances through the
|
|
366
|
+
* cascade without server-side recursion. Named/shaped to match the
|
|
367
|
+
* generated compiled-path `EmittedEvent` (orbital-shell-typescript's
|
|
368
|
+
* `shared/types.ts`) so the two execution paths agree on one shape.
|
|
369
|
+
*/
|
|
370
|
+
interface EmittedEvent {
|
|
371
|
+
event: string;
|
|
372
|
+
payload?: EventPayload;
|
|
373
|
+
source?: BusEventSource;
|
|
374
|
+
}
|
|
375
|
+
/** Zod twin of `EmittedEvent`. Third type param `object`, see `BusEventSourceSchema`. */
|
|
376
|
+
declare const EmittedEventSchema: z.ZodType<EmittedEvent, z.ZodTypeDef, object>;
|
|
377
|
+
/**
|
|
378
|
+
* Client-side effect tuple shipped in `OrbitalEventResponse.clientEffects`.
|
|
379
|
+
* Restricted to the effect kinds the client knows how to apply to the
|
|
380
|
+
* UI: render-ui (slot mutation, including the `toast` slot that carries
|
|
381
|
+
* what used to be the separate notify effect) and navigate (route change).
|
|
382
|
+
* Server-only effects (persist, set, fetch, ...) execute on the server and
|
|
383
|
+
* surface their results via `effectResults` and `emittedEvents`, not here.
|
|
384
|
+
*
|
|
385
|
+
* Shape note: the wire form is broader than `RenderUIEffect` /
|
|
386
|
+
* `NavigateEffect` from `@almadar/core/types/effect.ts` in two places — the
|
|
387
|
+
* runtime appends an interpolated `props` object plus an optional `priority`
|
|
388
|
+
* slot to render-ui (slot 4 + 5), and `navigate`'s optional argument may
|
|
389
|
+
* surface as `undefined` rather than absent. The local union spells those
|
|
390
|
+
* variants out explicitly so consumers (ServerBridge.tsx parser, debugger
|
|
391
|
+
* inspector) get accurate completions instead of `unknown[]`.
|
|
392
|
+
*
|
|
393
|
+
* `slot` is a plain `string` in this wire shape (not `UISlot`'s literal
|
|
394
|
+
* union) because the runtime forwards the raw string from the trait's
|
|
395
|
+
* `(render-ui slot ...)` SExpr without re-validating against the registry —
|
|
396
|
+
* registry validation lives in `orbital validate` / `lolo` parse, not here.
|
|
397
|
+
*/
|
|
398
|
+
type ClientRenderUITuple = ['render-ui', string, PatternConfig | null] | ['render-ui', string, PatternConfig | null, ResolvedPatternProps] | ['render-ui', string, PatternConfig | null, ResolvedPatternProps | undefined, number | undefined];
|
|
399
|
+
type ClientNavigateTuple = ['navigate', string] | ['navigate', string, Record<string, string> | undefined] | ['navigate', string, Record<string, string> | undefined, {
|
|
400
|
+
crumb?: string;
|
|
401
|
+
}];
|
|
402
|
+
type ClientNavigateBackTuple = ['navigate-back'];
|
|
403
|
+
type ClientEffectTuple = ClientRenderUITuple | ClientNavigateTuple | ClientNavigateBackTuple;
|
|
404
|
+
/** Zod twin of `ClientRenderUITuple` — one variant per fixed arity (3/4/5), unioned. */
|
|
405
|
+
declare const ClientRenderUITupleSchema: z.ZodUnion<[z.ZodTuple<[z.ZodLiteral<"render-ui">, z.ZodString, z.ZodType<AnyPatternConfig | null, z.ZodTypeDef, AnyPatternConfig | null>], null>, z.ZodTuple<[z.ZodLiteral<"render-ui">, z.ZodString, z.ZodType<AnyPatternConfig | null, z.ZodTypeDef, AnyPatternConfig | null>, z.ZodType<ResolvedPatternProps, z.ZodTypeDef, ResolvedPatternProps>], null>, z.ZodTuple<[z.ZodLiteral<"render-ui">, z.ZodString, z.ZodType<AnyPatternConfig | null, z.ZodTypeDef, AnyPatternConfig | null>, z.ZodOptional<z.ZodType<ResolvedPatternProps, z.ZodTypeDef, ResolvedPatternProps>>, z.ZodOptional<z.ZodNumber>], null>]>;
|
|
406
|
+
/** Zod twin of `ClientNavigateTuple` — one variant per fixed arity (2/3/4), unioned. */
|
|
407
|
+
declare const ClientNavigateTupleSchema: z.ZodUnion<[z.ZodTuple<[z.ZodLiteral<"navigate">, z.ZodString], null>, z.ZodTuple<[z.ZodLiteral<"navigate">, z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>], null>, z.ZodTuple<[z.ZodLiteral<"navigate">, z.ZodString, z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>, z.ZodObject<{
|
|
408
|
+
crumb: z.ZodOptional<z.ZodString>;
|
|
409
|
+
}, "strip", z.ZodTypeAny, {
|
|
410
|
+
crumb?: string | undefined;
|
|
411
|
+
}, {
|
|
412
|
+
crumb?: string | undefined;
|
|
413
|
+
}>], null>]>;
|
|
414
|
+
/** Zod twin of `ClientNavigateBackTuple`. */
|
|
415
|
+
declare const ClientNavigateBackTupleSchema: z.ZodTuple<[z.ZodLiteral<"navigate-back">], null>;
|
|
416
|
+
/** Zod twin of `ClientEffectTuple`. */
|
|
417
|
+
declare const ClientEffectTupleSchema: z.ZodType<ClientEffectTuple>;
|
|
418
|
+
/**
|
|
419
|
+
* Client → server event dispatch request. The single upstream owner of
|
|
420
|
+
* this shape — both the JS interpreter (`@almadar/runtime`'s
|
|
421
|
+
* `OrbitalEventRequest`) and the compiled path's generated `EventRequest`
|
|
422
|
+
* (orbital-shell-typescript's `shared/types.ts`, mirrored 1:1 in
|
|
423
|
+
* `orbital-core`) carry the same fields, so the two execution paths cannot
|
|
424
|
+
* drift.
|
|
425
|
+
*/
|
|
426
|
+
interface OrbitalEventRequest {
|
|
427
|
+
event: string;
|
|
428
|
+
/**
|
|
429
|
+
* V4 dual-carry id sibling of `event` — the fired event's id, when known
|
|
430
|
+
* (e.g. threaded from a `listens[].triggersId`). Optional; absent means
|
|
431
|
+
* the state machine dispatches by name only (legacy).
|
|
432
|
+
*/
|
|
433
|
+
eventId?: EventId;
|
|
434
|
+
payload?: EventPayload;
|
|
435
|
+
entityId?: string;
|
|
436
|
+
/**
|
|
437
|
+
* Scoped-listen delivery: dispatch to THIS trait only. A listens-matched
|
|
438
|
+
* trigger is addressed to the listening trait; without this, a trigger
|
|
439
|
+
* renamed to INIT broadcast orbital-wide and re-ran every trait's
|
|
440
|
+
* initializer (R-SCOPED-LISTEN-INIT-RENAME-FREEZE re-fire cascade).
|
|
441
|
+
*/
|
|
442
|
+
targetTrait?: string;
|
|
443
|
+
/** Provider claims for `@user` bindings, normalized by `normalizeUserContext`. */
|
|
444
|
+
user?: RawUserClaims;
|
|
445
|
+
/** Per-tab client identity (UUID) — excludes this request's origin from live-broadcast delivery. */
|
|
446
|
+
clientId?: string;
|
|
447
|
+
/**
|
|
448
|
+
* Broadcast-class marker (T6, docs/Almadar_Tick_Loop.md §3a): the name of
|
|
449
|
+
* the tick that emitted this event. Tick-stamped dispatches are
|
|
450
|
+
* latest-state broadcasts — the client fires them without awaiting the
|
|
451
|
+
* response, and the server relays them to OTHER tabs coalesced
|
|
452
|
+
* (newest-per-key) at a snapshot rate instead of 1:1.
|
|
453
|
+
*/
|
|
454
|
+
tick?: string;
|
|
455
|
+
/** Emitting trait for a tick-stamped dispatch — builds the relay's BusEventSource (sourceless emits are dropped client-side). */
|
|
456
|
+
sourceTrait?: string;
|
|
457
|
+
/**
|
|
458
|
+
* Stateless addressing: the traits this dispatch runs against, each with
|
|
459
|
+
* the scope it dispatches `from` (a single-element array is the common
|
|
460
|
+
* case; a listens fan-out that crosses traits carries more than one). The
|
|
461
|
+
* compiled server is stateless-per-trait too (`handlers.rs:510-532` seeds
|
|
462
|
+
* state from `currentState`) — this generalizes that mechanism instead of
|
|
463
|
+
* the retired single `currentState`/`fields` pair.
|
|
464
|
+
*/
|
|
465
|
+
traits?: Array<{
|
|
466
|
+
trait: string;
|
|
467
|
+
from: string;
|
|
468
|
+
}>;
|
|
469
|
+
/**
|
|
470
|
+
* The dispatching traits' current `@entity` frames (declared defaults <
|
|
471
|
+
* fetched row < `[shared]` frame), keyed by trait name. The server layers
|
|
472
|
+
* each row over the one it resolves via `resolveEntityView` so guards and
|
|
473
|
+
* effects read the same values the client does.
|
|
474
|
+
*/
|
|
475
|
+
entityByTrait?: Record<string, EntityRow>;
|
|
476
|
+
/** The orbital/behavior name this dispatch targets, for stateless multi-orbital addressing. */
|
|
477
|
+
behavior?: string;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Server → client event dispatch response. Mirrors the compiled path's
|
|
481
|
+
* generated `EventResponse` (orbital-shell-typescript's `shared/types.ts`,
|
|
482
|
+
* mirrored 1:1 in `orbital-core`'s `effects/response.rs`) — canonical = the
|
|
483
|
+
* TS runtime's `OrbitalEventResponse` (`@almadar/runtime`'s
|
|
484
|
+
* `OrbitalServerRuntime.ts`).
|
|
485
|
+
*/
|
|
486
|
+
interface OrbitalEventResponse {
|
|
487
|
+
success: boolean;
|
|
488
|
+
transitioned: boolean;
|
|
489
|
+
/** Whole-orbital state snapshot, keyed by trait name. */
|
|
490
|
+
states: Record<string, string>;
|
|
491
|
+
/**
|
|
492
|
+
* Events emitted during processing, in declaration order. ALWAYS present
|
|
493
|
+
* (`[]` when none) — the compiled Hono path used to omit this field on a
|
|
494
|
+
* no-cascade response, which forced every consumer to optional-chain a
|
|
495
|
+
* field that is really always there.
|
|
496
|
+
*
|
|
497
|
+
* Each entry carries a `source: BusEventSource` so the client-side
|
|
498
|
+
* ServerBridge can re-broadcast on the qualified `UI:Orbital.Trait.EVENT`
|
|
499
|
+
* bus key. Without source the re-broadcast skips the entry and downstream
|
|
500
|
+
* listeners (e.g. ContactBrowse waiting for ContactLoaded after a fetch)
|
|
501
|
+
* never fire — the dashboard-layout that ContactLoaded renders disappears.
|
|
502
|
+
*/
|
|
503
|
+
emittedEvents: EmittedEvent[];
|
|
504
|
+
/** Fetched/queried entity collections this response carries, keyed by entity name. */
|
|
505
|
+
data?: Record<string, EntityRow[]>;
|
|
506
|
+
/**
|
|
507
|
+
* `@entity` fields this transition's server-side `set` effects wrote,
|
|
508
|
+
* post-effect, keyed by trait name — the response-side twin of the
|
|
509
|
+
* request's `entityByTrait`. The client merges them over its own effect
|
|
510
|
+
* results (server wins).
|
|
511
|
+
*/
|
|
512
|
+
entityByTrait?: Record<string, EntityRow>;
|
|
513
|
+
/** Client-side effects to execute (render-ui, navigate). */
|
|
514
|
+
clientEffects?: ClientEffectTuple[];
|
|
515
|
+
/**
|
|
516
|
+
* Same effects as `clientEffects`, paired with the producing trait name.
|
|
517
|
+
* Consumers that need per-trait attribution (e.g. `<TraitFrame>` resolving
|
|
518
|
+
* `@trait.X` bindings) read from this field; legacy consumers ignore it
|
|
519
|
+
* and continue with the flat `clientEffects` array unchanged.
|
|
520
|
+
*
|
|
521
|
+
* Same length and ordering as `clientEffects`; entries are 1:1 by index.
|
|
522
|
+
*/
|
|
523
|
+
clientEffectsByTrait?: Array<{
|
|
524
|
+
traitName: string;
|
|
525
|
+
effect: ClientEffectTuple;
|
|
526
|
+
}>;
|
|
527
|
+
/** Results from server-side effects (persist, call-service, set). */
|
|
528
|
+
effectResults?: ServerEffectResult[];
|
|
529
|
+
/** Guard that failed, addressed as `"<Trait>.<event>"`, for debugging. */
|
|
530
|
+
guardFailed?: string;
|
|
531
|
+
error?: string;
|
|
532
|
+
}
|
|
533
|
+
/** Zod twin of `OrbitalEventRequest`. Third type param `object`, see `BusEventSourceSchema`. */
|
|
534
|
+
declare const OrbitalEventRequestSchema: z.ZodType<OrbitalEventRequest, z.ZodTypeDef, object>;
|
|
535
|
+
/** Zod twin of `OrbitalEventResponse`. Third type param `object`, see `BusEventSourceSchema`. */
|
|
536
|
+
declare const OrbitalEventResponseSchema: z.ZodType<OrbitalEventResponse, z.ZodTypeDef, object>;
|
|
537
|
+
/**
|
|
538
|
+
* One persist-envelope success emit, handed to the live-broadcast sink
|
|
539
|
+
* (`OrbitalServerRuntime.setLiveBroadcastSink`) and relayed to every OTHER
|
|
540
|
+
* connected client. Fired only from the `persist` effect's `emit:{success}`
|
|
541
|
+
* envelope (batch and single-op) — never from the generic emit funnel — so
|
|
542
|
+
* transport layers can fan it out without matching on event names. Promoted
|
|
543
|
+
* from `@almadar/runtime`'s own `LiveBroadcastItem` (canonical per Program
|
|
544
|
+
* A's "converge on the TS runtime" ruling) so `orbital-server`'s `GET
|
|
545
|
+
* /api/events` broadcast mirrors the same shape.
|
|
546
|
+
*/
|
|
547
|
+
interface LiveBroadcastItem {
|
|
548
|
+
event: string;
|
|
549
|
+
payload?: EventPayload;
|
|
550
|
+
source: BusEventSource;
|
|
551
|
+
/** `clientId` of the request that produced this emit; excluded from delivery by the transport. */
|
|
552
|
+
originClientId?: string;
|
|
553
|
+
}
|
|
554
|
+
/** Zod twin of `LiveBroadcastItem`. Third type param `object`, see `BusEventSourceSchema`. */
|
|
555
|
+
declare const LiveBroadcastItemSchema: z.ZodType<LiveBroadcastItem, z.ZodTypeDef, object>;
|
|
556
|
+
/** @deprecated use {@link OrbitalEventRequest}. Kept until every referrer migrates (Program A wave A8). */
|
|
557
|
+
type EventDispatchRequest = OrbitalEventRequest;
|
|
558
|
+
/** @deprecated use {@link OrbitalEventRequestSchema}. */
|
|
559
|
+
declare const EventDispatchRequestSchema: z.ZodType<OrbitalEventRequest, z.ZodTypeDef, object>;
|
|
560
|
+
/** @deprecated use {@link OrbitalEventResponse}. Kept until every referrer migrates (Program A wave A8). */
|
|
561
|
+
type EventDispatchResponse = OrbitalEventResponse;
|
|
562
|
+
/** @deprecated use {@link OrbitalEventResponseSchema}. */
|
|
563
|
+
declare const EventDispatchResponseSchema: z.ZodType<OrbitalEventResponse, z.ZodTypeDef, object>;
|
|
564
|
+
|
|
565
|
+
export { ANONYMOUS_USER as A, type BusEvent as B, type ClientEffectTuple as C, DEFAULT_VIEWER as D, type EmittedEvent as E, ServerEffectResultSchema as F, type Unsubscribe as G, decodeDevIdentityToken as H, encodeDevIdentityToken as I, findPersonaInRoster as J, normalizeUserContext as K, type LiveBroadcastItem as L, personaFromIdentityRow as M, resolveDefaultViewer as N, type OrbitalEventRequest as O, resolvePersonaSpec as P, type RawUserClaims as R, type ServerBatchSummary as S, type UserContext as U, type OrbitalEventResponse as a, type BusEventListener as b, type BusEventSource as c, BusEventSourceSchema as d, ClientEffectTupleSchema as e, type ClientNavigateBackTuple as f, ClientNavigateBackTupleSchema as g, type ClientNavigateTuple as h, ClientNavigateTupleSchema as i, type ClientRenderUITuple as j, ClientRenderUITupleSchema as k, DEV_TOKEN_PREFIX as l, EmittedEventSchema as m, type EventDispatchRequest as n, EventDispatchRequestSchema as o, type EventDispatchResponse as p, EventDispatchResponseSchema as q, type EventEmit as r, type EventKey as s, type EventListen as t, LiveBroadcastItemSchema as u, OrbitalEventRequestSchema as v, OrbitalEventResponseSchema as w, RawUserClaimsSchema as x, ServerBatchSummarySchema as y, type ServerEffectResult as z };
|