@almadar/runtime 6.71.0 → 6.72.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-A474B57C.js} +2702 -263
- 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, 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,205 @@ 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 resolveTraitTypeParamSentinels(trait, entityDef, entitiesByName, typesByName, typeArgs) {
|
|
3856
|
+
const declared = trait.typeParams ?? [];
|
|
3857
|
+
const subs = /* @__PURE__ */ new Map();
|
|
3858
|
+
const declaredNames = /* @__PURE__ */ new Set();
|
|
3859
|
+
for (const p of declared) {
|
|
3860
|
+
declaredNames.add(p.name);
|
|
3861
|
+
const argValue = typeArgs?.[p.name];
|
|
3862
|
+
let sub;
|
|
3863
|
+
if (argValue !== void 0) {
|
|
3864
|
+
sub = resolveTypeArgValue(argValue, entitiesByName, typesByName);
|
|
3865
|
+
} else if (p.kind === "Entity" && entityDef) {
|
|
3866
|
+
sub = { kind: "entity", entity: entityDef };
|
|
3867
|
+
} else if (p.default) {
|
|
3868
|
+
sub = resolveTypeArgValue(p.default, entitiesByName, typesByName);
|
|
3869
|
+
}
|
|
3870
|
+
if (sub) subs.set(p.name, sub);
|
|
3871
|
+
}
|
|
3872
|
+
let changed = false;
|
|
3873
|
+
for (const emit of trait.emits ?? []) {
|
|
3874
|
+
if (!emit.payloadSchema) continue;
|
|
3875
|
+
const schema = emit.payloadSchema;
|
|
3876
|
+
if (flattenBareEntityPayload(schema, entityDef, subs)) {
|
|
3877
|
+
changed = true;
|
|
3878
|
+
} else {
|
|
3879
|
+
changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
|
|
3880
|
+
}
|
|
3881
|
+
}
|
|
3882
|
+
for (const ev of trait.stateMachine?.events ?? []) {
|
|
3883
|
+
if (!ev.payloadSchema) continue;
|
|
3884
|
+
const schema = ev.payloadSchema;
|
|
3885
|
+
if (flattenBareEntityPayload(schema, entityDef, subs)) {
|
|
3886
|
+
changed = true;
|
|
3887
|
+
} else {
|
|
3888
|
+
changed = resolveSentinelFields(schema, entityDef, subs, declaredNames) || changed;
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
return changed;
|
|
3892
|
+
}
|
|
3893
|
+
function resolveOrbitalTypeParamSentinels(traits, primaryEntity, auxiliaryEntities, orbitalTypes) {
|
|
3894
|
+
const entitiesByName = /* @__PURE__ */ new Map();
|
|
3895
|
+
entitiesByName.set(primaryEntity.name, primaryEntity);
|
|
3896
|
+
for (const e of auxiliaryEntities) entitiesByName.set(e.name, e);
|
|
3897
|
+
const typesByName = orbitalTypes ?? {};
|
|
3898
|
+
for (const rt of traits) {
|
|
3899
|
+
const entityDef = rt.trait.linkedEntity ? entitiesByName.get(rt.trait.linkedEntity) : void 0;
|
|
3900
|
+
resolveTraitTypeParamSentinels(rt.trait, entityDef, entitiesByName, typesByName, rt.typeArgs);
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3640
3904
|
// src/resolver/reference-resolver.ts
|
|
3641
3905
|
var refResolverLog = createLogger("almadar:runtime:ref-resolver");
|
|
3642
3906
|
function indexOrbitalNodes(orbital, idIndex) {
|
|
@@ -3910,6 +4174,25 @@ function renameTraitEmbedsInValue(node, subs) {
|
|
|
3910
4174
|
}
|
|
3911
4175
|
return next;
|
|
3912
4176
|
}
|
|
4177
|
+
function renameEntityNameTokensInValue(node, entitySubs) {
|
|
4178
|
+
if (node === null || node === void 0) return node;
|
|
4179
|
+
if (typeof node === "string") {
|
|
4180
|
+
if (!node.startsWith("@")) return node;
|
|
4181
|
+
const rest = node.slice(1);
|
|
4182
|
+
const dot = rest.search(/[.[]/);
|
|
4183
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
4184
|
+
const suffix = dot === -1 ? "" : rest.slice(dot);
|
|
4185
|
+
const to = entitySubs.get(name);
|
|
4186
|
+
return to === void 0 ? node : `@${to}${suffix}`;
|
|
4187
|
+
}
|
|
4188
|
+
if (Array.isArray(node)) return node.map((item) => renameEntityNameTokensInValue(item, entitySubs));
|
|
4189
|
+
if (typeof node !== "object") return node;
|
|
4190
|
+
const next = {};
|
|
4191
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4192
|
+
next[key] = renameEntityNameTokensInValue(value, entitySubs);
|
|
4193
|
+
}
|
|
4194
|
+
return next;
|
|
4195
|
+
}
|
|
3913
4196
|
function renameTraitEmbeds(trait, subs) {
|
|
3914
4197
|
if (subs.size === 0) return trait;
|
|
3915
4198
|
const sm = trait.stateMachine;
|
|
@@ -3956,6 +4239,36 @@ function findTraitEntryInOrbital(orbital, localName) {
|
|
|
3956
4239
|
}
|
|
3957
4240
|
return null;
|
|
3958
4241
|
}
|
|
4242
|
+
function homeOrbitalConfigForTrait(imported, traitName) {
|
|
4243
|
+
for (const o of importedOrbitals(imported)) {
|
|
4244
|
+
if (findTraitEntryInOrbital(o, traitName)) return o.config;
|
|
4245
|
+
}
|
|
4246
|
+
return void 0;
|
|
4247
|
+
}
|
|
4248
|
+
function findPageEntryInOrbital(orbital, localName) {
|
|
4249
|
+
for (const pageRef of orbital.pages ?? []) {
|
|
4250
|
+
if (typeof pageRef === "string") continue;
|
|
4251
|
+
if (!("ref" in pageRef)) {
|
|
4252
|
+
if (pageRef.name === localName) return pageRef;
|
|
4253
|
+
continue;
|
|
4254
|
+
}
|
|
4255
|
+
const refObj = pageRef;
|
|
4256
|
+
if (parsePageRef(refObj.ref)?.pageName === localName) return refObj;
|
|
4257
|
+
}
|
|
4258
|
+
return null;
|
|
4259
|
+
}
|
|
4260
|
+
function toPageTraitRef(traitRef) {
|
|
4261
|
+
if (typeof traitRef === "string") return { ref: traitRef };
|
|
4262
|
+
if ("stateMachine" in traitRef) return { ref: traitRef.name };
|
|
4263
|
+
const refObj = traitRef;
|
|
4264
|
+
return {
|
|
4265
|
+
ref: refObj.name ?? refObj.ref,
|
|
4266
|
+
...refObj.refId !== void 0 ? { refId: refObj.refId } : {},
|
|
4267
|
+
...refObj.linkedEntity !== void 0 ? { linkedEntity: refObj.linkedEntity } : {},
|
|
4268
|
+
...refObj.linkedEntityId !== void 0 ? { linkedEntityId: refObj.linkedEntityId } : {},
|
|
4269
|
+
...refObj.config !== void 0 ? { config: refObj.config } : {}
|
|
4270
|
+
};
|
|
4271
|
+
}
|
|
3959
4272
|
function traitEmbedNamesOf(trait) {
|
|
3960
4273
|
const found = /* @__PURE__ */ new Set();
|
|
3961
4274
|
const walk = (node) => {
|
|
@@ -3975,34 +4288,179 @@ function traitEmbedNamesOf(trait) {
|
|
|
3975
4288
|
if (typeof node !== "object") return;
|
|
3976
4289
|
for (const value of Object.values(node)) walk(value);
|
|
3977
4290
|
};
|
|
3978
|
-
for (const t of trait.stateMachine?.transitions ?? [])
|
|
3979
|
-
|
|
4291
|
+
for (const t of trait.stateMachine?.transitions ?? []) {
|
|
4292
|
+
walk(t.guard);
|
|
4293
|
+
walk(t.effects);
|
|
4294
|
+
}
|
|
4295
|
+
for (const tick of trait.ticks ?? []) {
|
|
4296
|
+
walk(tick.guard);
|
|
4297
|
+
walk(tick.effects);
|
|
4298
|
+
}
|
|
3980
4299
|
for (const field of Object.values(trait.config ?? {})) walk(field.default);
|
|
3981
|
-
return [...found];
|
|
4300
|
+
return [...found].sort();
|
|
3982
4301
|
}
|
|
3983
|
-
function
|
|
4302
|
+
function resolveForwardedSiblingConfigFrom(trait, parentChain, orbitalConfig, schemaConfig) {
|
|
3984
4303
|
const declared = trait.config;
|
|
3985
|
-
|
|
3986
|
-
|
|
4304
|
+
if (!declared) return trait;
|
|
4305
|
+
const next = resolveConfigForwards(declared, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
|
|
4306
|
+
return next ? { ...trait, config: next } : trait;
|
|
4307
|
+
}
|
|
4308
|
+
function callSiteRungValue(rungConfig, knob) {
|
|
4309
|
+
const entry = rungConfig[knob];
|
|
4310
|
+
if (entry === void 0) return void 0;
|
|
4311
|
+
return isCallSiteConfigDeclaration(entry) ? entry.default : entry;
|
|
4312
|
+
}
|
|
4313
|
+
function walkConfigForwardChain(forward, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
|
|
4314
|
+
let knob = forward.slice("@config.".length);
|
|
4315
|
+
if (knob.length === 0 || knob.includes(".")) return void 0;
|
|
4316
|
+
let value;
|
|
4317
|
+
let currentForward = forward;
|
|
4318
|
+
for (const rungConfig of parentChain) {
|
|
4319
|
+
const rungValue = callSiteRungValue(rungConfig, knob);
|
|
4320
|
+
if (rungValue === void 0 || rungValue === currentForward) continue;
|
|
4321
|
+
if (typeof rungValue === "string" && rungValue.startsWith("@config.")) {
|
|
4322
|
+
const nextKnob = rungValue.slice("@config.".length);
|
|
4323
|
+
if (nextKnob.length === 0 || nextKnob.includes(".") || nextKnob === knob) continue;
|
|
4324
|
+
knob = nextKnob;
|
|
4325
|
+
currentForward = rungValue;
|
|
4326
|
+
continue;
|
|
4327
|
+
}
|
|
4328
|
+
value = rungValue;
|
|
4329
|
+
break;
|
|
4330
|
+
}
|
|
4331
|
+
if (value === void 0 || value === currentForward) value = orbitalConfig?.[knob]?.default;
|
|
4332
|
+
if (value === void 0 || value === currentForward) value = upstreamOrbitalConfig?.[knob]?.default;
|
|
4333
|
+
if (value === void 0 || value === currentForward) value = upstreamSchemaConfig?.[knob]?.default;
|
|
4334
|
+
if (value === void 0 || value === currentForward) value = schemaConfig?.[knob]?.default;
|
|
4335
|
+
if (value === void 0 || value === currentForward) return void 0;
|
|
4336
|
+
return value;
|
|
4337
|
+
}
|
|
4338
|
+
function resolveConfigForwards(declared, parentChain, orbitalConfig, upstreamOrbitalConfig, upstreamSchemaConfig, schemaConfig) {
|
|
3987
4339
|
let next;
|
|
3988
4340
|
for (const [key, field] of Object.entries(declared)) {
|
|
3989
4341
|
const forward = field.default;
|
|
3990
4342
|
if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
|
|
3991
|
-
const
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
4343
|
+
const value = walkConfigForwardChain(
|
|
4344
|
+
forward,
|
|
4345
|
+
parentChain,
|
|
4346
|
+
orbitalConfig,
|
|
4347
|
+
upstreamOrbitalConfig,
|
|
4348
|
+
upstreamSchemaConfig,
|
|
4349
|
+
schemaConfig
|
|
4350
|
+
);
|
|
4351
|
+
if (value === void 0) continue;
|
|
3995
4352
|
next ??= { ...declared };
|
|
3996
|
-
next[key] = { ...field, default: value };
|
|
4353
|
+
next[key] = { ...field, default: value, forwardedFrom: forward };
|
|
3997
4354
|
}
|
|
3998
|
-
return next
|
|
4355
|
+
return next;
|
|
4356
|
+
}
|
|
4357
|
+
function resolveCallSiteConfigForwards(config, parentChain, orbitalConfig, schemaConfig) {
|
|
4358
|
+
let next;
|
|
4359
|
+
for (const [key, entry] of Object.entries(config)) {
|
|
4360
|
+
const forward = isCallSiteConfigDeclaration(entry) ? entry.default : entry;
|
|
4361
|
+
if (typeof forward !== "string" || !forward.startsWith("@config.")) continue;
|
|
4362
|
+
const value = walkConfigForwardChain(forward, parentChain, orbitalConfig, void 0, void 0, schemaConfig);
|
|
4363
|
+
if (value === void 0) continue;
|
|
4364
|
+
next ??= { ...config };
|
|
4365
|
+
next[key] = isCallSiteConfigDeclaration(entry) ? { ...entry, default: value, forwardedFrom: forward } : value;
|
|
4366
|
+
}
|
|
4367
|
+
return next;
|
|
4368
|
+
}
|
|
4369
|
+
function traitRefEmbedNamesOf(traitRef) {
|
|
4370
|
+
if (typeof traitRef === "string") return [];
|
|
4371
|
+
return traitEmbedNamesOf(traitRef);
|
|
4372
|
+
}
|
|
4373
|
+
function traitRefLocalName(traitRef) {
|
|
4374
|
+
if (typeof traitRef === "string") {
|
|
4375
|
+
return parseImportedTraitRef(traitRef)?.traitName ?? traitRef;
|
|
4376
|
+
}
|
|
4377
|
+
if ("stateMachine" in traitRef) return traitRef.name;
|
|
4378
|
+
const refObj = traitRef;
|
|
4379
|
+
return refObj.name ?? parseImportedTraitRef(refObj.ref)?.traitName ?? refObj.ref;
|
|
4380
|
+
}
|
|
4381
|
+
function traitRefConfigOf(traitRef) {
|
|
4382
|
+
if (typeof traitRef === "string") return void 0;
|
|
4383
|
+
return traitRef.config;
|
|
4384
|
+
}
|
|
4385
|
+
function buildEmbedGraph(traitRefs) {
|
|
4386
|
+
const out = /* @__PURE__ */ new Map();
|
|
4387
|
+
for (const traitRef of traitRefs) {
|
|
4388
|
+
const referrerName = traitRefLocalName(traitRef);
|
|
4389
|
+
if (!referrerName) continue;
|
|
4390
|
+
for (const child of traitRefEmbedNamesOf(traitRef)) {
|
|
4391
|
+
if (child === referrerName) continue;
|
|
4392
|
+
if (!out.has(child)) out.set(child, referrerName);
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
return out;
|
|
4396
|
+
}
|
|
4397
|
+
function embedderChain(localName, traitRefs, graph) {
|
|
4398
|
+
const chain = [];
|
|
4399
|
+
const visited = /* @__PURE__ */ new Set([localName]);
|
|
4400
|
+
let cur = graph.get(localName);
|
|
4401
|
+
let hops = 0;
|
|
4402
|
+
while (cur !== void 0 && !visited.has(cur) && hops < traitRefs.length) {
|
|
4403
|
+
visited.add(cur);
|
|
4404
|
+
hops++;
|
|
4405
|
+
const entry = traitRefs.find((t) => traitRefLocalName(t) === cur);
|
|
4406
|
+
const entryConfig = entry ? traitRefConfigOf(entry) : void 0;
|
|
4407
|
+
if (entryConfig) chain.push(entryConfig);
|
|
4408
|
+
cur = graph.get(cur);
|
|
4409
|
+
}
|
|
4410
|
+
return chain;
|
|
4411
|
+
}
|
|
4412
|
+
function resolveEmbedderConfigForward(config, localName, embedCtx, schemaConfig) {
|
|
4413
|
+
const chain = embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph);
|
|
4414
|
+
const next = resolveCallSiteConfigForwards(config, chain, embedCtx.orbitalConfig, schemaConfig);
|
|
4415
|
+
return next ? next : config;
|
|
4416
|
+
}
|
|
4417
|
+
function consumerKnownEntityRebindSubs(trait, entityIds) {
|
|
4418
|
+
const out = /* @__PURE__ */ new Map();
|
|
4419
|
+
const refs = trait.entityRefIds;
|
|
4420
|
+
if (!refs) return out;
|
|
4421
|
+
const idToConsumerName = /* @__PURE__ */ new Map();
|
|
4422
|
+
for (const [name, id] of entityIds) {
|
|
4423
|
+
if (!idToConsumerName.has(id)) idToConsumerName.set(id, name);
|
|
4424
|
+
}
|
|
4425
|
+
for (const [tokenName, entityId] of Object.entries(refs)) {
|
|
4426
|
+
const consumerName = idToConsumerName.get(entityId);
|
|
4427
|
+
if (consumerName !== void 0 && consumerName !== tokenName) {
|
|
4428
|
+
out.set(tokenName, consumerName);
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
return out;
|
|
4432
|
+
}
|
|
4433
|
+
function staleEntityRebindSubs(trait, newEntity) {
|
|
4434
|
+
const out = /* @__PURE__ */ new Map();
|
|
4435
|
+
const boundId = trait.linkedEntityId;
|
|
4436
|
+
const refs = trait.entityRefIds;
|
|
4437
|
+
if (boundId && refs) {
|
|
4438
|
+
for (const [tokenName, entityId] of Object.entries(refs)) {
|
|
4439
|
+
if (entityId === boundId) out.set(tokenName, newEntity);
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
return out;
|
|
3999
4443
|
}
|
|
4000
|
-
function applyLinkedEntityRename(trait, linkedEntity) {
|
|
4444
|
+
function applyLinkedEntityRename(trait, linkedEntity, entityIds) {
|
|
4001
4445
|
const atomLinked = trait.linkedEntity;
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4446
|
+
const entitySubs = consumerKnownEntityRebindSubs(trait, entityIds);
|
|
4447
|
+
if (!linkedEntity || !atomLinked || linkedEntity === atomLinked) {
|
|
4448
|
+
return rewriteEntityRefIds(trait, entitySubs, entityIds);
|
|
4449
|
+
}
|
|
4450
|
+
for (const [from, to] of staleEntityRebindSubs(trait, linkedEntity)) {
|
|
4451
|
+
entitySubs.set(from, to);
|
|
4452
|
+
}
|
|
4453
|
+
entitySubs.set(atomLinked, linkedEntity);
|
|
4005
4454
|
const rename = (name) => name === atomLinked ? linkedEntity : void 0;
|
|
4455
|
+
const sm = trait.stateMachine;
|
|
4456
|
+
const rebound = {
|
|
4457
|
+
...trait,
|
|
4458
|
+
linkedEntity,
|
|
4459
|
+
linkedEntityId: entityIds.get(linkedEntity)
|
|
4460
|
+
};
|
|
4461
|
+
if (!sm) {
|
|
4462
|
+
return renamePayloadEntityMarkers(rewriteEntityRefIds(rebound, entitySubs, entityIds), rename);
|
|
4463
|
+
}
|
|
4006
4464
|
const nextTransitions = (sm.transitions ?? []).map((t) => {
|
|
4007
4465
|
const nextEffects = t.effects ? renameEntityInEffects(
|
|
4008
4466
|
t.effects,
|
|
@@ -4017,11 +4475,14 @@ function applyLinkedEntityRename(trait, linkedEntity) {
|
|
|
4017
4475
|
to: linkedEntity,
|
|
4018
4476
|
transitionCount: nextTransitions.length
|
|
4019
4477
|
});
|
|
4020
|
-
return
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4478
|
+
return renamePayloadEntityMarkers(
|
|
4479
|
+
rewriteEntityRefIds(
|
|
4480
|
+
{ ...rebound, stateMachine: { ...sm, transitions: nextTransitions } },
|
|
4481
|
+
entitySubs,
|
|
4482
|
+
entityIds
|
|
4483
|
+
),
|
|
4484
|
+
rename
|
|
4485
|
+
);
|
|
4025
4486
|
}
|
|
4026
4487
|
function resolveEntityTokensById(trait, idIndex) {
|
|
4027
4488
|
const map = trait.entityRefIds;
|
|
@@ -4170,17 +4631,44 @@ function applyEventRenamesToCallSiteConfig(config, declared, renames) {
|
|
|
4170
4631
|
}
|
|
4171
4632
|
return touched ? next : config;
|
|
4172
4633
|
}
|
|
4634
|
+
function resolvedKnobValues(before, after, knobs) {
|
|
4635
|
+
const out = /* @__PURE__ */ new Map();
|
|
4636
|
+
if (knobs.length === 0) return out;
|
|
4637
|
+
const knobSet = new Set(knobs);
|
|
4638
|
+
const beforeEmits = before.emits ?? [];
|
|
4639
|
+
const afterEmits = after.emits ?? [];
|
|
4640
|
+
for (let i = 0; i < beforeEmits.length; i++) {
|
|
4641
|
+
const knob = configRefEventKnob(beforeEmits[i].event);
|
|
4642
|
+
if (knob !== void 0 && knobSet.has(knob)) out.set(knob, afterEmits[i].event);
|
|
4643
|
+
}
|
|
4644
|
+
return out;
|
|
4645
|
+
}
|
|
4646
|
+
function foldEventRenameOntoDeclaredKnobs(trait, resolved, eventRenames) {
|
|
4647
|
+
if (!eventRenames || resolved.size === 0 || !trait.config) return trait;
|
|
4648
|
+
let nextConfig;
|
|
4649
|
+
for (const [knob, resolvedValue] of resolved) {
|
|
4650
|
+
const renamed = eventRenames[resolvedValue];
|
|
4651
|
+
if (renamed === void 0 || renamed === resolvedValue) continue;
|
|
4652
|
+
const field = trait.config[knob];
|
|
4653
|
+
if (!field) continue;
|
|
4654
|
+
nextConfig ??= { ...trait.config };
|
|
4655
|
+
nextConfig[knob] = { ...field, default: renamed };
|
|
4656
|
+
}
|
|
4657
|
+
return nextConfig ? { ...trait, config: nextConfig } : trait;
|
|
4658
|
+
}
|
|
4173
4659
|
function resolveConfigRefEmitNames(trait, callSiteConfig) {
|
|
4174
4660
|
const emits = trait.emits ?? [];
|
|
4175
4661
|
const hasRef = emits.some((em) => configRefEventKnob(em.event) !== void 0);
|
|
4176
|
-
if (!hasRef) return { trait, errors: [] };
|
|
4662
|
+
if (!hasRef) return { trait, errors: [], resolvedKnobs: [] };
|
|
4177
4663
|
const effectiveConfig = {
|
|
4178
4664
|
...normalizeCallSiteConfigToValues(trait.config) ?? {},
|
|
4179
4665
|
...normalizeCallSiteConfigToValues(callSiteConfig) ?? {}
|
|
4180
4666
|
};
|
|
4181
4667
|
const errors = [];
|
|
4668
|
+
const resolvedTriples = [];
|
|
4182
4669
|
const nextEmits = emits.map((em) => {
|
|
4183
|
-
|
|
4670
|
+
const knob = configRefEventKnob(em.event);
|
|
4671
|
+
if (knob === void 0) return em;
|
|
4184
4672
|
const result = resolveConfigRefEventName(em.event, trait.config, effectiveConfig);
|
|
4185
4673
|
if (!result.ok) {
|
|
4186
4674
|
errors.push(
|
|
@@ -4193,78 +4681,1065 @@ function resolveConfigRefEmitNames(trait, callSiteConfig) {
|
|
|
4193
4681
|
ref: em.event,
|
|
4194
4682
|
resolved: result.value
|
|
4195
4683
|
});
|
|
4684
|
+
resolvedTriples.push({ knob, from: em.event, to: result.value });
|
|
4196
4685
|
return { ...em, event: result.value };
|
|
4197
4686
|
});
|
|
4198
|
-
|
|
4687
|
+
const sm = trait.stateMachine;
|
|
4688
|
+
const nextEvents = resolvedTriples.length > 0 && sm ? sm.events.map((ev) => {
|
|
4689
|
+
const hit = resolvedTriples.find((t) => t.from === ev.key);
|
|
4690
|
+
return hit ? { ...ev, key: hit.to } : ev;
|
|
4691
|
+
}) : sm?.events;
|
|
4692
|
+
return {
|
|
4693
|
+
trait: {
|
|
4694
|
+
...trait,
|
|
4695
|
+
emits: nextEmits,
|
|
4696
|
+
...sm && nextEvents !== sm.events ? { stateMachine: { ...sm, events: nextEvents } } : {}
|
|
4697
|
+
},
|
|
4698
|
+
errors,
|
|
4699
|
+
resolvedKnobs: resolvedTriples.map((t) => t.knob)
|
|
4700
|
+
};
|
|
4199
4701
|
}
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4702
|
+
function foldCallSiteConfigOntoTrait(trait, callSiteConfig) {
|
|
4703
|
+
if (!callSiteConfig) return trait;
|
|
4704
|
+
const declared = trait.config;
|
|
4705
|
+
const overrideValues = {};
|
|
4706
|
+
const overriddenKeys = /* @__PURE__ */ new Set();
|
|
4707
|
+
const newDeclarations = {};
|
|
4708
|
+
for (const [key, entry] of Object.entries(callSiteConfig)) {
|
|
4709
|
+
const isDecl = isCallSiteConfigDeclaration(entry);
|
|
4710
|
+
const value = isDecl ? entry.default : entry;
|
|
4711
|
+
if (declared && key in declared) {
|
|
4712
|
+
if (value !== void 0) {
|
|
4713
|
+
overrideValues[key] = value;
|
|
4714
|
+
overriddenKeys.add(key);
|
|
4715
|
+
}
|
|
4716
|
+
} else if (isDecl) {
|
|
4717
|
+
newDeclarations[key] = entry;
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4720
|
+
if (overriddenKeys.size === 0 && Object.keys(newDeclarations).length === 0) {
|
|
4721
|
+
return trait;
|
|
4722
|
+
}
|
|
4723
|
+
let nextConfig = overrideDeclaredKnobs(declared ?? {}, overrideValues);
|
|
4724
|
+
if (overriddenKeys.size > 0) {
|
|
4725
|
+
const patched = { ...nextConfig };
|
|
4726
|
+
for (const key of overriddenKeys) {
|
|
4727
|
+
const field = patched[key];
|
|
4728
|
+
if (!field) continue;
|
|
4729
|
+
const entry = callSiteConfig[key];
|
|
4730
|
+
const entryDecl = isCallSiteConfigDeclaration(entry) ? entry : void 0;
|
|
4731
|
+
patched[key] = {
|
|
4732
|
+
...field,
|
|
4733
|
+
forwardedFrom: entryDecl?.forwardedFrom,
|
|
4734
|
+
// The atom's OWN `refId` (a reference-config field's declared
|
|
4735
|
+
// default names a SPECIFIC node by id) describes the ATOM's OWN
|
|
4736
|
+
// `default`, not whatever this override just replaced it with —
|
|
4737
|
+
// carrying it forward unchanged left a STALE id bound to the NEW
|
|
4738
|
+
// literal string, so the id-index's "current name" correction
|
|
4739
|
+
// (`resolveConfigRefsById`) silently rewrote the override BACK to
|
|
4740
|
+
// the atom's own default target — found via std-notes'
|
|
4741
|
+
// `NoteGlobalSearch`: `idleContent`'s override says `@trait.
|
|
4742
|
+
// NoteCatalog` but the atom's OWN stale `refId` (still pointing at
|
|
4743
|
+
// `AppSearchIdleHint`, the atom's default) rewrote the sibling-pull
|
|
4744
|
+
// target back to it (rung 2: an override with no id of its own
|
|
4745
|
+
// names no id, so it must clear the atom's). An override that
|
|
4746
|
+
// carries ITS OWN `refId` (an annotated, id-aware override) wins
|
|
4747
|
+
// instead — same precedence a `default` override already has.
|
|
4748
|
+
refId: entryDecl?.refId,
|
|
4749
|
+
...entryDecl?.label !== void 0 ? { label: entryDecl.label } : {},
|
|
4750
|
+
...entryDecl?.description !== void 0 ? { description: entryDecl.description } : {},
|
|
4751
|
+
...entryDecl?.synonyms !== void 0 ? { synonyms: entryDecl.synonyms } : {},
|
|
4752
|
+
...entryDecl?.tier !== void 0 ? { tier: entryDecl.tier } : {}
|
|
4753
|
+
};
|
|
4217
4754
|
}
|
|
4755
|
+
nextConfig = patched;
|
|
4218
4756
|
}
|
|
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
|
-
}
|
|
4757
|
+
if (Object.keys(newDeclarations).length > 0) {
|
|
4758
|
+
nextConfig = { ...nextConfig, ...newDeclarations };
|
|
4227
4759
|
}
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
const
|
|
4239
|
-
const
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4760
|
+
return { ...trait, config: nextConfig };
|
|
4761
|
+
}
|
|
4762
|
+
var ENTITY_FIELD_TOKEN_PREFIX = "@entity.";
|
|
4763
|
+
function rewriteEntityFieldTokensInValue(node, subs) {
|
|
4764
|
+
if (node === null || node === void 0) return node;
|
|
4765
|
+
if (typeof node === "string") {
|
|
4766
|
+
if (!node.startsWith(ENTITY_FIELD_TOKEN_PREFIX)) return node;
|
|
4767
|
+
const rest = node.slice(ENTITY_FIELD_TOKEN_PREFIX.length);
|
|
4768
|
+
const dot = rest.search(/[.[]/);
|
|
4769
|
+
const name = dot === -1 ? rest : rest.slice(0, dot);
|
|
4770
|
+
const suffix = dot === -1 ? "" : rest.slice(dot);
|
|
4771
|
+
const to = subs.get(name);
|
|
4772
|
+
return to === void 0 ? node : `${ENTITY_FIELD_TOKEN_PREFIX}${to}${suffix}`;
|
|
4773
|
+
}
|
|
4774
|
+
if (Array.isArray(node)) return node.map((item) => rewriteEntityFieldTokensInValue(item, subs));
|
|
4775
|
+
if (typeof node !== "object") return node;
|
|
4776
|
+
const next = {};
|
|
4777
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4778
|
+
next[key] = rewriteEntityFieldTokensInValue(value, subs);
|
|
4779
|
+
}
|
|
4780
|
+
return next;
|
|
4781
|
+
}
|
|
4782
|
+
function rewriteEntityFieldsInTrait(trait, fieldSubs) {
|
|
4783
|
+
if (fieldSubs.size === 0) return trait;
|
|
4784
|
+
const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
|
|
4785
|
+
const next = { ...trait };
|
|
4786
|
+
const sm = trait.stateMachine;
|
|
4787
|
+
if (sm) {
|
|
4788
|
+
next.stateMachine = {
|
|
4789
|
+
...sm,
|
|
4790
|
+
transitions: (sm.transitions ?? []).map((t) => ({
|
|
4791
|
+
...t,
|
|
4792
|
+
...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
|
|
4793
|
+
...t.effects ? { effects: rewrite(t.effects) } : {}
|
|
4794
|
+
}))
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
4797
|
+
if (trait.ticks) {
|
|
4798
|
+
next.ticks = trait.ticks.map((tick) => ({
|
|
4799
|
+
...tick,
|
|
4800
|
+
...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
|
|
4801
|
+
effects: rewrite(tick.effects)
|
|
4802
|
+
}));
|
|
4803
|
+
}
|
|
4804
|
+
if (trait.listens) {
|
|
4805
|
+
next.listens = trait.listens.map((l) => ({
|
|
4806
|
+
...l,
|
|
4807
|
+
...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
|
|
4808
|
+
...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
|
|
4809
|
+
}));
|
|
4810
|
+
}
|
|
4811
|
+
if (trait.initialEffects) {
|
|
4812
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
4813
|
+
}
|
|
4814
|
+
if (trait.config) {
|
|
4815
|
+
const nextConfig = {};
|
|
4816
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
4817
|
+
nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewrite(field.default) };
|
|
4257
4818
|
}
|
|
4258
|
-
|
|
4259
|
-
|
|
4819
|
+
next.config = nextConfig;
|
|
4820
|
+
}
|
|
4821
|
+
return next;
|
|
4822
|
+
}
|
|
4823
|
+
function rewriteEntityFieldsInEntity(entity, fieldSubs) {
|
|
4824
|
+
if (fieldSubs.size === 0) return entity;
|
|
4825
|
+
const rewrite = (v) => rewriteEntityFieldTokensInValue(v, fieldSubs);
|
|
4826
|
+
return {
|
|
4827
|
+
...entity,
|
|
4828
|
+
fields: entity.fields.map((f) => f.name && fieldSubs.has(f.name) ? { ...f, name: fieldSubs.get(f.name) } : f),
|
|
4829
|
+
...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
|
|
4830
|
+
...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
|
|
4831
|
+
...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
|
|
4832
|
+
...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
|
|
4833
|
+
};
|
|
4834
|
+
}
|
|
4835
|
+
var USER_FIELD_PREFIX = "@user.";
|
|
4836
|
+
function directUserField(node) {
|
|
4837
|
+
if (typeof node !== "string" || !node.startsWith(USER_FIELD_PREFIX)) return void 0;
|
|
4838
|
+
const rest = node.slice(USER_FIELD_PREFIX.length);
|
|
4839
|
+
return rest.length > 0 && !/[.[]/.test(rest) ? rest : void 0;
|
|
4840
|
+
}
|
|
4841
|
+
var EQUALITY_OPS = /* @__PURE__ */ new Set(["=", "==", "!=", "!==", "eq", "neq"]);
|
|
4842
|
+
var NEGATED_EQUALITY_OPS = /* @__PURE__ */ new Set(["!=", "!==", "neq"]);
|
|
4843
|
+
function literalHaystackMembers(items) {
|
|
4844
|
+
const isListCall = items[0] === "list";
|
|
4845
|
+
const members = isListCall ? items.slice(1) : items;
|
|
4846
|
+
return members.every((v) => typeof v === "string") ? [...members] : void 0;
|
|
4847
|
+
}
|
|
4848
|
+
function rewriteRoleLiteralsInValue(node, roleFields, roles) {
|
|
4849
|
+
if (node === null || node === void 0) return node;
|
|
4850
|
+
if (Array.isArray(node)) {
|
|
4851
|
+
const head = node[0];
|
|
4852
|
+
if (typeof head === "string" && EQUALITY_OPS.has(head) && node.length === 3) {
|
|
4853
|
+
const [, left, right] = node;
|
|
4854
|
+
const leftField = directUserField(left);
|
|
4855
|
+
const rightField = directUserField(right);
|
|
4856
|
+
const userField = leftField !== void 0 && rightField === void 0 ? leftField : rightField !== void 0 && leftField === void 0 ? rightField : void 0;
|
|
4857
|
+
if (userField !== void 0 && roleFields.has(userField)) {
|
|
4858
|
+
const literalSide = leftField !== void 0 ? right : left;
|
|
4859
|
+
if (typeof literalSide === "string" && literalSide in roles) {
|
|
4860
|
+
const targets = roles[literalSide];
|
|
4861
|
+
if (targets.length === 1) {
|
|
4862
|
+
return leftField !== void 0 ? [head, left, targets[0]] : [head, targets[0], right];
|
|
4863
|
+
}
|
|
4864
|
+
const includesExpr = ["array/includes", [...targets], leftField !== void 0 ? left : right];
|
|
4865
|
+
return NEGATED_EQUALITY_OPS.has(head) ? ["not", includesExpr] : includesExpr;
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4260
4868
|
}
|
|
4261
|
-
if (
|
|
4262
|
-
|
|
4869
|
+
if (head === "array/includes" && node.length === 3 && Array.isArray(node[1])) {
|
|
4870
|
+
const needleField = directUserField(node[2]);
|
|
4871
|
+
if (needleField !== void 0 && roleFields.has(needleField)) {
|
|
4872
|
+
const members = literalHaystackMembers(node[1]);
|
|
4873
|
+
if (members !== void 0) {
|
|
4874
|
+
const expanded = [];
|
|
4875
|
+
for (const literal of members) {
|
|
4876
|
+
const mapped = roles[literal];
|
|
4877
|
+
if (mapped) {
|
|
4878
|
+
for (const target of mapped) if (!expanded.includes(target)) expanded.push(target);
|
|
4879
|
+
} else if (!expanded.includes(literal)) {
|
|
4880
|
+
expanded.push(literal);
|
|
4881
|
+
}
|
|
4882
|
+
}
|
|
4883
|
+
const isListCall = node[1][0] === "list";
|
|
4884
|
+
return ["array/includes", isListCall ? ["list", ...expanded] : expanded, node[2]];
|
|
4885
|
+
}
|
|
4886
|
+
}
|
|
4263
4887
|
}
|
|
4264
|
-
|
|
4265
|
-
|
|
4888
|
+
return node.map((item) => rewriteRoleLiteralsInValue(item, roleFields, roles));
|
|
4889
|
+
}
|
|
4890
|
+
if (typeof node !== "object") return node;
|
|
4891
|
+
const next = {};
|
|
4892
|
+
for (const [key, value] of Object.entries(node)) {
|
|
4893
|
+
next[key] = rewriteRoleLiteralsInValue(value, roleFields, roles);
|
|
4894
|
+
}
|
|
4895
|
+
return next;
|
|
4896
|
+
}
|
|
4897
|
+
function rewriteRoleLiteralsInTrait(trait, roleFields, roles) {
|
|
4898
|
+
if (roleFields.size === 0 || Object.keys(roles).length === 0) return trait;
|
|
4899
|
+
const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
|
|
4900
|
+
const next = { ...trait };
|
|
4901
|
+
const sm = trait.stateMachine;
|
|
4902
|
+
if (sm) {
|
|
4903
|
+
next.stateMachine = {
|
|
4904
|
+
...sm,
|
|
4905
|
+
transitions: (sm.transitions ?? []).map((t) => ({
|
|
4906
|
+
...t,
|
|
4907
|
+
...t.guard !== void 0 ? { guard: rewrite(t.guard) } : {},
|
|
4908
|
+
...t.effects ? { effects: rewrite(t.effects) } : {}
|
|
4909
|
+
}))
|
|
4910
|
+
};
|
|
4911
|
+
}
|
|
4912
|
+
if (trait.ticks) {
|
|
4913
|
+
next.ticks = trait.ticks.map((tick) => ({
|
|
4914
|
+
...tick,
|
|
4915
|
+
...tick.guard !== void 0 ? { guard: rewrite(tick.guard) } : {},
|
|
4916
|
+
effects: rewrite(tick.effects)
|
|
4917
|
+
}));
|
|
4918
|
+
}
|
|
4919
|
+
if (trait.listens) {
|
|
4920
|
+
next.listens = trait.listens.map((l) => ({
|
|
4921
|
+
...l,
|
|
4922
|
+
...l.guard !== void 0 ? { guard: rewrite(l.guard) } : {},
|
|
4923
|
+
...l.payloadMapping ? { payloadMapping: rewrite(l.payloadMapping) } : {}
|
|
4924
|
+
}));
|
|
4925
|
+
}
|
|
4926
|
+
if (trait.initialEffects) {
|
|
4927
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
4928
|
+
}
|
|
4929
|
+
if (trait.config) {
|
|
4930
|
+
const nextConfig = {};
|
|
4931
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
4932
|
+
nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewrite(field.default) };
|
|
4933
|
+
}
|
|
4934
|
+
next.config = nextConfig;
|
|
4935
|
+
}
|
|
4936
|
+
if (trait.sourceEntityDefinition) {
|
|
4937
|
+
next.sourceEntityDefinition = rewriteRoleLiteralsInEntity(trait.sourceEntityDefinition, roleFields, roles);
|
|
4938
|
+
}
|
|
4939
|
+
return next;
|
|
4940
|
+
}
|
|
4941
|
+
function rewriteRoleLiteralsInEntity(entity, roleFields, roles) {
|
|
4942
|
+
if (roleFields.size === 0 || Object.keys(roles).length === 0) return entity;
|
|
4943
|
+
const rewrite = (v) => rewriteRoleLiteralsInValue(v, roleFields, roles);
|
|
4944
|
+
return {
|
|
4945
|
+
...entity,
|
|
4946
|
+
...entity.read_policy !== void 0 ? { read_policy: rewrite(entity.read_policy) } : {},
|
|
4947
|
+
...entity.create_policy !== void 0 ? { create_policy: rewrite(entity.create_policy) } : {},
|
|
4948
|
+
...entity.update_policy !== void 0 ? { update_policy: rewrite(entity.update_policy) } : {},
|
|
4949
|
+
...entity.delete_policy !== void 0 ? { delete_policy: rewrite(entity.delete_policy) } : {}
|
|
4950
|
+
};
|
|
4951
|
+
}
|
|
4952
|
+
function renameRelationTargetsInField(field, entitySubs, entityIds) {
|
|
4953
|
+
let next = field;
|
|
4954
|
+
if (next.type === "relation") {
|
|
4955
|
+
const to = entitySubs.get(next.relation.entity);
|
|
4956
|
+
if (to !== void 0) {
|
|
4957
|
+
next = { ...next, relation: { ...next.relation, entity: to, entityId: entityIds.get(to) } };
|
|
4958
|
+
}
|
|
4959
|
+
}
|
|
4960
|
+
if ((next.type === "array" || next.type === "object") && next.items) {
|
|
4961
|
+
next = { ...next, items: renameRelationTargetsInField(next.items, entitySubs, entityIds) };
|
|
4962
|
+
}
|
|
4963
|
+
if (next.properties) {
|
|
4964
|
+
const nextProperties = {};
|
|
4965
|
+
for (const [key, value] of Object.entries(next.properties)) {
|
|
4966
|
+
nextProperties[key] = renameRelationTargetsInField(value, entitySubs, entityIds);
|
|
4967
|
+
}
|
|
4968
|
+
next = { ...next, properties: nextProperties };
|
|
4969
|
+
}
|
|
4970
|
+
return next;
|
|
4971
|
+
}
|
|
4972
|
+
function renameEntityRelationTargets(entity, entitySubs, entityIds) {
|
|
4973
|
+
if (entitySubs.size === 0) return entity;
|
|
4974
|
+
return { ...entity, fields: entity.fields.map((f) => renameRelationTargetsInField(f, entitySubs, entityIds)) };
|
|
4975
|
+
}
|
|
4976
|
+
function renameSourceEntityDefinition(trait, subs, entityIds) {
|
|
4977
|
+
const src = trait.sourceEntityDefinition;
|
|
4978
|
+
if (!src || subs.size === 0) return trait;
|
|
4979
|
+
const renamedName = subs.get(src.name) ?? src.name;
|
|
4980
|
+
const nextSrc = renameEntityRelationTargets({ ...src, name: renamedName }, subs, entityIds);
|
|
4981
|
+
return { ...trait, sourceEntityDefinition: nextSrc };
|
|
4982
|
+
}
|
|
4983
|
+
function renamePayloadEntity(fields, rename) {
|
|
4984
|
+
return fields.map((field) => {
|
|
4985
|
+
const renamedEntity = field.entity !== void 0 ? rename(field.entity) : void 0;
|
|
4986
|
+
const renamedProps = field.properties ? renamePayloadEntity(field.properties, rename) : field.properties;
|
|
4987
|
+
return {
|
|
4988
|
+
...field,
|
|
4989
|
+
...renamedEntity !== void 0 ? { entity: renamedEntity } : {},
|
|
4990
|
+
...renamedProps !== void 0 ? { properties: renamedProps } : {}
|
|
4991
|
+
};
|
|
4992
|
+
});
|
|
4993
|
+
}
|
|
4994
|
+
function renamePayloadEntityMarkers(trait, rename) {
|
|
4995
|
+
const sm = trait.stateMachine;
|
|
4996
|
+
const nextEvents = sm?.events ? sm.events.map(
|
|
4997
|
+
(ev) => ev.payloadSchema ? { ...ev, payloadSchema: renamePayloadEntity(ev.payloadSchema, rename) } : ev
|
|
4998
|
+
) : void 0;
|
|
4999
|
+
const nextEmits = trait.emits ? trait.emits.map(
|
|
5000
|
+
(em) => em.payloadSchema ? { ...em, payloadSchema: renamePayloadEntity(em.payloadSchema, rename) } : em
|
|
5001
|
+
) : void 0;
|
|
5002
|
+
return {
|
|
5003
|
+
...trait,
|
|
5004
|
+
...sm && nextEvents ? { stateMachine: { ...sm, events: nextEvents } } : {},
|
|
5005
|
+
...nextEmits ? { emits: nextEmits } : {}
|
|
5006
|
+
};
|
|
5007
|
+
}
|
|
5008
|
+
function walkEntityInPayloadMapping(payloadMapping, rename, props) {
|
|
5009
|
+
const next = {};
|
|
5010
|
+
for (const [key, value] of Object.entries(payloadMapping)) {
|
|
5011
|
+
next[key] = renameEntityInEffect(value, rename, props);
|
|
5012
|
+
}
|
|
5013
|
+
return next;
|
|
5014
|
+
}
|
|
5015
|
+
function renameEntitiesInTrait(trait, entitySubs) {
|
|
5016
|
+
if (entitySubs.size === 0) return trait;
|
|
5017
|
+
const rename = (name) => entitySubs.get(name);
|
|
5018
|
+
const withTokens = (value) => renameEntityNameTokensInValue(value, entitySubs);
|
|
5019
|
+
const nextLinked = trait.linkedEntity !== void 0 ? entitySubs.get(trait.linkedEntity) ?? trait.linkedEntity : trait.linkedEntity;
|
|
5020
|
+
const sm = trait.stateMachine;
|
|
5021
|
+
const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
|
|
5022
|
+
...t,
|
|
5023
|
+
...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5024
|
+
effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
|
|
5025
|
+
})) : sm?.transitions;
|
|
5026
|
+
const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
|
|
5027
|
+
...tick,
|
|
5028
|
+
...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5029
|
+
effects: withTokens(renameEntityInEffects(
|
|
5030
|
+
tick.effects,
|
|
5031
|
+
rename,
|
|
5032
|
+
REBIND_ENTITY_PROPS
|
|
5033
|
+
))
|
|
5034
|
+
})) : trait.ticks;
|
|
5035
|
+
const nextListens = trait.listens ? trait.listens.map((l) => ({
|
|
5036
|
+
...l,
|
|
5037
|
+
...l.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(l.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5038
|
+
...l.payloadMapping ? { payloadMapping: withTokens(walkEntityInPayloadMapping(l.payloadMapping, rename, REBIND_ENTITY_PROPS)) } : {}
|
|
5039
|
+
})) : trait.listens;
|
|
5040
|
+
const nextInitial = trait.initialEffects ? withTokens(renameEntityInEffects(
|
|
5041
|
+
trait.initialEffects,
|
|
5042
|
+
rename,
|
|
5043
|
+
REBIND_ENTITY_PROPS
|
|
5044
|
+
)) : trait.initialEffects;
|
|
5045
|
+
return renamePayloadEntityMarkers(
|
|
5046
|
+
{
|
|
5047
|
+
...trait,
|
|
5048
|
+
linkedEntity: nextLinked,
|
|
5049
|
+
...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
|
|
5050
|
+
...nextTicks !== void 0 ? { ticks: nextTicks } : {},
|
|
5051
|
+
...nextListens !== void 0 ? { listens: nextListens } : {},
|
|
5052
|
+
...nextInitial !== void 0 ? { initialEffects: nextInitial } : {}
|
|
5053
|
+
},
|
|
5054
|
+
rename
|
|
5055
|
+
);
|
|
5056
|
+
}
|
|
5057
|
+
function rewriteEntityRefIds(trait, entitySubs, entityIds) {
|
|
5058
|
+
const refs = trait.entityRefIds;
|
|
5059
|
+
if (!refs) return trait;
|
|
5060
|
+
const out = {};
|
|
5061
|
+
for (const [from, oldId] of Object.entries(refs)) {
|
|
5062
|
+
const name = entitySubs.get(from) ?? from;
|
|
5063
|
+
out[name] = entityIds.get(name) ?? oldId;
|
|
5064
|
+
}
|
|
5065
|
+
return { ...trait, entityRefIds: out };
|
|
5066
|
+
}
|
|
5067
|
+
function applyAliasEntityRenames(trait, subs, entityIds) {
|
|
5068
|
+
if (subs.size === 0) return trait;
|
|
5069
|
+
const rename = (name) => subs.get(name);
|
|
5070
|
+
const withTokens = (value) => renameEntityNameTokensInValue(value, subs);
|
|
5071
|
+
const sm = trait.stateMachine;
|
|
5072
|
+
const nextTransitions = sm?.transitions ? sm.transitions.map((t) => ({
|
|
5073
|
+
...t,
|
|
5074
|
+
...t.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(t.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5075
|
+
effects: t.effects ? withTokens(renameEntityInEffects(t.effects, rename, REBIND_ENTITY_PROPS)) : t.effects
|
|
5076
|
+
})) : sm?.transitions;
|
|
5077
|
+
const nextTicks = trait.ticks ? trait.ticks.map((tick) => ({
|
|
5078
|
+
...tick,
|
|
5079
|
+
...tick.guard !== void 0 ? { guard: withTokens(renameEntityInEffect(tick.guard, rename, REBIND_ENTITY_PROPS)) } : {},
|
|
5080
|
+
effects: withTokens(
|
|
5081
|
+
renameEntityInEffects(tick.effects, rename, REBIND_ENTITY_PROPS)
|
|
5082
|
+
)
|
|
5083
|
+
})) : trait.ticks;
|
|
5084
|
+
const next = {
|
|
5085
|
+
...trait,
|
|
5086
|
+
...sm ? { stateMachine: { ...sm, transitions: nextTransitions ?? [] } } : {},
|
|
5087
|
+
...nextTicks !== void 0 ? { ticks: nextTicks } : {}
|
|
5088
|
+
};
|
|
5089
|
+
return rewriteEntityRefIds(next, subs, entityIds);
|
|
5090
|
+
}
|
|
5091
|
+
function collectEntityNamesInTrait(trait, candidates) {
|
|
5092
|
+
const collected = /* @__PURE__ */ new Set();
|
|
5093
|
+
const collect = (name) => {
|
|
5094
|
+
if (candidates.has(name)) collected.add(name);
|
|
5095
|
+
return void 0;
|
|
5096
|
+
};
|
|
5097
|
+
const sm = trait.stateMachine;
|
|
5098
|
+
for (const t of sm?.transitions ?? []) {
|
|
5099
|
+
if (t.guard !== void 0) renameEntityInEffect(t.guard, collect, REBIND_ENTITY_PROPS);
|
|
5100
|
+
if (t.effects) renameEntityInEffects(t.effects, collect, REBIND_ENTITY_PROPS);
|
|
5101
|
+
}
|
|
5102
|
+
for (const tick of trait.ticks ?? []) {
|
|
5103
|
+
if (tick.guard !== void 0) renameEntityInEffect(tick.guard, collect, REBIND_ENTITY_PROPS);
|
|
5104
|
+
renameEntityInEffects(tick.effects, collect, REBIND_ENTITY_PROPS);
|
|
5105
|
+
}
|
|
5106
|
+
for (const l of trait.listens ?? []) {
|
|
5107
|
+
if (l.guard !== void 0) renameEntityInEffect(l.guard, collect, REBIND_ENTITY_PROPS);
|
|
5108
|
+
if (l.payloadMapping) walkEntityInPayloadMapping(l.payloadMapping, collect, REBIND_ENTITY_PROPS);
|
|
5109
|
+
}
|
|
5110
|
+
if (trait.initialEffects) {
|
|
5111
|
+
renameEntityInEffects(trait.initialEffects, collect, REBIND_ENTITY_PROPS);
|
|
5112
|
+
}
|
|
5113
|
+
return collected;
|
|
5114
|
+
}
|
|
5115
|
+
function collectRelationTargets(field, candidates, out) {
|
|
5116
|
+
if (field.type === "relation" && candidates.has(field.relation.entity)) out.add(field.relation.entity);
|
|
5117
|
+
if ((field.type === "array" || field.type === "object") && field.items) {
|
|
5118
|
+
collectRelationTargets(field.items, candidates, out);
|
|
5119
|
+
}
|
|
5120
|
+
if (field.properties) {
|
|
5121
|
+
for (const value of Object.values(field.properties)) collectRelationTargets(value, candidates, out);
|
|
5122
|
+
}
|
|
5123
|
+
}
|
|
5124
|
+
function relationTargetsOfEntity(entity, candidates) {
|
|
5125
|
+
const out = /* @__PURE__ */ new Set();
|
|
5126
|
+
for (const field of entity.fields) collectRelationTargets(field, candidates, out);
|
|
5127
|
+
return out;
|
|
5128
|
+
}
|
|
5129
|
+
function rewriteListenSources(trait, subs, idByName, orbitalRename) {
|
|
5130
|
+
const listens = trait.listens;
|
|
5131
|
+
if (!listens || listens.length === 0) return trait;
|
|
5132
|
+
let changed = false;
|
|
5133
|
+
const nextListens = listens.map((listen) => {
|
|
5134
|
+
const source = listen.source;
|
|
5135
|
+
if (!source) return listen;
|
|
5136
|
+
if (source.kind === "trait") {
|
|
5137
|
+
const target = subs.get(source.trait);
|
|
5138
|
+
if (target === void 0 || target === source.trait) return listen;
|
|
5139
|
+
changed = true;
|
|
5140
|
+
const traitId = idByName.get(target);
|
|
5141
|
+
return {
|
|
5142
|
+
...listen,
|
|
5143
|
+
source: { kind: "trait", trait: target, ...traitId ? { traitId } : {} }
|
|
5144
|
+
};
|
|
5145
|
+
}
|
|
5146
|
+
if (source.kind === "orbital" && orbitalRename && source.orbital === orbitalRename.from) {
|
|
5147
|
+
const targetTrait = subs.get(source.trait) ?? source.trait;
|
|
5148
|
+
changed = true;
|
|
5149
|
+
const traitId = idByName.get(targetTrait);
|
|
5150
|
+
return {
|
|
5151
|
+
...listen,
|
|
5152
|
+
source: {
|
|
5153
|
+
kind: "orbital",
|
|
5154
|
+
orbital: orbitalRename.to,
|
|
5155
|
+
trait: targetTrait,
|
|
5156
|
+
...traitId ? { traitId } : {}
|
|
5157
|
+
}
|
|
5158
|
+
};
|
|
5159
|
+
}
|
|
5160
|
+
return listen;
|
|
5161
|
+
});
|
|
5162
|
+
return changed ? { ...trait, listens: nextListens } : trait;
|
|
5163
|
+
}
|
|
5164
|
+
function isInlineEntity(ref) {
|
|
5165
|
+
return !isEntityReference(ref) && !isEntityCall(ref);
|
|
5166
|
+
}
|
|
5167
|
+
function inlineEntityRefsOf(orbital) {
|
|
5168
|
+
return [orbital.entity, ...orbital.auxiliaryEntities ?? []].filter(isInlineEntity);
|
|
5169
|
+
}
|
|
5170
|
+
function entityByNameForAlias(imports, alias, entityName) {
|
|
5171
|
+
const imported = imports.orbitals.get(alias);
|
|
5172
|
+
if (!imported) return void 0;
|
|
5173
|
+
for (const o of importedOrbitals(imported)) {
|
|
5174
|
+
const found = inlineEntityRefsOf(o).find((e) => e.name === entityName);
|
|
5175
|
+
if (found) return found;
|
|
5176
|
+
}
|
|
5177
|
+
return void 0;
|
|
5178
|
+
}
|
|
5179
|
+
function entityByNameAnyAlias(imports, entityName) {
|
|
5180
|
+
const aliases = Array.from(imports.orbitals.keys()).sort();
|
|
5181
|
+
for (const alias of aliases) {
|
|
5182
|
+
const found = entityByNameForAlias(imports, alias, entityName);
|
|
5183
|
+
if (found) return found;
|
|
5184
|
+
}
|
|
5185
|
+
return void 0;
|
|
5186
|
+
}
|
|
5187
|
+
function ownedTraitEntryFor(imports, alias, traitName) {
|
|
5188
|
+
const imported = imports.orbitals.get(alias);
|
|
5189
|
+
if (!imported) return void 0;
|
|
5190
|
+
const owner = importedOrbitals(imported).find(
|
|
5191
|
+
(o) => findTraitEntryInOrbital(o, traitName) !== null
|
|
5192
|
+
);
|
|
5193
|
+
if (!owner || !isInlineEntity(owner.entity)) return void 0;
|
|
5194
|
+
return { owner, ownerEntity: owner.entity, entry: findTraitEntryInOrbital(owner, traitName) };
|
|
5195
|
+
}
|
|
5196
|
+
function boundTraitOrbitalBinding(imports, alias, traitName) {
|
|
5197
|
+
const imported = imports.orbitals.get(alias);
|
|
5198
|
+
if (imported?.resolvedOrbitals) {
|
|
5199
|
+
for (const ro of imported.resolvedOrbitals) {
|
|
5200
|
+
const entry = findTraitEntryInOrbital(ro.original, traitName);
|
|
5201
|
+
if (!entry) continue;
|
|
5202
|
+
const bound2 = entry.linkedEntity;
|
|
5203
|
+
const resolvedEntities = [ro.entity, ...ro.auxiliaryEntities ?? []];
|
|
5204
|
+
const boundEntity2 = bound2 !== void 0 ? resolvedEntities.find((e) => e.name === bound2) : void 0;
|
|
5205
|
+
const requiredData2 = new Set(
|
|
5206
|
+
ro.traits.find((rt) => rt.trait.name === traitName)?.trait.entityContract?.requires ?? []
|
|
5207
|
+
);
|
|
5208
|
+
return { owner: ro.original, ownerEntity: ro.entity, entity: boundEntity2 ?? ro.entity, requiredData: requiredData2 };
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
const owned = ownedTraitEntryFor(imports, alias, traitName);
|
|
5212
|
+
if (!owned) return void 0;
|
|
5213
|
+
const ownerEntities = inlineEntityRefsOf(owned.owner);
|
|
5214
|
+
const bound = owned.entry?.linkedEntity;
|
|
5215
|
+
const boundEntity = bound !== void 0 ? ownerEntities.find((e) => e.name === bound) : void 0;
|
|
5216
|
+
const requiredData = new Set(
|
|
5217
|
+
owned.entry && "stateMachine" in owned.entry ? owned.entry.entityContract?.requires ?? [] : []
|
|
5218
|
+
);
|
|
5219
|
+
return { owner: owned.owner, ownerEntity: owned.ownerEntity, entity: boundEntity ?? owned.ownerEntity, requiredData };
|
|
5220
|
+
}
|
|
5221
|
+
function auxEntitiesFromUnrebindTraitRefs(orbitalTraits, imports) {
|
|
5222
|
+
const out = [];
|
|
5223
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5224
|
+
const push = (e) => {
|
|
5225
|
+
if (!seen.has(e.name)) {
|
|
5226
|
+
seen.add(e.name);
|
|
5227
|
+
out.push(e);
|
|
5228
|
+
}
|
|
5229
|
+
};
|
|
5230
|
+
for (const tr of orbitalTraits) {
|
|
5231
|
+
let ref;
|
|
5232
|
+
let linkedEntity;
|
|
5233
|
+
if (typeof tr === "string") {
|
|
5234
|
+
ref = tr;
|
|
5235
|
+
} else if ("ref" in tr) {
|
|
5236
|
+
ref = tr.ref;
|
|
5237
|
+
linkedEntity = tr.linkedEntity;
|
|
5238
|
+
} else {
|
|
5239
|
+
continue;
|
|
5240
|
+
}
|
|
5241
|
+
const parsed = parseImportedTraitRef(ref);
|
|
5242
|
+
if (!parsed) continue;
|
|
5243
|
+
const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
|
|
5244
|
+
if (!binding) continue;
|
|
5245
|
+
if (linkedEntity === void 0) {
|
|
5246
|
+
push(binding.entity);
|
|
5247
|
+
}
|
|
5248
|
+
for (const e of inlineEntityRefsOf(binding.owner)) {
|
|
5249
|
+
if (e.name !== binding.ownerEntity.name) push(e);
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
5252
|
+
return out;
|
|
5253
|
+
}
|
|
5254
|
+
function rewriteSelfRelationTarget(field, oldName, newName, newId) {
|
|
5255
|
+
if (field.type === "relation" && field.relation.entity === oldName) {
|
|
5256
|
+
field.relation = { ...field.relation, entity: newName, entityId: newId };
|
|
5257
|
+
}
|
|
5258
|
+
if (field.type === "array" && field.items) {
|
|
5259
|
+
rewriteSelfRelationTarget(field.items, oldName, newName, newId);
|
|
5260
|
+
}
|
|
5261
|
+
if (field.type === "object" && field.items) {
|
|
5262
|
+
rewriteSelfRelationTarget(field.items, oldName, newName, newId);
|
|
5263
|
+
}
|
|
5264
|
+
if (field.properties) {
|
|
5265
|
+
for (const key of Object.keys(field.properties)) {
|
|
5266
|
+
rewriteSelfRelationTarget(field.properties[key], oldName, newName, newId);
|
|
5267
|
+
}
|
|
5268
|
+
}
|
|
5269
|
+
}
|
|
5270
|
+
function mergeImportedEntityFields(callerEntity, importedEntity, intrinsicOnly, requiredData) {
|
|
5271
|
+
const existingNames = new Set(
|
|
5272
|
+
callerEntity.fields.map((f) => f.name).filter((n) => n !== void 0)
|
|
5273
|
+
);
|
|
5274
|
+
const oldName = importedEntity.name;
|
|
5275
|
+
const newName = callerEntity.name;
|
|
5276
|
+
const newId = callerEntity.id;
|
|
5277
|
+
for (const field of importedEntity.fields) {
|
|
5278
|
+
if (intrinsicOnly && field.intrinsic !== true) continue;
|
|
5279
|
+
if (field.name === void 0) continue;
|
|
5280
|
+
if (requiredData.has(field.name) && field.intrinsic !== true) continue;
|
|
5281
|
+
if (existingNames.has(field.name)) continue;
|
|
5282
|
+
const cloned = structuredClone(field);
|
|
5283
|
+
rewriteSelfRelationTarget(cloned, oldName, newName, newId);
|
|
5284
|
+
callerEntity.fields.push(cloned);
|
|
5285
|
+
}
|
|
5286
|
+
}
|
|
5287
|
+
function mergeImportedEntityFieldsIntoOrbital(orbitalTraits, entity, declaredAuxEntities, imports) {
|
|
5288
|
+
const mergedAliases = /* @__PURE__ */ new Set();
|
|
5289
|
+
const pending = [];
|
|
5290
|
+
for (const tr of orbitalTraits) {
|
|
5291
|
+
let ref;
|
|
5292
|
+
let linkedEntity;
|
|
5293
|
+
if (typeof tr === "string") {
|
|
5294
|
+
ref = tr;
|
|
5295
|
+
} else if ("ref" in tr) {
|
|
5296
|
+
ref = tr.ref;
|
|
5297
|
+
linkedEntity = tr.linkedEntity;
|
|
5298
|
+
} else {
|
|
5299
|
+
continue;
|
|
5300
|
+
}
|
|
5301
|
+
const parsed = parseImportedTraitRef(ref);
|
|
5302
|
+
if (!parsed) continue;
|
|
5303
|
+
const binding = boundTraitOrbitalBinding(imports, parsed.alias, parsed.traitName);
|
|
5304
|
+
if (!binding) continue;
|
|
5305
|
+
const carriesFields = linkedEntity !== void 0 ? true : binding.entity.name === entity.name;
|
|
5306
|
+
if (!carriesFields) continue;
|
|
5307
|
+
const key = `${parsed.alias}\0${parsed.traitName}`;
|
|
5308
|
+
if (mergedAliases.has(key)) continue;
|
|
5309
|
+
mergedAliases.add(key);
|
|
5310
|
+
pending.push({
|
|
5311
|
+
target: linkedEntity,
|
|
5312
|
+
imported: binding.entity,
|
|
5313
|
+
intrinsicOnly: linkedEntity === void 0,
|
|
5314
|
+
requiredData: binding.requiredData
|
|
5315
|
+
});
|
|
5316
|
+
}
|
|
5317
|
+
for (const pm of pending) {
|
|
5318
|
+
const auxTarget = pm.target !== void 0 && pm.target !== entity.name ? declaredAuxEntities.find((e) => e.name === pm.target) : void 0;
|
|
5319
|
+
mergeImportedEntityFields(auxTarget ?? entity, pm.imported, pm.intrinsicOnly, pm.requiredData);
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
function consumerEntityIdsOf(orbitals) {
|
|
5323
|
+
const out = /* @__PURE__ */ new Map();
|
|
5324
|
+
for (const orbital of orbitals) {
|
|
5325
|
+
for (const entity of inlineEntityRefsOf(orbital)) {
|
|
5326
|
+
if (entity.id) out.set(entity.name, entity.id);
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5329
|
+
return out;
|
|
5330
|
+
}
|
|
5331
|
+
function materializedPrimaryEntity(upstreamEntity, upstreamOrbitalId, ref, localName) {
|
|
5332
|
+
const name = ref.entity ?? `${localName}${upstreamEntity.name}`;
|
|
5333
|
+
const id = asEntityId(
|
|
5334
|
+
deriveMaterializedId(upstreamEntity.id, upstreamOrbitalId, upstreamEntity.name, localName, "entity")
|
|
5335
|
+
);
|
|
5336
|
+
return { name, id };
|
|
5337
|
+
}
|
|
5338
|
+
function applyExtendFields(entity, extend, fieldSubs, consumerEntityIds, localName) {
|
|
5339
|
+
if (!extend || extend.length === 0) return { entity, errors: [] };
|
|
5340
|
+
const errors = [];
|
|
5341
|
+
const taken = new Set(entity.fields.map((f) => f.name).filter((n) => Boolean(n)));
|
|
5342
|
+
for (const target of fieldSubs.values()) taken.add(target);
|
|
5343
|
+
const added = [];
|
|
5344
|
+
for (const field of extend) {
|
|
5345
|
+
const name = field.name;
|
|
5346
|
+
if (!name) continue;
|
|
5347
|
+
if (taken.has(name)) {
|
|
5348
|
+
errors.push(
|
|
5349
|
+
`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)`
|
|
5350
|
+
);
|
|
5351
|
+
continue;
|
|
5352
|
+
}
|
|
5353
|
+
taken.add(name);
|
|
5354
|
+
if (field.type === "relation" && !field.relation.entityId) {
|
|
5355
|
+
const targetId = consumerEntityIds.get(field.relation.entity);
|
|
5356
|
+
added.push(targetId ? { ...field, relation: { ...field.relation, entityId: targetId } } : field);
|
|
5357
|
+
continue;
|
|
5358
|
+
}
|
|
5359
|
+
added.push(field);
|
|
5360
|
+
}
|
|
5361
|
+
if (added.length === 0) return { entity, errors };
|
|
5362
|
+
return { entity: { ...entity, fields: [...entity.fields, ...added] }, errors };
|
|
5363
|
+
}
|
|
5364
|
+
function deriveMaterializedId(sourceId, upstreamOrbitalId, sourceName, localName, kind) {
|
|
5365
|
+
const parent = sourceId ?? `${idPrefix(kind)}orbital-import-seed:${upstreamOrbitalId ?? "no-orbital-id"}:${sourceName}`;
|
|
5366
|
+
return deriveId(parent, localName);
|
|
5367
|
+
}
|
|
5368
|
+
function navigatePathSegments(path) {
|
|
5369
|
+
return path.split("/").filter((segment) => segment.length > 0);
|
|
5370
|
+
}
|
|
5371
|
+
function navigateParamStrippedPrefix(path) {
|
|
5372
|
+
const segments = navigatePathSegments(path);
|
|
5373
|
+
const last = segments[segments.length - 1];
|
|
5374
|
+
if (last === void 0 || !last.startsWith(":")) return void 0;
|
|
5375
|
+
return `/${segments.slice(0, -1).join("/")}/`;
|
|
5376
|
+
}
|
|
5377
|
+
function rewriteConcatPrefix(literalPrefix, pathMap) {
|
|
5378
|
+
const normalized = literalPrefix.endsWith("/") ? literalPrefix : `${literalPrefix}/`;
|
|
5379
|
+
for (const [upstreamPath, finalPath] of pathMap) {
|
|
5380
|
+
const stripped = navigateParamStrippedPrefix(upstreamPath);
|
|
5381
|
+
if (stripped === void 0 || stripped !== normalized) continue;
|
|
5382
|
+
const finalStripped = navigateParamStrippedPrefix(finalPath);
|
|
5383
|
+
if (finalStripped !== void 0) return finalStripped;
|
|
5384
|
+
}
|
|
5385
|
+
return void 0;
|
|
5386
|
+
}
|
|
5387
|
+
function rewriteNavigateTargets(node, pathMap) {
|
|
5388
|
+
if (node === null || node === void 0) return node;
|
|
5389
|
+
if (Array.isArray(node)) {
|
|
5390
|
+
if (node[0] === "navigate" && node.length >= 2) {
|
|
5391
|
+
const target = node[1];
|
|
5392
|
+
if (typeof target === "string" && pathMap.has(target)) {
|
|
5393
|
+
return [node[0], pathMap.get(target), ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
|
|
5394
|
+
}
|
|
5395
|
+
if (Array.isArray(target) && target[0] === "str/concat" && typeof target[1] === "string" && target[1].startsWith("/")) {
|
|
5396
|
+
const rewrittenPrefix = rewriteConcatPrefix(target[1], pathMap);
|
|
5397
|
+
const nextTarget = rewrittenPrefix !== void 0 ? [target[0], rewrittenPrefix, ...target.slice(2)] : target;
|
|
5398
|
+
return [node[0], nextTarget, ...node.slice(2).map((v) => rewriteNavigateTargets(v, pathMap))];
|
|
5399
|
+
}
|
|
5400
|
+
}
|
|
5401
|
+
return node.map((item) => rewriteNavigateTargets(item, pathMap));
|
|
5402
|
+
}
|
|
5403
|
+
if (typeof node !== "object") return node;
|
|
5404
|
+
const next = {};
|
|
5405
|
+
for (const [key, value] of Object.entries(node)) {
|
|
5406
|
+
next[key] = rewriteNavigateTargets(value, pathMap);
|
|
5407
|
+
}
|
|
5408
|
+
return next;
|
|
5409
|
+
}
|
|
5410
|
+
function rewriteTraitNavigateTargets(trait, pathMap) {
|
|
5411
|
+
if (pathMap.size === 0) return trait;
|
|
5412
|
+
const rewrite = (v) => rewriteNavigateTargets(v, pathMap);
|
|
5413
|
+
const next = { ...trait };
|
|
5414
|
+
const sm = trait.stateMachine;
|
|
5415
|
+
if (sm) {
|
|
5416
|
+
next.stateMachine = {
|
|
5417
|
+
...sm,
|
|
5418
|
+
transitions: (sm.transitions ?? []).map(
|
|
5419
|
+
(t) => t.effects ? { ...t, effects: rewrite(t.effects) } : t
|
|
5420
|
+
)
|
|
5421
|
+
};
|
|
5422
|
+
}
|
|
5423
|
+
if (trait.ticks) {
|
|
5424
|
+
next.ticks = trait.ticks.map((tick) => ({ ...tick, effects: rewrite(tick.effects) }));
|
|
5425
|
+
}
|
|
5426
|
+
if (trait.initialEffects) {
|
|
5427
|
+
next.initialEffects = rewrite(trait.initialEffects);
|
|
5428
|
+
}
|
|
5429
|
+
return next;
|
|
5430
|
+
}
|
|
5431
|
+
function rewriteConfigPagePaths(node, pathMap) {
|
|
5432
|
+
if (typeof node === "string") return pathMap.get(node) ?? node;
|
|
5433
|
+
if (Array.isArray(node)) return node.map((item) => rewriteConfigPagePaths(item, pathMap));
|
|
5434
|
+
if (node !== null && typeof node === "object") {
|
|
5435
|
+
const next = {};
|
|
5436
|
+
for (const [key, value] of Object.entries(node)) {
|
|
5437
|
+
next[key] = rewriteConfigPagePaths(value, pathMap);
|
|
5438
|
+
}
|
|
5439
|
+
return next;
|
|
5440
|
+
}
|
|
5441
|
+
return node;
|
|
5442
|
+
}
|
|
5443
|
+
function rewriteTraitConfigPagePaths(trait, pathMap) {
|
|
5444
|
+
if (pathMap.size === 0 || !trait.config) return trait;
|
|
5445
|
+
const nextConfig = {};
|
|
5446
|
+
for (const [key, field] of Object.entries(trait.config)) {
|
|
5447
|
+
nextConfig[key] = field.default === void 0 ? field : { ...field, default: rewriteConfigPagePaths(field.default, pathMap) };
|
|
5448
|
+
}
|
|
5449
|
+
return { ...trait, config: nextConfig };
|
|
5450
|
+
}
|
|
5451
|
+
function foldUseConfigOverride(declared, override, context) {
|
|
5452
|
+
if (!override) return declared;
|
|
5453
|
+
const values = {};
|
|
5454
|
+
for (const [key, field] of Object.entries(override)) {
|
|
5455
|
+
if (!(key in declared)) {
|
|
5456
|
+
refResolverLog.warn("use-config:unknown-knob", { ...context, key });
|
|
5457
|
+
continue;
|
|
5458
|
+
}
|
|
5459
|
+
if (field.default !== void 0) values[key] = field.default;
|
|
5460
|
+
}
|
|
5461
|
+
return Object.keys(values).length > 0 ? overrideDeclaredKnobs(declared, values) : declared;
|
|
5462
|
+
}
|
|
5463
|
+
function forwardConsumerAppKnobs(folded, consumer) {
|
|
5464
|
+
if (!consumer) return folded;
|
|
5465
|
+
const forwards = {};
|
|
5466
|
+
for (const [key, field] of Object.entries(folded)) {
|
|
5467
|
+
const token = field.default;
|
|
5468
|
+
if (typeof token !== "string" || !token.startsWith("@config.")) continue;
|
|
5469
|
+
const source = token.slice("@config.".length);
|
|
5470
|
+
if (source.includes(".") || !(source in consumer)) continue;
|
|
5471
|
+
if (consumer[source].default === void 0) continue;
|
|
5472
|
+
forwards[key] = source;
|
|
5473
|
+
}
|
|
5474
|
+
if (Object.keys(forwards).length === 0) return folded;
|
|
5475
|
+
const next = { ...folded };
|
|
5476
|
+
for (const [key, source] of Object.entries(forwards)) {
|
|
5477
|
+
next[key] = { ...folded[key], default: consumer[source].default, forwardedFrom: `@config.${source}` };
|
|
5478
|
+
}
|
|
5479
|
+
return next;
|
|
5480
|
+
}
|
|
5481
|
+
var ReferenceResolver = class _ReferenceResolver {
|
|
5482
|
+
loader;
|
|
5483
|
+
options;
|
|
5484
|
+
localTraits;
|
|
5485
|
+
/** id-keyed mirror of `localTraits`, populated wherever the trait carries an `id`. */
|
|
5486
|
+
localTraitsById = /* @__PURE__ */ new Map();
|
|
5487
|
+
/** Import scope of each loaded source orbital, keyed by its source path. */
|
|
5488
|
+
sourceImportsCache = /* @__PURE__ */ new Map();
|
|
5489
|
+
/**
|
|
5490
|
+
* {@link preResolveImportFile}'s cache, keyed by absolute source path —
|
|
5491
|
+
* `null` for a file whose own pre-resolution failed (best-effort, cached
|
|
5492
|
+
* too, so a repeat import doesn't retry a doomed resolve). Distinct from
|
|
5493
|
+
* {@link sourceImportsCache} (raw import SCOPE, no trait resolution) —
|
|
5494
|
+
* this holds the file's fully RESOLVED orbitals.
|
|
5495
|
+
*/
|
|
5496
|
+
importFileResolveCache = /* @__PURE__ */ new Map();
|
|
5497
|
+
loaderInitialized = false;
|
|
5498
|
+
/** The schema's declared `config {}` — outermost rung of the forwarded-config chain (§4.5). */
|
|
5499
|
+
schemaConfig;
|
|
5500
|
+
/**
|
|
5501
|
+
* Schema-wide CONSUMER entity NAME → id, growing as each of THIS
|
|
5502
|
+
* schema's own orbitals finishes resolving. JS twin of the compiled
|
|
5503
|
+
* path's `consumer_entity_ids` (`orbital-compiler/src/phases/inline/
|
|
5504
|
+
* mod.rs`), extended the same way: once per orbital, right after it
|
|
5505
|
+
* resolves. Extended ONLY by {@link noteResolvedEntityIds} — called by
|
|
5506
|
+
* the free function {@link resolveSchema} after each of ITS OWN orbitals
|
|
5507
|
+
* finishes — never automatically inside `resolve()` itself, so the
|
|
5508
|
+
* nested `this.resolve()` call {@link materializeOrbitalRef} makes for an
|
|
5509
|
+
* external upstream orbital (a DIFFERENT file, never this consumer
|
|
5510
|
+
* schema) cannot pollute it.
|
|
5511
|
+
*/
|
|
5512
|
+
schemaEntityIds = /* @__PURE__ */ new Map();
|
|
5513
|
+
/**
|
|
5514
|
+
* Entity NAME → id visible to the orbital CURRENTLY being resolved:
|
|
5515
|
+
* {@link schemaEntityIds} (every name an EARLIER orbital in this schema
|
|
5516
|
+
* already established) plus the current orbital's own declared primary +
|
|
5517
|
+
* auxiliary entities — JS twin of the compiled path's per-orbital `entity_
|
|
5518
|
+
* ids = consumer_entity_ids.clone(); entity_ids.extend(collect_orbital_
|
|
5519
|
+
* entity_ids(orbital))`, timed the same way (before this orbital's own
|
|
5520
|
+
* trait composition runs). Read by {@link applyLinkedEntityRename}'s call
|
|
5521
|
+
* sites so a call-site `-> Entity` rebind can REFRESH (never merely drop)
|
|
5522
|
+
* the trait's `entityRefIds` side-map when the rebind target's id is
|
|
5523
|
+
* already known — the gap `std-api-gateway` exposed: `RouteOrbital`'s
|
|
5524
|
+
* no-rebind `Audit.traits.AuditCaptureListener` pull establishes
|
|
5525
|
+
* `AuditEntry`'s id; `GatewayUserOrbital`, resolved LATER in the same
|
|
5526
|
+
* schema, rebinds `Browse.traits.BrowseItemBrowse -> AuditEntry` and must
|
|
5527
|
+
* see it. `resolve()` re-sets this fresh at its own entry (no restore
|
|
5528
|
+
* needed once it returns): nothing reads it once `resolve()` has
|
|
5529
|
+
* returned, and no `resolve()` call is ever active while another is on
|
|
5530
|
+
* this instance — the only recursive `this.resolve()` call
|
|
5531
|
+
* (`materializeOrbitalRef`'s upstream re-resolve) runs strictly BEFORE
|
|
5532
|
+
* `resolveSchema`'s own per-orbital loop begins, never nested inside it.
|
|
5533
|
+
*/
|
|
5534
|
+
entityIdsInScope = /* @__PURE__ */ new Map();
|
|
5535
|
+
/**
|
|
5536
|
+
* Per-orbital name → the FINAL trait names {@link pullSiblingTraits}
|
|
5537
|
+
* auto-pulled for it (`ResolvedOrbital.name` keyed, set once per `resolve()`
|
|
5538
|
+
* call). JS twin of Rust's `pulled_by_orbital` (`inline/mod.rs`) — read by
|
|
5539
|
+
* {@link uniquifyCrossOrbitalPulledSiblings}, run once by the free
|
|
5540
|
+
* function {@link resolveSchema} AFTER every orbital in the schema has
|
|
5541
|
+
* resolved, because the rename decision (does this pulled name collide
|
|
5542
|
+
* with ANOTHER orbital's own declared trait name?) needs the WHOLE
|
|
5543
|
+
* schema's roster, not just this orbital's — exactly why Rust's own
|
|
5544
|
+
* `uniquify_cross_orbital_pulled_siblings` runs once, after its per-orbital
|
|
5545
|
+
* inline loop, not inside `inline_orbital` itself.
|
|
5546
|
+
*/
|
|
5547
|
+
pulledTraitNamesByOrbital = /* @__PURE__ */ new Map();
|
|
5548
|
+
/**
|
|
5549
|
+
* Seed {@link schemaEntityIds} with EVERY orbital's PRIMARY (+ any
|
|
5550
|
+
* already-declared auxiliary) entity name → id, from the RAW pre-resolve
|
|
5551
|
+
* schema — JS twin of the compiled path's `consumer_entity_ids` INITIAL
|
|
5552
|
+
* build (`orbital-compiler/src/phases/inline/mod.rs`, `schema.orbitals
|
|
5553
|
+
* .iter().flat_map(...)`), which scans ALL orbitals' primaries up front,
|
|
5554
|
+
* before ANY of them inlines — not just the ones resolved so far. Without
|
|
5555
|
+
* this, an EARLY-resolved orbital's own `entityRefIds` secondary
|
|
5556
|
+
* references to a LATER orbital's primary entity (`RouteOrbital`'s
|
|
5557
|
+
* `entityRefIds["RateBucket"]`, `RateBucket` being a DIFFERENT, not-yet-
|
|
5558
|
+
* resolved orbital's own primary in `std-api-gateway`) would see nothing
|
|
5559
|
+
* in {@link entityIdsInScope} and {@link consumerKnownEntityRebindSubs}
|
|
5560
|
+
* would never refresh the stale atom-baked id. Called by {@link
|
|
5561
|
+
* resolveSchema} ONCE, before its per-orbital loop begins; {@link
|
|
5562
|
+
* noteResolvedEntityIds} then keeps widening past this seed with each
|
|
5563
|
+
* orbital's post-resolve auxiliary discoveries (Gap #22, sibling pulls),
|
|
5564
|
+
* same as before.
|
|
5565
|
+
*/
|
|
5566
|
+
seedSchemaEntityIds(orbitals) {
|
|
5567
|
+
const next = new Map(this.schemaEntityIds);
|
|
5568
|
+
for (const orbital of orbitals) {
|
|
5569
|
+
for (const e of inlineEntityRefsOf(orbital)) {
|
|
5570
|
+
if (e.id) next.set(e.name, e.id);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
this.schemaEntityIds = next;
|
|
5574
|
+
}
|
|
5575
|
+
/**
|
|
5576
|
+
* Extend {@link schemaEntityIds} with a just-resolved orbital's FINAL
|
|
5577
|
+
* entity set — primary + every auxiliary entity resolution carried in
|
|
5578
|
+
* (including a no-rebind sibling pull's own bound entity,
|
|
5579
|
+
* `ResolvedOrbital.auxiliaryEntities`). Mirrors the compiled path's
|
|
5580
|
+
* `consumer_entity_ids.extend(collect_orbital_entity_ids(orbital))`,
|
|
5581
|
+
* called the same way: once per orbital, immediately after it resolves.
|
|
5582
|
+
* Called by {@link resolveSchema}'s own per-orbital loop only.
|
|
5583
|
+
*/
|
|
5584
|
+
noteResolvedEntityIds(resolved) {
|
|
5585
|
+
const next = new Map(this.schemaEntityIds);
|
|
5586
|
+
if (resolved.entity.id) next.set(resolved.entity.name, resolved.entity.id);
|
|
5587
|
+
for (const aux of resolved.auxiliaryEntities ?? []) {
|
|
5588
|
+
if (aux.id) next.set(aux.name, aux.id);
|
|
5589
|
+
}
|
|
5590
|
+
this.schemaEntityIds = next;
|
|
5591
|
+
}
|
|
5592
|
+
/**
|
|
5593
|
+
* Make auto-pulled sibling traits app-unique across orbitals — JS twin of
|
|
5594
|
+
* Rust's `uniquify_cross_orbital_pulled_siblings` (`inline/mod.rs`), called
|
|
5595
|
+
* by the free function {@link resolveSchema} once every orbital in the
|
|
5596
|
+
* schema has resolved (mirroring Rust's own post-per-orbital-loop timing:
|
|
5597
|
+
* the rename decision needs the WHOLE schema's trait-name roster, built
|
|
5598
|
+
* fresh here rather than grown incrementally like {@link schemaEntityIds}).
|
|
5599
|
+
* An auto-pulled sibling keeps its source name within its OWN orbital, so a
|
|
5600
|
+
* `@trait.<Sibling>` reference inside that orbital still resolves — but
|
|
5601
|
+
* when TWO orbitals in the same schema each declare (pulled OR explicit) a
|
|
5602
|
+
* trait of the SAME name, that name collides app-wide. Only renames a
|
|
5603
|
+
* PULLED copy (never an explicitly-authored trait ref —
|
|
5604
|
+
* {@link pulledTraitNamesByOrbital} is the eligibility set) whose name is
|
|
5605
|
+
* ALSO declared by at least one OTHER orbital, prefixing it with the
|
|
5606
|
+
* owning orbital's own name; the prefixed name must itself be free
|
|
5607
|
+
* schema-wide or the rename is skipped (matches Rust: a collision on the
|
|
5608
|
+
* PREFIXED name is left for the validator, never silently double-renamed).
|
|
5609
|
+
* Mutates `orbitals`' traits in place, same mutation style as
|
|
5610
|
+
* {@link pullSiblingTraits}.
|
|
5611
|
+
*/
|
|
5612
|
+
uniquifyCrossOrbitalPulledSiblings(orbitals) {
|
|
5613
|
+
if (this.pulledTraitNamesByOrbital.size === 0) return;
|
|
5614
|
+
const nameOrbitalCount = /* @__PURE__ */ new Map();
|
|
5615
|
+
for (const orbital of orbitals) {
|
|
5616
|
+
const local = new Set(
|
|
5617
|
+
orbital.traits.map((rt) => rt.trait.name).filter((n) => Boolean(n))
|
|
5618
|
+
);
|
|
5619
|
+
for (const name of local) {
|
|
5620
|
+
nameOrbitalCount.set(name, (nameOrbitalCount.get(name) ?? 0) + 1);
|
|
5621
|
+
}
|
|
5622
|
+
}
|
|
5623
|
+
for (const orbital of orbitals) {
|
|
5624
|
+
const pulledNames = this.pulledTraitNamesByOrbital.get(orbital.name);
|
|
5625
|
+
if (!pulledNames || pulledNames.size === 0) continue;
|
|
5626
|
+
const renames = /* @__PURE__ */ new Map();
|
|
5627
|
+
for (const oldName of pulledNames) {
|
|
5628
|
+
if ((nameOrbitalCount.get(oldName) ?? 0) <= 1) continue;
|
|
5629
|
+
const newName = `${orbital.name}${oldName}`;
|
|
5630
|
+
if (nameOrbitalCount.has(newName)) continue;
|
|
5631
|
+
renames.set(oldName, newName);
|
|
5632
|
+
}
|
|
5633
|
+
if (renames.size === 0) continue;
|
|
5634
|
+
for (const rt of orbital.traits) {
|
|
5635
|
+
if (rt.trait.name && renames.has(rt.trait.name)) {
|
|
5636
|
+
rt.trait = { ...rt.trait, name: renames.get(rt.trait.name) };
|
|
5637
|
+
}
|
|
5638
|
+
}
|
|
5639
|
+
const idByName = /* @__PURE__ */ new Map();
|
|
5640
|
+
for (const rt of orbital.traits) {
|
|
5641
|
+
if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
|
|
5642
|
+
}
|
|
5643
|
+
for (const rt of orbital.traits) {
|
|
5644
|
+
rt.trait = renameTraitEmbeds(rt.trait, renames);
|
|
5645
|
+
rt.trait = rewriteListenSources(rt.trait, renames, idByName);
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
constructor(options) {
|
|
5650
|
+
this.options = options;
|
|
5651
|
+
this.loader = options.loader;
|
|
5652
|
+
this.schemaConfig = options.schemaConfig;
|
|
5653
|
+
this.localTraits = options.localTraits ?? /* @__PURE__ */ new Map();
|
|
5654
|
+
for (const trait of this.localTraits.values()) {
|
|
5655
|
+
if (trait.id) {
|
|
5656
|
+
this.localTraitsById.set(trait.id, trait);
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
async ensureLoader() {
|
|
5661
|
+
if (this.loader || this.loaderInitialized) return;
|
|
5662
|
+
this.loaderInitialized = true;
|
|
5663
|
+
try {
|
|
5664
|
+
const { ExternalOrbitalLoader } = await import('./external-loader-CISUEINQ.js');
|
|
5665
|
+
this.loader = new ExternalOrbitalLoader(this.options);
|
|
5666
|
+
} catch {
|
|
5667
|
+
}
|
|
5668
|
+
}
|
|
5669
|
+
/**
|
|
5670
|
+
* Resolve all references in an orbital.
|
|
5671
|
+
*/
|
|
5672
|
+
async resolve(orbital, sourcePath, chain, opts) {
|
|
5673
|
+
const errors = [];
|
|
5674
|
+
const warnings = [];
|
|
5675
|
+
const importChain = chain ?? { push: () => null, pop: () => {
|
|
5676
|
+
}, clone() {
|
|
5677
|
+
return this;
|
|
5678
|
+
} };
|
|
5679
|
+
this.entityIdsInScope = new Map([...this.schemaEntityIds, ...inlineEntityRefsOf(orbital).flatMap((e) => e.id ? [[e.name, e.id]] : [])]);
|
|
5680
|
+
const traitsList = orbital.traits ?? [];
|
|
5681
|
+
const alreadyResolved = traitsList.length > 0 && traitsList.every((t) => isInlineTrait(t));
|
|
5682
|
+
const importsResult = alreadyResolved ? { success: true, data: { orbitals: /* @__PURE__ */ new Map(), idIndex: /* @__PURE__ */ new Map() }} : await this.resolveImports(orbital.uses ?? [], sourcePath, importChain);
|
|
5683
|
+
if (!importsResult.success) {
|
|
5684
|
+
return { success: false, errors: importsResult.errors };
|
|
5685
|
+
}
|
|
5686
|
+
const imports = importsResult.data;
|
|
5687
|
+
imports.idIndex = buildIdIndex(orbital, imports.orbitals);
|
|
5688
|
+
const gap22AuxEntities = auxEntitiesFromUnrebindTraitRefs(orbital.traits ?? [], imports);
|
|
5689
|
+
if (gap22AuxEntities.length > 0) {
|
|
5690
|
+
const next = new Map(this.entityIdsInScope);
|
|
5691
|
+
for (const e of gap22AuxEntities) {
|
|
5692
|
+
if (e.id && !next.has(e.name)) next.set(e.name, e.id);
|
|
5693
|
+
}
|
|
5694
|
+
this.entityIdsInScope = next;
|
|
5695
|
+
}
|
|
5696
|
+
if (isInlineEntity(orbital.entity)) {
|
|
5697
|
+
mergeImportedEntityFieldsIntoOrbital(
|
|
5698
|
+
orbital.traits ?? [],
|
|
5699
|
+
orbital.entity,
|
|
5700
|
+
(orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
|
|
5701
|
+
imports
|
|
5702
|
+
);
|
|
5703
|
+
}
|
|
5704
|
+
const entityResult = this.resolveEntity(orbital.entity, imports);
|
|
5705
|
+
if (!entityResult.success) {
|
|
5706
|
+
errors.push(...entityResult.errors);
|
|
5707
|
+
}
|
|
5708
|
+
const traitsResult = await this.resolveTraits(orbital.traits, imports, importChain, orbital.config);
|
|
5709
|
+
if (!traitsResult.success) {
|
|
5710
|
+
errors.push(...traitsResult.errors);
|
|
5711
|
+
}
|
|
5712
|
+
const pagesResult = await this.resolvePages(orbital.pages, imports, importChain);
|
|
5713
|
+
if (!pagesResult.success) {
|
|
5714
|
+
errors.push(...pagesResult.errors);
|
|
5715
|
+
}
|
|
5716
|
+
if (errors.length > 0) {
|
|
5717
|
+
return { success: false, errors };
|
|
5718
|
+
}
|
|
5719
|
+
if (!entityResult.success || !traitsResult.success || !pagesResult.success) {
|
|
5720
|
+
return { success: false, errors: ["Internal error: unexpected failure state"] };
|
|
5721
|
+
}
|
|
5722
|
+
const { errors: pullErrors, auxEntities: pulledAuxEntities, pulledNames } = await this.pullSiblingTraits(
|
|
5723
|
+
traitsResult.data,
|
|
5724
|
+
imports,
|
|
5725
|
+
importChain,
|
|
5726
|
+
orbital.config
|
|
5727
|
+
);
|
|
5728
|
+
if (pullErrors.length > 0) {
|
|
4266
5729
|
return { success: false, errors: pullErrors };
|
|
4267
5730
|
}
|
|
5731
|
+
this.pulledTraitNamesByOrbital.set(orbital.name, pulledNames);
|
|
5732
|
+
const known = /* @__PURE__ */ new Set([entityResult.data.entity.name]);
|
|
5733
|
+
const declaredAux = (orbital.auxiliaryEntities ?? []).filter(isInlineEntity);
|
|
5734
|
+
for (const e of declaredAux) known.add(e.name);
|
|
5735
|
+
const combined = [...declaredAux];
|
|
5736
|
+
for (const e of [...gap22AuxEntities, ...pulledAuxEntities]) {
|
|
5737
|
+
if (!known.has(e.name)) {
|
|
5738
|
+
known.add(e.name);
|
|
5739
|
+
combined.push(e);
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
const resolvedAuxEntities = combined.length > 0 ? combined : void 0;
|
|
4268
5743
|
for (const resolvedTrait of traitsResult.data) {
|
|
4269
5744
|
resolvedTrait.trait = resolveEntityTokensById(resolvedTrait.trait, imports.idIndex);
|
|
4270
5745
|
resolvedTrait.trait = resolveConfigRefsById(resolvedTrait.trait, imports.idIndex);
|
|
@@ -4277,6 +5752,14 @@ var ReferenceResolver = class {
|
|
|
4277
5752
|
}
|
|
4278
5753
|
throw e;
|
|
4279
5754
|
}
|
|
5755
|
+
if (!opts?.skipTypeParamSentinels) {
|
|
5756
|
+
resolveOrbitalTypeParamSentinels(
|
|
5757
|
+
traitsResult.data,
|
|
5758
|
+
entityResult.data.entity,
|
|
5759
|
+
resolvedAuxEntities ?? [],
|
|
5760
|
+
orbital.types
|
|
5761
|
+
);
|
|
5762
|
+
}
|
|
4280
5763
|
return {
|
|
4281
5764
|
success: true,
|
|
4282
5765
|
data: {
|
|
@@ -4284,6 +5767,7 @@ var ReferenceResolver = class {
|
|
|
4284
5767
|
entity: entityResult.data.entity,
|
|
4285
5768
|
entitySource: entityResult.data.source,
|
|
4286
5769
|
traits: traitsResult.data,
|
|
5770
|
+
...resolvedAuxEntities ? { auxiliaryEntities: resolvedAuxEntities } : {},
|
|
4287
5771
|
pages: pagesResult.data,
|
|
4288
5772
|
imports,
|
|
4289
5773
|
original: orbital
|
|
@@ -4291,6 +5775,98 @@ var ReferenceResolver = class {
|
|
|
4291
5775
|
warnings
|
|
4292
5776
|
};
|
|
4293
5777
|
}
|
|
5778
|
+
/**
|
|
5779
|
+
* Pre-resolve one imported FILE's own orbitals to completion — its own
|
|
5780
|
+
* `uses` (recursively, through THIS same method), its own trait refs,
|
|
5781
|
+
* its own sibling pulls, its own entity-ref-id rebinds — BEFORE the
|
|
5782
|
+
* consumer that names this alias ever folds or pulls from it. JS twin
|
|
5783
|
+
* of Rust's per-`uses` recursive `inline_orbital` call (`orbital-
|
|
5784
|
+
* compiler/src/phases/inline/mod.rs:1001-1013`): every `uses` alias's
|
|
5785
|
+
* OWN orbitals are inlined to completion, ahead of `ctx.add_alias_multi`
|
|
5786
|
+
* registering the alias for the consumer's own lookups. Without this, a
|
|
5787
|
+
* sibling-pull collision that is a genuine top-level PEER collision
|
|
5788
|
+
* INSIDE the imported file (`std-approval-request.orb`'s
|
|
5789
|
+
* `InlineBrowseItemBrowse6`/`…10`, both `ref: Dense.traits.
|
|
5790
|
+
* BrowseItemBrowse`, each embedding `@trait.DataGrid1`) never becomes
|
|
5791
|
+
* visible as a peer collision to the CONSUMER's own {@link
|
|
5792
|
+
* pullSiblingTraits} call — it arrives already flattened one level
|
|
5793
|
+
* deeper, sharing one JS-visible owner (see that method's own
|
|
5794
|
+
* drain-order doc for the full trace this ports).
|
|
5795
|
+
*
|
|
5796
|
+
* Cached per absolute `sourcePath` ({@link importFileResolveCache}) —
|
|
5797
|
+
* "a file imported twice resolves once" — so the cache must not bake in
|
|
5798
|
+
* any ONE call site's `uses { config }` override: the child resolver
|
|
5799
|
+
* below is seeded with this FILE's own raw, un-folded `config {}`
|
|
5800
|
+
* (`fileSchemaConfig`), never a folded override. A genuinely
|
|
5801
|
+
* call-site-configured explicit ref (`Alias.traits.X { config: {…} }`)
|
|
5802
|
+
* still resolves through the pre-existing lazy path
|
|
5803
|
+
* ({@link resolveTraitEntry} / {@link resolveTraitRefString}), which
|
|
5804
|
+
* this cache does not touch.
|
|
5805
|
+
*
|
|
5806
|
+
* Runs on a FRESH child `ReferenceResolver`, never `this` — `resolve()`'s
|
|
5807
|
+
* own `entityIdsInScope` / `schemaEntityIds` / `pulledTraitNamesByOrbital`
|
|
5808
|
+
* are single mutable instance state scoped to ONE active `resolve()` call
|
|
5809
|
+
* tree (see {@link entityIdsInScope}'s own doc: "no `resolve()` call is
|
|
5810
|
+
* ever active while another is on this instance"); reusing `this` here
|
|
5811
|
+
* would nest a `resolve()` call inside the CONSUMER's own still-active
|
|
5812
|
+
* `resolve()` → `resolveImports` call and corrupt that state once this
|
|
5813
|
+
* nested call returns. The child reuses `this.loader` (and therefore its
|
|
5814
|
+
* underlying `LoaderCache`) so raw parsing still dedupes exactly as
|
|
5815
|
+
* before. `chain` is threaded through unchanged (not cloned, matching
|
|
5816
|
+
* every other cross-call `chain` hand-off in this file) so genuine `uses`
|
|
5817
|
+
* cycles are still caught by the loader.
|
|
5818
|
+
*
|
|
5819
|
+
* Mirrors {@link resolveSchema}'s own orchestration (flatten orbital
|
|
5820
|
+
* references → collect local traits → seed schema entity ids →
|
|
5821
|
+
* per-orbital `resolve()` → `uniquifyCrossOrbitalPulledSiblings`) rather
|
|
5822
|
+
* than calling that free function directly — it accepts no `chain`
|
|
5823
|
+
* parameter, so a direct call would silently drop cycle protection one
|
|
5824
|
+
* level in.
|
|
5825
|
+
*
|
|
5826
|
+
* Best-effort: returns `null` (never throws) on any failure — a caller
|
|
5827
|
+
* falls back to the pre-existing raw-ref walk, matching this file's
|
|
5828
|
+
* other best-effort pre-passes (e.g. {@link precomputeReferenceFormPrimaryIds}).
|
|
5829
|
+
*/
|
|
5830
|
+
async preResolveImportFile(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
|
|
5831
|
+
const cached = this.importFileResolveCache.get(sourcePath);
|
|
5832
|
+
if (cached !== void 0) return cached;
|
|
5833
|
+
let result;
|
|
5834
|
+
try {
|
|
5835
|
+
result = await this.preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain);
|
|
5836
|
+
} catch {
|
|
5837
|
+
result = null;
|
|
5838
|
+
}
|
|
5839
|
+
this.importFileResolveCache.set(sourcePath, result);
|
|
5840
|
+
return result;
|
|
5841
|
+
}
|
|
5842
|
+
async preResolveImportFileUncached(fileOrbitals, sourcePath, fileSchemaConfig, chain) {
|
|
5843
|
+
const child = new _ReferenceResolver({
|
|
5844
|
+
...this.options,
|
|
5845
|
+
loader: this.loader,
|
|
5846
|
+
schemaConfig: fileSchemaConfig
|
|
5847
|
+
});
|
|
5848
|
+
const fileSchema = {
|
|
5849
|
+
name: sourcePath,
|
|
5850
|
+
orbitals: fileOrbitals,
|
|
5851
|
+
...fileSchemaConfig ? { config: fileSchemaConfig } : {}
|
|
5852
|
+
};
|
|
5853
|
+
const flattenResult = await child.resolveOrbitalImports(fileSchema, { skipTypeParamSentinels: true });
|
|
5854
|
+
if (!flattenResult.success) return null;
|
|
5855
|
+
const orbitals = flattenResult.data;
|
|
5856
|
+
const inlineTraits = orbitals.flatMap(
|
|
5857
|
+
(o) => o.traits.filter((t) => typeof t !== "string" && "stateMachine" in t)
|
|
5858
|
+
);
|
|
5859
|
+
child.addLocalTraits(inlineTraits);
|
|
5860
|
+
child.seedSchemaEntityIds(orbitals);
|
|
5861
|
+
const resolved = [];
|
|
5862
|
+
for (const orbital of orbitals) {
|
|
5863
|
+
const result = await child.resolve(orbital, sourcePath, chain, { skipTypeParamSentinels: true });
|
|
5864
|
+
if (!result.success) return null;
|
|
5865
|
+
resolved.push(result.data);
|
|
5866
|
+
child.noteResolvedEntityIds(result.data);
|
|
5867
|
+
}
|
|
5868
|
+
return resolved;
|
|
5869
|
+
}
|
|
4294
5870
|
/**
|
|
4295
5871
|
* Resolve `uses` declarations to loaded orbitals.
|
|
4296
5872
|
*/
|
|
@@ -4304,6 +5880,10 @@ var ReferenceResolver = class {
|
|
|
4304
5880
|
warnings: ["External loading skipped"]
|
|
4305
5881
|
};
|
|
4306
5882
|
}
|
|
5883
|
+
const effectiveChain = chain ?? { push: () => null, pop: () => {
|
|
5884
|
+
}, clone() {
|
|
5885
|
+
return this;
|
|
5886
|
+
} };
|
|
4307
5887
|
for (const use of uses) {
|
|
4308
5888
|
if (orbitals.has(use.as)) {
|
|
4309
5889
|
errors.push(`Duplicate import alias: ${use.as}`);
|
|
@@ -4318,18 +5898,32 @@ var ReferenceResolver = class {
|
|
|
4318
5898
|
use.from,
|
|
4319
5899
|
void 0,
|
|
4320
5900
|
sourcePath,
|
|
4321
|
-
|
|
5901
|
+
effectiveChain
|
|
4322
5902
|
);
|
|
4323
5903
|
if (!loadResult.success) {
|
|
4324
5904
|
errors.push(`Failed to load "${use.from}" as "${use.as}": ${loadResult.error}`);
|
|
4325
5905
|
continue;
|
|
4326
5906
|
}
|
|
5907
|
+
const fileOrbitals = loadResult.data.orbitals ?? [loadResult.data.orbital];
|
|
5908
|
+
const resolvedOrbitals = await this.preResolveImportFile(
|
|
5909
|
+
fileOrbitals,
|
|
5910
|
+
loadResult.data.sourcePath,
|
|
5911
|
+
loadResult.data.schemaConfig,
|
|
5912
|
+
effectiveChain
|
|
5913
|
+
);
|
|
4327
5914
|
orbitals.set(use.as, {
|
|
4328
5915
|
alias: use.as,
|
|
4329
5916
|
from: use.from,
|
|
4330
5917
|
orbital: loadResult.data.orbital,
|
|
4331
|
-
orbitals:
|
|
4332
|
-
sourcePath: loadResult.data.sourcePath
|
|
5918
|
+
orbitals: fileOrbitals,
|
|
5919
|
+
sourcePath: loadResult.data.sourcePath,
|
|
5920
|
+
...resolvedOrbitals ? { resolvedOrbitals } : {},
|
|
5921
|
+
...loadResult.data.schemaConfig ? {
|
|
5922
|
+
schemaConfig: forwardConsumerAppKnobs(
|
|
5923
|
+
foldUseConfigOverride(loadResult.data.schemaConfig, use.config, use),
|
|
5924
|
+
this.schemaConfig
|
|
5925
|
+
)
|
|
5926
|
+
} : {}
|
|
4333
5927
|
});
|
|
4334
5928
|
}
|
|
4335
5929
|
if (errors.length > 0) {
|
|
@@ -4420,14 +6014,79 @@ var ReferenceResolver = class {
|
|
|
4420
6014
|
}
|
|
4421
6015
|
return entityRef;
|
|
4422
6016
|
}
|
|
6017
|
+
/**
|
|
6018
|
+
* The ATOM's OWN trait `alias.traits.traitName` resolves to — no call-site
|
|
6019
|
+
* overrides applied (`callSiteConfig` omitted) — so its DECLARED
|
|
6020
|
+
* `linkedEntity` can drive {@link buildAliasEntityRenames}. Same lookup
|
|
6021
|
+
* `resolveTraitRefString`'s imported branch performs to find the base
|
|
6022
|
+
* `trait` before any rebind, factored out so the pre-pass and the main
|
|
6023
|
+
* resolve share one lookup rather than two. `null` when the alias or
|
|
6024
|
+
* trait cannot be found — the pre-pass simply skips that entry, same as a
|
|
6025
|
+
* lookup failure anywhere else in this best-effort pass.
|
|
6026
|
+
*/
|
|
6027
|
+
async atomOwnTrait(alias, traitName, imports, chain) {
|
|
6028
|
+
const imported = imports.orbitals.get(alias);
|
|
6029
|
+
if (!imported) return null;
|
|
6030
|
+
for (const o of importedOrbitals(imported)) {
|
|
6031
|
+
const entry = findTraitEntryInOrbital(o, traitName);
|
|
6032
|
+
if (!entry) continue;
|
|
6033
|
+
const entryResolved = await this.resolveTraitEntry(imported, entry, traitName, chain, imports);
|
|
6034
|
+
return entryResolved.success ? entryResolved.data.trait : null;
|
|
6035
|
+
}
|
|
6036
|
+
return null;
|
|
6037
|
+
}
|
|
6038
|
+
/**
|
|
6039
|
+
* Alias-scoped cross-trait entity-rebind propagation — JS twin of Rust's
|
|
6040
|
+
* `alias_entity_renames` pre-pass (`inline/trait.rs::inline_traits`). One
|
|
6041
|
+
* explicit pull's `linkedEntity` override (`Button.traits.ButtonRender ->
|
|
6042
|
+
* Route`) establishes a rebind (the atom's OWN declared `linkedEntity` →
|
|
6043
|
+
* the override) that a SIBLING pull from the SAME alias with NO rebind of
|
|
6044
|
+
* its own (`Button.traits.ButtonRender`, no `->`) never sees through
|
|
6045
|
+
* {@link applyLinkedEntityRename} — that call only ever knows ITS OWN
|
|
6046
|
+
* delta. But the no-rebind pull's `entityRefIds` side-map can still carry
|
|
6047
|
+
* a SECONDARY, positional reference to that same atom-local name (a
|
|
6048
|
+
* "self" entry keyed by the atom's own bound entity), which nothing else
|
|
6049
|
+
* rewrites — `std-api-gateway`'s `RouteOrbital.InlineButtonRender3`
|
|
6050
|
+
* (`Button.traits.ButtonRender`, no rebind) recovers `entityRefIds`'
|
|
6051
|
+
* `ButtonItem` key to `Route` only because `InlineButtonRender9` (`Button.
|
|
6052
|
+
* traits.ButtonRender -> Route`) established the rebind earlier in the
|
|
6053
|
+
* SAME orbital's `traits` list. Scanned once per orbital, over every
|
|
6054
|
+
* EXPLICIT `Alias.traits.X -> Y` entry in `traitRefs`: `(alias, atom's
|
|
6055
|
+
* declared linkedEntity) -> override`. First rebind for a given `(alias,
|
|
6056
|
+
* atomLocal)` pair wins (`Map.set` only on a fresh key), matching Rust's
|
|
6057
|
+
* `.or_insert_with`.
|
|
6058
|
+
*/
|
|
6059
|
+
async buildAliasEntityRenames(traitRefs, imports, chain) {
|
|
6060
|
+
const out = /* @__PURE__ */ new Map();
|
|
6061
|
+
for (const traitRef of traitRefs) {
|
|
6062
|
+
if (typeof traitRef === "string" || "stateMachine" in traitRef || !("ref" in traitRef)) continue;
|
|
6063
|
+
const refObj = traitRef;
|
|
6064
|
+
if (!refObj.linkedEntity) continue;
|
|
6065
|
+
const parsed = parseImportedTraitRef(refObj.ref);
|
|
6066
|
+
if (!parsed) continue;
|
|
6067
|
+
const atomTrait = await this.atomOwnTrait(parsed.alias, parsed.traitName, imports, chain);
|
|
6068
|
+
const atomLocal = atomTrait?.linkedEntity;
|
|
6069
|
+
if (!atomLocal || atomLocal === refObj.linkedEntity) continue;
|
|
6070
|
+
const forAlias = out.get(parsed.alias) ?? /* @__PURE__ */ new Map();
|
|
6071
|
+
if (!forAlias.has(atomLocal)) forAlias.set(atomLocal, refObj.linkedEntity);
|
|
6072
|
+
out.set(parsed.alias, forAlias);
|
|
6073
|
+
}
|
|
6074
|
+
return out;
|
|
6075
|
+
}
|
|
4423
6076
|
/**
|
|
4424
6077
|
* Resolve trait references.
|
|
4425
6078
|
*/
|
|
4426
|
-
resolveTraits(traitRefs, imports) {
|
|
6079
|
+
async resolveTraits(traitRefs, imports, chain, orbitalConfig) {
|
|
4427
6080
|
const errors = [];
|
|
4428
6081
|
const resolved = [];
|
|
6082
|
+
const embedCtx = {
|
|
6083
|
+
traitRefs,
|
|
6084
|
+
embedGraph: buildEmbedGraph(traitRefs),
|
|
6085
|
+
orbitalConfig
|
|
6086
|
+
};
|
|
6087
|
+
const aliasEntityRenames = await this.buildAliasEntityRenames(traitRefs, imports, chain);
|
|
4429
6088
|
for (const traitRef of traitRefs) {
|
|
4430
|
-
const result = this.resolveTraitRef(traitRef, imports);
|
|
6089
|
+
const result = await this.resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames);
|
|
4431
6090
|
if (!result.success) {
|
|
4432
6091
|
errors.push(...result.errors);
|
|
4433
6092
|
} else {
|
|
@@ -4458,6 +6117,99 @@ var ReferenceResolver = class {
|
|
|
4458
6117
|
this.sourceImportsCache.set(key, result.data);
|
|
4459
6118
|
return result.data;
|
|
4460
6119
|
}
|
|
6120
|
+
/**
|
|
6121
|
+
* The concrete base `Trait` a trait entry (found under `localName` in
|
|
6122
|
+
* `imported`) resolves to — an inline entry resolves its own
|
|
6123
|
+
* `@config.<knob>` emit refs against `callSiteConfig` (the ref hop that
|
|
6124
|
+
* led here, e.g. `std-approval-gate`'s `CloseButton = Button.traits.
|
|
6125
|
+
* ButtonRender { config: { action: CLOSE } }` resolving `ButtonRender`
|
|
6126
|
+
* itself); a ref-shaped entry (an atom's sub-view declared `trait X =
|
|
6127
|
+
* Y.traits.Z {…}` INSIDE the source atom, e.g. `std-note`'s
|
|
6128
|
+
* `NoteSubpages = RecordDetail.traits.RecordItemDetail`) recurses through
|
|
6129
|
+
* that source's own import scope via {@link importsOfSource} — the
|
|
6130
|
+
* entry's own declared overrides are its call site. Single owner for
|
|
6131
|
+
* `pullSiblingTraits`' sibling pull and `resolveTraitRefString`'s
|
|
6132
|
+
* imported branch, both of which used to reach `findTraitInOrbital`'s
|
|
6133
|
+
* `stateMachine`-gated lookup (its ref arm did nothing), silently failing
|
|
6134
|
+
* to resolve a nested ref (ledger (i)).
|
|
6135
|
+
*
|
|
6136
|
+
* `callSiteConfig` MUST be threaded by any caller that goes on to fold a
|
|
6137
|
+
* call-site config of its own onto the returned trait
|
|
6138
|
+
* (`resolveTraitRefString`'s ref-imported branch, ledger (o)) — the
|
|
6139
|
+
* `@config.<knob>` emit-name substitution is destructive
|
|
6140
|
+
* (`resolveConfigRefEmitNames` rewrites the marker to a concrete literal
|
|
6141
|
+
* in place), so resolving it here with the WRONG effective config
|
|
6142
|
+
* (the atom's own bare default, absent the override) permanently loses
|
|
6143
|
+
* the override: a second `resolveConfigRefEmitNames` call downstream sees
|
|
6144
|
+
* no more `@config.<knob>` marker to substitute and silently no-ops.
|
|
6145
|
+
* `pullSiblingTraits` (no further fold of its own) omits it, matching its
|
|
6146
|
+
* prior no-callSiteConfig behavior exactly.
|
|
6147
|
+
*/
|
|
6148
|
+
async resolveTraitEntry(imported, entry, localName, chain, homeImports, callSiteConfig) {
|
|
6149
|
+
if ("stateMachine" in entry) {
|
|
6150
|
+
const { trait, errors } = resolveConfigRefEmitNames(entry, callSiteConfig);
|
|
6151
|
+
if (errors.length > 0) return { success: false, errors };
|
|
6152
|
+
return {
|
|
6153
|
+
success: true,
|
|
6154
|
+
data: { trait, embedScope: { imports: homeImports, alias: imported.alias } },
|
|
6155
|
+
warnings: []
|
|
6156
|
+
};
|
|
6157
|
+
}
|
|
6158
|
+
const refObj = entry;
|
|
6159
|
+
const srcImports = await this.importsOfSource(imported, chain);
|
|
6160
|
+
if (!srcImports) {
|
|
6161
|
+
return {
|
|
6162
|
+
success: false,
|
|
6163
|
+
errors: [
|
|
6164
|
+
`Trait "${localName}" in imported behavior could not resolve its own import scope to follow ref "${refObj.ref}"`
|
|
6165
|
+
]
|
|
6166
|
+
};
|
|
6167
|
+
}
|
|
6168
|
+
const nested = await this.resolveTraitRefString(
|
|
6169
|
+
refObj.ref,
|
|
6170
|
+
srcImports,
|
|
6171
|
+
chain,
|
|
6172
|
+
refObj.config,
|
|
6173
|
+
refObj.linkedEntity,
|
|
6174
|
+
refObj.name ?? localName,
|
|
6175
|
+
refObj.events,
|
|
6176
|
+
refObj.listens,
|
|
6177
|
+
refObj.refId,
|
|
6178
|
+
refObj.typeArgs
|
|
6179
|
+
);
|
|
6180
|
+
if (!nested.success) return nested;
|
|
6181
|
+
return {
|
|
6182
|
+
success: true,
|
|
6183
|
+
data: {
|
|
6184
|
+
trait: nested.data.trait,
|
|
6185
|
+
embedScope: nested.data.embedScope ?? { imports: srcImports, alias: imported.alias },
|
|
6186
|
+
...nested.data.typeArgs !== void 0 ? { typeArgs: nested.data.typeArgs } : {}
|
|
6187
|
+
},
|
|
6188
|
+
warnings: nested.warnings
|
|
6189
|
+
};
|
|
6190
|
+
}
|
|
6191
|
+
/**
|
|
6192
|
+
* The concrete `Page` a page entry (found under `localName` in `imported`)
|
|
6193
|
+
* resolves to — an inline `Page` passes through; a `PageRefObject` (a
|
|
6194
|
+
* re-exported page declared inside the SOURCE orbital's own `pages {}`,
|
|
6195
|
+
* {@link findPageEntryInOrbital}'s ref arm) recurses through that source's
|
|
6196
|
+
* own import scope via {@link importsOfSource} and
|
|
6197
|
+
* {@link resolvePageRefObject} — the page twin of {@link resolveTraitEntry}
|
|
6198
|
+
* (nested refs, ledger (i)).
|
|
6199
|
+
*/
|
|
6200
|
+
async resolvePageEntry(imported, entry, chain) {
|
|
6201
|
+
if (!("ref" in entry)) return { success: true, data: { page: entry }, warnings: [] };
|
|
6202
|
+
const srcImports = await this.importsOfSource(imported, chain);
|
|
6203
|
+
if (!srcImports) {
|
|
6204
|
+
return {
|
|
6205
|
+
success: false,
|
|
6206
|
+
errors: [`Page in imported behavior could not resolve its own import scope to follow ref "${entry.ref}"`]
|
|
6207
|
+
};
|
|
6208
|
+
}
|
|
6209
|
+
const nested = await this.resolvePageRefObject(entry, srcImports, chain);
|
|
6210
|
+
if (!nested.success) return nested;
|
|
6211
|
+
return { success: true, data: { page: nested.data.page }, warnings: nested.warnings };
|
|
6212
|
+
}
|
|
4461
6213
|
/**
|
|
4462
6214
|
* Sibling-trait auto-pull — the JS twin of the compiler's
|
|
4463
6215
|
* `phases/inline/trait.rs` pass, appending to `resolved` in place.
|
|
@@ -4479,7 +6231,8 @@ var ReferenceResolver = class {
|
|
|
4479
6231
|
* source name; later owners pull under `<Owner><Sibling>` — unique by
|
|
4480
6232
|
* construction, since owner names are unique within the orbital.
|
|
4481
6233
|
*/
|
|
4482
|
-
async pullSiblingTraits(resolved, imports, chain) {
|
|
6234
|
+
async pullSiblingTraits(resolved, imports, chain, orbitalConfig) {
|
|
6235
|
+
const auxEntities = [];
|
|
4483
6236
|
const work = [];
|
|
4484
6237
|
const ownerSubs = /* @__PURE__ */ new Map();
|
|
4485
6238
|
const subsFor = (owner) => {
|
|
@@ -4495,18 +6248,48 @@ var ReferenceResolver = class {
|
|
|
4495
6248
|
const owner = rt.trait.name;
|
|
4496
6249
|
subsFor(owner).set(rt.source.traitName, owner);
|
|
4497
6250
|
for (const sibling of traitEmbedNamesOf(rt.trait)) {
|
|
4498
|
-
work.push({
|
|
6251
|
+
work.push({
|
|
6252
|
+
alias: rt.source.alias,
|
|
6253
|
+
fallback: rt.embedScope,
|
|
6254
|
+
sibling,
|
|
6255
|
+
linkedEntity: rt.linkedEntity,
|
|
6256
|
+
parent: owner,
|
|
6257
|
+
owner,
|
|
6258
|
+
// Top-level SEED — always starts with the raw-walk-first gate
|
|
6259
|
+
// (see {@link PullItem.preResolvedScope}'s own doc).
|
|
6260
|
+
preResolvedScope: void 0
|
|
6261
|
+
});
|
|
4499
6262
|
}
|
|
4500
6263
|
}
|
|
4501
|
-
if (work.length === 0) return [];
|
|
6264
|
+
if (work.length === 0) return { errors: [], auxEntities: [], pulledNames: /* @__PURE__ */ new Set() };
|
|
4502
6265
|
const errors = [];
|
|
4503
6266
|
const consumerDeclared = new Set(resolved.map((r) => r.trait.name).filter(Boolean));
|
|
6267
|
+
const consumerDeclaredProvenance = /* @__PURE__ */ new Map();
|
|
6268
|
+
for (const rt of resolved) {
|
|
6269
|
+
if (rt.source.type === "imported" && rt.trait.name) {
|
|
6270
|
+
consumerDeclaredProvenance.set(rt.trait.name, { alias: rt.source.alias, traitName: rt.source.traitName });
|
|
6271
|
+
}
|
|
6272
|
+
}
|
|
4504
6273
|
const seen = new Set(consumerDeclared);
|
|
4505
6274
|
const visited = /* @__PURE__ */ new Set();
|
|
4506
6275
|
const pulledAs = /* @__PURE__ */ new Map();
|
|
4507
6276
|
const ownerOf = /* @__PURE__ */ new Map();
|
|
6277
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
4508
6278
|
const parentRewrites = /* @__PURE__ */ new Map();
|
|
4509
6279
|
const pulled = [];
|
|
6280
|
+
const embedderChain2 = (finalName) => {
|
|
6281
|
+
const chain2 = [];
|
|
6282
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
6283
|
+
let cur = finalName;
|
|
6284
|
+
while (cur !== void 0 && !seenNames.has(cur)) {
|
|
6285
|
+
seenNames.add(cur);
|
|
6286
|
+
const t = resolved.find((r) => r.trait.name === cur)?.trait ?? pulled.find((r) => r.trait.name === cur)?.trait;
|
|
6287
|
+
if (!t) break;
|
|
6288
|
+
if (t.config) chain2.push(t.config);
|
|
6289
|
+
cur = parentOf.get(cur);
|
|
6290
|
+
}
|
|
6291
|
+
return chain2;
|
|
6292
|
+
};
|
|
4510
6293
|
const noteRewrite = (parent, from, to) => {
|
|
4511
6294
|
let m = parentRewrites.get(parent);
|
|
4512
6295
|
if (!m) {
|
|
@@ -4516,8 +6299,8 @@ var ReferenceResolver = class {
|
|
|
4516
6299
|
m.set(from, to);
|
|
4517
6300
|
};
|
|
4518
6301
|
for (let item = work.pop(); item !== void 0; item = work.pop()) {
|
|
4519
|
-
const { alias, sibling, linkedEntity, parent, owner } = item;
|
|
4520
|
-
const pullKey = `${alias}
|
|
6302
|
+
const { alias, fallback, sibling, linkedEntity, parent, owner, preResolvedScope } = item;
|
|
6303
|
+
const pullKey = `${alias} ${sibling} ${owner} ${parent}`;
|
|
4521
6304
|
const existing = pulledAs.get(pullKey);
|
|
4522
6305
|
if (existing !== void 0) {
|
|
4523
6306
|
if (existing !== sibling) noteRewrite(parent, sibling, existing);
|
|
@@ -4525,73 +6308,122 @@ var ReferenceResolver = class {
|
|
|
4525
6308
|
}
|
|
4526
6309
|
let finalName = sibling;
|
|
4527
6310
|
if (seen.has(sibling)) {
|
|
4528
|
-
|
|
4529
|
-
|
|
6311
|
+
const provenance = consumerDeclaredProvenance.get(sibling);
|
|
6312
|
+
if (consumerDeclared.has(sibling) && provenance?.alias === alias && provenance.traitName === sibling) {
|
|
6313
|
+
continue;
|
|
6314
|
+
}
|
|
6315
|
+
finalName = `${parent}${sibling}`;
|
|
4530
6316
|
if (seen.has(finalName)) continue;
|
|
4531
6317
|
}
|
|
4532
6318
|
if (visited.has(pullKey)) continue;
|
|
4533
6319
|
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;
|
|
6320
|
+
let searchImports = imports;
|
|
6321
|
+
let searchAlias = alias;
|
|
4542
6322
|
let atomTrait;
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
6323
|
+
let childScope;
|
|
6324
|
+
let foundTypeArgs;
|
|
6325
|
+
let childPreResolvedScope;
|
|
6326
|
+
if (preResolvedScope) {
|
|
6327
|
+
const found = preResolvedScope.traits.find((rt) => rt.trait.name === sibling);
|
|
6328
|
+
if (found) {
|
|
6329
|
+
atomTrait = found.trait;
|
|
6330
|
+
childScope = { imports: searchImports, alias: searchAlias };
|
|
6331
|
+
foundTypeArgs = found.typeArgs;
|
|
6332
|
+
childPreResolvedScope = preResolvedScope;
|
|
4550
6333
|
}
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
if (!
|
|
4567
|
-
|
|
4568
|
-
|
|
6334
|
+
}
|
|
6335
|
+
if (!atomTrait) {
|
|
6336
|
+
let imported = imports.orbitals.get(alias);
|
|
6337
|
+
let atomEntry = null;
|
|
6338
|
+
let atomOrbitalIndex = -1;
|
|
6339
|
+
if (imported) {
|
|
6340
|
+
const list = importedOrbitals(imported);
|
|
6341
|
+
for (let i = 0; i < list.length; i++) {
|
|
6342
|
+
atomEntry = findTraitEntryInOrbital(list[i], sibling);
|
|
6343
|
+
if (atomEntry) {
|
|
6344
|
+
atomOrbitalIndex = i;
|
|
6345
|
+
break;
|
|
6346
|
+
}
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
if (!atomEntry && fallback) {
|
|
6350
|
+
const fbImported = fallback.imports.orbitals.get(fallback.alias);
|
|
6351
|
+
if (fbImported) {
|
|
6352
|
+
const list = importedOrbitals(fbImported);
|
|
6353
|
+
for (let i = 0; i < list.length; i++) {
|
|
6354
|
+
atomEntry = findTraitEntryInOrbital(list[i], sibling);
|
|
6355
|
+
if (atomEntry) {
|
|
6356
|
+
imported = fbImported;
|
|
6357
|
+
searchImports = fallback.imports;
|
|
6358
|
+
searchAlias = fallback.alias;
|
|
6359
|
+
atomOrbitalIndex = i;
|
|
6360
|
+
break;
|
|
6361
|
+
}
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
}
|
|
6365
|
+
if (!imported || !atomEntry) continue;
|
|
6366
|
+
const preResolvedOrbital = imported.resolvedOrbitals?.[atomOrbitalIndex];
|
|
6367
|
+
const preResolved = preResolvedOrbital?.traits.find((rt) => rt.trait.name === sibling);
|
|
6368
|
+
if (preResolved) {
|
|
6369
|
+
atomTrait = preResolved.trait;
|
|
6370
|
+
childScope = { imports: searchImports, alias: searchAlias };
|
|
6371
|
+
foundTypeArgs = preResolved.typeArgs;
|
|
6372
|
+
childPreResolvedScope = preResolvedOrbital;
|
|
6373
|
+
} else {
|
|
6374
|
+
const entryResolved = await this.resolveTraitEntry(imported, atomEntry, sibling, chain, searchImports);
|
|
6375
|
+
if (!entryResolved.success) {
|
|
6376
|
+
errors.push(...entryResolved.errors);
|
|
6377
|
+
continue;
|
|
6378
|
+
}
|
|
6379
|
+
atomTrait = entryResolved.data.trait;
|
|
6380
|
+
childScope = entryResolved.data.embedScope;
|
|
6381
|
+
foundTypeArgs = entryResolved.data.typeArgs;
|
|
4569
6382
|
}
|
|
4570
|
-
atomTrait = nested.data.trait;
|
|
4571
6383
|
}
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
6384
|
+
if (!atomTrait || !childScope) continue;
|
|
6385
|
+
const nextFallback = childScope.alias === searchAlias && childScope.imports === searchImports ? void 0 : childScope;
|
|
6386
|
+
let copy = resolveForwardedSiblingConfigFrom(
|
|
6387
|
+
applyLinkedEntityRename(atomTrait, linkedEntity, this.entityIdsInScope),
|
|
6388
|
+
embedderChain2(parent),
|
|
6389
|
+
orbitalConfig,
|
|
6390
|
+
this.schemaConfig
|
|
4576
6391
|
);
|
|
4577
6392
|
if (finalName !== sibling) {
|
|
4578
6393
|
copy = { ...copy, name: finalName };
|
|
4579
6394
|
noteRewrite(parent, sibling, finalName);
|
|
4580
6395
|
}
|
|
6396
|
+
const childParent = childPreResolvedScope ? parent : finalName;
|
|
4581
6397
|
for (const next of traitEmbedNamesOf(copy)) {
|
|
4582
|
-
work.push({
|
|
6398
|
+
work.push({
|
|
6399
|
+
alias,
|
|
6400
|
+
fallback: nextFallback,
|
|
6401
|
+
sibling: next,
|
|
6402
|
+
linkedEntity,
|
|
6403
|
+
parent: childParent,
|
|
6404
|
+
owner,
|
|
6405
|
+
preResolvedScope: childPreResolvedScope
|
|
6406
|
+
});
|
|
4583
6407
|
}
|
|
4584
6408
|
pulledAs.set(pullKey, finalName);
|
|
4585
6409
|
subsFor(owner).set(sibling, finalName);
|
|
4586
6410
|
ownerOf.set(finalName, owner);
|
|
6411
|
+
parentOf.set(finalName, parent);
|
|
4587
6412
|
seen.add(finalName);
|
|
4588
6413
|
pulled.push({
|
|
4589
6414
|
trait: copy,
|
|
4590
6415
|
source: { type: "imported", alias, traitName: sibling },
|
|
4591
|
-
...linkedEntity !== void 0 ? { linkedEntity } : {}
|
|
6416
|
+
...linkedEntity !== void 0 ? { linkedEntity } : {},
|
|
6417
|
+
...foundTypeArgs !== void 0 ? { typeArgs: foundTypeArgs } : {}
|
|
4592
6418
|
});
|
|
6419
|
+
if (copy.linkedEntity !== void 0) {
|
|
6420
|
+
const aux = entityByNameForAlias(imports, alias, copy.linkedEntity) ?? entityByNameAnyAlias(imports, copy.linkedEntity);
|
|
6421
|
+
if (aux) auxEntities.push(aux);
|
|
6422
|
+
}
|
|
6423
|
+
}
|
|
6424
|
+
if (pulled.length === 0 && parentRewrites.size === 0) {
|
|
6425
|
+
return { errors, auxEntities, pulledNames: /* @__PURE__ */ new Set() };
|
|
4593
6426
|
}
|
|
4594
|
-
if (pulled.length === 0 && parentRewrites.size === 0) return errors;
|
|
4595
6427
|
const applyRewrites = (rt) => {
|
|
4596
6428
|
const subs = rt.trait.name ? parentRewrites.get(rt.trait.name) : void 0;
|
|
4597
6429
|
if (subs) rt.trait = renameTraitEmbeds(rt.trait, subs);
|
|
@@ -4603,39 +6435,29 @@ var ReferenceResolver = class {
|
|
|
4603
6435
|
if (rt.trait.name) idByName.set(rt.trait.name, rt.trait.id);
|
|
4604
6436
|
}
|
|
4605
6437
|
for (const rt of pulled) {
|
|
4606
|
-
const listens = rt.trait.listens;
|
|
4607
6438
|
const owner = rt.trait.name ? ownerOf.get(rt.trait.name) : void 0;
|
|
4608
6439
|
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 };
|
|
6440
|
+
if (!subs) continue;
|
|
6441
|
+
rt.trait = rewriteListenSources(rt.trait, subs, idByName);
|
|
4624
6442
|
}
|
|
4625
6443
|
refResolverLog.info("sibling-pull", {
|
|
4626
6444
|
pulled: pulled.map((p) => ({
|
|
4627
6445
|
trait: p.trait.name,
|
|
4628
6446
|
owner: p.trait.name ? ownerOf.get(p.trait.name) : void 0,
|
|
6447
|
+
parent: p.trait.name ? parentOf.get(p.trait.name) : void 0,
|
|
4629
6448
|
linkedEntity: p.linkedEntity ?? p.trait.linkedEntity
|
|
4630
6449
|
}))
|
|
4631
6450
|
});
|
|
4632
6451
|
resolved.push(...pulled);
|
|
4633
|
-
|
|
6452
|
+
const pulledNames = new Set(
|
|
6453
|
+
pulled.map((p) => p.trait.name).filter((n) => Boolean(n))
|
|
6454
|
+
);
|
|
6455
|
+
return { errors, auxEntities, pulledNames };
|
|
4634
6456
|
}
|
|
4635
6457
|
/**
|
|
4636
6458
|
* Resolve a single trait reference.
|
|
4637
6459
|
*/
|
|
4638
|
-
resolveTraitRef(traitRef, imports) {
|
|
6460
|
+
async resolveTraitRef(traitRef, imports, chain, embedCtx, aliasEntityRenames) {
|
|
4639
6461
|
if (typeof traitRef !== "string" && "stateMachine" in traitRef) {
|
|
4640
6462
|
const { trait: resolvedInline, errors } = resolveConfigRefEmitNames(traitRef);
|
|
4641
6463
|
if (errors.length > 0) {
|
|
@@ -4655,16 +6477,33 @@ var ReferenceResolver = class {
|
|
|
4655
6477
|
return this.resolveTraitRefString(
|
|
4656
6478
|
refObj.ref,
|
|
4657
6479
|
imports,
|
|
6480
|
+
chain,
|
|
4658
6481
|
refObj.config,
|
|
4659
6482
|
refObj.linkedEntity,
|
|
4660
6483
|
refObj.name,
|
|
4661
6484
|
refObj.events,
|
|
4662
6485
|
refObj.listens,
|
|
4663
|
-
refObj.refId
|
|
6486
|
+
refObj.refId,
|
|
6487
|
+
refObj.typeArgs,
|
|
6488
|
+
embedCtx,
|
|
6489
|
+
aliasEntityRenames
|
|
4664
6490
|
);
|
|
4665
6491
|
}
|
|
4666
6492
|
if (typeof traitRef === "string") {
|
|
4667
|
-
return this.resolveTraitRefString(
|
|
6493
|
+
return this.resolveTraitRefString(
|
|
6494
|
+
traitRef,
|
|
6495
|
+
imports,
|
|
6496
|
+
chain,
|
|
6497
|
+
void 0,
|
|
6498
|
+
void 0,
|
|
6499
|
+
void 0,
|
|
6500
|
+
void 0,
|
|
6501
|
+
void 0,
|
|
6502
|
+
void 0,
|
|
6503
|
+
void 0,
|
|
6504
|
+
embedCtx,
|
|
6505
|
+
aliasEntityRenames
|
|
6506
|
+
);
|
|
4668
6507
|
}
|
|
4669
6508
|
return {
|
|
4670
6509
|
success: false,
|
|
@@ -4674,8 +6513,10 @@ var ReferenceResolver = class {
|
|
|
4674
6513
|
/**
|
|
4675
6514
|
* Resolve a trait reference string.
|
|
4676
6515
|
*/
|
|
4677
|
-
resolveTraitRefString(ref, imports, config, linkedEntity, overrideName, eventRenames, listensOverride, refId) {
|
|
6516
|
+
async resolveTraitRefString(ref, imports, chain, config, linkedEntity, overrideName, eventRenames, listensOverride, refId, typeArgs, embedCtx, aliasEntityRenames) {
|
|
4678
6517
|
const parsed = parseImportedTraitRef(ref);
|
|
6518
|
+
const localName = overrideName ?? (parsed ? parsed.traitName : ref);
|
|
6519
|
+
const resolvedConfig = config && embedCtx ? resolveEmbedderConfigForward(config, localName, embedCtx, this.schemaConfig) : config;
|
|
4679
6520
|
if (parsed) {
|
|
4680
6521
|
const imported = imports.orbitals.get(parsed.alias);
|
|
4681
6522
|
if (!imported) {
|
|
@@ -4687,9 +6528,27 @@ var ReferenceResolver = class {
|
|
|
4687
6528
|
};
|
|
4688
6529
|
}
|
|
4689
6530
|
let trait = null;
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
6531
|
+
let embedScope = { imports, alias: parsed.alias };
|
|
6532
|
+
const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
|
|
6533
|
+
if (idEntry && idEntry.kind === "trait") {
|
|
6534
|
+
trait = idEntry.node;
|
|
6535
|
+
} else {
|
|
6536
|
+
for (const o of importedOrbitals(imported)) {
|
|
6537
|
+
const entry = findTraitEntryInOrbital(o, parsed.traitName);
|
|
6538
|
+
if (!entry) continue;
|
|
6539
|
+
const entryResolved = await this.resolveTraitEntry(
|
|
6540
|
+
imported,
|
|
6541
|
+
entry,
|
|
6542
|
+
parsed.traitName,
|
|
6543
|
+
chain,
|
|
6544
|
+
imports,
|
|
6545
|
+
resolvedConfig
|
|
6546
|
+
);
|
|
6547
|
+
if (!entryResolved.success) return entryResolved;
|
|
6548
|
+
trait = entryResolved.data.trait;
|
|
6549
|
+
embedScope = entryResolved.data.embedScope;
|
|
6550
|
+
break;
|
|
6551
|
+
}
|
|
4693
6552
|
}
|
|
4694
6553
|
if (!trait) {
|
|
4695
6554
|
const available = importedOrbitals(imported).flatMap((o) => this.listTraitsInOrbital(o));
|
|
@@ -4700,15 +6559,36 @@ var ReferenceResolver = class {
|
|
|
4700
6559
|
]
|
|
4701
6560
|
};
|
|
4702
6561
|
}
|
|
6562
|
+
if (embedCtx && trait.config) {
|
|
6563
|
+
const homeResolvedConfig = resolveConfigForwards(
|
|
6564
|
+
trait.config,
|
|
6565
|
+
embedderChain(localName, embedCtx.traitRefs, embedCtx.embedGraph),
|
|
6566
|
+
embedCtx.orbitalConfig,
|
|
6567
|
+
homeOrbitalConfigForTrait(imported, parsed.traitName),
|
|
6568
|
+
imported.schemaConfig,
|
|
6569
|
+
this.schemaConfig
|
|
6570
|
+
);
|
|
6571
|
+
if (homeResolvedConfig) {
|
|
6572
|
+
trait = { ...trait, config: homeResolvedConfig };
|
|
6573
|
+
}
|
|
6574
|
+
}
|
|
4703
6575
|
const baseTrait = overrideName ? { ...trait, name: overrideName } : trait;
|
|
4704
|
-
const { trait: configResolvedTrait, errors: configRefErrors } = resolveConfigRefEmitNames(baseTrait,
|
|
6576
|
+
const { trait: configResolvedTrait, errors: configRefErrors, resolvedKnobs } = resolveConfigRefEmitNames(baseTrait, resolvedConfig);
|
|
4705
6577
|
if (configRefErrors.length > 0) {
|
|
4706
6578
|
return { success: false, errors: configRefErrors };
|
|
4707
6579
|
}
|
|
4708
|
-
const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity);
|
|
4709
|
-
const
|
|
4710
|
-
const
|
|
4711
|
-
const
|
|
6580
|
+
const reboundTrait = applyLinkedEntityRename(configResolvedTrait, linkedEntity, this.entityIdsInScope);
|
|
6581
|
+
const aliasSubs = aliasEntityRenames?.get(parsed.alias);
|
|
6582
|
+
const aliasReboundTrait = aliasSubs ? applyAliasEntityRenames(reboundTrait, aliasSubs, this.entityIdsInScope) : reboundTrait;
|
|
6583
|
+
const renamedTrait = applyEventRenames(aliasReboundTrait, eventRenames);
|
|
6584
|
+
const foldedTrait = foldEventRenameOntoDeclaredKnobs(
|
|
6585
|
+
renamedTrait,
|
|
6586
|
+
resolvedKnobValues(baseTrait, configResolvedTrait, resolvedKnobs),
|
|
6587
|
+
eventRenames
|
|
6588
|
+
);
|
|
6589
|
+
const renamedConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundTrait.config, eventRenames);
|
|
6590
|
+
const configFoldedTrait = foldCallSiteConfigOntoTrait(foldedTrait, renamedConfig);
|
|
6591
|
+
const finalTrait = listensOverride !== void 0 ? { ...configFoldedTrait, listens: listensOverride } : configFoldedTrait;
|
|
4712
6592
|
if (listensOverride !== void 0) {
|
|
4713
6593
|
refResolverLog.info("listens-override:imported", {
|
|
4714
6594
|
trait: finalTrait.name,
|
|
@@ -4723,7 +6603,9 @@ var ReferenceResolver = class {
|
|
|
4723
6603
|
trait: finalTrait,
|
|
4724
6604
|
source: { type: "imported", alias: parsed.alias, traitName: parsed.traitName },
|
|
4725
6605
|
config: renamedConfig,
|
|
4726
|
-
linkedEntity
|
|
6606
|
+
linkedEntity,
|
|
6607
|
+
embedScope,
|
|
6608
|
+
...typeArgs !== void 0 ? { typeArgs } : {}
|
|
4727
6609
|
},
|
|
4728
6610
|
warnings: []
|
|
4729
6611
|
};
|
|
@@ -4731,14 +6613,20 @@ var ReferenceResolver = class {
|
|
|
4731
6613
|
const localTrait = (refId && this.localTraitsById.get(refId)) ?? this.localTraits.get(ref);
|
|
4732
6614
|
if (localTrait) {
|
|
4733
6615
|
const baseLocal = overrideName ? { ...localTrait, name: overrideName } : localTrait;
|
|
4734
|
-
const { trait: configResolvedLocal, errors: localConfigRefErrors } = resolveConfigRefEmitNames(baseLocal,
|
|
6616
|
+
const { trait: configResolvedLocal, errors: localConfigRefErrors, resolvedKnobs: localResolvedKnobs } = resolveConfigRefEmitNames(baseLocal, resolvedConfig);
|
|
4735
6617
|
if (localConfigRefErrors.length > 0) {
|
|
4736
6618
|
return { success: false, errors: localConfigRefErrors };
|
|
4737
6619
|
}
|
|
4738
|
-
const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity);
|
|
6620
|
+
const reboundLocal = applyLinkedEntityRename(configResolvedLocal, linkedEntity, this.entityIdsInScope);
|
|
4739
6621
|
const renamedLocalTrait = applyEventRenames(reboundLocal, eventRenames);
|
|
4740
|
-
const
|
|
4741
|
-
|
|
6622
|
+
const foldedLocalTrait = foldEventRenameOntoDeclaredKnobs(
|
|
6623
|
+
renamedLocalTrait,
|
|
6624
|
+
resolvedKnobValues(baseLocal, configResolvedLocal, localResolvedKnobs),
|
|
6625
|
+
eventRenames
|
|
6626
|
+
);
|
|
6627
|
+
const renamedLocalConfig = applyEventRenamesToCallSiteConfig(resolvedConfig, reboundLocal.config, eventRenames);
|
|
6628
|
+
const configFoldedLocalTrait = foldCallSiteConfigOntoTrait(foldedLocalTrait, renamedLocalConfig);
|
|
6629
|
+
const finalLocalTrait = listensOverride !== void 0 ? { ...configFoldedLocalTrait, listens: listensOverride } : configFoldedLocalTrait;
|
|
4742
6630
|
if (listensOverride !== void 0) {
|
|
4743
6631
|
refResolverLog.info("listens-override:local", {
|
|
4744
6632
|
trait: finalLocalTrait.name,
|
|
@@ -4753,7 +6641,8 @@ var ReferenceResolver = class {
|
|
|
4753
6641
|
trait: finalLocalTrait,
|
|
4754
6642
|
source: { type: "local", name: ref },
|
|
4755
6643
|
config: renamedLocalConfig,
|
|
4756
|
-
linkedEntity
|
|
6644
|
+
linkedEntity,
|
|
6645
|
+
...typeArgs !== void 0 ? { typeArgs } : {}
|
|
4757
6646
|
},
|
|
4758
6647
|
warnings: []
|
|
4759
6648
|
};
|
|
@@ -4765,31 +6654,6 @@ var ReferenceResolver = class {
|
|
|
4765
6654
|
]
|
|
4766
6655
|
};
|
|
4767
6656
|
}
|
|
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
6657
|
/**
|
|
4794
6658
|
* List trait names in an orbital.
|
|
4795
6659
|
*/
|
|
@@ -4805,11 +6669,11 @@ var ReferenceResolver = class {
|
|
|
4805
6669
|
/**
|
|
4806
6670
|
* Resolve page references.
|
|
4807
6671
|
*/
|
|
4808
|
-
resolvePages(pageRefs, imports) {
|
|
6672
|
+
async resolvePages(pageRefs, imports, chain) {
|
|
4809
6673
|
const errors = [];
|
|
4810
6674
|
const resolved = [];
|
|
4811
6675
|
for (const pageRef of pageRefs) {
|
|
4812
|
-
const result = this.resolvePageRef(pageRef, imports);
|
|
6676
|
+
const result = await this.resolvePageRef(pageRef, imports, chain);
|
|
4813
6677
|
if (!result.success) {
|
|
4814
6678
|
errors.push(...result.errors);
|
|
4815
6679
|
} else {
|
|
@@ -4824,7 +6688,7 @@ var ReferenceResolver = class {
|
|
|
4824
6688
|
/**
|
|
4825
6689
|
* Resolve a single page reference.
|
|
4826
6690
|
*/
|
|
4827
|
-
resolvePageRef(pageRef, imports) {
|
|
6691
|
+
async resolvePageRef(pageRef, imports, chain) {
|
|
4828
6692
|
if (!isPageReference(pageRef)) {
|
|
4829
6693
|
return {
|
|
4830
6694
|
success: true,
|
|
@@ -4837,10 +6701,10 @@ var ReferenceResolver = class {
|
|
|
4837
6701
|
};
|
|
4838
6702
|
}
|
|
4839
6703
|
if (isPageReferenceString(pageRef)) {
|
|
4840
|
-
return this.resolvePageRefString(pageRef, imports);
|
|
6704
|
+
return this.resolvePageRefString(pageRef, imports, chain);
|
|
4841
6705
|
}
|
|
4842
6706
|
if (isPageReferenceObject(pageRef)) {
|
|
4843
|
-
return this.resolvePageRefObject(pageRef, imports);
|
|
6707
|
+
return this.resolvePageRefObject(pageRef, imports, chain);
|
|
4844
6708
|
}
|
|
4845
6709
|
return {
|
|
4846
6710
|
success: false,
|
|
@@ -4850,7 +6714,7 @@ var ReferenceResolver = class {
|
|
|
4850
6714
|
/**
|
|
4851
6715
|
* Resolve a page reference string.
|
|
4852
6716
|
*/
|
|
4853
|
-
resolvePageRefString(ref, imports, refId) {
|
|
6717
|
+
async resolvePageRefString(ref, imports, chain, refId) {
|
|
4854
6718
|
const parsed = parsePageRef(ref);
|
|
4855
6719
|
if (!parsed) {
|
|
4856
6720
|
return {
|
|
@@ -4868,9 +6732,18 @@ var ReferenceResolver = class {
|
|
|
4868
6732
|
};
|
|
4869
6733
|
}
|
|
4870
6734
|
let page = null;
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
6735
|
+
const idEntry = refId ? imports.idIndex?.get(refId) : void 0;
|
|
6736
|
+
if (idEntry && idEntry.kind === "page") {
|
|
6737
|
+
page = { ...idEntry.node };
|
|
6738
|
+
} else {
|
|
6739
|
+
for (const o of importedOrbitals(imported)) {
|
|
6740
|
+
const entry = findPageEntryInOrbital(o, parsed.pageName);
|
|
6741
|
+
if (!entry) continue;
|
|
6742
|
+
const entryResolved = await this.resolvePageEntry(imported, entry, chain);
|
|
6743
|
+
if (!entryResolved.success) return entryResolved;
|
|
6744
|
+
page = entryResolved.data.page;
|
|
6745
|
+
break;
|
|
6746
|
+
}
|
|
4874
6747
|
}
|
|
4875
6748
|
if (!page) {
|
|
4876
6749
|
const available = importedOrbitals(imported).flatMap((o) => this.listPagesInOrbital(o));
|
|
@@ -4892,10 +6765,18 @@ var ReferenceResolver = class {
|
|
|
4892
6765
|
};
|
|
4893
6766
|
}
|
|
4894
6767
|
/**
|
|
4895
|
-
* Resolve a page reference object
|
|
6768
|
+
* Resolve a page reference object, applying every call-site override —
|
|
6769
|
+
* `path` (direct assignment), `linkedEntity` (rebind `primaryEntity` and
|
|
6770
|
+
* every page-level trait pointer that named the old entity), and `traits`
|
|
6771
|
+
* (full replacement) — mirroring the compiler's `apply_overrides_to_page`
|
|
6772
|
+
* (`phases/inline/page.rs:21-93`). `Page.traits` is a `PageTraitRef[]`
|
|
6773
|
+
* pointer list (a trait's own body lives in the orbital's `traits {}`, not
|
|
6774
|
+
* on the page), so unlike Rust's `TraitReference` the `linkedEntity` rebind
|
|
6775
|
+
* only ever touches each pointer's OWN `linkedEntity` field — there is no
|
|
6776
|
+
* inline trait body here to walk with `renameEntitiesInTrait`.
|
|
4896
6777
|
*/
|
|
4897
|
-
resolvePageRefObject(refObj, imports) {
|
|
4898
|
-
const baseResult = this.resolvePageRefString(refObj.ref, imports, refObj.refId);
|
|
6778
|
+
async resolvePageRefObject(refObj, imports, chain) {
|
|
6779
|
+
const baseResult = await this.resolvePageRefString(refObj.ref, imports, chain, refObj.refId);
|
|
4899
6780
|
if (!baseResult.success) {
|
|
4900
6781
|
return baseResult;
|
|
4901
6782
|
}
|
|
@@ -4909,36 +6790,25 @@ var ReferenceResolver = class {
|
|
|
4909
6790
|
resolved.pathOverridden = true;
|
|
4910
6791
|
resolved.originalPath = originalPath;
|
|
4911
6792
|
}
|
|
6793
|
+
if (refObj.linkedEntity) {
|
|
6794
|
+
const oldEntity = resolved.page.primaryEntity;
|
|
6795
|
+
const newEntity = refObj.linkedEntity;
|
|
6796
|
+
const rebindPointers = (pointers) => oldEntity && oldEntity !== newEntity ? pointers?.map((pt) => pt.linkedEntity === oldEntity ? { ...pt, linkedEntity: newEntity } : pt) : pointers;
|
|
6797
|
+
resolved.page = {
|
|
6798
|
+
...resolved.page,
|
|
6799
|
+
primaryEntity: newEntity,
|
|
6800
|
+
traits: rebindPointers(resolved.page.traits)
|
|
6801
|
+
};
|
|
6802
|
+
}
|
|
6803
|
+
if (refObj.traits) {
|
|
6804
|
+
resolved.page = { ...resolved.page, traits: refObj.traits.map(toPageTraitRef) };
|
|
6805
|
+
}
|
|
4912
6806
|
return {
|
|
4913
6807
|
success: true,
|
|
4914
6808
|
data: resolved,
|
|
4915
6809
|
warnings: baseResult.warnings
|
|
4916
6810
|
};
|
|
4917
6811
|
}
|
|
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
6812
|
/**
|
|
4943
6813
|
* List page names in an orbital.
|
|
4944
6814
|
*/
|
|
@@ -4953,6 +6823,567 @@ var ReferenceResolver = class {
|
|
|
4953
6823
|
}
|
|
4954
6824
|
return names;
|
|
4955
6825
|
}
|
|
6826
|
+
/**
|
|
6827
|
+
* Flatten every reference-form orbital (`orbital X = Alias.orbitals.Y
|
|
6828
|
+
* { … }`, docs/Almadar_Orbital_Import.md §4) in a schema BEFORE the
|
|
6829
|
+
* ordinary per-orbital {@link resolve} pass runs — the interpreter-path
|
|
6830
|
+
* twin of the (not-yet-landed) compiler's inline-phase flatten. After this
|
|
6831
|
+
* call, no returned `OrbitalDefinition` carries `.reference`.
|
|
6832
|
+
*/
|
|
6833
|
+
async resolveOrbitalImports(schema, opts) {
|
|
6834
|
+
const errors = [];
|
|
6835
|
+
const flattened = [];
|
|
6836
|
+
const chain = { push: () => null, pop: () => {
|
|
6837
|
+
}, clone() {
|
|
6838
|
+
return this;
|
|
6839
|
+
} };
|
|
6840
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
6841
|
+
const consumerEntityIds = consumerEntityIdsOf(schema.orbitals);
|
|
6842
|
+
for (const [name, id] of await this.precomputeReferenceFormPrimaryIds(schema, chain)) {
|
|
6843
|
+
if (!consumerEntityIds.has(name)) consumerEntityIds.set(name, id);
|
|
6844
|
+
}
|
|
6845
|
+
const consumerRoster = identityEntitiesOf(schema.orbitals);
|
|
6846
|
+
for (const orbital of schema.orbitals) {
|
|
6847
|
+
if (!orbital.reference) {
|
|
6848
|
+
if (!opts?.skipTypeParamSentinels && isInlineEntity(orbital.entity)) {
|
|
6849
|
+
resolveOrbitalTypeParamSentinels(
|
|
6850
|
+
orbital.traits.filter(isInlineTrait).map((t) => ({ trait: t })),
|
|
6851
|
+
orbital.entity,
|
|
6852
|
+
(orbital.auxiliaryEntities ?? []).filter(isInlineEntity),
|
|
6853
|
+
orbital.types
|
|
6854
|
+
);
|
|
6855
|
+
}
|
|
6856
|
+
flattened.push(orbital);
|
|
6857
|
+
continue;
|
|
6858
|
+
}
|
|
6859
|
+
const result = await this.resolveOrbitalRefChain(orbital, void 0, chain, visiting, consumerEntityIds, consumerRoster);
|
|
6860
|
+
if (!result.success) {
|
|
6861
|
+
errors.push(...result.errors);
|
|
6862
|
+
continue;
|
|
6863
|
+
}
|
|
6864
|
+
flattened.push(result.data);
|
|
6865
|
+
}
|
|
6866
|
+
if (errors.length > 0) return { success: false, errors };
|
|
6867
|
+
return { success: true, data: flattened, warnings: [] };
|
|
6868
|
+
}
|
|
6869
|
+
/**
|
|
6870
|
+
* (B) The materialized primary name → derived id of every REFERENCE-FORM
|
|
6871
|
+
* orbital this schema declares (`orbital X = Alias.orbitals.Y { … }`),
|
|
6872
|
+
* computed order-free — WITHOUT requiring any other orbital in `schema`
|
|
6873
|
+
* to have resolved first, and without recursively flattening the
|
|
6874
|
+
* upstream. Each reference's alias is loaded via the ordinary
|
|
6875
|
+
* `resolveImports` path, which the loader caches by absolute path (see
|
|
6876
|
+
* `ExternalOrbitalLoader`'s `LoaderCache`) — the REAL flatten
|
|
6877
|
+
* (`resolveOrbitalRefChain`) moments later is then a cache hit, no
|
|
6878
|
+
* duplicate work — and its named orbital looked up directly in the
|
|
6879
|
+
* loaded (un-flattened) schema: an upstream's OWN primary entity id/name
|
|
6880
|
+
* never change through resolution (only a CONSUMER-side CLONE gets a
|
|
6881
|
+
* fresh derived id), so this shallow load's entity is exactly what the
|
|
6882
|
+
* real flatten pass would see too. Uses the SAME `materializedPrimaryEntity`
|
|
6883
|
+
* pair `materializeOrbitalRef` computes for itself — one owner. JS twin
|
|
6884
|
+
* of the compiled path's `precompute_reference_form_primary_ids`.
|
|
6885
|
+
*
|
|
6886
|
+
* Best-effort: a reference this pre-pass cannot resolve (unknown alias,
|
|
6887
|
+
* malformed reference string, upstream orbital not found, load failure)
|
|
6888
|
+
* is silently skipped here — the REAL `resolveOrbitalRefChain` call
|
|
6889
|
+
* moments later still surfaces the actual error for it.
|
|
6890
|
+
*/
|
|
6891
|
+
async precomputeReferenceFormPrimaryIds(schema, chain) {
|
|
6892
|
+
const out = /* @__PURE__ */ new Map();
|
|
6893
|
+
for (const orbital of schema.orbitals) {
|
|
6894
|
+
const ref = orbital.reference;
|
|
6895
|
+
if (!ref) continue;
|
|
6896
|
+
const parsed = parseOrbitalRef(ref.ref);
|
|
6897
|
+
if (!parsed) continue;
|
|
6898
|
+
const importsResult = await this.resolveImports(orbital.uses ?? [], void 0, chain);
|
|
6899
|
+
if (!importsResult.success) continue;
|
|
6900
|
+
const imported = importsResult.data.orbitals.get(parsed.alias);
|
|
6901
|
+
if (!imported) continue;
|
|
6902
|
+
const upstream = importedOrbitals(imported).find((o) => o.name === parsed.orbitalName);
|
|
6903
|
+
if (!upstream || !isInlineEntity(upstream.entity)) continue;
|
|
6904
|
+
const { name, id } = materializedPrimaryEntity(upstream.entity, upstream.id, ref, orbital.name);
|
|
6905
|
+
out.set(name, id);
|
|
6906
|
+
}
|
|
6907
|
+
return out;
|
|
6908
|
+
}
|
|
6909
|
+
/**
|
|
6910
|
+
* Resolve one reference-form orbital, recursing into the upstream first
|
|
6911
|
+
* when IT is also reference-form ("already fully inlined because inline
|
|
6912
|
+
* recursed into every loaded orbital" — docs/Almadar_Orbital_Import.md §9
|
|
6913
|
+
* step 3 — the JS resolver needs its own cycle guard since it has no
|
|
6914
|
+
* file-level inline-order pass to lean on).
|
|
6915
|
+
*/
|
|
6916
|
+
async resolveOrbitalRefChain(orbital, sourcePath, chain, visiting, consumerEntityIds, consumerRoster) {
|
|
6917
|
+
const ref = orbital.reference;
|
|
6918
|
+
if (!ref) return { success: true, data: orbital, warnings: [] };
|
|
6919
|
+
const parsed = parseOrbitalRef(ref.ref);
|
|
6920
|
+
if (!parsed) {
|
|
6921
|
+
return {
|
|
6922
|
+
success: false,
|
|
6923
|
+
errors: [`Invalid orbital reference format: ${ref.ref}. Expected "Alias.orbitals.OrbitalName"`]
|
|
6924
|
+
};
|
|
6925
|
+
}
|
|
6926
|
+
const importsResult = await this.resolveImports(orbital.uses ?? [], sourcePath, chain);
|
|
6927
|
+
if (!importsResult.success) return { success: false, errors: importsResult.errors };
|
|
6928
|
+
const imported = importsResult.data.orbitals.get(parsed.alias);
|
|
6929
|
+
if (!imported) {
|
|
6930
|
+
return {
|
|
6931
|
+
success: false,
|
|
6932
|
+
errors: [
|
|
6933
|
+
`Unknown import alias in orbital reference: ${parsed.alias}. Available aliases: ${Array.from(importsResult.data.orbitals.keys()).join(", ") || "none"}`
|
|
6934
|
+
]
|
|
6935
|
+
};
|
|
6936
|
+
}
|
|
6937
|
+
const candidates = importedOrbitals(imported);
|
|
6938
|
+
let upstream = candidates.find((o) => o.name === parsed.orbitalName);
|
|
6939
|
+
if (!upstream) {
|
|
6940
|
+
return {
|
|
6941
|
+
success: false,
|
|
6942
|
+
errors: [
|
|
6943
|
+
`Orbital "${parsed.orbitalName}" not found in imported behavior "${parsed.alias}". Available orbitals: ${candidates.map((o) => o.name).join(", ") || "none"}`
|
|
6944
|
+
]
|
|
6945
|
+
};
|
|
6946
|
+
}
|
|
6947
|
+
const cycleKey = `${imported.sourcePath}::${parsed.orbitalName}`;
|
|
6948
|
+
if (visiting.has(cycleKey)) {
|
|
6949
|
+
return {
|
|
6950
|
+
success: false,
|
|
6951
|
+
errors: [
|
|
6952
|
+
`Circular orbital reference: "${orbital.name}" imports "${parsed.alias}.orbitals.${parsed.orbitalName}" while that orbital is itself being resolved`
|
|
6953
|
+
]
|
|
6954
|
+
};
|
|
6955
|
+
}
|
|
6956
|
+
visiting.add(cycleKey);
|
|
6957
|
+
if (upstream.reference) {
|
|
6958
|
+
const nested = await this.resolveOrbitalRefChain(
|
|
6959
|
+
upstream,
|
|
6960
|
+
imported.sourcePath,
|
|
6961
|
+
chain,
|
|
6962
|
+
visiting,
|
|
6963
|
+
consumerEntityIds,
|
|
6964
|
+
consumerRoster
|
|
6965
|
+
);
|
|
6966
|
+
if (!nested.success) {
|
|
6967
|
+
visiting.delete(cycleKey);
|
|
6968
|
+
return nested;
|
|
6969
|
+
}
|
|
6970
|
+
upstream = nested.data;
|
|
6971
|
+
}
|
|
6972
|
+
visiting.delete(cycleKey);
|
|
6973
|
+
const materialized = await this.materializeOrbitalRef(
|
|
6974
|
+
upstream,
|
|
6975
|
+
ref,
|
|
6976
|
+
orbital.name,
|
|
6977
|
+
orbital.id,
|
|
6978
|
+
imported.sourcePath,
|
|
6979
|
+
chain,
|
|
6980
|
+
candidates,
|
|
6981
|
+
consumerEntityIds,
|
|
6982
|
+
consumerRoster,
|
|
6983
|
+
imported.schemaConfig
|
|
6984
|
+
);
|
|
6985
|
+
if (!materialized.success) return materialized;
|
|
6986
|
+
const siblingTraits = orbital.traits ?? [];
|
|
6987
|
+
return {
|
|
6988
|
+
success: true,
|
|
6989
|
+
data: {
|
|
6990
|
+
...materialized.data,
|
|
6991
|
+
...siblingTraits.length > 0 ? { traits: [...materialized.data.traits, ...siblingTraits] } : {},
|
|
6992
|
+
uses: orbital.uses
|
|
6993
|
+
},
|
|
6994
|
+
warnings: materialized.warnings
|
|
6995
|
+
};
|
|
6996
|
+
}
|
|
6997
|
+
/**
|
|
6998
|
+
* Materialize a reference-form orbital: flatten the (already-inlined)
|
|
6999
|
+
* upstream orbital's whole trait/entity/page closure into the consumer,
|
|
7000
|
+
* unconditionally prefixed by `localName` (docs/Almadar_Orbital_Import.md
|
|
7001
|
+
* §4.3). JS twin of the (not-yet-landed) compiler's
|
|
7002
|
+
* `resolve_orbital_reference`.
|
|
7003
|
+
*/
|
|
7004
|
+
async materializeOrbitalRef(upstream, ref, localName, localId, sourcePath, chain, aliasOrbitals, consumerEntityIds, consumerRoster, importedSchemaConfig) {
|
|
7005
|
+
const savedSchemaConfig = this.schemaConfig;
|
|
7006
|
+
this.schemaConfig = importedSchemaConfig;
|
|
7007
|
+
let resolvedUpstream;
|
|
7008
|
+
try {
|
|
7009
|
+
resolvedUpstream = await this.resolve(upstream, sourcePath, chain);
|
|
7010
|
+
} finally {
|
|
7011
|
+
this.schemaConfig = savedSchemaConfig;
|
|
7012
|
+
}
|
|
7013
|
+
if (!resolvedUpstream.success) {
|
|
7014
|
+
return {
|
|
7015
|
+
success: false,
|
|
7016
|
+
errors: resolvedUpstream.errors.map(
|
|
7017
|
+
(e) => `Orbital reference "${localName}" (${ref.ref}): ${e}`
|
|
7018
|
+
)
|
|
7019
|
+
};
|
|
7020
|
+
}
|
|
7021
|
+
const {
|
|
7022
|
+
entity: upstreamEntity,
|
|
7023
|
+
traits: upstreamTraits,
|
|
7024
|
+
pages: upstreamPages,
|
|
7025
|
+
// (C) the RESOLVED aux-entity set — includes whatever sibling-pull
|
|
7026
|
+
// surfaced (`pullSiblingTraits`'s aux-entity carry), never just
|
|
7027
|
+
// `upstream.auxiliaryEntities` (the pre-resolve INPUT, which misses
|
|
7028
|
+
// every un-rebound composed atom's own entity).
|
|
7029
|
+
auxiliaryEntities: upstreamAuxiliaryEntities
|
|
7030
|
+
} = resolvedUpstream.data;
|
|
7031
|
+
const onlySet = ref.only ? new Set(ref.only) : void 0;
|
|
7032
|
+
const omitSet = new Set(ref.omit ?? []);
|
|
7033
|
+
const keptTraits = upstreamTraits.filter(
|
|
7034
|
+
(rt) => onlySet ? onlySet.has(rt.trait.name) : !omitSet.has(rt.trait.name)
|
|
7035
|
+
);
|
|
7036
|
+
const keptNames = new Set(keptTraits.map((rt) => rt.trait.name));
|
|
7037
|
+
const removedNames = new Set(
|
|
7038
|
+
upstreamTraits.map((rt) => rt.trait.name).filter((n) => !keptNames.has(n))
|
|
7039
|
+
);
|
|
7040
|
+
const errors = [];
|
|
7041
|
+
for (const rt of keptTraits) {
|
|
7042
|
+
for (const embed of traitEmbedNamesOf(rt.trait)) {
|
|
7043
|
+
if (removedNames.has(embed)) {
|
|
7044
|
+
errors.push(
|
|
7045
|
+
`Orbital "${localName}" omits trait "${embed}" but surviving trait "${rt.trait.name}" still embeds it via @trait.${embed} (ORB_O_OMIT_EMBEDDED_TRAIT)`
|
|
7046
|
+
);
|
|
7047
|
+
}
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7051
|
+
let auxEntities = upstreamAuxiliaryEntities ?? [];
|
|
7052
|
+
const subs = /* @__PURE__ */ new Map();
|
|
7053
|
+
for (const rt of keptTraits) subs.set(rt.trait.name, `${localName}${rt.trait.name}`);
|
|
7054
|
+
const { name: primaryFinalName, id: primaryId } = materializedPrimaryEntity(
|
|
7055
|
+
upstreamEntity,
|
|
7056
|
+
upstream.id,
|
|
7057
|
+
ref,
|
|
7058
|
+
localName
|
|
7059
|
+
);
|
|
7060
|
+
subs.set(upstreamEntity.name, primaryFinalName);
|
|
7061
|
+
for (const e of auxEntities) subs.set(e.name, `${localName}${e.name}`);
|
|
7062
|
+
const fieldSubs = new Map(Object.entries(ref.fields ?? {}));
|
|
7063
|
+
const closure = /* @__PURE__ */ new Set([upstreamEntity.name, ...auxEntities.map((e) => e.name)]);
|
|
7064
|
+
const upstreamUniverse = /* @__PURE__ */ new Set();
|
|
7065
|
+
const upstreamUniverseEntities = /* @__PURE__ */ new Map();
|
|
7066
|
+
const primaryEntityNames = /* @__PURE__ */ new Set();
|
|
7067
|
+
for (const o of aliasOrbitals) {
|
|
7068
|
+
if (o.name === upstream.name) continue;
|
|
7069
|
+
if (isInlineEntity(o.entity)) primaryEntityNames.add(o.entity.name);
|
|
7070
|
+
for (const entity of inlineEntityRefsOf(o)) {
|
|
7071
|
+
if (!closure.has(entity.name)) {
|
|
7072
|
+
upstreamUniverse.add(entity.name);
|
|
7073
|
+
upstreamUniverseEntities.set(entity.name, entity);
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
}
|
|
7077
|
+
const entityIds = /* @__PURE__ */ new Map();
|
|
7078
|
+
if (ref.entities) {
|
|
7079
|
+
for (const [upstreamKey, consumerName] of Object.entries(ref.entities)) {
|
|
7080
|
+
if (!upstreamUniverse.has(upstreamKey)) {
|
|
7081
|
+
errors.push(
|
|
7082
|
+
`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)`
|
|
7083
|
+
);
|
|
7084
|
+
continue;
|
|
7085
|
+
}
|
|
7086
|
+
const consumerId = consumerEntityIds.get(consumerName);
|
|
7087
|
+
if (consumerId === void 0) {
|
|
7088
|
+
errors.push(
|
|
7089
|
+
`Orbital "${localName}" entities { ${upstreamKey}: ${consumerName} } targets "${consumerName}", which the consumer schema does not declare (ORB_O_ENTITY_TARGET_UNKNOWN)`
|
|
7090
|
+
);
|
|
7091
|
+
continue;
|
|
7092
|
+
}
|
|
7093
|
+
subs.set(upstreamKey, consumerName);
|
|
7094
|
+
entityIds.set(consumerName, consumerId);
|
|
7095
|
+
}
|
|
7096
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7097
|
+
}
|
|
7098
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
7099
|
+
for (const rt of keptTraits) {
|
|
7100
|
+
if (rt.trait.linkedEntity && upstreamUniverse.has(rt.trait.linkedEntity)) {
|
|
7101
|
+
referenced.add(rt.trait.linkedEntity);
|
|
7102
|
+
}
|
|
7103
|
+
for (const name of collectEntityNamesInTrait(rt.trait, upstreamUniverse)) referenced.add(name);
|
|
7104
|
+
if (rt.trait.sourceEntityDefinition) {
|
|
7105
|
+
for (const name of relationTargetsOfEntity(rt.trait.sourceEntityDefinition, upstreamUniverse)) {
|
|
7106
|
+
referenced.add(name);
|
|
7107
|
+
}
|
|
7108
|
+
}
|
|
7109
|
+
}
|
|
7110
|
+
for (const name of relationTargetsOfEntity(upstreamEntity, upstreamUniverse)) referenced.add(name);
|
|
7111
|
+
for (const aux of auxEntities) {
|
|
7112
|
+
for (const name of relationTargetsOfEntity(aux, upstreamUniverse)) referenced.add(name);
|
|
7113
|
+
}
|
|
7114
|
+
for (const rp of upstreamPages) {
|
|
7115
|
+
if (rp.page.primaryEntity && upstreamUniverse.has(rp.page.primaryEntity)) {
|
|
7116
|
+
referenced.add(rp.page.primaryEntity);
|
|
7117
|
+
}
|
|
7118
|
+
for (const tr of rp.page.traits ?? []) {
|
|
7119
|
+
if (tr.linkedEntity && upstreamUniverse.has(tr.linkedEntity)) referenced.add(tr.linkedEntity);
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
7122
|
+
for (const name of referenced) {
|
|
7123
|
+
if (subs.has(name)) continue;
|
|
7124
|
+
const definition = upstreamUniverseEntities.get(name);
|
|
7125
|
+
const auxOnly = definition !== void 0 && !primaryEntityNames.has(name);
|
|
7126
|
+
if (definition && auxOnly && !definition.identity) {
|
|
7127
|
+
auxEntities = [...auxEntities, definition];
|
|
7128
|
+
subs.set(name, `${localName}${name}`);
|
|
7129
|
+
continue;
|
|
7130
|
+
}
|
|
7131
|
+
errors.push(
|
|
7132
|
+
`Orbital "${localName}" references out-of-orbital entity "${name}" with no "${name}: <consumer entity>" mapping in entities {} (ORB_O_ENTITY_UNMAPPED)`
|
|
7133
|
+
);
|
|
7134
|
+
}
|
|
7135
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7136
|
+
const roleFields = /* @__PURE__ */ new Map();
|
|
7137
|
+
for (const entity of identityEntitiesOf(aliasOrbitals)) {
|
|
7138
|
+
for (const field of entity.fields) {
|
|
7139
|
+
if (!field.name) continue;
|
|
7140
|
+
const vocab = roleVocabularyOf(entity, field.name);
|
|
7141
|
+
if (vocab) roleFields.set(field.name, vocab);
|
|
7142
|
+
}
|
|
7143
|
+
}
|
|
7144
|
+
const consumerRoleFields = /* @__PURE__ */ new Map();
|
|
7145
|
+
for (const entity of consumerRoster) {
|
|
7146
|
+
for (const field of entity.fields) {
|
|
7147
|
+
if (!field.name) continue;
|
|
7148
|
+
const vocab = roleVocabularyOf(entity, field.name);
|
|
7149
|
+
if (!vocab) continue;
|
|
7150
|
+
let values = consumerRoleFields.get(field.name);
|
|
7151
|
+
if (!values) {
|
|
7152
|
+
values = /* @__PURE__ */ new Set();
|
|
7153
|
+
consumerRoleFields.set(field.name, values);
|
|
7154
|
+
}
|
|
7155
|
+
for (const value of vocab) values.add(value);
|
|
7156
|
+
}
|
|
7157
|
+
}
|
|
7158
|
+
for (const [literal, targets] of Object.entries(ref.roles ?? {})) {
|
|
7159
|
+
const matchingFields = [...roleFields.entries()].filter(([, vocab]) => vocab.includes(literal)).map(([field]) => field).sort();
|
|
7160
|
+
if (matchingFields.length === 0) {
|
|
7161
|
+
errors.push(
|
|
7162
|
+
`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)`
|
|
7163
|
+
);
|
|
7164
|
+
continue;
|
|
7165
|
+
}
|
|
7166
|
+
for (const field of matchingFields) {
|
|
7167
|
+
const allowed = consumerRoleFields.get(field);
|
|
7168
|
+
for (const target of targets) {
|
|
7169
|
+
if (allowed?.has(target)) continue;
|
|
7170
|
+
errors.push(
|
|
7171
|
+
`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)`
|
|
7172
|
+
);
|
|
7173
|
+
}
|
|
7174
|
+
}
|
|
7175
|
+
}
|
|
7176
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7177
|
+
const declaredConfig = upstream.config;
|
|
7178
|
+
if (ref.config) {
|
|
7179
|
+
for (const key of Object.keys(ref.config)) {
|
|
7180
|
+
if (!declaredConfig || !(key in declaredConfig)) {
|
|
7181
|
+
errors.push(
|
|
7182
|
+
`Orbital "${localName}" overrides config "${key}" but upstream orbital "${upstream.name}" does not declare that knob (ORB_O_CONFIG_UNKNOWN_KEY)`
|
|
7183
|
+
);
|
|
7184
|
+
}
|
|
7185
|
+
}
|
|
7186
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7187
|
+
}
|
|
7188
|
+
const configOverrideValues = {};
|
|
7189
|
+
for (const [key, field] of Object.entries(ref.config ?? {})) {
|
|
7190
|
+
if (field.default !== void 0) configOverrideValues[key] = field.default;
|
|
7191
|
+
}
|
|
7192
|
+
const foldedConfig = declaredConfig ? overrideDeclaredKnobs(declaredConfig, configOverrideValues) : void 0;
|
|
7193
|
+
const idByName = /* @__PURE__ */ new Map();
|
|
7194
|
+
const materializedTraits = keptTraits.map((rt) => {
|
|
7195
|
+
const finalName = subs.get(rt.trait.name);
|
|
7196
|
+
const finalId = asTraitId(deriveMaterializedId(rt.trait.id, upstream.id, rt.trait.name, localName, "trait"));
|
|
7197
|
+
idByName.set(finalName, finalId);
|
|
7198
|
+
return { ...rt.trait, name: finalName, id: finalId };
|
|
7199
|
+
});
|
|
7200
|
+
const embeddersOf = /* @__PURE__ */ new Map();
|
|
7201
|
+
for (const t of materializedTraits) {
|
|
7202
|
+
for (const embed of traitEmbedNamesOf(t)) {
|
|
7203
|
+
const embedFinal = subs.get(embed);
|
|
7204
|
+
if (!embedFinal) continue;
|
|
7205
|
+
let embedders = embeddersOf.get(embedFinal);
|
|
7206
|
+
if (!embedders) {
|
|
7207
|
+
embedders = [];
|
|
7208
|
+
embeddersOf.set(embedFinal, embedders);
|
|
7209
|
+
}
|
|
7210
|
+
embedders.push(t.name);
|
|
7211
|
+
}
|
|
7212
|
+
}
|
|
7213
|
+
const parentConfigs = new Map(
|
|
7214
|
+
materializedTraits.map((t) => [t.name, t.config])
|
|
7215
|
+
);
|
|
7216
|
+
const transitiveEmbedderChain = (name) => {
|
|
7217
|
+
const chain2 = [];
|
|
7218
|
+
const seenNames = /* @__PURE__ */ new Set([name]);
|
|
7219
|
+
let cur = embeddersOf.get(name)?.[0];
|
|
7220
|
+
while (cur !== void 0 && !seenNames.has(cur)) {
|
|
7221
|
+
seenNames.add(cur);
|
|
7222
|
+
const cfg = parentConfigs.get(cur);
|
|
7223
|
+
if (cfg) chain2.push(cfg);
|
|
7224
|
+
cur = embeddersOf.get(cur)?.[0];
|
|
7225
|
+
}
|
|
7226
|
+
return chain2;
|
|
7227
|
+
};
|
|
7228
|
+
entityIds.set(primaryFinalName, primaryId);
|
|
7229
|
+
for (const e of auxEntities) {
|
|
7230
|
+
entityIds.set(
|
|
7231
|
+
subs.get(e.name),
|
|
7232
|
+
asEntityId(deriveMaterializedId(e.id, upstream.id, e.name, localName, "entity"))
|
|
7233
|
+
);
|
|
7234
|
+
}
|
|
7235
|
+
const upstreamPathSet = new Set(upstreamPages.map((rp) => rp.page.path));
|
|
7236
|
+
for (const path of [...Object.keys(ref.pages ?? {}), ...Object.keys(ref.mounts ?? {})]) {
|
|
7237
|
+
if (!upstreamPathSet.has(path)) {
|
|
7238
|
+
errors.push(
|
|
7239
|
+
`Orbital "${localName}" names page path "${path}" but upstream orbital "${upstream.name}" has no page at that path (ORB_O_PAGE_UNKNOWN_PATH)`
|
|
7240
|
+
);
|
|
7241
|
+
}
|
|
7242
|
+
}
|
|
7243
|
+
if (errors.length > 0) return { success: false, errors };
|
|
7244
|
+
const pathMap = new Map(
|
|
7245
|
+
upstreamPages.map((rp) => [rp.page.path, ref.pages?.[rp.page.path] ?? rp.page.path])
|
|
7246
|
+
);
|
|
7247
|
+
const orbitalRename = upstream.name !== localName ? { from: upstream.name, to: localName } : void 0;
|
|
7248
|
+
const finalTraits = materializedTraits.map((trait) => {
|
|
7249
|
+
let next = renameTraitEmbeds(trait, subs);
|
|
7250
|
+
next = renameEntitiesInTrait(next, subs);
|
|
7251
|
+
if (next.linkedEntity !== void 0) {
|
|
7252
|
+
const linkedEntityId = entityIds.get(next.linkedEntity);
|
|
7253
|
+
if (linkedEntityId !== void 0) next = { ...next, linkedEntityId };
|
|
7254
|
+
}
|
|
7255
|
+
next = rewriteEntityRefIds(next, subs, entityIds);
|
|
7256
|
+
next = renameSourceEntityDefinition(next, subs, entityIds);
|
|
7257
|
+
next = rewriteRoleLiteralsInTrait(next, roleFields, ref.roles ?? {});
|
|
7258
|
+
if (fieldSubs.size > 0) next = rewriteEntityFieldsInTrait(next, fieldSubs);
|
|
7259
|
+
next = rewriteListenSources(next, subs, idByName, orbitalRename);
|
|
7260
|
+
if (pathMap.size > 0) {
|
|
7261
|
+
next = rewriteTraitNavigateTargets(next, pathMap);
|
|
7262
|
+
}
|
|
7263
|
+
for (const embedderName of embeddersOf.get(trait.name) ?? []) {
|
|
7264
|
+
const embedderConfig = parentConfigs.get(embedderName);
|
|
7265
|
+
next = resolveForwardedSiblingConfigFrom(next, embedderConfig ? [embedderConfig] : []);
|
|
7266
|
+
}
|
|
7267
|
+
next = resolveForwardedSiblingConfigFrom(next, transitiveEmbedderChain(trait.name));
|
|
7268
|
+
next = resolveForwardedSiblingConfigFrom(next, [], foldedConfig, importedSchemaConfig);
|
|
7269
|
+
if (pathMap.size > 0) {
|
|
7270
|
+
next = rewriteTraitConfigPagePaths(next, pathMap);
|
|
7271
|
+
}
|
|
7272
|
+
next = applyEventRenames(next, ref.events);
|
|
7273
|
+
return next;
|
|
7274
|
+
});
|
|
7275
|
+
const renamedPrimaryEntity = rewriteRoleLiteralsInEntity(
|
|
7276
|
+
renameEntityRelationTargets(
|
|
7277
|
+
rewriteEntityFieldsInEntity(
|
|
7278
|
+
{
|
|
7279
|
+
...upstreamEntity,
|
|
7280
|
+
name: primaryFinalName,
|
|
7281
|
+
id: primaryId
|
|
7282
|
+
},
|
|
7283
|
+
fieldSubs
|
|
7284
|
+
),
|
|
7285
|
+
subs,
|
|
7286
|
+
entityIds
|
|
7287
|
+
),
|
|
7288
|
+
roleFields,
|
|
7289
|
+
ref.roles ?? {}
|
|
7290
|
+
);
|
|
7291
|
+
const extendResult = applyExtendFields(
|
|
7292
|
+
renamedPrimaryEntity,
|
|
7293
|
+
ref.extend,
|
|
7294
|
+
fieldSubs,
|
|
7295
|
+
consumerEntityIds,
|
|
7296
|
+
localName
|
|
7297
|
+
);
|
|
7298
|
+
if (extendResult.errors.length > 0) return { success: false, errors: extendResult.errors };
|
|
7299
|
+
const primaryEntity = extendResult.entity;
|
|
7300
|
+
const finalAuxEntities = auxEntities.map((e) => {
|
|
7301
|
+
const finalName = subs.get(e.name);
|
|
7302
|
+
return rewriteRoleLiteralsInEntity(
|
|
7303
|
+
renameEntityRelationTargets(
|
|
7304
|
+
rewriteEntityFieldsInEntity(
|
|
7305
|
+
{
|
|
7306
|
+
...e,
|
|
7307
|
+
name: finalName,
|
|
7308
|
+
id: entityIds.get(finalName)
|
|
7309
|
+
},
|
|
7310
|
+
fieldSubs
|
|
7311
|
+
),
|
|
7312
|
+
subs,
|
|
7313
|
+
entityIds
|
|
7314
|
+
),
|
|
7315
|
+
roleFields,
|
|
7316
|
+
ref.roles ?? {}
|
|
7317
|
+
);
|
|
7318
|
+
});
|
|
7319
|
+
const finalPages = upstreamPages.map((rp) => {
|
|
7320
|
+
const original = rp.page;
|
|
7321
|
+
const mountNames = ref.mounts?.[original.path] ?? [];
|
|
7322
|
+
const finalPageTraits = [
|
|
7323
|
+
...(original.traits ?? []).filter((tr) => !removedNames.has(tr.ref)).map((tr) => {
|
|
7324
|
+
const finalRef = subs.get(tr.ref) ?? tr.ref;
|
|
7325
|
+
const refId = idByName.get(finalRef);
|
|
7326
|
+
return {
|
|
7327
|
+
...tr,
|
|
7328
|
+
ref: finalRef,
|
|
7329
|
+
...refId !== void 0 ? { refId } : {},
|
|
7330
|
+
...tr.linkedEntity !== void 0 ? { linkedEntity: subs.get(tr.linkedEntity) ?? tr.linkedEntity } : {}
|
|
7331
|
+
};
|
|
7332
|
+
}),
|
|
7333
|
+
...mountNames.map((name) => ({ ref: name }))
|
|
7334
|
+
];
|
|
7335
|
+
return {
|
|
7336
|
+
...original,
|
|
7337
|
+
// Gap (E) — unconditionally prefixed, same as traits/entities (§4.3):
|
|
7338
|
+
// two imports of the same upstream orbital with distinct `pages {}`
|
|
7339
|
+
// path maps must not collide on page NAME (`Duplicate page name`).
|
|
7340
|
+
// `id` is the page-scope sibling of `deriveMaterializedId` (never
|
|
7341
|
+
// `mintId`) — fresh and pairwise-disjoint across imports, same as
|
|
7342
|
+
// trait/entity ids above.
|
|
7343
|
+
name: `${localName}${original.name}`,
|
|
7344
|
+
id: asPageId(deriveMaterializedId(original.id, upstream.id, original.name, localName, "page")),
|
|
7345
|
+
path: pathMap.get(original.path) ?? original.path,
|
|
7346
|
+
...original.primaryEntity !== void 0 ? { primaryEntity: subs.get(original.primaryEntity) ?? original.primaryEntity } : {},
|
|
7347
|
+
traits: finalPageTraits
|
|
7348
|
+
};
|
|
7349
|
+
});
|
|
7350
|
+
const forwardedKnobs = /* @__PURE__ */ new Set();
|
|
7351
|
+
for (const rt of keptTraits) {
|
|
7352
|
+
for (const field of Object.values(rt.trait.config ?? {})) {
|
|
7353
|
+
if (typeof field.default === "string" && field.default.startsWith("@config.")) {
|
|
7354
|
+
const knob = field.default.slice("@config.".length);
|
|
7355
|
+
if (knob.length > 0 && !knob.includes(".")) forwardedKnobs.add(knob);
|
|
7356
|
+
}
|
|
7357
|
+
}
|
|
7358
|
+
}
|
|
7359
|
+
const prunedConfig = foldedConfig ? Object.fromEntries(Object.entries(foldedConfig).filter(([key]) => forwardedKnobs.has(key))) : void 0;
|
|
7360
|
+
const orbitalId = localId ?? (upstream.id ? asOrbitalId(deriveId(upstream.id, localName)) : void 0);
|
|
7361
|
+
refResolverLog.info("orbital-import:materialize", {
|
|
7362
|
+
local: localName,
|
|
7363
|
+
upstream: upstream.name,
|
|
7364
|
+
traits: finalTraits.length,
|
|
7365
|
+
pages: finalPages.length
|
|
7366
|
+
});
|
|
7367
|
+
return {
|
|
7368
|
+
success: true,
|
|
7369
|
+
data: {
|
|
7370
|
+
...upstream,
|
|
7371
|
+
name: localName,
|
|
7372
|
+
...orbitalId ? { id: orbitalId } : {},
|
|
7373
|
+
entity: primaryEntity,
|
|
7374
|
+
...finalAuxEntities.length > 0 ? { auxiliaryEntities: finalAuxEntities } : {},
|
|
7375
|
+
traits: finalTraits,
|
|
7376
|
+
pages: finalPages,
|
|
7377
|
+
emits: void 0,
|
|
7378
|
+
listens: void 0,
|
|
7379
|
+
exposes: void 0,
|
|
7380
|
+
...prunedConfig ? { config: prunedConfig } : { config: void 0 },
|
|
7381
|
+
uses: void 0,
|
|
7382
|
+
reference: void 0
|
|
7383
|
+
},
|
|
7384
|
+
warnings: []
|
|
7385
|
+
};
|
|
7386
|
+
}
|
|
4956
7387
|
/**
|
|
4957
7388
|
* Add local traits for resolution.
|
|
4958
7389
|
*/
|
|
@@ -4972,28 +7403,36 @@ var ReferenceResolver = class {
|
|
|
4972
7403
|
}
|
|
4973
7404
|
};
|
|
4974
7405
|
async function resolveSchema(schema, options) {
|
|
4975
|
-
const resolver = new ReferenceResolver(options);
|
|
7406
|
+
const resolver = new ReferenceResolver({ ...options, schemaConfig: schema.config });
|
|
4976
7407
|
const errors = [];
|
|
4977
7408
|
const warnings = [];
|
|
4978
7409
|
const resolved = [];
|
|
4979
|
-
|
|
7410
|
+
const flattenResult = await resolver.resolveOrbitalImports(schema);
|
|
7411
|
+
if (!flattenResult.success) {
|
|
7412
|
+
return { success: false, errors: flattenResult.errors };
|
|
7413
|
+
}
|
|
7414
|
+
const orbitals = flattenResult.data;
|
|
7415
|
+
for (const orbital of orbitals) {
|
|
4980
7416
|
const inlineTraits = orbital.traits.filter(
|
|
4981
7417
|
(t) => typeof t !== "string" && "stateMachine" in t
|
|
4982
7418
|
);
|
|
4983
7419
|
resolver.addLocalTraits(inlineTraits);
|
|
4984
7420
|
}
|
|
4985
|
-
|
|
7421
|
+
resolver.seedSchemaEntityIds(orbitals);
|
|
7422
|
+
for (const orbital of orbitals) {
|
|
4986
7423
|
const result = await resolver.resolve(orbital);
|
|
4987
7424
|
if (!result.success) {
|
|
4988
7425
|
errors.push(`Orbital "${orbital.name}": ${result.errors.join(", ")}`);
|
|
4989
7426
|
} else {
|
|
4990
7427
|
resolved.push(result.data);
|
|
7428
|
+
resolver.noteResolvedEntityIds(result.data);
|
|
4991
7429
|
warnings.push(...result.warnings.map((w) => `Orbital "${orbital.name}": ${w}`));
|
|
4992
7430
|
}
|
|
4993
7431
|
}
|
|
4994
7432
|
if (errors.length > 0) {
|
|
4995
7433
|
return { success: false, errors };
|
|
4996
7434
|
}
|
|
7435
|
+
resolver.uniquifyCrossOrbitalPulledSiblings(resolved);
|
|
4997
7436
|
return { success: true, data: resolved, warnings };
|
|
4998
7437
|
}
|
|
4999
7438
|
|
|
@@ -5208,4 +7647,4 @@ var InMemoryPersistence = class {
|
|
|
5208
7647
|
}
|
|
5209
7648
|
};
|
|
5210
7649
|
|
|
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 };
|
|
7650
|
+
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 };
|