@almadar/runtime 6.33.0 → 6.34.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.
@@ -1,6 +1,6 @@
1
1
  import { Router } from 'express';
2
- import { I as IEventBus, R as RuntimeEvent, a as EventListener, U as Unsubscribe, T as TraitDefinition, b as RuntimeConfig, c as TransitionObserver, C as ConfigContext, d as TraitState, e as TransitionResult, f as EvaluationContextExtensions, E as EffectHandlers } from './types-ConZnrpe.js';
3
- import { EventPayload, EntityRow, Orbital, ServiceCallResult, TraitConfig, DeclaredTraitConfig, Entity, OrbitalSchema, Trait, PatternConfig, ResolvedPatternProps, SExpr, BusEventSource, OrbitalDefinition, TraitTick } from '@almadar/core';
2
+ import { I as IEventBus, R as RuntimeEvent, a as EventListener, U as Unsubscribe, T as TraitDefinition, b as RuntimeConfig, c as TransitionObserver, d as TraitState, C as ConfigContext, e as TransitionResult, f as EvaluationContextExtensions, E as EffectHandlers } from './types-C8RsO0xa.js';
3
+ import { EventPayload, EventId, EntityRow, Orbital, ServiceCallResult, TraitConfig, DeclaredTraitConfig, Entity, OrbitalSchema, Trait, PatternConfig, ResolvedPatternProps, SExpr, BusEventSource, OrbitalDefinition, TraitTick } from '@almadar/core';
4
4
 
5
5
  /**
6
6
  * EventBus - Platform-Agnostic Pub/Sub Implementation
@@ -47,7 +47,7 @@ declare class EventBus implements IEventBus {
47
47
  * beyond `maxDepth`, the event is dropped and an error is logged.
48
48
  * This prevents infinite loops from circular emit/listen chains.
49
49
  */
50
- emit(type: string, payload?: EventPayload, source?: RuntimeEvent['source']): void;
50
+ emit(type: string, payload?: EventPayload, source?: RuntimeEvent['source'], routingKey?: string): void;
51
51
  /**
52
52
  * Subscribe to an event type
53
53
  */
@@ -101,7 +101,7 @@ declare function createInitialTraitState(trait: TraitDefinition): TraitState;
101
101
  * when multiple sibling transitions share the same `from`/`event` and
102
102
  * disambiguate by guard.
103
103
  */
104
- declare function findTransition(trait: TraitDefinition, currentState: string, eventKey: string): TraitDefinition['transitions'][0] | undefined;
104
+ declare function findTransition(trait: TraitDefinition, currentState: string, eventKey: string, eventId?: EventId): TraitDefinition['transitions'][0] | undefined;
105
105
  /**
106
106
  * Normalize event key - strip UI: prefix if present.
107
107
  */
