@almadar/runtime 6.42.0 → 6.44.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-C3TtYP6I.d.ts → OrbitalServerRuntime-Dz0oubQ_.d.ts} +9 -1
- package/dist/OrbitalServerRuntime.d.ts +1 -1
- package/dist/OrbitalServerRuntime.js +35 -6
- package/dist/{chunk-USANWPGZ.js → chunk-EJHMWSUS.js} +306 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +2 -2
- package/package.json +3 -3
|
@@ -316,7 +316,7 @@ declare class StateMachineManager {
|
|
|
316
316
|
*
|
|
317
317
|
* @returns Array of transition results (one per trait that had a matching transition)
|
|
318
318
|
*/
|
|
319
|
-
sendEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>, eventId?: EventId, targetTrait?: string, user?: UserContext): Array<{
|
|
319
|
+
sendEvent(eventKey: string, payload?: EventPayload, entityData?: EntityRow, entityByTrait?: Record<string, EntityRow>, eventId?: EventId, targetTrait?: string, user?: UserContext, allowedTraits?: ReadonlySet<string>): Array<{
|
|
320
320
|
traitName: string;
|
|
321
321
|
result: TransitionResult;
|
|
322
322
|
}>;
|
|
@@ -1199,6 +1199,14 @@ declare class OrbitalServerRuntime {
|
|
|
1199
1199
|
* std registry on disk.
|
|
1200
1200
|
*/
|
|
1201
1201
|
register(schema: OrbitalSchema): Promise<void>;
|
|
1202
|
+
/**
|
|
1203
|
+
* Teach the mock seeder which columns hold the viewer's id, derived from the
|
|
1204
|
+
* schema's `[identity]` entity. No-op for a program that declares none, so
|
|
1205
|
+
* unmigrated apps seed exactly as before. Mirrors
|
|
1206
|
+
* `orbital-core/src/runtime/seed.rs::owner_fields_from_schema` — a feature
|
|
1207
|
+
* that lives on only one execution path is not a feature.
|
|
1208
|
+
*/
|
|
1209
|
+
private applyIdentityOwnerFields;
|
|
1202
1210
|
/**
|
|
1203
1211
|
* Register an OrbitalSchema synchronously (for backward compatibility).
|
|
1204
1212
|
* Note: This version doesn't wait for instance seeding to complete.
|
|
@@ -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 LiveBroadcastItem, N as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, Q as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, T as RuntimeTraitTick, p as collectDeclaredConfigDefaults, V as createOrbitalServerRuntime } from './OrbitalServerRuntime-
|
|
2
|
+
export { F as ClientEffectTuple, G as ClientNavigateTuple, H as ClientNotifyTuple, J as ClientRenderUITuple, K as EffectResult, e as InMemoryPersistence, M as LiveBroadcastItem, N as LoaderConfig, O as OrbitalEventRequest, f as OrbitalEventResponse, Q as OrbitalServerRuntime, g as OrbitalServerRuntimeConfig, P as PersistenceAdapter, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, T as RuntimeTraitTick, p as collectDeclaredConfigDefaults, V as createOrbitalServerRuntime } from './OrbitalServerRuntime-Dz0oubQ_.js';
|
|
3
3
|
import './types-p_L8-Sk4.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-
|
|
2
|
-
export { InMemoryPersistence, collectDeclaredConfigDefaults } from './chunk-
|
|
1
|
+
import { createTickScheduler, EventBus, createUnifiedLoader, MockPersistenceAdapter, InMemoryPersistence, preprocessSchema, normalizeCallSiteConfigToValues, StateMachineManager, parseDurationString, createContextFromBindings, validateEventPayload, formatPayloadValidationError, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, collectDeclaredEntityDefaults, EffectExecutor } from './chunk-EJHMWSUS.js';
|
|
2
|
+
export { InMemoryPersistence, collectDeclaredConfigDefaults } from './chunk-EJHMWSUS.js';
|
|
3
3
|
import { isValidCronExpression } from './chunk-OU3ITB5S.js';
|
|
4
4
|
import './chunk-T4VDAB4C.js';
|
|
5
5
|
import './chunk-SCRAHWOC.js';
|
|
@@ -7,7 +7,8 @@ import './chunk-MLKGABMK.js';
|
|
|
7
7
|
import { createLogger } from '@almadar/logger';
|
|
8
8
|
import * as nodeModule from 'module';
|
|
9
9
|
import { evaluateListenPayloadExpr, evaluateGuard, evaluate } from '@almadar/evaluator';
|
|
10
|
-
import { buildResolvedTraitConfigs, isInlineTrait, isEntityCall, applyListenPayloadMapping, normalizeUserContext } from '@almadar/core';
|
|
10
|
+
import { DEFAULT_VIEWER, buildResolvedTraitConfigs, isInlineTrait, isEntityCall, applyListenPayloadMapping, normalizeUserContext } from '@almadar/core';
|
|
11
|
+
import { ownerFieldsFromSchema, identityEntityName } from '@almadar/core/mock';
|
|
11
12
|
|
|
12
13
|
// src/identity/routing.ts
|
|
13
14
|
function eventRouteKey(eventName, eventId) {
|
|
@@ -115,7 +116,12 @@ var OrbitalServerRuntime = class {
|
|
|
115
116
|
// Default to mock mode for preview
|
|
116
117
|
autoPreprocess: false,
|
|
117
118
|
namespaceEvents: true,
|
|
118
|
-
...config
|
|
119
|
+
...config,
|
|
120
|
+
// `@user` is never Null. A host that named no viewer (no ALMADAR_PERSONA,
|
|
121
|
+
// no auth yet) otherwise renders every `viewerName: @user.name` blank, so
|
|
122
|
+
// the app cannot say who you are. DEFAULT_VIEWER carries an empty `role`,
|
|
123
|
+
// so no `@user.role` guard changes outcome — see its doc in @almadar/core.
|
|
124
|
+
defaultUser: config.defaultUser ?? DEFAULT_VIEWER
|
|
119
125
|
};
|
|
120
126
|
this.eventBus = new EventBus();
|
|
121
127
|
if (config.loaderConfig?.loader) {
|
|
@@ -135,7 +141,9 @@ var OrbitalServerRuntime = class {
|
|
|
135
141
|
// Let the dev viewer own some seeded rows, so ownership-scoped views
|
|
136
142
|
// ("only mine") have data instead of being indistinguishable from a
|
|
137
143
|
// broken filter. Columns are declared, never inferred by name.
|
|
138
|
-
|
|
144
|
+
// `this.config`, not `config` — the DEFAULT_VIEWER fallback is applied
|
|
145
|
+
// there, and reading the raw param leaves every seeded row unowned.
|
|
146
|
+
ownerId: this.config.defaultUser?.id,
|
|
139
147
|
ownerFields: config.mockOwnerFields
|
|
140
148
|
});
|
|
141
149
|
if (config.debug) {
|
|
@@ -293,6 +301,7 @@ var OrbitalServerRuntime = class {
|
|
|
293
301
|
registerLog.warn("register:no-loader", { name: schema.name });
|
|
294
302
|
}
|
|
295
303
|
}
|
|
304
|
+
this.applyIdentityOwnerFields(schema);
|
|
296
305
|
for (const orbital of schema.orbitals) {
|
|
297
306
|
await this.registerOrbitalAsync(orbital);
|
|
298
307
|
}
|
|
@@ -301,6 +310,23 @@ var OrbitalServerRuntime = class {
|
|
|
301
310
|
this.resolvedSchema = schema;
|
|
302
311
|
this.resolvedTraitConfigs = buildResolvedTraitConfigs(schema);
|
|
303
312
|
}
|
|
313
|
+
/**
|
|
314
|
+
* Teach the mock seeder which columns hold the viewer's id, derived from the
|
|
315
|
+
* schema's `[identity]` entity. No-op for a program that declares none, so
|
|
316
|
+
* unmigrated apps seed exactly as before. Mirrors
|
|
317
|
+
* `orbital-core/src/runtime/seed.rs::owner_fields_from_schema` — a feature
|
|
318
|
+
* that lives on only one execution path is not a feature.
|
|
319
|
+
*/
|
|
320
|
+
applyIdentityOwnerFields(schema) {
|
|
321
|
+
if (!(this.persistence instanceof MockPersistenceAdapter)) return;
|
|
322
|
+
const derived = ownerFieldsFromSchema(schema);
|
|
323
|
+
if (derived.length === 0) return;
|
|
324
|
+
this.persistence.addOwnerFields(derived);
|
|
325
|
+
persistLog.debug("mock:identity-owner-fields", {
|
|
326
|
+
identity: identityEntityName(schema),
|
|
327
|
+
columns: derived
|
|
328
|
+
});
|
|
329
|
+
}
|
|
304
330
|
/**
|
|
305
331
|
* Register an OrbitalSchema synchronously (for backward compatibility).
|
|
306
332
|
* Note: This version doesn't wait for instance seeding to complete.
|
|
@@ -310,6 +336,7 @@ var OrbitalServerRuntime = class {
|
|
|
310
336
|
if (this.config.debug) {
|
|
311
337
|
registerLog.debug("register:schema-sync", { name: schema.name });
|
|
312
338
|
}
|
|
339
|
+
this.applyIdentityOwnerFields(schema);
|
|
313
340
|
for (const orbital of schema.orbitals) {
|
|
314
341
|
this.registerOrbital(orbital);
|
|
315
342
|
}
|
|
@@ -317,6 +344,7 @@ var OrbitalServerRuntime = class {
|
|
|
317
344
|
this.setupTicks();
|
|
318
345
|
this.resolvedSchema = schema;
|
|
319
346
|
this.resolvedTraitConfigs = buildResolvedTraitConfigs(schema);
|
|
347
|
+
this.applyIdentityOwnerFields(schema);
|
|
320
348
|
}
|
|
321
349
|
/**
|
|
322
350
|
* Returns the schema that this runtime is currently executing, post-
|
|
@@ -994,7 +1022,8 @@ var OrbitalServerRuntime = class {
|
|
|
994
1022
|
entityByTrait,
|
|
995
1023
|
eventId,
|
|
996
1024
|
targetTrait,
|
|
997
|
-
viewer
|
|
1025
|
+
viewer,
|
|
1026
|
+
activeTraits && activeTraits.length > 0 ? new Set(activeTraits) : void 0
|
|
998
1027
|
);
|
|
999
1028
|
const filteredResults = activeTraits && activeTraits.length > 0 ? results.filter(({ traitName }) => activeTraits.includes(traitName)) : results;
|
|
1000
1029
|
if (this.config.debug && activeTraits) {
|
|
@@ -962,11 +962,15 @@ var StateMachineManager = class {
|
|
|
962
962
|
*
|
|
963
963
|
* @returns Array of transition results (one per trait that had a matching transition)
|
|
964
964
|
*/
|
|
965
|
-
sendEvent(eventKey, payload, entityData, entityByTrait, eventId, targetTrait, user) {
|
|
965
|
+
sendEvent(eventKey, payload, entityData, entityByTrait, eventId, targetTrait, user, allowedTraits) {
|
|
966
966
|
const results = [];
|
|
967
967
|
const scope = scopeOf(entityData);
|
|
968
968
|
for (const [traitName, trait] of this.traits) {
|
|
969
|
-
if (targetTrait !== void 0
|
|
969
|
+
if (targetTrait !== void 0) {
|
|
970
|
+
if (traitName !== targetTrait) continue;
|
|
971
|
+
} else if (allowedTraits !== void 0 && !allowedTraits.has(traitName)) {
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
970
974
|
const traitState = this.getOrInitState(traitName, scope);
|
|
971
975
|
if (!traitState) continue;
|
|
972
976
|
const key = compositeKey(traitName, scope);
|
|
@@ -2342,6 +2346,22 @@ var MockPersistenceAdapter = class {
|
|
|
2342
2346
|
seedRandom(this.config.seed);
|
|
2343
2347
|
mockLog.debug("mock:adapter:init", { seed: this.config.seed });
|
|
2344
2348
|
}
|
|
2349
|
+
/**
|
|
2350
|
+
* Add owner columns discovered after construction.
|
|
2351
|
+
*
|
|
2352
|
+
* The adapter is built before any schema is registered, so schema-DERIVED
|
|
2353
|
+
* owner columns (relation fields pointing at the `[identity]` entity) can
|
|
2354
|
+
* only arrive later.
|
|
2355
|
+
*
|
|
2356
|
+
* ⚠️ Seeding is EAGER — `registerEntity()` seeds immediately — so callers must
|
|
2357
|
+
* supply these columns BEFORE registering any orbital. Calling this afterwards
|
|
2358
|
+
* silently stamps nothing.
|
|
2359
|
+
*/
|
|
2360
|
+
addOwnerFields(fields) {
|
|
2361
|
+
if (fields.length === 0) return;
|
|
2362
|
+
const merged = /* @__PURE__ */ new Set([...this.config.ownerFields ?? [], ...fields]);
|
|
2363
|
+
this.config.ownerFields = [...merged];
|
|
2364
|
+
}
|
|
2345
2365
|
/** Re-anchor the PRNG to the configured seed. Called before every
|
|
2346
2366
|
* re-seed loop so identical reseed sequences produce identical rows
|
|
2347
2367
|
* (timestamps + generated fields). Without this, the first
|
|
@@ -2418,6 +2438,9 @@ var MockPersistenceAdapter = class {
|
|
|
2418
2438
|
if (relationFields.length === 0) continue;
|
|
2419
2439
|
for (const row of store.values()) {
|
|
2420
2440
|
for (const field of relationFields) {
|
|
2441
|
+
if (this.config.ownerId !== void 0 && row[field.name] === this.config.ownerId) {
|
|
2442
|
+
continue;
|
|
2443
|
+
}
|
|
2421
2444
|
const targetNormalized = (field.relation.entityId && this.storeNameById.get(field.relation.entityId)) ?? field.relation.entity.toLowerCase();
|
|
2422
2445
|
const targetStore = this.stores.get(targetNormalized);
|
|
2423
2446
|
if (!targetStore || targetStore.size === 0) continue;
|
|
@@ -3638,6 +3661,96 @@ function renameEntityInEffect(effect, rename, props) {
|
|
|
3638
3661
|
}
|
|
3639
3662
|
return effect;
|
|
3640
3663
|
}
|
|
3664
|
+
var TRAIT_EMBED_PREFIX = "@trait.";
|
|
3665
|
+
function renameTraitEmbedsInValue(node, subs) {
|
|
3666
|
+
if (node === null || node === void 0) return node;
|
|
3667
|
+
if (typeof node === "string") {
|
|
3668
|
+
if (!node.startsWith(TRAIT_EMBED_PREFIX)) return node;
|
|
3669
|
+
const rest = node.slice(TRAIT_EMBED_PREFIX.length);
|
|
3670
|
+
const dot = rest.search(/[.[]/);
|
|
3671
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
3672
|
+
const suffix = dot === -1 ? "" : rest.slice(dot);
|
|
3673
|
+
const to = subs.get(name);
|
|
3674
|
+
return to === void 0 ? node : `${TRAIT_EMBED_PREFIX}${to}${suffix}`;
|
|
3675
|
+
}
|
|
3676
|
+
if (Array.isArray(node)) return node.map((item) => renameTraitEmbedsInValue(item, subs));
|
|
3677
|
+
if (typeof node !== "object") return node;
|
|
3678
|
+
const next = {};
|
|
3679
|
+
for (const [key, value] of Object.entries(node)) {
|
|
3680
|
+
next[key] = renameTraitEmbedsInValue(value, subs);
|
|
3681
|
+
}
|
|
3682
|
+
return next;
|
|
3683
|
+
}
|
|
3684
|
+
function renameTraitEmbeds(trait, subs) {
|
|
3685
|
+
if (subs.size === 0) return trait;
|
|
3686
|
+
const sm = trait.stateMachine;
|
|
3687
|
+
const next = { ...trait };
|
|
3688
|
+
if (sm) {
|
|
3689
|
+
next.stateMachine = {
|
|
3690
|
+
...sm,
|
|
3691
|
+
transitions: (sm.transitions ?? []).map(
|
|
3692
|
+
(t) => t.effects ? { ...t, effects: renameTraitEmbedsInValue(t.effects, subs) } : t
|
|
3693
|
+
)
|
|
3694
|
+
};
|
|
3695
|
+
}
|
|
3696
|
+
if (trait.ticks) {
|
|
3697
|
+
next.ticks = trait.ticks.map(
|
|
3698
|
+
(tick) => tick.effects ? { ...tick, effects: renameTraitEmbedsInValue(tick.effects, subs) } : tick
|
|
3699
|
+
);
|
|
3700
|
+
}
|
|
3701
|
+
if (trait.config) {
|
|
3702
|
+
const nextConfig = {};
|
|
3703
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
3704
|
+
nextConfig[key] = field.default === void 0 ? field : {
|
|
3705
|
+
...field,
|
|
3706
|
+
default: renameTraitEmbedsInValue(
|
|
3707
|
+
field.default,
|
|
3708
|
+
subs
|
|
3709
|
+
)
|
|
3710
|
+
};
|
|
3711
|
+
}
|
|
3712
|
+
next.config = nextConfig;
|
|
3713
|
+
}
|
|
3714
|
+
return next;
|
|
3715
|
+
}
|
|
3716
|
+
function findTraitEntryInOrbital(orbital, localName) {
|
|
3717
|
+
for (const traitRef of orbital.traits ?? []) {
|
|
3718
|
+
if (typeof traitRef === "string") continue;
|
|
3719
|
+
if ("stateMachine" in traitRef) {
|
|
3720
|
+
if (traitRef.name === localName) return traitRef;
|
|
3721
|
+
continue;
|
|
3722
|
+
}
|
|
3723
|
+
if (!("ref" in traitRef)) continue;
|
|
3724
|
+
const refObj = traitRef;
|
|
3725
|
+
const declared = refObj.name ?? parseImportedTraitRef(refObj.ref)?.traitName;
|
|
3726
|
+
if (declared === localName) return traitRef;
|
|
3727
|
+
}
|
|
3728
|
+
return null;
|
|
3729
|
+
}
|
|
3730
|
+
function traitEmbedNamesOf(trait) {
|
|
3731
|
+
const found = /* @__PURE__ */ new Set();
|
|
3732
|
+
const walk = (node) => {
|
|
3733
|
+
if (node === null || node === void 0) return;
|
|
3734
|
+
if (typeof node === "string") {
|
|
3735
|
+
if (!node.startsWith(TRAIT_EMBED_PREFIX)) return;
|
|
3736
|
+
const rest = node.slice(TRAIT_EMBED_PREFIX.length);
|
|
3737
|
+
const dot = rest.search(/[.[]/);
|
|
3738
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
3739
|
+
if (name.length > 0) found.add(name);
|
|
3740
|
+
return;
|
|
3741
|
+
}
|
|
3742
|
+
if (Array.isArray(node)) {
|
|
3743
|
+
for (const item of node) walk(item);
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
if (typeof node !== "object") return;
|
|
3747
|
+
for (const value of Object.values(node)) walk(value);
|
|
3748
|
+
};
|
|
3749
|
+
for (const t of trait.stateMachine?.transitions ?? []) walk(t.effects);
|
|
3750
|
+
for (const tick of trait.ticks ?? []) walk(tick.effects);
|
|
3751
|
+
for (const field of Object.values(trait.config ?? {})) walk(field.default);
|
|
3752
|
+
return [...found];
|
|
3753
|
+
}
|
|
3641
3754
|
function applyLinkedEntityRename(trait, linkedEntity) {
|
|
3642
3755
|
const atomLinked = trait.linkedEntity;
|
|
3643
3756
|
if (!linkedEntity || !atomLinked || linkedEntity === atomLinked) return trait;
|
|
@@ -3809,6 +3922,8 @@ var ReferenceResolver = class {
|
|
|
3809
3922
|
localTraits;
|
|
3810
3923
|
/** id-keyed mirror of `localTraits`, populated wherever the trait carries an `id`. */
|
|
3811
3924
|
localTraitsById = /* @__PURE__ */ new Map();
|
|
3925
|
+
/** Import scope of each loaded source orbital, keyed by its source path. */
|
|
3926
|
+
sourceImportsCache = /* @__PURE__ */ new Map();
|
|
3812
3927
|
loaderInitialized = false;
|
|
3813
3928
|
constructor(options) {
|
|
3814
3929
|
this.options = options;
|
|
@@ -3865,6 +3980,10 @@ var ReferenceResolver = class {
|
|
|
3865
3980
|
if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
|
|
3866
3981
|
return { success: false, errors: ["Internal error: unexpected failure state"] };
|
|
3867
3982
|
}
|
|
3983
|
+
const pullErrors = await this.pullSiblingTraits(traitsResult.data, imports, importChain);
|
|
3984
|
+
if (pullErrors.length > 0) {
|
|
3985
|
+
return { success: false, errors: pullErrors };
|
|
3986
|
+
}
|
|
3868
3987
|
for (const resolvedTrait of traitsResult.data) {
|
|
3869
3988
|
resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
|
|
3870
3989
|
resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
|
|
@@ -4038,6 +4157,191 @@ var ReferenceResolver = class {
|
|
|
4038
4157
|
}
|
|
4039
4158
|
return { success: true, data: resolved, warnings: [] };
|
|
4040
4159
|
}
|
|
4160
|
+
/**
|
|
4161
|
+
* The import scope of an already-loaded orbital, memoised per source path.
|
|
4162
|
+
* A sibling that is itself a ref names its target through the SOURCE atom's
|
|
4163
|
+
* aliases, so it can only be resolved against those.
|
|
4164
|
+
*/
|
|
4165
|
+
async importsOfSource(imported, chain) {
|
|
4166
|
+
const key = imported.sourcePath ?? `${imported.alias}:${imported.from}`;
|
|
4167
|
+
const cached = this.sourceImportsCache.get(key);
|
|
4168
|
+
if (cached) return cached;
|
|
4169
|
+
const result = await this.resolveImports(
|
|
4170
|
+
imported.orbital.uses ?? [],
|
|
4171
|
+
imported.sourcePath,
|
|
4172
|
+
chain
|
|
4173
|
+
);
|
|
4174
|
+
if (!result.success) return null;
|
|
4175
|
+
result.data.idIndex = buildIdIndex(imported.orbital, result.data.orbitals);
|
|
4176
|
+
this.sourceImportsCache.set(key, result.data);
|
|
4177
|
+
return result.data;
|
|
4178
|
+
}
|
|
4179
|
+
/**
|
|
4180
|
+
* Sibling-trait auto-pull — the JS twin of the compiler's
|
|
4181
|
+
* `phases/inline/trait.rs` pass, appending to `resolved` in place.
|
|
4182
|
+
*
|
|
4183
|
+
* An atom's main trait embeds its own sub-views as `@trait.<Sibling>` string
|
|
4184
|
+
* literals (`std-browse`'s `bodyContent: {children: [@trait.DataGrid1]}`).
|
|
4185
|
+
* A consumer that imports only the main trait never instantiates those
|
|
4186
|
+
* siblings, so the token dangles: no state machine, no fetch, an empty list
|
|
4187
|
+
* where the grid should be. The compiled path materialises them; without this
|
|
4188
|
+
* pass the interpreted path did not, so a raw `.orb` handed straight to
|
|
4189
|
+
* `OrbitalServerRuntime` rendered a different app than the same `.orb` run
|
|
4190
|
+
* through `orbital resolve`.
|
|
4191
|
+
*
|
|
4192
|
+
* Pulls are keyed per EMBEDDER (`owner` = the top-level consumer trait that
|
|
4193
|
+
* started the chain), not per atom. Two rebinds of one atom in one orbital
|
|
4194
|
+
* (`ChannelRail -> Channel` and `ChatThread -> ChatMessage`, both std-browse)
|
|
4195
|
+
* carry different entity rebinds and different hosts to listen to, so one
|
|
4196
|
+
* shared copy can only ever serve one of them. The first owner keeps the
|
|
4197
|
+
* source name; later owners pull under `<Owner><Sibling>` — unique by
|
|
4198
|
+
* construction, since owner names are unique within the orbital.
|
|
4199
|
+
*/
|
|
4200
|
+
async pullSiblingTraits(resolved, imports, chain) {
|
|
4201
|
+
const work = [];
|
|
4202
|
+
const ownerSubs = /* @__PURE__ */ new Map();
|
|
4203
|
+
const subsFor = (owner) => {
|
|
4204
|
+
let m = ownerSubs.get(owner);
|
|
4205
|
+
if (!m) {
|
|
4206
|
+
m = /* @__PURE__ */ new Map();
|
|
4207
|
+
ownerSubs.set(owner, m);
|
|
4208
|
+
}
|
|
4209
|
+
return m;
|
|
4210
|
+
};
|
|
4211
|
+
for (const rt of resolved) {
|
|
4212
|
+
if (rt.source.type !== "imported" || !rt.trait.name) continue;
|
|
4213
|
+
const owner = rt.trait.name;
|
|
4214
|
+
subsFor(owner).set(rt.source.traitName, owner);
|
|
4215
|
+
for (const sibling of traitEmbedNamesOf(rt.trait)) {
|
|
4216
|
+
work.push({ alias: rt.source.alias, sibling, linkedEntity: rt.linkedEntity, parent: owner, owner });
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
if (work.length === 0) return [];
|
|
4220
|
+
const errors = [];
|
|
4221
|
+
const consumerDeclared = new Set(resolved.map((r) => r.trait.name).filter(Boolean));
|
|
4222
|
+
const seen = new Set(consumerDeclared);
|
|
4223
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4224
|
+
const pulledAs = /* @__PURE__ */ new Map();
|
|
4225
|
+
const ownerOf = /* @__PURE__ */ new Map();
|
|
4226
|
+
const parentRewrites = /* @__PURE__ */ new Map();
|
|
4227
|
+
const pulled = [];
|
|
4228
|
+
const noteRewrite = (parent, from, to) => {
|
|
4229
|
+
let m = parentRewrites.get(parent);
|
|
4230
|
+
if (!m) {
|
|
4231
|
+
m = /* @__PURE__ */ new Map();
|
|
4232
|
+
parentRewrites.set(parent, m);
|
|
4233
|
+
}
|
|
4234
|
+
m.set(from, to);
|
|
4235
|
+
};
|
|
4236
|
+
for (let item = work.pop(); item !== void 0; item = work.pop()) {
|
|
4237
|
+
const { alias, sibling, linkedEntity, parent, owner } = item;
|
|
4238
|
+
const pullKey = `${alias}\0${sibling}\0${owner}`;
|
|
4239
|
+
const existing = pulledAs.get(pullKey);
|
|
4240
|
+
if (existing !== void 0) {
|
|
4241
|
+
if (existing !== sibling) noteRewrite(parent, sibling, existing);
|
|
4242
|
+
continue;
|
|
4243
|
+
}
|
|
4244
|
+
let finalName = sibling;
|
|
4245
|
+
if (seen.has(sibling)) {
|
|
4246
|
+
if (consumerDeclared.has(sibling)) continue;
|
|
4247
|
+
finalName = `${owner}${sibling}`;
|
|
4248
|
+
if (seen.has(finalName)) continue;
|
|
4249
|
+
}
|
|
4250
|
+
if (visited.has(pullKey)) continue;
|
|
4251
|
+
visited.add(pullKey);
|
|
4252
|
+
const imported = imports.orbitals.get(alias);
|
|
4253
|
+
if (!imported) continue;
|
|
4254
|
+
const atomEntry = findTraitEntryInOrbital(imported.orbital, sibling);
|
|
4255
|
+
if (!atomEntry) continue;
|
|
4256
|
+
let atomTrait;
|
|
4257
|
+
if ("stateMachine" in atomEntry) {
|
|
4258
|
+
const { trait: cfgResolved, errors: cfgErrors } = resolveConfigRefEmitNames(
|
|
4259
|
+
atomEntry
|
|
4260
|
+
);
|
|
4261
|
+
if (cfgErrors.length > 0) {
|
|
4262
|
+
errors.push(...cfgErrors);
|
|
4263
|
+
continue;
|
|
4264
|
+
}
|
|
4265
|
+
atomTrait = cfgResolved;
|
|
4266
|
+
} else {
|
|
4267
|
+
const srcImports = await this.importsOfSource(imported, chain);
|
|
4268
|
+
if (!srcImports) continue;
|
|
4269
|
+
const refObj = atomEntry;
|
|
4270
|
+
const nested = this.resolveTraitRefString(
|
|
4271
|
+
refObj.ref,
|
|
4272
|
+
srcImports,
|
|
4273
|
+
refObj.config,
|
|
4274
|
+
refObj.linkedEntity,
|
|
4275
|
+
refObj.name ?? sibling,
|
|
4276
|
+
refObj.events,
|
|
4277
|
+
refObj.listens,
|
|
4278
|
+
refObj.refId
|
|
4279
|
+
);
|
|
4280
|
+
if (!nested.success) {
|
|
4281
|
+
errors.push(...nested.errors);
|
|
4282
|
+
continue;
|
|
4283
|
+
}
|
|
4284
|
+
atomTrait = nested.data.trait;
|
|
4285
|
+
}
|
|
4286
|
+
let copy = applyLinkedEntityRename(atomTrait, linkedEntity);
|
|
4287
|
+
if (finalName !== sibling) {
|
|
4288
|
+
copy = { ...copy, name: finalName };
|
|
4289
|
+
noteRewrite(parent, sibling, finalName);
|
|
4290
|
+
}
|
|
4291
|
+
for (const next of traitEmbedNamesOf(copy)) {
|
|
4292
|
+
work.push({ alias, sibling: next, linkedEntity, parent: finalName, owner });
|
|
4293
|
+
}
|
|
4294
|
+
pulledAs.set(pullKey, finalName);
|
|
4295
|
+
subsFor(owner).set(sibling, finalName);
|
|
4296
|
+
ownerOf.set(finalName, owner);
|
|
4297
|
+
seen.add(finalName);
|
|
4298
|
+
pulled.push({
|
|
4299
|
+
trait: copy,
|
|
4300
|
+
source: { type: "imported", alias, traitName: sibling },
|
|
4301
|
+
...linkedEntity !== void 0 ? { linkedEntity } : {}
|
|
4302
|
+
});
|
|
4303
|
+
}
|
|
4304
|
+
if (pulled.length === 0 && parentRewrites.size === 0) return errors;
|
|
4305
|
+
const applyRewrites = (rt) => {
|
|
4306
|
+
const subs = rt.trait.name ? parentRewrites.get(rt.trait.name) : void 0;
|
|
4307
|
+
if (subs) rt.trait = renameTraitEmbeds(rt.trait, subs);
|
|
4308
|
+
};
|
|
4309
|
+
for (const rt of resolved) applyRewrites(rt);
|
|
4310
|
+
for (const rt of pulled) applyRewrites(rt);
|
|
4311
|
+
const idByName = /* @__PURE__ */ new Map();
|
|
4312
|
+
for (const rt of [...resolved, ...pulled]) {
|
|
4313
|
+
if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
|
|
4314
|
+
}
|
|
4315
|
+
for (const rt of pulled) {
|
|
4316
|
+
const listens = rt.trait.listens;
|
|
4317
|
+
const owner = rt.trait.name ? ownerOf.get(rt.trait.name) : void 0;
|
|
4318
|
+
const subs = owner ? ownerSubs.get(owner) : void 0;
|
|
4319
|
+
if (!listens || listens.length === 0 || !subs) continue;
|
|
4320
|
+
let changed = false;
|
|
4321
|
+
const nextListens = listens.map((listen) => {
|
|
4322
|
+
const source = listen.source;
|
|
4323
|
+
if (!source || source.kind !== "trait") return listen;
|
|
4324
|
+
const target = subs.get(source.trait);
|
|
4325
|
+
if (target === void 0 || target === source.trait) return listen;
|
|
4326
|
+
changed = true;
|
|
4327
|
+
const traitId = idByName.get(target);
|
|
4328
|
+
return {
|
|
4329
|
+
...listen,
|
|
4330
|
+
source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
|
|
4331
|
+
};
|
|
4332
|
+
});
|
|
4333
|
+
if (changed) rt.trait = { ...rt.trait, listens: nextListens };
|
|
4334
|
+
}
|
|
4335
|
+
refResolverLog.info("sibling-pull", {
|
|
4336
|
+
pulled: pulled.map((p) => ({
|
|
4337
|
+
trait: p.trait.name,
|
|
4338
|
+
owner: p.trait.name ? ownerOf.get(p.trait.name) : void 0,
|
|
4339
|
+
linkedEntity: p.linkedEntity ?? p.trait.linkedEntity
|
|
4340
|
+
}))
|
|
4341
|
+
});
|
|
4342
|
+
resolved.push(...pulled);
|
|
4343
|
+
return errors;
|
|
4344
|
+
}
|
|
4041
4345
|
/**
|
|
4042
4346
|
* Resolve a single trait reference.
|
|
4043
4347
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { B as BindingContext, f as EvaluationContextExtensions, P as PatternProps, E as EffectHandlers, g as EffectContext, h as ExecutionEnvironment, i as EffectResult, T as TraitDefinition } from './types-p_L8-Sk4.js';
|
|
2
2
|
export { j as BrowserFileMeta, k as BrowserFilePickerOptions, l as BrowserGeolocationOptions, m as BrowserGeolocationPosition, C as ConfigContext, n as Effect, a as EventListener, H as HANDLER_MANIFEST, I as IEventBus, b as RuntimeConfig, R as RuntimeEvent, d as TraitState, c as TransitionObserver, e as TransitionResult, U as Unsubscribe } from './types-p_L8-Sk4.js';
|
|
3
|
-
import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-
|
|
4
|
-
export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeEventKey, B as parseNamespacedEvent, C as preprocessSchema, D as processEvent } from './OrbitalServerRuntime-
|
|
3
|
+
import { U as UnifiedLoaderOptions, S as SchemaLoader, I as ImportChainLike, L as LoadResult, a as LoadedSchema, b as LoadedOrbital, P as PersistenceAdapter } from './OrbitalServerRuntime-Dz0oubQ_.js';
|
|
4
|
+
export { E as EntitySharingMap, c as EventBus, d as EventNamespaceMap, e as InMemoryPersistence, O as OrbitalEventRequest, f as OrbitalEventResponse, g as OrbitalServerRuntimeConfig, h as PreprocessOptions, i as PreprocessResult, j as PreprocessedSchema, k as ProcessEventOptions, R as RegisteredOrbital, l as RuntimeOrbital, m as RuntimeOrbitalSchema, n as RuntimeTrait, o as StateMachineManager, p as collectDeclaredConfigDefaults, q as collectDeclaredEntityDefaults, r as createInitialTraitState, s as findInitialState, t as findTransition, u as getIsolatedCollectionName, v as getNamespacedEvent, w as isBrowser, x as isElectron, y as isNamespacedEvent, z as isNode, A as normalizeEventKey, B as parseNamespacedEvent, C as preprocessSchema, D as processEvent } from './OrbitalServerRuntime-Dz0oubQ_.js';
|
|
5
5
|
import { EvaluationContext, SExpressionEvaluator } from '@almadar/evaluator';
|
|
6
6
|
export { EvaluationContext, createMinimalContext } from '@almadar/evaluator';
|
|
7
7
|
import { TraitConfigObject, EventPayload, PatternConfig, EntityId, EntityField, EntityRow, EntityPersistence, ServiceParams, PayloadField, OrbitalDefinition, OrbitalSchema } from '@almadar/core';
|
|
@@ -585,6 +585,18 @@ declare class MockPersistenceAdapter implements PersistenceAdapter {
|
|
|
585
585
|
private storeNameById;
|
|
586
586
|
private config;
|
|
587
587
|
constructor(config?: MockPersistenceConfig);
|
|
588
|
+
/**
|
|
589
|
+
* Add owner columns discovered after construction.
|
|
590
|
+
*
|
|
591
|
+
* The adapter is built before any schema is registered, so schema-DERIVED
|
|
592
|
+
* owner columns (relation fields pointing at the `[identity]` entity) can
|
|
593
|
+
* only arrive later.
|
|
594
|
+
*
|
|
595
|
+
* ⚠️ Seeding is EAGER — `registerEntity()` seeds immediately — so callers must
|
|
596
|
+
* supply these columns BEFORE registering any orbital. Calling this afterwards
|
|
597
|
+
* silently stamps nothing.
|
|
598
|
+
*/
|
|
599
|
+
addOwnerFields(fields: readonly string[]): void;
|
|
588
600
|
/** Re-anchor the PRNG to the configured seed. Called before every
|
|
589
601
|
* re-seed loop so identical reseed sequences produce identical rows
|
|
590
602
|
* (timestamps + generated fields). Without this, the first
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { EffectExecutor, createContextFromBindings } from './chunk-
|
|
2
|
-
export { CALLSITE_PAYLOAD_PREFIX, EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, containsBindings, createContextFromBindings, createInitialTraitState, createMinimalContext, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, extractBindings, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeCallSiteConfigToValues, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, resolveCallSitePayloadCaptures, validateEventPayload, validatePayloadShapes } from './chunk-
|
|
1
|
+
import { EffectExecutor, createContextFromBindings } from './chunk-EJHMWSUS.js';
|
|
2
|
+
export { CALLSITE_PAYLOAD_PREFIX, EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, containsBindings, createContextFromBindings, createInitialTraitState, createMinimalContext, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, extractBindings, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, interpolateProps, interpolateValue, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeCallSiteConfigToValues, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, resolveCallSitePayloadCaptures, validateEventPayload, validatePayloadShapes } from './chunk-EJHMWSUS.js';
|
|
3
3
|
export { cronMatches, cronMinuteKey, isValidCronExpression, parseCron, parseCronField } from './chunk-OU3ITB5S.js';
|
|
4
4
|
import './chunk-T4VDAB4C.js';
|
|
5
5
|
export { PERF_NAMESPACE, RendererContractViolationError, adjustSchemaForMockData, aggregateSlotContent, assertIsMultiSourceSlotManager, assertIsSlotManager, bindEventBus, bindTraitStateGetter, buildMockData, buildOrbitalsByTrait, clearPerf, createSlotSetter, ensureVerificationApi, getOrbitalVerification, perfEnd, perfStart, perfStore, perfTime, prepareSchemaForPreview, pushPerfEntry, validateSlotContent, wrapCallbackForEvent } from './chunk-FOFLEZRJ.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/runtime",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.44.0",
|
|
4
4
|
"description": "Interpreted runtime for Almadar orbital applications (OrbitalServerRuntime)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@almadar/core": "^10.
|
|
55
|
+
"@almadar/core": "^10.42.0",
|
|
56
56
|
"@almadar/evaluator": "^2.37.0",
|
|
57
57
|
"@almadar/logger": "^1.10.0",
|
|
58
58
|
"@almadar/server": "^2.29.0",
|
|
59
|
-
"@almadar/std": "^16.
|
|
59
|
+
"@almadar/std": "^16.152.0"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"express": "^5.0.0"
|