@almadar/runtime 5.0.0 → 5.2.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,5 +1,5 @@
1
1
  import { Router } from 'express';
2
- import { I as IEventBus, g as RuntimeEvent, f as EventListener, U as Unsubscribe, T as TraitDefinition, R as RuntimeConfig, i as TransitionObserver, h as TraitState, j as TransitionResult, E as EvaluationContextExtensions, a as EffectHandlers } from './types-DwDhc9Jt.js';
2
+ import { I as IEventBus, g as RuntimeEvent, f as EventListener, U as Unsubscribe, T as TraitDefinition, R as RuntimeConfig, i as TransitionObserver, C as ConfigContext, h as TraitState, j as TransitionResult, E as EvaluationContextExtensions, a as EffectHandlers } from './types-SmmabGZk.js';
3
3
  import { EventPayload, EntityRow, OrbitalSchema, Orbital, Trait, OrbitalDefinition, Entity, TraitConfig, TraitTick } from '@almadar/core';
4
4
 
5
5
  /**
@@ -121,6 +121,17 @@ interface ProcessEventOptions {
121
121
  payload?: EventPayload;
122
122
  /** Entity data for binding resolution */
123
123
  entityData?: EntityRow;
124
+ /**
125
+ * Trait config for `@config.X` resolution inside guard expressions.
126
+ * Surfaced on the EvaluationContext so guards can write mode-aware
127
+ * predicates — e.g. std-modal's OPEN can require `@payload.row` only
128
+ * when `@config.mode === "edit"`. The validator (sigil_context.rs)
129
+ * allows `@config` in guard context as of v3.12.0; this field is
130
+ * the runtime side of the same contract. Threaded by the caller
131
+ * (typically `OrbitalServerRuntime.processEvent` reading from the
132
+ * trait's `RegisteredOrbital.configByTrait`).
133
+ */
134
+ config?: ConfigContext;
124
135
  /**
125
136
  * Guard evaluation error handling mode. (RCG-02)
126
137
  * - "permissive": Guard errors allow the transition (default, backwards-compatible)
@@ -169,6 +180,15 @@ interface ProcessEventOptions {
169
180
  declare function processEvent(options: ProcessEventOptions): TransitionResult;
170
181
  declare class StateMachineManager {
171
182
  private traits;
183
+ /**
184
+ * Per-trait call-site config, surfaced to guard expressions so
185
+ * `@config.X` resolves at runtime. Populated by the orbital's
186
+ * registration step (see `OrbitalServerRuntime.registerOrbital`'s
187
+ * `configByTrait` projection). Empty for atom-scope traits whose
188
+ * call-site config wasn't supplied — guards that read `@config.X`
189
+ * in that case will see `undefined` and short-circuit accordingly.
190
+ */
191
+ private traitConfigs;
172
192
  /**
173
193
  * State map keyed by `${traitName}::${entityId | __singleton__}`.
174
194
  *
@@ -198,6 +218,13 @@ declare class StateMachineManager {
198
218
  * Add a trait to the manager.
199
219
  */
200
220
  addTrait(trait: TraitDefinition): void;
221
+ /**
222
+ * Bind the call-site config for a trait so guard `@config.X`
223
+ * resolves at runtime. Typically called by the orbital
224
+ * registration step right after `addTrait`. Idempotent; passing
225
+ * `undefined` clears the binding.
226
+ */
227
+ setTraitConfig(traitName: string, config: ConfigContext | undefined): void;
201
228
  /**
202
229
  * Remove a trait from the manager.
203
230
  */
@@ -1,4 +1,4 @@
1
1
  import 'express';
2
- export { C as EffectResult, e as InMemoryPersistence, D as LoaderConfig, F as LocalPersistenceAdapter, O as OrbitalEventRequest, f as OrbitalEventResponse, G as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, H as RuntimeTraitTick, J as createOrbitalServerRuntime } from './OrbitalServerRuntime-D-b_dg8I.js';
3
- import './types-DwDhc9Jt.js';
2
+ export { C as EffectResult, e as InMemoryPersistence, D as LoaderConfig, F as LocalPersistenceAdapter, O as OrbitalEventRequest, f as OrbitalEventResponse, G as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, H as RuntimeTraitTick, J as createOrbitalServerRuntime } from './OrbitalServerRuntime-BrJ7m0hz.js';
3
+ import './types-SmmabGZk.js';
4
4
  import '@almadar/core';
