@almadar/core 10.129.0 → 11.0.1
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/behavior-package.d.ts +49 -11
- package/dist/behavior-package.js +1 -1
- package/dist/{orbital-CkFdDS9f.d.ts → builders-BdgbY7Th.d.ts} +5828 -6917
- package/dist/builders.d.ts +6 -6
- package/dist/builders.js +7 -6
- package/dist/{bus-CcbB__oo.d.ts → bus-C0hFDNFR.d.ts} +262 -354
- package/dist/chunk-347APWFM.js +286 -0
- package/dist/chunk-347APWFM.js.map +1 -0
- package/dist/chunk-5WQ3U7NJ.js +2363 -0
- package/dist/chunk-5WQ3U7NJ.js.map +1 -0
- package/dist/chunk-5YTPYMPZ.js +99 -0
- package/dist/chunk-5YTPYMPZ.js.map +1 -0
- package/dist/chunk-66Q5VX2F.js +3810 -0
- package/dist/chunk-66Q5VX2F.js.map +1 -0
- package/dist/chunk-7GHJU5WI.js +39 -0
- package/dist/chunk-7GHJU5WI.js.map +1 -0
- package/dist/chunk-B4MNHGBP.js +8 -0
- package/dist/chunk-B4MNHGBP.js.map +1 -0
- package/dist/chunk-E4T2MQAV.js +24 -0
- package/dist/chunk-E4T2MQAV.js.map +1 -0
- package/dist/chunk-ENOCKYGA.js +412 -0
- package/dist/chunk-ENOCKYGA.js.map +1 -0
- package/dist/chunk-FGT5OS2Y.js +918 -0
- package/dist/chunk-FGT5OS2Y.js.map +1 -0
- package/dist/chunk-GF7KCLNR.js +3284 -0
- package/dist/chunk-GF7KCLNR.js.map +1 -0
- package/dist/chunk-PNGFWLHD.js +1567 -0
- package/dist/chunk-PNGFWLHD.js.map +1 -0
- package/dist/{chunk-X4SC7FGF.js → chunk-RGACZEYC.js} +99 -96
- package/dist/chunk-RGACZEYC.js.map +1 -0
- package/dist/{chunk-RYPVOI6H.js → chunk-SNZYN7UA.js} +2541 -433
- package/dist/{chunk-RYPVOI6H.js.map → chunk-SNZYN7UA.js.map} +1 -1
- package/dist/{chunk-KDMV222Q.js → chunk-TDNQT3M3.js} +304 -373
- package/dist/chunk-TDNQT3M3.js.map +1 -0
- package/dist/chunk-VG7BRFUD.js +152 -0
- package/dist/chunk-VG7BRFUD.js.map +1 -0
- package/dist/chunk-Z7BI7DE7.js +1293 -0
- package/dist/chunk-Z7BI7DE7.js.map +1 -0
- package/dist/{domain-Dz3jP-UM.d.ts → domain-Cpmja5ak.d.ts} +55 -55
- package/dist/{effect-CiEVLsZz.d.ts → effect-DZaXwSAz.d.ts} +283 -453
- package/dist/{effect-result-Bebwu9yT.d.ts → effect-result-1HpXgeBc.d.ts} +656 -851
- package/dist/{expression-D0Fs0riG.d.ts → expression-DirYKz-f.d.ts} +5 -13
- package/dist/factory/index.d.ts +7 -144
- package/dist/factory/index.js +8 -8
- package/dist/factory-runtime/index.d.ts +7 -6
- package/dist/factory-runtime/index.js +527 -8
- package/dist/factory-runtime/index.js.map +1 -1
- package/dist/fixtures.d.ts +9 -11
- package/dist/fixtures.js +12 -8
- package/dist/fixtures.js.map +1 -1
- package/dist/i18n/index.d.ts +15 -19
- package/dist/i18n/index.js +2 -1
- package/dist/{index-BC-Jycqj.d.ts → index-D7SxwNdv.d.ts} +34 -734
- package/dist/index.d.ts +92 -247
- package/dist/index.js +322 -986
- package/dist/index.js.map +1 -1
- package/dist/kernel-wire.d.ts +3 -3
- package/dist/kernel-wire.js +3 -79
- package/dist/kernel-wire.js.map +1 -1
- package/dist/language/constructs.json +22 -2
- package/dist/language/program-types.json +203 -22
- package/dist/language/protocols.json +46 -0
- package/dist/language/ui-vocabulary.json +1697 -0
- package/dist/language/validation-codes.json +1222 -1212
- package/dist/language/vocabulary.json +44 -8
- package/dist/language-data.d.ts +7 -4
- package/dist/language-data.js +20 -14
- package/dist/language-data.js.map +1 -1
- package/dist/patterns/component-mapping.json +11 -1
- package/dist/patterns/definitions.d.ts +2 -2
- package/dist/patterns/definitions.js +1 -1
- package/dist/patterns/event-contracts.json +1 -15
- package/dist/patterns/game-font-families.json +13 -0
- package/dist/patterns/index.d.ts +24 -120
- package/dist/patterns/index.js +3 -3
- package/dist/patterns/pattern-tile-geometry.json +1065 -0
- package/dist/patterns/patterns-registry.json +2539 -431
- package/dist/patterns/registry.json +2539 -431
- package/dist/trait-sRjIivFq.d.ts +3519 -0
- package/dist/types/index.d.ts +9 -10
- package/dist/types/index.js +11 -5
- package/dist/{types-DGwrltUF.d.ts → types-C6_yPMpn.d.ts} +3 -3
- package/fixtures/events-wire/client-effects-by-trait/response.json +0 -18
- package/fixtures/events-wire/client-effects-provenance/response.json +0 -18
- package/fixtures/events-wire/effect-results-every-kind/response.json +2 -27
- package/fixtures/events-wire/navigate-1/response.json +8 -5
- package/fixtures/events-wire/navigate-2/response.json +11 -8
- package/fixtures/events-wire/navigate-3/response.json +14 -11
- package/fixtures/events-wire/navigate-back/response.json +7 -4
- package/fixtures/events-wire/render-ui-3/response.json +12 -9
- package/fixtures/events-wire/render-ui-clear/response.json +0 -7
- package/fixtures/events-wire/sse-stream/response.json +0 -20
- package/fixtures/events-wire/sse-stream/stream.json +0 -20
- package/fixtures/events-wire/stateless-traits/response.json +14 -5
- package/fixtures/kernel-wire/golden/basic-entity.json +1687 -0
- package/fixtures/kernel-wire/golden/entity-rerender.json +743 -0
- package/fixtures/kernel-wire/golden/rollback.json +793 -0
- package/fixtures/kernel-wire/golden/tick-counter.json +1538 -0
- package/fixtures/kernel-wire/golden/two-orbital-chore.json +847 -0
- package/fixtures/kernel-wire/golden/two-orbital-task.json +457 -0
- package/fixtures/kernel-wire/played-step.json +136 -0
- package/fixtures/kernel-wire/scripts/basic-entity.json +28 -0
- package/fixtures/kernel-wire/scripts/entity-rerender.json +13 -0
- package/fixtures/kernel-wire/scripts/rollback.json +53 -0
- package/fixtures/kernel-wire/scripts/tick-counter.json +26 -0
- package/fixtures/kernel-wire/scripts/two-orbital-chore.json +9 -0
- package/fixtures/kernel-wire/scripts/two-orbital-task.json +9 -0
- package/package.json +28 -19
- package/dist/builders-DmZE5By0.d.ts +0 -2663
- package/dist/chunk-45I2O4SJ.js +0 -4646
- package/dist/chunk-45I2O4SJ.js.map +0 -1
- package/dist/chunk-6LR43Z5E.js +0 -3061
- package/dist/chunk-6LR43Z5E.js.map +0 -1
- package/dist/chunk-GIUA3NUJ.js +0 -809
- package/dist/chunk-GIUA3NUJ.js.map +0 -1
- package/dist/chunk-GTY53NS5.js +0 -1908
- package/dist/chunk-GTY53NS5.js.map +0 -1
- package/dist/chunk-JOHDVS6J.js +0 -1614
- package/dist/chunk-JOHDVS6J.js.map +0 -1
- package/dist/chunk-KDMV222Q.js.map +0 -1
- package/dist/chunk-QRHJUS3D.js +0 -23
- package/dist/chunk-QRHJUS3D.js.map +0 -1
- package/dist/chunk-QUOTJULD.js +0 -4009
- package/dist/chunk-QUOTJULD.js.map +0 -1
- package/dist/chunk-V5VNGRVU.js +0 -66
- package/dist/chunk-V5VNGRVU.js.map +0 -1
- package/dist/chunk-X4SC7FGF.js.map +0 -1
- package/dist/entityAccess-BPSz1i2n.d.ts +0 -80
- package/dist/mock/index.d.ts +0 -153
- package/dist/mock/index.js +0 -190
- package/dist/mock/index.js.map +0 -1
- package/dist/schema-T5RT5s6H.d.ts +0 -282
- package/dist/state-machine/index.d.ts +0 -359
- package/dist/state-machine/index.js +0 -3
- package/dist/state-machine/index.js.map +0 -1
package/dist/chunk-6LR43Z5E.js
DELETED
|
@@ -1,3061 +0,0 @@
|
|
|
1
|
-
import { isInlineTrait, overrideDeclaredKnobs, mergeCallSiteConfigOverrides, isCallSiteConfigDeclaration, isEntityReferenceAny, isPageReference, isRoutePage, parseOrbitalSchema, isOrbitalValue, OrbitalValueSchema, canonicalJson, isEntityReference, parseEntityRef, isEntityCall, unionOsGrants } from './chunk-45I2O4SJ.js';
|
|
2
|
-
import { ledgerRename, EntityFieldSchema, persistenceModeAllowsOverrides } from './chunk-GTY53NS5.js';
|
|
3
|
-
import { isJsonObject } from './chunk-QRHJUS3D.js';
|
|
4
|
-
|
|
5
|
-
// src/builders/apply-config-overrides.ts
|
|
6
|
-
function overrideTrait(trait, values) {
|
|
7
|
-
if (isInlineTrait(trait)) {
|
|
8
|
-
const config = trait.config;
|
|
9
|
-
if (config === void 0) return trait;
|
|
10
|
-
const next = { ...config };
|
|
11
|
-
for (const [field, value] of Object.entries(values)) {
|
|
12
|
-
const decl = config[field];
|
|
13
|
-
if (decl !== void 0) {
|
|
14
|
-
next[field] = { ...decl, default: value };
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return { ...trait, config: next };
|
|
18
|
-
}
|
|
19
|
-
return { ...trait, config: mergeCallSiteConfigOverrides(trait.config ?? {}, values) };
|
|
20
|
-
}
|
|
21
|
-
function traitIdentity(trait) {
|
|
22
|
-
if (trait.name !== void 0) return trait.name;
|
|
23
|
-
return "ref" in trait ? trait.ref : void 0;
|
|
24
|
-
}
|
|
25
|
-
function applyTraitConfigOverrides(schema, overrides) {
|
|
26
|
-
if (overrides === void 0 || Object.keys(overrides).length === 0) return schema;
|
|
27
|
-
return {
|
|
28
|
-
...schema,
|
|
29
|
-
orbitals: schema.orbitals.map((orbital) => ({
|
|
30
|
-
...orbital,
|
|
31
|
-
traits: orbital.traits.map((trait) => {
|
|
32
|
-
if (typeof trait === "string") return trait;
|
|
33
|
-
const id = traitIdentity(trait);
|
|
34
|
-
const values = id !== void 0 ? overrides[id] : void 0;
|
|
35
|
-
return values !== void 0 ? overrideTrait(trait, values) : trait;
|
|
36
|
-
})
|
|
37
|
-
}))
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/builders/layout-strategy.ts
|
|
42
|
-
function hasSequentialChain(wiring) {
|
|
43
|
-
if (wiring.length < 2) {
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
const adjacency = /* @__PURE__ */ new Map();
|
|
47
|
-
const allTargets = /* @__PURE__ */ new Set();
|
|
48
|
-
for (const entry of wiring) {
|
|
49
|
-
let targets = adjacency.get(entry.from);
|
|
50
|
-
if (!targets) {
|
|
51
|
-
targets = /* @__PURE__ */ new Set();
|
|
52
|
-
adjacency.set(entry.from, targets);
|
|
53
|
-
}
|
|
54
|
-
targets.add(entry.to);
|
|
55
|
-
allTargets.add(entry.to);
|
|
56
|
-
}
|
|
57
|
-
const roots = [];
|
|
58
|
-
for (const from of adjacency.keys()) {
|
|
59
|
-
if (!allTargets.has(from)) {
|
|
60
|
-
roots.push(from);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const starts = roots.length > 0 ? roots : [...adjacency.keys()];
|
|
64
|
-
for (const start of starts) {
|
|
65
|
-
let current = start;
|
|
66
|
-
let length = 1;
|
|
67
|
-
const visited = /* @__PURE__ */ new Set([current]);
|
|
68
|
-
while (true) {
|
|
69
|
-
const nexts = adjacency.get(current);
|
|
70
|
-
if (!nexts || nexts.size === 0) break;
|
|
71
|
-
let advanced = false;
|
|
72
|
-
for (const next of nexts) {
|
|
73
|
-
if (!visited.has(next)) {
|
|
74
|
-
visited.add(next);
|
|
75
|
-
current = next;
|
|
76
|
-
length++;
|
|
77
|
-
advanced = true;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (!advanced) break;
|
|
82
|
-
}
|
|
83
|
-
if (length >= 3) {
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
function detectLayoutStrategy(orbitals, eventWiring) {
|
|
90
|
-
if (eventWiring && eventWiring.length > 0 && hasSequentialChain(eventWiring)) {
|
|
91
|
-
return "wizard-flow";
|
|
92
|
-
}
|
|
93
|
-
const count = orbitals.length;
|
|
94
|
-
if (count <= 1) {
|
|
95
|
-
return "single";
|
|
96
|
-
}
|
|
97
|
-
if (count <= 4) {
|
|
98
|
-
return "tabs";
|
|
99
|
-
}
|
|
100
|
-
return "sidebar";
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// src/builders/event-wiring.ts
|
|
104
|
-
function findInlineTrait(orbitals, name) {
|
|
105
|
-
for (const orbital of orbitals) {
|
|
106
|
-
for (const traitRef of orbital.traits) {
|
|
107
|
-
if (isInlineTrait(traitRef) && traitRef.name === name) {
|
|
108
|
-
return traitRef;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return null;
|
|
113
|
-
}
|
|
114
|
-
function hasEmit(emits, event) {
|
|
115
|
-
return emits.some((e) => e.event === event);
|
|
116
|
-
}
|
|
117
|
-
function hasListen(listens, event, triggers) {
|
|
118
|
-
return listens.some((l) => l.event === event && l.triggers === triggers);
|
|
119
|
-
}
|
|
120
|
-
function applyEventWiring(orbitals, wiring) {
|
|
121
|
-
const cloned = JSON.parse(
|
|
122
|
-
JSON.stringify(orbitals)
|
|
123
|
-
);
|
|
124
|
-
for (const entry of wiring) {
|
|
125
|
-
const sourceTrait = findInlineTrait(cloned, entry.from);
|
|
126
|
-
if (sourceTrait) {
|
|
127
|
-
if (!sourceTrait.emits) {
|
|
128
|
-
sourceTrait.emits = [];
|
|
129
|
-
}
|
|
130
|
-
if (!hasEmit(sourceTrait.emits, entry.event)) {
|
|
131
|
-
sourceTrait.emits.push({
|
|
132
|
-
event: entry.event,
|
|
133
|
-
scope: "external"
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const targetTrait = findInlineTrait(cloned, entry.to);
|
|
138
|
-
if (targetTrait) {
|
|
139
|
-
if (!targetTrait.listens) {
|
|
140
|
-
targetTrait.listens = [];
|
|
141
|
-
}
|
|
142
|
-
if (!hasListen(targetTrait.listens, entry.event, entry.triggers)) {
|
|
143
|
-
targetTrait.listens.push({
|
|
144
|
-
event: entry.event,
|
|
145
|
-
triggers: entry.triggers,
|
|
146
|
-
scope: "external"
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return cloned;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// src/builders/compose-behaviors.ts
|
|
155
|
-
function isSchema(input) {
|
|
156
|
-
return "orbitals" in input && Array.isArray(input.orbitals);
|
|
157
|
-
}
|
|
158
|
-
function asDefinitions(inputs) {
|
|
159
|
-
return inputs.flatMap(
|
|
160
|
-
(input) => isSchema(input) ? input.orbitals : [input]
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
|
-
function mergeLedgers(inputs) {
|
|
164
|
-
const merged = /* @__PURE__ */ new Map();
|
|
165
|
-
let sawLedger = false;
|
|
166
|
-
for (const input of inputs) {
|
|
167
|
-
if (!isSchema(input) || input.ledger === void 0) continue;
|
|
168
|
-
sawLedger = true;
|
|
169
|
-
for (const [id, entry] of Object.entries(input.ledger.entries)) {
|
|
170
|
-
if (!merged.has(id)) merged.set(id, entry);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (!sawLedger) return void 0;
|
|
174
|
-
const entries = {};
|
|
175
|
-
for (const [id, entry] of [...merged.entries()].sort(
|
|
176
|
-
([a], [b]) => a < b ? -1 : a > b ? 1 : 0
|
|
177
|
-
)) {
|
|
178
|
-
entries[id] = entry;
|
|
179
|
-
}
|
|
180
|
-
return { schemaVersion: 1, entries };
|
|
181
|
-
}
|
|
182
|
-
function mergeSchemaVersions(inputs) {
|
|
183
|
-
let max;
|
|
184
|
-
for (const input of inputs) {
|
|
185
|
-
if (!isSchema(input) || input.schemaVersion === void 0) continue;
|
|
186
|
-
max = max === void 0 ? input.schemaVersion : Math.max(max, input.schemaVersion);
|
|
187
|
-
}
|
|
188
|
-
return max;
|
|
189
|
-
}
|
|
190
|
-
function toKebabCase(name) {
|
|
191
|
-
return name.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
192
|
-
}
|
|
193
|
-
function generatePages(orbitals, strategy) {
|
|
194
|
-
switch (strategy) {
|
|
195
|
-
case "single": {
|
|
196
|
-
const orbital = orbitals[0];
|
|
197
|
-
const name = orbital?.name ?? "Main";
|
|
198
|
-
return [
|
|
199
|
-
{
|
|
200
|
-
name: `${name}Page`,
|
|
201
|
-
path: "/",
|
|
202
|
-
isInitial: true,
|
|
203
|
-
primaryEntity: getEntityName(orbital)
|
|
204
|
-
}
|
|
205
|
-
];
|
|
206
|
-
}
|
|
207
|
-
case "dashboard": {
|
|
208
|
-
return [
|
|
209
|
-
{
|
|
210
|
-
name: "DashboardPage",
|
|
211
|
-
path: "/",
|
|
212
|
-
viewType: "dashboard",
|
|
213
|
-
isInitial: true
|
|
214
|
-
}
|
|
215
|
-
];
|
|
216
|
-
}
|
|
217
|
-
case "sidebar":
|
|
218
|
-
case "tabs":
|
|
219
|
-
case "wizard-flow": {
|
|
220
|
-
return orbitals.map((orbital, index) => ({
|
|
221
|
-
name: `${orbital.name}Page`,
|
|
222
|
-
path: index === 0 ? "/" : `/${toKebabCase(orbital.name)}`,
|
|
223
|
-
isInitial: index === 0,
|
|
224
|
-
primaryEntity: getEntityName(orbital)
|
|
225
|
-
}));
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
function getEntityName(orbital) {
|
|
230
|
-
if (!orbital) return void 0;
|
|
231
|
-
const entity = orbital.entity;
|
|
232
|
-
if (typeof entity === "string") {
|
|
233
|
-
return entity.replace(".entity", "");
|
|
234
|
-
}
|
|
235
|
-
return entity.name;
|
|
236
|
-
}
|
|
237
|
-
function composeBehaviors(input) {
|
|
238
|
-
const {
|
|
239
|
-
appName,
|
|
240
|
-
orbitals: rawInputs,
|
|
241
|
-
layoutStrategy: strategyInput,
|
|
242
|
-
eventWiring
|
|
243
|
-
} = input;
|
|
244
|
-
const rawOrbitals = asDefinitions(rawInputs);
|
|
245
|
-
const wiredOrbitals = eventWiring && eventWiring.length > 0 ? applyEventWiring(rawOrbitals, eventWiring) : rawOrbitals;
|
|
246
|
-
const strategy = !strategyInput || strategyInput === "auto" ? detectLayoutStrategy(wiredOrbitals, eventWiring) : strategyInput;
|
|
247
|
-
const pages = generatePages(wiredOrbitals, strategy);
|
|
248
|
-
const orbitalsWithPages = wiredOrbitals.map((orbital, index) => {
|
|
249
|
-
if (orbital.pages && orbital.pages.length > 0) {
|
|
250
|
-
return orbital;
|
|
251
|
-
}
|
|
252
|
-
if (orbital.reference !== void 0) {
|
|
253
|
-
return orbital;
|
|
254
|
-
}
|
|
255
|
-
const page = strategy === "dashboard" || strategy === "single" ? pages[0] : pages[index];
|
|
256
|
-
return {
|
|
257
|
-
...orbital,
|
|
258
|
-
pages: page ? [page] : []
|
|
259
|
-
};
|
|
260
|
-
});
|
|
261
|
-
const ledger = mergeLedgers(rawInputs);
|
|
262
|
-
const schemaVersion = mergeSchemaVersions(rawInputs);
|
|
263
|
-
const schema = {
|
|
264
|
-
name: appName,
|
|
265
|
-
version: "1.0.0",
|
|
266
|
-
orbitals: orbitalsWithPages,
|
|
267
|
-
...schemaVersion !== void 0 ? { schemaVersion } : {},
|
|
268
|
-
...ledger !== void 0 ? { ledger } : {}
|
|
269
|
-
};
|
|
270
|
-
return {
|
|
271
|
-
schema,
|
|
272
|
-
layout: {
|
|
273
|
-
strategy,
|
|
274
|
-
pageCount: pages.length
|
|
275
|
-
},
|
|
276
|
-
wiring: {
|
|
277
|
-
connections: eventWiring?.length ?? 0
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// src/expectation-shape.ts
|
|
283
|
-
function mergeExpectationShape(existing, incoming) {
|
|
284
|
-
if (existing === void 0 && incoming === void 0) return void 0;
|
|
285
|
-
const mergeField = (prior, field) => {
|
|
286
|
-
const fail = () => {
|
|
287
|
-
throw new Error(`expectation shape mismatch \u2014 field "${field.name ?? prior.name}" has incompatible type constraints`);
|
|
288
|
-
};
|
|
289
|
-
const priorType = prior.type === "enum" ? "string" : prior.type;
|
|
290
|
-
const fieldType = field.type === "enum" ? "string" : field.type;
|
|
291
|
-
if (priorType !== fieldType) return fail();
|
|
292
|
-
if (prior.type === "relation" && field.type === "relation") {
|
|
293
|
-
if (prior.relation.entityId !== void 0 && field.relation.entityId !== void 0 && prior.relation.entityId !== field.relation.entityId) return fail();
|
|
294
|
-
const relation = (value) => ({ entity: value.entity, cardinality: value.cardinality, field: value.field, onDelete: value.onDelete });
|
|
295
|
-
if (canonicalJson(relation(prior.relation)) !== canonicalJson(relation(field.relation))) return fail();
|
|
296
|
-
}
|
|
297
|
-
if (prior.type === "tuple" && field.type === "tuple" && canonicalJson(Object.keys(prior.properties).sort()) !== canonicalJson(Object.keys(field.properties).sort())) return fail();
|
|
298
|
-
const min = prior.min === void 0 ? field.min : field.min === void 0 ? prior.min : Math.max(prior.min, field.min);
|
|
299
|
-
const max = prior.max === void 0 ? field.max : field.max === void 0 ? prior.max : Math.min(prior.max, field.max);
|
|
300
|
-
if (min !== void 0 && max !== void 0 && min > max) return fail();
|
|
301
|
-
let merged2 = { ...prior, ...prior.required === true || field.required === true ? { required: true } : {}, ...min !== void 0 ? { min } : {}, ...max !== void 0 ? { max } : {} };
|
|
302
|
-
if (prior.type === "relation" && field.type === "relation") merged2 = { ...merged2, type: "relation", relation: { ...prior.relation, ...prior.relation.entityId === void 0 && field.relation.entityId !== void 0 ? { entityId: field.relation.entityId } : {} } };
|
|
303
|
-
if ("values" in prior || "values" in field) {
|
|
304
|
-
const values = [.../* @__PURE__ */ new Set([..."values" in prior ? prior.values ?? [] : [], ..."values" in field ? field.values ?? [] : []])];
|
|
305
|
-
if (values.length > 0) merged2 = EntityFieldSchema.parse({ ...merged2, values });
|
|
306
|
-
}
|
|
307
|
-
if (prior.properties !== void 0 || field.properties !== void 0) {
|
|
308
|
-
const properties = { ...prior.properties };
|
|
309
|
-
for (const [key, value] of Object.entries(field.properties ?? {})) properties[key] = properties[key] === void 0 ? value : mergeField(properties[key], value);
|
|
310
|
-
merged2 = { ...merged2, properties };
|
|
311
|
-
}
|
|
312
|
-
if ("items" in prior || "items" in field) {
|
|
313
|
-
const priorItems = "items" in prior ? prior.items : void 0;
|
|
314
|
-
const incomingItems = "items" in field ? field.items : void 0;
|
|
315
|
-
const items = priorItems === void 0 ? incomingItems : incomingItems === void 0 ? priorItems : mergeField(priorItems, incomingItems);
|
|
316
|
-
if (items !== void 0) merged2 = EntityFieldSchema.parse({ ...merged2, items });
|
|
317
|
-
}
|
|
318
|
-
return merged2;
|
|
319
|
-
};
|
|
320
|
-
const merged = [...existing ?? []];
|
|
321
|
-
for (const field of incoming ?? []) {
|
|
322
|
-
const index = merged.findIndex((candidate) => candidate.name === field.name);
|
|
323
|
-
const prior = merged[index];
|
|
324
|
-
if (prior === void 0) merged.push(field);
|
|
325
|
-
else merged[index] = mergeField(prior, field);
|
|
326
|
-
}
|
|
327
|
-
return merged;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// src/builders/rename-entity.ts
|
|
331
|
-
var ENTITY_VALUED_KEYS = /* @__PURE__ */ new Set(["entity", "source", "entityType", "linkedEntity", "primaryEntity", "payloadEntity", "extends"]);
|
|
332
|
-
var PERSIST_ACTIONS = /* @__PURE__ */ new Set(["create", "upsert", "update", "delete"]);
|
|
333
|
-
function renameAtomEntitySlots(trait, atomOf, from, to) {
|
|
334
|
-
if (!isJsonObject(trait) || typeof trait["ref"] !== "string") return trait;
|
|
335
|
-
const atom = atomOf(trait["ref"]);
|
|
336
|
-
if (atom === void 0) return trait;
|
|
337
|
-
const next = { ...trait };
|
|
338
|
-
if (trait["linkedEntity"] === void 0 && atom.linkedEntity === from) next["linkedEntity"] = to;
|
|
339
|
-
const config = trait["config"];
|
|
340
|
-
if (isJsonObject(config)) {
|
|
341
|
-
const renamed = { ...config };
|
|
342
|
-
for (const [knob, declared] of Object.entries(atom.config ?? {})) {
|
|
343
|
-
const field = renamed[knob];
|
|
344
|
-
if (isCallSiteConfigDeclaration(declared) && declared.type === "entity" && isJsonObject(field) && field["default"] === from) renamed[knob] = { ...field, default: to };
|
|
345
|
-
}
|
|
346
|
-
next["config"] = renamed;
|
|
347
|
-
}
|
|
348
|
-
const typeArgs = trait["typeArgs"];
|
|
349
|
-
if (isJsonObject(typeArgs)) {
|
|
350
|
-
const entityParams = new Set((atom.typeParams ?? []).filter((p) => p.kind === "Entity").map((p) => p.name));
|
|
351
|
-
next["typeArgs"] = Object.fromEntries(Object.entries(typeArgs).map(([param, value]) => [param, entityParams.has(param) && value === from ? to : value]));
|
|
352
|
-
}
|
|
353
|
-
return next;
|
|
354
|
-
}
|
|
355
|
-
function renameToken(value, from, to) {
|
|
356
|
-
if (value === `@${from}`) return `@${to}`;
|
|
357
|
-
if (value.startsWith(`@${from}.`)) return `@${to}${value.slice(from.length + 1)}`;
|
|
358
|
-
return value;
|
|
359
|
-
}
|
|
360
|
-
function walk(node, from, to, options) {
|
|
361
|
-
if (typeof node === "string") return renameToken(node, from, to);
|
|
362
|
-
if (Array.isArray(node)) {
|
|
363
|
-
const out2 = node.map((item) => walk(item, from, to, options));
|
|
364
|
-
const op = node[0];
|
|
365
|
-
if ((op === "fetch" || op === "spawn") && node[1] === from) out2[1] = to;
|
|
366
|
-
if (op === "ref" && node.length === 2 && node[1] === from) out2[1] = to;
|
|
367
|
-
if (op === "persist" && typeof node[1] === "string" && PERSIST_ACTIONS.has(node[1]) && node[2] === from) out2[2] = to;
|
|
368
|
-
return out2;
|
|
369
|
-
}
|
|
370
|
-
if (!isJsonObject(node)) return node;
|
|
371
|
-
const out = {};
|
|
372
|
-
for (const [key, value] of Object.entries(node)) {
|
|
373
|
-
if (key === "entityRefIds" && isJsonObject(value)) {
|
|
374
|
-
out[key] = Object.fromEntries(Object.entries(value).map(([name, id]) => [name === from ? to : name, id]));
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
if (typeof value === "string" && ENTITY_VALUED_KEYS.has(key) && value === from) {
|
|
378
|
-
out[key] = to;
|
|
379
|
-
continue;
|
|
380
|
-
}
|
|
381
|
-
if (key === "type" && typeof value === "string" && (value === from || value === `[${from}]`)) {
|
|
382
|
-
out[key] = value === from ? to : `[${to}]`;
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
out[key] = walk(value, from, to, options);
|
|
386
|
-
}
|
|
387
|
-
const isDeclaration = node["name"] === from && Array.isArray(node["fields"]);
|
|
388
|
-
if (isDeclaration) {
|
|
389
|
-
out["name"] = to;
|
|
390
|
-
if (options.collection !== void 0) out["collection"] = options.collection;
|
|
391
|
-
}
|
|
392
|
-
if ((node["kind"] === "persist" || node["kind"] === "fetch") && node["resource"] === from) out["resource"] = to;
|
|
393
|
-
const isExpectation = node["name"] === from && (node["kind"] === "entity" || node["kind"] === "identity");
|
|
394
|
-
if (isExpectation) out["name"] = to;
|
|
395
|
-
if (node["type"] === "entity" && node["default"] === from) out["default"] = to;
|
|
396
|
-
return out;
|
|
397
|
-
}
|
|
398
|
-
function renameEntity(orbitals, from, to, options = {}) {
|
|
399
|
-
if (from === to) return [...orbitals];
|
|
400
|
-
return orbitals.map((orbital) => {
|
|
401
|
-
const tree = JSON.parse(JSON.stringify(orbital));
|
|
402
|
-
const atomTraitOf = options.atomTraitOf;
|
|
403
|
-
if (atomTraitOf !== void 0 && isJsonObject(tree)) {
|
|
404
|
-
const atomOf = (ref) => atomTraitOf(orbital, ref);
|
|
405
|
-
if (Array.isArray(tree["traits"])) tree["traits"] = tree["traits"].map((t) => renameAtomEntitySlots(t, atomOf, from, to));
|
|
406
|
-
if (Array.isArray(tree["pages"])) {
|
|
407
|
-
tree["pages"] = tree["pages"].map((page) => isJsonObject(page) && Array.isArray(page["traits"]) ? { ...page, traits: page["traits"].map((t) => renameAtomEntitySlots(t, atomOf, from, to)) } : page);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
const renamed = JSON.parse(JSON.stringify(walk(tree, from, to, options)));
|
|
411
|
-
return renamed;
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
function declarationIds(orbitals, name) {
|
|
415
|
-
const ids = [];
|
|
416
|
-
const visit = (node) => {
|
|
417
|
-
if (Array.isArray(node)) {
|
|
418
|
-
node.forEach(visit);
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
if (!isJsonObject(node)) return;
|
|
422
|
-
if (node["name"] === name && Array.isArray(node["fields"]) && typeof node["id"] === "string") ids.push(node["id"]);
|
|
423
|
-
Object.values(node).forEach(visit);
|
|
424
|
-
};
|
|
425
|
-
visit(JSON.parse(JSON.stringify(orbitals)));
|
|
426
|
-
return ids;
|
|
427
|
-
}
|
|
428
|
-
function renameEntityInSchema(schema, from, to, options = {}, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
429
|
-
const orbitals = renameEntity(schema.orbitals, from, to, options);
|
|
430
|
-
let ledger = schema.ledger;
|
|
431
|
-
if (ledger !== void 0) {
|
|
432
|
-
for (const id of declarationIds(schema.orbitals, from)) {
|
|
433
|
-
if (ledger.entries[id] !== void 0) ledger = ledgerRename(ledger, id, to, at);
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
return { ...schema, orbitals, ...ledger !== void 0 ? { ledger } : {} };
|
|
437
|
-
}
|
|
438
|
-
function entityRenameBlockers(orbitals, name, atomTraitOf) {
|
|
439
|
-
const isRebindable = (orbital, ref) => atomTraitOf(orbital, ref)?.entityRebindable === true;
|
|
440
|
-
const blockers = [];
|
|
441
|
-
for (const orbital of orbitals) {
|
|
442
|
-
for (const trait of orbital.traits ?? []) {
|
|
443
|
-
if (typeof trait !== "object" || !("ref" in trait) || typeof trait.ref !== "string") continue;
|
|
444
|
-
const bound = trait.linkedEntity ?? atomTraitOf(orbital, trait.ref)?.linkedEntity;
|
|
445
|
-
if (bound !== name || isRebindable(orbital, trait.ref)) continue;
|
|
446
|
-
blockers.push({ orbitalName: orbital.name, traitName: trait.name ?? trait.ref, traitRef: trait.ref });
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
return blockers;
|
|
450
|
-
}
|
|
451
|
-
function atomTraitResolver(loadBehaviorOrb) {
|
|
452
|
-
const loaded = /* @__PURE__ */ new Map();
|
|
453
|
-
return (orbital, traitRef) => {
|
|
454
|
-
const [alias, kind, traitName] = traitRef.split(".");
|
|
455
|
-
if (kind !== "traits" || traitName === void 0) return void 0;
|
|
456
|
-
const use = (orbital.uses ?? []).find((u) => u.as === alias);
|
|
457
|
-
if (use === void 0) return void 0;
|
|
458
|
-
const behavior = use.from.split("/").pop() ?? use.from;
|
|
459
|
-
if (!loaded.has(behavior)) loaded.set(behavior, loadBehaviorOrb(behavior));
|
|
460
|
-
for (const atomOrbital of loaded.get(behavior)?.orbitals ?? []) {
|
|
461
|
-
for (const trait of atomOrbital.traits ?? []) {
|
|
462
|
-
if (typeof trait === "object" && !("ref" in trait) && trait.name === traitName) return trait;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
return void 0;
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
function renameOrbitalNode(node, from, to) {
|
|
469
|
-
if (Array.isArray(node)) return node.map((item) => renameOrbitalNode(item, from, to));
|
|
470
|
-
if (!isJsonObject(node)) return node;
|
|
471
|
-
const out = {};
|
|
472
|
-
for (const [key, value] of Object.entries(node)) out[key] = renameOrbitalNode(value, from, to);
|
|
473
|
-
if (node["kind"] === "orbital" && node["orbital"] === from) out["orbital"] = to;
|
|
474
|
-
return out;
|
|
475
|
-
}
|
|
476
|
-
function renameOrbital(orbitals, from, to) {
|
|
477
|
-
if (from === to) return [...orbitals];
|
|
478
|
-
return orbitals.map((orbital) => {
|
|
479
|
-
const renamed = JSON.parse(JSON.stringify(renameOrbitalNode(JSON.parse(JSON.stringify(orbital)), from, to)));
|
|
480
|
-
return renamed.name === from ? { ...renamed, name: to } : renamed;
|
|
481
|
-
});
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// src/data-bearing.ts
|
|
485
|
-
function touchesRecord(effect, name) {
|
|
486
|
-
if (!Array.isArray(effect)) return false;
|
|
487
|
-
if (effect[0] === "fetch" && effect[1] === name) return true;
|
|
488
|
-
if (effect[0] === "persist" && effect[2] === name) return true;
|
|
489
|
-
for (const item of effect) {
|
|
490
|
-
if (Array.isArray(item) && touchesRecord(item, name)) return true;
|
|
491
|
-
}
|
|
492
|
-
return false;
|
|
493
|
-
}
|
|
494
|
-
function orbitalTouchesOwnRecord(orbital) {
|
|
495
|
-
const entity = orbital.entity;
|
|
496
|
-
const name = typeof entity === "object" && entity !== null && "name" in entity ? entity.name : void 0;
|
|
497
|
-
if (typeof name !== "string") return false;
|
|
498
|
-
return (orbital.traits ?? []).some(
|
|
499
|
-
(trait) => isInlineTrait(trait) && (trait.stateMachine?.transitions ?? []).some((t) => (t.effects ?? []).some((e) => touchesRecord(e, name)))
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// src/factory-runtime/apply-params-to-orb.ts
|
|
504
|
-
function validateOrbitalFactoryParams(manifest, raw) {
|
|
505
|
-
if (raw === null || Array.isArray(raw)) {
|
|
506
|
-
return {
|
|
507
|
-
ok: false,
|
|
508
|
-
error: { kind: "not-object", received: Array.isArray(raw) ? "array" : "null" }
|
|
509
|
-
};
|
|
510
|
-
}
|
|
511
|
-
const ALLOWED_KEYS = new Set(manifest.paramFields.map((f) => f.name));
|
|
512
|
-
for (const key of Object.keys(raw)) {
|
|
513
|
-
if (!ALLOWED_KEYS.has(key)) {
|
|
514
|
-
return { ok: false, error: { kind: "unknown-key", key } };
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
const candidate = raw;
|
|
518
|
-
if (candidate.traitOverrides !== void 0) {
|
|
519
|
-
const to = candidate.traitOverrides;
|
|
520
|
-
if (to === null || typeof to !== "object" || Array.isArray(to)) {
|
|
521
|
-
return {
|
|
522
|
-
ok: false,
|
|
523
|
-
error: {
|
|
524
|
-
kind: "trait-overrides-not-object",
|
|
525
|
-
received: Array.isArray(to) ? "array" : typeof to
|
|
526
|
-
}
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
const allowed = new Set(manifest.traitNames);
|
|
530
|
-
for (const traitName of Object.keys(to)) {
|
|
531
|
-
if (!allowed.has(traitName)) {
|
|
532
|
-
return {
|
|
533
|
-
ok: false,
|
|
534
|
-
error: {
|
|
535
|
-
kind: "unknown-trait-override",
|
|
536
|
-
trait: traitName,
|
|
537
|
-
allowed: manifest.traitNames
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
if (candidate.config !== void 0) {
|
|
544
|
-
const cfg = candidate.config;
|
|
545
|
-
if (cfg === null || typeof cfg !== "object" || Array.isArray(cfg)) {
|
|
546
|
-
return {
|
|
547
|
-
ok: false,
|
|
548
|
-
error: { kind: "config-not-object", received: Array.isArray(cfg) ? "array" : typeof cfg }
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
const allowedKeys = manifest.configKeys ?? [];
|
|
552
|
-
for (const key of Object.keys(cfg)) {
|
|
553
|
-
if (!allowedKeys.includes(key)) {
|
|
554
|
-
return { ok: false, error: { kind: "unknown-config-key", key, allowed: allowedKeys } };
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
return { ok: true, params: candidate };
|
|
559
|
-
}
|
|
560
|
-
function assertResolvedEntity(entity, orbitalName, orbName) {
|
|
561
|
-
if (typeof entity === "string") {
|
|
562
|
-
throw new Error(
|
|
563
|
-
`applyParamsToOrb: orbital "${orbitalName}" in orb "${orbName}" has an unresolved entity reference (string form). Pass a resolved .orb.`
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
|
-
if ("extends" in entity) {
|
|
567
|
-
throw new Error(
|
|
568
|
-
`applyParamsToOrb: orbital "${orbitalName}" in orb "${orbName}" has an unresolved EntityCall ("extends" form). Pass a resolved .orb.`
|
|
569
|
-
);
|
|
570
|
-
}
|
|
571
|
-
return entity;
|
|
572
|
-
}
|
|
573
|
-
function findOrbitalOrThrow(orb, orbitalName) {
|
|
574
|
-
const orbital = orb.orbitals.find((o) => o.name === orbitalName);
|
|
575
|
-
if (!orbital) {
|
|
576
|
-
throw new Error(
|
|
577
|
-
`applyParamsToOrb: orbital "${orbitalName}" not found in orb "${orb.name}". Available: ${orb.orbitals.map((o) => o.name).join(", ")}`
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
return orbital;
|
|
581
|
-
}
|
|
582
|
-
function buildEntity(ctx, effectiveName, effectiveCollection, params) {
|
|
583
|
-
const canonicalFields = Array.isArray(ctx.canonicalEntity.fields) ? ctx.canonicalEntity.fields : [];
|
|
584
|
-
const extras = params.fields ?? [];
|
|
585
|
-
for (const f of extras) {
|
|
586
|
-
if (f.type === "enum") {
|
|
587
|
-
if (!Array.isArray(f.values) || f.values.length === 0) {
|
|
588
|
-
throw new Error(
|
|
589
|
-
`Field "${f.name ?? "<unnamed>"}" (type: "enum") requires a non-empty \`values: string[]\` array. Got: ${f.values === void 0 ? "undefined" : JSON.stringify(f.values)}.`
|
|
590
|
-
);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
if (f.type === "relation") {
|
|
594
|
-
const rel = f.relation;
|
|
595
|
-
if (!rel || typeof rel.entity !== "string" || rel.entity.length === 0) {
|
|
596
|
-
throw new Error(
|
|
597
|
-
`Field "${f.name ?? "<unnamed>"}" (type: "relation") requires \`relation: { entity: <EntityName>, cardinality: "one" | "many" }\`. Got: ${rel === void 0 ? "undefined" : JSON.stringify(rel)}.`
|
|
598
|
-
);
|
|
599
|
-
}
|
|
600
|
-
if (rel.cardinality !== "one" && rel.cardinality !== "many") {
|
|
601
|
-
throw new Error(
|
|
602
|
-
`Field "${f.name ?? "<unnamed>"}" (type: "relation") requires \`relation.cardinality: "one" | "many"\`. Got: ${rel.cardinality === void 0 ? "undefined" : JSON.stringify(rel.cardinality)}.`
|
|
603
|
-
);
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
let mergedFields;
|
|
608
|
-
if (extras.length === 0) {
|
|
609
|
-
mergedFields = canonicalFields;
|
|
610
|
-
} else {
|
|
611
|
-
const extraNames = new Set(extras.map((f) => f.name));
|
|
612
|
-
mergedFields = [
|
|
613
|
-
...canonicalFields.filter((f) => !extraNames.has(f.name)),
|
|
614
|
-
...extras
|
|
615
|
-
];
|
|
616
|
-
}
|
|
617
|
-
const allowPersistenceOverride = persistenceModeAllowsOverrides(
|
|
618
|
-
ctx.canonicalEntity.persistence,
|
|
619
|
-
ctx.dataBearing
|
|
620
|
-
);
|
|
621
|
-
const entity = {
|
|
622
|
-
name: effectiveName,
|
|
623
|
-
persistence: allowPersistenceOverride ? params.persistence ?? ctx.canonicalEntity.persistence : ctx.canonicalEntity.persistence,
|
|
624
|
-
fields: [...mergedFields]
|
|
625
|
-
};
|
|
626
|
-
if (allowPersistenceOverride && effectiveCollection !== void 0) {
|
|
627
|
-
entity.collection = effectiveCollection;
|
|
628
|
-
} else if (allowPersistenceOverride && entity.persistence === "persistent" && ctx.canonicalEntity.persistence === "runtime") {
|
|
629
|
-
entity.collection = `${(params.entityName ?? effectiveName).toLowerCase()}s`;
|
|
630
|
-
}
|
|
631
|
-
return entity;
|
|
632
|
-
}
|
|
633
|
-
function isTraitReferenceObject(t) {
|
|
634
|
-
if (t === null || typeof t !== "object") return false;
|
|
635
|
-
if (!("ref" in t)) return false;
|
|
636
|
-
return typeof t.ref === "string";
|
|
637
|
-
}
|
|
638
|
-
function isPageRefObject(p) {
|
|
639
|
-
if (p === null || typeof p !== "object") return false;
|
|
640
|
-
if (!("ref" in p)) return false;
|
|
641
|
-
return typeof p.ref === "string";
|
|
642
|
-
}
|
|
643
|
-
function rewriteInlineLinkedEntity(shape, oldName, newName) {
|
|
644
|
-
if (shape.linkedEntity !== oldName) return shape;
|
|
645
|
-
return { ...shape, linkedEntity: newName };
|
|
646
|
-
}
|
|
647
|
-
var ENTITY_POSITIONAL_OPS = [
|
|
648
|
-
{ op: "fetch", entityIndex: 1 },
|
|
649
|
-
{ op: "ref", entityIndex: 1 },
|
|
650
|
-
{ op: "spawn", entityIndex: 1 },
|
|
651
|
-
{ op: "persist", actionGuard: /* @__PURE__ */ new Set(["create", "update", "delete"]), entityIndex: 2 }
|
|
652
|
-
];
|
|
653
|
-
var ENTITY_VALUED_PROPS = /* @__PURE__ */ new Set([
|
|
654
|
-
"entity",
|
|
655
|
-
"source",
|
|
656
|
-
"entityType",
|
|
657
|
-
"linkedEntity"
|
|
658
|
-
]);
|
|
659
|
-
function rewriteEntityInSExpr(value, oldName, newName) {
|
|
660
|
-
if (value === null) return null;
|
|
661
|
-
if (typeof value === "boolean" || typeof value === "number") return value;
|
|
662
|
-
if (typeof value === "string") {
|
|
663
|
-
const prefix = `@${oldName}`;
|
|
664
|
-
if (value === prefix || value.startsWith(`${prefix}.`)) {
|
|
665
|
-
return `@${newName}${value.slice(prefix.length)}`;
|
|
666
|
-
}
|
|
667
|
-
return value;
|
|
668
|
-
}
|
|
669
|
-
if (Array.isArray(value)) {
|
|
670
|
-
const first = value[0];
|
|
671
|
-
if (typeof first === "string") {
|
|
672
|
-
for (const entry of ENTITY_POSITIONAL_OPS) {
|
|
673
|
-
if (first !== entry.op) continue;
|
|
674
|
-
if (entry.actionGuard !== void 0) {
|
|
675
|
-
const action = value[1];
|
|
676
|
-
if (typeof action !== "string" || !entry.actionGuard.has(action)) continue;
|
|
677
|
-
}
|
|
678
|
-
const at = entry.entityIndex;
|
|
679
|
-
const slot = value[at];
|
|
680
|
-
if (typeof slot !== "string" || slot !== oldName) continue;
|
|
681
|
-
const rewritten = [];
|
|
682
|
-
for (let i = 0; i < value.length; i++) {
|
|
683
|
-
rewritten.push(i === at ? newName : rewriteEntityInSExpr(value[i], oldName, newName));
|
|
684
|
-
}
|
|
685
|
-
return rewritten;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return value.map((v) => rewriteEntityInSExpr(v, oldName, newName));
|
|
689
|
-
}
|
|
690
|
-
return rewriteEntityInSExprMap(value, oldName, newName);
|
|
691
|
-
}
|
|
692
|
-
function rewriteEntityInSExprMap(obj, oldName, newName) {
|
|
693
|
-
const next = {};
|
|
694
|
-
for (const [k, v] of Object.entries(obj)) {
|
|
695
|
-
if (ENTITY_VALUED_PROPS.has(k) && typeof v === "string" && v === oldName) {
|
|
696
|
-
next[k] = newName;
|
|
697
|
-
} else {
|
|
698
|
-
next[k] = rewriteEntityInSExpr(v, oldName, newName);
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
return next;
|
|
702
|
-
}
|
|
703
|
-
function rewritePayloadFieldType(typeStr, oldName, newName) {
|
|
704
|
-
if (typeStr === oldName) return newName;
|
|
705
|
-
if (typeStr === `[${oldName}]`) return `[${newName}]`;
|
|
706
|
-
return typeStr;
|
|
707
|
-
}
|
|
708
|
-
function rewriteEventContract(contract, oldName, newName) {
|
|
709
|
-
if (!contract.payloadSchema || contract.payloadSchema.length === 0) return contract;
|
|
710
|
-
return {
|
|
711
|
-
...contract,
|
|
712
|
-
payloadSchema: contract.payloadSchema.map((f) => {
|
|
713
|
-
const next = { ...f, type: rewritePayloadFieldType(f.type, oldName, newName) };
|
|
714
|
-
if (typeof f.entity === "string" && f.entity === oldName) {
|
|
715
|
-
next.entity = newName;
|
|
716
|
-
}
|
|
717
|
-
return next;
|
|
718
|
-
})
|
|
719
|
-
};
|
|
720
|
-
}
|
|
721
|
-
function rewriteListener(listener, oldName, newName) {
|
|
722
|
-
if (!listener.payloadMapping) return listener;
|
|
723
|
-
const nextMapping = {};
|
|
724
|
-
for (const [k, v] of Object.entries(listener.payloadMapping)) {
|
|
725
|
-
nextMapping[k] = rewriteEntityInSExpr(v, oldName, newName);
|
|
726
|
-
}
|
|
727
|
-
return { ...listener, payloadMapping: nextMapping };
|
|
728
|
-
}
|
|
729
|
-
function rewriteTick(tick, oldName, newName) {
|
|
730
|
-
const next = { ...tick };
|
|
731
|
-
if (next.guard !== void 0 && next.guard !== null) {
|
|
732
|
-
next.guard = rewriteEntityInSExpr(next.guard, oldName, newName);
|
|
733
|
-
}
|
|
734
|
-
next.effects = next.effects.map(
|
|
735
|
-
(e) => rewriteEntityInSExpr(e, oldName, newName)
|
|
736
|
-
);
|
|
737
|
-
return next;
|
|
738
|
-
}
|
|
739
|
-
function rebindInlineTraitEntity(trait, oldName, newName) {
|
|
740
|
-
if (oldName === newName) return trait;
|
|
741
|
-
return rewriteEntityInInlineTrait(rewriteInlineLinkedEntity(trait, oldName, newName), oldName, newName);
|
|
742
|
-
}
|
|
743
|
-
function rewriteEntityInInlineTrait(trait, oldName, newName) {
|
|
744
|
-
if (oldName === newName) return trait;
|
|
745
|
-
const next = { ...trait };
|
|
746
|
-
if (next.stateMachine) {
|
|
747
|
-
next.stateMachine = {
|
|
748
|
-
...next.stateMachine,
|
|
749
|
-
transitions: next.stateMachine.transitions.map((t) => {
|
|
750
|
-
const updated = { ...t };
|
|
751
|
-
if (updated.guard !== void 0 && updated.guard !== null) {
|
|
752
|
-
updated.guard = rewriteEntityInSExpr(updated.guard, oldName, newName);
|
|
753
|
-
}
|
|
754
|
-
if (updated.effects) {
|
|
755
|
-
updated.effects = updated.effects.map(
|
|
756
|
-
(e) => rewriteEntityInSExpr(e, oldName, newName)
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
return updated;
|
|
760
|
-
})
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
if (next.initialEffects) {
|
|
764
|
-
next.initialEffects = next.initialEffects.map(
|
|
765
|
-
(e) => rewriteEntityInSExpr(e, oldName, newName)
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
if (next.ticks) {
|
|
769
|
-
next.ticks = next.ticks.map((t) => rewriteTick(t, oldName, newName));
|
|
770
|
-
}
|
|
771
|
-
if (next.emits) {
|
|
772
|
-
next.emits = next.emits.map((c) => rewriteEventContract(c, oldName, newName));
|
|
773
|
-
}
|
|
774
|
-
if (next.listens) {
|
|
775
|
-
next.listens = next.listens.map((l) => rewriteListener(l, oldName, newName));
|
|
776
|
-
}
|
|
777
|
-
return next;
|
|
778
|
-
}
|
|
779
|
-
function rebuildTraits(traits) {
|
|
780
|
-
return traits.map((t) => {
|
|
781
|
-
if (!isTraitReferenceObject(t)) return t;
|
|
782
|
-
return makeTraitRef({ ...t });
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
function rebuildPages(pages) {
|
|
786
|
-
if (!pages) return [];
|
|
787
|
-
return pages.map((p) => {
|
|
788
|
-
if (!isPageRefObject(p)) return p;
|
|
789
|
-
return makePageRef({ ...p });
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
function rewriteTraitRefToken(value, renames) {
|
|
793
|
-
const prefix = "@trait.";
|
|
794
|
-
if (!value.startsWith(prefix)) return value;
|
|
795
|
-
const rest = value.slice(prefix.length);
|
|
796
|
-
const splitAt = rest.search(/[.[]/);
|
|
797
|
-
const name = splitAt === -1 ? rest : rest.slice(0, splitAt);
|
|
798
|
-
const to = renames.get(name);
|
|
799
|
-
if (to === void 0) return value;
|
|
800
|
-
return `${prefix}${to}${splitAt === -1 ? "" : rest.slice(splitAt)}`;
|
|
801
|
-
}
|
|
802
|
-
function rewriteTraitRefsInTree(node, renames) {
|
|
803
|
-
if (typeof node === "string") return rewriteTraitRefToken(node, renames);
|
|
804
|
-
if (Array.isArray(node)) return node.map((item) => rewriteTraitRefsInTree(item, renames));
|
|
805
|
-
if (node !== null && typeof node === "object") {
|
|
806
|
-
const out = {};
|
|
807
|
-
for (const [key, value] of Object.entries(node)) out[key] = rewriteTraitRefsInTree(value, renames);
|
|
808
|
-
return out;
|
|
809
|
-
}
|
|
810
|
-
return node;
|
|
811
|
-
}
|
|
812
|
-
function rekeyTraitEmbedIds(embedIds, renames) {
|
|
813
|
-
let out;
|
|
814
|
-
for (const [token, id] of Object.entries(embedIds)) {
|
|
815
|
-
const to = renames.get(token);
|
|
816
|
-
if (to === void 0) continue;
|
|
817
|
-
out = out ?? { ...embedIds };
|
|
818
|
-
delete out[token];
|
|
819
|
-
out[to] = id;
|
|
820
|
-
}
|
|
821
|
-
return out ?? embedIds;
|
|
822
|
-
}
|
|
823
|
-
function applyDeclarationTraitRenames(schema, renames, at) {
|
|
824
|
-
if (renames.size === 0) return schema;
|
|
825
|
-
const renamedTraitIds = [];
|
|
826
|
-
const renameDeclaration = (t) => {
|
|
827
|
-
if (typeof t !== "object" || t === null) return t;
|
|
828
|
-
let next = t;
|
|
829
|
-
const named = t;
|
|
830
|
-
if (typeof named.name === "string") {
|
|
831
|
-
const renamed = renames.get(named.name);
|
|
832
|
-
if (renamed !== void 0) {
|
|
833
|
-
const id = t.id;
|
|
834
|
-
if (typeof id === "string") renamedTraitIds.push({ id, to: renamed });
|
|
835
|
-
next = { ...next, name: renamed };
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
const walked = rewriteTraitRefsInTree(next, renames);
|
|
839
|
-
const embedIds = walked.traitEmbedIds;
|
|
840
|
-
if (embedIds !== void 0) {
|
|
841
|
-
const rekeyed = rekeyTraitEmbedIds(embedIds, renames);
|
|
842
|
-
if (rekeyed !== embedIds) {
|
|
843
|
-
walked.traitEmbedIds = rekeyed;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
return walked;
|
|
847
|
-
};
|
|
848
|
-
const renamePageTraitRefs = (p) => {
|
|
849
|
-
if (typeof p !== "object" || p === null) return p;
|
|
850
|
-
const walked = rewriteTraitRefsInTree(p, renames);
|
|
851
|
-
const traits = walked.traits;
|
|
852
|
-
if (!Array.isArray(traits)) return walked;
|
|
853
|
-
return {
|
|
854
|
-
...walked,
|
|
855
|
-
traits: traits.map((t) => {
|
|
856
|
-
if (typeof t === "string") return renames.get(t) ?? t;
|
|
857
|
-
const to = renames.get(t.ref);
|
|
858
|
-
return to === void 0 ? t : { ...t, ref: to };
|
|
859
|
-
})
|
|
860
|
-
};
|
|
861
|
-
};
|
|
862
|
-
const orbitals = schema.orbitals.map((orbital) => {
|
|
863
|
-
if (!("traits" in orbital) || !Array.isArray(orbital.traits)) return orbital;
|
|
864
|
-
return {
|
|
865
|
-
...orbital,
|
|
866
|
-
traits: orbital.traits.map(renameDeclaration),
|
|
867
|
-
...orbital.pages !== void 0 ? { pages: orbital.pages.map(renamePageTraitRefs) } : {}
|
|
868
|
-
};
|
|
869
|
-
});
|
|
870
|
-
let ledger = schema.ledger;
|
|
871
|
-
if (ledger !== void 0) {
|
|
872
|
-
for (const { id, to } of renamedTraitIds) {
|
|
873
|
-
ledger = ledgerRename(ledger, id, to, at);
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
return { ...schema, orbitals, ...ledger !== schema.ledger ? { ledger } : {} };
|
|
877
|
-
}
|
|
878
|
-
function declaredEntityName(orbital) {
|
|
879
|
-
const entity = orbital.entity;
|
|
880
|
-
if (typeof entity === "object" && entity !== null && typeof entity.name === "string") return entity.name;
|
|
881
|
-
return orbital.reference?.entity ?? null;
|
|
882
|
-
}
|
|
883
|
-
function applyDeclarationEntityRename(schema, rename, at) {
|
|
884
|
-
if (rename.from === rename.to) return schema;
|
|
885
|
-
const linkedEntityIsFrom = (shape) => shape.linkedEntity === rename.from;
|
|
886
|
-
const renamedEntityIds = [];
|
|
887
|
-
const orbitals = schema.orbitals.map((orbital) => {
|
|
888
|
-
const entity = orbital.entity;
|
|
889
|
-
if (orbital.reference !== void 0 && orbital.reference.entity === rename.from) {
|
|
890
|
-
return {
|
|
891
|
-
...orbital,
|
|
892
|
-
reference: { ...orbital.reference, entity: rename.to },
|
|
893
|
-
traits: orbital.traits.map(
|
|
894
|
-
(t) => typeof t === "object" && t !== null && linkedEntityIsFrom(t) ? { ...t, linkedEntity: rename.to } : t
|
|
895
|
-
)
|
|
896
|
-
};
|
|
897
|
-
}
|
|
898
|
-
if (typeof entity !== "object" || entity === null || entity.name !== rename.from) {
|
|
899
|
-
return orbital;
|
|
900
|
-
}
|
|
901
|
-
const entityId = entity.id;
|
|
902
|
-
if (typeof entityId === "string") renamedEntityIds.push(entityId);
|
|
903
|
-
const traits = orbital.traits.map(
|
|
904
|
-
(t) => typeof t === "object" && t !== null && linkedEntityIsFrom(t) ? { ...t, linkedEntity: rename.to } : t
|
|
905
|
-
);
|
|
906
|
-
const pages = orbital.pages?.map(
|
|
907
|
-
(p) => typeof p === "object" && p !== null && linkedEntityIsFrom(p) ? { ...p, linkedEntity: rename.to } : p
|
|
908
|
-
);
|
|
909
|
-
return {
|
|
910
|
-
...orbital,
|
|
911
|
-
entity: { ...entity, name: rename.to },
|
|
912
|
-
traits,
|
|
913
|
-
...pages !== void 0 ? { pages } : {}
|
|
914
|
-
};
|
|
915
|
-
});
|
|
916
|
-
let ledger = schema.ledger;
|
|
917
|
-
if (ledger !== void 0) {
|
|
918
|
-
for (const id of renamedEntityIds) {
|
|
919
|
-
ledger = ledgerRename(ledger, id, rename.to, at);
|
|
920
|
-
}
|
|
921
|
-
}
|
|
922
|
-
return { ...schema, orbitals, ...ledger !== schema.ledger ? { ledger } : {} };
|
|
923
|
-
}
|
|
924
|
-
function healEntityLedgerRows(schema, at) {
|
|
925
|
-
let ledger = schema.ledger;
|
|
926
|
-
if (ledger === void 0) return schema;
|
|
927
|
-
for (const orbital of schema.orbitals) {
|
|
928
|
-
const entity = orbital.entity;
|
|
929
|
-
if (typeof entity !== "object" || entity === null) continue;
|
|
930
|
-
const id = entity.id;
|
|
931
|
-
const name = entity.name;
|
|
932
|
-
if (typeof id !== "string" || typeof name !== "string") continue;
|
|
933
|
-
const entry = ledger.entries[id];
|
|
934
|
-
if (entry === void 0 || entry.kind !== "entity" || entry.curName === name) continue;
|
|
935
|
-
ledger = ledgerRename(ledger, id, name, at);
|
|
936
|
-
}
|
|
937
|
-
return ledger !== schema.ledger ? { ...schema, ledger } : schema;
|
|
938
|
-
}
|
|
939
|
-
function healTraitLedgerRows(schema, at) {
|
|
940
|
-
let ledger = schema.ledger;
|
|
941
|
-
if (ledger === void 0) return schema;
|
|
942
|
-
for (const orbital of schema.orbitals) {
|
|
943
|
-
for (const trait of orbital.traits ?? []) {
|
|
944
|
-
if (typeof trait !== "object" || trait === null) continue;
|
|
945
|
-
const id = trait.id;
|
|
946
|
-
if (typeof id !== "string") continue;
|
|
947
|
-
const declared = trait;
|
|
948
|
-
const name = typeof declared.name === "string" ? declared.name : typeof declared.ref === "string" ? declared.ref.slice(declared.ref.lastIndexOf(".") + 1) : void 0;
|
|
949
|
-
if (name === void 0) continue;
|
|
950
|
-
const entry = ledger.entries[id];
|
|
951
|
-
if (entry === void 0 || entry.kind !== "trait" || entry.curName === name) continue;
|
|
952
|
-
ledger = ledgerRename(ledger, id, name, at);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
return ledger !== schema.ledger ? { ...schema, ledger } : schema;
|
|
956
|
-
}
|
|
957
|
-
function applyParamsToOrb(orb, orbitalName, _manifest, params) {
|
|
958
|
-
const orbital = findOrbitalOrThrow(orb, orbitalName);
|
|
959
|
-
const canonicalEntity = assertResolvedEntity(orbital.entity, orbitalName, orb.name);
|
|
960
|
-
const canonicalEntityName = canonicalEntity.name;
|
|
961
|
-
const effectiveCollection = typeof canonicalEntity.collection === "string" ? params.collection ?? (params.entityName ? `${params.entityName.toLowerCase()}s` : canonicalEntity.collection) : params.collection;
|
|
962
|
-
const ctx = { canonicalEntity, dataBearing: orbitalTouchesOwnRecord(orbital) };
|
|
963
|
-
const built = makeOrbitalWithUses({
|
|
964
|
-
name: orbital.name,
|
|
965
|
-
uses: orbital.uses ?? [],
|
|
966
|
-
// Derived `expects` declarations ride the overlay untouched — they name
|
|
967
|
-
// SIBLING entities (never the orbital's own), so the entityName rename
|
|
968
|
-
// below cannot affect them.
|
|
969
|
-
...orbital.expects !== void 0 ? { expects: orbital.expects } : {},
|
|
970
|
-
entity: buildEntity(ctx, canonicalEntityName, effectiveCollection, params),
|
|
971
|
-
traits: rebuildTraits(orbital.traits),
|
|
972
|
-
pages: rebuildPages(orbital.pages)
|
|
973
|
-
});
|
|
974
|
-
if (orbital.config !== void 0) {
|
|
975
|
-
built.config = params.config !== void 0 ? overrideDeclaredKnobs(orbital.config, params.config) : orbital.config;
|
|
976
|
-
}
|
|
977
|
-
if (built.traits && params.traitOverrides !== void 0) {
|
|
978
|
-
built.traits = built.traits.map((t) => {
|
|
979
|
-
if (!isTraitReferenceObject(t) || typeof t.name !== "string") return t;
|
|
980
|
-
const override = params.traitOverrides?.[t.name];
|
|
981
|
-
if (!override) return t;
|
|
982
|
-
const merged = { ...t };
|
|
983
|
-
if (override.config !== void 0) {
|
|
984
|
-
merged.config = mergeCallSiteConfigOverrides(t.config ?? {}, override.config);
|
|
985
|
-
}
|
|
986
|
-
if (override.linkedEntity !== void 0) merged.linkedEntity = override.linkedEntity;
|
|
987
|
-
if (override.events !== void 0) {
|
|
988
|
-
if (override.events === null || typeof override.events !== "object" || Array.isArray(override.events)) {
|
|
989
|
-
throw new Error(
|
|
990
|
-
`traitOverrides["${t.name}"].events must be a Record<string,string> (rename map like { "OPEN": "ADD_ITEM" }), got ${Array.isArray(override.events) ? "an array" : typeof override.events}`
|
|
991
|
-
);
|
|
992
|
-
}
|
|
993
|
-
for (const [k, v] of Object.entries(override.events)) {
|
|
994
|
-
if (typeof v !== "string") {
|
|
995
|
-
throw new Error(
|
|
996
|
-
`traitOverrides["${t.name}"].events["${k}"] must be a string (target event name), got ${typeof v}`
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
merged.events = { ...t.events ?? {}, ...override.events };
|
|
1001
|
-
}
|
|
1002
|
-
if (override.emitsScope !== void 0) merged.emitsScope = override.emitsScope;
|
|
1003
|
-
if (override.listens !== void 0) merged.listens = override.listens;
|
|
1004
|
-
return merged;
|
|
1005
|
-
});
|
|
1006
|
-
}
|
|
1007
|
-
if (built.pages && params.pagePath !== void 0) {
|
|
1008
|
-
built.pages = built.pages.map((p, idx) => {
|
|
1009
|
-
if (!isPageRefObject(p) || idx !== 0) return p;
|
|
1010
|
-
return { ...p, path: params.pagePath };
|
|
1011
|
-
});
|
|
1012
|
-
}
|
|
1013
|
-
return built;
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
// src/embedded-trait-config.ts
|
|
1017
|
-
var TRAIT_BINDING_PREFIX = "@trait.";
|
|
1018
|
-
var CONFIG_FORWARD_RE = /^@config\.([A-Za-z_][A-Za-z0-9_]*)$/;
|
|
1019
|
-
var CALLSITE_PAYLOAD_PREFIX = "@callsitePayload.";
|
|
1020
|
-
function valueContainsPrefixedString(value, prefix) {
|
|
1021
|
-
if (value === null || value === void 0) return false;
|
|
1022
|
-
if (typeof value === "string") return value.startsWith(prefix);
|
|
1023
|
-
if (Array.isArray(value)) return value.some((item) => valueContainsPrefixedString(item, prefix));
|
|
1024
|
-
if (typeof value === "object") {
|
|
1025
|
-
return Object.values(value).some((v) => valueContainsPrefixedString(v, prefix));
|
|
1026
|
-
}
|
|
1027
|
-
return false;
|
|
1028
|
-
}
|
|
1029
|
-
function collectTraitRefsFromValue(value, into) {
|
|
1030
|
-
if (value === null || value === void 0) return;
|
|
1031
|
-
if (typeof value === "string") {
|
|
1032
|
-
if (value.startsWith(TRAIT_BINDING_PREFIX)) {
|
|
1033
|
-
const rest = value.slice(TRAIT_BINDING_PREFIX.length);
|
|
1034
|
-
const dot = rest.indexOf(".");
|
|
1035
|
-
const traitName = dot === -1 ? rest : rest.slice(0, dot);
|
|
1036
|
-
if (traitName.length > 0) into.add(traitName);
|
|
1037
|
-
}
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
if (Array.isArray(value)) {
|
|
1041
|
-
for (const item of value) collectTraitRefsFromValue(item, into);
|
|
1042
|
-
return;
|
|
1043
|
-
}
|
|
1044
|
-
if (typeof value === "object") {
|
|
1045
|
-
for (const v of Object.values(value)) {
|
|
1046
|
-
collectTraitRefsFromValue(v, into);
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
var CONFIG_BINDING_PREFIX = "@config.";
|
|
1051
|
-
function collectConfigKeysFromValue(value, into) {
|
|
1052
|
-
if (value === null || value === void 0) return;
|
|
1053
|
-
if (typeof value === "string") {
|
|
1054
|
-
if (value.startsWith(CONFIG_BINDING_PREFIX)) {
|
|
1055
|
-
const key = value.slice(CONFIG_BINDING_PREFIX.length).split(".")[0];
|
|
1056
|
-
if (key.length > 0) into.add(key);
|
|
1057
|
-
}
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
if (Array.isArray(value)) {
|
|
1061
|
-
for (const item of value) collectConfigKeysFromValue(item, into);
|
|
1062
|
-
return;
|
|
1063
|
-
}
|
|
1064
|
-
if (typeof value === "object") {
|
|
1065
|
-
for (const v of Object.values(value)) collectConfigKeysFromValue(v, into);
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
function traitsEmbeddedByEffects(trait, effects) {
|
|
1069
|
-
const refs = /* @__PURE__ */ new Set();
|
|
1070
|
-
const configKeys = /* @__PURE__ */ new Set();
|
|
1071
|
-
collectTraitRefsFromValue(effects, refs);
|
|
1072
|
-
collectConfigKeysFromValue(effects, configKeys);
|
|
1073
|
-
const config = trait.config;
|
|
1074
|
-
if (config) for (const key of configKeys) collectTraitRefsFromValue(config[key] ?? null, refs);
|
|
1075
|
-
refs.delete(trait.name);
|
|
1076
|
-
return refs;
|
|
1077
|
-
}
|
|
1078
|
-
function traitsEmbeddedByEvent(trait, eventKey) {
|
|
1079
|
-
const transitions = trait.stateMachine?.transitions ?? [];
|
|
1080
|
-
const out = /* @__PURE__ */ new Set();
|
|
1081
|
-
for (const transition of transitions) {
|
|
1082
|
-
if (transition.event !== eventKey) continue;
|
|
1083
|
-
for (const child of traitsEmbeddedByEffects(trait, transition.effects ?? null)) out.add(child);
|
|
1084
|
-
}
|
|
1085
|
-
return out;
|
|
1086
|
-
}
|
|
1087
|
-
function targetTraitOf(traitRef) {
|
|
1088
|
-
if (!traitRef || typeof traitRef !== "object") return void 0;
|
|
1089
|
-
const resolved = traitRef._resolved;
|
|
1090
|
-
return resolved && typeof resolved === "object" ? resolved : traitRef;
|
|
1091
|
-
}
|
|
1092
|
-
function collectTraitEmbedAdjacency(orbital) {
|
|
1093
|
-
const out = /* @__PURE__ */ new Map();
|
|
1094
|
-
const traits = orbital.traits;
|
|
1095
|
-
if (!Array.isArray(traits)) return out;
|
|
1096
|
-
for (const traitRef of traits) {
|
|
1097
|
-
const target = targetTraitOf(traitRef);
|
|
1098
|
-
if (!target) continue;
|
|
1099
|
-
const referrerName = target.name;
|
|
1100
|
-
if (typeof referrerName !== "string" || referrerName.length === 0) continue;
|
|
1101
|
-
const refs = /* @__PURE__ */ new Set();
|
|
1102
|
-
if (target.config) collectTraitRefsFromValue(target.config, refs);
|
|
1103
|
-
const stateMachine = target.stateMachine;
|
|
1104
|
-
if (stateMachine) collectTraitRefsFromValue(stateMachine, refs);
|
|
1105
|
-
refs.delete(referrerName);
|
|
1106
|
-
if (refs.size > 0) out.set(referrerName, refs);
|
|
1107
|
-
}
|
|
1108
|
-
return out;
|
|
1109
|
-
}
|
|
1110
|
-
function collectTraitConfigRefAdjacency(orbital) {
|
|
1111
|
-
const out = /* @__PURE__ */ new Map();
|
|
1112
|
-
const traits = orbital.traits;
|
|
1113
|
-
if (!Array.isArray(traits)) return out;
|
|
1114
|
-
for (const traitRef of traits) {
|
|
1115
|
-
const target = targetTraitOf(traitRef);
|
|
1116
|
-
if (!target) continue;
|
|
1117
|
-
const referrerName = target.name;
|
|
1118
|
-
if (typeof referrerName !== "string" || referrerName.length === 0) continue;
|
|
1119
|
-
if (!target.config) continue;
|
|
1120
|
-
const refs = /* @__PURE__ */ new Set();
|
|
1121
|
-
collectTraitRefsFromValue(target.config, refs);
|
|
1122
|
-
refs.delete(referrerName);
|
|
1123
|
-
if (refs.size > 0) out.set(referrerName, refs);
|
|
1124
|
-
}
|
|
1125
|
-
return out;
|
|
1126
|
-
}
|
|
1127
|
-
function traitDeclaresConfigForward(trait) {
|
|
1128
|
-
const config = trait?.config;
|
|
1129
|
-
if (!config) return false;
|
|
1130
|
-
let found = false;
|
|
1131
|
-
const walk2 = (value) => {
|
|
1132
|
-
if (found || value === null || value === void 0) return;
|
|
1133
|
-
if (typeof value === "string") {
|
|
1134
|
-
const knob = CONFIG_FORWARD_RE.exec(value)?.[1];
|
|
1135
|
-
if (knob !== void 0 && !(knob in config)) found = true;
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
if (Array.isArray(value)) {
|
|
1139
|
-
for (const item of value) walk2(item);
|
|
1140
|
-
return;
|
|
1141
|
-
}
|
|
1142
|
-
if (typeof value === "object") {
|
|
1143
|
-
for (const v of Object.values(value)) walk2(v);
|
|
1144
|
-
}
|
|
1145
|
-
};
|
|
1146
|
-
for (const field of Object.values(config)) {
|
|
1147
|
-
const value = field?.default;
|
|
1148
|
-
if (typeof value === "string") {
|
|
1149
|
-
if (CONFIG_FORWARD_RE.test(value)) return true;
|
|
1150
|
-
continue;
|
|
1151
|
-
}
|
|
1152
|
-
walk2(value);
|
|
1153
|
-
if (found) return true;
|
|
1154
|
-
}
|
|
1155
|
-
return false;
|
|
1156
|
-
}
|
|
1157
|
-
function configReferencesCallsitePayload(config) {
|
|
1158
|
-
return config !== void 0 && valueContainsPrefixedString(config, CALLSITE_PAYLOAD_PREFIX);
|
|
1159
|
-
}
|
|
1160
|
-
function traitReferencesCallsitePayload(trait) {
|
|
1161
|
-
if (!trait) return false;
|
|
1162
|
-
if (trait.config && valueContainsPrefixedString(trait.config, CALLSITE_PAYLOAD_PREFIX)) {
|
|
1163
|
-
return true;
|
|
1164
|
-
}
|
|
1165
|
-
const stateMachine = trait.stateMachine;
|
|
1166
|
-
if (stateMachine && valueContainsPrefixedString(stateMachine, CALLSITE_PAYLOAD_PREFIX)) {
|
|
1167
|
-
return true;
|
|
1168
|
-
}
|
|
1169
|
-
return false;
|
|
1170
|
-
}
|
|
1171
|
-
function collectCallsiteCaptureChildren(orbital) {
|
|
1172
|
-
const adjacency = collectTraitEmbedAdjacency(orbital);
|
|
1173
|
-
const traitsByName = /* @__PURE__ */ new Map();
|
|
1174
|
-
const traits = orbital.traits;
|
|
1175
|
-
if (Array.isArray(traits)) {
|
|
1176
|
-
for (const traitRef of traits) {
|
|
1177
|
-
const target = targetTraitOf(traitRef);
|
|
1178
|
-
if (target?.name) traitsByName.set(target.name, target);
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
const reachesCapture = /* @__PURE__ */ new Map();
|
|
1182
|
-
function traitReachesCapture(name, seen) {
|
|
1183
|
-
const cached = reachesCapture.get(name);
|
|
1184
|
-
if (cached !== void 0) return cached;
|
|
1185
|
-
if (seen.has(name)) return false;
|
|
1186
|
-
seen.add(name);
|
|
1187
|
-
const trait = traitsByName.get(name);
|
|
1188
|
-
if (trait && traitReferencesCallsitePayload(trait)) {
|
|
1189
|
-
reachesCapture.set(name, true);
|
|
1190
|
-
return true;
|
|
1191
|
-
}
|
|
1192
|
-
const children = adjacency.get(name);
|
|
1193
|
-
if (children) {
|
|
1194
|
-
for (const child of children) {
|
|
1195
|
-
if (traitReachesCapture(child, seen)) {
|
|
1196
|
-
reachesCapture.set(name, true);
|
|
1197
|
-
return true;
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
reachesCapture.set(name, false);
|
|
1202
|
-
return false;
|
|
1203
|
-
}
|
|
1204
|
-
const out = /* @__PURE__ */ new Map();
|
|
1205
|
-
for (const [referrer, children] of adjacency) {
|
|
1206
|
-
const keep = /* @__PURE__ */ new Set();
|
|
1207
|
-
for (const child of children) {
|
|
1208
|
-
if (traitReachesCapture(child, /* @__PURE__ */ new Set())) keep.add(child);
|
|
1209
|
-
}
|
|
1210
|
-
if (keep.size > 0) out.set(referrer, keep);
|
|
1211
|
-
}
|
|
1212
|
-
return out;
|
|
1213
|
-
}
|
|
1214
|
-
function configForwardTokens(entry) {
|
|
1215
|
-
const tokens = [];
|
|
1216
|
-
const walk2 = (value) => {
|
|
1217
|
-
if (typeof value === "string") {
|
|
1218
|
-
if (value.startsWith("@config.")) tokens.push(value);
|
|
1219
|
-
} else if (Array.isArray(value)) {
|
|
1220
|
-
for (const item of value) walk2(item);
|
|
1221
|
-
} else if (value !== null && typeof value === "object") {
|
|
1222
|
-
for (const item of Object.values(value)) walk2(item);
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
|
-
walk2(entry.default);
|
|
1226
|
-
if (entry.forwardedFrom !== void 0) tokens.push(entry.forwardedFrom);
|
|
1227
|
-
tokens.push(...entry.nestedForwardedFrom ?? []);
|
|
1228
|
-
return tokens;
|
|
1229
|
-
}
|
|
1230
|
-
function collectForwardedConfigKeys(traits) {
|
|
1231
|
-
const forwarded = /* @__PURE__ */ new Set();
|
|
1232
|
-
for (const traitRef of traits) {
|
|
1233
|
-
const config = typeof traitRef === "string" ? void 0 : traitRef.config;
|
|
1234
|
-
if (!config) continue;
|
|
1235
|
-
for (const entry of Object.values(config)) {
|
|
1236
|
-
if (!isCallSiteConfigDeclaration(entry)) continue;
|
|
1237
|
-
for (const token of configForwardTokens(entry)) {
|
|
1238
|
-
const knob = CONFIG_FORWARD_RE.exec(token)?.[1];
|
|
1239
|
-
if (knob) forwarded.add(knob);
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
}
|
|
1243
|
-
return forwarded;
|
|
1244
|
-
}
|
|
1245
|
-
function collectOrbitalForwardedConfigKeys(orbital) {
|
|
1246
|
-
const forwarded = new Set(collectForwardedConfigKeys(orbital.traits ?? []));
|
|
1247
|
-
for (const use of orbital.uses ?? []) {
|
|
1248
|
-
for (const entry of Object.values(use.config ?? {})) {
|
|
1249
|
-
for (const token of configForwardTokens(entry)) {
|
|
1250
|
-
const knob = CONFIG_FORWARD_RE.exec(token)?.[1];
|
|
1251
|
-
if (knob) forwarded.add(knob);
|
|
1252
|
-
}
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
return forwarded;
|
|
1256
|
-
}
|
|
1257
|
-
function filterConfigToForwardedKeys(config, forwarded) {
|
|
1258
|
-
const kept = Object.entries(config).filter(([key]) => forwarded.has(key));
|
|
1259
|
-
return kept.length > 0 ? Object.fromEntries(kept) : void 0;
|
|
1260
|
-
}
|
|
1261
|
-
function orbitalFileOf(schema, orbital) {
|
|
1262
|
-
const config = schema.config !== void 0 ? filterConfigToForwardedKeys(schema.config, collectOrbitalForwardedConfigKeys(orbital)) : void 0;
|
|
1263
|
-
return { name: orbital.name, version: schema.version ?? "1.0.0", orbitals: [orbital], ...config !== void 0 ? { config } : {} };
|
|
1264
|
-
}
|
|
1265
|
-
function navItemsList(field) {
|
|
1266
|
-
return field.type === "[NavItem]" && Array.isArray(field.default) ? field.default : null;
|
|
1267
|
-
}
|
|
1268
|
-
function isConfigObject(value) {
|
|
1269
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1270
|
-
}
|
|
1271
|
-
function navItemHref(item) {
|
|
1272
|
-
return isConfigObject(item) && typeof item.href === "string" ? item.href : void 0;
|
|
1273
|
-
}
|
|
1274
|
-
function unionOrganismConfigs(schemas) {
|
|
1275
|
-
let merged;
|
|
1276
|
-
for (const schema of schemas) {
|
|
1277
|
-
if (schema.config === void 0) continue;
|
|
1278
|
-
merged ?? (merged = {});
|
|
1279
|
-
for (const [key, field] of Object.entries(schema.config)) {
|
|
1280
|
-
const held = merged[key];
|
|
1281
|
-
if (held === void 0) {
|
|
1282
|
-
merged[key] = field;
|
|
1283
|
-
continue;
|
|
1284
|
-
}
|
|
1285
|
-
const heldList = navItemsList(held);
|
|
1286
|
-
const addedList = navItemsList(field);
|
|
1287
|
-
if (heldList === null || addedList === null) continue;
|
|
1288
|
-
const listed = new Set(heldList.map(navItemHref).filter((href) => href !== void 0));
|
|
1289
|
-
const added = addedList.filter((item) => {
|
|
1290
|
-
const href = navItemHref(item);
|
|
1291
|
-
return href === void 0 || !listed.has(href);
|
|
1292
|
-
});
|
|
1293
|
-
if (added.length > 0) merged[key] = { ...held, default: [...heldList, ...added] };
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
return merged;
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
// src/factory/questions/generate.ts
|
|
1300
|
-
function generateQuestions(plan, catalog, ruleOverlay, _userPrompt) {
|
|
1301
|
-
const out = [];
|
|
1302
|
-
const ruleCapabilities = collectRuleCapabilities(ruleOverlay);
|
|
1303
|
-
for (const call of plan) {
|
|
1304
|
-
const signature = findSignature(catalog, call.organism, call.orbital);
|
|
1305
|
-
if (!signature) continue;
|
|
1306
|
-
out.push(...configKeyQuestions(call, signature));
|
|
1307
|
-
out.push(...entityFieldQuestions(call, signature));
|
|
1308
|
-
out.push(...capabilityQuestions(call, signature, ruleCapabilities));
|
|
1309
|
-
}
|
|
1310
|
-
return out;
|
|
1311
|
-
}
|
|
1312
|
-
var TIER_D_NAMED_PRIMITIVES = /* @__PURE__ */ new Set([
|
|
1313
|
-
"layoutMode",
|
|
1314
|
-
"layoutPattern",
|
|
1315
|
-
"viewPattern",
|
|
1316
|
-
"detailPattern",
|
|
1317
|
-
"detailSlot",
|
|
1318
|
-
"contentTrait"
|
|
1319
|
-
]);
|
|
1320
|
-
var TIER_D_TYPES = /* @__PURE__ */ new Set(["trait", "slot", "pattern", "event"]);
|
|
1321
|
-
function configKeyQuestions(call, signature) {
|
|
1322
|
-
const out = [];
|
|
1323
|
-
for (const trait of signature.traits) {
|
|
1324
|
-
for (const param of trait.overridableConfigKeys) {
|
|
1325
|
-
if (param.tier === "internal") continue;
|
|
1326
|
-
if (TIER_D_TYPES.has(param.type)) continue;
|
|
1327
|
-
if (TIER_D_NAMED_PRIMITIVES.has(param.key)) continue;
|
|
1328
|
-
out.push(buildConfigKeyQuestion(call, trait, param));
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
return out;
|
|
1332
|
-
}
|
|
1333
|
-
function buildConfigKeyQuestion(call, trait, param) {
|
|
1334
|
-
const question = param.label ?? humanizeKey(param.key);
|
|
1335
|
-
const callSiteOverride = callSiteOverrideValue(call, trait.name, param.key);
|
|
1336
|
-
const effectiveDefault = callSiteOverride !== void 0 ? callSiteOverride : param.default;
|
|
1337
|
-
const helpText = param.description;
|
|
1338
|
-
const syntheticReason = `Customizes "${param.key}" on the ${trait.name} trait. ` + (effectiveDefault !== void 0 ? `Default: ${stringifyDefault(effectiveDefault)}.` : `No default \u2014 leave blank to inherit the factory's behavior.`);
|
|
1339
|
-
const reason = helpText !== void 0 ? void 0 : syntheticReason;
|
|
1340
|
-
const isAdvanced = !isPrimaryTier(param.tier);
|
|
1341
|
-
const out = {
|
|
1342
|
-
id: `${factoryCallPlanOrbitalName(call)}.${trait.name}.${param.key}`,
|
|
1343
|
-
orbitalName: factoryCallPlanOrbitalName(call),
|
|
1344
|
-
question,
|
|
1345
|
-
inputType: deriveInputType(param),
|
|
1346
|
-
mutationTemplate: {
|
|
1347
|
-
kind: "set-trait-override-config",
|
|
1348
|
-
orbitalName: factoryCallPlanOrbitalName(call),
|
|
1349
|
-
traitName: trait.name,
|
|
1350
|
-
configKey: param.key
|
|
1351
|
-
}
|
|
1352
|
-
};
|
|
1353
|
-
if (reason !== void 0) {
|
|
1354
|
-
out.reason = reason;
|
|
1355
|
-
}
|
|
1356
|
-
if (helpText !== void 0) {
|
|
1357
|
-
out.helpText = helpText;
|
|
1358
|
-
}
|
|
1359
|
-
if (effectiveDefault !== void 0) {
|
|
1360
|
-
out.defaultValue = effectiveDefault;
|
|
1361
|
-
}
|
|
1362
|
-
if (param.enumValues && param.enumValues.length > 0) {
|
|
1363
|
-
out.suggestedAnswers = param.enumValues;
|
|
1364
|
-
}
|
|
1365
|
-
if (param.items) {
|
|
1366
|
-
out.itemSchema = param.items;
|
|
1367
|
-
}
|
|
1368
|
-
if (param.properties) {
|
|
1369
|
-
out.objectSchema = param.properties;
|
|
1370
|
-
}
|
|
1371
|
-
if (param.tier) {
|
|
1372
|
-
out.tier = param.tier;
|
|
1373
|
-
}
|
|
1374
|
-
if (isAdvanced) {
|
|
1375
|
-
out.advanced = true;
|
|
1376
|
-
}
|
|
1377
|
-
const weight = tierWeight(param.tier);
|
|
1378
|
-
out.weight = weight;
|
|
1379
|
-
out.priority = weight;
|
|
1380
|
-
return out;
|
|
1381
|
-
}
|
|
1382
|
-
function tierWeight(tier) {
|
|
1383
|
-
switch (tier) {
|
|
1384
|
-
case "domain":
|
|
1385
|
-
case "policy":
|
|
1386
|
-
return 3;
|
|
1387
|
-
case "infra":
|
|
1388
|
-
return 2;
|
|
1389
|
-
case "internal":
|
|
1390
|
-
return 0;
|
|
1391
|
-
case "presentation":
|
|
1392
|
-
default:
|
|
1393
|
-
return 1;
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
function isPrimaryTier(tier) {
|
|
1397
|
-
return tier === "domain" || tier === "policy";
|
|
1398
|
-
}
|
|
1399
|
-
function callSiteOverrideValue(call, traitName, configKey) {
|
|
1400
|
-
const override = call.params.traitOverrides?.[traitName];
|
|
1401
|
-
if (!override?.config) return void 0;
|
|
1402
|
-
if (!Object.prototype.hasOwnProperty.call(override.config, configKey)) {
|
|
1403
|
-
return void 0;
|
|
1404
|
-
}
|
|
1405
|
-
return override.config[configKey];
|
|
1406
|
-
}
|
|
1407
|
-
function deriveInputType(param) {
|
|
1408
|
-
if (param.type.startsWith("[")) {
|
|
1409
|
-
if (param.items?.properties && Object.keys(param.items.properties).length > 0) {
|
|
1410
|
-
return "listOfObjects";
|
|
1411
|
-
}
|
|
1412
|
-
if (param.enumValues && param.enumValues.length > 0) {
|
|
1413
|
-
return "multiselect";
|
|
1414
|
-
}
|
|
1415
|
-
return "tagList";
|
|
1416
|
-
}
|
|
1417
|
-
if (param.type.startsWith("Map<")) {
|
|
1418
|
-
return "objectForm";
|
|
1419
|
-
}
|
|
1420
|
-
if (param.type === "object") {
|
|
1421
|
-
if (param.properties && Object.keys(param.properties).length > 0) {
|
|
1422
|
-
return "objectForm";
|
|
1423
|
-
}
|
|
1424
|
-
return "text";
|
|
1425
|
-
}
|
|
1426
|
-
switch (param.type) {
|
|
1427
|
-
case "number":
|
|
1428
|
-
case "integer":
|
|
1429
|
-
return "number";
|
|
1430
|
-
case "boolean":
|
|
1431
|
-
return "boolean";
|
|
1432
|
-
case "enum":
|
|
1433
|
-
return "enum";
|
|
1434
|
-
case "string":
|
|
1435
|
-
return param.enumValues && param.enumValues.length > 0 ? "enum" : "text";
|
|
1436
|
-
default:
|
|
1437
|
-
return "text";
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
function humanizeKey(key) {
|
|
1441
|
-
const parts = key.replace(/[-_]+/g, " ").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(" ").filter((s) => s.length > 0);
|
|
1442
|
-
return parts.map((p) => /^[A-Z]+$/.test(p) ? p : p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
|
|
1443
|
-
}
|
|
1444
|
-
function stringifyDefault(v) {
|
|
1445
|
-
if (typeof v === "string") return JSON.stringify(v);
|
|
1446
|
-
if (typeof v === "number" || typeof v === "boolean") return String(v);
|
|
1447
|
-
if (Array.isArray(v)) return `${v.length} item${v.length === 1 ? "" : "s"}`;
|
|
1448
|
-
return "object";
|
|
1449
|
-
}
|
|
1450
|
-
function entityFieldQuestions(call, signature) {
|
|
1451
|
-
if (signature.entities.length === 0) return [];
|
|
1452
|
-
const entity = signature.entities[0];
|
|
1453
|
-
const entityName = call.params.entityName ?? entity.name;
|
|
1454
|
-
const candidateFields = entity.fields.map(signatureFieldToEntityField);
|
|
1455
|
-
const fieldCandidates = {};
|
|
1456
|
-
const fieldDescriptions = {};
|
|
1457
|
-
const candidateNames = [];
|
|
1458
|
-
for (let i = 0; i < entity.fields.length; i++) {
|
|
1459
|
-
const sig = entity.fields[i];
|
|
1460
|
-
const ef = candidateFields[i];
|
|
1461
|
-
const name = sig.name;
|
|
1462
|
-
candidateNames.push(name);
|
|
1463
|
-
fieldCandidates[name] = ef;
|
|
1464
|
-
if (sig.description) {
|
|
1465
|
-
fieldDescriptions[name] = sig.description;
|
|
1466
|
-
}
|
|
1467
|
-
}
|
|
1468
|
-
const weight = tierWeight("domain");
|
|
1469
|
-
const q = {
|
|
1470
|
-
id: `${factoryCallPlanOrbitalName(call)}.__entityFields`,
|
|
1471
|
-
orbitalName: factoryCallPlanOrbitalName(call),
|
|
1472
|
-
question: `Fields for ${entityName}`,
|
|
1473
|
-
reason: `Defines the data model for ${entityName}. Pick the fields that matter for your use case.`,
|
|
1474
|
-
inputType: "multiselect",
|
|
1475
|
-
mutationTemplate: {
|
|
1476
|
-
kind: "set-orbital-entity-fields",
|
|
1477
|
-
orbitalName: factoryCallPlanOrbitalName(call)
|
|
1478
|
-
},
|
|
1479
|
-
suggestedAnswers: candidateNames,
|
|
1480
|
-
defaultValue: candidateNames,
|
|
1481
|
-
fieldCandidates,
|
|
1482
|
-
tier: "domain",
|
|
1483
|
-
weight,
|
|
1484
|
-
priority: weight
|
|
1485
|
-
};
|
|
1486
|
-
if (Object.keys(fieldDescriptions).length > 0) {
|
|
1487
|
-
q.fieldDescriptions = fieldDescriptions;
|
|
1488
|
-
}
|
|
1489
|
-
return [q];
|
|
1490
|
-
}
|
|
1491
|
-
function signatureFieldToEntityField(f) {
|
|
1492
|
-
const base = {
|
|
1493
|
-
name: f.name,
|
|
1494
|
-
required: f.required,
|
|
1495
|
-
description: f.description,
|
|
1496
|
-
synonyms: f.synonyms,
|
|
1497
|
-
intrinsic: f.intrinsic
|
|
1498
|
-
};
|
|
1499
|
-
switch (f.type) {
|
|
1500
|
-
case "string":
|
|
1501
|
-
case "number":
|
|
1502
|
-
case "boolean":
|
|
1503
|
-
case "date":
|
|
1504
|
-
case "timestamp":
|
|
1505
|
-
case "datetime":
|
|
1506
|
-
// Semantic string domains carry no dependent payload, so they pass through
|
|
1507
|
-
// as-is and the question widget narrows the input accordingly.
|
|
1508
|
-
case "email":
|
|
1509
|
-
case "url":
|
|
1510
|
-
case "phone":
|
|
1511
|
-
case "uuid":
|
|
1512
|
-
case "image":
|
|
1513
|
-
return { ...base, type: f.type };
|
|
1514
|
-
case "array":
|
|
1515
|
-
return { ...base, type: "array" };
|
|
1516
|
-
case "object":
|
|
1517
|
-
return { ...base, type: "object" };
|
|
1518
|
-
case "enum":
|
|
1519
|
-
if (Array.isArray(f.values) && f.values.length > 0) {
|
|
1520
|
-
return { ...base, type: "enum", values: f.values };
|
|
1521
|
-
}
|
|
1522
|
-
return { ...base, type: "string" };
|
|
1523
|
-
case "relation":
|
|
1524
|
-
if (f.relation !== void 0) {
|
|
1525
|
-
return { ...base, type: "relation", relation: f.relation };
|
|
1526
|
-
}
|
|
1527
|
-
return { ...base, type: "string" };
|
|
1528
|
-
case "node":
|
|
1529
|
-
return { ...base, type: "node" };
|
|
1530
|
-
case "event":
|
|
1531
|
-
return { ...base, type: "event" };
|
|
1532
|
-
case "money":
|
|
1533
|
-
case "instant":
|
|
1534
|
-
case "file":
|
|
1535
|
-
case "bytes":
|
|
1536
|
-
return { ...base, type: f.type };
|
|
1537
|
-
default: {
|
|
1538
|
-
f.type;
|
|
1539
|
-
return { ...base, type: "string" };
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
function capabilityQuestions(call, signature, ruleCapabilities) {
|
|
1544
|
-
const entityName = call.params.entityName ?? signature.entities[0]?.name ?? factoryCallPlanOrbitalName(call);
|
|
1545
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1546
|
-
const out = [];
|
|
1547
|
-
for (const trait of signature.traits) {
|
|
1548
|
-
const policyKnobKeys = new Set(
|
|
1549
|
-
trait.overridableConfigKeys.filter((p) => p.tier === "policy").map((p) => p.key)
|
|
1550
|
-
);
|
|
1551
|
-
for (const cap of trait.capabilities) {
|
|
1552
|
-
if (seen.has(cap)) continue;
|
|
1553
|
-
seen.add(cap);
|
|
1554
|
-
if (ruleCapabilities.has(cap)) continue;
|
|
1555
|
-
if (policyKnobKeys.has(cap)) continue;
|
|
1556
|
-
out.push({
|
|
1557
|
-
id: `${factoryCallPlanOrbitalName(call)}.capability.${cap}`,
|
|
1558
|
-
orbitalName: factoryCallPlanOrbitalName(call),
|
|
1559
|
-
question: capabilityPrompt(cap, entityName),
|
|
1560
|
-
helpText: capabilityHelp(cap, trait),
|
|
1561
|
-
capability: cap,
|
|
1562
|
-
inputType: "boolean",
|
|
1563
|
-
mutationTemplate: {
|
|
1564
|
-
kind: "set-rule",
|
|
1565
|
-
capability: cap,
|
|
1566
|
-
appliesTo: [entityName]
|
|
1567
|
-
},
|
|
1568
|
-
// Capabilities encode governance/policy decisions — high impact.
|
|
1569
|
-
weight: 3,
|
|
1570
|
-
priority: 3
|
|
1571
|
-
});
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
return out;
|
|
1575
|
-
}
|
|
1576
|
-
function capabilityPrompt(capability, entity) {
|
|
1577
|
-
const label = humanizeKey(capability);
|
|
1578
|
-
return `Enable ${label} for ${entity}?`;
|
|
1579
|
-
}
|
|
1580
|
-
function capabilityHelp(capability, trait) {
|
|
1581
|
-
return `Turns on the "${capability}" behavior from the ${trait.name} trait. Say yes to wire a governance rule into the schema.`;
|
|
1582
|
-
}
|
|
1583
|
-
function findSignature(catalog, organism, orbital) {
|
|
1584
|
-
return catalog.find((s) => s.organism === organism && s.orbital === orbital);
|
|
1585
|
-
}
|
|
1586
|
-
function collectRuleCapabilities(overlay) {
|
|
1587
|
-
const out = /* @__PURE__ */ new Set();
|
|
1588
|
-
for (const r of overlay?.rules ?? []) {
|
|
1589
|
-
if (typeof r.capability === "string") out.add(r.capability);
|
|
1590
|
-
}
|
|
1591
|
-
return out;
|
|
1592
|
-
}
|
|
1593
|
-
function factoryCallPlanOrbitalName(call) {
|
|
1594
|
-
return call.orbitalName ?? call.orbital;
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
// src/builders/route-slug.ts
|
|
1598
|
-
function orbitalRouteSlug(orbitalName) {
|
|
1599
|
-
return orbitalName.replace(/Orbital$/, "").replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").toLowerCase().replace(/^-+|-+$/g, "");
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
// src/builders/owned-surface.ts
|
|
1603
|
-
function collectOwnedSurface(node, pages, traits) {
|
|
1604
|
-
if (Array.isArray(node)) {
|
|
1605
|
-
for (const item of node) collectOwnedSurface(item, pages, traits);
|
|
1606
|
-
return;
|
|
1607
|
-
}
|
|
1608
|
-
if (node === null || typeof node !== "object") return;
|
|
1609
|
-
const pagesField = node["pages"];
|
|
1610
|
-
if (Array.isArray(pagesField)) {
|
|
1611
|
-
for (const p of pagesField) {
|
|
1612
|
-
if (p !== null && typeof p === "object" && !Array.isArray(p) && typeof p["path"] === "string") {
|
|
1613
|
-
pages.add(p["path"]);
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
const traitsField = node["traits"];
|
|
1618
|
-
if (Array.isArray(traitsField)) {
|
|
1619
|
-
for (const t of traitsField) {
|
|
1620
|
-
if (t !== null && typeof t === "object" && !Array.isArray(t) && typeof t["name"] === "string") {
|
|
1621
|
-
traits.add(t["name"]);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
for (const value of Object.values(node)) collectOwnedSurface(value, pages, traits);
|
|
1626
|
-
}
|
|
1627
|
-
function findDanglingRefs(node, deletedPages, deletedTraits, ownTraits, out) {
|
|
1628
|
-
if (Array.isArray(node)) {
|
|
1629
|
-
if (node[0] === "navigate" && typeof node[1] === "string" && deletedPages.has(node[1])) {
|
|
1630
|
-
out.add(`navigate "${node[1]}" targets a deleted orbital's page`);
|
|
1631
|
-
}
|
|
1632
|
-
for (const item of node) findDanglingRefs(item, deletedPages, deletedTraits, ownTraits, out);
|
|
1633
|
-
return;
|
|
1634
|
-
}
|
|
1635
|
-
if (node === null || typeof node !== "object") return;
|
|
1636
|
-
const source = node["source"];
|
|
1637
|
-
if (source !== null && typeof source === "object" && !Array.isArray(source) && source["kind"] === "trait" && typeof source["trait"] === "string" && deletedTraits.has(source["trait"]) && !ownTraits.has(source["trait"])) {
|
|
1638
|
-
out.add(`a listens entry is sourced from deleted trait "${source["trait"]}"`);
|
|
1639
|
-
}
|
|
1640
|
-
for (const value of Object.values(node)) {
|
|
1641
|
-
findDanglingRefs(value, deletedPages, deletedTraits, ownTraits, out);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
// src/builders/field-comparison-literals.ts
|
|
1646
|
-
var EQUALITY_OPS = /* @__PURE__ */ new Set(["=", "==", "!=", "!==", "eq", "neq"]);
|
|
1647
|
-
function isFieldBinding(node, ctx) {
|
|
1648
|
-
if (typeof node === "string") {
|
|
1649
|
-
if (ctx.isIdentity && node === `@user.${ctx.field}`) return true;
|
|
1650
|
-
if (node === `@${ctx.entityName}.${ctx.field}`) return true;
|
|
1651
|
-
return ctx.scopeEntityName === ctx.entityName && node === `@entity.${ctx.field}`;
|
|
1652
|
-
}
|
|
1653
|
-
if (Array.isArray(node) && node[0] === "object/get" && node.length === 3) {
|
|
1654
|
-
if (ctx.isIdentity && node[1] === "@user" && node[2] === ctx.field) return true;
|
|
1655
|
-
if (node[1] === `@${ctx.entityName}` && node[2] === ctx.field) return true;
|
|
1656
|
-
return ctx.scopeEntityName === ctx.entityName && node[1] === "@entity" && node[2] === ctx.field;
|
|
1657
|
-
}
|
|
1658
|
-
return false;
|
|
1659
|
-
}
|
|
1660
|
-
function collectFieldComparisonLiterals(node, ctx, out) {
|
|
1661
|
-
if (Array.isArray(node)) {
|
|
1662
|
-
const op = node[0];
|
|
1663
|
-
if (typeof op === "string" && EQUALITY_OPS.has(op)) {
|
|
1664
|
-
const args = node.slice(1);
|
|
1665
|
-
if (args.some((arg) => isFieldBinding(arg, ctx))) {
|
|
1666
|
-
for (const arg of args) {
|
|
1667
|
-
if (typeof arg === "string" && !arg.startsWith("@") && !isFieldBinding(arg, ctx)) out.add(arg);
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
} else if (op === "array/includes") {
|
|
1671
|
-
if (isFieldBinding(node[1], ctx)) {
|
|
1672
|
-
const needle = node[2];
|
|
1673
|
-
if (typeof needle === "string" && !needle.startsWith("@")) out.add(needle);
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
for (const item of node) collectFieldComparisonLiterals(item, ctx, out);
|
|
1677
|
-
return;
|
|
1678
|
-
}
|
|
1679
|
-
if (node !== null && typeof node === "object") {
|
|
1680
|
-
for (const value of Object.values(node)) collectFieldComparisonLiterals(value, ctx, out);
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
function entityFieldOf(s) {
|
|
1684
|
-
if (!s.startsWith("@entity.")) return null;
|
|
1685
|
-
const rest = s.slice("@entity.".length);
|
|
1686
|
-
return rest.length === 0 || rest.includes(".") || rest.includes("[") ? null : rest;
|
|
1687
|
-
}
|
|
1688
|
-
function isUserIdToken(node) {
|
|
1689
|
-
if (node === "@user.id") return true;
|
|
1690
|
-
return Array.isArray(node) && node[0] === "object/get" && node[1] === "@user" && node[2] === "id";
|
|
1691
|
-
}
|
|
1692
|
-
function entityFieldBinding(node) {
|
|
1693
|
-
if (typeof node === "string") return entityFieldOf(node);
|
|
1694
|
-
if (Array.isArray(node) && node[0] === "object/get" && node[1] === "@entity" && typeof node[2] === "string") {
|
|
1695
|
-
return node[2];
|
|
1696
|
-
}
|
|
1697
|
-
return null;
|
|
1698
|
-
}
|
|
1699
|
-
function collectOwnerComparedFields(node, out) {
|
|
1700
|
-
if (Array.isArray(node)) {
|
|
1701
|
-
const op = node[0];
|
|
1702
|
-
if (op === "=" || op === "==") {
|
|
1703
|
-
const args = node.slice(1);
|
|
1704
|
-
if (args.some(isUserIdToken)) {
|
|
1705
|
-
for (const arg of args) {
|
|
1706
|
-
const field = entityFieldBinding(arg);
|
|
1707
|
-
if (field !== null && field !== "id") out.add(field);
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
}
|
|
1711
|
-
for (const item of node) collectOwnerComparedFields(item, out);
|
|
1712
|
-
return;
|
|
1713
|
-
}
|
|
1714
|
-
if (node !== null && typeof node === "object") {
|
|
1715
|
-
for (const value of Object.values(node)) collectOwnerComparedFields(value, out);
|
|
1716
|
-
}
|
|
1717
|
-
}
|
|
1718
|
-
function collectOwnerStampedFields(node, out) {
|
|
1719
|
-
if (Array.isArray(node)) {
|
|
1720
|
-
if (node[0] === "persist" && (node[1] === "create" || node[1] === "upsert" || node[1] === "update") && typeof node[2] === "string") {
|
|
1721
|
-
const payload = node[3];
|
|
1722
|
-
const isOptionsBag = node.length === 4 && payload !== null && typeof payload === "object" && !Array.isArray(payload) && "emit" in payload;
|
|
1723
|
-
if (payload !== null && typeof payload === "object" && !Array.isArray(payload) && !isOptionsBag) {
|
|
1724
|
-
for (const [key, value] of Object.entries(payload)) {
|
|
1725
|
-
if (!isUserIdToken(value)) continue;
|
|
1726
|
-
const set = out.get(node[2]) ?? /* @__PURE__ */ new Set();
|
|
1727
|
-
set.add(key);
|
|
1728
|
-
out.set(node[2], set);
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
for (const item of node) collectOwnerStampedFields(item, out);
|
|
1733
|
-
return;
|
|
1734
|
-
}
|
|
1735
|
-
if (node !== null && typeof node === "object") {
|
|
1736
|
-
for (const value of Object.values(node)) collectOwnerStampedFields(value, out);
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
|
|
1740
|
-
// src/builders/compose-app.ts
|
|
1741
|
-
function rewriteInlineTraitName(node, oldName, newName) {
|
|
1742
|
-
if (Array.isArray(node)) {
|
|
1743
|
-
for (const item of node) rewriteInlineTraitName(item, oldName, newName);
|
|
1744
|
-
return;
|
|
1745
|
-
}
|
|
1746
|
-
if (!isJsonObject(node)) return;
|
|
1747
|
-
for (const key of ["name", "ref", "trait"]) {
|
|
1748
|
-
if (node[key] === oldName) node[key] = newName;
|
|
1749
|
-
}
|
|
1750
|
-
const traits = node["traits"];
|
|
1751
|
-
if (Array.isArray(traits)) {
|
|
1752
|
-
for (let i = 0; i < traits.length; i += 1) {
|
|
1753
|
-
if (traits[i] === oldName) traits[i] = newName;
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
for (const value of Object.values(node)) rewriteInlineTraitName(value, oldName, newName);
|
|
1757
|
-
}
|
|
1758
|
-
function rewriteOwnRoute(node, oldPath, newPath) {
|
|
1759
|
-
if (Array.isArray(node)) {
|
|
1760
|
-
if (node[0] === "navigate" && node[1] === oldPath) node[1] = newPath;
|
|
1761
|
-
for (const item of node) rewriteOwnRoute(item, oldPath, newPath);
|
|
1762
|
-
return;
|
|
1763
|
-
}
|
|
1764
|
-
if (!isJsonObject(node)) return;
|
|
1765
|
-
if (node["path"] === oldPath) node["path"] = newPath;
|
|
1766
|
-
for (const value of Object.values(node)) rewriteOwnRoute(value, oldPath, newPath);
|
|
1767
|
-
}
|
|
1768
|
-
function cloneOrbitalNode(orbital) {
|
|
1769
|
-
return JSON.parse(JSON.stringify(orbital));
|
|
1770
|
-
}
|
|
1771
|
-
function nodeToOrbital(node) {
|
|
1772
|
-
return JSON.parse(JSON.stringify(node));
|
|
1773
|
-
}
|
|
1774
|
-
function firstFreeName(base, taken) {
|
|
1775
|
-
if (!taken.has(base)) return base;
|
|
1776
|
-
for (let n = 2; ; n += 1) {
|
|
1777
|
-
const candidate = `${base}${n}`;
|
|
1778
|
-
if (!taken.has(candidate)) return candidate;
|
|
1779
|
-
}
|
|
1780
|
-
}
|
|
1781
|
-
function firstFreeRoute(slug, taken) {
|
|
1782
|
-
const base = `/${slug}`;
|
|
1783
|
-
if (!taken.has(base)) return base;
|
|
1784
|
-
for (let n = 2; ; n += 1) {
|
|
1785
|
-
const candidate = `${base}-${n}`;
|
|
1786
|
-
if (!taken.has(candidate)) return candidate;
|
|
1787
|
-
}
|
|
1788
|
-
}
|
|
1789
|
-
function dedupeComposedSurface(orbitals) {
|
|
1790
|
-
const routes = [];
|
|
1791
|
-
const traits = [];
|
|
1792
|
-
const pageNames = [];
|
|
1793
|
-
const seenRoutes = /* @__PURE__ */ new Set();
|
|
1794
|
-
const seenTraits = /* @__PURE__ */ new Set();
|
|
1795
|
-
const seenPageNames = /* @__PURE__ */ new Set();
|
|
1796
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
1797
|
-
let node = cloneOrbitalNode(orbitals[i]);
|
|
1798
|
-
const orbitalName = typeof node["name"] === "string" ? node["name"] : `orbital-${i}`;
|
|
1799
|
-
let mutated = false;
|
|
1800
|
-
const pages = node["pages"];
|
|
1801
|
-
const ownRoutes = [];
|
|
1802
|
-
if (Array.isArray(pages)) {
|
|
1803
|
-
for (const p of pages) {
|
|
1804
|
-
if (isJsonObject(p) && typeof p["path"] === "string") ownRoutes.push(p["path"]);
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
const reservedRoutes = /* @__PURE__ */ new Set([...seenRoutes, ...ownRoutes]);
|
|
1808
|
-
for (const route of ownRoutes) {
|
|
1809
|
-
if (!seenRoutes.has(route)) {
|
|
1810
|
-
seenRoutes.add(route);
|
|
1811
|
-
continue;
|
|
1812
|
-
}
|
|
1813
|
-
const next = firstFreeRoute(orbitalRouteSlug(orbitalName), reservedRoutes);
|
|
1814
|
-
rewriteOwnRoute(node, route, next);
|
|
1815
|
-
seenRoutes.add(next);
|
|
1816
|
-
reservedRoutes.add(next);
|
|
1817
|
-
routes.push({ orbitalName, from: route, to: next });
|
|
1818
|
-
mutated = true;
|
|
1819
|
-
}
|
|
1820
|
-
if (Array.isArray(pages)) {
|
|
1821
|
-
const ownPageNames = pages.flatMap((p) => isJsonObject(p) && typeof p["path"] === "string" && typeof p["name"] === "string" ? [p["name"]] : []);
|
|
1822
|
-
const reservedPageNames = /* @__PURE__ */ new Set([...seenPageNames, ...ownPageNames]);
|
|
1823
|
-
for (const p of pages) {
|
|
1824
|
-
if (!isJsonObject(p) || typeof p["path"] !== "string" || typeof p["name"] !== "string") continue;
|
|
1825
|
-
const pageName = p["name"];
|
|
1826
|
-
if (!seenPageNames.has(pageName)) {
|
|
1827
|
-
seenPageNames.add(pageName);
|
|
1828
|
-
continue;
|
|
1829
|
-
}
|
|
1830
|
-
const next = firstFreeName(`${orbitalName.replace(/Orbital$/, "")}${pageName}`, reservedPageNames);
|
|
1831
|
-
p["name"] = next;
|
|
1832
|
-
seenPageNames.add(next);
|
|
1833
|
-
reservedPageNames.add(next);
|
|
1834
|
-
pageNames.push({ orbitalName, from: pageName, to: next });
|
|
1835
|
-
mutated = true;
|
|
1836
|
-
}
|
|
1837
|
-
}
|
|
1838
|
-
const traitDefs = node["traits"];
|
|
1839
|
-
const ownTraitNames = [];
|
|
1840
|
-
if (Array.isArray(traitDefs)) {
|
|
1841
|
-
for (const t of traitDefs) {
|
|
1842
|
-
if (isJsonObject(t) && typeof t["name"] === "string") ownTraitNames.push(t["name"]);
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
const prefix = orbitalName.replace(/Orbital$/, "");
|
|
1846
|
-
const reservedTraits = /* @__PURE__ */ new Set([...seenTraits, ...ownTraitNames]);
|
|
1847
|
-
const tokenRenames = /* @__PURE__ */ new Map();
|
|
1848
|
-
for (const traitName of ownTraitNames) {
|
|
1849
|
-
if (!seenTraits.has(traitName)) {
|
|
1850
|
-
seenTraits.add(traitName);
|
|
1851
|
-
continue;
|
|
1852
|
-
}
|
|
1853
|
-
const next = firstFreeName(`${prefix}${traitName}`, reservedTraits);
|
|
1854
|
-
let traitId;
|
|
1855
|
-
if (Array.isArray(traitDefs)) {
|
|
1856
|
-
for (const t of traitDefs) {
|
|
1857
|
-
if (isJsonObject(t) && t["name"] === traitName && typeof t["id"] === "string") {
|
|
1858
|
-
traitId = t["id"];
|
|
1859
|
-
break;
|
|
1860
|
-
}
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
rewriteInlineTraitName(node, traitName, next);
|
|
1864
|
-
tokenRenames.set(traitName, next);
|
|
1865
|
-
seenTraits.add(next);
|
|
1866
|
-
reservedTraits.add(next);
|
|
1867
|
-
traits.push({ orbitalName, from: traitName, to: next, ...traitId !== void 0 ? { id: traitId } : {} });
|
|
1868
|
-
mutated = true;
|
|
1869
|
-
}
|
|
1870
|
-
if (tokenRenames.size > 0) {
|
|
1871
|
-
node = rewriteTraitRefsInTree(node, tokenRenames);
|
|
1872
|
-
}
|
|
1873
|
-
if (mutated) orbitals[i] = nodeToOrbital(node);
|
|
1874
|
-
}
|
|
1875
|
-
return { routes, traits, pageNames };
|
|
1876
|
-
}
|
|
1877
|
-
function dedupeComposedIdentity(orbitals) {
|
|
1878
|
-
const demotions = [];
|
|
1879
|
-
const demotedEntities = [];
|
|
1880
|
-
let winnerIndex = -1;
|
|
1881
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
1882
|
-
const def = orbitals[i];
|
|
1883
|
-
const entity = def.entity;
|
|
1884
|
-
if (entity === void 0 || isEntityReferenceAny(entity)) continue;
|
|
1885
|
-
if (entity.identity !== true) continue;
|
|
1886
|
-
if (winnerIndex === -1) {
|
|
1887
|
-
winnerIndex = i;
|
|
1888
|
-
continue;
|
|
1889
|
-
}
|
|
1890
|
-
const demoted = { ...entity };
|
|
1891
|
-
delete demoted.identity;
|
|
1892
|
-
orbitals[i] = { ...def, entity: demoted };
|
|
1893
|
-
demotions.push({ orbitalName: def.name, entityName: entity.name });
|
|
1894
|
-
demotedEntities.push(demoted);
|
|
1895
|
-
}
|
|
1896
|
-
if (winnerIndex === -1) {
|
|
1897
|
-
return { demotions, roleUnions: [], expectsRewrites: [], relationsRetargeted: [] };
|
|
1898
|
-
}
|
|
1899
|
-
const winnerName = orbitalEntityName(orbitals[winnerIndex]);
|
|
1900
|
-
if (winnerName === null) throw new Error("identity dedupe requires a named identity entity");
|
|
1901
|
-
const demotedNames = new Set(demotions.map((d) => d.entityName));
|
|
1902
|
-
const strayExpects = [];
|
|
1903
|
-
for (const def of orbitals) {
|
|
1904
|
-
for (const e of def.expects ?? []) {
|
|
1905
|
-
if (e.kind !== "identity" || e.name === void 0 || e.name === winnerName || demotedNames.has(e.name)) continue;
|
|
1906
|
-
strayExpects.push({ name: e.name, shape: e.shape ?? [] });
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
if (demotions.length === 0 && strayExpects.length === 0) {
|
|
1910
|
-
return { demotions, roleUnions: [], expectsRewrites: [], relationsRetargeted: [] };
|
|
1911
|
-
}
|
|
1912
|
-
const providedNames = new Set(orbitals.flatMap((def) => inlineEntitiesOf(def).map((e) => e.name)));
|
|
1913
|
-
const roleUnions = unionDemotedRoleVocabularies(orbitals, winnerIndex, [
|
|
1914
|
-
...demotedEntities.map((d) => ({ name: d.name, fields: d.fields })),
|
|
1915
|
-
...strayExpects.map((e) => ({ name: e.name, fields: e.shape }))
|
|
1916
|
-
]);
|
|
1917
|
-
const loserNames = /* @__PURE__ */ new Set([
|
|
1918
|
-
...demotedNames,
|
|
1919
|
-
...strayExpects.map((e) => e.name).filter((name) => providedNames.has(name))
|
|
1920
|
-
]);
|
|
1921
|
-
const expectsRewrites = rewriteDemotedIdentityExpects(orbitals, loserNames, winnerName);
|
|
1922
|
-
const relationsRetargeted = retargetDemotedOwnerRelations(orbitals, winnerIndex, loserNames);
|
|
1923
|
-
return { demotions, roleUnions, expectsRewrites, relationsRetargeted };
|
|
1924
|
-
}
|
|
1925
|
-
function fieldVocabulary(field) {
|
|
1926
|
-
if ("values" in field && Array.isArray(field.values) && field.values.length > 0) return field.values;
|
|
1927
|
-
if ((field.type === "array" || field.type === "object") && field.items !== void 0) {
|
|
1928
|
-
return fieldVocabulary(field.items);
|
|
1929
|
-
}
|
|
1930
|
-
return null;
|
|
1931
|
-
}
|
|
1932
|
-
function withUnionedVocabulary(field, missing) {
|
|
1933
|
-
if ("values" in field && Array.isArray(field.values) && field.values.length > 0) {
|
|
1934
|
-
return { ...field, values: [...field.values, ...missing] };
|
|
1935
|
-
}
|
|
1936
|
-
if ((field.type === "array" || field.type === "object") && field.items !== void 0) {
|
|
1937
|
-
return { ...field, items: withUnionedVocabulary(field.items, missing) };
|
|
1938
|
-
}
|
|
1939
|
-
return field;
|
|
1940
|
-
}
|
|
1941
|
-
function identityVocabularyDelta(identity, others) {
|
|
1942
|
-
const delta = { fields: [], added: [] };
|
|
1943
|
-
for (const field of identity.fields ?? []) {
|
|
1944
|
-
if (typeof field.name !== "string") continue;
|
|
1945
|
-
const vocab = fieldVocabulary(field);
|
|
1946
|
-
if (vocab === null) continue;
|
|
1947
|
-
const referenced = /* @__PURE__ */ new Set();
|
|
1948
|
-
for (const def of others) {
|
|
1949
|
-
collectFieldComparisonLiterals(def, { entityName: identity.name, isIdentity: true, scopeEntityName: orbitalEntityName(def), field: field.name }, referenced);
|
|
1950
|
-
}
|
|
1951
|
-
const missing = [...referenced].filter((l) => !vocab.includes(l)).sort();
|
|
1952
|
-
if (missing.length === 0) continue;
|
|
1953
|
-
delta.fields.push(withUnionedVocabulary(field, missing));
|
|
1954
|
-
delta.added.push({ field: field.name, literals: missing });
|
|
1955
|
-
}
|
|
1956
|
-
return delta;
|
|
1957
|
-
}
|
|
1958
|
-
function unionDemotedRoleVocabularies(orbitals, winnerIndex, demotedEntities) {
|
|
1959
|
-
const winnerDef = orbitals[winnerIndex];
|
|
1960
|
-
const winnerEntity = winnerDef.entity;
|
|
1961
|
-
if (winnerEntity === void 0 || isEntityReferenceAny(winnerEntity)) return [];
|
|
1962
|
-
const winnerFields = winnerEntity.fields;
|
|
1963
|
-
const fieldNames = /* @__PURE__ */ new Set();
|
|
1964
|
-
for (const demoted of demotedEntities) {
|
|
1965
|
-
for (const f of demoted.fields) {
|
|
1966
|
-
if (typeof f.name === "string") fieldNames.add(f.name);
|
|
1967
|
-
}
|
|
1968
|
-
}
|
|
1969
|
-
const unions = [];
|
|
1970
|
-
const replacements = /* @__PURE__ */ new Map();
|
|
1971
|
-
const mismatches = [];
|
|
1972
|
-
for (const fieldName of [...fieldNames].sort()) {
|
|
1973
|
-
const referenced = /* @__PURE__ */ new Set();
|
|
1974
|
-
for (const def of orbitals) {
|
|
1975
|
-
collectFieldComparisonLiterals(def, {
|
|
1976
|
-
entityName: winnerEntity.name,
|
|
1977
|
-
isIdentity: true,
|
|
1978
|
-
scopeEntityName: orbitalEntityName(def),
|
|
1979
|
-
field: fieldName
|
|
1980
|
-
}, referenced);
|
|
1981
|
-
}
|
|
1982
|
-
const winnerField = winnerFields.find((f) => f.name === fieldName);
|
|
1983
|
-
if (winnerField !== void 0 && fieldVocabulary(winnerField) !== null) {
|
|
1984
|
-
for (const demoted of demotedEntities) {
|
|
1985
|
-
const own = demoted.fields.find((f) => f.name === fieldName);
|
|
1986
|
-
for (const literal of (own !== void 0 ? fieldVocabulary(own) : null) ?? []) referenced.add(literal);
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
|
-
if (referenced.size === 0) continue;
|
|
1990
|
-
if (winnerField === void 0) {
|
|
1991
|
-
const sources = demotedEntities.filter((d) => d.fields.some((f) => f.name === fieldName)).map((d) => d.name);
|
|
1992
|
-
mismatches.push(
|
|
1993
|
-
`@user.${fieldName} is compared against ${[...referenced].sort().map((l) => JSON.stringify(l)).join(", ")} (field declared by demoted ${sources.join(", ")}), but the surviving [identity] entity ${winnerEntity.name} declares no field "${fieldName}"`
|
|
1994
|
-
);
|
|
1995
|
-
continue;
|
|
1996
|
-
}
|
|
1997
|
-
const vocab = fieldVocabulary(winnerField);
|
|
1998
|
-
if (vocab === null) continue;
|
|
1999
|
-
const missing = [...referenced].filter((l) => !vocab.includes(l)).sort();
|
|
2000
|
-
if (missing.length === 0) continue;
|
|
2001
|
-
replacements.set(fieldName, withUnionedVocabulary(winnerField, missing));
|
|
2002
|
-
unions.push({
|
|
2003
|
-
orbitalName: winnerDef.name,
|
|
2004
|
-
entityName: winnerEntity.name,
|
|
2005
|
-
field: fieldName,
|
|
2006
|
-
addedLiterals: missing
|
|
2007
|
-
});
|
|
2008
|
-
}
|
|
2009
|
-
if (mismatches.length > 0) {
|
|
2010
|
-
throw new Error(
|
|
2011
|
-
`identity dedupe shape mismatch \u2014 ${mismatches.join("; ")}. The identity shapes cannot be reconciled deterministically and silently dropping the literals ships dead policy branches (ORB_S_ROLE_LITERAL_NOT_MEMBER); compose cannot proceed.`
|
|
2012
|
-
);
|
|
2013
|
-
}
|
|
2014
|
-
if (replacements.size > 0) {
|
|
2015
|
-
orbitals[winnerIndex] = {
|
|
2016
|
-
...winnerDef,
|
|
2017
|
-
entity: {
|
|
2018
|
-
...winnerEntity,
|
|
2019
|
-
fields: winnerFields.map((f) => typeof f.name === "string" ? replacements.get(f.name) ?? f : f)
|
|
2020
|
-
}
|
|
2021
|
-
};
|
|
2022
|
-
}
|
|
2023
|
-
return unions;
|
|
2024
|
-
}
|
|
2025
|
-
function collectPersistedFields(node, entityName, out) {
|
|
2026
|
-
if (Array.isArray(node)) {
|
|
2027
|
-
if (node[0] === "persist" && (node[1] === "create" || node[1] === "upsert" || node[1] === "update") && node[2] === entityName) {
|
|
2028
|
-
const payload = node[3];
|
|
2029
|
-
const isOptionsBag = node.length === 4 && payload !== null && typeof payload === "object" && !Array.isArray(payload) && "emit" in payload;
|
|
2030
|
-
if (payload !== null && typeof payload === "object" && !Array.isArray(payload) && !isOptionsBag) {
|
|
2031
|
-
for (const key of Object.keys(payload)) out.add(key);
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
for (const item of node) collectPersistedFields(item, entityName, out);
|
|
2035
|
-
return;
|
|
2036
|
-
}
|
|
2037
|
-
if (node !== null && typeof node === "object") {
|
|
2038
|
-
for (const value of Object.values(node)) collectPersistedFields(value, entityName, out);
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2041
|
-
function rewriteDemotedIdentityExpects(orbitals, demotedNames, winnerName) {
|
|
2042
|
-
const entityByName = /* @__PURE__ */ new Map();
|
|
2043
|
-
for (const def of orbitals) for (const entity of inlineEntitiesOf(def)) entityByName.set(entity.name, entity);
|
|
2044
|
-
const rewrites = [];
|
|
2045
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2046
|
-
const def = orbitals[i];
|
|
2047
|
-
const expects = def.expects;
|
|
2048
|
-
if (expects === void 0) continue;
|
|
2049
|
-
let mutated = false;
|
|
2050
|
-
let viewerShape;
|
|
2051
|
-
const next = expects.map((e) => {
|
|
2052
|
-
if (e.kind !== "identity" || e.name === void 0 || !demotedNames.has(e.name)) return e;
|
|
2053
|
-
viewerShape = mergeExpectationShape(viewerShape, e.shape);
|
|
2054
|
-
mutated = true;
|
|
2055
|
-
rewrites.push({ orbitalName: def.name, entityName: e.name });
|
|
2056
|
-
if (e.shape === void 0) return { kind: "entity", name: e.name };
|
|
2057
|
-
const persisted = /* @__PURE__ */ new Set();
|
|
2058
|
-
collectPersistedFields(def.traits ?? [], e.name, persisted);
|
|
2059
|
-
const declared = new Set(e.shape.map((f) => f.name));
|
|
2060
|
-
const entity = entityByName.get(e.name);
|
|
2061
|
-
const asDeclared = (field) => entity?.fields.find((f) => f.name === field.name) ?? field;
|
|
2062
|
-
const added = [...persisted].sort().flatMap((field) => {
|
|
2063
|
-
if (declared.has(field)) return [];
|
|
2064
|
-
const own = entity?.fields.find((f) => f.name === field);
|
|
2065
|
-
return own !== void 0 ? [own] : [];
|
|
2066
|
-
});
|
|
2067
|
-
return { kind: "entity", name: e.name, shape: [...e.shape.map(asDeclared), ...added] };
|
|
2068
|
-
});
|
|
2069
|
-
if (mutated) {
|
|
2070
|
-
const viewerIndex = next.findIndex((e) => e.kind === "identity" && (e.name === winnerName || e.name === void 0));
|
|
2071
|
-
const viewer = next[viewerIndex];
|
|
2072
|
-
const shape = mergeExpectationShape(viewer?.kind === "identity" ? viewer.shape : void 0, viewerShape);
|
|
2073
|
-
const requirement = { kind: "identity", name: winnerName, ...shape !== void 0 ? { shape } : {} };
|
|
2074
|
-
if (viewerIndex < 0) next.push(requirement);
|
|
2075
|
-
else next[viewerIndex] = requirement;
|
|
2076
|
-
orbitals[i] = { ...def, expects: next };
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2079
|
-
return rewrites;
|
|
2080
|
-
}
|
|
2081
|
-
function inlineEntitiesOf(def) {
|
|
2082
|
-
const out = [];
|
|
2083
|
-
if (def.entity !== void 0 && !isEntityReferenceAny(def.entity)) out.push(def.entity);
|
|
2084
|
-
for (const er of def.auxiliaryEntities ?? []) {
|
|
2085
|
-
if (!isEntityReferenceAny(er)) out.push(er);
|
|
2086
|
-
}
|
|
2087
|
-
return out;
|
|
2088
|
-
}
|
|
2089
|
-
function retargetOwnerRelationFields(entity, fieldNames, demotedNames, winner) {
|
|
2090
|
-
if (fieldNames === void 0) return null;
|
|
2091
|
-
const applied = [];
|
|
2092
|
-
const fields = entity.fields.map((f) => {
|
|
2093
|
-
if (f.name === void 0 || !fieldNames.has(f.name) || f.type !== "relation") return f;
|
|
2094
|
-
if (!demotedNames.has(f.relation.entity)) return f;
|
|
2095
|
-
applied.push({ field: f.name, fromEntity: f.relation.entity, toEntity: winner.name });
|
|
2096
|
-
const relation = { ...f.relation, entity: winner.name };
|
|
2097
|
-
if (relation.entityId !== void 0) {
|
|
2098
|
-
if (winner.id !== void 0) relation.entityId = winner.id;
|
|
2099
|
-
else delete relation.entityId;
|
|
2100
|
-
}
|
|
2101
|
-
return { ...f, relation };
|
|
2102
|
-
});
|
|
2103
|
-
return applied.length === 0 ? null : { entity: { ...entity, fields }, applied };
|
|
2104
|
-
}
|
|
2105
|
-
function retargetDemotedOwnerRelations(orbitals, winnerIndex, demotedNames) {
|
|
2106
|
-
const winnerDef = orbitals[winnerIndex];
|
|
2107
|
-
const winnerEntity = winnerDef.entity;
|
|
2108
|
-
if (winnerEntity === void 0 || isEntityReferenceAny(winnerEntity)) return [];
|
|
2109
|
-
const candidates = /* @__PURE__ */ new Map();
|
|
2110
|
-
const addAll = (entityName, fields) => {
|
|
2111
|
-
if (fields.size === 0) return;
|
|
2112
|
-
const set = candidates.get(entityName) ?? /* @__PURE__ */ new Set();
|
|
2113
|
-
for (const f of fields) set.add(f);
|
|
2114
|
-
candidates.set(entityName, set);
|
|
2115
|
-
};
|
|
2116
|
-
for (const def of orbitals) {
|
|
2117
|
-
for (const entity of inlineEntitiesOf(def)) {
|
|
2118
|
-
const fields = /* @__PURE__ */ new Set();
|
|
2119
|
-
for (const policy of [entity.read_policy, entity.create_policy, entity.update_policy, entity.delete_policy]) {
|
|
2120
|
-
if (policy !== void 0) collectOwnerComparedFields(policy, fields);
|
|
2121
|
-
}
|
|
2122
|
-
addAll(entity.name, fields);
|
|
2123
|
-
}
|
|
2124
|
-
const stamped = /* @__PURE__ */ new Map();
|
|
2125
|
-
collectOwnerStampedFields(def.traits ?? [], stamped);
|
|
2126
|
-
for (const [entityName, fields] of stamped) addAll(entityName, fields);
|
|
2127
|
-
}
|
|
2128
|
-
const retargets = [];
|
|
2129
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2130
|
-
const def = orbitals[i];
|
|
2131
|
-
let next = def;
|
|
2132
|
-
if (next.entity !== void 0 && !isEntityReferenceAny(next.entity)) {
|
|
2133
|
-
const replaced = retargetOwnerRelationFields(next.entity, candidates.get(next.entity.name), demotedNames, winnerEntity);
|
|
2134
|
-
if (replaced !== null) {
|
|
2135
|
-
next = { ...next, entity: replaced.entity };
|
|
2136
|
-
for (const a of replaced.applied) retargets.push({ orbitalName: def.name, entityName: replaced.entity.name, ...a });
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
const aux = next.auxiliaryEntities;
|
|
2140
|
-
if (aux !== void 0) {
|
|
2141
|
-
let auxNext = aux;
|
|
2142
|
-
for (let j = 0; j < aux.length; j += 1) {
|
|
2143
|
-
const er = aux[j];
|
|
2144
|
-
if (isEntityReferenceAny(er)) continue;
|
|
2145
|
-
const replaced = retargetOwnerRelationFields(er, candidates.get(er.name), demotedNames, winnerEntity);
|
|
2146
|
-
if (replaced === null) continue;
|
|
2147
|
-
if (auxNext === aux) auxNext = [...aux];
|
|
2148
|
-
auxNext[j] = replaced.entity;
|
|
2149
|
-
for (const a of replaced.applied) retargets.push({ orbitalName: def.name, entityName: replaced.entity.name, ...a });
|
|
2150
|
-
}
|
|
2151
|
-
if (auxNext !== aux) next = { ...next, auxiliaryEntities: auxNext };
|
|
2152
|
-
}
|
|
2153
|
-
if (next !== def) orbitals[i] = next;
|
|
2154
|
-
}
|
|
2155
|
-
return retargets;
|
|
2156
|
-
}
|
|
2157
|
-
function asEntityObject(entity) {
|
|
2158
|
-
if (entity === void 0 || entity === null || typeof entity === "string") return null;
|
|
2159
|
-
return entity;
|
|
2160
|
-
}
|
|
2161
|
-
function orbitalEntityName(def) {
|
|
2162
|
-
const name = asEntityObject(def.entity)?.name;
|
|
2163
|
-
return typeof name === "string" ? name : null;
|
|
2164
|
-
}
|
|
2165
|
-
function isNavItemsConfigField(entry) {
|
|
2166
|
-
return isJsonObject(entry) && entry["type"] === "[NavItem]" && Array.isArray(entry["default"]);
|
|
2167
|
-
}
|
|
2168
|
-
function narrowNavItemsToOwnedPages(orbitals, ownedPages) {
|
|
2169
|
-
const drops = [];
|
|
2170
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2171
|
-
const node = cloneOrbitalNode(orbitals[i]);
|
|
2172
|
-
const orbitalName = typeof node["name"] === "string" ? node["name"] : `orbital-${i}`;
|
|
2173
|
-
const traitDefs = node["traits"];
|
|
2174
|
-
if (!Array.isArray(traitDefs)) continue;
|
|
2175
|
-
let mutated = false;
|
|
2176
|
-
for (const t of traitDefs) {
|
|
2177
|
-
if (!isJsonObject(t)) continue;
|
|
2178
|
-
const config = t["config"];
|
|
2179
|
-
if (!isJsonObject(config)) continue;
|
|
2180
|
-
const traitName = typeof t["name"] === "string" ? t["name"] : typeof t["ref"] === "string" ? t["ref"] : "trait";
|
|
2181
|
-
for (const [key, entry] of Object.entries(config)) {
|
|
2182
|
-
if (!isNavItemsConfigField(entry)) continue;
|
|
2183
|
-
const kept = [];
|
|
2184
|
-
const droppedHrefs = [];
|
|
2185
|
-
for (const item of entry.default) {
|
|
2186
|
-
const href = isJsonObject(item) && typeof item["href"] === "string" ? item["href"] : void 0;
|
|
2187
|
-
if (href !== void 0 && !ownedPages.has(href)) {
|
|
2188
|
-
droppedHrefs.push(href);
|
|
2189
|
-
} else {
|
|
2190
|
-
kept.push(item);
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
if (droppedHrefs.length > 0) {
|
|
2194
|
-
config[key] = { ...entry, default: kept };
|
|
2195
|
-
mutated = true;
|
|
2196
|
-
drops.push({ orbitalName, traitName, droppedHrefs });
|
|
2197
|
-
}
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2200
|
-
if (mutated) orbitals[i] = nodeToOrbital(node);
|
|
2201
|
-
}
|
|
2202
|
-
return drops;
|
|
2203
|
-
}
|
|
2204
|
-
function collectOwnedPages(orbitals, importedOrbitalOf) {
|
|
2205
|
-
const owned = /* @__PURE__ */ new Set();
|
|
2206
|
-
const traitNames = /* @__PURE__ */ new Set();
|
|
2207
|
-
for (const orbital of orbitals) {
|
|
2208
|
-
collectOwnedSurface(cloneOrbitalNode(orbital), owned, traitNames);
|
|
2209
|
-
if (importedOrbitalOf === void 0) continue;
|
|
2210
|
-
for (const path of importedPagePaths(orbital, importedOrbitalOf, /* @__PURE__ */ new Set())) owned.add(path);
|
|
2211
|
-
}
|
|
2212
|
-
return owned;
|
|
2213
|
-
}
|
|
2214
|
-
function importedPagePaths(orbital, importedOrbitalOf, seen) {
|
|
2215
|
-
const reference = orbital.reference;
|
|
2216
|
-
if (reference === void 0 || seen.has(orbital)) return [];
|
|
2217
|
-
seen.add(orbital);
|
|
2218
|
-
const upstream = importedOrbitalOf(orbital);
|
|
2219
|
-
if (upstream === void 0) return [];
|
|
2220
|
-
const upstreamPaths = [];
|
|
2221
|
-
for (const page of upstream.pages ?? []) {
|
|
2222
|
-
if (!isPageReference(page) && isRoutePage(page) && typeof page.path === "string") upstreamPaths.push(page.path);
|
|
2223
|
-
}
|
|
2224
|
-
upstreamPaths.push(...importedPagePaths(upstream, importedOrbitalOf, seen));
|
|
2225
|
-
const omitted = new Set(reference.omit ?? []);
|
|
2226
|
-
const remap = reference.pages ?? {};
|
|
2227
|
-
return upstreamPaths.filter((path) => !omitted.has(path)).map((path) => remap[path] ?? path);
|
|
2228
|
-
}
|
|
2229
|
-
function organismOrderResolver(catalogOrbitalOf, loadOrganism) {
|
|
2230
|
-
const declared = /* @__PURE__ */ new Map();
|
|
2231
|
-
return (orbitalName) => {
|
|
2232
|
-
const source = catalogOrbitalOf(orbitalName);
|
|
2233
|
-
if (source === void 0) return void 0;
|
|
2234
|
-
if (!declared.has(source.organism)) {
|
|
2235
|
-
declared.set(source.organism, loadOrganism(source.organism)?.orbitals.map((o) => o.name) ?? null);
|
|
2236
|
-
}
|
|
2237
|
-
const index = declared.get(source.organism)?.indexOf(source.orbital) ?? -1;
|
|
2238
|
-
return index >= 0 ? index : void 0;
|
|
2239
|
-
};
|
|
2240
|
-
}
|
|
2241
|
-
function orbitalImportResolver(loadBehaviorOrb) {
|
|
2242
|
-
const loaded = /* @__PURE__ */ new Map();
|
|
2243
|
-
return (orbital) => {
|
|
2244
|
-
const ref = orbital.reference?.ref;
|
|
2245
|
-
if (ref === void 0) return void 0;
|
|
2246
|
-
const [alias, kind, name] = ref.split(".");
|
|
2247
|
-
if (kind !== "orbitals" || name === void 0) return void 0;
|
|
2248
|
-
const use = (orbital.uses ?? []).find((u) => u.as === alias);
|
|
2249
|
-
if (use === void 0) return void 0;
|
|
2250
|
-
const behavior = use.from.split("/").pop() ?? use.from;
|
|
2251
|
-
if (!loaded.has(behavior)) loaded.set(behavior, loadBehaviorOrb(behavior));
|
|
2252
|
-
return loaded.get(behavior)?.orbitals.find((o) => o.name === name);
|
|
2253
|
-
};
|
|
2254
|
-
}
|
|
2255
|
-
function narrowConfigNavItems(config, ownedPages) {
|
|
2256
|
-
const drops = [];
|
|
2257
|
-
const next = { ...config };
|
|
2258
|
-
for (const [knob, field] of Object.entries(config)) {
|
|
2259
|
-
if (field.type !== "[NavItem]" || !Array.isArray(field.default)) continue;
|
|
2260
|
-
const droppedHrefs = [];
|
|
2261
|
-
const kept = field.default.filter((item) => {
|
|
2262
|
-
const href = navItemHref(item);
|
|
2263
|
-
if (href !== void 0 && !ownedPages.has(href)) {
|
|
2264
|
-
droppedHrefs.push(href);
|
|
2265
|
-
return false;
|
|
2266
|
-
}
|
|
2267
|
-
return true;
|
|
2268
|
-
});
|
|
2269
|
-
if (droppedHrefs.length === 0) continue;
|
|
2270
|
-
next[knob] = { ...field, default: kept };
|
|
2271
|
-
drops.push({ knob, droppedHrefs });
|
|
2272
|
-
}
|
|
2273
|
-
return { config: next, drops };
|
|
2274
|
-
}
|
|
2275
|
-
function collectLinkedPaths(node, out) {
|
|
2276
|
-
if (Array.isArray(node)) {
|
|
2277
|
-
if (node[0] === "navigate" && typeof node[1] === "string") out.add(node[1]);
|
|
2278
|
-
for (const item of node) collectLinkedPaths(item, out);
|
|
2279
|
-
return;
|
|
2280
|
-
}
|
|
2281
|
-
if (node !== null && typeof node === "object") {
|
|
2282
|
-
for (const [key, value] of Object.entries(node)) {
|
|
2283
|
-
if (key === "href" && typeof value === "string") out.add(value);
|
|
2284
|
-
collectLinkedPaths(value, out);
|
|
2285
|
-
}
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
function firstInlinePage(orbital) {
|
|
2289
|
-
for (const page of orbital.pages ?? []) {
|
|
2290
|
-
if (isPageReference(page) || !isRoutePage(page)) continue;
|
|
2291
|
-
if (typeof page.path === "string" && typeof page.name === "string") return { name: page.name, path: page.path };
|
|
2292
|
-
}
|
|
2293
|
-
return void 0;
|
|
2294
|
-
}
|
|
2295
|
-
function linkLandingPages(orbitals, config, organismOf, navDeclaringOrbitals, organismOrderOf) {
|
|
2296
|
-
const navKnobs = Object.entries(config).filter(([, field2]) => field2.type === "[NavItem]" && Array.isArray(field2.default));
|
|
2297
|
-
if (navKnobs.length !== 1) return { config, added: [] };
|
|
2298
|
-
const [knob, field] = navKnobs[0];
|
|
2299
|
-
const list = Array.isArray(field.default) ? field.default : [];
|
|
2300
|
-
const linked = /* @__PURE__ */ new Set();
|
|
2301
|
-
collectLinkedPaths(orbitals, linked);
|
|
2302
|
-
collectLinkedPaths(config, linked);
|
|
2303
|
-
const ownerIndex = /* @__PURE__ */ new Map();
|
|
2304
|
-
orbitals.forEach((orbital, i) => {
|
|
2305
|
-
for (const page of orbital.pages ?? []) {
|
|
2306
|
-
if (!isPageReference(page) && isRoutePage(page) && typeof page.path === "string" && !ownerIndex.has(page.path)) ownerIndex.set(page.path, i);
|
|
2307
|
-
}
|
|
2308
|
-
});
|
|
2309
|
-
const indexOf = (entry) => {
|
|
2310
|
-
const href = navItemHref(entry);
|
|
2311
|
-
return href !== void 0 ? ownerIndex.get(href) ?? -1 : -1;
|
|
2312
|
-
};
|
|
2313
|
-
const added = [];
|
|
2314
|
-
const next = [...list];
|
|
2315
|
-
const navOrganisms = /* @__PURE__ */ new Set();
|
|
2316
|
-
for (const name of navDeclaringOrbitals) {
|
|
2317
|
-
const organism = organismOf(name);
|
|
2318
|
-
if (organism !== void 0) navOrganisms.add(organism);
|
|
2319
|
-
}
|
|
2320
|
-
const landingOf = /* @__PURE__ */ new Map();
|
|
2321
|
-
orbitals.forEach((orbital, i) => {
|
|
2322
|
-
const organism = organismOf(orbital.name);
|
|
2323
|
-
if (organism === void 0 || firstInlinePage(orbital) === void 0) return;
|
|
2324
|
-
const rank = organismOrderOf?.(orbital.name) ?? orbitals.length + i;
|
|
2325
|
-
const current = landingOf.get(organism);
|
|
2326
|
-
if (current === void 0 || rank < current.rank) landingOf.set(organism, { name: orbital.name, rank });
|
|
2327
|
-
});
|
|
2328
|
-
let bootOrganism;
|
|
2329
|
-
let booted = false;
|
|
2330
|
-
orbitals.forEach((orbital, i) => {
|
|
2331
|
-
const page = firstInlinePage(orbital);
|
|
2332
|
-
if (page === void 0) return;
|
|
2333
|
-
const organism = organismOf(orbital.name);
|
|
2334
|
-
if (!booted) {
|
|
2335
|
-
booted = true;
|
|
2336
|
-
bootOrganism = organism;
|
|
2337
|
-
return;
|
|
2338
|
-
}
|
|
2339
|
-
if (organism === void 0) return;
|
|
2340
|
-
if (navOrganisms.has(organism) && (organism === bootOrganism || landingOf.get(organism)?.name !== orbital.name)) return;
|
|
2341
|
-
if (linked.has(page.path) || page.path.split("/").some((segment) => segment.startsWith(":"))) return;
|
|
2342
|
-
let at = 0;
|
|
2343
|
-
next.forEach((entry, p) => {
|
|
2344
|
-
if (indexOf(entry) < i) at = p + 1;
|
|
2345
|
-
});
|
|
2346
|
-
next.splice(at, 0, { href: page.path, label: humanizeKey(page.name) });
|
|
2347
|
-
linked.add(page.path);
|
|
2348
|
-
added.push({ organism, href: page.path });
|
|
2349
|
-
});
|
|
2350
|
-
if (added.length === 0) return { config, added };
|
|
2351
|
-
return { config: { ...config, [knob]: { ...field, default: next } }, added };
|
|
2352
|
-
}
|
|
2353
|
-
function organismPrefix(organism) {
|
|
2354
|
-
return organism.replace(/^std-/, "").split(/[^a-zA-Z0-9]+/).filter(Boolean).map((w) => w[0].toUpperCase() + w.slice(1)).join("");
|
|
2355
|
-
}
|
|
2356
|
-
function snakePrefix(prefix) {
|
|
2357
|
-
return prefix.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
2358
|
-
}
|
|
2359
|
-
function routeShape(path) {
|
|
2360
|
-
return path.split("/").map((segment) => segment.startsWith(":") ? ":" : segment).join("/");
|
|
2361
|
-
}
|
|
2362
|
-
function routeRoot(path) {
|
|
2363
|
-
return `/${path.split("/")[1] ?? ""}`;
|
|
2364
|
-
}
|
|
2365
|
-
function underRoot(link, root) {
|
|
2366
|
-
return link === root || link.startsWith(`${root}/`);
|
|
2367
|
-
}
|
|
2368
|
-
function pagePaths(file) {
|
|
2369
|
-
return asDefinitions([file]).flatMap((orbital) => (orbital.pages ?? []).flatMap((page) => !isPageReference(page) && typeof page.path === "string" ? [page.path] : []));
|
|
2370
|
-
}
|
|
2371
|
-
function moveRoutes(node, roots, base, inPages = false) {
|
|
2372
|
-
const move = (path) => path === "/" ? base : `${base}${path}`;
|
|
2373
|
-
const hit = (value) => [...roots].some((root) => underRoot(value, root));
|
|
2374
|
-
if (Array.isArray(node)) {
|
|
2375
|
-
const out2 = node.map((item) => moveRoutes(item, roots, base, inPages));
|
|
2376
|
-
if (node[0] === "navigate" && typeof node[1] === "string" && hit(node[1])) out2[1] = move(node[1]);
|
|
2377
|
-
return out2;
|
|
2378
|
-
}
|
|
2379
|
-
if (!isJsonObject(node)) return node;
|
|
2380
|
-
const out = {};
|
|
2381
|
-
for (const [key, value] of Object.entries(node)) {
|
|
2382
|
-
if (typeof value === "string" && (key === "href" || inPages && key === "path") && hit(value)) out[key] = move(value);
|
|
2383
|
-
else out[key] = moveRoutes(value, roots, base, key === "pages");
|
|
2384
|
-
}
|
|
2385
|
-
return out;
|
|
2386
|
-
}
|
|
2387
|
-
function declaredEntities(file) {
|
|
2388
|
-
return asDefinitions([file]).flatMap((orbital) => inlineEntitiesOf(orbital));
|
|
2389
|
-
}
|
|
2390
|
-
function renameCollection(file, from, to) {
|
|
2391
|
-
const swap = (entity) => entity.collection === from ? { ...entity, collection: to } : entity;
|
|
2392
|
-
const each = (orbital) => ({
|
|
2393
|
-
...orbital,
|
|
2394
|
-
...orbital.entity !== void 0 && !isEntityReferenceAny(orbital.entity) ? { entity: swap(orbital.entity) } : {},
|
|
2395
|
-
...orbital.auxiliaryEntities !== void 0 ? { auxiliaryEntities: orbital.auxiliaryEntities.map((e) => isEntityReferenceAny(e) ? e : swap(e)) } : {}
|
|
2396
|
-
});
|
|
2397
|
-
return "orbitals" in file ? { ...file, orbitals: file.orbitals.map(each) } : each(file);
|
|
2398
|
-
}
|
|
2399
|
-
function namespaceOrganisms(files, organismOf, atomTraitOf) {
|
|
2400
|
-
const organismOfFile = (file) => {
|
|
2401
|
-
const first = asDefinitions([file])[0];
|
|
2402
|
-
return first !== void 0 ? organismOf(first.name) : void 0;
|
|
2403
|
-
};
|
|
2404
|
-
const out = [...files];
|
|
2405
|
-
const order = [];
|
|
2406
|
-
for (const file of files) {
|
|
2407
|
-
const organism = organismOfFile(file);
|
|
2408
|
-
if (organism !== void 0 && !order.includes(organism)) order.push(organism);
|
|
2409
|
-
}
|
|
2410
|
-
const entityOwner = /* @__PURE__ */ new Map();
|
|
2411
|
-
const collectionOwner = /* @__PURE__ */ new Map();
|
|
2412
|
-
const routeOwner = /* @__PURE__ */ new Map();
|
|
2413
|
-
const renames = [];
|
|
2414
|
-
const unrenamable = [];
|
|
2415
|
-
const implicitOwner = /* @__PURE__ */ new Map();
|
|
2416
|
-
const implicitKey = /* @__PURE__ */ new Map();
|
|
2417
|
-
for (const organism of order) {
|
|
2418
|
-
const own = files.filter((file) => organismOfFile(file) === organism);
|
|
2419
|
-
const declared = new Set(own.flatMap((file) => declaredEntities(file).map((e) => e.name)));
|
|
2420
|
-
const conflicts = /* @__PURE__ */ new Map();
|
|
2421
|
-
for (const orbital of asDefinitions([...own])) {
|
|
2422
|
-
const node = cloneOrbitalNode(orbital);
|
|
2423
|
-
const traits = Array.isArray(node["traits"]) ? node["traits"] : [];
|
|
2424
|
-
for (const trait of traits) {
|
|
2425
|
-
if (!isJsonObject(trait) || typeof trait["ref"] !== "string" || trait["linkedEntity"] !== void 0) continue;
|
|
2426
|
-
const ref = trait["ref"];
|
|
2427
|
-
const implicit = atomTraitOf(orbital, ref)?.linkedEntity;
|
|
2428
|
-
if (implicit === void 0 || declared.has(implicit)) continue;
|
|
2429
|
-
const alias = ref.split(".")[0];
|
|
2430
|
-
const behavior = (orbital.uses ?? []).find((u) => u.as === alias)?.from ?? alias;
|
|
2431
|
-
const typeArgs = isJsonObject(trait["typeArgs"]) ? Object.entries(trait["typeArgs"]).sort(([a], [b]) => a.localeCompare(b)) : [];
|
|
2432
|
-
const key = JSON.stringify([behavior, ref.split(".").slice(1), typeArgs]);
|
|
2433
|
-
const owner = implicitOwner.get(implicit);
|
|
2434
|
-
if (owner === void 0) {
|
|
2435
|
-
implicitOwner.set(implicit, organism);
|
|
2436
|
-
implicitKey.set(implicit, key);
|
|
2437
|
-
} else if (owner !== organism && implicitKey.get(implicit) !== key) {
|
|
2438
|
-
const blockers = conflicts.get(implicit) ?? [];
|
|
2439
|
-
blockers.push({ orbitalName: orbital.name, traitName: typeof trait["name"] === "string" ? trait["name"] : ref, traitRef: ref });
|
|
2440
|
-
conflicts.set(implicit, blockers);
|
|
2441
|
-
}
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
for (const [entity, blockers] of conflicts) unrenamable.push({ organism, entity, blockers });
|
|
2445
|
-
}
|
|
2446
|
-
for (const organism of order) {
|
|
2447
|
-
const indices = out.flatMap((file, i) => organismOfFile(file) === organism ? [i] : []);
|
|
2448
|
-
const orbitalsOf = () => indices.flatMap((i) => asDefinitions([out[i]]));
|
|
2449
|
-
const prefix = organismPrefix(organism);
|
|
2450
|
-
const rename = { organism, entities: [], collections: [], routes: [] };
|
|
2451
|
-
const names = [...new Set(indices.flatMap((i) => declaredEntities(out[i]).map((e) => e.name)))];
|
|
2452
|
-
for (const name of names) {
|
|
2453
|
-
const owner = entityOwner.get(name);
|
|
2454
|
-
const implicit = implicitOwner.get(name);
|
|
2455
|
-
const collides = owner !== void 0 && owner !== organism || implicit !== void 0 && implicit !== organism;
|
|
2456
|
-
if (!collides) continue;
|
|
2457
|
-
const blockers = entityRenameBlockers(orbitalsOf(), name, atomTraitOf);
|
|
2458
|
-
if (blockers.length > 0) {
|
|
2459
|
-
unrenamable.push({ organism, entity: name, blockers });
|
|
2460
|
-
continue;
|
|
2461
|
-
}
|
|
2462
|
-
const to = `${prefix}${name}`;
|
|
2463
|
-
for (const i of indices) {
|
|
2464
|
-
const file = out[i];
|
|
2465
|
-
out[i] = "orbitals" in file ? renameEntityInSchema(file, name, to, { atomTraitOf }) : renameEntity([file], name, to, { atomTraitOf })[0];
|
|
2466
|
-
}
|
|
2467
|
-
rename.entities.push({ from: name, to });
|
|
2468
|
-
}
|
|
2469
|
-
const roots = new Set(indices.flatMap((i) => pagePaths(out[i])).filter((path) => {
|
|
2470
|
-
const owner = routeOwner.get(routeShape(path));
|
|
2471
|
-
return owner !== void 0 && owner !== organism;
|
|
2472
|
-
}).map(routeRoot));
|
|
2473
|
-
if (roots.size > 0) {
|
|
2474
|
-
const base = `/${organism.replace(/^std-/, "")}`;
|
|
2475
|
-
for (const i of indices) {
|
|
2476
|
-
const file = out[i];
|
|
2477
|
-
const moved = moveRoutes(JSON.parse(JSON.stringify(file)), roots, base);
|
|
2478
|
-
if (isJsonObject(moved)) out[i] = JSON.parse(JSON.stringify(moved));
|
|
2479
|
-
}
|
|
2480
|
-
rename.routes.push(...[...roots].map((root) => ({ from: root, to: `${base}${root === "/" ? "" : root}` })));
|
|
2481
|
-
}
|
|
2482
|
-
const collections = [...new Set(indices.flatMap((i) => declaredEntities(out[i]).flatMap((e) => e.collection !== void 0 ? [e.collection] : [])))];
|
|
2483
|
-
for (const collection of collections) {
|
|
2484
|
-
const owner = collectionOwner.get(collection);
|
|
2485
|
-
if (owner === void 0 || owner === organism) continue;
|
|
2486
|
-
const to = `${snakePrefix(prefix)}_${collection}`;
|
|
2487
|
-
for (const i of indices) out[i] = renameCollection(out[i], collection, to);
|
|
2488
|
-
rename.collections.push({ from: collection, to });
|
|
2489
|
-
}
|
|
2490
|
-
for (const i of indices) {
|
|
2491
|
-
for (const path of pagePaths(out[i])) if (!routeOwner.has(routeShape(path))) routeOwner.set(routeShape(path), organism);
|
|
2492
|
-
for (const entity of declaredEntities(out[i])) {
|
|
2493
|
-
if (!entityOwner.has(entity.name)) entityOwner.set(entity.name, organism);
|
|
2494
|
-
if (entity.collection !== void 0 && !collectionOwner.has(entity.collection)) collectionOwner.set(entity.collection, organism);
|
|
2495
|
-
}
|
|
2496
|
-
}
|
|
2497
|
-
if (rename.entities.length > 0 || rename.collections.length > 0 || rename.routes.length > 0) renames.push(rename);
|
|
2498
|
-
}
|
|
2499
|
-
return { files: out, renames, unrenamable };
|
|
2500
|
-
}
|
|
2501
|
-
function renameNavHrefs(config, from, to) {
|
|
2502
|
-
let next;
|
|
2503
|
-
for (const [knob, field] of Object.entries(config)) {
|
|
2504
|
-
if (field.type !== "[NavItem]" || !Array.isArray(field.default)) continue;
|
|
2505
|
-
if (!field.default.some((item) => navItemHref(item) === from)) continue;
|
|
2506
|
-
next ?? (next = { ...config });
|
|
2507
|
-
next[knob] = { ...field, default: field.default.map((item) => navItemHref(item) === from && isJsonObject(item) ? { ...item, href: to } : item) };
|
|
2508
|
-
}
|
|
2509
|
-
return next ?? config;
|
|
2510
|
-
}
|
|
2511
|
-
function renameListenSources(node, orbital, from, to) {
|
|
2512
|
-
if (Array.isArray(node)) return node.map((item) => renameListenSources(item, orbital, from, to));
|
|
2513
|
-
if (!isJsonObject(node)) return node;
|
|
2514
|
-
const out = {};
|
|
2515
|
-
for (const [key, value] of Object.entries(node)) out[key] = renameListenSources(value, orbital, from, to);
|
|
2516
|
-
if (node["kind"] === "orbital" && node["orbital"] === orbital && node["trait"] === from) out["trait"] = to;
|
|
2517
|
-
return out;
|
|
2518
|
-
}
|
|
2519
|
-
function renameRouteLinks(node, from, to) {
|
|
2520
|
-
if (Array.isArray(node)) {
|
|
2521
|
-
const out2 = node.map((item) => renameRouteLinks(item, from, to));
|
|
2522
|
-
if (node[0] === "navigate" && node[1] === from) out2[1] = to;
|
|
2523
|
-
return out2;
|
|
2524
|
-
}
|
|
2525
|
-
if (!isJsonObject(node)) return node;
|
|
2526
|
-
const out = {};
|
|
2527
|
-
for (const [key, value] of Object.entries(node)) out[key] = key === "href" && value === from ? to : renameRouteLinks(value, from, to);
|
|
2528
|
-
return out;
|
|
2529
|
-
}
|
|
2530
|
-
function composeOrbitalSurface(files, options = {}) {
|
|
2531
|
-
const namespaced = options.organismOf !== void 0 ? namespaceOrganisms(files, options.organismOf, options.atomTraitOf ?? (() => void 0)) : { files: [...files], renames: [], unrenamable: [] };
|
|
2532
|
-
files = namespaced.files;
|
|
2533
|
-
const orbitals = [...asDefinitions([...files])];
|
|
2534
|
-
const surfaceRenames = dedupeComposedSurface(orbitals);
|
|
2535
|
-
for (const r of surfaceRenames.traits) {
|
|
2536
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2537
|
-
const next = nodeToOrbital(renameListenSources(cloneOrbitalNode(orbitals[i]), r.orbitalName, r.from, r.to));
|
|
2538
|
-
if (JSON.stringify(next) !== JSON.stringify(orbitals[i])) orbitals[i] = next;
|
|
2539
|
-
}
|
|
2540
|
-
}
|
|
2541
|
-
if (options.organismOf !== void 0) {
|
|
2542
|
-
for (const r of surfaceRenames.routes) {
|
|
2543
|
-
const organism = options.organismOf(r.orbitalName);
|
|
2544
|
-
if (organism === void 0) continue;
|
|
2545
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2546
|
-
const orbital = orbitals[i];
|
|
2547
|
-
if (orbital.name === r.orbitalName || options.organismOf(orbital.name) !== organism) continue;
|
|
2548
|
-
const next = nodeToOrbital(renameRouteLinks(cloneOrbitalNode(orbital), r.from, r.to));
|
|
2549
|
-
if (JSON.stringify(next) !== JSON.stringify(orbital)) orbitals[i] = next;
|
|
2550
|
-
}
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
const organismOfFile = (file) => new Set(asDefinitions([file]).map((o) => options.organismOf?.(o.name)));
|
|
2554
|
-
const renamedFiles = files.map((file) => {
|
|
2555
|
-
if (!("orbitals" in file) || file.config === void 0) return file;
|
|
2556
|
-
const ownNames = new Set(file.orbitals.map((o) => o.name));
|
|
2557
|
-
const organisms = organismOfFile(file);
|
|
2558
|
-
const ownPaths = /* @__PURE__ */ new Set();
|
|
2559
|
-
for (const o of orbitals) {
|
|
2560
|
-
if (!ownNames.has(o.name)) continue;
|
|
2561
|
-
for (const page of o.pages ?? []) {
|
|
2562
|
-
if (!isPageReference(page) && isRoutePage(page) && typeof page.path === "string") ownPaths.add(page.path);
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
let config2 = file.config;
|
|
2566
|
-
for (const r of surfaceRenames.routes) {
|
|
2567
|
-
const organism = options.organismOf?.(r.orbitalName);
|
|
2568
|
-
if (!ownNames.has(r.orbitalName) && ownPaths.has(r.from)) continue;
|
|
2569
|
-
if (ownNames.has(r.orbitalName) || organism !== void 0 && organisms.has(organism)) config2 = renameNavHrefs(config2, r.from, r.to);
|
|
2570
|
-
}
|
|
2571
|
-
return config2 === file.config ? file : { ...file, config: config2 };
|
|
2572
|
-
});
|
|
2573
|
-
const identity = dedupeComposedIdentity(orbitals);
|
|
2574
|
-
const ownedPages = collectOwnedPages(orbitals, options.importedOrbitalOf);
|
|
2575
|
-
const navItemsNarrowed = narrowNavItemsToOwnedPages(orbitals, ownedPages);
|
|
2576
|
-
let ledger = mergeLedgers([...renamedFiles]);
|
|
2577
|
-
if (ledger !== void 0) {
|
|
2578
|
-
for (const r of surfaceRenames.traits) {
|
|
2579
|
-
if (r.id !== void 0) ledger = ledgerRename(ledger, r.id, r.to, (/* @__PURE__ */ new Date()).toISOString());
|
|
2580
|
-
}
|
|
2581
|
-
}
|
|
2582
|
-
const hoistedNav = /* @__PURE__ */ new Map();
|
|
2583
|
-
for (let i = 0; i < orbitals.length; i += 1) {
|
|
2584
|
-
const orbital = orbitals[i];
|
|
2585
|
-
if (orbital.config === void 0) continue;
|
|
2586
|
-
const forwarded = collectOrbitalForwardedConfigKeys(orbital);
|
|
2587
|
-
const lifted = Object.entries(orbital.config).filter(([key, field]) => field.type === "[NavItem]" && forwarded.has(key));
|
|
2588
|
-
if (lifted.length === 0) continue;
|
|
2589
|
-
hoistedNav.set(orbital.name, Object.fromEntries(lifted));
|
|
2590
|
-
const kept = Object.fromEntries(Object.entries(orbital.config).filter(([key]) => !lifted.some(([k]) => k === key)));
|
|
2591
|
-
const { config: _dropped, ...rest } = orbital;
|
|
2592
|
-
orbitals[i] = Object.keys(kept).length > 0 ? { ...rest, config: kept } : rest;
|
|
2593
|
-
}
|
|
2594
|
-
const configSources = renamedFiles.flatMap((f) => [
|
|
2595
|
-
..."orbitals" in f ? [f] : [],
|
|
2596
|
-
...asDefinitions([f]).flatMap((o) => {
|
|
2597
|
-
const config2 = hoistedNav.get(o.name);
|
|
2598
|
-
return config2 === void 0 ? [] : [{ config: config2 }];
|
|
2599
|
-
})
|
|
2600
|
-
]);
|
|
2601
|
-
const unioned = unionOrganismConfigs(configSources);
|
|
2602
|
-
let config;
|
|
2603
|
-
let configNavItemsNarrowed = [];
|
|
2604
|
-
if (unioned !== void 0) {
|
|
2605
|
-
const narrowed = narrowConfigNavItems(unioned, ownedPages);
|
|
2606
|
-
config = narrowed.config;
|
|
2607
|
-
configNavItemsNarrowed = narrowed.drops;
|
|
2608
|
-
}
|
|
2609
|
-
let landingNavAdded = [];
|
|
2610
|
-
if (config !== void 0 && options.organismOf !== void 0) {
|
|
2611
|
-
const navDeclaringOrbitals = /* @__PURE__ */ new Set();
|
|
2612
|
-
for (const f of renamedFiles) {
|
|
2613
|
-
if (!("orbitals" in f) || f.config === void 0) continue;
|
|
2614
|
-
if (!Object.values(f.config).some((entry) => entry.type === "[NavItem]")) continue;
|
|
2615
|
-
for (const o of f.orbitals) navDeclaringOrbitals.add(o.name);
|
|
2616
|
-
}
|
|
2617
|
-
const linked = linkLandingPages(orbitals, config, options.organismOf, navDeclaringOrbitals, options.organismOrderOf);
|
|
2618
|
-
config = linked.config;
|
|
2619
|
-
landingNavAdded = linked.added;
|
|
2620
|
-
}
|
|
2621
|
-
return {
|
|
2622
|
-
orbitals,
|
|
2623
|
-
...config !== void 0 ? { config } : {},
|
|
2624
|
-
...ledger !== void 0 ? { ledger } : {},
|
|
2625
|
-
surfaceRenames,
|
|
2626
|
-
identity,
|
|
2627
|
-
navItemsNarrowed,
|
|
2628
|
-
configNavItemsNarrowed,
|
|
2629
|
-
landingNavAdded,
|
|
2630
|
-
organismRenames: namespaced.renames,
|
|
2631
|
-
unrenamableCollisions: namespaced.unrenamable
|
|
2632
|
-
};
|
|
2633
|
-
}
|
|
2634
|
-
function withUpstreamOsGrants(files, importedOrbitalOf) {
|
|
2635
|
-
const granted = (orbital) => {
|
|
2636
|
-
const upstream = orbital.reference === void 0 ? void 0 : importedOrbitalOf?.(orbital);
|
|
2637
|
-
return upstream?.osGrants === void 0 ? orbital : { ...orbital, osGrants: unionOsGrants(orbital.osGrants, upstream.osGrants) };
|
|
2638
|
-
};
|
|
2639
|
-
return files.map((file) => "orbitals" in file ? { ...file, orbitals: file.orbitals.map(granted) } : granted(file));
|
|
2640
|
-
}
|
|
2641
|
-
function declaredReach(files, importedProgramOf) {
|
|
2642
|
-
const inbound = [];
|
|
2643
|
-
const egress = [];
|
|
2644
|
-
const add = (into, items) => {
|
|
2645
|
-
for (const item of items ?? []) if (!into.includes(item)) into.push(item);
|
|
2646
|
-
};
|
|
2647
|
-
for (const file of files) {
|
|
2648
|
-
if (!("orbitals" in file)) continue;
|
|
2649
|
-
add(inbound, file.inbound);
|
|
2650
|
-
add(egress, file.egress);
|
|
2651
|
-
for (const orbital of file.orbitals) {
|
|
2652
|
-
const upstream = importedProgramOf?.(orbital);
|
|
2653
|
-
add(inbound, upstream?.inbound);
|
|
2654
|
-
add(egress, upstream?.egress);
|
|
2655
|
-
}
|
|
2656
|
-
}
|
|
2657
|
-
return { inbound, egress };
|
|
2658
|
-
}
|
|
2659
|
-
function composeAppFromFiles(inputs, options) {
|
|
2660
|
-
const files = withUpstreamOsGrants(inputs, options.importedOrbitalOf);
|
|
2661
|
-
const { orbitals, config, ledger, ...outcomes } = composeOrbitalSurface(files, {
|
|
2662
|
-
...options.organismOf !== void 0 ? { organismOf: options.organismOf } : {},
|
|
2663
|
-
...options.atomTraitOf !== void 0 ? { atomTraitOf: options.atomTraitOf } : {},
|
|
2664
|
-
...options.importedOrbitalOf !== void 0 ? { importedOrbitalOf: options.importedOrbitalOf } : {},
|
|
2665
|
-
...options.organismOrderOf !== void 0 ? { organismOrderOf: options.organismOrderOf } : {}
|
|
2666
|
-
});
|
|
2667
|
-
const result = composeBehaviors({
|
|
2668
|
-
appName: options.appName,
|
|
2669
|
-
orbitals,
|
|
2670
|
-
...options.layoutStrategy !== void 0 ? { layoutStrategy: options.layoutStrategy } : {},
|
|
2671
|
-
...options.eventWiring !== void 0 ? { eventWiring: options.eventWiring } : {}
|
|
2672
|
-
});
|
|
2673
|
-
const reach = declaredReach(files, options.importedProgramOf);
|
|
2674
|
-
return {
|
|
2675
|
-
schema: {
|
|
2676
|
-
...result.schema,
|
|
2677
|
-
...ledger !== void 0 ? { ledger } : {},
|
|
2678
|
-
...config !== void 0 ? { config } : {},
|
|
2679
|
-
...reach.inbound.length > 0 ? { inbound: reach.inbound } : {},
|
|
2680
|
-
...reach.egress.length > 0 ? { egress: reach.egress } : {}
|
|
2681
|
-
},
|
|
2682
|
-
layout: result.layout,
|
|
2683
|
-
wiring: result.wiring,
|
|
2684
|
-
...outcomes
|
|
2685
|
-
};
|
|
2686
|
-
}
|
|
2687
|
-
|
|
2688
|
-
// src/builders/layout-trait.ts
|
|
2689
|
-
function makeSlot(traitName) {
|
|
2690
|
-
return `@trait.${traitName}`;
|
|
2691
|
-
}
|
|
2692
|
-
function makeRenderUI(slot, root) {
|
|
2693
|
-
if (root === null) return ["render-ui", slot, null];
|
|
2694
|
-
if (typeof root === "string") return ["render-ui", slot, root];
|
|
2695
|
-
return ["render-ui", slot, root];
|
|
2696
|
-
}
|
|
2697
|
-
function makeLayoutTrait(opts) {
|
|
2698
|
-
const slot = opts.slot ?? "main";
|
|
2699
|
-
const effects = [];
|
|
2700
|
-
const emits = [];
|
|
2701
|
-
const eventDefs = [
|
|
2702
|
-
{ key: "INIT", name: "Initialize" }
|
|
2703
|
-
];
|
|
2704
|
-
if (opts.fetchEntity) {
|
|
2705
|
-
if (!opts.loadedEvent || !opts.loadFailedEvent) {
|
|
2706
|
-
throw new Error(
|
|
2707
|
-
`makeLayoutTrait: fetchEntity '${opts.fetchEntity}' set but loadedEvent / loadFailedEvent are required`
|
|
2708
|
-
);
|
|
2709
|
-
}
|
|
2710
|
-
const payloadSchema = opts.loadedPayloadSchema ?? [{ name: "data", type: `[${opts.fetchEntity}]` }];
|
|
2711
|
-
emits.push(
|
|
2712
|
-
{ event: opts.loadedEvent, scope: "internal", payloadSchema },
|
|
2713
|
-
{
|
|
2714
|
-
event: opts.loadFailedEvent,
|
|
2715
|
-
scope: "internal",
|
|
2716
|
-
payloadSchema: [
|
|
2717
|
-
{ name: "error", type: "string" },
|
|
2718
|
-
{ name: "code", type: "string" }
|
|
2719
|
-
]
|
|
2720
|
-
}
|
|
2721
|
-
);
|
|
2722
|
-
eventDefs.push(
|
|
2723
|
-
{ key: opts.loadedEvent, name: `${opts.fetchEntity} loaded`, payloadSchema },
|
|
2724
|
-
{
|
|
2725
|
-
key: opts.loadFailedEvent,
|
|
2726
|
-
name: `${opts.fetchEntity} load failed`,
|
|
2727
|
-
payloadSchema: [
|
|
2728
|
-
{ name: "error", type: "string" },
|
|
2729
|
-
{ name: "code", type: "string" }
|
|
2730
|
-
]
|
|
2731
|
-
}
|
|
2732
|
-
);
|
|
2733
|
-
const fetchFx = [
|
|
2734
|
-
"fetch",
|
|
2735
|
-
opts.fetchEntity,
|
|
2736
|
-
{ emit: { success: opts.loadedEvent, failure: opts.loadFailedEvent } }
|
|
2737
|
-
];
|
|
2738
|
-
effects.push(fetchFx);
|
|
2739
|
-
}
|
|
2740
|
-
effects.push(makeRenderUI(slot, opts.renderUI));
|
|
2741
|
-
if (opts.extraEffects && opts.extraEffects.length > 0) {
|
|
2742
|
-
effects.push(...opts.extraEffects);
|
|
2743
|
-
}
|
|
2744
|
-
const trait = {
|
|
2745
|
-
name: opts.name,
|
|
2746
|
-
...opts.description ? { description: opts.description } : {},
|
|
2747
|
-
linkedEntity: opts.linkedEntity,
|
|
2748
|
-
...emits.length > 0 ? { emits } : {},
|
|
2749
|
-
stateMachine: {
|
|
2750
|
-
states: [{ name: "composing", isInitial: true }],
|
|
2751
|
-
events: eventDefs,
|
|
2752
|
-
transitions: [
|
|
2753
|
-
{
|
|
2754
|
-
from: "composing",
|
|
2755
|
-
to: "composing",
|
|
2756
|
-
event: "INIT",
|
|
2757
|
-
effects
|
|
2758
|
-
}
|
|
2759
|
-
]
|
|
2760
|
-
}
|
|
2761
|
-
};
|
|
2762
|
-
return trait;
|
|
2763
|
-
}
|
|
2764
|
-
|
|
2765
|
-
// src/builders.ts
|
|
2766
|
-
function ensureIdField(fields) {
|
|
2767
|
-
if (!fields || fields.length === 0) return [{ name: "id", type: "string", required: true }];
|
|
2768
|
-
if (fields.some((f) => f.name === "id")) return fields;
|
|
2769
|
-
return [{ name: "id", type: "string", required: true }, ...fields];
|
|
2770
|
-
}
|
|
2771
|
-
function plural(name) {
|
|
2772
|
-
return name + "s";
|
|
2773
|
-
}
|
|
2774
|
-
function resolveEntityNameForBuilder(ref) {
|
|
2775
|
-
if (isEntityReference(ref)) {
|
|
2776
|
-
return parseEntityRef(ref)?.alias ?? ref;
|
|
2777
|
-
}
|
|
2778
|
-
if (isEntityCall(ref)) {
|
|
2779
|
-
if (ref.name) return ref.name;
|
|
2780
|
-
return parseEntityRef(ref.extends)?.alias ?? ref.extends;
|
|
2781
|
-
}
|
|
2782
|
-
return ref.name;
|
|
2783
|
-
}
|
|
2784
|
-
function makeEntity(opts) {
|
|
2785
|
-
const fields = ensureIdField(opts.fields);
|
|
2786
|
-
const persistence = opts.persistence ?? "runtime";
|
|
2787
|
-
return {
|
|
2788
|
-
name: opts.name,
|
|
2789
|
-
persistence,
|
|
2790
|
-
...persistence === "persistent" ? { collection: opts.collection ?? plural(opts.name).toLowerCase() } : {},
|
|
2791
|
-
fields,
|
|
2792
|
-
...opts.instances && opts.instances.length > 0 ? { instances: opts.instances } : {}
|
|
2793
|
-
};
|
|
2794
|
-
}
|
|
2795
|
-
function makePage(opts) {
|
|
2796
|
-
return {
|
|
2797
|
-
name: opts.name,
|
|
2798
|
-
path: opts.path,
|
|
2799
|
-
...opts.isInitial ? { isInitial: true } : {},
|
|
2800
|
-
traits: [{ ref: opts.traitName }]
|
|
2801
|
-
};
|
|
2802
|
-
}
|
|
2803
|
-
function makeOrbital(name, entity, traits, pages) {
|
|
2804
|
-
return { name, entity, traits, pages };
|
|
2805
|
-
}
|
|
2806
|
-
function makeTraitRef(opts) {
|
|
2807
|
-
const ref = { ref: opts.ref };
|
|
2808
|
-
if (opts.from !== void 0) ref.from = opts.from;
|
|
2809
|
-
if (opts.name !== void 0) ref.name = opts.name;
|
|
2810
|
-
if (opts.linkedEntity !== void 0) ref.linkedEntity = opts.linkedEntity;
|
|
2811
|
-
if (opts.linkedEntityId !== void 0) ref.linkedEntityId = opts.linkedEntityId;
|
|
2812
|
-
if (opts.events !== void 0) ref.events = opts.events;
|
|
2813
|
-
if (opts.typeArgs !== void 0) ref.typeArgs = opts.typeArgs;
|
|
2814
|
-
if (opts.fields !== void 0) ref.fields = opts.fields;
|
|
2815
|
-
if (opts.effects !== void 0) ref.effects = opts.effects;
|
|
2816
|
-
if (opts.listens !== void 0) ref.listens = opts.listens;
|
|
2817
|
-
if (opts.emitsScope !== void 0) ref.emitsScope = opts.emitsScope;
|
|
2818
|
-
if (opts.config !== void 0) ref.config = opts.config;
|
|
2819
|
-
return ref;
|
|
2820
|
-
}
|
|
2821
|
-
function makePageRef(opts) {
|
|
2822
|
-
const ref = { ref: opts.ref };
|
|
2823
|
-
if (opts.from !== void 0) ref.from = opts.from;
|
|
2824
|
-
if (opts.path !== void 0) ref.path = opts.path;
|
|
2825
|
-
if (opts.linkedEntity !== void 0) ref.linkedEntity = opts.linkedEntity;
|
|
2826
|
-
if (opts.traits !== void 0) ref.traits = opts.traits;
|
|
2827
|
-
return ref;
|
|
2828
|
-
}
|
|
2829
|
-
function makeOrbitalWithUses(opts) {
|
|
2830
|
-
const orbital = {
|
|
2831
|
-
name: opts.name,
|
|
2832
|
-
uses: opts.uses,
|
|
2833
|
-
...opts.expects !== void 0 ? { expects: opts.expects } : {},
|
|
2834
|
-
entity: opts.entity,
|
|
2835
|
-
...opts.auxiliaryEntities !== void 0 ? { auxiliaryEntities: opts.auxiliaryEntities } : {},
|
|
2836
|
-
traits: opts.traits,
|
|
2837
|
-
pages: opts.pages ?? [],
|
|
2838
|
-
...opts.config !== void 0 ? { config: opts.config } : {}
|
|
2839
|
-
};
|
|
2840
|
-
return orbital;
|
|
2841
|
-
}
|
|
2842
|
-
var ORBITAL_VALUE_IMPORT_ALIAS = "Source";
|
|
2843
|
-
function orbitalImportFromValue(value) {
|
|
2844
|
-
const { behavior, orbital, name, app, config, traits, uses, siblings, ...body } = value;
|
|
2845
|
-
const ref = `${ORBITAL_VALUE_IMPORT_ALIAS}.orbitals.${orbital}`;
|
|
2846
|
-
const clash = (uses ?? []).find((u) => u.as === ORBITAL_VALUE_IMPORT_ALIAS);
|
|
2847
|
-
if (clash !== void 0) {
|
|
2848
|
-
throw new Error(`orbital value ${orbital}: an import aliased '${ORBITAL_VALUE_IMPORT_ALIAS}' (from ${clash.from}) collides with the value's own source alias`);
|
|
2849
|
-
}
|
|
2850
|
-
const traitOverrides = traits === void 0 ? void 0 : Object.fromEntries(
|
|
2851
|
-
Object.entries(traits).map(([trait, overrides]) => {
|
|
2852
|
-
const { config: traitConfig, ...rest } = overrides;
|
|
2853
|
-
return [trait, { ...rest, ...traitConfig !== void 0 ? { config: mergeCallSiteConfigOverrides({}, traitConfig) } : {} }];
|
|
2854
|
-
})
|
|
2855
|
-
);
|
|
2856
|
-
return {
|
|
2857
|
-
name: name ?? orbital,
|
|
2858
|
-
uses: [{ from: behavior, as: ORBITAL_VALUE_IMPORT_ALIAS, ...app !== void 0 ? { config: mergeCallSiteConfigOverrides({}, app) } : {} }, ...uses ?? []],
|
|
2859
|
-
entity: `${ref}.entity`,
|
|
2860
|
-
traits: (siblings ?? []).map((sibling) => ({
|
|
2861
|
-
name: sibling.name,
|
|
2862
|
-
ref: sibling.ref,
|
|
2863
|
-
...sibling.linkedEntity !== void 0 ? { linkedEntity: sibling.linkedEntity } : {},
|
|
2864
|
-
...sibling.config !== void 0 ? { config: mergeCallSiteConfigOverrides({}, sibling.config) } : {}
|
|
2865
|
-
})),
|
|
2866
|
-
pages: [],
|
|
2867
|
-
reference: {
|
|
2868
|
-
ref,
|
|
2869
|
-
...body,
|
|
2870
|
-
...config !== void 0 ? { config: mergeCallSiteConfigOverrides({}, config) } : {},
|
|
2871
|
-
...traitOverrides !== void 0 ? { traits: traitOverrides } : {}
|
|
2872
|
-
}
|
|
2873
|
-
};
|
|
2874
|
-
}
|
|
2875
|
-
function parseProgram(data) {
|
|
2876
|
-
if (data === null || typeof data !== "object" || Array.isArray(data) || !("orbitals" in data) || !Array.isArray(data.orbitals)) {
|
|
2877
|
-
return parseOrbitalSchema(data);
|
|
2878
|
-
}
|
|
2879
|
-
return parseOrbitalSchema({
|
|
2880
|
-
...data,
|
|
2881
|
-
orbitals: data.orbitals.map((entry) => isOrbitalValue(entry) ? orbitalImportFromValue(OrbitalValueSchema.parse(entry)) : entry)
|
|
2882
|
-
});
|
|
2883
|
-
}
|
|
2884
|
-
function makeAtomOrbital(opts) {
|
|
2885
|
-
const traitRef = makeTraitRef({
|
|
2886
|
-
from: opts.atomPath,
|
|
2887
|
-
ref: opts.traitRef,
|
|
2888
|
-
linkedEntity: opts.entity.name,
|
|
2889
|
-
...opts.traitOverrides?.name !== void 0 ? { name: opts.traitOverrides.name } : {},
|
|
2890
|
-
...opts.traitOverrides?.events !== void 0 ? { events: opts.traitOverrides.events } : {},
|
|
2891
|
-
...opts.traitOverrides?.effects !== void 0 ? { effects: opts.traitOverrides.effects } : {},
|
|
2892
|
-
...opts.traitOverrides?.listens !== void 0 ? { listens: opts.traitOverrides.listens } : {},
|
|
2893
|
-
...opts.traitOverrides?.emitsScope !== void 0 ? { emitsScope: opts.traitOverrides.emitsScope } : {},
|
|
2894
|
-
...opts.traitOverrides?.config !== void 0 ? { config: opts.traitOverrides.config } : {}
|
|
2895
|
-
});
|
|
2896
|
-
const pages = opts.pageRef ? [
|
|
2897
|
-
makePageRef({
|
|
2898
|
-
from: opts.atomPath,
|
|
2899
|
-
ref: opts.pageRef,
|
|
2900
|
-
linkedEntity: opts.entity.name,
|
|
2901
|
-
...opts.pageOverrides?.path !== void 0 ? { path: opts.pageOverrides.path } : {}
|
|
2902
|
-
})
|
|
2903
|
-
] : void 0;
|
|
2904
|
-
return makeOrbitalWithUses({
|
|
2905
|
-
name: opts.name,
|
|
2906
|
-
uses: [{ from: opts.atomPath, as: opts.alias }],
|
|
2907
|
-
entity: opts.entity,
|
|
2908
|
-
traits: [traitRef],
|
|
2909
|
-
...pages !== void 0 ? { pages } : {}
|
|
2910
|
-
});
|
|
2911
|
-
}
|
|
2912
|
-
function makeSchema(name, ...definitions) {
|
|
2913
|
-
return { name, version: "1.0.0", orbitals: definitions };
|
|
2914
|
-
}
|
|
2915
|
-
function asDefinitions2(inputs) {
|
|
2916
|
-
return inputs.flatMap((input) => {
|
|
2917
|
-
if ("orbitals" in input && Array.isArray(input.orbitals)) {
|
|
2918
|
-
return input.orbitals;
|
|
2919
|
-
}
|
|
2920
|
-
return [input];
|
|
2921
|
-
});
|
|
2922
|
-
}
|
|
2923
|
-
function asDefinition(input) {
|
|
2924
|
-
if ("orbitals" in input && Array.isArray(input.orbitals)) {
|
|
2925
|
-
return input.orbitals[0];
|
|
2926
|
-
}
|
|
2927
|
-
return input;
|
|
2928
|
-
}
|
|
2929
|
-
function mergeOrbitals(name, entity, sources, pages) {
|
|
2930
|
-
const allTraits = sources.flatMap(
|
|
2931
|
-
(s) => s.traits.map((t) => structuredClone(t))
|
|
2932
|
-
);
|
|
2933
|
-
return { name, entity, traits: allTraits, pages };
|
|
2934
|
-
}
|
|
2935
|
-
function wire(source, target, event, triggers) {
|
|
2936
|
-
const s = structuredClone(source);
|
|
2937
|
-
const t = structuredClone(target);
|
|
2938
|
-
s.emits = [...s.emits ?? [], { ...event, scope: event.scope ?? "internal" }];
|
|
2939
|
-
t.listens = [...t.listens ?? [], {
|
|
2940
|
-
event: event.event,
|
|
2941
|
-
triggers,
|
|
2942
|
-
scope: "internal"
|
|
2943
|
-
}];
|
|
2944
|
-
return [s, t];
|
|
2945
|
-
}
|
|
2946
|
-
function extractTrait(input) {
|
|
2947
|
-
const orbital = asDefinition(input);
|
|
2948
|
-
return structuredClone(orbital.traits[0]);
|
|
2949
|
-
}
|
|
2950
|
-
function connect(a, b, event, triggers) {
|
|
2951
|
-
const aClone = structuredClone(asDefinition(a));
|
|
2952
|
-
const bClone = structuredClone(asDefinition(b));
|
|
2953
|
-
const aTrait = aClone.traits[0];
|
|
2954
|
-
if (aTrait) {
|
|
2955
|
-
const emitContract = {
|
|
2956
|
-
...event,
|
|
2957
|
-
scope: event.scope ?? "external"
|
|
2958
|
-
};
|
|
2959
|
-
aTrait.emits = [...aTrait.emits ?? [], emitContract];
|
|
2960
|
-
}
|
|
2961
|
-
const bTrait = bClone.traits[0];
|
|
2962
|
-
if (bTrait) {
|
|
2963
|
-
const listener = {
|
|
2964
|
-
event: event.event,
|
|
2965
|
-
triggers: triggers ?? "INIT",
|
|
2966
|
-
scope: "external"
|
|
2967
|
-
};
|
|
2968
|
-
bTrait.listens = [...bTrait.listens ?? [], listener];
|
|
2969
|
-
}
|
|
2970
|
-
return [aClone, bClone];
|
|
2971
|
-
}
|
|
2972
|
-
function compose(orbitals, pages, connections, appName) {
|
|
2973
|
-
const cloned = structuredClone(asDefinitions2(orbitals));
|
|
2974
|
-
for (const conn of connections) {
|
|
2975
|
-
const emitter = cloned.find((o) => {
|
|
2976
|
-
const traits = o.traits;
|
|
2977
|
-
return traits.some((t) => t.name === conn.from);
|
|
2978
|
-
});
|
|
2979
|
-
const listener = cloned.find((o) => {
|
|
2980
|
-
const traits = o.traits;
|
|
2981
|
-
return traits.some((t) => t.name === conn.to);
|
|
2982
|
-
});
|
|
2983
|
-
if (emitter && listener) {
|
|
2984
|
-
const eTrait = emitter.traits.find((t) => t.name === conn.from);
|
|
2985
|
-
const lTrait = listener.traits.find((t) => t.name === conn.to);
|
|
2986
|
-
if (eTrait) {
|
|
2987
|
-
const emitContract = { ...conn.event, scope: conn.event.scope ?? "external" };
|
|
2988
|
-
eTrait.emits = [...eTrait.emits ?? [], emitContract];
|
|
2989
|
-
}
|
|
2990
|
-
if (lTrait) {
|
|
2991
|
-
const listenContract = {
|
|
2992
|
-
event: conn.event.event,
|
|
2993
|
-
triggers: conn.triggers ?? "INIT",
|
|
2994
|
-
scope: "external"
|
|
2995
|
-
};
|
|
2996
|
-
lTrait.listens = [...lTrait.listens ?? [], listenContract];
|
|
2997
|
-
}
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
for (const orbital of cloned) {
|
|
3001
|
-
const traitNames = orbital.traits.map((t) => t.name);
|
|
3002
|
-
const matchingPages = pages.filter(
|
|
3003
|
-
(p) => p.traits.some((t) => traitNames.includes(t))
|
|
3004
|
-
);
|
|
3005
|
-
orbital.pages = matchingPages.map((p) => ({
|
|
3006
|
-
name: p.name,
|
|
3007
|
-
path: p.path,
|
|
3008
|
-
...p.isInitial ? { isInitial: true } : {},
|
|
3009
|
-
traits: p.traits.filter((t) => traitNames.includes(t)).map((ref) => ({ ref }))
|
|
3010
|
-
}));
|
|
3011
|
-
}
|
|
3012
|
-
return {
|
|
3013
|
-
name: appName ?? "Application",
|
|
3014
|
-
version: "1.0.0",
|
|
3015
|
-
orbitals: cloned
|
|
3016
|
-
};
|
|
3017
|
-
}
|
|
3018
|
-
function pipe(orbitals, events, appName) {
|
|
3019
|
-
if (events.length !== orbitals.length - 1) {
|
|
3020
|
-
throw new Error(`pipe requires exactly ${orbitals.length - 1} events for ${orbitals.length} orbitals`);
|
|
3021
|
-
}
|
|
3022
|
-
const cloned = structuredClone(asDefinitions2(orbitals));
|
|
3023
|
-
for (let i = 0; i < events.length; i++) {
|
|
3024
|
-
const aTrait = cloned[i].traits[0];
|
|
3025
|
-
const bTrait = cloned[i + 1].traits[0];
|
|
3026
|
-
if (aTrait) {
|
|
3027
|
-
const emitContract = { ...events[i], scope: events[i].scope ?? "external" };
|
|
3028
|
-
aTrait.emits = [...aTrait.emits ?? [], emitContract];
|
|
3029
|
-
}
|
|
3030
|
-
if (bTrait) {
|
|
3031
|
-
const listener = {
|
|
3032
|
-
event: events[i].event,
|
|
3033
|
-
triggers: "INIT",
|
|
3034
|
-
scope: "external"
|
|
3035
|
-
};
|
|
3036
|
-
bTrait.listens = [...bTrait.listens ?? [], listener];
|
|
3037
|
-
}
|
|
3038
|
-
}
|
|
3039
|
-
const pages = cloned.map((o, i) => {
|
|
3040
|
-
const entityName = resolveEntityNameForBuilder(o.entity);
|
|
3041
|
-
const traitNames = o.traits.map((t) => t.name);
|
|
3042
|
-
return {
|
|
3043
|
-
name: `${entityName}Page`,
|
|
3044
|
-
path: `/${plural(entityName).toLowerCase()}`,
|
|
3045
|
-
...i === 0 ? { isInitial: true } : {},
|
|
3046
|
-
traits: traitNames.map((ref) => ({ ref }))
|
|
3047
|
-
};
|
|
3048
|
-
});
|
|
3049
|
-
for (let i = 0; i < cloned.length; i++) {
|
|
3050
|
-
cloned[i].pages = [pages[i]];
|
|
3051
|
-
}
|
|
3052
|
-
return {
|
|
3053
|
-
name: appName ?? "Application",
|
|
3054
|
-
version: "1.0.0",
|
|
3055
|
-
orbitals: cloned
|
|
3056
|
-
};
|
|
3057
|
-
}
|
|
3058
|
-
|
|
3059
|
-
export { ORBITAL_VALUE_IMPORT_ALIAS, applyDeclarationEntityRename, applyDeclarationTraitRenames, applyEventWiring, applyParamsToOrb, applyTraitConfigOverrides, asEntityObject, atomTraitResolver, collectCallsiteCaptureChildren, collectFieldComparisonLiterals, collectForwardedConfigKeys, collectOrbitalForwardedConfigKeys, collectOwnedSurface, collectOwnerComparedFields, collectOwnerStampedFields, collectTraitConfigRefAdjacency, collectTraitEmbedAdjacency, compose, composeAppFromFiles, composeBehaviors, composeOrbitalSurface, configForwardTokens, configReferencesCallsitePayload, connect, declaredEntityName, dedupeComposedIdentity, dedupeComposedSurface, deriveInputType, detectLayoutStrategy, ensureIdField, entityRenameBlockers, extractTrait, factoryCallPlanOrbitalName, filterConfigToForwardedKeys, findDanglingRefs, generateQuestions, healEntityLedgerRows, healTraitLedgerRows, humanizeKey, identityVocabularyDelta, makeAtomOrbital, makeEntity, makeLayoutTrait, makeOrbital, makeOrbitalWithUses, makePage, makePageRef, makeRenderUI, makeSchema, makeSlot, makeTraitRef, mergeExpectationShape, mergeLedgers, mergeOrbitals, navItemHref, orbitalEntityName, orbitalFileOf, orbitalImportFromValue, orbitalImportResolver, orbitalRouteSlug, orbitalTouchesOwnRecord, organismOrderResolver, parseProgram, pipe, plural, rebindInlineTraitEntity, renameEntity, renameEntityInSchema, renameOrbital, rewriteEntityInInlineTrait, rewriteTraitRefsInTree, traitDeclaresConfigForward, traitReferencesCallsitePayload, traitsEmbeddedByEffects, traitsEmbeddedByEvent, unionOrganismConfigs, validateOrbitalFactoryParams, wire };
|
|
3060
|
-
//# sourceMappingURL=chunk-6LR43Z5E.js.map
|
|
3061
|
-
//# sourceMappingURL=chunk-6LR43Z5E.js.map
|