@@ -116,6 +116,12 @@ interface ProcessEventOptions {
116
116
  trait: TraitDefinition;
117
117
  /** Event key to process */
118
118
  eventKey: string;
119
+ /**
120
+ * V4 dual-carry id sibling of `eventKey` — the id of the fired event,
121
+ * when known. Threaded to `findMatchingTransitions` for id-primary
122
+ * matching; absent means name-only dispatch (legacy).
123
+ */
124
+ eventId?: EventId;
119
125
  /** Event payload */
120
126
  payload?: EventPayload;
121
127
  /** Entity data for binding resolution */
@@ -179,6 +185,15 @@ interface ProcessEventOptions {
179
185
  declare function processEvent(options: ProcessEventOptions): TransitionResult;
180
186
  declare class StateMachineManager {
181
187
  private traits;
188
+ /**
189
+ * V4 identity index: trait id → trait name. Populated for traits that
190
+ * carry an `id` (ledger-backed schemas). Lets callers resolve a trait's
191
+ * state by its stable id, which survives a mid-session rename — the
192
+ * name-keyed maps are re-pointed on rename via {@link renameTrait}, but
193
+ * an id holder never has to observe the rename at all. Empty for legacy
194
+ * id-free schemas, where every lookup stays name-keyed (unchanged).
195
+ */
196
+ private traitIdToName;
182
197
  /**
183
198
  * Per-trait call-site config, surfaced to guard expressions so
184
199
  * `@config.X` resolves at runtime. Populated by the orbital's
@@ -217,6 +232,26 @@ declare class StateMachineManager {
217
232
  * Add a trait to the manager.
218
233
  */
219
234
  addTrait(trait: TraitDefinition): void;
235
+ /**
236
+ * Resolve a trait by its V4 id. Returns undefined when no trait carries
237
+ * that id (legacy schema, or unknown id). Exact-match only — no name
238
+ * similarity.
239
+ */
240
+ getTraitById(traitId: string): TraitDefinition | undefined;
241
+ /**
242
+ * Get a trait's current state by its V4 id (id-first lookup). Falls back
243
+ * to `undefined` when the id is unknown. The id survives a rename, so a
244
+ * holder of the id reads the right state without ever seeing the new name.
245
+ */
246
+ getStateById(traitId: string, entityId?: string): TraitState | undefined;
247
+ /**
248
+ * Apply a mid-session trait rename: re-point the name-keyed maps from
249
+ * `oldName` to `newName`, preserving live state, queues, and the id
250
+ * index. A no-op when the trait isn't registered under `oldName`. This
251
+ * is the interpreter-side of a ledger `curName` edit for the trait's own
252
+ * name-keyed storage; id-keyed references need no update.
253
+ */
254
+ renameTrait(oldName: string, newName: string): void;
220
255
  /**
221
256
  * Bind the call-site config for a trait so guard `@config.X`
222
257
  * resolves at runtime. Typically called by the orbital
@@ -256,7 +291,7 @@ declare class StateMachineManager {
256
291
  /**
257
292
  * Check if a trait can handle an event from its current state.
258
293
  */
259
- canHandleEvent(traitName: string, eventKey: string, entityId?: string): boolean;
294
+ canHandleEvent(traitName: string, eventKey: string, entityId?: string, eventId?: EventId): boolean;
260
295
  /**
261
296
  * Send an event to all traits.
262
297
  *
@@ -267,9 +302,13 @@ declare class StateMachineManager {
267
302
  * `@entity.X` see prior step writes — required for [runtime] entities
268
303
  * that have no persistence row to reload.
269
304
  *
305
+ * `eventId` is the V4 dual-carry id sibling of `eventKey` (see
306
+ * {@link ProcessEventOptions.eventId}) — additive and optional, threaded
307
+ * through to `processEvent` for id-primary transition matching.
308
+ *
270
309
  * @returns Array of transition results (one per trait that had a matching transition)
271
310
  */
272
- sendEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>): Array<{
311
+ sendEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>, eventId?: EventId): Array<{
273
312
  traitName: string;
274
313
  result: TransitionResult;
275
314
  }>;
@@ -280,7 +319,7 @@ declare class StateMachineManager {
280
319
  * trait to process them sequentially (actor-model guarantee: one event
281
320
  * at a time per trait, effects fully awaited before the next event).
282
321
  */
283
- enqueueEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>): void;
322
+ enqueueEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>, eventId?: EventId): void;
284
323
  /**
285
324
  * Drain a single (trait, entity) pair's event queue, processing
286
325
  * events sequentially. Pass `entityId` to drain a specific entity
@@ -898,6 +937,12 @@ interface RegisteredOrbital {
898
937
  */
899
938
  interface OrbitalEventRequest {
900
939
  event: string;
940
+ /**
941
+ * V4 dual-carry id sibling of `event` — the fired event's id, when known
942
+ * (e.g. threaded from a `listens[].triggersId`). Optional; absent means
943
+ * the state machine dispatches by name only (legacy).
944
+ */
945
+ eventId?: EventId;
901
946
  payload?: EventPayload;
902
947
  entityId?: string;
903
948
  /** User context for @user bindings (from Firebase auth) */
@@ -1,4 +1,4 @@
1
1
  import 'express';
2
- export { F as ClientEffectTuple, G as ClientNavigateTuple, H as ClientNotifyTuple, J as ClientRenderUITuple, K as EffectResult, e as InMemoryPersistence, M as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, N as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, Q as RuntimeTraitTick, p as collectDeclaredConfigDefaults, T as createOrbitalServerRuntime } from './OrbitalServerRuntime-Cep380it.js';
3
- import './types-ConZnrpe.js';
2
+ export { F as ClientEffectTuple, G as ClientNavigateTuple, H as ClientNotifyTuple, J as ClientRenderUITuple, K as EffectResult, e as InMemoryPersistence, M as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, N as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, Q as RuntimeTraitTick, p as collectDeclaredConfigDefaults, T as createOrbitalServerRuntime } from './OrbitalServerRuntime-BrHSXDfp.js';
3
+ import './types-C8RsO0xa.js';
4
4
  import '@almadar/core';
@@ -1,5 +1,5 @@
1
- import { createTickScheduler, EventBus, createUnifiedLoader, MockPersistenceAdapter, InMemoryPersistence, preprocessSchema, normalizeCallSiteConfigToValues, StateMachineManager, parseDurationString, createContextFromBindings, validateEventPayload, formatPayloadValidationError, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, collectDeclaredEntityDefaults, EffectExecutor } from './chunk-JZDLN2FS.js';
2
- export { InMemoryPersistence, collectDeclaredConfigDefaults } from './chunk-JZDLN2FS.js';
1
+ import { createTickScheduler, EventBus, createUnifiedLoader, MockPersistenceAdapter, InMemoryPersistence, preprocessSchema, normalizeCallSiteConfigToValues, StateMachineManager, parseDurationString, createContextFromBindings, validateEventPayload, formatPayloadValidationError, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, collectDeclaredEntityDefaults, EffectExecutor } from './chunk-TRA44DDY.js';
2
+ export { InMemoryPersistence, collectDeclaredConfigDefaults } from './chunk-TRA44DDY.js';
3
3
  import { isValidCronExpression } from './chunk-OU3ITB5S.js';
4
4
  import './chunk-OQJIK6PZ.js';
5
5
  import './chunk-SCRAHWOC.js';
@@ -9,6 +9,29 @@ import * as nodeModule from 'module';
9
9
  import { evaluateGuard, evaluate } from '@almadar/evaluator';
10
10
  import { buildResolvedTraitConfigs, isInlineTrait, isEntityCall } from '@almadar/core';
11
11
 
12
+ // src/identity/routing.ts
13
+ function eventRouteKey(eventName, eventId) {
14
+ return eventId ? `@evt:${eventId}` : eventName;
15
+ }
16
+ function buildSourceMatcher(src, listenerOrbital) {
17
+ if (src.kind === "any") return () => true;
18
+ if (src.kind === "trait") {
19
+ if (src.traitId !== void 0) {
20
+ const wantedTraitId = src.traitId;
21
+ return (source) => !!source && source.traitId === wantedTraitId;
22
+ }
23
+ const wantedTrait2 = src.trait;
24
+ return (source) => !!source && source.orbital === listenerOrbital && source.trait === wantedTrait2;
25
+ }
26
+ if (src.orbitalId !== void 0 && src.traitId !== void 0) {
27
+ const wantedOrbitalId = src.orbitalId;
28
+ const wantedTraitId = src.traitId;
29
+ return (source) => !!source && source.orbitalId === wantedOrbitalId && source.traitId === wantedTraitId;
30
+ }
31
+ const wantedOrbital = src.orbital;
32
+ const wantedTrait = src.trait;
33
+ return (source) => !!source && source.orbital === wantedOrbital && source.trait === wantedTrait;
34
+ }
12
35
  var _resolvedNodeRequire = null;
13
36
  function nodeRequire(modulePath) {
14
37
  if (!_resolvedNodeRequire) {
@@ -454,6 +477,9 @@ var OrbitalServerRuntime = class {
454
477
  const states = sm?.states || [];
455
478
  const transitions = sm?.transitions || [];
456
479
  return {
480
+ // V4 dual-carry: thread the trait id so the manager's id index is
481
+ // populated for ledger-backed schemas (undefined → name-keyed only).
482
+ ...t.id !== void 0 ? { id: t.id } : {},
457
483
  name: t.name,
458
484
  states,
459
485
  transitions,
@@ -521,7 +547,7 @@ var OrbitalServerRuntime = class {
521
547
  const fields = entity.fields.filter(
522
548
  (f) => typeof f.name === "string" && f.name.length > 0
523
549
  );
524
- this.persistence.registerEntity({ name: entity.name, fields });
550
+ this.persistence.registerEntity({ name: entity.name, id: entity.id, fields });
525
551
  if (this.config.debug) {
526
552
  persistLog.debug("mock:seeded", { entity: entity.name, count: this.persistence.count(entity.name) });
527
553
  }
@@ -536,7 +562,7 @@ var OrbitalServerRuntime = class {
536
562
  const auxFields = auxEntity.fields.filter(
537
563
  (f) => typeof f.name === "string" && f.name.length > 0
538
564
  );
539
- this.persistence.registerEntity({ name: auxEntity.name, fields: auxFields });
565
+ this.persistence.registerEntity({ name: auxEntity.name, id: auxEntity.id, fields: auxFields });
540
566
  if (this.config.debug) {
541
567
  persistLog.debug("mock:seeded-auxiliary", {
542
568
  entity: auxEntity.name,
@@ -576,7 +602,8 @@ var OrbitalServerRuntime = class {
576
602
  if (!trait.listens) continue;
577
603
  for (const listener of trait.listens) {
578
604
  const { bareEvent, matcher } = parseListenSource(listener, orbitalName);
579
- const cleanup = this.eventBus.on(bareEvent, async (event) => {
605
+ const routeKey = eventRouteKey(bareEvent, listener.eventId);
606
+ const cleanup = this.eventBus.on(routeKey, async (event) => {
580
607
  if (!matcher(event.source)) return;
581
608
  if (this.config.debug) {
582
609
  xOrbitalLog.debug("listen:received", () => ({
@@ -607,6 +634,7 @@ var OrbitalServerRuntime = class {
607
634
  const forwardedEntityId = pickId("entityId") ?? pickId("orbitalName");
608
635
  await this.processOrbitalEvent(orbitalName, {
609
636
  event: listener.triggers,
637
+ eventId: listener.triggersId,
610
638
  payload: mappedPayload,
611
639
  entityId: forwardedEntityId
612
640
  });
@@ -812,7 +840,7 @@ var OrbitalServerRuntime = class {
812
840
  const fields = entity.fields.filter(
813
841
  (f) => typeof f.name === "string" && f.name.length > 0
814
842
  );
815
- this.persistence.registerEntity({ name: entity.name, fields });
843
+ this.persistence.registerEntity({ name: entity.name, id: entity.id, fields });
816
844
  }
817
845
  }
818
846
  }
@@ -871,7 +899,7 @@ var OrbitalServerRuntime = class {
871
899
  request.payload?.["_activeTraits"] ?? null
872
900
  )
873
901
  }));
874
- const { event, payload, entityId, user } = request;
902
+ const { event, eventId, payload, entityId, user } = request;
875
903
  const validationFailures = [];
876
904
  for (const trait of registered.traits) {
877
905
  const eventSchema = trait.stateMachine?.events?.find((e) => e.key === event);
@@ -920,7 +948,8 @@ var OrbitalServerRuntime = class {
920
948
  event,
921
949
  cleanPayload,
922
950
  entityData,
923
- entityByTrait
951
+ entityByTrait,
952
+ eventId
924
953
  );
925
954
  const filteredResults = activeTraits && activeTraits.length > 0 ? results.filter(({ traitName }) => activeTraits.includes(traitName)) : results;
926
955
  if (this.config.debug && activeTraits) {
@@ -1008,11 +1037,22 @@ var OrbitalServerRuntime = class {
1008
1037
  sourceTrait: source?.trait
1009
1038
  }));
1010
1039
  }
1040
+ const emittingTrait = registered.traits.find((t) => t.name === traitName);
1041
+ const emitContract = emittingTrait?.emits?.find((e) => e.event === event);
1011
1042
  const stamp = source ?? {
1012
1043
  orbital: registered.schema.name,
1013
1044
  trait: traitName
1014
1045
  };
1015
- this.eventBus.emit(event, eventPayload, stamp);
1046
+ if (stamp.orbitalId === void 0 && registered.schema.id !== void 0) {
1047
+ stamp.orbitalId = registered.schema.id;
1048
+ }
1049
+ if (stamp.traitId === void 0 && emittingTrait?.id !== void 0) {
1050
+ stamp.traitId = emittingTrait.id;
1051
+ }
1052
+ if (stamp.eventId === void 0 && emitContract?.eventId !== void 0) {
1053
+ stamp.eventId = emitContract.eventId;
1054
+ }
1055
+ this.eventBus.emit(event, eventPayload, stamp, eventRouteKey(event, stamp.eventId));
1016
1056
  const emittedItem = { event, payload: eventPayload, source: stamp };
1017
1057
  emittedEvents.push(emittedItem);
1018
1058
  onPush?.({ type: "event", data: emittedItem });
@@ -1683,7 +1723,15 @@ var OrbitalServerRuntime = class {
1683
1723
  continue;
1684
1724
  }
1685
1725
  const foreignKeyField = relationField.name;
1686
- const relatedEntityType = relationField.relation.entity;
1726
+ let relatedEntityType = relationField.relation.entity;
1727
+ if (relationField.relation.entityId) {
1728
+ for (const registered of this.orbitals.values()) {
1729
+ if (registered.entity.id === relationField.relation.entityId) {
1730
+ relatedEntityType = registered.entity.name;
1731
+ break;
1732
+ }
1733
+ }
1734
+ }
1687
1735
  const cardinality = relationField.relation.cardinality || "one";
1688
1736
  const foreignKeyIds = /* @__PURE__ */ new Set();
1689
1737
  for (const entity of entities) {
@@ -1921,7 +1969,7 @@ function parseListenSource(listener, listenerOrbital) {
1921
1969
  if (explicit && typeof explicit === "object") {
1922
1970
  return {
1923
1971
  bareEvent: listener.event,
1924
- matcher: buildMatcher(explicit, listenerOrbital)
1972
+ matcher: buildSourceMatcher(explicit, listenerOrbital)
1925
1973
  };
1926
1974
  }
1927
1975
  const key = listener.event;
@@ -1936,7 +1984,7 @@ function parseListenSource(listener, listenerOrbital) {
1936
1984
  }
1937
1985
  return {
1938
1986
  bareEvent: eventName,
1939
- matcher: buildMatcher(
1987
+ matcher: buildSourceMatcher(
1940
1988
  { kind: "trait", trait: sourceOrStar },
1941
1989
  listenerOrbital
1942
1990
  )
@@ -1948,20 +1996,10 @@ function parseListenSource(listener, listenerOrbital) {
1948
1996
  const orbital = parts.slice(0, parts.length - 2).join(".");
1949
1997
  return {
1950
1998
  bareEvent: eventName,
1951
- matcher: buildMatcher({ kind: "orbital", orbital, trait }, listenerOrbital)
1999
+ matcher: buildSourceMatcher({ kind: "orbital", orbital, trait }, listenerOrbital)
1952
2000
  };
1953
2001
  }
1954
2002
  return { bareEvent: key, matcher: () => true };
1955
2003
  }
1956
- function buildMatcher(src, listenerOrbital) {
1957
- if (src.kind === "any") return () => true;
1958
- if (src.kind === "trait") {
1959
- const wantedTrait2 = src.trait;
1960
- return (source) => !!source && source.orbital === listenerOrbital && source.trait === wantedTrait2;
1961
- }
1962
- const wantedOrbital = src.orbital;
1963
- const wantedTrait = src.trait;
1964
- return (source) => !!source && source.orbital === wantedOrbital && source.trait === wantedTrait;
1965
- }
1966
2004
 
1967
2005
  export { OrbitalServerRuntime, createOrbitalServerRuntime };
@@ -1,4 +1,4 @@
1
- import { I as IEventBus } from './types-ConZnrpe.js';
1
+ import { I as IEventBus } from './types-C8RsO0xa.js';
2
2
  import { EventPayload } from '@almadar/core';
3
3
 
4
4
  /**