@@ -1,5 +1,5 @@
1
- import { EventBus, createUnifiedLoader, MockPersistenceAdapter, InMemoryPersistence, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-S5OLFFHT.js';
2
- export { InMemoryPersistence } from './chunk-S5OLFFHT.js';
1
+ import { createLogger, EventBus, createUnifiedLoader, MockPersistenceAdapter, InMemoryPersistence, preprocessSchema, StateMachineManager, createContextFromBindings, validateEventPayload, formatPayloadValidationError, EffectExecutor } from './chunk-OG2NHXES.js';
2
+ export { InMemoryPersistence } from './chunk-OG2NHXES.js';
3
3
  import './chunk-PZ5AY32C.js';
4
4
  import { Router } from 'express';
5
5
  import * as fs from 'fs';
@@ -359,6 +359,8 @@ function createOsHandlers(ctx) {
359
359
  }
360
360
 
361
361
  // src/OrbitalServerRuntime.ts
362
+ var effectLog = createLogger("almadar:runtime:effects");
363
+ var renderLog = createLogger("almadar:runtime:render-ui");
362
364
  function collectDeclaredConfigDefaults(trait) {
363
365
  if (!trait) return void 0;
364
366
  const schema = trait.config;
@@ -751,6 +753,9 @@ var OrbitalServerRuntime = class {
751
753
  const manager = new StateMachineManager(traitDefs, {
752
754
  contextExtensions: this.config.contextExtensions
753
755
  });
756
+ for (const [traitName, traitConfig] of configByTrait) {
757
+ manager.setTraitConfig(traitName, traitConfig);
758
+ }
754
759
  const entityRef = orbital.entity;
755
760
  let entity;
756
761
  if (typeof entityRef === "string") {
@@ -1096,7 +1101,35 @@ var OrbitalServerRuntime = class {
1096
1101
  error: `Orbital not found: ${orbitalName}`
1097
1102
  };
1098
1103
  }
1104
+ const payloadRow = request.payload?.["row"];
1105
+ const payloadRowAsPayload = payloadRow !== null && typeof payloadRow === "object" && !Array.isArray(payloadRow) ? payloadRow : void 0;
1106
+ const payloadRowId = payloadRowAsPayload?.["id"];
1107
+ renderLog.debug("processOrbitalEvent:enter", {
1108
+ orbital: orbitalName,
1109
+ event: request.event,
1110
+ hasPayloadRow: payloadRowAsPayload !== void 0,
1111
+ payloadRowId: typeof payloadRowId === "string" || typeof payloadRowId === "number" ? payloadRowId : void 0,
1112
+ entityId: request.entityId
1113
+ });
1099
1114
  const { event, payload, entityId, user } = request;
1115
+ const validationFailures = [];
1116
+ for (const trait of registered.traits) {
1117
+ const eventSchema = trait.stateMachine?.events?.find((e) => e.key === event);
1118
+ if (eventSchema?.payloadSchema && eventSchema.payloadSchema.length > 0) {
1119
+ validationFailures.push(
1120
+ ...validateEventPayload(event, payload, eventSchema.payloadSchema)
1121
+ );
1122
+ }
1123
+ }
1124
+ if (validationFailures.length > 0) {
1125
+ return {
1126
+ success: false,
1127
+ transitioned: false,
1128
+ states: {},
1129
+ emittedEvents: [],
1130
+ error: formatPayloadValidationError(validationFailures)
1131
+ };
1132
+ }
1100
1133
  const emittedEvents = [];
1101
1134
  const fetchedData = {};
1102
1135
  const clientEffects = [];
@@ -1191,6 +1224,12 @@ var OrbitalServerRuntime = class {
1191
1224
  };
1192
1225
  this.eventBus.emit(event, eventPayload, stamp);
1193
1226
  emittedEvents.push({ event, payload: eventPayload });
1227
+ effectLog.debug("emit:push", {
1228
+ event,
1229
+ cumulativeEmittedCount: emittedEvents.length,
1230
+ sourceTrait: stamp.trait,
1231
+ sourceOrbital: stamp.orbital
1232
+ });
1194
1233
  },
1195
1234
  set: async (targetId, field, value) => {
1196
1235
  const id = targetId || entityId;
@@ -1289,6 +1328,7 @@ var OrbitalServerRuntime = class {
1289
1328
  }
1290
1329
  const type = targetEntityType || entityType;
1291
1330
  let resultData;
1331
+ const sizeBefore = (await this.persistence.list(type)).length;
1292
1332
  try {
1293
1333
  if (action === "create" || action === "update") {
1294
1334
  this.validateRelationCardinality(type, data || {});
@@ -1319,6 +1359,15 @@ var OrbitalServerRuntime = class {
1319
1359
  break;
1320
1360
  }
1321
1361
  }
1362
+ const sizeAfter = (await this.persistence.list(type)).length;
1363
+ effectLog.debug("persist:store-mutate", {
1364
+ action,
1365
+ entityType: type,
1366
+ resultId: resultData?.id,
1367
+ sizeBefore,
1368
+ sizeAfter,
1369
+ delta: sizeAfter - sizeBefore
1370
+ });
1322
1371
  effectResults.push({
1323
1372
  effect: "persist",
1324
1373
  action,
@@ -1327,6 +1376,11 @@ var OrbitalServerRuntime = class {
1327
1376
  success: true
1328
1377
  });
1329
1378
  } catch (err) {
1379
+ effectLog.error("persist:store-mutate-error", {
1380
+ action,
1381
+ entityType: type,
1382
+ error: err instanceof Error ? err.message : String(err)
1383
+ });
1330
1384
  effectResults.push({
1331
1385
  effect: "persist",
1332
1386
  action,
@@ -1555,6 +1609,17 @@ var OrbitalServerRuntime = class {
1555
1609
  },
1556
1610
  // Client-side effects - collect for forwarding to client
1557
1611
  renderUI: (slot, pattern, props, priority) => {
1612
+ const patternNode = pattern !== null && typeof pattern === "object" && !Array.isArray(pattern) ? pattern : null;
1613
+ const patternEntity = patternNode?.entity;
1614
+ const entityRow = patternEntity !== null && typeof patternEntity === "object" && !Array.isArray(patternEntity) ? patternEntity : null;
1615
+ const patternTypeRaw = patternNode?.["type"];
1616
+ renderLog.debug("renderUI:push", {
1617
+ trait: traitName,
1618
+ slot,
1619
+ patternType: typeof patternTypeRaw === "string" ? patternTypeRaw : void 0,
1620
+ entityRowId: typeof entityRow?.id === "string" ? entityRow.id : void 0,
1621
+ entityIsObject: entityRow !== null
1622
+ });
1558
1623
  pushClientEffect(["render-ui", slot, pattern, props, priority]);
1559
1624
  },
1560
1625
  navigate: (path2, params) => {