@almadar/runtime 3.3.0 → 4.1.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/dist/{OrbitalServerRuntime-DMRvEfcT.d.ts → OrbitalServerRuntime-DXMHHVZI.d.ts} +28 -9
- package/dist/OrbitalServerRuntime.d.ts +2 -2
- package/dist/OrbitalServerRuntime.js +162 -39
- package/dist/OrbitalServerRuntime.js.map +1 -1
- package/dist/ServerBridge.d.ts +1 -1
- package/dist/{chunk-II3JSETH.js → chunk-Z72NLOSF.js} +15 -12
- package/dist/chunk-Z72NLOSF.js.map +1 -0
- package/dist/{external-loader-UBJ6VRW5.js → external-loader-22F5V5NN.js} +28 -13
- package/dist/external-loader-22F5V5NN.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +1 -1
- package/dist/{types-B8OfRFfV.d.ts → types-CVSBlnzV.d.ts} +15 -2
- package/package.json +7 -7
- package/dist/chunk-II3JSETH.js.map +0 -1
- package/dist/external-loader-UBJ6VRW5.js.map +0 -1
|
@@ -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-
|
|
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-CVSBlnzV.js';
|
|
3
3
|
import { EventPayload, EntityRow, OrbitalSchema, Orbital, Trait, OrbitalDefinition, Entity, TraitTick } from '@almadar/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -748,14 +748,16 @@ interface OrbitalEventResponse {
|
|
|
748
748
|
success: boolean;
|
|
749
749
|
transitioned: boolean;
|
|
750
750
|
states: Record<string, string>;
|
|
751
|
+
/**
|
|
752
|
+
* Events emitted during processing, in declaration order. Payloads are
|
|
753
|
+
* typed against `@almadar/core`'s `EventPayload` — the recursive record of
|
|
754
|
+
* primitive + nested EventPayload values the state machine already uses
|
|
755
|
+
* internally. Kept as the single source of truth for emit-payload shape.
|
|
756
|
+
*/
|
|
751
757
|
emittedEvents: Array<{
|
|
752
758
|
event: string;
|
|
753
|
-
payload?:
|
|
759
|
+
payload?: EventPayload;
|
|
754
760
|
}>;
|
|
755
|
-
/** Entity data fetched by `fetch` effects - keyed by entity type */
|
|
756
|
-
data?: {
|
|
757
|
-
[entityType: string]: EntityRow | EntityRow[];
|
|
758
|
-
};
|
|
759
761
|
/** Client-side effects to execute (render-ui, navigate, notify) */
|
|
760
762
|
clientEffects?: Array<unknown>;
|
|
761
763
|
/**
|
|
@@ -883,13 +885,30 @@ declare class OrbitalServerRuntime {
|
|
|
883
885
|
private osHandlers;
|
|
884
886
|
private localPersistence;
|
|
885
887
|
constructor(config?: OrbitalServerRuntimeConfig);
|
|
888
|
+
/**
|
|
889
|
+
* Lazily construct a default loader when the caller didn't provide one
|
|
890
|
+
* but `register()` needs to preprocess. Looks for `@almadar/std` in the
|
|
891
|
+
* nearest `node_modules` so cross-orbital `std/behaviors/<name>` imports
|
|
892
|
+
* resolve to the tiered registry on disk.
|
|
893
|
+
*
|
|
894
|
+
* Node only — browsers should receive already-preprocessed schemas from
|
|
895
|
+
* their server.
|
|
896
|
+
*/
|
|
897
|
+
private ensureLoader;
|
|
886
898
|
/**
|
|
887
899
|
* Register an OrbitalSchema for execution.
|
|
888
900
|
*
|
|
889
|
-
*
|
|
890
|
-
*
|
|
901
|
+
* Auto-preprocesses the schema when it contains `uses` declarations or
|
|
902
|
+
* unresolved cross-orbital trait references (e.g. a trait with
|
|
903
|
+
* `ref: "Modal.traits.ModalRecordModal"` and no inline `stateMachine`).
|
|
904
|
+
* Without preprocessing, those refs arrive empty at the state machine and
|
|
905
|
+
* button clicks silently do nothing — see Phase 9.5.H.
|
|
891
906
|
*
|
|
892
|
-
*
|
|
907
|
+
* Preprocessing needs a loader. If `loaderConfig` is set, that loader is
|
|
908
|
+
* used. Otherwise, a default loader is constructed that points at
|
|
909
|
+
* `<cwd>` (for `basePath`) and the nearest `node_modules/@almadar/std` (for
|
|
910
|
+
* `stdLibPath`), which matches how every caller in this monorepo has the
|
|
911
|
+
* std registry on disk.
|
|
893
912
|
*/
|
|
894
913
|
register(schema: OrbitalSchema): Promise<void>;
|
|
895
914
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import 'express';
|
|
2
|
-
export { B as EffectResult, C as LoaderConfig, D as LocalPersistenceAdapter, O as OrbitalEventRequest, e as OrbitalEventResponse, F as OrbitalServerRuntime, f as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, k as RuntimeOrbital, l as RuntimeOrbitalSchema, m as RuntimeTrait, G as RuntimeTraitTick, H as createOrbitalServerRuntime } from './OrbitalServerRuntime-
|
|
3
|
-
import './types-
|
|
2
|
+
export { B as EffectResult, C as LoaderConfig, D as LocalPersistenceAdapter, O as OrbitalEventRequest, e as OrbitalEventResponse, F as OrbitalServerRuntime, f as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, k as RuntimeOrbital, l as RuntimeOrbitalSchema, m as RuntimeTrait, G as RuntimeTraitTick, H as createOrbitalServerRuntime } from './OrbitalServerRuntime-DXMHHVZI.js';
|
|
3
|
+
import './types-CVSBlnzV.js';
|
|
4
4
|
import '@almadar/core';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventBus, createUnifiedLoader, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-
|
|
1
|
+
import { EventBus, createUnifiedLoader, preprocessSchema, StateMachineManager, createContextFromBindings, EffectExecutor } from './chunk-Z72NLOSF.js';
|
|
2
2
|
import './chunk-PZ5AY32C.js';
|
|
3
3
|
import { Router } from 'express';
|
|
4
4
|
import * as fs from 'fs';
|
|
@@ -649,6 +649,23 @@ var InMemoryPersistence = class {
|
|
|
649
649
|
return collection ? Array.from(collection.values()) : [];
|
|
650
650
|
}
|
|
651
651
|
};
|
|
652
|
+
function needsPreprocessing(schema) {
|
|
653
|
+
for (const orbital of schema.orbitals) {
|
|
654
|
+
const uses = orbital.uses;
|
|
655
|
+
if (Array.isArray(uses) && uses.length > 0) {
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
const traits = orbital.traits ?? [];
|
|
659
|
+
for (const t of traits) {
|
|
660
|
+
if (!t || typeof t !== "object") continue;
|
|
661
|
+
const obj = t;
|
|
662
|
+
if (typeof obj.ref === "string" && obj.ref.includes(".") && !obj.stateMachine) {
|
|
663
|
+
return true;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
652
669
|
var OrbitalServerRuntime = class {
|
|
653
670
|
orbitals = /* @__PURE__ */ new Map();
|
|
654
671
|
eventBus;
|
|
@@ -701,21 +718,102 @@ var OrbitalServerRuntime = class {
|
|
|
701
718
|
...this.config.effectHandlers
|
|
702
719
|
};
|
|
703
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Lazily construct a default loader when the caller didn't provide one
|
|
723
|
+
* but `register()` needs to preprocess. Looks for `@almadar/std` in the
|
|
724
|
+
* nearest `node_modules` so cross-orbital `std/behaviors/<name>` imports
|
|
725
|
+
* resolve to the tiered registry on disk.
|
|
726
|
+
*
|
|
727
|
+
* Node only — browsers should receive already-preprocessed schemas from
|
|
728
|
+
* their server.
|
|
729
|
+
*/
|
|
730
|
+
async ensureLoader() {
|
|
731
|
+
if (this.loader) return;
|
|
732
|
+
if (typeof process === "undefined" || !process.versions?.node) {
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
try {
|
|
736
|
+
const [{ createRequire }, path2] = await Promise.all([
|
|
737
|
+
import('module'),
|
|
738
|
+
import('path')
|
|
739
|
+
]);
|
|
740
|
+
const require2 = createRequire(import.meta.url);
|
|
741
|
+
const stdPkgJson = require2.resolve("@almadar/std/package.json");
|
|
742
|
+
const stdLibPath = path2.dirname(stdPkgJson);
|
|
743
|
+
const basePath = this.config.loaderConfig?.basePath ?? process.cwd();
|
|
744
|
+
this.loader = createUnifiedLoader({
|
|
745
|
+
basePath,
|
|
746
|
+
stdLibPath,
|
|
747
|
+
scopedPaths: this.config.loaderConfig?.scopedPaths
|
|
748
|
+
});
|
|
749
|
+
if (this.config.debug) {
|
|
750
|
+
console.log(
|
|
751
|
+
`[OrbitalRuntime] Default loader constructed: basePath=${basePath} stdLibPath=${stdLibPath}`
|
|
752
|
+
);
|
|
753
|
+
}
|
|
754
|
+
} catch (err) {
|
|
755
|
+
if (this.config.debug) {
|
|
756
|
+
console.warn(
|
|
757
|
+
`[OrbitalRuntime] Could not auto-construct loader: ${err instanceof Error ? err.message : String(err)}`
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
704
762
|
// ==========================================================================
|
|
705
763
|
// Schema Registration
|
|
706
764
|
// ==========================================================================
|
|
707
765
|
/**
|
|
708
766
|
* Register an OrbitalSchema for execution.
|
|
709
767
|
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
768
|
+
* Auto-preprocesses the schema when it contains `uses` declarations or
|
|
769
|
+
* unresolved cross-orbital trait references (e.g. a trait with
|
|
770
|
+
* `ref: "Modal.traits.ModalRecordModal"` and no inline `stateMachine`).
|
|
771
|
+
* Without preprocessing, those refs arrive empty at the state machine and
|
|
772
|
+
* button clicks silently do nothing — see Phase 9.5.H.
|
|
712
773
|
*
|
|
713
|
-
*
|
|
774
|
+
* Preprocessing needs a loader. If `loaderConfig` is set, that loader is
|
|
775
|
+
* used. Otherwise, a default loader is constructed that points at
|
|
776
|
+
* `<cwd>` (for `basePath`) and the nearest `node_modules/@almadar/std` (for
|
|
777
|
+
* `stdLibPath`), which matches how every caller in this monorepo has the
|
|
778
|
+
* std registry on disk.
|
|
714
779
|
*/
|
|
715
780
|
async register(schema) {
|
|
716
781
|
if (this.config.debug) {
|
|
717
782
|
console.log(`[OrbitalRuntime] Registering schema: ${schema.name}`);
|
|
718
783
|
}
|
|
784
|
+
if (needsPreprocessing(schema)) {
|
|
785
|
+
await this.ensureLoader();
|
|
786
|
+
if (this.loader) {
|
|
787
|
+
if (this.config.debug) {
|
|
788
|
+
console.log(`[OrbitalRuntime] Schema has uses/refs \u2014 auto-preprocessing`);
|
|
789
|
+
}
|
|
790
|
+
const result = await preprocessSchema(schema, {
|
|
791
|
+
basePath: this.config.loaderConfig?.basePath || process.cwd(),
|
|
792
|
+
stdLibPath: this.config.loaderConfig?.stdLibPath,
|
|
793
|
+
scopedPaths: this.config.loaderConfig?.scopedPaths,
|
|
794
|
+
loader: this.loader,
|
|
795
|
+
namespaceEvents: this.config.namespaceEvents
|
|
796
|
+
});
|
|
797
|
+
if (!result.success) {
|
|
798
|
+
throw new Error(
|
|
799
|
+
`Schema preprocessing failed: ${result.errors.join("; ")}`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
schema = result.data.schema;
|
|
803
|
+
this.entitySharingMap = {
|
|
804
|
+
...this.entitySharingMap,
|
|
805
|
+
...result.data.entitySharing
|
|
806
|
+
};
|
|
807
|
+
this.eventNamespaceMap = {
|
|
808
|
+
...this.eventNamespaceMap,
|
|
809
|
+
...result.data.eventNamespaces
|
|
810
|
+
};
|
|
811
|
+
} else if (this.config.debug) {
|
|
812
|
+
console.warn(
|
|
813
|
+
`[OrbitalRuntime] Schema has uses/refs but no loader available \u2014 proceeding without preprocessing. Cross-orbital trait refs will be empty.`
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
}
|
|
719
817
|
for (const orbital of schema.orbitals) {
|
|
720
818
|
await this.registerOrbitalAsync(orbital);
|
|
721
819
|
}
|
|
@@ -953,10 +1051,12 @@ var OrbitalServerRuntime = class {
|
|
|
953
1051
|
for (const trait of registered.traits) {
|
|
954
1052
|
if (!trait.listens) continue;
|
|
955
1053
|
for (const listener of trait.listens) {
|
|
956
|
-
const
|
|
1054
|
+
const { bareEvent, matcher } = parseListenSource(listener, orbitalName);
|
|
1055
|
+
const cleanup = this.eventBus.on(bareEvent, async (event) => {
|
|
1056
|
+
if (!matcher(event.source)) return;
|
|
957
1057
|
if (this.config.debug) {
|
|
958
1058
|
console.log(
|
|
959
|
-
`[OrbitalRuntime] ${orbitalName}.${trait.name} received: ${listener.event}`
|
|
1059
|
+
`[OrbitalRuntime] ${orbitalName}.${trait.name} received: ${listener.event} (from ${event.source?.orbital ?? "?"}.${event.source?.trait ?? "?"})`
|
|
960
1060
|
);
|
|
961
1061
|
}
|
|
962
1062
|
let mappedPayload = event.payload;
|
|
@@ -1223,32 +1323,6 @@ var OrbitalServerRuntime = class {
|
|
|
1223
1323
|
);
|
|
1224
1324
|
}
|
|
1225
1325
|
}
|
|
1226
|
-
const persistedTypes = /* @__PURE__ */ new Set();
|
|
1227
|
-
for (const er of effectResults) {
|
|
1228
|
-
if ((er.effect === "persist" || er.effect === "set" || er.effect === "swap") && er.success && er.entityType) {
|
|
1229
|
-
persistedTypes.add(er.entityType);
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
const refTypes = /* @__PURE__ */ new Set();
|
|
1233
|
-
for (const trait of registered.traits) {
|
|
1234
|
-
const transitions = trait.stateMachine?.transitions ?? [];
|
|
1235
|
-
for (const trans of transitions) {
|
|
1236
|
-
for (const eff of trans.effects ?? []) {
|
|
1237
|
-
if (Array.isArray(eff) && eff[0] === "ref" && typeof eff[1] === "string") {
|
|
1238
|
-
refTypes.add(eff[1]);
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
for (const mutatedEntityType of persistedTypes) {
|
|
1244
|
-
if (refTypes.has(mutatedEntityType)) {
|
|
1245
|
-
try {
|
|
1246
|
-
const fresh = await this.persistence.list(mutatedEntityType);
|
|
1247
|
-
fetchedData[mutatedEntityType] = fresh;
|
|
1248
|
-
} catch {
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
1326
|
const states = {};
|
|
1253
1327
|
for (const [name, state] of registered.manager.getAllStates()) {
|
|
1254
1328
|
states[name] = state.currentState;
|
|
@@ -1259,9 +1333,6 @@ var OrbitalServerRuntime = class {
|
|
|
1259
1333
|
states,
|
|
1260
1334
|
emittedEvents
|
|
1261
1335
|
};
|
|
1262
|
-
if (Object.keys(fetchedData).length > 0) {
|
|
1263
|
-
response.data = fetchedData;
|
|
1264
|
-
}
|
|
1265
1336
|
if (clientEffects.length > 0) {
|
|
1266
1337
|
response.clientEffects = clientEffects;
|
|
1267
1338
|
}
|
|
@@ -1285,11 +1356,15 @@ var OrbitalServerRuntime = class {
|
|
|
1285
1356
|
let bindingsRef = null;
|
|
1286
1357
|
let contextRef = null;
|
|
1287
1358
|
const handlers = {
|
|
1288
|
-
emit: (event, eventPayload) => {
|
|
1359
|
+
emit: (event, eventPayload, source) => {
|
|
1289
1360
|
if (this.config.debug) {
|
|
1290
|
-
console.log(`[OrbitalRuntime] Emitting: ${event}`, eventPayload);
|
|
1361
|
+
console.log(`[OrbitalRuntime] Emitting: ${event}`, eventPayload, source);
|
|
1291
1362
|
}
|
|
1292
|
-
|
|
1363
|
+
const stamp = source ?? {
|
|
1364
|
+
orbital: registered.schema.name,
|
|
1365
|
+
trait: traitName
|
|
1366
|
+
};
|
|
1367
|
+
this.eventBus.emit(event, eventPayload, stamp);
|
|
1293
1368
|
emittedEvents.push({ event, payload: eventPayload });
|
|
1294
1369
|
},
|
|
1295
1370
|
set: async (targetId, field, value) => {
|
|
@@ -1623,7 +1698,7 @@ var OrbitalServerRuntime = class {
|
|
|
1623
1698
|
const atomicExecutor = new EffectExecutor({
|
|
1624
1699
|
handlers,
|
|
1625
1700
|
bindings: bindingsRef ?? {},
|
|
1626
|
-
context: contextRef ?? { traitName, state: "unknown", transition: "unknown" },
|
|
1701
|
+
context: contextRef ?? { traitName, orbitalName: registered.schema.name, state: "unknown", transition: "unknown" },
|
|
1627
1702
|
debug: this.config.debug,
|
|
1628
1703
|
contextExtensions: this.config.contextExtensions
|
|
1629
1704
|
});
|
|
@@ -1684,6 +1759,7 @@ var OrbitalServerRuntime = class {
|
|
|
1684
1759
|
bindingsRef = bindings;
|
|
1685
1760
|
const context = {
|
|
1686
1761
|
traitName,
|
|
1762
|
+
orbitalName: registered.schema.name,
|
|
1687
1763
|
state: state?.currentState || "unknown",
|
|
1688
1764
|
transition: "unknown",
|
|
1689
1765
|
entityId
|
|
@@ -2029,6 +2105,53 @@ var OrbitalServerRuntime = class {
|
|
|
2029
2105
|
function createOrbitalServerRuntime(config) {
|
|
2030
2106
|
return new OrbitalServerRuntime(config);
|
|
2031
2107
|
}
|
|
2108
|
+
function parseListenSource(listener, listenerOrbital) {
|
|
2109
|
+
const explicit = listener.source;
|
|
2110
|
+
if (explicit && typeof explicit === "object") {
|
|
2111
|
+
return {
|
|
2112
|
+
bareEvent: listener.event,
|
|
2113
|
+
matcher: buildMatcher(explicit, listenerOrbital)
|
|
2114
|
+
};
|
|
2115
|
+
}
|
|
2116
|
+
const key = listener.event;
|
|
2117
|
+
const parts = key.split(".");
|
|
2118
|
+
if (parts.length === 1) {
|
|
2119
|
+
return { bareEvent: key, matcher: () => true };
|
|
2120
|
+
}
|
|
2121
|
+
if (parts.length === 2) {
|
|
2122
|
+
const [sourceOrStar, eventName] = parts;
|
|
2123
|
+
if (sourceOrStar === "*") {
|
|
2124
|
+
return { bareEvent: eventName, matcher: () => true };
|
|
2125
|
+
}
|
|
2126
|
+
return {
|
|
2127
|
+
bareEvent: eventName,
|
|
2128
|
+
matcher: buildMatcher(
|
|
2129
|
+
{ kind: "trait", trait: sourceOrStar },
|
|
2130
|
+
listenerOrbital
|
|
2131
|
+
)
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
if (parts.length >= 3) {
|
|
2135
|
+
const eventName = parts[parts.length - 1];
|
|
2136
|
+
const trait = parts[parts.length - 2];
|
|
2137
|
+
const orbital = parts.slice(0, parts.length - 2).join(".");
|
|
2138
|
+
return {
|
|
2139
|
+
bareEvent: eventName,
|
|
2140
|
+
matcher: buildMatcher({ kind: "orbital", orbital, trait }, listenerOrbital)
|
|
2141
|
+
};
|
|
2142
|
+
}
|
|
2143
|
+
return { bareEvent: key, matcher: () => true };
|
|
2144
|
+
}
|
|
2145
|
+
function buildMatcher(src, listenerOrbital) {
|
|
2146
|
+
if (src.kind === "any") return () => true;
|
|
2147
|
+
if (src.kind === "trait") {
|
|
2148
|
+
const wantedTrait2 = src.trait;
|
|
2149
|
+
return (source) => !!source && source.orbital === listenerOrbital && source.trait === wantedTrait2;
|
|
2150
|
+
}
|
|
2151
|
+
const wantedOrbital = src.orbital;
|
|
2152
|
+
const wantedTrait = src.trait;
|
|
2153
|
+
return (source) => !!source && source.orbital === wantedOrbital && source.trait === wantedTrait;
|
|
2154
|
+
}
|
|
2032
2155
|
|
|
2033
2156
|
export { LocalPersistenceAdapter, OrbitalServerRuntime, createOrbitalServerRuntime };
|
|
2034
2157
|
//# sourceMappingURL=OrbitalServerRuntime.js.map
|