@almadar/runtime 6.71.0 → 6.73.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-DnDJhpLS.d.ts → OrbitalServerRuntime-BiEntWd-.d.ts} +258 -86
- package/dist/OrbitalServerRuntime.d.ts +2 -2
- package/dist/OrbitalServerRuntime.js +171 -16
- package/dist/ServerBridge.d.ts +1 -1
- package/dist/{chunk-PAEMYGKV.js → chunk-H7HQQVQJ.js} +3071 -299
- package/dist/{chunk-ZJ62H3ES.js → chunk-ZWAOJT6R.js} +5 -29
- package/dist/createOsHandlers.d.ts +1 -1
- package/dist/entityAccess.js +1 -1
- package/dist/{external-loader-YUUADLAP.js → external-loader-CISUEINQ.js} +1 -0
- package/dist/index.d.ts +14 -132
- package/dist/index.js +28 -10
- package/dist/{types-BaD_ox7e.d.ts → types-CWaIuEQn.d.ts} +34 -4
- package/package.json +7 -7
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { parseCron, cronMinuteKey, cronMatches } from './chunk-OU3ITB5S.js';
|
|
2
|
-
import { createContextFromBindings, interpolateValue, deferEntityBindings } from './chunk-
|
|
2
|
+
import { createContextFromBindings, interpolateValue, deferEntityBindings } from './chunk-ZWAOJT6R.js';
|
|
3
3
|
import { seedRandom, randomArrayElement, randomInt, shuffleArray, randomPastDate } from './chunk-T4VDAB4C.js';
|
|
4
4
|
import { collectTraitRefsFromValue, collectTraitRefsFromEffects } from './chunk-SCRAHWOC.js';
|
|
5
5
|
import { createLogger, setNamespaceLevel } from '@almadar/logger';
|
|
6
6
|
import { evaluateGuard, SExpressionEvaluator } from '@almadar/evaluator';
|
|
7
|
-
import { OrbitalSchemaSchema, isInlineTrait, isEntityCall, isEntityReference, parseEntityRef, parseImportedTraitRef, isPageReference, isPageReferenceString, isPageReferenceObject, parsePageRef, isReferenceConfigType, configRefEventKnob, normalizeCallSiteConfigToValues, resolveConfigRefEventName, eventListPropsOf } from '@almadar/core';
|
|
7
|
+
import { OrbitalSchemaSchema, isInlineTrait, isEntityCall, isEntityReference, parseEntityRef, parseImportedTraitRef, isPageReference, isPageReferenceString, isPageReferenceObject, parsePageRef, parseOrbitalRef, overrideDeclaredKnobs, asTraitId, asEntityId, asPageId, asOrbitalId, deriveId, isReferenceConfigType, configRefEventKnob, normalizeCallSiteConfigToValues, resolveConfigRefEventName, isCallSiteConfigDeclaration, asEventId, ledgerRename, idPrefix, eventListPropsOf } from '@almadar/core';
|
|
8
8
|
export { normalizeCallSiteConfigToValues } from '@almadar/core';
|
|
9
|
-
import { sampleRowCount, sampleRow } from '@almadar/core/mock';
|
|
9
|
+
import { sampleRowCount, sampleRow, identityEntitiesOf, roleVocabularyOf } from '@almadar/core/mock';
|
|
10
10
|
|
|
11
11
|
var log = createLogger("almadar:runtime:eventbus");
|
|
12
12
|
var EventBus = class {
|
|
@@ -324,6 +324,7 @@ function isValidDurationString(interval) {
|
|
|
324
324
|
return /^(\d+)(ms|s|m|h)?$/.test(interval);
|
|
325
325
|
}
|
|
326
326
|
var smLog = createLogger("almadar:runtime:sm");
|
|
327
|
+
var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
|
|
327
328
|
function findInitialState(trait) {
|
|
328
329
|
if (!trait.states || trait.states.length === 0) {
|
|
329
330
|
smLog.warn("trait-has-no-states", { trait: trait.name });
|
|
@@ -1197,13 +1198,23 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1197
1198
|
const isCompound = operator === "do" || operator === "when" || operator === "let" || operator === "if";
|
|
1198
1199
|
const resolvedArgs = isCompound ? rawArgs : resolveArgs(rawArgs, this.bindings, this.strictBindings, this.contextExtensions);
|
|
1199
1200
|
try {
|
|
1200
|
-
await this.dispatch(operator, resolvedArgs);
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1201
|
+
const outcome = await this.dispatch(operator, resolvedArgs);
|
|
1202
|
+
if (outcome?.failed) {
|
|
1203
|
+
results.push({
|
|
1204
|
+
type: operator,
|
|
1205
|
+
args: resolvedArgs,
|
|
1206
|
+
status: "failed",
|
|
1207
|
+
error: outcome.error,
|
|
1208
|
+
durationMs: Date.now() - start
|
|
1209
|
+
});
|
|
1210
|
+
} else {
|
|
1211
|
+
results.push({
|
|
1212
|
+
type: operator,
|
|
1213
|
+
args: resolvedArgs,
|
|
1214
|
+
status: "executed",
|
|
1215
|
+
durationMs: Date.now() - start
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1207
1218
|
} catch (error) {
|
|
1208
1219
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1209
1220
|
results.push({
|
|
@@ -1260,10 +1271,10 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1260
1271
|
this.handlers.emit(eventName, payload, this.sourceStamp(), fromPersistSuccess);
|
|
1261
1272
|
}
|
|
1262
1273
|
}
|
|
1263
|
-
emitFailure(emit, err) {
|
|
1274
|
+
emitFailure(emit, err, extra) {
|
|
1264
1275
|
if (!emit?.failure) return;
|
|
1265
1276
|
const error = err instanceof Error ? err.message : String(err);
|
|
1266
|
-
this.handlers.emit(emit.failure, { error }, this.sourceStamp());
|
|
1277
|
+
this.handlers.emit(emit.failure, { ...extra, error }, this.sourceStamp());
|
|
1267
1278
|
}
|
|
1268
1279
|
/**
|
|
1269
1280
|
* Narrow the generic emit config into the `os/watch-*` handler surface
|
|
@@ -1310,6 +1321,14 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1310
1321
|
// ==========================================================================
|
|
1311
1322
|
// Effect Dispatch
|
|
1312
1323
|
// ==========================================================================
|
|
1324
|
+
/**
|
|
1325
|
+
* Dispatches one effect. Returns `void` for the ordinary case (the
|
|
1326
|
+
* caller only cares whether it threw). A `persist` that resolves
|
|
1327
|
+
* without throwing — the store DENIED the write, signalled by return
|
|
1328
|
+
* value rather than an exception, per the "close the circuit" doctrine
|
|
1329
|
+
* — reports that outcome here so `executeWithResults` can record it as
|
|
1330
|
+
* `status: 'failed'` instead of the default `'executed'`.
|
|
1331
|
+
*/
|
|
1313
1332
|
async dispatch(operator, args) {
|
|
1314
1333
|
switch (operator) {
|
|
1315
1334
|
// === Universal Effects ===
|
|
@@ -1383,6 +1402,15 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1383
1402
|
success: emitCfg?.success,
|
|
1384
1403
|
failure: emitCfg?.failure
|
|
1385
1404
|
});
|
|
1405
|
+
if (this.handlers.persistDelegated === true) {
|
|
1406
|
+
persistLog.debug("persist:delegated", {
|
|
1407
|
+
action,
|
|
1408
|
+
entityType: action === "batch" ? "batch" : args[1],
|
|
1409
|
+
traitName: this.context.traitName,
|
|
1410
|
+
transition: this.context.transition
|
|
1411
|
+
});
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1386
1414
|
try {
|
|
1387
1415
|
if (action === "batch") {
|
|
1388
1416
|
const operations = args[1];
|
|
@@ -1406,16 +1434,38 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1406
1434
|
const entityType = args[1];
|
|
1407
1435
|
const data = args[2];
|
|
1408
1436
|
const persisted = await this.handlers.persist(action, entityType, data);
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
action
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1437
|
+
if (persisted === void 0) {
|
|
1438
|
+
const attemptedId = typeof data === "string" ? data : data && typeof data === "object" ? data.id : void 0;
|
|
1439
|
+
persistLog.error("persist:denied", { action, entityType, attemptedId });
|
|
1440
|
+
const deniedError = `persist ${action} ${entityType} was denied or failed`;
|
|
1441
|
+
this.emitFailure(
|
|
1442
|
+
emitCfg,
|
|
1443
|
+
new Error(deniedError),
|
|
1444
|
+
{ entityType, id: attemptedId }
|
|
1445
|
+
);
|
|
1446
|
+
return { failed: true, error: deniedError };
|
|
1447
|
+
} else {
|
|
1448
|
+
const dataId = typeof persisted === "string" ? persisted : persisted.id;
|
|
1449
|
+
persistLog.debug("persist:success", {
|
|
1450
|
+
action,
|
|
1451
|
+
entityType,
|
|
1452
|
+
dataId,
|
|
1453
|
+
willEmit: emitCfg?.success
|
|
1454
|
+
});
|
|
1455
|
+
if (action === "create" && this.bindings.entity && typeof dataId === "string") {
|
|
1456
|
+
const boundId = this.bindings.entity.id;
|
|
1457
|
+
const submittedId = data && typeof data === "object" ? data.id : void 0;
|
|
1458
|
+
if (boundId === void 0 || boundId === submittedId) {
|
|
1459
|
+
this.bindings.entity.id = dataId;
|
|
1460
|
+
persistLog.debug("persist:create-bound-id", {
|
|
1461
|
+
entityType,
|
|
1462
|
+
id: dataId
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
this.emitSuccess(emitCfg, "success", persisted, true);
|
|
1467
|
+
persistLog.debug("persist:emit-fired", { action, eventName: emitCfg?.success });
|
|
1468
|
+
}
|
|
1419
1469
|
}
|
|
1420
1470
|
} catch (err) {
|
|
1421
1471
|
persistLog.error("persist:error", {
|
|
@@ -1450,8 +1500,16 @@ var EffectExecutor = class _EffectExecutor {
|
|
|
1450
1500
|
const emitCfg = this.extractEmitConfig(rawOpt);
|
|
1451
1501
|
try {
|
|
1452
1502
|
const result = await this.handlers.fetch(entityType, options);
|
|
1453
|
-
|
|
1454
|
-
|
|
1503
|
+
if (result === null) {
|
|
1504
|
+
if (options?.id !== void 0) {
|
|
1505
|
+
this.emitFailure(emitCfg, new Error(`${entityType} ${options.id} not found`));
|
|
1506
|
+
} else {
|
|
1507
|
+
this.emitSuccess(emitCfg, "success", { data: [], totalCount: 0 });
|
|
1508
|
+
}
|
|
1509
|
+
} else {
|
|
1510
|
+
const payload = { data: result.rows, totalCount: result.total };
|
|
1511
|
+
this.emitSuccess(emitCfg, "success", payload);
|
|
1512
|
+
}
|
|
1455
1513
|
} catch (err) {
|
|
1456
1514
|
this.emitFailure(emitCfg, err);
|
|
1457
1515
|
throw err;
|
|
@@ -2642,7 +2700,11 @@ var MockPersistenceAdapter = class _MockPersistenceAdapter {
|
|
|
2642
2700
|
async create(entityType, data) {
|
|
2643
2701
|
const store = this.getStore(entityType);
|
|
2644
2702
|
this.assertFileValuesWithinCeiling(entityType, data);
|
|
2645
|
-
const
|
|
2703
|
+
const suppliedId = typeof data.id === "string" && data.id.length > 0 ? data.id : void 0;
|
|
2704
|
+
if (suppliedId && store.has(suppliedId)) {
|
|
2705
|
+
throw new Error(`Entity ${entityType} with id ${suppliedId} already exists`);
|
|
2706
|
+
}
|
|
2707
|
+
const id = suppliedId ?? this.nextId(entityType);
|
|
2646
2708
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2647
2709
|
const withDefaults = this.applyFieldDefaults(entityType, data);
|
|
2648
2710
|
const item = {
|
|
@@ -2904,6 +2966,7 @@ var HttpLoader = class {
|
|
|
2904
2966
|
data: {
|
|
2905
2967
|
orbital,
|
|
2906
2968
|
orbitals: schema.orbitals,
|
|
2969
|
+
...schema.config ? { schemaConfig: schema.config } : {},
|
|
2907
2970
|
sourcePath: schemaResult.data.sourcePath,
|
|
2908
2971
|
importPath
|
|
2909
2972
|
}
|
|
@@ -3113,7 +3176,7 @@ async function getExternalLoaderModule() {
|
|
|
3113
3176
|
return null;
|
|
3114
3177
|
}
|
|
3115
3178
|
try {
|
|
3116
|
-
externalLoaderModule = await import('./external-loader-
|
|
3179
|
+
externalLoaderModule = await import('./external-loader-CISUEINQ.js');
|
|
3117
3180
|
return externalLoaderModule;
|
|
3118
3181
|
} catch {
|
|
3119
3182
|
return null;
|
|
@@ -3287,6 +3350,7 @@ var UnifiedLoader = class {
|
|
|
3287
3350
|
data: {
|
|
3288
3351
|
orbital: found,
|
|
3289
3352
|
orbitals: schema.orbitals,
|
|
3353
|
+
...schema.config ? { schemaConfig: schema.config } : {},
|
|
3290
3354
|
sourcePath: schemaResult.data.sourcePath,
|
|
3291
3355
|
importPath
|
|
3292
3356
|
}
|
|
@@ -3303,6 +3367,7 @@ var UnifiedLoader = class {
|
|
|
3303
3367
|
data: {
|
|
3304
3368
|
orbital: schema.orbitals[0],
|
|
3305
3369
|
orbitals: schema.orbitals,
|
|
3370
|
+
...schema.config ? { schemaConfig: schema.config } : {},
|
|
3306
3371
|
sourcePath: schemaResult.data.sourcePath,
|
|
3307
3372
|
importPath
|
|
3308
3373
|
}
|
|
@@ -3637,6 +3702,232 @@ function spliceLambdaTraitRefs(traits, pages) {
|
|
|
3637
3702
|
}
|
|
3638
3703
|
}
|
|
3639
3704
|
|
|
3705
|
+
// src/resolver/sentinel-resolution.ts
|
|
3706
|
+
var PRIMITIVE_TYPE_ARG_NAMES = /* @__PURE__ */ new Set([
|
|
3707
|
+
"string",
|
|
3708
|
+
"money",
|
|
3709
|
+
"any",
|
|
3710
|
+
"icon",
|
|
3711
|
+
"component",
|
|
3712
|
+
"email",
|
|
3713
|
+
"url",
|
|
3714
|
+
"phone",
|
|
3715
|
+
"uuid",
|
|
3716
|
+
"image",
|
|
3717
|
+
"node",
|
|
3718
|
+
"json",
|
|
3719
|
+
"render-ui",
|
|
3720
|
+
"relation",
|
|
3721
|
+
"int",
|
|
3722
|
+
"float",
|
|
3723
|
+
"number",
|
|
3724
|
+
"duration",
|
|
3725
|
+
"bool",
|
|
3726
|
+
"boolean",
|
|
3727
|
+
"date",
|
|
3728
|
+
"datetime",
|
|
3729
|
+
"timestamp",
|
|
3730
|
+
"object",
|
|
3731
|
+
"sexpr",
|
|
3732
|
+
"scalar"
|
|
3733
|
+
]);
|
|
3734
|
+
var BARE_PAYLOAD_CARRIER = "value";
|
|
3735
|
+
function resolveTypeArgValue(value, entitiesByName, typesByName) {
|
|
3736
|
+
if (PRIMITIVE_TYPE_ARG_NAMES.has(value)) {
|
|
3737
|
+
return { kind: "scalar", primitive: value };
|
|
3738
|
+
}
|
|
3739
|
+
const entity = entitiesByName.get(value);
|
|
3740
|
+
if (entity) {
|
|
3741
|
+
return { kind: "entity", entity };
|
|
3742
|
+
}
|
|
3743
|
+
const shape = typesByName[value];
|
|
3744
|
+
if (shape) {
|
|
3745
|
+
return { kind: "struct", shape };
|
|
3746
|
+
}
|
|
3747
|
+
return void 0;
|
|
3748
|
+
}
|
|
3749
|
+
function entityFieldToPayloadField(f) {
|
|
3750
|
+
if (f.type === "object" && f.items) {
|
|
3751
|
+
const valueType = fieldTypeTagOf(f.items);
|
|
3752
|
+
return {
|
|
3753
|
+
name: f.name ?? "",
|
|
3754
|
+
type: `Map<string,${valueType}>`,
|
|
3755
|
+
...f.required !== void 0 ? { required: f.required } : {}
|
|
3756
|
+
};
|
|
3757
|
+
}
|
|
3758
|
+
let properties;
|
|
3759
|
+
if (f.type === "object" && f.properties) {
|
|
3760
|
+
properties = Object.values(f.properties).map(entityFieldToPayloadField);
|
|
3761
|
+
} else if (f.type === "union" && f.properties) {
|
|
3762
|
+
const ordered = f.values ?? Object.keys(f.properties);
|
|
3763
|
+
properties = ordered.map((k) => f.properties?.[k]).filter((v) => v !== void 0).map(entityFieldToPayloadField);
|
|
3764
|
+
} else if (f.type === "array" && f.items) {
|
|
3765
|
+
properties = entityFieldToPayloadField(f.items).properties;
|
|
3766
|
+
}
|
|
3767
|
+
const isArrayOfStruct = f.type === "array" && properties !== void 0;
|
|
3768
|
+
return {
|
|
3769
|
+
name: f.name ?? "",
|
|
3770
|
+
type: isArrayOfStruct ? "[object]" : fieldTypeTagOf(f),
|
|
3771
|
+
...f.required !== void 0 ? { required: f.required } : {},
|
|
3772
|
+
...properties && properties.length > 0 ? { properties } : {}
|
|
3773
|
+
};
|
|
3774
|
+
}
|
|
3775
|
+
function fieldTypeTagOf(f) {
|
|
3776
|
+
return f.type;
|
|
3777
|
+
}
|
|
3778
|
+
function entityFieldsToPayloadFields(entity) {
|
|
3779
|
+
return entity.fields.map(entityFieldToPayloadField);
|
|
3780
|
+
}
|
|
3781
|
+
function flattenBareEntityPayload(fields, entityDef, subs) {
|
|
3782
|
+
if (fields.length !== 1) return false;
|
|
3783
|
+
const field = fields[0];
|
|
3784
|
+
if (field.name !== BARE_PAYLOAD_CARRIER) return false;
|
|
3785
|
+
let entity;
|
|
3786
|
+
if (field.type === "@entity") {
|
|
3787
|
+
entity = entityDef;
|
|
3788
|
+
} else if (field.type === "object" && field.properties) {
|
|
3789
|
+
entity = entityDef;
|
|
3790
|
+
} else if (field.type.startsWith("$")) {
|
|
3791
|
+
const sub = subs.get(field.type.slice(1));
|
|
3792
|
+
entity = sub?.kind === "entity" ? sub.entity : void 0;
|
|
3793
|
+
}
|
|
3794
|
+
if (!entity) return false;
|
|
3795
|
+
fields.length = 0;
|
|
3796
|
+
fields.push(...entityFieldsToPayloadFields(entity));
|
|
3797
|
+
return true;
|
|
3798
|
+
}
|
|
3799
|
+
function resolveSentinelFields(fields, entityDef, subs, declaredNames) {
|
|
3800
|
+
let changed = false;
|
|
3801
|
+
for (const field of fields) {
|
|
3802
|
+
const isSelfRef = field.type === "@entity" || field.type === "[@entity]";
|
|
3803
|
+
if (isSelfRef) {
|
|
3804
|
+
if (entityDef) {
|
|
3805
|
+
const isArray = field.type.startsWith("[");
|
|
3806
|
+
field.type = isArray ? "[object]" : "object";
|
|
3807
|
+
field.properties = entityFieldsToPayloadFields(entityDef);
|
|
3808
|
+
field.entity = entityDef.name;
|
|
3809
|
+
changed = true;
|
|
3810
|
+
}
|
|
3811
|
+
continue;
|
|
3812
|
+
}
|
|
3813
|
+
const isArraySentinel = field.type.startsWith("[$") && field.type.endsWith("]");
|
|
3814
|
+
const isBareSentinel = !isArraySentinel && field.type.startsWith("$");
|
|
3815
|
+
if (isBareSentinel || isArraySentinel) {
|
|
3816
|
+
const paramName = isArraySentinel ? field.type.slice(2, -1) : field.type.slice(1);
|
|
3817
|
+
const sub = subs.get(paramName);
|
|
3818
|
+
if (sub) {
|
|
3819
|
+
switch (sub.kind) {
|
|
3820
|
+
case "scalar":
|
|
3821
|
+
field.type = isArraySentinel ? `[${sub.primitive}]` : sub.primitive;
|
|
3822
|
+
field.properties = void 0;
|
|
3823
|
+
break;
|
|
3824
|
+
case "entity":
|
|
3825
|
+
field.type = isArraySentinel ? "[object]" : "object";
|
|
3826
|
+
field.properties = entityFieldsToPayloadFields(sub.entity);
|
|
3827
|
+
field.entity = sub.entity.name;
|
|
3828
|
+
break;
|
|
3829
|
+
case "struct":
|
|
3830
|
+
field.type = isArraySentinel ? "[object]" : "object";
|
|
3831
|
+
field.properties = [...sub.shape];
|
|
3832
|
+
break;
|
|
3833
|
+
}
|
|
3834
|
+
changed = true;
|
|
3835
|
+
continue;
|
|
3836
|
+
}
|
|
3837
|
+
if (declaredNames.has(paramName)) {
|
|
3838
|
+
continue;
|
|
3839
|
+
}
|
|
3840
|
+
if (entityDef) {
|
|
3841
|
+
field.type = isArraySentinel ? "[object]" : "object";
|
|
3842
|
+
field.properties = entityFieldsToPayloadFields(entityDef);
|
|
3843
|
+
field.entity = entityDef.name;
|
|
3844
|
+
changed = true;
|
|
3845
|
+
}
|
|
3846
|
+
continue;
|
|
3847
|
+
}
|
|
3848
|
+
if (field.properties) {
|
|
3849
|
+
const mutableProps = field.properties;
|
|
3850
|
+
changed = resolveSentinelFields(mutableProps, entityDef, subs, declaredNames) || changed;
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
return changed;
|
|
3854
|
+
}
|
|
3855
|
+
function resolvePayloadEntitySchema(payloadEntity, setPayloadSchema, entitiesByName) {
|
|
3856
|
+
if (!payloadEntity) return false;
|
|
3857
|
+
const entity = entitiesByName.get(payloadEntity);
|
|
3858
|
+
if (!entity) return false;
|
|
3859
|
+
setPayloadSchema(entityFieldsToPayloadFields(entity));
|
|
3860
|
+
return true;
|
|
3861
|
+
}
|
|
3862
|
+
function resolveTraitTypeParamSentinels(trait, entityDef, entitiesByName, typesByName, typeArgs) {
|
|
3863
|
+
const declared = trait.typeParams ?? [];
|
|
3864
|
+
const subs = /* @__PURE__ */ new Map();
|
|
3865
|
+
const declaredNames = /* @__PURE__ */ new Set();
|
|
3866
|
+
for (const p of declared) {
|
|
3867
|
+
declaredNames.add(p.name);
|
|
3868
|
+
const argValue = typeArgs?.[p.name];
|
|
3869
|
+
let sub;
|
|
3870
|
+
if (argValue !== void 0) {
|
|
3871
|
+
sub = resolveTypeArgValue(argValue, entitiesByName, typesByName);
|
|
3872
|
+
} else if (p.kind === "Entity" && entityDef) {
|
|
3873
|
+
sub = { kind: "entity", entity: entityDef };
|
|
3874
|
+
} else if (p.default) {
|
|
3875
|
+
sub = resolveTypeArgValue(p.default, entitiesByName, typesByName);
|
|
3876
|
+
}
|
|
3877
|
+
if (sub) subs.set(p.name, sub);
|
|
3878
|
+
}
|
|
3879
|
+
let changed = false;
|
|
3880
|
+
for (const emit of trait.emits ?? []) {
|
|
3881
|
+
if (!emit.payloadSchema) continue;
|
|
3882
|
+
if (resolvePayloadEntitySchema(
|
|
3883
|
+
emit.payloadEntity,
|
|
3884
|
+
(schema2) => {
|
|
3885
|
+
emit.payloadSchema = schema2;
|
|
3886
|
+
},
|
|
3887
|
+
entitiesByName
|
|
3888
|
+
)) {
|
|
3889
|
+
changed = true;
|
|
3890
|
+
continue;
|
|
3891
|
+
}
|
|
3892
|
+
const schema = emit.payloadSchema;
|
|
3893
|
+
if (flattenBareEntityPayload(schema, entityDef, subs)) {
|
|
3894
|
+
changed = true;
|
|
3895
|
+
} else {
|
|
3896
|
+
changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
for (const ev of trait.stateMachine?.events ?? []) {
|
|
3900
|
+
if (!ev.payloadSchema) continue;
|
|
3901
|
+
if (resolvePayloadEntitySchema(
|
|
3902
|
+
ev.payloadEntity,
|
|
3903
|
+
(schema2) => {
|
|
3904
|
+
ev.payloadSchema = schema2;
|
|
3905
|
+
},
|
|
3906
|
+
entitiesByName
|
|
3907
|
+
)) {
|
|
3908
|
+
changed = true;
|
|
3909
|
+
continue;
|
|
3910
|
+
}
|
|
3911
|
+
const schema = ev.payloadSchema;
|
|
3912
|
+
if (flattenBareEntityPayload(schema, entityDef, subs)) {
|
|
3913
|
+
changed = true;
|
|
3914
|
+
} else {
|
|
3915
|
+
changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
return changed;
|
|
3919
|
+
}
|
|
3920
|
+
function resolveOrbitalTypeParamSentinels(traits, primaryEntity, auxiliaryEntities, orbitalTypes) {
|
|
3921
|
+
const entitiesByName = /* @__PURE__ */ new Map();
|
|
3922
|
+
entitiesByName.set(primaryEntity.name, primaryEntity);
|
|
3923
|
+
for (const e of auxiliaryEntities) entitiesByName.set(e.name, e);
|
|
3924
|
+
const typesByName = orbitalTypes ?? {};
|
|
3925
|
+
for (const rt of traits) {
|
|
3926
|
+
const entityDef = rt.trait.linkedEntity ? entitiesByName.get(rt.trait.linkedEntity) : void 0;
|
|
3927
|
+
resolveTraitTypeParamSentinels(rt.trait, entityDef, entitiesByName, typesByName, rt.typeArgs);
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3640
3931
|
// src/resolver/reference-resolver.ts
|
|
3641
3932
|
var refResolverLog = createLogger("almadar:runtime:ref-resolver");
|
|
3642
3933
|
function indexOrbitalNodes(orbital, idIndex) {
|
|
@@ -3910,6 +4201,25 @@ function renameTraitEmbedsInValue(node, subs) {
|
|
|
3910
4201
|
}
|
|
3911
4202
|
return next;
|
|
3912
4203
|
}
|
|
4204
|
+
function renameEntityNameTokensInValue(node, entitySubs) {
|
|
4205
|
+
if (node === null || node === void 0) return node;
|
|
4206
|
+
if (typeof node === "string") {
|
|
4207
|
+
if (!node.startsWith("@")) return node;
|
|
4208
|
+
const rest = node.slice(1);
|
|
4209
|
+
const dot = rest.search(/[.[]/);
|
|
4210
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
4211
|
+
const suffix = dot === -1 ? "" : rest.slice(dot);
|
|
4212
|
+
const to = entitySubs.get(name);
|
|
4213
|
+
return to === void 0 ? node : `@${to}${suffix}`;
|
|
4214
|
+
}
|
|
4215
|
+
if (Array.isArray(node)) return node.map((item) => renameEntityNameTokensInValue(item, entitySubs));
|
|
4216
|
+
if (typeof node !== "object") return node;
|
|
4217
|
+
const next = {};
|
|
4218
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4219
|
+
next[key] = renameEntityNameTokensInValue(value, entitySubs);
|
|
4220
|
+
}
|
|
4221
|
+
return next;
|
|
4222
|
+
}
|
|
3913
4223
|
function renameTraitEmbeds(trait, subs) {
|
|
3914
4224
|
if (subs.size === 0) return trait;
|
|
3915
4225
|
const sm = trait.stateMachine;
|
|
@@ -3956,6 +4266,36 @@ function findTraitEntryInOrbital(orbital, localName) {
|
|
|
3956
4266
|
}
|
|
3957
4267
|
return null;
|
|
3958
4268
|
}
|
|
4269
|
+
function homeOrbitalConfigForTrait(imported, traitName) {
|
|
4270
|
+
for (const o of importedOrbitals(imported)) {
|
|
4271
|
+
if (findTraitEntryInOrbital(o, traitName)) return o.config;
|
|
4272
|
+
}
|
|
4273
|
+
return void 0;
|
|
4274
|
+
}
|
|
4275
|
+
function findPageEntryInOrbital(orbital, localName) {
|
|
4276
|
+
for (const pageRef of orbital.pages ?? []) {
|
|
4277
|
+
if (typeof pageRef === "string") continue;
|
|
4278
|
+
if (!("ref" in pageRef)) {
|
|
4279
|
+
if (pageRef.name === localName) return pageRef;
|
|
4280
|
+
continue;
|
|
4281
|
+
}
|
|
4282
|
+
const refObj = pageRef;
|
|
4283
|
+
if (parsePageRef(refObj.ref)?.pageName === localName) return refObj;
|
|
4284
|
+
}
|
|
4285
|
+
return null;
|
|
4286
|
+
}
|
|
4287
|
+
function toPageTraitRef(traitRef) {
|
|
4288
|
+
if (typeof traitRef === "string") return { ref: traitRef };
|
|
4289
|
+
if ("stateMachine" in traitRef) return { ref: traitRef.name };
|
|
4290
|
+
const refObj = traitRef;
|
|
4291
|
+
return {
|
|
4292
|
+
ref: refObj.name ?? refObj.ref,
|
|
4293
|
+
...refObj.refId !== void 0 ? { refId: refObj.refId } : {},
|
|
4294
|
+
...refObj.linkedEntity !== void 0 ? { linkedEntity: refObj.linkedEntity } : {},
|
|
4295
|
+
...refObj.linkedEntityId !== void 0 ? { linkedEntityId: refObj.linkedEntityId } : {},
|
|
4296
|
+
...refObj.config !== void 0 ? { config: refObj.config } : {}
|
|
4297
|
+
};
|
|
4298
|
+
}
|
|
3959
4299
|
function traitEmbedNamesOf(trait) {
|
|
3960
4300
|
const found = /* @__PURE__ */ new Set();
|
|
3961
4301
|
const walk = (node) => {
|
|
@@ -3975,34 +4315,183 @@ function traitEmbedNamesOf(trait) {
|
|
|
3975
4315
|
if (typeof node !== "object") return;
|
|
3976
4316
|
for (const value of Object.values(node)) walk(value);
|
|
3977
4317
|
};
|
|
3978
|
-
for (const t of trait.stateMachine?.transitions ?? [])
|
|
3979
|
-
|
|
4318
|
+
for (const t of trait.stateMachine?.transitions ?? []) {
|
|
4319
|
+
walk(t.guard);
|
|
4320
|
+
walk(t.effects);
|
|
4321
|
+
}
|
|
4322
|
+
for (const tick of trait.ticks ?? []) {
|
|
4323
|
+
walk(tick.guard);
|
|
4324
|
+
walk(tick.effects);
|
|
4325
|
+
}
|
|
3980
4326
|
for (const field of Object.values(trait.config ?? {})) walk(field.default);
|
|
3981
|
-
return [...found];
|
|
4327
|
+
return [...found].sort();
|
|
3982
4328
|
}
|
|
3983
|
-
function
|
|
4329
|
+
function resolveForwardedSiblingConfigFrom(trait, parentChain, orbitalConfig, schemaConfig) {
|
|
3984
4330
|
const declared = trait.config;
|
|
3985
|
-
|
|
3986
|
-
|
|
4331
|
+
if (!declared) return trait;
|
|
4332
|
+
const next = resolveConfigForwards(declared, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
|
|
4333
|
+
return next ? { ...trait, config: next } : trait;
|
|
4334
|
+
}
|
|
4335
|
+
function callSiteRungValue(rungConfig, knob) {
|
|
4336
|
+
const entry = rungConfig[knob];
|
|
4337
|
+
if (entry === void 0) return void 0;
|
|
4338
|
+
return isCallSiteConfigDeclaration(entry) ? entry.default : entry;
|
|
4339
|
+
}
|
|
4340
|
+
function walkConfigForwardChain(forward, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
|
|
4341
|
+
let knob = forward.slice("@config.".length);
|
|
4342
|
+
if (knob.length === 0 || knob.includes(".")) return void 0;
|
|
4343
|
+
let value;
|
|
4344
|
+
let currentForward = forward;
|
|
4345
|
+
for (const rungConfig of parentChain) {
|
|
4346
|
+
const rungValue = callSiteRungValue(rungConfig, knob);
|
|
4347
|
+
if (rungValue === void 0 || rungValue === currentForward) continue;
|
|
4348
|
+
if (typeof rungValue === "string" && rungValue.startsWith("@config.")) {
|
|
4349
|
+
const nextKnob = rungValue.slice("@config.".length);
|
|
4350
|
+
if (nextKnob.length === 0 || nextKnob.includes(".") || nextKnob === knob) continue;
|
|
4351
|
+
knob = nextKnob;
|
|
4352
|
+
currentForward = rungValue;
|
|
4353
|
+
continue;
|
|
4354
|
+
}
|
|
4355
|
+
value = rungValue;
|
|
4356
|
+
break;
|
|
4357
|
+
}
|
|
4358
|
+
if (value === void 0 || value === currentForward) value = orbitalConfig?.[knob]?.default;
|
|
4359
|
+
if (value === void 0 || value === currentForward) value = upstreamOrbitalConfig?.[knob]?.default;
|
|
4360
|
+
if (value === void 0 || value === currentForward) value = upstreamSchemaConfig?.[knob]?.default;
|
|
4361
|
+
if (value === void 0 || value === currentForward) value = schemaConfig?.[knob]?.default;
|
|
4362
|
+
if (value === void 0 || value === currentForward) return void 0;
|
|
4363
|
+
return value;
|
|
4364
|
+
}
|
|
4365
|
+
function resolveConfigForwards(declared, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
|
|
3987
4366
|
let next;
|
|
3988
4367
|
for (const [key, field] of Object.entries(declared)) {
|
|
3989
4368
|
const forward = field.default;
|
|
3990
4369
|
if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
|
|
3991
|
-
const
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
4370
|
+
const value = walkConfigForwardChain(
|
|
4371
|
+
forward,
|
|
4372
|
+
parentChain,
|
|
4373
|
+
orbitalConfig,
|
|
4374
|
+
upstreamOrbitalConfig,
|
|
4375
|
+
upstreamSchemaConfig,
|
|
4376
|
+
schemaConfig
|
|
4377
|
+
);
|
|
4378
|
+
if (value === void 0) continue;
|
|
3995
4379
|
next ??= { ...declared };
|
|
3996
|
-
next[key] = { ...field, default: value };
|
|
4380
|
+
next[key] = { ...field, default: value, forwardedFrom: forward };
|
|
3997
4381
|
}
|
|
3998
|
-
return next
|
|
4382
|
+
return next;
|
|
4383
|
+
}
|
|
4384
|
+
function resolveCallSiteConfigForwards(config, parentChain, orbitalConfig, schemaConfig) {
|
|
4385
|
+
let next;
|
|
4386
|
+
for (const [key, entry] of Object.entries(config)) {
|
|
4387
|
+
const forward = isCallSiteConfigDeclaration(entry) ? entry.default : entry;
|
|
4388
|
+
if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
|
|
4389
|
+
const value = walkConfigForwardChain(forward, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
|
|
4390
|
+
if (value === void 0) continue;
|
|
4391
|
+
next ??= { ...config };
|
|
4392
|
+
next[key] = isCallSiteConfigDeclaration(entry) ? { ...entry, default: value, forwardedFrom: forward } : value;
|
|
4393
|
+
}
|
|
4394
|
+
return next;
|
|
4395
|
+
}
|
|
4396
|
+
function traitRefEmbedNamesOf(traitRef) {
|
|
4397
|
+
if (typeof traitRef === "string") return [];
|
|
4398
|
+
return traitEmbedNamesOf(traitRef);
|
|
4399
|
+
}
|
|
4400
|
+
function traitRefLocalName(traitRef) {
|
|
4401
|
+
if (typeof traitRef === "string") {
|
|
4402
|
+
return parseImportedTraitRef(traitRef)?.traitName ?? traitRef;
|
|
4403
|
+
}
|
|
4404
|
+
if ("stateMachine" in traitRef) return traitRef.name;
|
|
4405
|
+
const refObj = traitRef;
|
|
4406
|
+
return refObj.name ?? parseImportedTraitRef(refObj.ref)?.traitName ?? refObj.ref;
|
|
4407
|
+
}
|
|
4408
|
+
function traitRefConfigOf(traitRef) {
|
|
4409
|
+
if (typeof traitRef === "string") return void 0;
|
|
4410
|
+
return traitRef.config;
|
|
4411
|
+
}
|
|
4412
|
+
function buildEmbedGraph(traitRefs) {
|
|
4413
|
+
const out = /* @__PURE__ */ new Map();
|
|
4414
|
+
for (const traitRef of traitRefs) {
|
|
4415
|
+
const referrerName = traitRefLocalName(traitRef);
|
|
4416
|
+
if (!referrerName) continue;
|
|
4417
|
+
for (const child of traitRefEmbedNamesOf(traitRef)) {
|
|
4418
|
+
if (child === referrerName) continue;
|
|
4419
|
+
if (!out.has(child)) out.set(child, referrerName);
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
return out;
|
|
3999
4423
|
}
|
|
4000
|
-
function
|
|
4424
|
+
function embedderChain(localName, traitRefs, graph) {
|
|
4425
|
+
const chain = [];
|
|
4426
|
+
const visited = /* @__PURE__ */ new Set([localName]);
|
|
4427
|
+
let cur = graph.get(localName);
|
|
4428
|
+
let hops = 0;
|
|
4429
|
+
while (cur !== void 0 && !visited.has(cur) && hops < traitRefs.length) {
|
|
4430
|
+
visited.add(cur);
|
|
4431
|
+
hops++;
|
|
4432
|
+
const entry = traitRefs.find((t) => traitRefLocalName(t) === cur);
|
|
4433
|
+
const entryConfig = entry ? traitRefConfigOf(entry) : void 0;
|
|
4434
|
+
if (entryConfig) chain.push(entryConfig);
|
|
4435
|
+
cur = graph.get(cur);
|
|
4436
|
+
}
|
|
4437
|
+
return chain;
|
|
4438
|
+
}
|
|
4439
|
+
function resolveEmbedderConfigForward(config, localName, embedCtx, schemaConfig) {
|
|
4440
|
+
const chain = embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph);
|
|
4441
|
+
const next = resolveCallSiteConfigForwards(config, chain, embedCtx.orbitalConfig, schemaConfig);
|
|
4442
|
+
return next ? next : config;
|
|
4443
|
+
}
|
|
4444
|
+
function consumerKnownEntityRebindSubs(trait, entityIds) {
|
|
4445
|
+
const out = /* @__PURE__ */ new Map();
|
|
4446
|
+
const refs = trait.entityRefIds;
|
|
4447
|
+
if (!refs) return out;
|
|
4448
|
+
const idToConsumerName = /* @__PURE__ */ new Map();
|
|
4449
|
+
for (const [name, id] of entityIds) {
|
|
4450
|
+
if (!idToConsumerName.has(id)) idToConsumerName.set(id, name);
|
|
4451
|
+
}
|
|
4452
|
+
for (const [tokenName, entityId] of Object.entries(refs)) {
|
|
4453
|
+
const consumerName = idToConsumerName.get(entityId);
|
|
4454
|
+
if (consumerName !== void 0 && consumerName !== tokenName) {
|
|
4455
|
+
out.set(tokenName, consumerName);
|
|
4456
|
+
}
|
|
4457
|
+
}
|
|
4458
|
+
return out;
|
|
4459
|
+
}
|
|
4460
|
+
function staleEntityRebindSubs(trait, newEntity) {
|
|
4461
|
+
const out = /* @__PURE__ */ new Map();
|
|
4462
|
+
const boundId = trait.linkedEntityId;
|
|
4463
|
+
const refs = trait.entityRefIds;
|
|
4464
|
+
if (boundId && refs) {
|
|
4465
|
+
for (const [tokenName, entityId] of Object.entries(refs)) {
|
|
4466
|
+
if (entityId === boundId) out.set(tokenName, newEntity);
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
return out;
|
|
4470
|
+
}
|
|
4471
|
+
function applyLinkedEntityRename(trait, linkedEntity, entityIds) {
|
|
4001
4472
|
const atomLinked = trait.linkedEntity;
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4473
|
+
const entitySubs = consumerKnownEntityRebindSubs(trait, entityIds);
|
|
4474
|
+
if (!linkedEntity || !atomLinked || linkedEntity === atomLinked) {
|
|
4475
|
+
return rewriteEntityTypedConfigValues(rewriteEntityRefIds(trait, entitySubs, entityIds), entitySubs, entityIds);
|
|
4476
|
+
}
|
|
4477
|
+
for (const [from, to] of staleEntityRebindSubs(trait, linkedEntity)) {
|
|
4478
|
+
entitySubs.set(from, to);
|
|
4479
|
+
}
|
|
4480
|
+
entitySubs.set(atomLinked, linkedEntity);
|
|
4005
4481
|
const rename = (name) => name === atomLinked ? linkedEntity : void 0;
|
|
4482
|
+
const sm = trait.stateMachine;
|
|
4483
|
+
const rebound = {
|
|
4484
|
+
...trait,
|
|
4485
|
+
linkedEntity,
|
|
4486
|
+
linkedEntityId: entityIds.get(linkedEntity)
|
|
4487
|
+
};
|
|
4488
|
+
if (!sm) {
|
|
4489
|
+
return rewriteEntityTypedConfigValues(
|
|
4490
|
+
renamePayloadEntityMarkers(rewriteEntityRefIds(rebound, entitySubs, entityIds), rename),
|
|
4491
|
+
entitySubs,
|
|
4492
|
+
entityIds
|
|
4493
|
+
);
|
|
4494
|
+
}
|
|
4006
4495
|
const nextTransitions = (sm.transitions ?? []).map((t) => {
|
|
4007
4496
|
const nextEffects = t.effects ? renameEntityInEffects(
|
|
4008
4497
|
t.effects,
|
|
@@ -4017,11 +4506,18 @@ function applyLinkedEntityRename(trait, linkedEntity) {
|
|
|
4017
4506
|
to: linkedEntity,
|
|
4018
4507
|
transitionCount: nextTransitions.length
|
|
4019
4508
|
});
|
|
4020
|
-
return
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4509
|
+
return rewriteEntityTypedConfigValues(
|
|
4510
|
+
renamePayloadEntityMarkers(
|
|
4511
|
+
rewriteEntityRefIds(
|
|
4512
|
+
{ ...rebound, stateMachine: { ...sm, transitions: nextTransitions } },
|
|
4513
|
+
entitySubs,
|
|
4514
|
+
entityIds
|
|
4515
|
+
),
|
|
4516
|
+
rename
|
|
4517
|
+
),
|
|
4518
|
+
entitySubs,
|
|
4519
|
+
entityIds
|
|
4520
|
+
);
|
|
4025
4521
|
}
|
|
4026
4522
|
function resolveEntityTokensById(trait, idIndex) {
|
|
4027
4523
|
const map = trait.entityRefIds;
|
|
@@ -4105,7 +4601,7 @@ function resolveConfigRefsById(trait, idIndex) {
|
|
|
4105
4601
|
});
|
|
4106
4602
|
return { ...trait, config: nextSchema };
|
|
4107
4603
|
}
|
|
4108
|
-
function applyEventRenames(trait, renames) {
|
|
4604
|
+
function applyEventRenames(trait, renames, keptFinalNames) {
|
|
4109
4605
|
if (!renames || Object.keys(renames).length === 0) return trait;
|
|
4110
4606
|
const rename = (k) => k !== void 0 && k in renames ? renames[k] : k;
|
|
4111
4607
|
const sm = trait.stateMachine;
|
|
@@ -4135,7 +4631,9 @@ function applyEventRenames(trait, renames) {
|
|
|
4135
4631
|
);
|
|
4136
4632
|
const nextListens = (trait.listens ?? []).map((l) => {
|
|
4137
4633
|
const sourced = l.source !== void 0 && l.source.kind !== "any";
|
|
4138
|
-
const
|
|
4634
|
+
const sourceTraitName = l.source && l.source.kind !== "any" ? l.source.trait : void 0;
|
|
4635
|
+
const fromThisImport = sourceTraitName !== void 0 && keptFinalNames !== void 0 && keptFinalNames.has(sourceTraitName);
|
|
4636
|
+
const nextEvent = sourced && !fromThisImport ? l.event : rename(l.event) ?? l.event;
|
|
4139
4637
|
const nextTriggers = rename(l.triggers) ?? l.triggers;
|
|
4140
4638
|
return nextEvent === l.event && nextTriggers === l.triggers ? l : { ...l, event: nextEvent, triggers: nextTriggers };
|
|
4141
4639
|
});
|
|
@@ -4170,17 +4668,44 @@ function applyEventRenamesToCallSiteConfig(config, declared, renames) {
|
|
|
4170
4668
|
}
|
|
4171
4669
|
return touched ? next : config;
|
|
4172
4670
|
}
|
|
4671
|
+
function resolvedKnobValues(before, after, knobs) {
|
|
4672
|
+
const out = /* @__PURE__ */ new Map();
|
|
4673
|
+
if (knobs.length === 0) return out;
|
|
4674
|
+
const knobSet = new Set(knobs);
|
|
4675
|
+
const beforeEmits = before.emits ?? [];
|
|
4676
|
+
const afterEmits = after.emits ?? [];
|
|
4677
|
+
for (let i = 0; i < beforeEmits.length; i++) {
|
|
4678
|
+
const knob = configRefEventKnob(beforeEmits[i].event);
|
|
4679
|
+
if (knob !== void 0 && knobSet.has(knob)) out.set(knob, afterEmits[i].event);
|
|
4680
|
+
}
|
|
4681
|
+
return out;
|
|
4682
|
+
}
|
|
4683
|
+
function foldEventRenameOntoDeclaredKnobs(trait, resolved, eventRenames) {
|
|
4684
|
+
if (!eventRenames || resolved.size === 0 || !trait.config) return trait;
|
|
4685
|
+
let nextConfig;
|
|
4686
|
+
for (const [knob, resolvedValue] of resolved) {
|
|
4687
|
+
const renamed = eventRenames[resolvedValue];
|
|
4688
|
+
if (renamed === void 0 || renamed === resolvedValue) continue;
|
|
4689
|
+
const field = trait.config[knob];
|
|
4690
|
+
if (!field) continue;
|
|
4691
|
+
nextConfig ??= { ...trait.config };
|
|
4692
|
+
nextConfig[knob] = { ...field, default: renamed };
|
|
4693
|
+
}
|
|
4694
|
+
return nextConfig ? { ...trait, config: nextConfig } : trait;
|
|
4695
|
+
}
|
|
4173
4696
|
function resolveConfigRefEmitNames(trait, callSiteConfig) {
|
|
4174
4697
|
const emits = trait.emits ?? [];
|
|
4175
4698
|
const hasRef = emits.some((em) => configRefEventKnob(em.event) !== void 0);
|
|
4176
|
-
if (!hasRef) return { trait, errors: [] };
|
|
4699
|
+
if (!hasRef) return { trait, errors: [], resolvedKnobs: [] };
|
|
4177
4700
|
const effectiveConfig = {
|
|
4178
4701
|
...normalizeCallSiteConfigToValues(trait.config) ?? {},
|
|
4179
4702
|
...normalizeCallSiteConfigToValues(callSiteConfig) ?? {}
|
|
4180
4703
|
};
|
|
4181
4704
|
const errors = [];
|
|
4705
|
+
const resolvedTriples = [];
|
|
4182
4706
|
const nextEmits = emits.map((em) => {
|
|
4183
|
-
|
|
4707
|
+
const knob = configRefEventKnob(em.event);
|
|
4708
|
+
if (knob === void 0) return em;
|
|
4184
4709
|
const result = resolveConfigRefEventName(em.event, trait.config, effectiveConfig);
|
|
4185
4710
|
if (!result.ok) {
|
|
4186
4711
|
errors.push(
|
|
@@ -4193,117 +4718,1316 @@ function resolveConfigRefEmitNames(trait, callSiteConfig) {
|
|
|
4193
4718
|
ref: em.event,
|
|
4194
4719
|
resolved: result.value
|
|
4195
4720
|
});
|
|
4721
|
+
resolvedTriples.push({ knob, from: em.event, to: result.value });
|
|
4196
4722
|
return { ...em, event: result.value };
|
|
4197
4723
|
});
|
|
4198
|
-
|
|
4724
|
+
const sm = trait.stateMachine;
|
|
4725
|
+
const nextEvents = resolvedTriples.length > 0 && sm ? sm.events.map((ev) => {
|
|
4726
|
+
const hit = resolvedTriples.find((t) => t.from === ev.key);
|
|
4727
|
+
return hit ? { ...ev, key: hit.to } : ev;
|
|
4728
|
+
}) : sm?.events;
|
|
4729
|
+
return {
|
|
4730
|
+
trait: {
|
|
4731
|
+
...trait,
|
|
4732
|
+
emits: nextEmits,
|
|
4733
|
+
...sm && nextEvents !== sm.events ? { stateMachine: { ...sm, events: nextEvents } } : {}
|
|
4734
|
+
},
|
|
4735
|
+
errors,
|
|
4736
|
+
resolvedKnobs: resolvedTriples.map((t) => t.knob)
|
|
4737
|
+
};
|
|
4199
4738
|
}
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4739
|
+
function foldCallSiteConfigOntoTrait(trait, callSiteConfig) {
|
|
4740
|
+
if (!callSiteConfig) return trait;
|
|
4741
|
+
const declared = trait.config;
|
|
4742
|
+
const overrideValues = {};
|
|
4743
|
+
const overriddenKeys = /* @__PURE__ */ new Set();
|
|
4744
|
+
const newDeclarations = {};
|
|
4745
|
+
for (const [key, entry] of Object.entries(callSiteConfig)) {
|
|
4746
|
+
const isDecl = isCallSiteConfigDeclaration(entry);
|
|
4747
|
+
const value = isDecl ? entry.default : entry;
|
|
4748
|
+
if (declared && key in declared) {
|
|
4749
|
+
if (value !== void 0) {
|
|
4750
|
+
overrideValues[key] = value;
|
|
4751
|
+
overriddenKeys.add(key);
|
|
4752
|
+
}
|
|
4753
|
+
} else if (isDecl) {
|
|
4754
|
+
newDeclarations[key] = entry;
|
|
4755
|
+
}
|
|
4756
|
+
}
|
|
4757
|
+
if (overriddenKeys.size === 0 && Object.keys(newDeclarations).length === 0) {
|
|
4758
|
+
return trait;
|
|
4759
|
+
}
|
|
4760
|
+
let nextConfig = overrideDeclaredKnobs(declared ?? {}, overrideValues);
|
|
4761
|
+
if (overriddenKeys.size > 0) {
|
|
4762
|
+
const patched = { ...nextConfig };
|
|
4763
|
+
for (const key of overriddenKeys) {
|
|
4764
|
+
const field = patched[key];
|
|
4765
|
+
if (!field) continue;
|
|
4766
|
+
const entry = callSiteConfig[key];
|
|
4767
|
+
const entryDecl = isCallSiteConfigDeclaration(entry) ? entry : void 0;
|
|
4768
|
+
patched[key] = {
|
|
4769
|
+
...field,
|
|
4770
|
+
forwardedFrom: entryDecl?.forwardedFrom,
|
|
4771
|
+
// The atom's OWN `refId` (a reference-config field's declared
|
|
4772
|
+
// default names a SPECIFIC node by id) describes the ATOM's OWN
|
|
4773
|
+
// `default`, not whatever this override just replaced it with —
|
|
4774
|
+
// carrying it forward unchanged left a STALE id bound to the NEW
|
|
4775
|
+
// literal string, so the id-index's "current name" correction
|
|
4776
|
+
// (`resolveConfigRefsById`) silently rewrote the override BACK to
|
|
4777
|
+
// the atom's own default target — found via std-notes'
|
|
4778
|
+
// `NoteGlobalSearch`: `idleContent`'s override says `@trait.
|
|
4779
|
+
// NoteCatalog` but the atom's OWN stale `refId` (still pointing at
|
|
4780
|
+
// `AppSearchIdleHint`, the atom's default) rewrote the sibling-pull
|
|
4781
|
+
// target back to it (rung 2: an override with no id of its own
|
|
4782
|
+
// names no id, so it must clear the atom's). An override that
|
|
4783
|
+
// carries ITS OWN `refId` (an annotated, id-aware override) wins
|
|
4784
|
+
// instead — same precedence a `default` override already has.
|
|
4785
|
+
refId: entryDecl?.refId,
|
|
4786
|
+
...entryDecl?.label !== void 0 ? { label: entryDecl.label } : {},
|
|
4787
|
+
...entryDecl?.description !== void 0 ? { description: entryDecl.description } : {},
|
|
4788
|
+
...entryDecl?.synonyms !== void 0 ? { synonyms: entryDecl.synonyms } : {},
|
|
4789
|
+
...entryDecl?.tier !== void 0 ? { tier: entryDecl.tier } : {}
|
|
4790
|
+
};
|
|
4217
4791
|
}
|
|
4792
|
+
nextConfig = patched;
|
|
4218
4793
|
}
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
this.loaderInitialized = true;
|
|
4222
|
-
try {
|
|
4223
|
-
const { ExternalOrbitalLoader } = await import('./external-loader-YUUADLAP.js');
|
|
4224
|
-
this.loader = new ExternalOrbitalLoader(this.options);
|
|
4225
|
-
} catch {
|
|
4226
|
-
}
|
|
4794
|
+
if (Object.keys(newDeclarations).length > 0) {
|
|
4795
|
+
nextConfig = { ...nextConfig, ...newDeclarations };
|
|
4227
4796
|
}
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
const imports = importsResult.data;
|
|
4245
|
-
imports.idIndex = buildIdIndex(orbital, imports.orbitals);
|
|
4246
|
-
const entityResult = this.resolveEntity(orbital.entity, imports);
|
|
4247
|
-
if (!entityResult.success) {
|
|
4248
|
-
errors.push(...entityResult.errors);
|
|
4249
|
-
}
|
|
4250
|
-
const traitsResult = this.resolveTraits(orbital.traits, imports);
|
|
4251
|
-
if (!traitsResult.success) {
|
|
4252
|
-
errors.push(...traitsResult.errors);
|
|
4253
|
-
}
|
|
4254
|
-
const pagesResult = this.resolvePages(orbital.pages, imports);
|
|
4255
|
-
if (!pagesResult.success) {
|
|
4256
|
-
errors.push(...pagesResult.errors);
|
|
4257
|
-
}
|
|
4258
|
-
if (errors.length > 0) {
|
|
4259
|
-
return { success: false, errors };
|
|
4260
|
-
}
|
|
4261
|
-
if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
|
|
4262
|
-
return { success: false, errors: ["Internal error: unexpected failure state"] };
|
|
4263
|
-
}
|
|
4264
|
-
const pullErrors = await this.pullSiblingTraits(traitsResult.data, imports, importChain);
|
|
4265
|
-
if (pullErrors.length > 0) {
|
|
4266
|
-
return { success: false, errors: pullErrors };
|
|
4267
|
-
}
|
|
4268
|
-
for (const resolvedTrait of traitsResult.data) {
|
|
4269
|
-
resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
|
|
4270
|
-
resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
|
|
4797
|
+
return { ...trait, config: nextConfig };
|
|
4798
|
+
}
|
|
4799
|
+
var ROW_ALIAS_TOKEN_PREFIXES = ["@entity.", "@item.", "@row."];
|
|
4800
|
+
var ROW_ALIAS_ROOTS = /* @__PURE__ */ new Set(["@entity", "@item", "@row"]);
|
|
4801
|
+
var FIELD_NAME_MEMBER_KEYS = ["key", "name", "field"];
|
|
4802
|
+
function rewriteEntityFieldTokensInValue(node, subs) {
|
|
4803
|
+
if (node === null || node === void 0) return node;
|
|
4804
|
+
if (typeof node === "string") {
|
|
4805
|
+
for (const prefix of ROW_ALIAS_TOKEN_PREFIXES) {
|
|
4806
|
+
if (!node.startsWith(prefix)) continue;
|
|
4807
|
+
const rest = node.slice(prefix.length);
|
|
4808
|
+
const dot = rest.search(/[.[]/);
|
|
4809
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
4810
|
+
const suffix = dot === -1 ? "" : rest.slice(dot);
|
|
4811
|
+
const to = subs.get(name);
|
|
4812
|
+
return to === void 0 ? node : `${prefix}${to}${suffix}`;
|
|
4271
4813
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4814
|
+
return node;
|
|
4815
|
+
}
|
|
4816
|
+
if (Array.isArray(node)) {
|
|
4817
|
+
if (node.length >= 3 && node[0] === "object/get" && typeof node[1] === "string" && ROW_ALIAS_ROOTS.has(node[1]) && typeof node[2] === "string") {
|
|
4818
|
+
const to = subs.get(node[2]);
|
|
4819
|
+
if (to !== void 0) {
|
|
4820
|
+
const rewritten = node.map((item) => rewriteEntityFieldTokensInValue(item, subs));
|
|
4821
|
+
rewritten[2] = to;
|
|
4822
|
+
return rewritten;
|
|
4277
4823
|
}
|
|
4278
|
-
throw e;
|
|
4279
4824
|
}
|
|
4280
|
-
return
|
|
4281
|
-
success: true,
|
|
4282
|
-
data: {
|
|
4283
|
-
name: orbital.name,
|
|
4284
|
-
entity: entityResult.data.entity,
|
|
4285
|
-
entitySource: entityResult.data.source,
|
|
4286
|
-
traits: traitsResult.data,
|
|
4287
|
-
pages: pagesResult.data,
|
|
4288
|
-
imports,
|
|
4289
|
-
original: orbital
|
|
4290
|
-
},
|
|
4291
|
-
warnings
|
|
4292
|
-
};
|
|
4825
|
+
return node.map((item) => rewriteEntityFieldTokensInValue(item, subs));
|
|
4293
4826
|
}
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4827
|
+
if (typeof node !== "object") return node;
|
|
4828
|
+
const next = {};
|
|
4829
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4830
|
+
if (FIELD_NAME_MEMBER_KEYS.includes(key) && typeof value === "string") {
|
|
4831
|
+
const to = subs.get(value);
|
|
4832
|
+
next[key] = to === void 0 ? value : to;
|
|
4833
|
+
continue;
|
|
4834
|
+
}
|
|
4835
|
+
next[key] = rewriteEntityFieldTokensInValue(value, subs);
|
|
4836
|
+
}
|
|
4837
|
+
return next;
|
|
4838
|
+
}
|
|
4839
|
+
function rewriteBareFieldNameConfigDefault(value, fieldSubs) {
|
|
4840
|
+
if (typeof value === "string") {
|
|
4841
|
+
if (value === "" || value.startsWith("@")) return value;
|
|
4842
|
+
return fieldSubs.get(value) ?? value;
|
|
4843
|
+
}
|
|
4844
|
+
if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
|
|
4845
|
+
return value.map((v) => v === "" || v.startsWith("@") ? v : fieldSubs.get(v) ?? v);
|
|
4846
|
+
}
|
|
4847
|
+
return value;
|
|
4848
|
+
}
|
|
4849
|
+
function rewriteEntityFieldsInConfig(config, fieldSubs) {
|
|
4850
|
+
if (fieldSubs.size === 0 || !config) return config;
|
|
4851
|
+
const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
|
|
4852
|
+
const nextConfig = {};
|
|
4853
|
+
for (const [key, field] of Object.entries(config)) {
|
|
4854
|
+
if (field.default === void 0) {
|
|
4855
|
+
nextConfig[key] = field;
|
|
4856
|
+
continue;
|
|
4857
|
+
}
|
|
4858
|
+
const afterSigils = rewrite(field.default);
|
|
4859
|
+
nextConfig[key] = {
|
|
4860
|
+
...field,
|
|
4861
|
+
default: rewriteBareFieldNameConfigDefault(afterSigils, fieldSubs)
|
|
4862
|
+
};
|
|
4863
|
+
}
|
|
4864
|
+
return nextConfig;
|
|
4865
|
+
}
|
|
4866
|
+
function rewriteEntityFieldsInTrait(trait, fieldSubs) {
|
|
4867
|
+
if (fieldSubs.size === 0) return trait;
|
|
4868
|
+
const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
|
|
4869
|
+
const next = { ...trait };
|
|
4870
|
+
const sm = trait.stateMachine;
|
|
4871
|
+
if (sm) {
|
|
4872
|
+
next.stateMachine = {
|
|
4873
|
+
...sm,
|
|
4874
|
+
transitions: (sm.transitions ?? []).map((t) => ({
|
|
4875
|
+
...t,
|
|
4876
|
+
...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
|
|
4877
|
+
...t.effects ? { effects: rewrite(t.effects) } : {}
|
|
4878
|
+
}))
|
|
4879
|
+
};
|
|
4880
|
+
}
|
|
4881
|
+
if (trait.ticks) {
|
|
4882
|
+
next.ticks = trait.ticks.map((tick) => ({
|
|
4883
|
+
...tick,
|
|
4884
|
+
...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
|
|
4885
|
+
effects: rewrite(tick.effects)
|
|
4886
|
+
}));
|
|
4887
|
+
}
|
|
4888
|
+
if (trait.listens) {
|
|
4889
|
+
next.listens = trait.listens.map((l) => ({
|
|
4890
|
+
...l,
|
|
4891
|
+
...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
|
|
4892
|
+
...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
|
|
4893
|
+
}));
|
|
4894
|
+
}
|
|
4895
|
+
if (trait.initialEffects) {
|
|
4896
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
4897
|
+
}
|
|
4898
|
+
if (trait.config) {
|
|
4899
|
+
next.config = rewriteEntityFieldsInConfig(trait.config, fieldSubs);
|
|
4900
|
+
}
|
|
4901
|
+
return next;
|
|
4902
|
+
}
|
|
4903
|
+
function rewriteEntityFieldsInEntity(entity, fieldSubs) {
|
|
4904
|
+
if (fieldSubs.size === 0) return entity;
|
|
4905
|
+
const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
|
|
4906
|
+
return {
|
|
4907
|
+
...entity,
|
|
4908
|
+
fields: entity.fields.map((f) => f.name && fieldSubs.has(f.name) ? { ...f, name: fieldSubs.get(f.name) } : f),
|
|
4909
|
+
...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
|
|
4910
|
+
...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
|
|
4911
|
+
...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
|
|
4912
|
+
...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
|
|
4913
|
+
};
|
|
4914
|
+
}
|
|
4915
|
+
var USER_FIELD_PREFIX = "@user.";
|
|
4916
|
+
function directUserField(node) {
|
|
4917
|
+
if (typeof node !== "string" || !node.startsWith(USER_FIELD_PREFIX)) return void 0;
|
|
4918
|
+
const rest = node.slice(USER_FIELD_PREFIX.length);
|
|
4919
|
+
return rest.length > 0 && !/[.[]/.test(rest) ? rest : void 0;
|
|
4920
|
+
}
|
|
4921
|
+
var EQUALITY_OPS = /* @__PURE__ */ new Set(["=", "==", "!=", "!==", "eq", "neq"]);
|
|
4922
|
+
var NEGATED_EQUALITY_OPS = /* @__PURE__ */ new Set(["!=", "!==", "neq"]);
|
|
4923
|
+
function literalHaystackMembers(items) {
|
|
4924
|
+
const isListCall = items[0] === "list";
|
|
4925
|
+
const members = isListCall ? items.slice(1) : items;
|
|
4926
|
+
return members.every((v) => typeof v === "string") ? [...members] : void 0;
|
|
4927
|
+
}
|
|
4928
|
+
function rewriteRoleLiteralsInValue(node, roleFields, roles) {
|
|
4929
|
+
if (node === null || node === void 0) return node;
|
|
4930
|
+
if (Array.isArray(node)) {
|
|
4931
|
+
const head = node[0];
|
|
4932
|
+
if (typeof head === "string" && EQUALITY_OPS.has(head) && node.length === 3) {
|
|
4933
|
+
const [, left, right] = node;
|
|
4934
|
+
const leftField = directUserField(left);
|
|
4935
|
+
const rightField = directUserField(right);
|
|
4936
|
+
const userField = leftField !== void 0 && rightField === void 0 ? leftField : rightField !== void 0 && leftField === void 0 ? rightField : void 0;
|
|
4937
|
+
if (userField !== void 0 && roleFields.has(userField)) {
|
|
4938
|
+
const literalSide = leftField !== void 0 ? right : left;
|
|
4939
|
+
if (typeof literalSide === "string" && literalSide in roles) {
|
|
4940
|
+
const targets = roles[literalSide];
|
|
4941
|
+
if (targets.length === 1) {
|
|
4942
|
+
return leftField !== void 0 ? [head, left, targets[0]] : [head, targets[0], right];
|
|
4943
|
+
}
|
|
4944
|
+
const includesExpr = ["array/includes", [...targets], leftField !== void 0 ? left : right];
|
|
4945
|
+
return NEGATED_EQUALITY_OPS.has(head) ? ["not", includesExpr] : includesExpr;
|
|
4946
|
+
}
|
|
4947
|
+
}
|
|
4948
|
+
}
|
|
4949
|
+
if (head === "array/includes" && node.length === 3 && Array.isArray(node[1])) {
|
|
4950
|
+
const needleField = directUserField(node[2]);
|
|
4951
|
+
if (needleField !== void 0 && roleFields.has(needleField)) {
|
|
4952
|
+
const members = literalHaystackMembers(node[1]);
|
|
4953
|
+
if (members !== void 0) {
|
|
4954
|
+
const expanded = [];
|
|
4955
|
+
for (const literal of members) {
|
|
4956
|
+
const mapped = roles[literal];
|
|
4957
|
+
if (mapped) {
|
|
4958
|
+
for (const target of mapped) if (!expanded.includes(target)) expanded.push(target);
|
|
4959
|
+
} else if (!expanded.includes(literal)) {
|
|
4960
|
+
expanded.push(literal);
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
const isListCall = node[1][0] === "list";
|
|
4964
|
+
return ["array/includes", isListCall ? ["list", ...expanded] : expanded, node[2]];
|
|
4965
|
+
}
|
|
4966
|
+
}
|
|
4967
|
+
}
|
|
4968
|
+
return node.map((item) => rewriteRoleLiteralsInValue(item, roleFields, roles));
|
|
4969
|
+
}
|
|
4970
|
+
if (typeof node !== "object") return node;
|
|
4971
|
+
const next = {};
|
|
4972
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4973
|
+
next[key] = rewriteRoleLiteralsInValue(value, roleFields, roles);
|
|
4974
|
+
}
|
|
4975
|
+
return next;
|
|
4976
|
+
}
|
|
4977
|
+
function rewriteRoleLiteralsInTrait(trait, roleFields, roles) {
|
|
4978
|
+
if (roleFields.size === 0 || Object.keys(roles).length === 0) return trait;
|
|
4979
|
+
const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
|
|
4980
|
+
const next = { ...trait };
|
|
4981
|
+
const sm = trait.stateMachine;
|
|
4982
|
+
if (sm) {
|
|
4983
|
+
next.stateMachine = {
|
|
4984
|
+
...sm,
|
|
4985
|
+
transitions: (sm.transitions ?? []).map((t) => ({
|
|
4986
|
+
...t,
|
|
4987
|
+
...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
|
|
4988
|
+
...t.effects ? { effects: rewrite(t.effects) } : {}
|
|
4989
|
+
}))
|
|
4990
|
+
};
|
|
4991
|
+
}
|
|
4992
|
+
if (trait.ticks) {
|
|
4993
|
+
next.ticks = trait.ticks.map((tick) => ({
|
|
4994
|
+
...tick,
|
|
4995
|
+
...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
|
|
4996
|
+
effects: rewrite(tick.effects)
|
|
4997
|
+
}));
|
|
4998
|
+
}
|
|
4999
|
+
if (trait.listens) {
|
|
5000
|
+
next.listens = trait.listens.map((l) => ({
|
|
5001
|
+
...l,
|
|
5002
|
+
...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
|
|
5003
|
+
...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
|
|
5004
|
+
}));
|
|
5005
|
+
}
|
|
5006
|
+
if (trait.initialEffects) {
|
|
5007
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
5008
|
+
}
|
|
5009
|
+
if (trait.config) {
|
|
5010
|
+
const nextConfig = {};
|
|
5011
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
5012
|
+
nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewrite(field.default) };
|
|
5013
|
+
}
|
|
5014
|
+
next.config = nextConfig;
|
|
5015
|
+
}
|
|
5016
|
+
if (trait.sourceEntityDefinition) {
|
|
5017
|
+
next.sourceEntityDefinition = rewriteRoleLiteralsInEntity(trait.sourceEntityDefinition, roleFields, roles);
|
|
5018
|
+
}
|
|
5019
|
+
return next;
|
|
5020
|
+
}
|
|
5021
|
+
function rewriteRoleLiteralsInEntity(entity, roleFields, roles) {
|
|
5022
|
+
if (roleFields.size === 0 || Object.keys(roles).length === 0) return entity;
|
|
5023
|
+
const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
|
|
5024
|
+
return {
|
|
5025
|
+
...entity,
|
|
5026
|
+
...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
|
|
5027
|
+
...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
|
|
5028
|
+
...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
|
|
5029
|
+
...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
|
|
5030
|
+
};
|
|
5031
|
+
}
|
|
5032
|
+
function renameRelationTargetsInField(field, entitySubs, entityIds) {
|
|
5033
|
+
let next = field;
|
|
5034
|
+
if (next.type === "relation") {
|
|
5035
|
+
const to = entitySubs.get(next.relation.entity);
|
|
5036
|
+
if (to !== void 0) {
|
|
5037
|
+
next = { ...next, relation: { ...next.relation, entity: to, entityId: entityIds.get(to) } };
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
if ((next.type === "array" || next.type === "object") && next.items) {
|
|
5041
|
+
next = { ...next, items: renameRelationTargetsInField(next.items, entitySubs, entityIds) };
|
|
5042
|
+
}
|
|
5043
|
+
if (next.properties) {
|
|
5044
|
+
const nextProperties = {};
|
|
5045
|
+
for (const [key, value] of Object.entries(next.properties)) {
|
|
5046
|
+
nextProperties[key] = renameRelationTargetsInField(value, entitySubs, entityIds);
|
|
5047
|
+
}
|
|
5048
|
+
next = { ...next, properties: nextProperties };
|
|
5049
|
+
}
|
|
5050
|
+
return next;
|
|
5051
|
+
}
|
|
5052
|
+
function renameEntityRelationTargets(entity, entitySubs, entityIds) {
|
|
5053
|
+
if (entitySubs.size === 0) return entity;
|
|
5054
|
+
return { ...entity, fields: entity.fields.map((f) => renameRelationTargetsInField(f, entitySubs, entityIds)) };
|
|
5055
|
+
}
|
|
5056
|
+
function renameSourceEntityDefinition(trait, subs, entityIds) {
|
|
5057
|
+
const src = trait.sourceEntityDefinition;
|
|
5058
|
+
if (!src || subs.size === 0) return trait;
|
|
5059
|
+
const renamedName = subs.get(src.name) ?? src.name;
|
|
5060
|
+
const nextSrc = renameEntityRelationTargets({ ...src, name: renamedName }, subs, entityIds);
|
|
5061
|
+
return { ...trait, sourceEntityDefinition: nextSrc };
|
|
5062
|
+
}
|
|
5063
|
+
function renamePayloadEntity(fields, rename) {
|
|
5064
|
+
return fields.map((field) => {
|
|
5065
|
+
const renamedEntity = field.entity !== void 0 ? rename(field.entity) : void 0;
|
|
5066
|
+
const renamedProps = field.properties ? renamePayloadEntity(field.properties, rename) : field.properties;
|
|
5067
|
+
return {
|
|
5068
|
+
...field,
|
|
5069
|
+
...renamedEntity !== void 0 ? { entity: renamedEntity } : {},
|
|
5070
|
+
...renamedProps !== void 0 ? { properties: renamedProps } : {}
|
|
5071
|
+
};
|
|
5072
|
+
});
|
|
5073
|
+
}
|
|
5074
|
+
function renamePayloadEntityMarkers(trait, rename) {
|
|
5075
|
+
const sm = trait.stateMachine;
|
|
5076
|
+
const nextEvents = sm?.events ? sm.events.map((ev) => {
|
|
5077
|
+
const renamedEntity = ev.payloadEntity !== void 0 ? rename(ev.payloadEntity) : void 0;
|
|
5078
|
+
if (!ev.payloadSchema && renamedEntity === void 0) return ev;
|
|
5079
|
+
return {
|
|
5080
|
+
...ev,
|
|
5081
|
+
...ev.payloadSchema ? { payloadSchema: renamePayloadEntity(ev.payloadSchema, rename) } : {},
|
|
5082
|
+
...renamedEntity !== void 0 ? { payloadEntity: renamedEntity } : {}
|
|
5083
|
+
};
|
|
5084
|
+
}) : void 0;
|
|
5085
|
+
const nextEmits = trait.emits ? trait.emits.map((em) => {
|
|
5086
|
+
const renamedEntity = em.payloadEntity !== void 0 ? rename(em.payloadEntity) : void 0;
|
|
5087
|
+
if (!em.payloadSchema && renamedEntity === void 0) return em;
|
|
5088
|
+
return {
|
|
5089
|
+
...em,
|
|
5090
|
+
...em.payloadSchema ? { payloadSchema: renamePayloadEntity(em.payloadSchema, rename) } : {},
|
|
5091
|
+
...renamedEntity !== void 0 ? { payloadEntity: renamedEntity } : {}
|
|
5092
|
+
};
|
|
5093
|
+
}) : void 0;
|
|
5094
|
+
return {
|
|
5095
|
+
...trait,
|
|
5096
|
+
...sm && nextEvents ? { stateMachine: { ...sm, events: nextEvents } } : {},
|
|
5097
|
+
...nextEmits ? { emits: nextEmits } : {}
|
|
5098
|
+
};
|
|
5099
|
+
}
|
|
5100
|
+
function walkEntityInPayloadMapping(payloadMapping, rename, props) {
|
|
5101
|
+
const next = {};
|
|
5102
|
+
for (const [key, value] of Object.entries(payloadMapping)) {
|
|
5103
|
+
next[key] = renameEntityInEffect(value, rename, props);
|
|
5104
|
+
}
|
|
5105
|
+
return next;
|
|
5106
|
+
}
|
|
5107
|
+
function renameEntitiesInTrait(trait, entitySubs, entityIds) {
|
|
5108
|
+
if (entitySubs.size === 0) return trait;
|
|
5109
|
+
const rename = (name) => entitySubs.get(name);
|
|
5110
|
+
const withTokens = (value) => renameEntityNameTokensInValue(value, entitySubs);
|
|
5111
|
+
const nextLinked = trait.linkedEntity !== void 0 ? entitySubs.get(trait.linkedEntity) ?? trait.linkedEntity : trait.linkedEntity;
|
|
5112
|
+
const sm = trait.stateMachine;
|
|
5113
|
+
const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
|
|
5114
|
+
...t,
|
|
5115
|
+
...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5116
|
+
effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
|
|
5117
|
+
})) : sm?.transitions;
|
|
5118
|
+
const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
|
|
5119
|
+
...tick,
|
|
5120
|
+
...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5121
|
+
effects: withTokens(renameEntityInEffects(
|
|
5122
|
+
tick.effects,
|
|
5123
|
+
rename,
|
|
5124
|
+
REBIND_ENTITY_PROPS
|
|
5125
|
+
))
|
|
5126
|
+
})) : trait.ticks;
|
|
5127
|
+
const nextListens = trait.listens ? trait.listens.map((l) => ({
|
|
5128
|
+
...l,
|
|
5129
|
+
...l.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(l.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5130
|
+
...l.payloadMapping ? { payloadMapping: withTokens(walkEntityInPayloadMapping(l.payloadMapping, rename, REBIND_ENTITY_PROPS)) } : {}
|
|
5131
|
+
})) : trait.listens;
|
|
5132
|
+
const nextInitial = trait.initialEffects ? withTokens(renameEntityInEffects(
|
|
5133
|
+
trait.initialEffects,
|
|
5134
|
+
rename,
|
|
5135
|
+
REBIND_ENTITY_PROPS
|
|
5136
|
+
)) : trait.initialEffects;
|
|
5137
|
+
return rewriteEntityTypedConfigValues(
|
|
5138
|
+
renamePayloadEntityMarkers(
|
|
5139
|
+
{
|
|
5140
|
+
...trait,
|
|
5141
|
+
linkedEntity: nextLinked,
|
|
5142
|
+
...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
|
|
5143
|
+
...nextTicks !== void 0 ? { ticks: nextTicks } : {},
|
|
5144
|
+
...nextListens !== void 0 ? { listens: nextListens } : {},
|
|
5145
|
+
...nextInitial !== void 0 ? { initialEffects: nextInitial } : {}
|
|
5146
|
+
},
|
|
5147
|
+
rename
|
|
5148
|
+
),
|
|
5149
|
+
entitySubs,
|
|
5150
|
+
entityIds
|
|
5151
|
+
);
|
|
5152
|
+
}
|
|
5153
|
+
function rewriteEntityRefIds(trait, entitySubs, entityIds) {
|
|
5154
|
+
const refs = trait.entityRefIds;
|
|
5155
|
+
if (!refs) return trait;
|
|
5156
|
+
const out = {};
|
|
5157
|
+
for (const [from, oldId] of Object.entries(refs)) {
|
|
5158
|
+
const name = entitySubs.get(from) ?? from;
|
|
5159
|
+
out[name] = entityIds.get(name) ?? oldId;
|
|
5160
|
+
}
|
|
5161
|
+
return { ...trait, entityRefIds: out };
|
|
5162
|
+
}
|
|
5163
|
+
function rewriteEntityTypedConfigValues(trait, entitySubs, entityIds) {
|
|
5164
|
+
if (entitySubs.size === 0 || !trait.config) return trait;
|
|
5165
|
+
let changed = false;
|
|
5166
|
+
const nextConfig = { ...trait.config };
|
|
5167
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
5168
|
+
if (field.type !== "entity" || typeof field.default !== "string") continue;
|
|
5169
|
+
const to = entitySubs.get(field.default);
|
|
5170
|
+
if (to === void 0) continue;
|
|
5171
|
+
changed = true;
|
|
5172
|
+
nextConfig[key] = { ...field, default: to, refId: entityIds.get(to) };
|
|
5173
|
+
}
|
|
5174
|
+
return changed ? { ...trait, config: nextConfig } : trait;
|
|
5175
|
+
}
|
|
5176
|
+
function applyAliasEntityRenames(trait, subs, entityIds) {
|
|
5177
|
+
if (subs.size === 0) return trait;
|
|
5178
|
+
const rename = (name) => subs.get(name);
|
|
5179
|
+
const withTokens = (value) => renameEntityNameTokensInValue(value, subs);
|
|
5180
|
+
const sm = trait.stateMachine;
|
|
5181
|
+
const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
|
|
5182
|
+
...t,
|
|
5183
|
+
...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5184
|
+
effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
|
|
5185
|
+
})) : sm?.transitions;
|
|
5186
|
+
const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
|
|
5187
|
+
...tick,
|
|
5188
|
+
...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5189
|
+
effects: withTokens(
|
|
5190
|
+
renameEntityInEffects(tick.effects, rename, REBIND_ENTITY_PROPS)
|
|
5191
|
+
)
|
|
5192
|
+
})) : trait.ticks;
|
|
5193
|
+
const next = {
|
|
5194
|
+
...trait,
|
|
5195
|
+
...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
|
|
5196
|
+
...nextTicks !== void 0 ? { ticks: nextTicks } : {}
|
|
5197
|
+
};
|
|
5198
|
+
return rewriteEntityRefIds(next, subs, entityIds);
|
|
5199
|
+
}
|
|
5200
|
+
function collectEntityNamesInTrait(trait, candidates) {
|
|
5201
|
+
const collected = /* @__PURE__ */ new Set();
|
|
5202
|
+
const collect = (name) => {
|
|
5203
|
+
if (candidates.has(name)) collected.add(name);
|
|
5204
|
+
return void 0;
|
|
5205
|
+
};
|
|
5206
|
+
const sm = trait.stateMachine;
|
|
5207
|
+
for (const t of sm?.transitions ?? []) {
|
|
5208
|
+
if (t.guard !== void 0) renameEntityInEffect(t.guard, collect, REBIND_ENTITY_PROPS);
|
|
5209
|
+
if (t.effects) renameEntityInEffects(t.effects, collect, REBIND_ENTITY_PROPS);
|
|
5210
|
+
}
|
|
5211
|
+
for (const tick of trait.ticks ?? []) {
|
|
5212
|
+
if (tick.guard !== void 0) renameEntityInEffect(tick.guard, collect, REBIND_ENTITY_PROPS);
|
|
5213
|
+
renameEntityInEffects(tick.effects, collect, REBIND_ENTITY_PROPS);
|
|
5214
|
+
}
|
|
5215
|
+
for (const l of trait.listens ?? []) {
|
|
5216
|
+
if (l.guard !== void 0) renameEntityInEffect(l.guard, collect, REBIND_ENTITY_PROPS);
|
|
5217
|
+
if (l.payloadMapping) walkEntityInPayloadMapping(l.payloadMapping, collect, REBIND_ENTITY_PROPS);
|
|
5218
|
+
}
|
|
5219
|
+
if (trait.initialEffects) {
|
|
5220
|
+
renameEntityInEffects(trait.initialEffects, collect, REBIND_ENTITY_PROPS);
|
|
5221
|
+
}
|
|
5222
|
+
return collected;
|
|
5223
|
+
}
|
|
5224
|
+
function collectRelationTargets(field, candidates, out) {
|
|
5225
|
+
if (field.type === "relation" && candidates.has(field.relation.entity)) out.add(field.relation.entity);
|
|
5226
|
+
if ((field.type === "array" || field.type === "object") && field.items) {
|
|
5227
|
+
collectRelationTargets(field.items, candidates, out);
|
|
5228
|
+
}
|
|
5229
|
+
if (field.properties) {
|
|
5230
|
+
for (const value of Object.values(field.properties)) collectRelationTargets(value, candidates, out);
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
function relationTargetsOfEntity(entity, candidates) {
|
|
5234
|
+
const out = /* @__PURE__ */ new Set();
|
|
5235
|
+
for (const field of entity.fields) collectRelationTargets(field, candidates, out);
|
|
5236
|
+
return out;
|
|
5237
|
+
}
|
|
5238
|
+
function rewriteListenSources(trait, subs, idByName, orbitalRename, alias, listenSourceTargets) {
|
|
5239
|
+
const listens = trait.listens;
|
|
5240
|
+
if (!listens || listens.length === 0) return trait;
|
|
5241
|
+
let changed = false;
|
|
5242
|
+
const nextListens = listens.map((listen) => {
|
|
5243
|
+
const source = listen.source;
|
|
5244
|
+
if (!source) return listen;
|
|
5245
|
+
if (source.kind === "trait") {
|
|
5246
|
+
const target = subs.get(source.trait);
|
|
5247
|
+
if (target === void 0 || target === source.trait) return listen;
|
|
5248
|
+
changed = true;
|
|
5249
|
+
const traitId = idByName.get(target);
|
|
5250
|
+
return {
|
|
5251
|
+
...listen,
|
|
5252
|
+
source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
|
|
5253
|
+
};
|
|
5254
|
+
}
|
|
5255
|
+
if (source.kind === "orbital") {
|
|
5256
|
+
if (orbitalRename && source.orbital === orbitalRename.from) {
|
|
5257
|
+
const targetTrait = subs.get(source.trait) ?? source.trait;
|
|
5258
|
+
changed = true;
|
|
5259
|
+
const traitId = idByName.get(targetTrait);
|
|
5260
|
+
return {
|
|
5261
|
+
...listen,
|
|
5262
|
+
source: {
|
|
5263
|
+
kind: "orbital",
|
|
5264
|
+
orbital: orbitalRename.to,
|
|
5265
|
+
trait: targetTrait,
|
|
5266
|
+
...traitId ? { traitId } : {}
|
|
5267
|
+
}
|
|
5268
|
+
};
|
|
5269
|
+
}
|
|
5270
|
+
const info = alias && listenSourceTargets ? listenSourceTargets.get(siblingImportKey(alias, source.orbital)) : void 0;
|
|
5271
|
+
if (info) {
|
|
5272
|
+
const target = info.traitSubs.get(source.trait);
|
|
5273
|
+
changed = true;
|
|
5274
|
+
return {
|
|
5275
|
+
...listen,
|
|
5276
|
+
source: {
|
|
5277
|
+
kind: "orbital",
|
|
5278
|
+
orbital: info.localName,
|
|
5279
|
+
trait: target?.finalName ?? source.trait,
|
|
5280
|
+
...target?.finalId ? { traitId: target.finalId } : {}
|
|
5281
|
+
}
|
|
5282
|
+
};
|
|
5283
|
+
}
|
|
5284
|
+
}
|
|
5285
|
+
return listen;
|
|
5286
|
+
});
|
|
5287
|
+
return changed ? { ...trait, listens: nextListens } : trait;
|
|
5288
|
+
}
|
|
5289
|
+
function isInlineEntity(ref) {
|
|
5290
|
+
return !isEntityReference(ref) && !isEntityCall(ref);
|
|
5291
|
+
}
|
|
5292
|
+
function inlineEntityRefsOf(orbital) {
|
|
5293
|
+
return [orbital.entity, ...orbital.auxiliaryEntities ?? []].filter(isInlineEntity);
|
|
5294
|
+
}
|
|
5295
|
+
function entityByNameForAlias(imports, alias, entityName) {
|
|
5296
|
+
const imported = imports.orbitals.get(alias);
|
|
5297
|
+
if (!imported) return void 0;
|
|
5298
|
+
for (const o of importedOrbitals(imported)) {
|
|
5299
|
+
const found = inlineEntityRefsOf(o).find((e) => e.name === entityName);
|
|
5300
|
+
if (found) return found;
|
|
5301
|
+
}
|
|
5302
|
+
return void 0;
|
|
5303
|
+
}
|
|
5304
|
+
function entityByNameAnyAlias(imports, entityName) {
|
|
5305
|
+
const aliases = Array.from(imports.orbitals.keys()).sort();
|
|
5306
|
+
for (const alias of aliases) {
|
|
5307
|
+
const found = entityByNameForAlias(imports, alias, entityName);
|
|
5308
|
+
if (found) return found;
|
|
5309
|
+
}
|
|
5310
|
+
return void 0;
|
|
5311
|
+
}
|
|
5312
|
+
function ownedTraitEntryFor(imports, alias, traitName) {
|
|
5313
|
+
const imported = imports.orbitals.get(alias);
|
|
5314
|
+
if (!imported) return void 0;
|
|
5315
|
+
const owner = importedOrbitals(imported).find(
|
|
5316
|
+
(o) => findTraitEntryInOrbital(o, traitName) !== null
|
|
5317
|
+
);
|
|
5318
|
+
if (!owner || !isInlineEntity(owner.entity)) return void 0;
|
|
5319
|
+
return { owner, ownerEntity: owner.entity, entry: findTraitEntryInOrbital(owner, traitName) };
|
|
5320
|
+
}
|
|
5321
|
+
function boundTraitOrbitalBinding(imports, alias, traitName) {
|
|
5322
|
+
const imported = imports.orbitals.get(alias);
|
|
5323
|
+
if (imported?.resolvedOrbitals) {
|
|
5324
|
+
for (const ro of imported.resolvedOrbitals) {
|
|
5325
|
+
const entry = findTraitEntryInOrbital(ro.original, traitName);
|
|
5326
|
+
if (!entry) continue;
|
|
5327
|
+
const bound2 = entry.linkedEntity;
|
|
5328
|
+
const resolvedEntities = [ro.entity, ...ro.auxiliaryEntities ?? []];
|
|
5329
|
+
const boundEntity2 = bound2 !== void 0 ? resolvedEntities.find((e) => e.name === bound2) : void 0;
|
|
5330
|
+
const requiredData2 = new Set(
|
|
5331
|
+
ro.traits.find((rt) => rt.trait.name === traitName)?.trait.entityContract?.requires ?? []
|
|
5332
|
+
);
|
|
5333
|
+
return { owner: ro.original, ownerEntity: ro.entity, entity: boundEntity2 ?? ro.entity, requiredData: requiredData2 };
|
|
5334
|
+
}
|
|
5335
|
+
}
|
|
5336
|
+
const owned = ownedTraitEntryFor(imports, alias, traitName);
|
|
5337
|
+
if (!owned) return void 0;
|
|
5338
|
+
const ownerEntities = inlineEntityRefsOf(owned.owner);
|
|
5339
|
+
const bound = owned.entry?.linkedEntity;
|
|
5340
|
+
const boundEntity = bound !== void 0 ? ownerEntities.find((e) => e.name === bound) : void 0;
|
|
5341
|
+
const requiredData = new Set(
|
|
5342
|
+
owned.entry && "stateMachine" in owned.entry ? owned.entry.entityContract?.requires ?? [] : []
|
|
5343
|
+
);
|
|
5344
|
+
return { owner: owned.owner, ownerEntity: owned.ownerEntity, entity: boundEntity ?? owned.ownerEntity, requiredData };
|
|
5345
|
+
}
|
|
5346
|
+
function auxEntitiesFromUnrebindTraitRefs(orbitalTraits, imports) {
|
|
5347
|
+
const out = [];
|
|
5348
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5349
|
+
const push = (e) => {
|
|
5350
|
+
if (!seen.has(e.name)) {
|
|
5351
|
+
seen.add(e.name);
|
|
5352
|
+
out.push(e);
|
|
5353
|
+
}
|
|
5354
|
+
};
|
|
5355
|
+
for (const tr of orbitalTraits) {
|
|
5356
|
+
let ref;
|
|
5357
|
+
let linkedEntity;
|
|
5358
|
+
if (typeof tr === "string") {
|
|
5359
|
+
ref = tr;
|
|
5360
|
+
} else if ("ref" in tr) {
|
|
5361
|
+
ref = tr.ref;
|
|
5362
|
+
linkedEntity = tr.linkedEntity;
|
|
5363
|
+
} else {
|
|
5364
|
+
continue;
|
|
5365
|
+
}
|
|
5366
|
+
const parsed = parseImportedTraitRef(ref);
|
|
5367
|
+
if (!parsed) continue;
|
|
5368
|
+
const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
|
|
5369
|
+
if (!binding) continue;
|
|
5370
|
+
if (linkedEntity === void 0) {
|
|
5371
|
+
push(binding.entity);
|
|
5372
|
+
}
|
|
5373
|
+
for (const e of inlineEntityRefsOf(binding.owner)) {
|
|
5374
|
+
if (e.name !== binding.ownerEntity.name) push(e);
|
|
5375
|
+
}
|
|
5376
|
+
}
|
|
5377
|
+
return out;
|
|
5378
|
+
}
|
|
5379
|
+
function rewriteSelfRelationTarget(field, oldName, newName, newId) {
|
|
5380
|
+
if (field.type === "relation" && field.relation.entity === oldName) {
|
|
5381
|
+
field.relation = { ...field.relation, entity: newName, entityId: newId };
|
|
5382
|
+
}
|
|
5383
|
+
if (field.type === "array" && field.items) {
|
|
5384
|
+
rewriteSelfRelationTarget(field.items, oldName, newName, newId);
|
|
5385
|
+
}
|
|
5386
|
+
if (field.type === "object" && field.items) {
|
|
5387
|
+
rewriteSelfRelationTarget(field.items, oldName, newName, newId);
|
|
5388
|
+
}
|
|
5389
|
+
if (field.properties) {
|
|
5390
|
+
for (const key of Object.keys(field.properties)) {
|
|
5391
|
+
rewriteSelfRelationTarget(field.properties[key], oldName, newName, newId);
|
|
5392
|
+
}
|
|
5393
|
+
}
|
|
5394
|
+
}
|
|
5395
|
+
function mergeImportedEntityFields(callerEntity, importedEntity, intrinsicOnly, requiredData) {
|
|
5396
|
+
const existingNames = new Set(
|
|
5397
|
+
callerEntity.fields.map((f) => f.name).filter((n) => n !== void 0)
|
|
5398
|
+
);
|
|
5399
|
+
const oldName = importedEntity.name;
|
|
5400
|
+
const newName = callerEntity.name;
|
|
5401
|
+
const newId = callerEntity.id;
|
|
5402
|
+
for (const field of importedEntity.fields) {
|
|
5403
|
+
if (intrinsicOnly && field.intrinsic !== true) continue;
|
|
5404
|
+
if (field.name === void 0) continue;
|
|
5405
|
+
if (requiredData.has(field.name) && field.intrinsic !== true) continue;
|
|
5406
|
+
if (existingNames.has(field.name)) continue;
|
|
5407
|
+
const cloned = structuredClone(field);
|
|
5408
|
+
rewriteSelfRelationTarget(cloned, oldName, newName, newId);
|
|
5409
|
+
callerEntity.fields.push(cloned);
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
function mergeImportedEntityFieldsIntoOrbital(orbitalTraits, entity, declaredAuxEntities, imports) {
|
|
5413
|
+
const mergedAliases = /* @__PURE__ */ new Set();
|
|
5414
|
+
const pending = [];
|
|
5415
|
+
for (const tr of orbitalTraits) {
|
|
5416
|
+
let ref;
|
|
5417
|
+
let linkedEntity;
|
|
5418
|
+
if (typeof tr === "string") {
|
|
5419
|
+
ref = tr;
|
|
5420
|
+
} else if ("ref" in tr) {
|
|
5421
|
+
ref = tr.ref;
|
|
5422
|
+
linkedEntity = tr.linkedEntity;
|
|
5423
|
+
} else {
|
|
5424
|
+
continue;
|
|
5425
|
+
}
|
|
5426
|
+
const parsed = parseImportedTraitRef(ref);
|
|
5427
|
+
if (!parsed) continue;
|
|
5428
|
+
const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
|
|
5429
|
+
if (!binding) continue;
|
|
5430
|
+
const carriesFields = linkedEntity !== void 0 ? true : binding.entity.name === entity.name;
|
|
5431
|
+
if (!carriesFields) continue;
|
|
5432
|
+
const key = `${parsed.alias}\0${parsed.traitName}`;
|
|
5433
|
+
if (mergedAliases.has(key)) continue;
|
|
5434
|
+
mergedAliases.add(key);
|
|
5435
|
+
pending.push({
|
|
5436
|
+
target: linkedEntity,
|
|
5437
|
+
imported: binding.entity,
|
|
5438
|
+
intrinsicOnly: linkedEntity === void 0,
|
|
5439
|
+
requiredData: binding.requiredData
|
|
5440
|
+
});
|
|
5441
|
+
}
|
|
5442
|
+
for (const pm of pending) {
|
|
5443
|
+
const auxTarget = pm.target !== void 0 && pm.target !== entity.name ? declaredAuxEntities.find((e) => e.name === pm.target) : void 0;
|
|
5444
|
+
mergeImportedEntityFields(auxTarget ?? entity, pm.imported, pm.intrinsicOnly, pm.requiredData);
|
|
5445
|
+
}
|
|
5446
|
+
}
|
|
5447
|
+
function consumerEntityIdsOf(orbitals) {
|
|
5448
|
+
const out = /* @__PURE__ */ new Map();
|
|
5449
|
+
for (const orbital of orbitals) {
|
|
5450
|
+
for (const entity of inlineEntityRefsOf(orbital)) {
|
|
5451
|
+
if (entity.id) out.set(entity.name, entity.id);
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
return out;
|
|
5455
|
+
}
|
|
5456
|
+
function materializedPrimaryEntity(upstreamEntity, upstreamOrbitalId, ref, localName) {
|
|
5457
|
+
const name = ref.entity ?? `${localName}${upstreamEntity.name}`;
|
|
5458
|
+
const id = asEntityId(
|
|
5459
|
+
deriveMaterializedId(upstreamEntity.id, upstreamOrbitalId, upstreamEntity.name, localName, "entity")
|
|
5460
|
+
);
|
|
5461
|
+
return { name, id };
|
|
5462
|
+
}
|
|
5463
|
+
function materializedTraitSubs(upstreamId, traits, ref, localName) {
|
|
5464
|
+
const onlySet = ref.only ? new Set(ref.only) : void 0;
|
|
5465
|
+
const omitSet = new Set(ref.omit ?? []);
|
|
5466
|
+
const out = /* @__PURE__ */ new Map();
|
|
5467
|
+
for (const rt of traits) {
|
|
5468
|
+
const name = rt.trait.name;
|
|
5469
|
+
if (!name) continue;
|
|
5470
|
+
const keep = onlySet ? onlySet.has(name) : !omitSet.has(name);
|
|
5471
|
+
if (!keep) continue;
|
|
5472
|
+
out.set(name, {
|
|
5473
|
+
finalName: `${localName}${name}`,
|
|
5474
|
+
finalId: asTraitId(deriveMaterializedId(rt.trait.id, upstreamId, name, localName, "trait"))
|
|
5475
|
+
});
|
|
5476
|
+
}
|
|
5477
|
+
return out;
|
|
5478
|
+
}
|
|
5479
|
+
function siblingImportKey(alias, upstreamOrbitalName) {
|
|
5480
|
+
return `${alias}\0${upstreamOrbitalName}`;
|
|
5481
|
+
}
|
|
5482
|
+
function applyExtendFields(entity, extend, fieldSubs, consumerEntityIds, localName) {
|
|
5483
|
+
if (!extend || extend.length === 0) return { entity, errors: [] };
|
|
5484
|
+
const errors = [];
|
|
5485
|
+
const taken = new Set(entity.fields.map((f) => f.name).filter((n) => Boolean(n)));
|
|
5486
|
+
for (const target of fieldSubs.values()) taken.add(target);
|
|
5487
|
+
const added = [];
|
|
5488
|
+
for (const field of extend) {
|
|
5489
|
+
const name = field.name;
|
|
5490
|
+
if (!name) continue;
|
|
5491
|
+
if (taken.has(name)) {
|
|
5492
|
+
errors.push(
|
|
5493
|
+
`Orbital "${localName}" declares extend field "${name}" but the upstream primary entity already has a field of that name after "fields {}" renames (ORB_O_EXTEND_FIELD_COLLISION)`
|
|
5494
|
+
);
|
|
5495
|
+
continue;
|
|
5496
|
+
}
|
|
5497
|
+
taken.add(name);
|
|
5498
|
+
if (field.type === "relation" && !field.relation.entityId) {
|
|
5499
|
+
const targetId = consumerEntityIds.get(field.relation.entity);
|
|
5500
|
+
added.push(targetId ? { ...field, relation: { ...field.relation, entityId: targetId } } : field);
|
|
5501
|
+
continue;
|
|
5502
|
+
}
|
|
5503
|
+
added.push(field);
|
|
5504
|
+
}
|
|
5505
|
+
if (added.length === 0) return { entity, errors };
|
|
5506
|
+
return { entity: { ...entity, fields: [...entity.fields, ...added] }, errors };
|
|
5507
|
+
}
|
|
5508
|
+
function deriveMaterializedId(sourceId, upstreamOrbitalId, sourceName, localName, kind) {
|
|
5509
|
+
const parent = sourceId ?? `${idPrefix(kind)}orbital-import-seed:${upstreamOrbitalId ?? "no-orbital-id"}:${sourceName}`;
|
|
5510
|
+
return deriveId(parent, localName);
|
|
5511
|
+
}
|
|
5512
|
+
function navigatePathSegments(path) {
|
|
5513
|
+
return path.split("/").filter((segment) => segment.length > 0);
|
|
5514
|
+
}
|
|
5515
|
+
function navigateParamStrippedPrefix(path) {
|
|
5516
|
+
const segments = navigatePathSegments(path);
|
|
5517
|
+
const last = segments[segments.length - 1];
|
|
5518
|
+
if (last === void 0 || !last.startsWith(":")) return void 0;
|
|
5519
|
+
return `/${segments.slice(0, -1).join("/")}/`;
|
|
5520
|
+
}
|
|
5521
|
+
function rewriteConcatPrefix(literalPrefix, pathMap) {
|
|
5522
|
+
const normalized = literalPrefix.endsWith("/") ? literalPrefix : `${literalPrefix}/`;
|
|
5523
|
+
for (const [upstreamPath, finalPath] of pathMap) {
|
|
5524
|
+
const stripped = navigateParamStrippedPrefix(upstreamPath);
|
|
5525
|
+
if (stripped === void 0 || stripped !== normalized) continue;
|
|
5526
|
+
const finalStripped = navigateParamStrippedPrefix(finalPath);
|
|
5527
|
+
if (finalStripped !== void 0) return finalStripped;
|
|
5528
|
+
}
|
|
5529
|
+
return void 0;
|
|
5530
|
+
}
|
|
5531
|
+
function rewriteNavigateTargets(node, pathMap) {
|
|
5532
|
+
if (node === null || node === void 0) return node;
|
|
5533
|
+
if (Array.isArray(node)) {
|
|
5534
|
+
if (node[0] === "navigate" && node.length >= 2) {
|
|
5535
|
+
const target = node[1];
|
|
5536
|
+
if (typeof target === "string" && pathMap.has(target)) {
|
|
5537
|
+
return [node[0], pathMap.get(target), ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
|
|
5538
|
+
}
|
|
5539
|
+
if (Array.isArray(target) && target[0] === "str/concat" && typeof target[1] === "string" && target[1].startsWith("/")) {
|
|
5540
|
+
const rewrittenPrefix = rewriteConcatPrefix(target[1], pathMap);
|
|
5541
|
+
const nextTarget = rewrittenPrefix !== void 0 ? [target[0], rewrittenPrefix, ...target.slice(2)] : target;
|
|
5542
|
+
return [node[0], nextTarget, ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
|
|
5543
|
+
}
|
|
5544
|
+
}
|
|
5545
|
+
return node.map((item) => rewriteNavigateTargets(item, pathMap));
|
|
5546
|
+
}
|
|
5547
|
+
if (typeof node !== "object") return node;
|
|
5548
|
+
const next = {};
|
|
5549
|
+
for (const [key, value] of Object.entries(node)) {
|
|
5550
|
+
next[key] = rewriteNavigateTargets(value, pathMap);
|
|
5551
|
+
}
|
|
5552
|
+
return next;
|
|
5553
|
+
}
|
|
5554
|
+
function rewriteTraitNavigateTargets(trait, pathMap) {
|
|
5555
|
+
if (pathMap.size === 0) return trait;
|
|
5556
|
+
const rewrite = (v) => rewriteNavigateTargets(v, pathMap);
|
|
5557
|
+
const next = { ...trait };
|
|
5558
|
+
const sm = trait.stateMachine;
|
|
5559
|
+
if (sm) {
|
|
5560
|
+
next.stateMachine = {
|
|
5561
|
+
...sm,
|
|
5562
|
+
transitions: (sm.transitions ?? []).map(
|
|
5563
|
+
(t) => t.effects ? { ...t, effects: rewrite(t.effects) } : t
|
|
5564
|
+
)
|
|
5565
|
+
};
|
|
5566
|
+
}
|
|
5567
|
+
if (trait.ticks) {
|
|
5568
|
+
next.ticks = trait.ticks.map((tick) => ({ ...tick, effects: rewrite(tick.effects) }));
|
|
5569
|
+
}
|
|
5570
|
+
if (trait.initialEffects) {
|
|
5571
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
5572
|
+
}
|
|
5573
|
+
return next;
|
|
5574
|
+
}
|
|
5575
|
+
function rewriteConfigPagePaths(node, pathMap) {
|
|
5576
|
+
if (typeof node === "string") return pathMap.get(node) ?? node;
|
|
5577
|
+
if (Array.isArray(node)) return node.map((item) => rewriteConfigPagePaths(item, pathMap));
|
|
5578
|
+
if (node !== null && typeof node === "object") {
|
|
5579
|
+
const next = {};
|
|
5580
|
+
for (const [key, value] of Object.entries(node)) {
|
|
5581
|
+
next[key] = rewriteConfigPagePaths(value, pathMap);
|
|
5582
|
+
}
|
|
5583
|
+
return next;
|
|
5584
|
+
}
|
|
5585
|
+
return node;
|
|
5586
|
+
}
|
|
5587
|
+
function rewriteTraitConfigPagePaths(trait, pathMap) {
|
|
5588
|
+
if (pathMap.size === 0 || !trait.config) return trait;
|
|
5589
|
+
const nextConfig = {};
|
|
5590
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
5591
|
+
nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewriteConfigPagePaths(field.default, pathMap) };
|
|
5592
|
+
}
|
|
5593
|
+
return { ...trait, config: nextConfig };
|
|
5594
|
+
}
|
|
5595
|
+
function foldUseConfigOverride(declared, override, context) {
|
|
5596
|
+
if (!override) return declared;
|
|
5597
|
+
const values = {};
|
|
5598
|
+
for (const [key, field] of Object.entries(override)) {
|
|
5599
|
+
if (!(key in declared)) {
|
|
5600
|
+
refResolverLog.warn("use-config:unknown-knob", { ...context, key });
|
|
5601
|
+
continue;
|
|
5602
|
+
}
|
|
5603
|
+
if (field.default !== void 0) values[key] = field.default;
|
|
5604
|
+
}
|
|
5605
|
+
return Object.keys(values).length > 0 ? overrideDeclaredKnobs(declared, values) : declared;
|
|
5606
|
+
}
|
|
5607
|
+
function forwardConsumerAppKnobs(folded, consumer) {
|
|
5608
|
+
if (!consumer) return folded;
|
|
5609
|
+
const forwards = {};
|
|
5610
|
+
for (const [key, field] of Object.entries(folded)) {
|
|
5611
|
+
const token = field.default;
|
|
5612
|
+
if (typeof token !== "string" || !token.startsWith("@config.")) continue;
|
|
5613
|
+
const source = token.slice("@config.".length);
|
|
5614
|
+
if (source.includes(".") || !(source in consumer)) continue;
|
|
5615
|
+
if (consumer[source].default === void 0) continue;
|
|
5616
|
+
forwards[key] = source;
|
|
5617
|
+
}
|
|
5618
|
+
if (Object.keys(forwards).length === 0) return folded;
|
|
5619
|
+
const next = { ...folded };
|
|
5620
|
+
for (const [key, source] of Object.entries(forwards)) {
|
|
5621
|
+
next[key] = { ...folded[key], default: consumer[source].default, forwardedFrom: `@config.${source}` };
|
|
5622
|
+
}
|
|
5623
|
+
return next;
|
|
5624
|
+
}
|
|
5625
|
+
var ReferenceResolver = class _ReferenceResolver {
|
|
5626
|
+
loader;
|
|
5627
|
+
options;
|
|
5628
|
+
localTraits;
|
|
5629
|
+
/** id-keyed mirror of `localTraits`, populated wherever the trait carries an `id`. */
|
|
5630
|
+
localTraitsById = /* @__PURE__ */ new Map();
|
|
5631
|
+
/** Import scope of each loaded source orbital, keyed by its source path. */
|
|
5632
|
+
sourceImportsCache = /* @__PURE__ */ new Map();
|
|
5633
|
+
/**
|
|
5634
|
+
* {@link preResolveImportFile}'s cache, keyed by absolute source path —
|
|
5635
|
+
* `null` for a file whose own pre-resolution failed (best-effort, cached
|
|
5636
|
+
* too, so a repeat import doesn't retry a doomed resolve). Distinct from
|
|
5637
|
+
* {@link sourceImportsCache} (raw import SCOPE, no trait resolution) —
|
|
5638
|
+
* this holds the file's fully RESOLVED orbitals.
|
|
5639
|
+
*/
|
|
5640
|
+
importFileResolveCache = /* @__PURE__ */ new Map();
|
|
5641
|
+
loaderInitialized = false;
|
|
5642
|
+
/** The schema's declared `config {}` — outermost rung of the forwarded-config chain (§4.5). */
|
|
5643
|
+
schemaConfig;
|
|
5644
|
+
/**
|
|
5645
|
+
* Schema-wide CONSUMER entity NAME → id, growing as each of THIS
|
|
5646
|
+
* schema's own orbitals finishes resolving. JS twin of the compiled
|
|
5647
|
+
* path's `consumer_entity_ids` (`orbital-compiler/src/phases/inline/
|
|
5648
|
+
* mod.rs`), extended the same way: once per orbital, right after it
|
|
5649
|
+
* resolves. Extended ONLY by {@link noteResolvedEntityIds} — called by
|
|
5650
|
+
* the free function {@link resolveSchema} after each of ITS OWN orbitals
|
|
5651
|
+
* finishes — never automatically inside `resolve()` itself, so the
|
|
5652
|
+
* nested `this.resolve()` call {@link materializeOrbitalRef} makes for an
|
|
5653
|
+
* external upstream orbital (a DIFFERENT file, never this consumer
|
|
5654
|
+
* schema) cannot pollute it.
|
|
5655
|
+
*/
|
|
5656
|
+
schemaEntityIds = /* @__PURE__ */ new Map();
|
|
5657
|
+
/**
|
|
5658
|
+
* Entity NAME → id visible to the orbital CURRENTLY being resolved:
|
|
5659
|
+
* {@link schemaEntityIds} (every name an EARLIER orbital in this schema
|
|
5660
|
+
* already established) plus the current orbital's own declared primary +
|
|
5661
|
+
* auxiliary entities — JS twin of the compiled path's per-orbital `entity_
|
|
5662
|
+
* ids = consumer_entity_ids.clone(); entity_ids.extend(collect_orbital_
|
|
5663
|
+
* entity_ids(orbital))`, timed the same way (before this orbital's own
|
|
5664
|
+
* trait composition runs). Read by {@link applyLinkedEntityRename}'s call
|
|
5665
|
+
* sites so a call-site `-> Entity` rebind can REFRESH (never merely drop)
|
|
5666
|
+
* the trait's `entityRefIds` side-map when the rebind target's id is
|
|
5667
|
+
* already known — the gap `std-api-gateway` exposed: `RouteOrbital`'s
|
|
5668
|
+
* no-rebind `Audit.traits.AuditCaptureListener` pull establishes
|
|
5669
|
+
* `AuditEntry`'s id; `GatewayUserOrbital`, resolved LATER in the same
|
|
5670
|
+
* schema, rebinds `Browse.traits.BrowseItemBrowse -> AuditEntry` and must
|
|
5671
|
+
* see it. `resolve()` re-sets this fresh at its own entry (no restore
|
|
5672
|
+
* needed once it returns): nothing reads it once `resolve()` has
|
|
5673
|
+
* returned, and no `resolve()` call is ever active while another is on
|
|
5674
|
+
* this instance — the only recursive `this.resolve()` call
|
|
5675
|
+
* (`materializeOrbitalRef`'s upstream re-resolve) runs strictly BEFORE
|
|
5676
|
+
* `resolveSchema`'s own per-orbital loop begins, never nested inside it.
|
|
5677
|
+
*/
|
|
5678
|
+
entityIdsInScope = /* @__PURE__ */ new Map();
|
|
5679
|
+
/**
|
|
5680
|
+
* Per-orbital name → the FINAL trait names {@link pullSiblingTraits}
|
|
5681
|
+
* auto-pulled for it (`ResolvedOrbital.name` keyed, set once per `resolve()`
|
|
5682
|
+
* call). JS twin of Rust's `pulled_by_orbital` (`inline/mod.rs`) — read by
|
|
5683
|
+
* {@link uniquifyCrossOrbitalPulledSiblings}, run once by the free
|
|
5684
|
+
* function {@link resolveSchema} AFTER every orbital in the schema has
|
|
5685
|
+
* resolved, because the rename decision (does this pulled name collide
|
|
5686
|
+
* with ANOTHER orbital's own declared trait name?) needs the WHOLE
|
|
5687
|
+
* schema's roster, not just this orbital's — exactly why Rust's own
|
|
5688
|
+
* `uniquify_cross_orbital_pulled_siblings` runs once, after its per-orbital
|
|
5689
|
+
* inline loop, not inside `inline_orbital` itself.
|
|
5690
|
+
*/
|
|
5691
|
+
pulledTraitNamesByOrbital = /* @__PURE__ */ new Map();
|
|
5692
|
+
/**
|
|
5693
|
+
* Seed {@link schemaEntityIds} with EVERY orbital's PRIMARY (+ any
|
|
5694
|
+
* already-declared auxiliary) entity name → id, from the RAW pre-resolve
|
|
5695
|
+
* schema — JS twin of the compiled path's `consumer_entity_ids` INITIAL
|
|
5696
|
+
* build (`orbital-compiler/src/phases/inline/mod.rs`, `schema.orbitals
|
|
5697
|
+
* .iter().flat_map(...)`), which scans ALL orbitals' primaries up front,
|
|
5698
|
+
* before ANY of them inlines — not just the ones resolved so far. Without
|
|
5699
|
+
* this, an EARLY-resolved orbital's own `entityRefIds` secondary
|
|
5700
|
+
* references to a LATER orbital's primary entity (`RouteOrbital`'s
|
|
5701
|
+
* `entityRefIds["RateBucket"]`, `RateBucket` being a DIFFERENT, not-yet-
|
|
5702
|
+
* resolved orbital's own primary in `std-api-gateway`) would see nothing
|
|
5703
|
+
* in {@link entityIdsInScope} and {@link consumerKnownEntityRebindSubs}
|
|
5704
|
+
* would never refresh the stale atom-baked id. Called by {@link
|
|
5705
|
+
* resolveSchema} ONCE, before its per-orbital loop begins; {@link
|
|
5706
|
+
* noteResolvedEntityIds} then keeps widening past this seed with each
|
|
5707
|
+
* orbital's post-resolve auxiliary discoveries (Gap #22, sibling pulls),
|
|
5708
|
+
* same as before.
|
|
5709
|
+
*/
|
|
5710
|
+
seedSchemaEntityIds(orbitals) {
|
|
5711
|
+
const next = new Map(this.schemaEntityIds);
|
|
5712
|
+
for (const orbital of orbitals) {
|
|
5713
|
+
for (const e of inlineEntityRefsOf(orbital)) {
|
|
5714
|
+
if (e.id) next.set(e.name, e.id);
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5717
|
+
this.schemaEntityIds = next;
|
|
5718
|
+
}
|
|
5719
|
+
/**
|
|
5720
|
+
* Extend {@link schemaEntityIds} with a just-resolved orbital's FINAL
|
|
5721
|
+
* entity set — primary + every auxiliary entity resolution carried in
|
|
5722
|
+
* (including a no-rebind sibling pull's own bound entity,
|
|
5723
|
+
* `ResolvedOrbital.auxiliaryEntities`). Mirrors the compiled path's
|
|
5724
|
+
* `consumer_entity_ids.extend(collect_orbital_entity_ids(orbital))`,
|
|
5725
|
+
* called the same way: once per orbital, immediately after it resolves.
|
|
5726
|
+
* Called by {@link resolveSchema}'s own per-orbital loop only.
|
|
5727
|
+
*/
|
|
5728
|
+
noteResolvedEntityIds(resolved) {
|
|
5729
|
+
const next = new Map(this.schemaEntityIds);
|
|
5730
|
+
if (resolved.entity.id) next.set(resolved.entity.name, resolved.entity.id);
|
|
5731
|
+
for (const aux of resolved.auxiliaryEntities ?? []) {
|
|
5732
|
+
if (aux.id) next.set(aux.name, aux.id);
|
|
5733
|
+
}
|
|
5734
|
+
this.schemaEntityIds = next;
|
|
5735
|
+
}
|
|
5736
|
+
/**
|
|
5737
|
+
* Make auto-pulled sibling traits app-unique across orbitals — JS twin of
|
|
5738
|
+
* Rust's `uniquify_cross_orbital_pulled_siblings` (`inline/mod.rs`), called
|
|
5739
|
+
* by the free function {@link resolveSchema} once every orbital in the
|
|
5740
|
+
* schema has resolved (mirroring Rust's own post-per-orbital-loop timing:
|
|
5741
|
+
* the rename decision needs the WHOLE schema's trait-name roster, built
|
|
5742
|
+
* fresh here rather than grown incrementally like {@link schemaEntityIds}).
|
|
5743
|
+
* An auto-pulled sibling keeps its source name within its OWN orbital, so a
|
|
5744
|
+
* `@trait.<Sibling>` reference inside that orbital still resolves — but
|
|
5745
|
+
* when TWO orbitals in the same schema each declare (pulled OR explicit) a
|
|
5746
|
+
* trait of the SAME name, that name collides app-wide. Only renames a
|
|
5747
|
+
* PULLED copy (never an explicitly-authored trait ref —
|
|
5748
|
+
* {@link pulledTraitNamesByOrbital} is the eligibility set) whose name is
|
|
5749
|
+
* ALSO declared by at least one OTHER orbital, prefixing it with the
|
|
5750
|
+
* owning orbital's own name; the prefixed name must itself be free
|
|
5751
|
+
* schema-wide or the rename is skipped (matches Rust: a collision on the
|
|
5752
|
+
* PREFIXED name is left for the validator, never silently double-renamed).
|
|
5753
|
+
* Mutates `orbitals`' traits in place, same mutation style as
|
|
5754
|
+
* {@link pullSiblingTraits}.
|
|
5755
|
+
*/
|
|
5756
|
+
uniquifyCrossOrbitalPulledSiblings(orbitals) {
|
|
5757
|
+
if (this.pulledTraitNamesByOrbital.size === 0) return;
|
|
5758
|
+
const nameOrbitalCount = /* @__PURE__ */ new Map();
|
|
5759
|
+
for (const orbital of orbitals) {
|
|
5760
|
+
const local = new Set(
|
|
5761
|
+
orbital.traits.map((rt) => rt.trait.name).filter((n) => Boolean(n))
|
|
5762
|
+
);
|
|
5763
|
+
for (const name of local) {
|
|
5764
|
+
nameOrbitalCount.set(name, (nameOrbitalCount.get(name) ?? 0) + 1);
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
for (const orbital of orbitals) {
|
|
5768
|
+
const pulledNames = this.pulledTraitNamesByOrbital.get(orbital.name);
|
|
5769
|
+
if (!pulledNames || pulledNames.size === 0) continue;
|
|
5770
|
+
const renames = /* @__PURE__ */ new Map();
|
|
5771
|
+
for (const oldName of pulledNames) {
|
|
5772
|
+
if ((nameOrbitalCount.get(oldName) ?? 0) <= 1) continue;
|
|
5773
|
+
const newName = `${orbital.name}${oldName}`;
|
|
5774
|
+
if (nameOrbitalCount.has(newName)) continue;
|
|
5775
|
+
renames.set(oldName, newName);
|
|
5776
|
+
}
|
|
5777
|
+
if (renames.size === 0) continue;
|
|
5778
|
+
for (const rt of orbital.traits) {
|
|
5779
|
+
if (rt.trait.name && renames.has(rt.trait.name)) {
|
|
5780
|
+
rt.trait = { ...rt.trait, name: renames.get(rt.trait.name) };
|
|
5781
|
+
}
|
|
5782
|
+
}
|
|
5783
|
+
const idByName = /* @__PURE__ */ new Map();
|
|
5784
|
+
for (const rt of orbital.traits) {
|
|
5785
|
+
if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
|
|
5786
|
+
}
|
|
5787
|
+
for (const rt of orbital.traits) {
|
|
5788
|
+
rt.trait = renameTraitEmbeds(rt.trait, renames);
|
|
5789
|
+
rt.trait = rewriteListenSources(rt.trait, renames, idByName);
|
|
5790
|
+
}
|
|
5791
|
+
}
|
|
5792
|
+
}
|
|
5793
|
+
constructor(options) {
|
|
5794
|
+
this.options = options;
|
|
5795
|
+
this.loader = options.loader;
|
|
5796
|
+
this.schemaConfig = options.schemaConfig;
|
|
5797
|
+
this.localTraits = options.localTraits ?? /* @__PURE__ */ new Map();
|
|
5798
|
+
for (const trait of this.localTraits.values()) {
|
|
5799
|
+
if (trait.id) {
|
|
5800
|
+
this.localTraitsById.set(trait.id, trait);
|
|
5801
|
+
}
|
|
5802
|
+
}
|
|
5803
|
+
}
|
|
5804
|
+
async ensureLoader() {
|
|
5805
|
+
if (this.loader || this.loaderInitialized) return;
|
|
5806
|
+
this.loaderInitialized = true;
|
|
5807
|
+
try {
|
|
5808
|
+
const { ExternalOrbitalLoader } = await import('./external-loader-CISUEINQ.js');
|
|
5809
|
+
this.loader = new ExternalOrbitalLoader(this.options);
|
|
5810
|
+
} catch {
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
/**
|
|
5814
|
+
* Resolve all references in an orbital.
|
|
5815
|
+
*/
|
|
5816
|
+
async resolve(orbital, sourcePath, chain, opts) {
|
|
5817
|
+
const errors = [];
|
|
5818
|
+
const warnings = [];
|
|
5819
|
+
const importChain = chain ?? { push: () => null, pop: () => {
|
|
5820
|
+
}, clone() {
|
|
5821
|
+
return this;
|
|
5822
|
+
} };
|
|
5823
|
+
this.entityIdsInScope = new Map([...this.schemaEntityIds, ...inlineEntityRefsOf(orbital).flatMap((e) => e.id ? [[e.name, e.id]] : [])]);
|
|
5824
|
+
const traitsList = orbital.traits ?? [];
|
|
5825
|
+
const alreadyResolved = traitsList.length > 0 && traitsList.every((t) => isInlineTrait(t));
|
|
5826
|
+
const importsResult = alreadyResolved ? { success: true, data: { orbitals: /* @__PURE__ */ new Map(), idIndex: /* @__PURE__ */ new Map() }} : await this.resolveImports(orbital.uses ?? [], sourcePath, importChain);
|
|
5827
|
+
if (!importsResult.success) {
|
|
5828
|
+
return { success: false, errors: importsResult.errors };
|
|
5829
|
+
}
|
|
5830
|
+
const imports = importsResult.data;
|
|
5831
|
+
imports.idIndex = buildIdIndex(orbital, imports.orbitals);
|
|
5832
|
+
const gap22AuxEntities = auxEntitiesFromUnrebindTraitRefs(orbital.traits ?? [], imports);
|
|
5833
|
+
if (gap22AuxEntities.length > 0) {
|
|
5834
|
+
const next = new Map(this.entityIdsInScope);
|
|
5835
|
+
for (const e of gap22AuxEntities) {
|
|
5836
|
+
if (e.id && !next.has(e.name)) next.set(e.name, e.id);
|
|
5837
|
+
}
|
|
5838
|
+
this.entityIdsInScope = next;
|
|
5839
|
+
}
|
|
5840
|
+
if (isInlineEntity(orbital.entity)) {
|
|
5841
|
+
mergeImportedEntityFieldsIntoOrbital(
|
|
5842
|
+
orbital.traits ?? [],
|
|
5843
|
+
orbital.entity,
|
|
5844
|
+
(orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
|
|
5845
|
+
imports
|
|
5846
|
+
);
|
|
5847
|
+
}
|
|
5848
|
+
const entityResult = this.resolveEntity(orbital.entity, imports);
|
|
5849
|
+
if (!entityResult.success) {
|
|
5850
|
+
errors.push(...entityResult.errors);
|
|
5851
|
+
}
|
|
5852
|
+
const traitsResult = await this.resolveTraits(orbital.traits, imports, importChain, orbital.config);
|
|
5853
|
+
if (!traitsResult.success) {
|
|
5854
|
+
errors.push(...traitsResult.errors);
|
|
5855
|
+
}
|
|
5856
|
+
const pagesResult = await this.resolvePages(orbital.pages, imports, importChain);
|
|
5857
|
+
if (!pagesResult.success) {
|
|
5858
|
+
errors.push(...pagesResult.errors);
|
|
5859
|
+
}
|
|
5860
|
+
if (errors.length > 0) {
|
|
5861
|
+
return { success: false, errors };
|
|
5862
|
+
}
|
|
5863
|
+
if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
|
|
5864
|
+
return { success: false, errors: ["Internal error: unexpected failure state"] };
|
|
5865
|
+
}
|
|
5866
|
+
const { errors: pullErrors, auxEntities: pulledAuxEntities, pulledNames } = await this.pullSiblingTraits(
|
|
5867
|
+
traitsResult.data,
|
|
5868
|
+
imports,
|
|
5869
|
+
importChain,
|
|
5870
|
+
orbital.config
|
|
5871
|
+
);
|
|
5872
|
+
if (pullErrors.length > 0) {
|
|
5873
|
+
return { success: false, errors: pullErrors };
|
|
5874
|
+
}
|
|
5875
|
+
this.pulledTraitNamesByOrbital.set(orbital.name, pulledNames);
|
|
5876
|
+
const known = /* @__PURE__ */ new Set([entityResult.data.entity.name]);
|
|
5877
|
+
const declaredAux = (orbital.auxiliaryEntities ?? []).filter(isInlineEntity);
|
|
5878
|
+
for (const e of declaredAux) known.add(e.name);
|
|
5879
|
+
const combined = [...declaredAux];
|
|
5880
|
+
for (const e of [...gap22AuxEntities, ...pulledAuxEntities]) {
|
|
5881
|
+
if (!known.has(e.name)) {
|
|
5882
|
+
known.add(e.name);
|
|
5883
|
+
combined.push(e);
|
|
5884
|
+
}
|
|
5885
|
+
}
|
|
5886
|
+
const resolvedAuxEntities = combined.length > 0 ? combined : void 0;
|
|
5887
|
+
for (const resolvedTrait of traitsResult.data) {
|
|
5888
|
+
resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
|
|
5889
|
+
resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
|
|
5890
|
+
}
|
|
5891
|
+
try {
|
|
5892
|
+
spliceLambdaTraitRefs(traitsResult.data, pagesResult.data);
|
|
5893
|
+
} catch (e) {
|
|
5894
|
+
if (e instanceof LambdaSpliceError) {
|
|
5895
|
+
return { success: false, errors: [e.message] };
|
|
5896
|
+
}
|
|
5897
|
+
throw e;
|
|
5898
|
+
}
|
|
5899
|
+
if (!opts?.skipTypeParamSentinels) {
|
|
5900
|
+
resolveOrbitalTypeParamSentinels(
|
|
5901
|
+
traitsResult.data,
|
|
5902
|
+
entityResult.data.entity,
|
|
5903
|
+
resolvedAuxEntities ?? [],
|
|
5904
|
+
orbital.types
|
|
5905
|
+
);
|
|
5906
|
+
}
|
|
5907
|
+
return {
|
|
5908
|
+
success: true,
|
|
5909
|
+
data: {
|
|
5910
|
+
name: orbital.name,
|
|
5911
|
+
entity: entityResult.data.entity,
|
|
5912
|
+
entitySource: entityResult.data.source,
|
|
5913
|
+
traits: traitsResult.data,
|
|
5914
|
+
...resolvedAuxEntities ? { auxiliaryEntities: resolvedAuxEntities } : {},
|
|
5915
|
+
pages: pagesResult.data,
|
|
5916
|
+
imports,
|
|
5917
|
+
original: orbital
|
|
5918
|
+
},
|
|
5919
|
+
warnings
|
|
5920
|
+
};
|
|
5921
|
+
}
|
|
5922
|
+
/**
|
|
5923
|
+
* Pre-resolve one imported FILE's own orbitals to completion — its own
|
|
5924
|
+
* `uses` (recursively, through THIS same method), its own trait refs,
|
|
5925
|
+
* its own sibling pulls, its own entity-ref-id rebinds — BEFORE the
|
|
5926
|
+
* consumer that names this alias ever folds or pulls from it. JS twin
|
|
5927
|
+
* of Rust's per-`uses` recursive `inline_orbital` call (`orbital-
|
|
5928
|
+
* compiler/src/phases/inline/mod.rs:1001-1013`): every `uses` alias's
|
|
5929
|
+
* OWN orbitals are inlined to completion, ahead of `ctx.add_alias_multi`
|
|
5930
|
+
* registering the alias for the consumer's own lookups. Without this, a
|
|
5931
|
+
* sibling-pull collision that is a genuine top-level PEER collision
|
|
5932
|
+
* INSIDE the imported file (`std-approval-request.orb`'s
|
|
5933
|
+
* `InlineBrowseItemBrowse6`/`…10`, both `ref: Dense.traits.
|
|
5934
|
+
* BrowseItemBrowse`, each embedding `@trait.DataGrid1`) never becomes
|
|
5935
|
+
* visible as a peer collision to the CONSUMER's own {@link
|
|
5936
|
+
* pullSiblingTraits} call — it arrives already flattened one level
|
|
5937
|
+
* deeper, sharing one JS-visible owner (see that method's own
|
|
5938
|
+
* drain-order doc for the full trace this ports).
|
|
5939
|
+
*
|
|
5940
|
+
* Cached per absolute `sourcePath` ({@link importFileResolveCache}) —
|
|
5941
|
+
* "a file imported twice resolves once" — so the cache must not bake in
|
|
5942
|
+
* any ONE call site's `uses { config }` override: the child resolver
|
|
5943
|
+
* below is seeded with this FILE's own raw, un-folded `config {}`
|
|
5944
|
+
* (`fileSchemaConfig`), never a folded override. A genuinely
|
|
5945
|
+
* call-site-configured explicit ref (`Alias.traits.X { config: {…} }`)
|
|
5946
|
+
* still resolves through the pre-existing lazy path
|
|
5947
|
+
* ({@link resolveTraitEntry} / {@link resolveTraitRefString}), which
|
|
5948
|
+
* this cache does not touch.
|
|
5949
|
+
*
|
|
5950
|
+
* Runs on a FRESH child `ReferenceResolver`, never `this` — `resolve()`'s
|
|
5951
|
+
* own `entityIdsInScope` / `schemaEntityIds` / `pulledTraitNamesByOrbital`
|
|
5952
|
+
* are single mutable instance state scoped to ONE active `resolve()` call
|
|
5953
|
+
* tree (see {@link entityIdsInScope}'s own doc: "no `resolve()` call is
|
|
5954
|
+
* ever active while another is on this instance"); reusing `this` here
|
|
5955
|
+
* would nest a `resolve()` call inside the CONSUMER's own still-active
|
|
5956
|
+
* `resolve()` → `resolveImports` call and corrupt that state once this
|
|
5957
|
+
* nested call returns. The child reuses `this.loader` (and therefore its
|
|
5958
|
+
* underlying `LoaderCache`) so raw parsing still dedupes exactly as
|
|
5959
|
+
* before. `chain` is threaded through unchanged (not cloned, matching
|
|
5960
|
+
* every other cross-call `chain` hand-off in this file) so genuine `uses`
|
|
5961
|
+
* cycles are still caught by the loader.
|
|
5962
|
+
*
|
|
5963
|
+
* Mirrors {@link resolveSchema}'s own orchestration (flatten orbital
|
|
5964
|
+
* references → collect local traits → seed schema entity ids →
|
|
5965
|
+
* per-orbital `resolve()` → `uniquifyCrossOrbitalPulledSiblings`) rather
|
|
5966
|
+
* than calling that free function directly — it accepts no `chain`
|
|
5967
|
+
* parameter, so a direct call would silently drop cycle protection one
|
|
5968
|
+
* level in.
|
|
5969
|
+
*
|
|
5970
|
+
* Best-effort: returns `null` (never throws) on any failure — a caller
|
|
5971
|
+
* falls back to the pre-existing raw-ref walk, matching this file's
|
|
5972
|
+
* other best-effort pre-passes (e.g. {@link precomputeReferenceFormPrimaryIds}).
|
|
5973
|
+
*/
|
|
5974
|
+
async preResolveImportFile(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
|
|
5975
|
+
const cached = this.importFileResolveCache.get(sourcePath);
|
|
5976
|
+
if (cached !== void 0) return cached;
|
|
5977
|
+
let result;
|
|
5978
|
+
try {
|
|
5979
|
+
result = await this.preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain);
|
|
5980
|
+
} catch {
|
|
5981
|
+
result = null;
|
|
5982
|
+
}
|
|
5983
|
+
this.importFileResolveCache.set(sourcePath, result);
|
|
5984
|
+
return result;
|
|
5985
|
+
}
|
|
5986
|
+
async preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
|
|
5987
|
+
const child = new _ReferenceResolver({
|
|
5988
|
+
...this.options,
|
|
5989
|
+
loader: this.loader,
|
|
5990
|
+
schemaConfig: fileSchemaConfig
|
|
5991
|
+
});
|
|
5992
|
+
const fileSchema = {
|
|
5993
|
+
name: sourcePath,
|
|
5994
|
+
orbitals: fileOrbitals,
|
|
5995
|
+
...fileSchemaConfig ? { config: fileSchemaConfig } : {}
|
|
5996
|
+
};
|
|
5997
|
+
const flattenResult = await child.resolveOrbitalImports(fileSchema, { skipTypeParamSentinels: true });
|
|
5998
|
+
if (!flattenResult.success) return null;
|
|
5999
|
+
const orbitals = flattenResult.data;
|
|
6000
|
+
const inlineTraits = orbitals.flatMap(
|
|
6001
|
+
(o) => o.traits.filter((t) => typeof t !== "string" && "stateMachine" in t)
|
|
6002
|
+
);
|
|
6003
|
+
child.addLocalTraits(inlineTraits);
|
|
6004
|
+
child.seedSchemaEntityIds(orbitals);
|
|
6005
|
+
const resolved = [];
|
|
6006
|
+
for (const orbital of orbitals) {
|
|
6007
|
+
const result = await child.resolve(orbital, sourcePath, chain, { skipTypeParamSentinels: true });
|
|
6008
|
+
if (!result.success) return null;
|
|
6009
|
+
resolved.push(result.data);
|
|
6010
|
+
child.noteResolvedEntityIds(result.data);
|
|
6011
|
+
}
|
|
6012
|
+
return resolved;
|
|
6013
|
+
}
|
|
6014
|
+
/**
|
|
6015
|
+
* Resolve `uses` declarations to loaded orbitals.
|
|
6016
|
+
*/
|
|
6017
|
+
async resolveImports(uses, sourcePath, chain) {
|
|
6018
|
+
const errors = [];
|
|
6019
|
+
const orbitals = /* @__PURE__ */ new Map();
|
|
6020
|
+
if (this.options.skipExternalLoading) {
|
|
4301
6021
|
return {
|
|
4302
6022
|
success: true,
|
|
4303
6023
|
data: { orbitals, idIndex: /* @__PURE__ */ new Map() },
|
|
4304
6024
|
warnings: ["External loading skipped"]
|
|
4305
6025
|
};
|
|
4306
6026
|
}
|
|
6027
|
+
const effectiveChain = chain ?? { push: () => null, pop: () => {
|
|
6028
|
+
}, clone() {
|
|
6029
|
+
return this;
|
|
6030
|
+
} };
|
|
4307
6031
|
for (const use of uses) {
|
|
4308
6032
|
if (orbitals.has(use.as)) {
|
|
4309
6033
|
errors.push(`Duplicate import alias: ${use.as}`);
|
|
@@ -4318,18 +6042,32 @@ var ReferenceResolver = class {
|
|
|
4318
6042
|
use.from,
|
|
4319
6043
|
void 0,
|
|
4320
6044
|
sourcePath,
|
|
4321
|
-
|
|
6045
|
+
effectiveChain
|
|
4322
6046
|
);
|
|
4323
6047
|
if (!loadResult.success) {
|
|
4324
6048
|
errors.push(`Failed to load "${use.from}" as "${use.as}": ${loadResult.error}`);
|
|
4325
6049
|
continue;
|
|
4326
6050
|
}
|
|
6051
|
+
const fileOrbitals = loadResult.data.orbitals ?? [loadResult.data.orbital];
|
|
6052
|
+
const resolvedOrbitals = await this.preResolveImportFile(
|
|
6053
|
+
fileOrbitals,
|
|
6054
|
+
loadResult.data.sourcePath,
|
|
6055
|
+
loadResult.data.schemaConfig,
|
|
6056
|
+
effectiveChain
|
|
6057
|
+
);
|
|
4327
6058
|
orbitals.set(use.as, {
|
|
4328
6059
|
alias: use.as,
|
|
4329
6060
|
from: use.from,
|
|
4330
6061
|
orbital: loadResult.data.orbital,
|
|
4331
|
-
orbitals:
|
|
4332
|
-
sourcePath: loadResult.data.sourcePath
|
|
6062
|
+
orbitals: fileOrbitals,
|
|
6063
|
+
sourcePath: loadResult.data.sourcePath,
|
|
6064
|
+
...resolvedOrbitals ? { resolvedOrbitals } : {},
|
|
6065
|
+
...loadResult.data.schemaConfig ? {
|
|
6066
|
+
schemaConfig: forwardConsumerAppKnobs(
|
|
6067
|
+
foldUseConfigOverride(loadResult.data.schemaConfig, use.config, use),
|
|
6068
|
+
this.schemaConfig
|
|
6069
|
+
)
|
|
6070
|
+
} : {}
|
|
4333
6071
|
});
|
|
4334
6072
|
}
|
|
4335
6073
|
if (errors.length > 0) {
|
|
@@ -4420,14 +6158,79 @@ var ReferenceResolver = class {
|
|
|
4420
6158
|
}
|
|
4421
6159
|
return entityRef;
|
|
4422
6160
|
}
|
|
6161
|
+
/**
|
|
6162
|
+
* The ATOM's OWN trait `alias.traits.traitName` resolves to — no call-site
|
|
6163
|
+
* overrides applied (`callSiteConfig` omitted) — so its DECLARED
|
|
6164
|
+
* `linkedEntity` can drive {@link buildAliasEntityRenames}. Same lookup
|
|
6165
|
+
* `resolveTraitRefString`'s imported branch performs to find the base
|
|
6166
|
+
* `trait` before any rebind, factored out so the pre-pass and the main
|
|
6167
|
+
* resolve share one lookup rather than two. `null` when the alias or
|
|
6168
|
+
* trait cannot be found — the pre-pass simply skips that entry, same as a
|
|
6169
|
+
* lookup failure anywhere else in this best-effort pass.
|
|
6170
|
+
*/
|
|
6171
|
+
async atomOwnTrait(alias, traitName, imports, chain) {
|
|
6172
|
+
const imported = imports.orbitals.get(alias);
|
|
6173
|
+
if (!imported) return null;
|
|
6174
|
+
for (const o of importedOrbitals(imported)) {
|
|
6175
|
+
const entry = findTraitEntryInOrbital(o, traitName);
|
|
6176
|
+
if (!entry) continue;
|
|
6177
|
+
const entryResolved = await this.resolveTraitEntry(imported, entry, traitName, chain, imports);
|
|
6178
|
+
return entryResolved.success ? entryResolved.data.trait : null;
|
|
6179
|
+
}
|
|
6180
|
+
return null;
|
|
6181
|
+
}
|
|
6182
|
+
/**
|
|
6183
|
+
* Alias-scoped cross-trait entity-rebind propagation — JS twin of Rust's
|
|
6184
|
+
* `alias_entity_renames` pre-pass (`inline/trait.rs::inline_traits`). One
|
|
6185
|
+
* explicit pull's `linkedEntity` override (`Button.traits.ButtonRender ->
|
|
6186
|
+
* Route`) establishes a rebind (the atom's OWN declared `linkedEntity` →
|
|
6187
|
+
* the override) that a SIBLING pull from the SAME alias with NO rebind of
|
|
6188
|
+
* its own (`Button.traits.ButtonRender`, no `->`) never sees through
|
|
6189
|
+
* {@link applyLinkedEntityRename} — that call only ever knows ITS OWN
|
|
6190
|
+
* delta. But the no-rebind pull's `entityRefIds` side-map can still carry
|
|
6191
|
+
* a SECONDARY, positional reference to that same atom-local name (a
|
|
6192
|
+
* "self" entry keyed by the atom's own bound entity), which nothing else
|
|
6193
|
+
* rewrites — `std-api-gateway`'s `RouteOrbital.InlineButtonRender3`
|
|
6194
|
+
* (`Button.traits.ButtonRender`, no rebind) recovers `entityRefIds`'
|
|
6195
|
+
* `ButtonItem` key to `Route` only because `InlineButtonRender9` (`Button.
|
|
6196
|
+
* traits.ButtonRender -> Route`) established the rebind earlier in the
|
|
6197
|
+
* SAME orbital's `traits` list. Scanned once per orbital, over every
|
|
6198
|
+
* EXPLICIT `Alias.traits.X -> Y` entry in `traitRefs`: `(alias, atom's
|
|
6199
|
+
* declared linkedEntity) -> override`. First rebind for a given `(alias,
|
|
6200
|
+
* atomLocal)` pair wins (`Map.set` only on a fresh key), matching Rust's
|
|
6201
|
+
* `.or_insert_with`.
|
|
6202
|
+
*/
|
|
6203
|
+
async buildAliasEntityRenames(traitRefs, imports, chain) {
|
|
6204
|
+
const out = /* @__PURE__ */ new Map();
|
|
6205
|
+
for (const traitRef of traitRefs) {
|
|
6206
|
+
if (typeof traitRef === "string" || "stateMachine" in traitRef || !("ref" in traitRef)) continue;
|
|
6207
|
+
const refObj = traitRef;
|
|
6208
|
+
if (!refObj.linkedEntity) continue;
|
|
6209
|
+
const parsed = parseImportedTraitRef(refObj.ref);
|
|
6210
|
+
if (!parsed) continue;
|
|
6211
|
+
const atomTrait = await this.atomOwnTrait(parsed.alias, parsed.traitName, imports, chain);
|
|
6212
|
+
const atomLocal = atomTrait?.linkedEntity;
|
|
6213
|
+
if (!atomLocal || atomLocal === refObj.linkedEntity) continue;
|
|
6214
|
+
const forAlias = out.get(parsed.alias) ?? /* @__PURE__ */ new Map();
|
|
6215
|
+
if (!forAlias.has(atomLocal)) forAlias.set(atomLocal, refObj.linkedEntity);
|
|
6216
|
+
out.set(parsed.alias, forAlias);
|
|
6217
|
+
}
|
|
6218
|
+
return out;
|
|
6219
|
+
}
|
|
4423
6220
|
/**
|
|
4424
6221
|
* Resolve trait references.
|
|
4425
6222
|
*/
|
|
4426
|
-
resolveTraits(traitRefs, imports) {
|
|
6223
|
+
async resolveTraits(traitRefs, imports, chain, orbitalConfig) {
|
|
4427
6224
|
const errors = [];
|
|
4428
6225
|
const resolved = [];
|
|
6226
|
+
const embedCtx = {
|
|
6227
|
+
traitRefs,
|
|
6228
|
+
embedGraph: buildEmbedGraph(traitRefs),
|
|
6229
|
+
orbitalConfig
|
|
6230
|
+
};
|
|
6231
|
+
const aliasEntityRenames = await this.buildAliasEntityRenames(traitRefs, imports, chain);
|
|
4429
6232
|
for (const traitRef of traitRefs) {
|
|
4430
|
-
const result = this.resolveTraitRef(traitRef, imports);
|
|
6233
|
+
const result = await this.resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames);
|
|
4431
6234
|
if (!result.success) {
|
|
4432
6235
|
errors.push(...result.errors);
|
|
4433
6236
|
} else {
|
|
@@ -4458,6 +6261,99 @@ var ReferenceResolver = class {
|
|
|
4458
6261
|
this.sourceImportsCache.set(key, result.data);
|
|
4459
6262
|
return result.data;
|
|
4460
6263
|
}
|
|
6264
|
+
/**
|
|
6265
|
+
* The concrete base `Trait` a trait entry (found under `localName` in
|
|
6266
|
+
* `imported`) resolves to — an inline entry resolves its own
|
|
6267
|
+
* `@config.<knob>` emit refs against `callSiteConfig` (the ref hop that
|
|
6268
|
+
* led here, e.g. `std-approval-gate`'s `CloseButton = Button.traits.
|
|
6269
|
+
* ButtonRender { config: { action: CLOSE } }` resolving `ButtonRender`
|
|
6270
|
+
* itself); a ref-shaped entry (an atom's sub-view declared `trait X =
|
|
6271
|
+
* Y.traits.Z {…}` INSIDE the source atom, e.g. `std-note`'s
|
|
6272
|
+
* `NoteSubpages = RecordDetail.traits.RecordItemDetail`) recurses through
|
|
6273
|
+
* that source's own import scope via {@link importsOfSource} — the
|
|
6274
|
+
* entry's own declared overrides are its call site. Single owner for
|
|
6275
|
+
* `pullSiblingTraits`' sibling pull and `resolveTraitRefString`'s
|
|
6276
|
+
* imported branch, both of which used to reach `findTraitInOrbital`'s
|
|
6277
|
+
* `stateMachine`-gated lookup (its ref arm did nothing), silently failing
|
|
6278
|
+
* to resolve a nested ref (ledger (i)).
|
|
6279
|
+
*
|
|
6280
|
+
* `callSiteConfig` MUST be threaded by any caller that goes on to fold a
|
|
6281
|
+
* call-site config of its own onto the returned trait
|
|
6282
|
+
* (`resolveTraitRefString`'s ref-imported branch, ledger (o)) — the
|
|
6283
|
+
* `@config.<knob>` emit-name substitution is destructive
|
|
6284
|
+
* (`resolveConfigRefEmitNames` rewrites the marker to a concrete literal
|
|
6285
|
+
* in place), so resolving it here with the WRONG effective config
|
|
6286
|
+
* (the atom's own bare default, absent the override) permanently loses
|
|
6287
|
+
* the override: a second `resolveConfigRefEmitNames` call downstream sees
|
|
6288
|
+
* no more `@config.<knob>` marker to substitute and silently no-ops.
|
|
6289
|
+
* `pullSiblingTraits` (no further fold of its own) omits it, matching its
|
|
6290
|
+
* prior no-callSiteConfig behavior exactly.
|
|
6291
|
+
*/
|
|
6292
|
+
async resolveTraitEntry(imported, entry, localName, chain, homeImports, callSiteConfig) {
|
|
6293
|
+
if ("stateMachine" in entry) {
|
|
6294
|
+
const { trait, errors } = resolveConfigRefEmitNames(entry, callSiteConfig);
|
|
6295
|
+
if (errors.length > 0) return { success: false, errors };
|
|
6296
|
+
return {
|
|
6297
|
+
success: true,
|
|
6298
|
+
data: { trait, embedScope: { imports: homeImports, alias: imported.alias } },
|
|
6299
|
+
warnings: []
|
|
6300
|
+
};
|
|
6301
|
+
}
|
|
6302
|
+
const refObj = entry;
|
|
6303
|
+
const srcImports = await this.importsOfSource(imported, chain);
|
|
6304
|
+
if (!srcImports) {
|
|
6305
|
+
return {
|
|
6306
|
+
success: false,
|
|
6307
|
+
errors: [
|
|
6308
|
+
`Trait "${localName}" in imported behavior could not resolve its own import scope to follow ref "${refObj.ref}"`
|
|
6309
|
+
]
|
|
6310
|
+
};
|
|
6311
|
+
}
|
|
6312
|
+
const nested = await this.resolveTraitRefString(
|
|
6313
|
+
refObj.ref,
|
|
6314
|
+
srcImports,
|
|
6315
|
+
chain,
|
|
6316
|
+
refObj.config,
|
|
6317
|
+
refObj.linkedEntity,
|
|
6318
|
+
refObj.name ?? localName,
|
|
6319
|
+
refObj.events,
|
|
6320
|
+
refObj.listens,
|
|
6321
|
+
refObj.refId,
|
|
6322
|
+
refObj.typeArgs
|
|
6323
|
+
);
|
|
6324
|
+
if (!nested.success) return nested;
|
|
6325
|
+
return {
|
|
6326
|
+
success: true,
|
|
6327
|
+
data: {
|
|
6328
|
+
trait: nested.data.trait,
|
|
6329
|
+
embedScope: nested.data.embedScope ?? { imports: srcImports, alias: imported.alias },
|
|
6330
|
+
...nested.data.typeArgs !== void 0 ? { typeArgs: nested.data.typeArgs } : {}
|
|
6331
|
+
},
|
|
6332
|
+
warnings: nested.warnings
|
|
6333
|
+
};
|
|
6334
|
+
}
|
|
6335
|
+
/**
|
|
6336
|
+
* The concrete `Page` a page entry (found under `localName` in `imported`)
|
|
6337
|
+
* resolves to — an inline `Page` passes through; a `PageRefObject` (a
|
|
6338
|
+
* re-exported page declared inside the SOURCE orbital's own `pages {}`,
|
|
6339
|
+
* {@link findPageEntryInOrbital}'s ref arm) recurses through that source's
|
|
6340
|
+
* own import scope via {@link importsOfSource} and
|
|
6341
|
+
* {@link resolvePageRefObject} — the page twin of {@link resolveTraitEntry}
|
|
6342
|
+
* (nested refs, ledger (i)).
|
|
6343
|
+
*/
|
|
6344
|
+
async resolvePageEntry(imported, entry, chain) {
|
|
6345
|
+
if (!("ref" in entry)) return { success: true, data: { page: entry }, warnings: [] };
|
|
6346
|
+
const srcImports = await this.importsOfSource(imported, chain);
|
|
6347
|
+
if (!srcImports) {
|
|
6348
|
+
return {
|
|
6349
|
+
success: false,
|
|
6350
|
+
errors: [`Page in imported behavior could not resolve its own import scope to follow ref "${entry.ref}"`]
|
|
6351
|
+
};
|
|
6352
|
+
}
|
|
6353
|
+
const nested = await this.resolvePageRefObject(entry, srcImports, chain);
|
|
6354
|
+
if (!nested.success) return nested;
|
|
6355
|
+
return { success: true, data: { page: nested.data.page }, warnings: nested.warnings };
|
|
6356
|
+
}
|
|
4461
6357
|
/**
|
|
4462
6358
|
* Sibling-trait auto-pull — the JS twin of the compiler's
|
|
4463
6359
|
* `phases/inline/trait.rs` pass, appending to `resolved` in place.
|
|
@@ -4479,7 +6375,8 @@ var ReferenceResolver = class {
|
|
|
4479
6375
|
* source name; later owners pull under `<Owner><Sibling>` — unique by
|
|
4480
6376
|
* construction, since owner names are unique within the orbital.
|
|
4481
6377
|
*/
|
|
4482
|
-
async pullSiblingTraits(resolved, imports, chain) {
|
|
6378
|
+
async pullSiblingTraits(resolved, imports, chain, orbitalConfig) {
|
|
6379
|
+
const auxEntities = [];
|
|
4483
6380
|
const work = [];
|
|
4484
6381
|
const ownerSubs = /* @__PURE__ */ new Map();
|
|
4485
6382
|
const subsFor = (owner) => {
|
|
@@ -4495,18 +6392,48 @@ var ReferenceResolver = class {
|
|
|
4495
6392
|
const owner = rt.trait.name;
|
|
4496
6393
|
subsFor(owner).set(rt.source.traitName, owner);
|
|
4497
6394
|
for (const sibling of traitEmbedNamesOf(rt.trait)) {
|
|
4498
|
-
work.push({
|
|
6395
|
+
work.push({
|
|
6396
|
+
alias: rt.source.alias,
|
|
6397
|
+
fallback: rt.embedScope,
|
|
6398
|
+
sibling,
|
|
6399
|
+
linkedEntity: rt.linkedEntity,
|
|
6400
|
+
parent: owner,
|
|
6401
|
+
owner,
|
|
6402
|
+
// Top-level SEED — always starts with the raw-walk-first gate
|
|
6403
|
+
// (see {@link PullItem.preResolvedScope}'s own doc).
|
|
6404
|
+
preResolvedScope: void 0
|
|
6405
|
+
});
|
|
4499
6406
|
}
|
|
4500
6407
|
}
|
|
4501
|
-
if (work.length === 0) return [];
|
|
6408
|
+
if (work.length === 0) return { errors: [], auxEntities: [], pulledNames: /* @__PURE__ */ new Set() };
|
|
4502
6409
|
const errors = [];
|
|
4503
6410
|
const consumerDeclared = new Set(resolved.map((r) => r.trait.name).filter(Boolean));
|
|
6411
|
+
const consumerDeclaredProvenance = /* @__PURE__ */ new Map();
|
|
6412
|
+
for (const rt of resolved) {
|
|
6413
|
+
if (rt.source.type === "imported" && rt.trait.name) {
|
|
6414
|
+
consumerDeclaredProvenance.set(rt.trait.name, { alias: rt.source.alias, traitName: rt.source.traitName });
|
|
6415
|
+
}
|
|
6416
|
+
}
|
|
4504
6417
|
const seen = new Set(consumerDeclared);
|
|
4505
6418
|
const visited = /* @__PURE__ */ new Set();
|
|
4506
6419
|
const pulledAs = /* @__PURE__ */ new Map();
|
|
4507
6420
|
const ownerOf = /* @__PURE__ */ new Map();
|
|
6421
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
4508
6422
|
const parentRewrites = /* @__PURE__ */ new Map();
|
|
4509
6423
|
const pulled = [];
|
|
6424
|
+
const embedderChain2 = (finalName) => {
|
|
6425
|
+
const chain2 = [];
|
|
6426
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
6427
|
+
let cur = finalName;
|
|
6428
|
+
while (cur !== void 0 && !seenNames.has(cur)) {
|
|
6429
|
+
seenNames.add(cur);
|
|
6430
|
+
const t = resolved.find((r) => r.trait.name === cur)?.trait ?? pulled.find((r) => r.trait.name === cur)?.trait;
|
|
6431
|
+
if (!t) break;
|
|
6432
|
+
if (t.config) chain2.push(t.config);
|
|
6433
|
+
cur = parentOf.get(cur);
|
|
6434
|
+
}
|
|
6435
|
+
return chain2;
|
|
6436
|
+
};
|
|
4510
6437
|
const noteRewrite = (parent, from, to) => {
|
|
4511
6438
|
let m = parentRewrites.get(parent);
|
|
4512
6439
|
if (!m) {
|
|
@@ -4516,8 +6443,8 @@ var ReferenceResolver = class {
|
|
|
4516
6443
|
m.set(from, to);
|
|
4517
6444
|
};
|
|
4518
6445
|
for (let item = work.pop(); item !== void 0; item = work.pop()) {
|
|
4519
|
-
const { alias, sibling, linkedEntity, parent, owner } = item;
|
|
4520
|
-
const pullKey = `${alias}
|
|
6446
|
+
const { alias, fallback, sibling, linkedEntity, parent, owner, preResolvedScope } = item;
|
|
6447
|
+
const pullKey = `${alias} ${sibling} ${owner} ${parent}`;
|
|
4521
6448
|
const existing = pulledAs.get(pullKey);
|
|
4522
6449
|
if (existing !== void 0) {
|
|
4523
6450
|
if (existing !== sibling) noteRewrite(parent, sibling, existing);
|
|
@@ -4525,73 +6452,122 @@ var ReferenceResolver = class {
|
|
|
4525
6452
|
}
|
|
4526
6453
|
let finalName = sibling;
|
|
4527
6454
|
if (seen.has(sibling)) {
|
|
4528
|
-
|
|
4529
|
-
|
|
6455
|
+
const provenance = consumerDeclaredProvenance.get(sibling);
|
|
6456
|
+
if (consumerDeclared.has(sibling) && provenance?.alias === alias && provenance.traitName === sibling) {
|
|
6457
|
+
continue;
|
|
6458
|
+
}
|
|
6459
|
+
finalName = `${parent}${sibling}`;
|
|
4530
6460
|
if (seen.has(finalName)) continue;
|
|
4531
6461
|
}
|
|
4532
6462
|
if (visited.has(pullKey)) continue;
|
|
4533
6463
|
visited.add(pullKey);
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
let atomEntry = null;
|
|
4537
|
-
for (const o of importedOrbitals(imported)) {
|
|
4538
|
-
atomEntry = findTraitEntryInOrbital(o, sibling);
|
|
4539
|
-
if (atomEntry) break;
|
|
4540
|
-
}
|
|
4541
|
-
if (!atomEntry) continue;
|
|
6464
|
+
let searchImports = imports;
|
|
6465
|
+
let searchAlias = alias;
|
|
4542
6466
|
let atomTrait;
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
6467
|
+
let childScope;
|
|
6468
|
+
let foundTypeArgs;
|
|
6469
|
+
let childPreResolvedScope;
|
|
6470
|
+
if (preResolvedScope) {
|
|
6471
|
+
const found = preResolvedScope.traits.find((rt) => rt.trait.name === sibling);
|
|
6472
|
+
if (found) {
|
|
6473
|
+
atomTrait = found.trait;
|
|
6474
|
+
childScope = { imports: searchImports, alias: searchAlias };
|
|
6475
|
+
foundTypeArgs = found.typeArgs;
|
|
6476
|
+
childPreResolvedScope = preResolvedScope;
|
|
4550
6477
|
}
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
if (!
|
|
4567
|
-
|
|
4568
|
-
|
|
6478
|
+
}
|
|
6479
|
+
if (!atomTrait) {
|
|
6480
|
+
let imported = imports.orbitals.get(alias);
|
|
6481
|
+
let atomEntry = null;
|
|
6482
|
+
let atomOrbitalIndex = -1;
|
|
6483
|
+
if (imported) {
|
|
6484
|
+
const list = importedOrbitals(imported);
|
|
6485
|
+
for (let i = 0; i < list.length; i++) {
|
|
6486
|
+
atomEntry = findTraitEntryInOrbital(list[i], sibling);
|
|
6487
|
+
if (atomEntry) {
|
|
6488
|
+
atomOrbitalIndex = i;
|
|
6489
|
+
break;
|
|
6490
|
+
}
|
|
6491
|
+
}
|
|
6492
|
+
}
|
|
6493
|
+
if (!atomEntry && fallback) {
|
|
6494
|
+
const fbImported = fallback.imports.orbitals.get(fallback.alias);
|
|
6495
|
+
if (fbImported) {
|
|
6496
|
+
const list = importedOrbitals(fbImported);
|
|
6497
|
+
for (let i = 0; i < list.length; i++) {
|
|
6498
|
+
atomEntry = findTraitEntryInOrbital(list[i], sibling);
|
|
6499
|
+
if (atomEntry) {
|
|
6500
|
+
imported = fbImported;
|
|
6501
|
+
searchImports = fallback.imports;
|
|
6502
|
+
searchAlias = fallback.alias;
|
|
6503
|
+
atomOrbitalIndex = i;
|
|
6504
|
+
break;
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
}
|
|
6508
|
+
}
|
|
6509
|
+
if (!imported || !atomEntry) continue;
|
|
6510
|
+
const preResolvedOrbital = imported.resolvedOrbitals?.[atomOrbitalIndex];
|
|
6511
|
+
const preResolved = preResolvedOrbital?.traits.find((rt) => rt.trait.name === sibling);
|
|
6512
|
+
if (preResolved) {
|
|
6513
|
+
atomTrait = preResolved.trait;
|
|
6514
|
+
childScope = { imports: searchImports, alias: searchAlias };
|
|
6515
|
+
foundTypeArgs = preResolved.typeArgs;
|
|
6516
|
+
childPreResolvedScope = preResolvedOrbital;
|
|
6517
|
+
} else {
|
|
6518
|
+
const entryResolved = await this.resolveTraitEntry(imported, atomEntry, sibling, chain, searchImports);
|
|
6519
|
+
if (!entryResolved.success) {
|
|
6520
|
+
errors.push(...entryResolved.errors);
|
|
6521
|
+
continue;
|
|
6522
|
+
}
|
|
6523
|
+
atomTrait = entryResolved.data.trait;
|
|
6524
|
+
childScope = entryResolved.data.embedScope;
|
|
6525
|
+
foundTypeArgs = entryResolved.data.typeArgs;
|
|
4569
6526
|
}
|
|
4570
|
-
atomTrait = nested.data.trait;
|
|
4571
6527
|
}
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
6528
|
+
if (!atomTrait || !childScope) continue;
|
|
6529
|
+
const nextFallback = childScope.alias === searchAlias && childScope.imports === searchImports ? void 0 : childScope;
|
|
6530
|
+
let copy = resolveForwardedSiblingConfigFrom(
|
|
6531
|
+
applyLinkedEntityRename(atomTrait, linkedEntity, this.entityIdsInScope),
|
|
6532
|
+
embedderChain2(parent),
|
|
6533
|
+
orbitalConfig,
|
|
6534
|
+
this.schemaConfig
|
|
4576
6535
|
);
|
|
4577
6536
|
if (finalName !== sibling) {
|
|
4578
6537
|
copy = { ...copy, name: finalName };
|
|
4579
6538
|
noteRewrite(parent, sibling, finalName);
|
|
4580
6539
|
}
|
|
6540
|
+
const childParent = childPreResolvedScope ? parent : finalName;
|
|
4581
6541
|
for (const next of traitEmbedNamesOf(copy)) {
|
|
4582
|
-
work.push({
|
|
6542
|
+
work.push({
|
|
6543
|
+
alias,
|
|
6544
|
+
fallback: nextFallback,
|
|
6545
|
+
sibling: next,
|
|
6546
|
+
linkedEntity,
|
|
6547
|
+
parent: childParent,
|
|
6548
|
+
owner,
|
|
6549
|
+
preResolvedScope: childPreResolvedScope
|
|
6550
|
+
});
|
|
4583
6551
|
}
|
|
4584
6552
|
pulledAs.set(pullKey, finalName);
|
|
4585
6553
|
subsFor(owner).set(sibling, finalName);
|
|
4586
6554
|
ownerOf.set(finalName, owner);
|
|
6555
|
+
parentOf.set(finalName, parent);
|
|
4587
6556
|
seen.add(finalName);
|
|
4588
6557
|
pulled.push({
|
|
4589
6558
|
trait: copy,
|
|
4590
6559
|
source: { type: "imported", alias, traitName: sibling },
|
|
4591
|
-
...linkedEntity !== void 0 ? { linkedEntity } : {}
|
|
6560
|
+
...linkedEntity !== void 0 ? { linkedEntity } : {},
|
|
6561
|
+
...foundTypeArgs !== void 0 ? { typeArgs: foundTypeArgs } : {}
|
|
4592
6562
|
});
|
|
6563
|
+
if (copy.linkedEntity !== void 0) {
|
|
6564
|
+
const aux = entityByNameForAlias(imports, alias, copy.linkedEntity) ?? entityByNameAnyAlias(imports, copy.linkedEntity);
|
|
6565
|
+
if (aux) auxEntities.push(aux);
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
if (pulled.length === 0 && parentRewrites.size === 0) {
|
|
6569
|
+
return { errors, auxEntities, pulledNames: /* @__PURE__ */ new Set() };
|
|
4593
6570
|
}
|
|
4594
|
-
if (pulled.length === 0 && parentRewrites.size === 0) return errors;
|
|
4595
6571
|
const applyRewrites = (rt) => {
|
|
4596
6572
|
const subs = rt.trait.name ? parentRewrites.get(rt.trait.name) : void 0;
|
|
4597
6573
|
if (subs) rt.trait = renameTraitEmbeds(rt.trait, subs);
|
|
@@ -4603,39 +6579,29 @@ var ReferenceResolver = class {
|
|
|
4603
6579
|
if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
|
|
4604
6580
|
}
|
|
4605
6581
|
for (const rt of pulled) {
|
|
4606
|
-
const listens = rt.trait.listens;
|
|
4607
6582
|
const owner = rt.trait.name ? ownerOf.get(rt.trait.name) : void 0;
|
|
4608
6583
|
const subs = owner ? ownerSubs.get(owner) : void 0;
|
|
4609
|
-
if (!
|
|
4610
|
-
|
|
4611
|
-
const nextListens = listens.map((listen) => {
|
|
4612
|
-
const source = listen.source;
|
|
4613
|
-
if (!source || source.kind !== "trait") return listen;
|
|
4614
|
-
const target = subs.get(source.trait);
|
|
4615
|
-
if (target === void 0 || target === source.trait) return listen;
|
|
4616
|
-
changed = true;
|
|
4617
|
-
const traitId = idByName.get(target);
|
|
4618
|
-
return {
|
|
4619
|
-
...listen,
|
|
4620
|
-
source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
|
|
4621
|
-
};
|
|
4622
|
-
});
|
|
4623
|
-
if (changed) rt.trait = { ...rt.trait, listens: nextListens };
|
|
6584
|
+
if (!subs) continue;
|
|
6585
|
+
rt.trait = rewriteListenSources(rt.trait, subs, idByName);
|
|
4624
6586
|
}
|
|
4625
6587
|
refResolverLog.info("sibling-pull", {
|
|
4626
6588
|
pulled: pulled.map((p) => ({
|
|
4627
6589
|
trait: p.trait.name,
|
|
4628
6590
|
owner: p.trait.name ? ownerOf.get(p.trait.name) : void 0,
|
|
6591
|
+
parent: p.trait.name ? parentOf.get(p.trait.name) : void 0,
|
|
4629
6592
|
linkedEntity: p.linkedEntity ?? p.trait.linkedEntity
|
|
4630
6593
|
}))
|
|
4631
6594
|
});
|
|
4632
6595
|
resolved.push(...pulled);
|
|
4633
|
-
|
|
6596
|
+
const pulledNames = new Set(
|
|
6597
|
+
pulled.map((p) => p.trait.name).filter((n) => Boolean(n))
|
|
6598
|
+
);
|
|
6599
|
+
return { errors, auxEntities, pulledNames };
|
|
4634
6600
|
}
|
|
4635
6601
|
/**
|
|
4636
6602
|
* Resolve a single trait reference.
|
|
4637
6603
|
*/
|
|
4638
|
-
resolveTraitRef(traitRef, imports) {
|
|
6604
|
+
async resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames) {
|
|
4639
6605
|
if (typeof traitRef !== "string" && "stateMachine" in traitRef) {
|
|
4640
6606
|
const { trait: resolvedInline, errors } = resolveConfigRefEmitNames(traitRef);
|
|
4641
6607
|
if (errors.length > 0) {
|
|
@@ -4655,16 +6621,33 @@ var ReferenceResolver = class {
|
|
|
4655
6621
|
return this.resolveTraitRefString(
|
|
4656
6622
|
refObj.ref,
|
|
4657
6623
|
imports,
|
|
6624
|
+
chain,
|
|
4658
6625
|
refObj.config,
|
|
4659
6626
|
refObj.linkedEntity,
|
|
4660
6627
|
refObj.name,
|
|
4661
6628
|
refObj.events,
|
|
4662
6629
|
refObj.listens,
|
|
4663
|
-
refObj.refId
|
|
6630
|
+
refObj.refId,
|
|
6631
|
+
refObj.typeArgs,
|
|
6632
|
+
embedCtx,
|
|
6633
|
+
aliasEntityRenames
|
|
4664
6634
|
);
|
|
4665
6635
|
}
|
|
4666
6636
|
if (typeof traitRef === "string") {
|
|
4667
|
-
return this.resolveTraitRefString(
|
|
6637
|
+
return this.resolveTraitRefString(
|
|
6638
|
+
traitRef,
|
|
6639
|
+
imports,
|
|
6640
|
+
chain,
|
|
6641
|
+
void 0,
|
|
6642
|
+
void 0,
|
|
6643
|
+
void 0,
|
|
6644
|
+
void 0,
|
|
6645
|
+
void 0,
|
|
6646
|
+
void 0,
|
|
6647
|
+
void 0,
|
|
6648
|
+
embedCtx,
|
|
6649
|
+
aliasEntityRenames
|
|
6650
|
+
);
|
|
4668
6651
|
}
|
|
4669
6652
|
return {
|
|
4670
6653
|
success: false,
|
|
@@ -4674,8 +6657,10 @@ var ReferenceResolver = class {
|
|
|
4674
6657
|
/**
|
|
4675
6658
|
* Resolve a trait reference string.
|
|
4676
6659
|
*/
|
|
4677
|
-
resolveTraitRefString(ref, imports, config, linkedEntity, overrideName, eventRenames, listensOverride, refId) {
|
|
6660
|
+
async resolveTraitRefString(ref, imports, chain, config, linkedEntity, overrideName, eventRenames, listensOverride, refId, typeArgs, embedCtx, aliasEntityRenames) {
|
|
4678
6661
|
const parsed = parseImportedTraitRef(ref);
|
|
6662
|
+
const localName = overrideName ?? (parsed ? parsed.traitName : ref);
|
|
6663
|
+
const resolvedConfig = config && embedCtx ? resolveEmbedderConfigForward(config, localName, embedCtx, this.schemaConfig) : config;
|
|
4679
6664
|
if (parsed) {
|
|
4680
6665
|
const imported = imports.orbitals.get(parsed.alias);
|
|
4681
6666
|
if (!imported) {
|
|
@@ -4687,9 +6672,27 @@ var ReferenceResolver = class {
|
|
|
4687
6672
|
};
|
|
4688
6673
|
}
|
|
4689
6674
|
let trait = null;
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
6675
|
+
let embedScope = { imports, alias: parsed.alias };
|
|
6676
|
+
const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
|
|
6677
|
+
if (idEntry && idEntry.kind === "trait") {
|
|
6678
|
+
trait = idEntry.node;
|
|
6679
|
+
} else {
|
|
6680
|
+
for (const o of importedOrbitals(imported)) {
|
|
6681
|
+
const entry = findTraitEntryInOrbital(o, parsed.traitName);
|
|
6682
|
+
if (!entry) continue;
|
|
6683
|
+
const entryResolved = await this.resolveTraitEntry(
|
|
6684
|
+
imported,
|
|
6685
|
+
entry,
|
|
6686
|
+
parsed.traitName,
|
|
6687
|
+
chain,
|
|
6688
|
+
imports,
|
|
6689
|
+
resolvedConfig
|
|
6690
|
+
);
|
|
6691
|
+
if (!entryResolved.success) return entryResolved;
|
|
6692
|
+
trait = entryResolved.data.trait;
|
|
6693
|
+
embedScope = entryResolved.data.embedScope;
|
|
6694
|
+
break;
|
|
6695
|
+
}
|
|
4693
6696
|
}
|
|
4694
6697
|
if (!trait) {
|
|
4695
6698
|
const available = importedOrbitals(imported).flatMap((o) => this.listTraitsInOrbital(o));
|
|
@@ -4700,15 +6703,36 @@ var ReferenceResolver = class {
|
|
|
4700
6703
|
]
|
|
4701
6704
|
};
|
|
4702
6705
|
}
|
|
6706
|
+
if (embedCtx && trait.config) {
|
|
6707
|
+
const homeResolvedConfig = resolveConfigForwards(
|
|
6708
|
+
trait.config,
|
|
6709
|
+
embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph),
|
|
6710
|
+
embedCtx.orbitalConfig,
|
|
6711
|
+
homeOrbitalConfigForTrait(imported, parsed.traitName),
|
|
6712
|
+
imported.schemaConfig,
|
|
6713
|
+
this.schemaConfig
|
|
6714
|
+
);
|
|
6715
|
+
if (homeResolvedConfig) {
|
|
6716
|
+
trait = { ...trait, config: homeResolvedConfig };
|
|
6717
|
+
}
|
|
6718
|
+
}
|
|
4703
6719
|
const baseTrait = overrideName ? { ...trait, name: overrideName } : trait;
|
|
4704
|
-
const { trait: configResolvedTrait, errors: configRefErrors } = resolveConfigRefEmitNames(baseTrait,
|
|
6720
|
+
const { trait: configResolvedTrait, errors: configRefErrors, resolvedKnobs } = resolveConfigRefEmitNames(baseTrait, resolvedConfig);
|
|
4705
6721
|
if (configRefErrors.length > 0) {
|
|
4706
6722
|
return { success: false, errors: configRefErrors };
|
|
4707
6723
|
}
|
|
4708
|
-
const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity);
|
|
4709
|
-
const
|
|
4710
|
-
const
|
|
4711
|
-
const
|
|
6724
|
+
const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity, this.entityIdsInScope);
|
|
6725
|
+
const aliasSubs = aliasEntityRenames?.get(parsed.alias);
|
|
6726
|
+
const aliasReboundTrait = aliasSubs ? applyAliasEntityRenames(reboundTrait, aliasSubs, this.entityIdsInScope) : reboundTrait;
|
|
6727
|
+
const renamedTrait = applyEventRenames(aliasReboundTrait, eventRenames);
|
|
6728
|
+
const foldedTrait = foldEventRenameOntoDeclaredKnobs(
|
|
6729
|
+
renamedTrait,
|
|
6730
|
+
resolvedKnobValues(baseTrait, configResolvedTrait, resolvedKnobs),
|
|
6731
|
+
eventRenames
|
|
6732
|
+
);
|
|
6733
|
+
const renamedConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundTrait.config, eventRenames);
|
|
6734
|
+
const configFoldedTrait = foldCallSiteConfigOntoTrait(foldedTrait, renamedConfig);
|
|
6735
|
+
const finalTrait = listensOverride !== void 0 ? { ...configFoldedTrait, listens: listensOverride } : configFoldedTrait;
|
|
4712
6736
|
if (listensOverride !== void 0) {
|
|
4713
6737
|
refResolverLog.info("listens-override:imported", {
|
|
4714
6738
|
trait: finalTrait.name,
|
|
@@ -4723,7 +6747,9 @@ var ReferenceResolver = class {
|
|
|
4723
6747
|
trait: finalTrait,
|
|
4724
6748
|
source: { type: "imported", alias: parsed.alias, traitName: parsed.traitName },
|
|
4725
6749
|
config: renamedConfig,
|
|
4726
|
-
linkedEntity
|
|
6750
|
+
linkedEntity,
|
|
6751
|
+
embedScope,
|
|
6752
|
+
...typeArgs !== void 0 ? { typeArgs } : {}
|
|
4727
6753
|
},
|
|
4728
6754
|
warnings: []
|
|
4729
6755
|
};
|
|
@@ -4731,14 +6757,20 @@ var ReferenceResolver = class {
|
|
|
4731
6757
|
const localTrait = (refId && this.localTraitsById.get(refId)) ?? this.localTraits.get(ref);
|
|
4732
6758
|
if (localTrait) {
|
|
4733
6759
|
const baseLocal = overrideName ? { ...localTrait, name: overrideName } : localTrait;
|
|
4734
|
-
const { trait: configResolvedLocal, errors: localConfigRefErrors } = resolveConfigRefEmitNames(baseLocal,
|
|
6760
|
+
const { trait: configResolvedLocal, errors: localConfigRefErrors, resolvedKnobs: localResolvedKnobs } = resolveConfigRefEmitNames(baseLocal, resolvedConfig);
|
|
4735
6761
|
if (localConfigRefErrors.length > 0) {
|
|
4736
6762
|
return { success: false, errors: localConfigRefErrors };
|
|
4737
6763
|
}
|
|
4738
|
-
const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity);
|
|
6764
|
+
const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity, this.entityIdsInScope);
|
|
4739
6765
|
const renamedLocalTrait = applyEventRenames(reboundLocal, eventRenames);
|
|
4740
|
-
const
|
|
4741
|
-
|
|
6766
|
+
const foldedLocalTrait = foldEventRenameOntoDeclaredKnobs(
|
|
6767
|
+
renamedLocalTrait,
|
|
6768
|
+
resolvedKnobValues(baseLocal, configResolvedLocal, localResolvedKnobs),
|
|
6769
|
+
eventRenames
|
|
6770
|
+
);
|
|
6771
|
+
const renamedLocalConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundLocal.config, eventRenames);
|
|
6772
|
+
const configFoldedLocalTrait = foldCallSiteConfigOntoTrait(foldedLocalTrait, renamedLocalConfig);
|
|
6773
|
+
const finalLocalTrait = listensOverride !== void 0 ? { ...configFoldedLocalTrait, listens: listensOverride } : configFoldedLocalTrait;
|
|
4742
6774
|
if (listensOverride !== void 0) {
|
|
4743
6775
|
refResolverLog.info("listens-override:local", {
|
|
4744
6776
|
trait: finalLocalTrait.name,
|
|
@@ -4753,7 +6785,8 @@ var ReferenceResolver = class {
|
|
|
4753
6785
|
trait: finalLocalTrait,
|
|
4754
6786
|
source: { type: "local", name: ref },
|
|
4755
6787
|
config: renamedLocalConfig,
|
|
4756
|
-
linkedEntity
|
|
6788
|
+
linkedEntity,
|
|
6789
|
+
...typeArgs !== void 0 ? { typeArgs } : {}
|
|
4757
6790
|
},
|
|
4758
6791
|
warnings: []
|
|
4759
6792
|
};
|
|
@@ -4765,31 +6798,6 @@ var ReferenceResolver = class {
|
|
|
4765
6798
|
]
|
|
4766
6799
|
};
|
|
4767
6800
|
}
|
|
4768
|
-
/**
|
|
4769
|
-
* Find a trait in an orbital by name. Id-primary: when the calling ref
|
|
4770
|
-
* carries a `refId` and the id index has a matching trait entry, return it
|
|
4771
|
-
* directly — else fall back to the existing name match unchanged.
|
|
4772
|
-
*/
|
|
4773
|
-
findTraitInOrbital(orbital, traitName, refId, idIndex) {
|
|
4774
|
-
if (refId && idIndex) {
|
|
4775
|
-
const entry = idIndex.get(refId);
|
|
4776
|
-
if (entry && entry.kind === "trait") {
|
|
4777
|
-
return entry.node;
|
|
4778
|
-
}
|
|
4779
|
-
}
|
|
4780
|
-
for (const traitRef of orbital.traits) {
|
|
4781
|
-
if (typeof traitRef !== "string" && "stateMachine" in traitRef) {
|
|
4782
|
-
if (traitRef.name === traitName) {
|
|
4783
|
-
return traitRef;
|
|
4784
|
-
}
|
|
4785
|
-
}
|
|
4786
|
-
if (typeof traitRef !== "string" && "ref" in traitRef) {
|
|
4787
|
-
const refObj = traitRef;
|
|
4788
|
-
if (refObj.ref === traitName || refObj.name === traitName) ;
|
|
4789
|
-
}
|
|
4790
|
-
}
|
|
4791
|
-
return null;
|
|
4792
|
-
}
|
|
4793
6801
|
/**
|
|
4794
6802
|
* List trait names in an orbital.
|
|
4795
6803
|
*/
|
|
@@ -4805,11 +6813,11 @@ var ReferenceResolver = class {
|
|
|
4805
6813
|
/**
|
|
4806
6814
|
* Resolve page references.
|
|
4807
6815
|
*/
|
|
4808
|
-
resolvePages(pageRefs, imports) {
|
|
6816
|
+
async resolvePages(pageRefs, imports, chain) {
|
|
4809
6817
|
const errors = [];
|
|
4810
6818
|
const resolved = [];
|
|
4811
6819
|
for (const pageRef of pageRefs) {
|
|
4812
|
-
const result = this.resolvePageRef(pageRef, imports);
|
|
6820
|
+
const result = await this.resolvePageRef(pageRef, imports, chain);
|
|
4813
6821
|
if (!result.success) {
|
|
4814
6822
|
errors.push(...result.errors);
|
|
4815
6823
|
} else {
|
|
@@ -4824,7 +6832,7 @@ var ReferenceResolver = class {
|
|
|
4824
6832
|
/**
|
|
4825
6833
|
* Resolve a single page reference.
|
|
4826
6834
|
*/
|
|
4827
|
-
resolvePageRef(pageRef, imports) {
|
|
6835
|
+
async resolvePageRef(pageRef, imports, chain) {
|
|
4828
6836
|
if (!isPageReference(pageRef)) {
|
|
4829
6837
|
return {
|
|
4830
6838
|
success: true,
|
|
@@ -4837,10 +6845,10 @@ var ReferenceResolver = class {
|
|
|
4837
6845
|
};
|
|
4838
6846
|
}
|
|
4839
6847
|
if (isPageReferenceString(pageRef)) {
|
|
4840
|
-
return this.resolvePageRefString(pageRef, imports);
|
|
6848
|
+
return this.resolvePageRefString(pageRef, imports, chain);
|
|
4841
6849
|
}
|
|
4842
6850
|
if (isPageReferenceObject(pageRef)) {
|
|
4843
|
-
return this.resolvePageRefObject(pageRef, imports);
|
|
6851
|
+
return this.resolvePageRefObject(pageRef, imports, chain);
|
|
4844
6852
|
}
|
|
4845
6853
|
return {
|
|
4846
6854
|
success: false,
|
|
@@ -4850,7 +6858,7 @@ var ReferenceResolver = class {
|
|
|
4850
6858
|
/**
|
|
4851
6859
|
* Resolve a page reference string.
|
|
4852
6860
|
*/
|
|
4853
|
-
resolvePageRefString(ref, imports, refId) {
|
|
6861
|
+
async resolvePageRefString(ref, imports, chain, refId) {
|
|
4854
6862
|
const parsed = parsePageRef(ref);
|
|
4855
6863
|
if (!parsed) {
|
|
4856
6864
|
return {
|
|
@@ -4868,9 +6876,18 @@ var ReferenceResolver = class {
|
|
|
4868
6876
|
};
|
|
4869
6877
|
}
|
|
4870
6878
|
let page = null;
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
6879
|
+
const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
|
|
6880
|
+
if (idEntry && idEntry.kind === "page") {
|
|
6881
|
+
page = { ...idEntry.node };
|
|
6882
|
+
} else {
|
|
6883
|
+
for (const o of importedOrbitals(imported)) {
|
|
6884
|
+
const entry = findPageEntryInOrbital(o, parsed.pageName);
|
|
6885
|
+
if (!entry) continue;
|
|
6886
|
+
const entryResolved = await this.resolvePageEntry(imported, entry, chain);
|
|
6887
|
+
if (!entryResolved.success) return entryResolved;
|
|
6888
|
+
page = entryResolved.data.page;
|
|
6889
|
+
break;
|
|
6890
|
+
}
|
|
4874
6891
|
}
|
|
4875
6892
|
if (!page) {
|
|
4876
6893
|
const available = importedOrbitals(imported).flatMap((o) => this.listPagesInOrbital(o));
|
|
@@ -4892,10 +6909,18 @@ var ReferenceResolver = class {
|
|
|
4892
6909
|
};
|
|
4893
6910
|
}
|
|
4894
6911
|
/**
|
|
4895
|
-
* Resolve a page reference object
|
|
6912
|
+
* Resolve a page reference object, applying every call-site override —
|
|
6913
|
+
* `path` (direct assignment), `linkedEntity` (rebind `primaryEntity` and
|
|
6914
|
+
* every page-level trait pointer that named the old entity), and `traits`
|
|
6915
|
+
* (full replacement) — mirroring the compiler's `apply_overrides_to_page`
|
|
6916
|
+
* (`phases/inline/page.rs:21-93`). `Page.traits` is a `PageTraitRef[]`
|
|
6917
|
+
* pointer list (a trait's own body lives in the orbital's `traits {}`, not
|
|
6918
|
+
* on the page), so unlike Rust's `TraitReference` the `linkedEntity` rebind
|
|
6919
|
+
* only ever touches each pointer's OWN `linkedEntity` field — there is no
|
|
6920
|
+
* inline trait body here to walk with `renameEntitiesInTrait`.
|
|
4896
6921
|
*/
|
|
4897
|
-
resolvePageRefObject(refObj, imports) {
|
|
4898
|
-
const baseResult = this.resolvePageRefString(refObj.ref, imports, refObj.refId);
|
|
6922
|
+
async resolvePageRefObject(refObj, imports, chain) {
|
|
6923
|
+
const baseResult = await this.resolvePageRefString(refObj.ref, imports, chain, refObj.refId);
|
|
4899
6924
|
if (!baseResult.success) {
|
|
4900
6925
|
return baseResult;
|
|
4901
6926
|
}
|
|
@@ -4909,36 +6934,25 @@ var ReferenceResolver = class {
|
|
|
4909
6934
|
resolved.pathOverridden = true;
|
|
4910
6935
|
resolved.originalPath = originalPath;
|
|
4911
6936
|
}
|
|
6937
|
+
if (refObj.linkedEntity) {
|
|
6938
|
+
const oldEntity = resolved.page.primaryEntity;
|
|
6939
|
+
const newEntity = refObj.linkedEntity;
|
|
6940
|
+
const rebindPointers = (pointers) => oldEntity && oldEntity !== newEntity ? pointers?.map((pt) => pt.linkedEntity === oldEntity ? { ...pt, linkedEntity: newEntity } : pt) : pointers;
|
|
6941
|
+
resolved.page = {
|
|
6942
|
+
...resolved.page,
|
|
6943
|
+
primaryEntity: newEntity,
|
|
6944
|
+
traits: rebindPointers(resolved.page.traits)
|
|
6945
|
+
};
|
|
6946
|
+
}
|
|
6947
|
+
if (refObj.traits) {
|
|
6948
|
+
resolved.page = { ...resolved.page, traits: refObj.traits.map(toPageTraitRef) };
|
|
6949
|
+
}
|
|
4912
6950
|
return {
|
|
4913
6951
|
success: true,
|
|
4914
6952
|
data: resolved,
|
|
4915
6953
|
warnings: baseResult.warnings
|
|
4916
6954
|
};
|
|
4917
6955
|
}
|
|
4918
|
-
/**
|
|
4919
|
-
* Find a page in an orbital by name. Id-primary: when the calling ref
|
|
4920
|
-
* carries a `refId` and the id index has a matching page entry, return it
|
|
4921
|
-
* directly — else fall back to the existing name match unchanged.
|
|
4922
|
-
*/
|
|
4923
|
-
findPageInOrbital(orbital, pageName, refId, idIndex) {
|
|
4924
|
-
if (refId && idIndex) {
|
|
4925
|
-
const entry = idIndex.get(refId);
|
|
4926
|
-
if (entry && entry.kind === "page") {
|
|
4927
|
-
return { ...entry.node };
|
|
4928
|
-
}
|
|
4929
|
-
}
|
|
4930
|
-
const pages = orbital.pages;
|
|
4931
|
-
if (!pages) return null;
|
|
4932
|
-
for (const pageRef of pages) {
|
|
4933
|
-
if (typeof pageRef !== "string" && !("ref" in pageRef)) {
|
|
4934
|
-
const page = pageRef;
|
|
4935
|
-
if (page.name === pageName) {
|
|
4936
|
-
return { ...page };
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
}
|
|
4940
|
-
return null;
|
|
4941
|
-
}
|
|
4942
6956
|
/**
|
|
4943
6957
|
* List page names in an orbital.
|
|
4944
6958
|
*/
|
|
@@ -4953,6 +6967,645 @@ var ReferenceResolver = class {
|
|
|
4953
6967
|
}
|
|
4954
6968
|
return names;
|
|
4955
6969
|
}
|
|
6970
|
+
/**
|
|
6971
|
+
* Flatten every reference-form orbital (`orbital X = Alias.orbitals.Y
|
|
6972
|
+
* { … }`, docs/Almadar_Orbital_Import.md §4) in a schema BEFORE the
|
|
6973
|
+
* ordinary per-orbital {@link resolve} pass runs — the interpreter-path
|
|
6974
|
+
* twin of the (not-yet-landed) compiler's inline-phase flatten. After this
|
|
6975
|
+
* call, no returned `OrbitalDefinition` carries `.reference`.
|
|
6976
|
+
*/
|
|
6977
|
+
async resolveOrbitalImports(schema, opts) {
|
|
6978
|
+
const errors = [];
|
|
6979
|
+
const flattened = [];
|
|
6980
|
+
const chain = { push: () => null, pop: () => {
|
|
6981
|
+
}, clone() {
|
|
6982
|
+
return this;
|
|
6983
|
+
} };
|
|
6984
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
6985
|
+
const consumerEntityIds = consumerEntityIdsOf(schema.orbitals);
|
|
6986
|
+
for (const [name, id] of await this.precomputeReferenceFormPrimaryIds(schema, chain)) {
|
|
6987
|
+
if (!consumerEntityIds.has(name)) consumerEntityIds.set(name, id);
|
|
6988
|
+
}
|
|
6989
|
+
const listenSourceTargets = await this.precomputeReferenceFormListenTargets(schema.orbitals, chain);
|
|
6990
|
+
const consumerRoster = identityEntitiesOf(schema.orbitals);
|
|
6991
|
+
for (const orbital of schema.orbitals) {
|
|
6992
|
+
if (!orbital.reference) {
|
|
6993
|
+
if (!opts?.skipTypeParamSentinels && isInlineEntity(orbital.entity)) {
|
|
6994
|
+
resolveOrbitalTypeParamSentinels(
|
|
6995
|
+
orbital.traits.filter(isInlineTrait).map((t) => ({ trait: t })),
|
|
6996
|
+
orbital.entity,
|
|
6997
|
+
(orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
|
|
6998
|
+
orbital.types
|
|
6999
|
+
);
|
|
7000
|
+
}
|
|
7001
|
+
flattened.push(orbital);
|
|
7002
|
+
continue;
|
|
7003
|
+
}
|
|
7004
|
+
const result = await this.resolveOrbitalRefChain(
|
|
7005
|
+
orbital,
|
|
7006
|
+
void 0,
|
|
7007
|
+
chain,
|
|
7008
|
+
visiting,
|
|
7009
|
+
consumerEntityIds,
|
|
7010
|
+
consumerRoster,
|
|
7011
|
+
listenSourceTargets
|
|
7012
|
+
);
|
|
7013
|
+
if (!result.success) {
|
|
7014
|
+
errors.push(...result.errors);
|
|
7015
|
+
continue;
|
|
7016
|
+
}
|
|
7017
|
+
if (!opts?.skipTypeParamSentinels && isInlineEntity(result.data.entity)) {
|
|
7018
|
+
resolveOrbitalTypeParamSentinels(
|
|
7019
|
+
result.data.traits.filter(isInlineTrait).map((t) => ({ trait: t })),
|
|
7020
|
+
result.data.entity,
|
|
7021
|
+
(result.data.auxiliaryEntities ?? []).filter(isInlineEntity),
|
|
7022
|
+
result.data.types
|
|
7023
|
+
);
|
|
7024
|
+
}
|
|
7025
|
+
flattened.push(result.data);
|
|
7026
|
+
}
|
|
7027
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7028
|
+
reconcileOrbitalRefEventIdRenames(schema, flattened);
|
|
7029
|
+
return { success: true, data: flattened, warnings: [] };
|
|
7030
|
+
}
|
|
7031
|
+
/**
|
|
7032
|
+
* (B) The materialized primary name → derived id of every REFERENCE-FORM
|
|
7033
|
+
* orbital this schema declares (`orbital X = Alias.orbitals.Y { … }`),
|
|
7034
|
+
* computed order-free — WITHOUT requiring any other orbital in `schema`
|
|
7035
|
+
* to have resolved first, and without recursively flattening the
|
|
7036
|
+
* upstream. Each reference's alias is loaded via the ordinary
|
|
7037
|
+
* `resolveImports` path, which the loader caches by absolute path (see
|
|
7038
|
+
* `ExternalOrbitalLoader`'s `LoaderCache`) — the REAL flatten
|
|
7039
|
+
* (`resolveOrbitalRefChain`) moments later is then a cache hit, no
|
|
7040
|
+
* duplicate work — and its named orbital looked up directly in the
|
|
7041
|
+
* loaded (un-flattened) schema: an upstream's OWN primary entity id/name
|
|
7042
|
+
* never change through resolution (only a CONSUMER-side CLONE gets a
|
|
7043
|
+
* fresh derived id), so this shallow load's entity is exactly what the
|
|
7044
|
+
* real flatten pass would see too. Uses the SAME `materializedPrimaryEntity`
|
|
7045
|
+
* pair `materializeOrbitalRef` computes for itself — one owner. JS twin
|
|
7046
|
+
* of the compiled path's `precompute_reference_form_primary_ids`.
|
|
7047
|
+
*
|
|
7048
|
+
* Best-effort: a reference this pre-pass cannot resolve (unknown alias,
|
|
7049
|
+
* malformed reference string, upstream orbital not found, load failure)
|
|
7050
|
+
* is silently skipped here — the REAL `resolveOrbitalRefChain` call
|
|
7051
|
+
* moments later still surfaces the actual error for it.
|
|
7052
|
+
*/
|
|
7053
|
+
async precomputeReferenceFormPrimaryIds(schema, chain) {
|
|
7054
|
+
const out = /* @__PURE__ */ new Map();
|
|
7055
|
+
for (const orbital of schema.orbitals) {
|
|
7056
|
+
const ref = orbital.reference;
|
|
7057
|
+
if (!ref) continue;
|
|
7058
|
+
const parsed = parseOrbitalRef(ref.ref);
|
|
7059
|
+
if (!parsed) continue;
|
|
7060
|
+
const importsResult = await this.resolveImports(orbital.uses ?? [], void 0, chain);
|
|
7061
|
+
if (!importsResult.success) continue;
|
|
7062
|
+
const imported = importsResult.data.orbitals.get(parsed.alias);
|
|
7063
|
+
if (!imported) continue;
|
|
7064
|
+
const upstream = importedOrbitals(imported).find((o) => o.name === parsed.orbitalName);
|
|
7065
|
+
if (!upstream || !isInlineEntity(upstream.entity)) continue;
|
|
7066
|
+
const { name, id } = materializedPrimaryEntity(upstream.entity, upstream.id, ref, orbital.name);
|
|
7067
|
+
out.set(name, id);
|
|
7068
|
+
}
|
|
7069
|
+
return out;
|
|
7070
|
+
}
|
|
7071
|
+
/**
|
|
7072
|
+
* G1 (`docs/Almadar_Compiler_Gaps.md` §82): every reference-form
|
|
7073
|
+
* orbital's OWN materialized trait set, keyed by {@link siblingImportKey}
|
|
7074
|
+
* (upstream alias + upstream orbital name), mapped to that import's local
|
|
7075
|
+
* orbital name + every kept trait's final name/id ({@link
|
|
7076
|
+
* materializedTraitSubs}). Computed order-free — WITHOUT requiring any
|
|
7077
|
+
* other orbital in `schema` to have resolved first — same precompute
|
|
7078
|
+
* shape as {@link precomputeReferenceFormPrimaryIds}, but for LISTEN-
|
|
7079
|
+
* SOURCE rewriting: consulted by {@link rewriteListenSources} so a source
|
|
7080
|
+
* naming ANY reference-form orbital of this schema resolves regardless of
|
|
7081
|
+
* declaration order. Unlike the entity-id precompute, this resolves the
|
|
7082
|
+
* upstream's OWN traits via the ordinary `this.resolve()` pass (the same
|
|
7083
|
+
* call {@link materializeOrbitalRef} makes on its own upstream, with the
|
|
7084
|
+
* same `schemaConfig` save/restore) rather than reading the raw unresolved
|
|
7085
|
+
* schema — the JS identity model has no pre-resolve declaration id for a
|
|
7086
|
+
* COMPOSED trait reference (unlike the compiled path's V4 dual-carry
|
|
7087
|
+
* `TraitReference::Reference.id`), so a shallow read would silently
|
|
7088
|
+
* under-report every composed trait's id.
|
|
7089
|
+
*
|
|
7090
|
+
* Best-effort: a reference this pre-pass cannot resolve (unknown alias,
|
|
7091
|
+
* malformed reference string, upstream orbital not found, itself still
|
|
7092
|
+
* reference-form, load/resolve failure) is silently skipped here — the
|
|
7093
|
+
* REAL `resolveOrbitalRefChain`/`materializeOrbitalRef` call moments
|
|
7094
|
+
* later still surfaces the actual error for it.
|
|
7095
|
+
*/
|
|
7096
|
+
async precomputeReferenceFormListenTargets(orbitals, chain) {
|
|
7097
|
+
const out = /* @__PURE__ */ new Map();
|
|
7098
|
+
for (const orbital of orbitals) {
|
|
7099
|
+
const ref = orbital.reference;
|
|
7100
|
+
if (!ref) continue;
|
|
7101
|
+
const parsed = parseOrbitalRef(ref.ref);
|
|
7102
|
+
if (!parsed) continue;
|
|
7103
|
+
const importsResult = await this.resolveImports(orbital.uses ?? [], void 0, chain);
|
|
7104
|
+
if (!importsResult.success) continue;
|
|
7105
|
+
const imported = importsResult.data.orbitals.get(parsed.alias);
|
|
7106
|
+
if (!imported) continue;
|
|
7107
|
+
const upstream = importedOrbitals(imported).find((o) => o.name === parsed.orbitalName);
|
|
7108
|
+
if (!upstream || upstream.reference) continue;
|
|
7109
|
+
const savedSchemaConfig = this.schemaConfig;
|
|
7110
|
+
this.schemaConfig = imported.schemaConfig;
|
|
7111
|
+
let resolvedUpstream;
|
|
7112
|
+
try {
|
|
7113
|
+
resolvedUpstream = await this.resolve(upstream, imported.sourcePath, chain);
|
|
7114
|
+
} finally {
|
|
7115
|
+
this.schemaConfig = savedSchemaConfig;
|
|
7116
|
+
}
|
|
7117
|
+
if (!resolvedUpstream.success) continue;
|
|
7118
|
+
const traitSubs = materializedTraitSubs(upstream.id, resolvedUpstream.data.traits, ref, orbital.name);
|
|
7119
|
+
out.set(siblingImportKey(parsed.alias, parsed.orbitalName), { localName: orbital.name, traitSubs });
|
|
7120
|
+
}
|
|
7121
|
+
return out;
|
|
7122
|
+
}
|
|
7123
|
+
/**
|
|
7124
|
+
* Resolve one reference-form orbital, recursing into the upstream first
|
|
7125
|
+
* when IT is also reference-form ("already fully inlined because inline
|
|
7126
|
+
* recursed into every loaded orbital" — docs/Almadar_Orbital_Import.md §9
|
|
7127
|
+
* step 3 — the JS resolver needs its own cycle guard since it has no
|
|
7128
|
+
* file-level inline-order pass to lean on).
|
|
7129
|
+
*/
|
|
7130
|
+
async resolveOrbitalRefChain(orbital, sourcePath, chain, visiting, consumerEntityIds, consumerRoster, listenSourceTargets) {
|
|
7131
|
+
const ref = orbital.reference;
|
|
7132
|
+
if (!ref) return { success: true, data: orbital, warnings: [] };
|
|
7133
|
+
const parsed = parseOrbitalRef(ref.ref);
|
|
7134
|
+
if (!parsed) {
|
|
7135
|
+
return {
|
|
7136
|
+
success: false,
|
|
7137
|
+
errors: [`Invalid orbital reference format: ${ref.ref}. Expected "Alias.orbitals.OrbitalName"`]
|
|
7138
|
+
};
|
|
7139
|
+
}
|
|
7140
|
+
const importsResult = await this.resolveImports(orbital.uses ?? [], sourcePath, chain);
|
|
7141
|
+
if (!importsResult.success) return { success: false, errors: importsResult.errors };
|
|
7142
|
+
const imported = importsResult.data.orbitals.get(parsed.alias);
|
|
7143
|
+
if (!imported) {
|
|
7144
|
+
return {
|
|
7145
|
+
success: false,
|
|
7146
|
+
errors: [
|
|
7147
|
+
`Unknown import alias in orbital reference: ${parsed.alias}. Available aliases: ${Array.from(importsResult.data.orbitals.keys()).join(", ") || "none"}`
|
|
7148
|
+
]
|
|
7149
|
+
};
|
|
7150
|
+
}
|
|
7151
|
+
const candidates = importedOrbitals(imported);
|
|
7152
|
+
let upstream = candidates.find((o) => o.name === parsed.orbitalName);
|
|
7153
|
+
if (!upstream) {
|
|
7154
|
+
return {
|
|
7155
|
+
success: false,
|
|
7156
|
+
errors: [
|
|
7157
|
+
`Orbital "${parsed.orbitalName}" not found in imported behavior "${parsed.alias}". Available orbitals: ${candidates.map((o) => o.name).join(", ") || "none"}`
|
|
7158
|
+
]
|
|
7159
|
+
};
|
|
7160
|
+
}
|
|
7161
|
+
const cycleKey = `${imported.sourcePath}::${parsed.orbitalName}`;
|
|
7162
|
+
if (visiting.has(cycleKey)) {
|
|
7163
|
+
return {
|
|
7164
|
+
success: false,
|
|
7165
|
+
errors: [
|
|
7166
|
+
`Circular orbital reference: "${orbital.name}" imports "${parsed.alias}.orbitals.${parsed.orbitalName}" while that orbital is itself being resolved`
|
|
7167
|
+
]
|
|
7168
|
+
};
|
|
7169
|
+
}
|
|
7170
|
+
visiting.add(cycleKey);
|
|
7171
|
+
if (upstream.reference) {
|
|
7172
|
+
const nestedListenSourceTargets = await this.precomputeReferenceFormListenTargets(candidates, chain);
|
|
7173
|
+
const nested = await this.resolveOrbitalRefChain(
|
|
7174
|
+
upstream,
|
|
7175
|
+
imported.sourcePath,
|
|
7176
|
+
chain,
|
|
7177
|
+
visiting,
|
|
7178
|
+
consumerEntityIds,
|
|
7179
|
+
consumerRoster,
|
|
7180
|
+
nestedListenSourceTargets
|
|
7181
|
+
);
|
|
7182
|
+
if (!nested.success) {
|
|
7183
|
+
visiting.delete(cycleKey);
|
|
7184
|
+
return nested;
|
|
7185
|
+
}
|
|
7186
|
+
upstream = nested.data;
|
|
7187
|
+
}
|
|
7188
|
+
visiting.delete(cycleKey);
|
|
7189
|
+
const materialized = await this.materializeOrbitalRef(
|
|
7190
|
+
upstream,
|
|
7191
|
+
ref,
|
|
7192
|
+
orbital.name,
|
|
7193
|
+
orbital.id,
|
|
7194
|
+
imported.sourcePath,
|
|
7195
|
+
chain,
|
|
7196
|
+
candidates,
|
|
7197
|
+
consumerEntityIds,
|
|
7198
|
+
consumerRoster,
|
|
7199
|
+
imported.schemaConfig,
|
|
7200
|
+
parsed.alias,
|
|
7201
|
+
listenSourceTargets
|
|
7202
|
+
);
|
|
7203
|
+
if (!materialized.success) return materialized;
|
|
7204
|
+
const siblingTraits = orbital.traits ?? [];
|
|
7205
|
+
return {
|
|
7206
|
+
success: true,
|
|
7207
|
+
data: {
|
|
7208
|
+
...materialized.data,
|
|
7209
|
+
...siblingTraits.length > 0 ? { traits: [...materialized.data.traits, ...siblingTraits] } : {},
|
|
7210
|
+
uses: orbital.uses
|
|
7211
|
+
},
|
|
7212
|
+
warnings: materialized.warnings
|
|
7213
|
+
};
|
|
7214
|
+
}
|
|
7215
|
+
/**
|
|
7216
|
+
* Materialize a reference-form orbital: flatten the (already-inlined)
|
|
7217
|
+
* upstream orbital's whole trait/entity/page closure into the consumer,
|
|
7218
|
+
* unconditionally prefixed by `localName` (docs/Almadar_Orbital_Import.md
|
|
7219
|
+
* §4.3). JS twin of the (not-yet-landed) compiler's
|
|
7220
|
+
* `resolve_orbital_reference`.
|
|
7221
|
+
*/
|
|
7222
|
+
async materializeOrbitalRef(upstream, ref, localName, localId, sourcePath, chain, aliasOrbitals, consumerEntityIds, consumerRoster, importedSchemaConfig, alias, listenSourceTargets) {
|
|
7223
|
+
const savedSchemaConfig = this.schemaConfig;
|
|
7224
|
+
this.schemaConfig = importedSchemaConfig;
|
|
7225
|
+
let resolvedUpstream;
|
|
7226
|
+
try {
|
|
7227
|
+
resolvedUpstream = await this.resolve(upstream, sourcePath, chain);
|
|
7228
|
+
} finally {
|
|
7229
|
+
this.schemaConfig = savedSchemaConfig;
|
|
7230
|
+
}
|
|
7231
|
+
if (!resolvedUpstream.success) {
|
|
7232
|
+
return {
|
|
7233
|
+
success: false,
|
|
7234
|
+
errors: resolvedUpstream.errors.map(
|
|
7235
|
+
(e) => `Orbital reference "${localName}" (${ref.ref}): ${e}`
|
|
7236
|
+
)
|
|
7237
|
+
};
|
|
7238
|
+
}
|
|
7239
|
+
const {
|
|
7240
|
+
entity: upstreamEntity,
|
|
7241
|
+
traits: upstreamTraits,
|
|
7242
|
+
pages: upstreamPages,
|
|
7243
|
+
// (C) the RESOLVED aux-entity set — includes whatever sibling-pull
|
|
7244
|
+
// surfaced (`pullSiblingTraits`'s aux-entity carry), never just
|
|
7245
|
+
// `upstream.auxiliaryEntities` (the pre-resolve INPUT, which misses
|
|
7246
|
+
// every un-rebound composed atom's own entity).
|
|
7247
|
+
auxiliaryEntities: upstreamAuxiliaryEntities
|
|
7248
|
+
} = resolvedUpstream.data;
|
|
7249
|
+
const onlySet = ref.only ? new Set(ref.only) : void 0;
|
|
7250
|
+
const omitSet = new Set(ref.omit ?? []);
|
|
7251
|
+
const keptTraits = upstreamTraits.filter(
|
|
7252
|
+
(rt) => onlySet ? onlySet.has(rt.trait.name) : !omitSet.has(rt.trait.name)
|
|
7253
|
+
);
|
|
7254
|
+
const keptNames = new Set(keptTraits.map((rt) => rt.trait.name));
|
|
7255
|
+
const removedNames = new Set(
|
|
7256
|
+
upstreamTraits.map((rt) => rt.trait.name).filter((n) => !keptNames.has(n))
|
|
7257
|
+
);
|
|
7258
|
+
const errors = [];
|
|
7259
|
+
for (const rt of keptTraits) {
|
|
7260
|
+
for (const embed of traitEmbedNamesOf(rt.trait)) {
|
|
7261
|
+
if (removedNames.has(embed)) {
|
|
7262
|
+
errors.push(
|
|
7263
|
+
`Orbital "${localName}" omits trait "${embed}" but surviving trait "${rt.trait.name}" still embeds it via @trait.${embed} (ORB_O_OMIT_EMBEDDED_TRAIT)`
|
|
7264
|
+
);
|
|
7265
|
+
}
|
|
7266
|
+
}
|
|
7267
|
+
}
|
|
7268
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7269
|
+
let auxEntities = upstreamAuxiliaryEntities ?? [];
|
|
7270
|
+
const subs = /* @__PURE__ */ new Map();
|
|
7271
|
+
for (const rt of keptTraits) subs.set(rt.trait.name, `${localName}${rt.trait.name}`);
|
|
7272
|
+
const keptFinalNames = new Set(subs.values());
|
|
7273
|
+
const { name: primaryFinalName, id: primaryId } = materializedPrimaryEntity(
|
|
7274
|
+
upstreamEntity,
|
|
7275
|
+
upstream.id,
|
|
7276
|
+
ref,
|
|
7277
|
+
localName
|
|
7278
|
+
);
|
|
7279
|
+
subs.set(upstreamEntity.name, primaryFinalName);
|
|
7280
|
+
for (const e of auxEntities) subs.set(e.name, `${localName}${e.name}`);
|
|
7281
|
+
const fieldSubs = new Map(Object.entries(ref.fields ?? {}));
|
|
7282
|
+
const closure = /* @__PURE__ */ new Set([upstreamEntity.name, ...auxEntities.map((e) => e.name)]);
|
|
7283
|
+
const upstreamUniverse = /* @__PURE__ */ new Set();
|
|
7284
|
+
const upstreamUniverseEntities = /* @__PURE__ */ new Map();
|
|
7285
|
+
const primaryEntityNames = /* @__PURE__ */ new Set();
|
|
7286
|
+
for (const o of aliasOrbitals) {
|
|
7287
|
+
if (o.name === upstream.name) continue;
|
|
7288
|
+
if (isInlineEntity(o.entity)) primaryEntityNames.add(o.entity.name);
|
|
7289
|
+
for (const entity of inlineEntityRefsOf(o)) {
|
|
7290
|
+
if (!closure.has(entity.name)) {
|
|
7291
|
+
upstreamUniverse.add(entity.name);
|
|
7292
|
+
upstreamUniverseEntities.set(entity.name, entity);
|
|
7293
|
+
}
|
|
7294
|
+
}
|
|
7295
|
+
}
|
|
7296
|
+
const entityIds = /* @__PURE__ */ new Map();
|
|
7297
|
+
if (ref.entities) {
|
|
7298
|
+
for (const [upstreamKey, consumerName] of Object.entries(ref.entities)) {
|
|
7299
|
+
if (!upstreamUniverse.has(upstreamKey)) {
|
|
7300
|
+
errors.push(
|
|
7301
|
+
`Orbital "${localName}" declares entities { ${upstreamKey}: ${consumerName} } but "${upstreamKey}" is not an out-of-orbital entity of upstream alias "${upstream.name}" (ORB_O_ENTITY_UNKNOWN_KEY)`
|
|
7302
|
+
);
|
|
7303
|
+
continue;
|
|
7304
|
+
}
|
|
7305
|
+
const consumerId = consumerEntityIds.get(consumerName);
|
|
7306
|
+
if (consumerId === void 0) {
|
|
7307
|
+
errors.push(
|
|
7308
|
+
`Orbital "${localName}" entities { ${upstreamKey}: ${consumerName} } targets "${consumerName}", which the consumer schema does not declare (ORB_O_ENTITY_TARGET_UNKNOWN)`
|
|
7309
|
+
);
|
|
7310
|
+
continue;
|
|
7311
|
+
}
|
|
7312
|
+
subs.set(upstreamKey, consumerName);
|
|
7313
|
+
entityIds.set(consumerName, consumerId);
|
|
7314
|
+
}
|
|
7315
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7316
|
+
}
|
|
7317
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
7318
|
+
for (const rt of keptTraits) {
|
|
7319
|
+
if (rt.trait.linkedEntity && upstreamUniverse.has(rt.trait.linkedEntity)) {
|
|
7320
|
+
referenced.add(rt.trait.linkedEntity);
|
|
7321
|
+
}
|
|
7322
|
+
for (const name of collectEntityNamesInTrait(rt.trait, upstreamUniverse)) referenced.add(name);
|
|
7323
|
+
if (rt.trait.sourceEntityDefinition) {
|
|
7324
|
+
for (const name of relationTargetsOfEntity(rt.trait.sourceEntityDefinition, upstreamUniverse)) {
|
|
7325
|
+
referenced.add(name);
|
|
7326
|
+
}
|
|
7327
|
+
}
|
|
7328
|
+
}
|
|
7329
|
+
for (const name of relationTargetsOfEntity(upstreamEntity, upstreamUniverse)) referenced.add(name);
|
|
7330
|
+
for (const aux of auxEntities) {
|
|
7331
|
+
for (const name of relationTargetsOfEntity(aux, upstreamUniverse)) referenced.add(name);
|
|
7332
|
+
}
|
|
7333
|
+
for (const rp of upstreamPages) {
|
|
7334
|
+
if (rp.page.primaryEntity && upstreamUniverse.has(rp.page.primaryEntity)) {
|
|
7335
|
+
referenced.add(rp.page.primaryEntity);
|
|
7336
|
+
}
|
|
7337
|
+
for (const tr of rp.page.traits ?? []) {
|
|
7338
|
+
if (tr.linkedEntity && upstreamUniverse.has(tr.linkedEntity)) referenced.add(tr.linkedEntity);
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
for (const name of referenced) {
|
|
7342
|
+
if (subs.has(name)) continue;
|
|
7343
|
+
const definition = upstreamUniverseEntities.get(name);
|
|
7344
|
+
const auxOnly = definition !== void 0 && !primaryEntityNames.has(name);
|
|
7345
|
+
if (definition && auxOnly && !definition.identity) {
|
|
7346
|
+
auxEntities = [...auxEntities, definition];
|
|
7347
|
+
subs.set(name, `${localName}${name}`);
|
|
7348
|
+
continue;
|
|
7349
|
+
}
|
|
7350
|
+
errors.push(
|
|
7351
|
+
`Orbital "${localName}" references out-of-orbital entity "${name}" with no "${name}: <consumer entity>" mapping in entities {} (ORB_O_ENTITY_UNMAPPED)`
|
|
7352
|
+
);
|
|
7353
|
+
}
|
|
7354
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7355
|
+
const roleFields = /* @__PURE__ */ new Map();
|
|
7356
|
+
for (const entity of identityEntitiesOf(aliasOrbitals)) {
|
|
7357
|
+
for (const field of entity.fields) {
|
|
7358
|
+
if (!field.name) continue;
|
|
7359
|
+
const vocab = roleVocabularyOf(entity, field.name);
|
|
7360
|
+
if (vocab) roleFields.set(field.name, vocab);
|
|
7361
|
+
}
|
|
7362
|
+
}
|
|
7363
|
+
const consumerRoleFields = /* @__PURE__ */ new Map();
|
|
7364
|
+
for (const entity of consumerRoster) {
|
|
7365
|
+
for (const field of entity.fields) {
|
|
7366
|
+
if (!field.name) continue;
|
|
7367
|
+
const vocab = roleVocabularyOf(entity, field.name);
|
|
7368
|
+
if (!vocab) continue;
|
|
7369
|
+
let values = consumerRoleFields.get(field.name);
|
|
7370
|
+
if (!values) {
|
|
7371
|
+
values = /* @__PURE__ */ new Set();
|
|
7372
|
+
consumerRoleFields.set(field.name, values);
|
|
7373
|
+
}
|
|
7374
|
+
for (const value of vocab) values.add(value);
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
for (const [literal, targets] of Object.entries(ref.roles ?? {})) {
|
|
7378
|
+
const matchingFields = [...roleFields.entries()].filter(([, vocab]) => vocab.includes(literal)).map(([field]) => field).sort();
|
|
7379
|
+
if (matchingFields.length === 0) {
|
|
7380
|
+
errors.push(
|
|
7381
|
+
`Orbital "${localName}" declares roles { ${literal}: ... } but upstream alias "${upstream.name}"'s roster declares no role field with literal "${literal}" in its vocabulary (ORB_O_ROLE_UNKNOWN_UPSTREAM)`
|
|
7382
|
+
);
|
|
7383
|
+
continue;
|
|
7384
|
+
}
|
|
7385
|
+
for (const field of matchingFields) {
|
|
7386
|
+
const allowed = consumerRoleFields.get(field);
|
|
7387
|
+
for (const target of targets) {
|
|
7388
|
+
if (allowed?.has(target)) continue;
|
|
7389
|
+
errors.push(
|
|
7390
|
+
`Orbital "${localName}" roles { ${literal}: ${target} } targets "${target}", which is not a member of consumer field "${field}" on the roster (values: ${allowed ? [...allowed].sort().join(", ") : "(none)"}) (ORB_O_ROLE_TARGET_NOT_MEMBER)`
|
|
7391
|
+
);
|
|
7392
|
+
}
|
|
7393
|
+
}
|
|
7394
|
+
}
|
|
7395
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7396
|
+
const declaredConfig = upstream.config;
|
|
7397
|
+
if (ref.config) {
|
|
7398
|
+
for (const key of Object.keys(ref.config)) {
|
|
7399
|
+
if (!declaredConfig || !(key in declaredConfig)) {
|
|
7400
|
+
errors.push(
|
|
7401
|
+
`Orbital "${localName}" overrides config "${key}" but upstream orbital "${upstream.name}" does not declare that knob (ORB_O_CONFIG_UNKNOWN_KEY)`
|
|
7402
|
+
);
|
|
7403
|
+
}
|
|
7404
|
+
}
|
|
7405
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7406
|
+
}
|
|
7407
|
+
const configOverrideValues = {};
|
|
7408
|
+
for (const [key, field] of Object.entries(ref.config ?? {})) {
|
|
7409
|
+
if (field.default !== void 0) configOverrideValues[key] = field.default;
|
|
7410
|
+
}
|
|
7411
|
+
const foldedConfig = declaredConfig ? overrideDeclaredKnobs(declaredConfig, configOverrideValues) : void 0;
|
|
7412
|
+
const idByName = /* @__PURE__ */ new Map();
|
|
7413
|
+
const materializedTraits = keptTraits.map((rt) => {
|
|
7414
|
+
const finalName = subs.get(rt.trait.name);
|
|
7415
|
+
const finalId = asTraitId(deriveMaterializedId(rt.trait.id, upstream.id, rt.trait.name, localName, "trait"));
|
|
7416
|
+
idByName.set(finalName, finalId);
|
|
7417
|
+
return { ...rt.trait, name: finalName, id: finalId };
|
|
7418
|
+
});
|
|
7419
|
+
const embeddersOf = /* @__PURE__ */ new Map();
|
|
7420
|
+
for (const t of materializedTraits) {
|
|
7421
|
+
for (const embed of traitEmbedNamesOf(t)) {
|
|
7422
|
+
const embedFinal = subs.get(embed);
|
|
7423
|
+
if (!embedFinal) continue;
|
|
7424
|
+
let embedders = embeddersOf.get(embedFinal);
|
|
7425
|
+
if (!embedders) {
|
|
7426
|
+
embedders = [];
|
|
7427
|
+
embeddersOf.set(embedFinal, embedders);
|
|
7428
|
+
}
|
|
7429
|
+
embedders.push(t.name);
|
|
7430
|
+
}
|
|
7431
|
+
}
|
|
7432
|
+
const parentConfigs = new Map(
|
|
7433
|
+
materializedTraits.map((t) => [t.name, t.config])
|
|
7434
|
+
);
|
|
7435
|
+
const transitiveEmbedderChain = (name) => {
|
|
7436
|
+
const chain2 = [];
|
|
7437
|
+
const seenNames = /* @__PURE__ */ new Set([name]);
|
|
7438
|
+
let cur = embeddersOf.get(name)?.[0];
|
|
7439
|
+
while (cur !== void 0 && !seenNames.has(cur)) {
|
|
7440
|
+
seenNames.add(cur);
|
|
7441
|
+
const cfg = parentConfigs.get(cur);
|
|
7442
|
+
if (cfg) chain2.push(cfg);
|
|
7443
|
+
cur = embeddersOf.get(cur)?.[0];
|
|
7444
|
+
}
|
|
7445
|
+
return chain2;
|
|
7446
|
+
};
|
|
7447
|
+
entityIds.set(primaryFinalName, primaryId);
|
|
7448
|
+
for (const e of auxEntities) {
|
|
7449
|
+
entityIds.set(
|
|
7450
|
+
subs.get(e.name),
|
|
7451
|
+
asEntityId(deriveMaterializedId(e.id, upstream.id, e.name, localName, "entity"))
|
|
7452
|
+
);
|
|
7453
|
+
}
|
|
7454
|
+
const upstreamPathSet = new Set(upstreamPages.map((rp) => rp.page.path));
|
|
7455
|
+
for (const path of [...Object.keys(ref.pages ?? {}), ...Object.keys(ref.mounts ?? {})]) {
|
|
7456
|
+
if (!upstreamPathSet.has(path)) {
|
|
7457
|
+
errors.push(
|
|
7458
|
+
`Orbital "${localName}" names page path "${path}" but upstream orbital "${upstream.name}" has no page at that path (ORB_O_PAGE_UNKNOWN_PATH)`
|
|
7459
|
+
);
|
|
7460
|
+
}
|
|
7461
|
+
}
|
|
7462
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7463
|
+
const pathMap = new Map(
|
|
7464
|
+
upstreamPages.map((rp) => [rp.page.path, ref.pages?.[rp.page.path] ?? rp.page.path])
|
|
7465
|
+
);
|
|
7466
|
+
const orbitalRename = upstream.name !== localName ? { from: upstream.name, to: localName } : void 0;
|
|
7467
|
+
const finalTraits = materializedTraits.map((trait) => {
|
|
7468
|
+
let next = renameTraitEmbeds(trait, subs);
|
|
7469
|
+
next = renameEntitiesInTrait(next, subs, entityIds);
|
|
7470
|
+
if (next.linkedEntity !== void 0) {
|
|
7471
|
+
const linkedEntityId = entityIds.get(next.linkedEntity);
|
|
7472
|
+
if (linkedEntityId !== void 0) next = { ...next, linkedEntityId };
|
|
7473
|
+
}
|
|
7474
|
+
next = rewriteEntityRefIds(next, subs, entityIds);
|
|
7475
|
+
next = renameSourceEntityDefinition(next, subs, entityIds);
|
|
7476
|
+
next = rewriteRoleLiteralsInTrait(next, roleFields, ref.roles ?? {});
|
|
7477
|
+
if (fieldSubs.size > 0) next = rewriteEntityFieldsInTrait(next, fieldSubs);
|
|
7478
|
+
next = rewriteListenSources(next, subs, idByName, orbitalRename, alias, listenSourceTargets);
|
|
7479
|
+
if (pathMap.size > 0) {
|
|
7480
|
+
next = rewriteTraitNavigateTargets(next, pathMap);
|
|
7481
|
+
}
|
|
7482
|
+
for (const embedderName of embeddersOf.get(trait.name) ?? []) {
|
|
7483
|
+
const embedderConfig = parentConfigs.get(embedderName);
|
|
7484
|
+
next = resolveForwardedSiblingConfigFrom(next, embedderConfig ? [embedderConfig] : []);
|
|
7485
|
+
}
|
|
7486
|
+
next = resolveForwardedSiblingConfigFrom(next, transitiveEmbedderChain(trait.name));
|
|
7487
|
+
next = resolveForwardedSiblingConfigFrom(next, [], foldedConfig, importedSchemaConfig);
|
|
7488
|
+
if (fieldSubs.size > 0 && next.config) {
|
|
7489
|
+
next = { ...next, config: rewriteEntityFieldsInConfig(next.config, fieldSubs) };
|
|
7490
|
+
}
|
|
7491
|
+
if (pathMap.size > 0) {
|
|
7492
|
+
next = rewriteTraitConfigPagePaths(next, pathMap);
|
|
7493
|
+
}
|
|
7494
|
+
next = applyEventRenames(next, ref.events, keptFinalNames);
|
|
7495
|
+
return next;
|
|
7496
|
+
});
|
|
7497
|
+
const renamedPrimaryEntity = rewriteRoleLiteralsInEntity(
|
|
7498
|
+
renameEntityRelationTargets(
|
|
7499
|
+
rewriteEntityFieldsInEntity(
|
|
7500
|
+
{
|
|
7501
|
+
...upstreamEntity,
|
|
7502
|
+
name: primaryFinalName,
|
|
7503
|
+
id: primaryId
|
|
7504
|
+
},
|
|
7505
|
+
fieldSubs
|
|
7506
|
+
),
|
|
7507
|
+
subs,
|
|
7508
|
+
entityIds
|
|
7509
|
+
),
|
|
7510
|
+
roleFields,
|
|
7511
|
+
ref.roles ?? {}
|
|
7512
|
+
);
|
|
7513
|
+
const extendResult = applyExtendFields(
|
|
7514
|
+
renamedPrimaryEntity,
|
|
7515
|
+
ref.extend,
|
|
7516
|
+
fieldSubs,
|
|
7517
|
+
consumerEntityIds,
|
|
7518
|
+
localName
|
|
7519
|
+
);
|
|
7520
|
+
if (extendResult.errors.length > 0) return { success: false, errors: extendResult.errors };
|
|
7521
|
+
const primaryEntity = extendResult.entity;
|
|
7522
|
+
const finalAuxEntities = auxEntities.map((e) => {
|
|
7523
|
+
const finalName = subs.get(e.name);
|
|
7524
|
+
return rewriteRoleLiteralsInEntity(
|
|
7525
|
+
renameEntityRelationTargets(
|
|
7526
|
+
rewriteEntityFieldsInEntity(
|
|
7527
|
+
{
|
|
7528
|
+
...e,
|
|
7529
|
+
name: finalName,
|
|
7530
|
+
id: entityIds.get(finalName)
|
|
7531
|
+
},
|
|
7532
|
+
fieldSubs
|
|
7533
|
+
),
|
|
7534
|
+
subs,
|
|
7535
|
+
entityIds
|
|
7536
|
+
),
|
|
7537
|
+
roleFields,
|
|
7538
|
+
ref.roles ?? {}
|
|
7539
|
+
);
|
|
7540
|
+
});
|
|
7541
|
+
const finalPages = upstreamPages.map((rp) => {
|
|
7542
|
+
const original = rp.page;
|
|
7543
|
+
const mountNames = ref.mounts?.[original.path] ?? [];
|
|
7544
|
+
const finalPageTraits = [
|
|
7545
|
+
...(original.traits ?? []).filter((tr) => !removedNames.has(tr.ref)).map((tr) => {
|
|
7546
|
+
const finalRef = subs.get(tr.ref) ?? tr.ref;
|
|
7547
|
+
const refId = idByName.get(finalRef);
|
|
7548
|
+
return {
|
|
7549
|
+
...tr,
|
|
7550
|
+
ref: finalRef,
|
|
7551
|
+
...refId !== void 0 ? { refId } : {},
|
|
7552
|
+
...tr.linkedEntity !== void 0 ? { linkedEntity: subs.get(tr.linkedEntity) ?? tr.linkedEntity } : {}
|
|
7553
|
+
};
|
|
7554
|
+
}),
|
|
7555
|
+
...mountNames.map((name) => ({ ref: name }))
|
|
7556
|
+
];
|
|
7557
|
+
return {
|
|
7558
|
+
...original,
|
|
7559
|
+
// Gap (E) — unconditionally prefixed, same as traits/entities (§4.3):
|
|
7560
|
+
// two imports of the same upstream orbital with distinct `pages {}`
|
|
7561
|
+
// path maps must not collide on page NAME (`Duplicate page name`).
|
|
7562
|
+
// `id` is the page-scope sibling of `deriveMaterializedId` (never
|
|
7563
|
+
// `mintId`) — fresh and pairwise-disjoint across imports, same as
|
|
7564
|
+
// trait/entity ids above.
|
|
7565
|
+
name: `${localName}${original.name}`,
|
|
7566
|
+
id: asPageId(deriveMaterializedId(original.id, upstream.id, original.name, localName, "page")),
|
|
7567
|
+
path: pathMap.get(original.path) ?? original.path,
|
|
7568
|
+
...original.primaryEntity !== void 0 ? { primaryEntity: subs.get(original.primaryEntity) ?? original.primaryEntity } : {},
|
|
7569
|
+
traits: finalPageTraits
|
|
7570
|
+
};
|
|
7571
|
+
});
|
|
7572
|
+
const forwardedKnobs = /* @__PURE__ */ new Set();
|
|
7573
|
+
for (const rt of keptTraits) {
|
|
7574
|
+
for (const field of Object.values(rt.trait.config ?? {})) {
|
|
7575
|
+
if (typeof field.default === "string" && field.default.startsWith("@config.")) {
|
|
7576
|
+
const knob = field.default.slice("@config.".length);
|
|
7577
|
+
if (knob.length > 0 && !knob.includes(".")) forwardedKnobs.add(knob);
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
}
|
|
7581
|
+
const prunedConfig = foldedConfig ? Object.fromEntries(Object.entries(foldedConfig).filter(([key]) => forwardedKnobs.has(key))) : void 0;
|
|
7582
|
+
const orbitalId = localId ?? (upstream.id ? asOrbitalId(deriveId(upstream.id, localName)) : void 0);
|
|
7583
|
+
refResolverLog.info("orbital-import:materialize", {
|
|
7584
|
+
local: localName,
|
|
7585
|
+
upstream: upstream.name,
|
|
7586
|
+
traits: finalTraits.length,
|
|
7587
|
+
pages: finalPages.length
|
|
7588
|
+
});
|
|
7589
|
+
return {
|
|
7590
|
+
success: true,
|
|
7591
|
+
data: {
|
|
7592
|
+
...upstream,
|
|
7593
|
+
name: localName,
|
|
7594
|
+
...orbitalId ? { id: orbitalId } : {},
|
|
7595
|
+
entity: primaryEntity,
|
|
7596
|
+
...finalAuxEntities.length > 0 ? { auxiliaryEntities: finalAuxEntities } : {},
|
|
7597
|
+
traits: finalTraits,
|
|
7598
|
+
pages: finalPages,
|
|
7599
|
+
emits: void 0,
|
|
7600
|
+
listens: void 0,
|
|
7601
|
+
exposes: void 0,
|
|
7602
|
+
...prunedConfig ? { config: prunedConfig } : { config: void 0 },
|
|
7603
|
+
uses: void 0,
|
|
7604
|
+
reference: void 0
|
|
7605
|
+
},
|
|
7606
|
+
warnings: []
|
|
7607
|
+
};
|
|
7608
|
+
}
|
|
4956
7609
|
/**
|
|
4957
7610
|
* Add local traits for resolution.
|
|
4958
7611
|
*/
|
|
@@ -4971,29 +7624,148 @@ var ReferenceResolver = class {
|
|
|
4971
7624
|
this.loader?.clearCache();
|
|
4972
7625
|
}
|
|
4973
7626
|
};
|
|
7627
|
+
function isInlineTraitWithStateMachine(tr) {
|
|
7628
|
+
return isInlineTrait(tr);
|
|
7629
|
+
}
|
|
7630
|
+
function reconcileOrbitalRefEventIdRenames(schema, flattened) {
|
|
7631
|
+
if (!schema.ledger) return;
|
|
7632
|
+
const renamedRefs = schema.orbitals.filter((o) => o.reference?.events && Object.keys(o.reference.events).length > 0).map((o) => ({ localName: o.name, eventSubs: o.reference.events }));
|
|
7633
|
+
if (renamedRefs.length === 0) return;
|
|
7634
|
+
const sites = [];
|
|
7635
|
+
for (const { localName, eventSubs } of renamedRefs) {
|
|
7636
|
+
const newKeys = new Set(Object.values(eventSubs));
|
|
7637
|
+
const orbital = flattened.find((o) => o.name === localName);
|
|
7638
|
+
if (!orbital) continue;
|
|
7639
|
+
for (const tr of orbital.traits) {
|
|
7640
|
+
if (!isInlineTraitWithStateMachine(tr)) continue;
|
|
7641
|
+
for (const ev of tr.stateMachine?.events ?? []) {
|
|
7642
|
+
if (!ev.id || !newKeys.has(ev.key)) continue;
|
|
7643
|
+
const entry = schema.ledger.entries[ev.id];
|
|
7644
|
+
if (!entry || entry.curName === ev.key) continue;
|
|
7645
|
+
sites.push({ orbitalName: orbital.name, traitName: tr.name, oldId: ev.id, newKey: ev.key });
|
|
7646
|
+
}
|
|
7647
|
+
}
|
|
7648
|
+
}
|
|
7649
|
+
if (sites.length === 0) return;
|
|
7650
|
+
const candidateIds = new Set(sites.map((s) => s.oldId));
|
|
7651
|
+
const owners = /* @__PURE__ */ new Map();
|
|
7652
|
+
for (const orbital of flattened) {
|
|
7653
|
+
for (const tr of orbital.traits) {
|
|
7654
|
+
if (!isInlineTraitWithStateMachine(tr)) continue;
|
|
7655
|
+
for (const ev of tr.stateMachine?.events ?? []) {
|
|
7656
|
+
if (ev.id && candidateIds.has(ev.id)) {
|
|
7657
|
+
const ownerKey = `${orbital.name}\0${tr.name}`;
|
|
7658
|
+
const set = owners.get(ev.id) ?? /* @__PURE__ */ new Set();
|
|
7659
|
+
set.add(ownerKey);
|
|
7660
|
+
owners.set(ev.id, set);
|
|
7661
|
+
}
|
|
7662
|
+
}
|
|
7663
|
+
}
|
|
7664
|
+
}
|
|
7665
|
+
const renameInPlace = /* @__PURE__ */ new Map();
|
|
7666
|
+
const deriveSites = [];
|
|
7667
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7668
|
+
for (const site of sites) {
|
|
7669
|
+
const ownerCount = owners.get(site.oldId)?.size ?? 1;
|
|
7670
|
+
if (ownerCount <= 1) {
|
|
7671
|
+
renameInPlace.set(site.oldId, site.newKey);
|
|
7672
|
+
} else if (!seen.has(site.oldId)) {
|
|
7673
|
+
seen.add(site.oldId);
|
|
7674
|
+
deriveSites.push({ site, newId: asEventId(deriveId(site.oldId, site.newKey)) });
|
|
7675
|
+
}
|
|
7676
|
+
}
|
|
7677
|
+
for (const { site, newId } of deriveSites) {
|
|
7678
|
+
const orbital = flattened.find((o) => o.name === site.orbitalName);
|
|
7679
|
+
if (!orbital) continue;
|
|
7680
|
+
orbital.traits = orbital.traits.map((tr) => {
|
|
7681
|
+
if (!isInlineTraitWithStateMachine(tr) || tr.name !== site.traitName) return tr;
|
|
7682
|
+
let next = tr;
|
|
7683
|
+
if (next.stateMachine?.events) {
|
|
7684
|
+
next = {
|
|
7685
|
+
...next,
|
|
7686
|
+
stateMachine: {
|
|
7687
|
+
...next.stateMachine,
|
|
7688
|
+
events: next.stateMachine.events.map((ev) => ev.id === site.oldId ? { ...ev, id: newId } : ev),
|
|
7689
|
+
transitions: (next.stateMachine.transitions ?? []).map(
|
|
7690
|
+
(t) => t.eventId === site.oldId ? { ...t, eventId: newId } : t
|
|
7691
|
+
)
|
|
7692
|
+
}
|
|
7693
|
+
};
|
|
7694
|
+
}
|
|
7695
|
+
if (next.emits) {
|
|
7696
|
+
next = {
|
|
7697
|
+
...next,
|
|
7698
|
+
emits: next.emits.map(
|
|
7699
|
+
(e) => typeof e !== "string" && e.eventId === site.oldId ? { ...e, eventId: newId } : e
|
|
7700
|
+
)
|
|
7701
|
+
};
|
|
7702
|
+
}
|
|
7703
|
+
if (next.listens) {
|
|
7704
|
+
next = {
|
|
7705
|
+
...next,
|
|
7706
|
+
listens: next.listens.map((l) => {
|
|
7707
|
+
const eventId = l.eventId === site.oldId ? newId : l.eventId;
|
|
7708
|
+
const triggersId = l.triggersId === site.oldId ? newId : l.triggersId;
|
|
7709
|
+
return eventId === l.eventId && triggersId === l.triggersId ? l : { ...l, eventId, triggersId };
|
|
7710
|
+
})
|
|
7711
|
+
};
|
|
7712
|
+
}
|
|
7713
|
+
return next;
|
|
7714
|
+
});
|
|
7715
|
+
}
|
|
7716
|
+
const at = (/* @__PURE__ */ new Date()).toISOString();
|
|
7717
|
+
let ledger = schema.ledger;
|
|
7718
|
+
for (const [oldId, newKey] of renameInPlace) {
|
|
7719
|
+
ledger = ledgerRename(ledger, oldId, newKey, at);
|
|
7720
|
+
}
|
|
7721
|
+
for (const { site, newId } of deriveSites) {
|
|
7722
|
+
const src = ledger.entries[site.oldId];
|
|
7723
|
+
if (!src) continue;
|
|
7724
|
+
const ownerTrait = flattened.find((o) => o.name === site.orbitalName)?.traits.find((tr) => isInlineTraitWithStateMachine(tr) && tr.name === site.traitName);
|
|
7725
|
+
const newEntry = {
|
|
7726
|
+
id: newId,
|
|
7727
|
+
kind: src.kind,
|
|
7728
|
+
bakedName: src.bakedName,
|
|
7729
|
+
curName: site.newKey,
|
|
7730
|
+
renames: [...src.renames, { from: src.curName, to: site.newKey, at }],
|
|
7731
|
+
owner: src.owner,
|
|
7732
|
+
...ownerTrait?.id !== void 0 ? { parent: ownerTrait.id } : {}
|
|
7733
|
+
};
|
|
7734
|
+
ledger = { ...ledger, entries: { ...ledger.entries, [newId]: newEntry } };
|
|
7735
|
+
}
|
|
7736
|
+
schema.ledger = ledger;
|
|
7737
|
+
}
|
|
4974
7738
|
async function resolveSchema(schema, options) {
|
|
4975
|
-
const resolver = new ReferenceResolver(options);
|
|
7739
|
+
const resolver = new ReferenceResolver({ ...options, schemaConfig: schema.config });
|
|
4976
7740
|
const errors = [];
|
|
4977
7741
|
const warnings = [];
|
|
4978
7742
|
const resolved = [];
|
|
4979
|
-
|
|
7743
|
+
const flattenResult = await resolver.resolveOrbitalImports(schema);
|
|
7744
|
+
if (!flattenResult.success) {
|
|
7745
|
+
return { success: false, errors: flattenResult.errors };
|
|
7746
|
+
}
|
|
7747
|
+
const orbitals = flattenResult.data;
|
|
7748
|
+
for (const orbital of orbitals) {
|
|
4980
7749
|
const inlineTraits = orbital.traits.filter(
|
|
4981
7750
|
(t) => typeof t !== "string" && "stateMachine" in t
|
|
4982
7751
|
);
|
|
4983
7752
|
resolver.addLocalTraits(inlineTraits);
|
|
4984
7753
|
}
|
|
4985
|
-
|
|
7754
|
+
resolver.seedSchemaEntityIds(orbitals);
|
|
7755
|
+
for (const orbital of orbitals) {
|
|
4986
7756
|
const result = await resolver.resolve(orbital);
|
|
4987
7757
|
if (!result.success) {
|
|
4988
7758
|
errors.push(`Orbital "${orbital.name}": ${result.errors.join(", ")}`);
|
|
4989
7759
|
} else {
|
|
4990
7760
|
resolved.push(result.data);
|
|
7761
|
+
resolver.noteResolvedEntityIds(result.data);
|
|
4991
7762
|
warnings.push(...result.warnings.map((w) => `Orbital "${orbital.name}": ${w}`));
|
|
4992
7763
|
}
|
|
4993
7764
|
}
|
|
4994
7765
|
if (errors.length > 0) {
|
|
4995
7766
|
return { success: false, errors };
|
|
4996
7767
|
}
|
|
7768
|
+
resolver.uniquifyCrossOrbitalPulledSiblings(resolved);
|
|
4997
7769
|
return { success: true, data: resolved, warnings };
|
|
4998
7770
|
}
|
|
4999
7771
|
|
|
@@ -5208,4 +7980,4 @@ var InMemoryPersistence = class {
|
|
|
5208
7980
|
}
|
|
5209
7981
|
};
|
|
5210
7982
|
|
|
5211
|
-
export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, createInitialTraitState, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, validateEventPayload, validatePayloadShapes };
|
|
7983
|
+
export { EffectExecutor, EventBus, HANDLER_MANIFEST, InMemoryPersistence, LIFECYCLE_EVENTS, MockPersistenceAdapter, StateMachineManager, TickScheduler, buildEmitsFromTraits, collectDeclaredConfigDefaults, collectDeclaredEntityDefaults, createInitialTraitState, createMockPersistence, createTestExecutor, createTickScheduler, createUnifiedLoader, findInitialState, findTransition, formatPayloadValidationError, getIsolatedCollectionName, getNamespacedEvent, isBrowser, isElectron, isNamespacedEvent, isNode, isValidDurationString, normalizeEventKey, parseDurationString, parseNamespacedEvent, preprocessSchema, processEvent, validateEventPayload, validatePayloadShapes };
|