@almadar/core 7.26.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builders.d.ts +3 -2
- package/dist/{compose-behaviors-CHAMivlZ.d.ts → compose-behaviors-Bq8tdeBU.d.ts} +1 -1
- package/dist/diff-factory-calls-DlBcMWPM.d.ts +648 -0
- package/dist/domain-language/index.d.ts +6 -647
- package/dist/factory/index.d.ts +105 -0
- package/dist/factory/index.js +484 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/index.d.ts +7 -4
- package/dist/{schema-BVni4uNf.d.ts → schema-Bg4qX43l.d.ts} +3 -5719
- package/dist/trait-BPe356_9.d.ts +5721 -0
- package/dist/types/index.d.ts +4 -2
- package/package.json +6 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { v as FactoryParamValue, p as DomainRuleOverlayEntry, N as RuleOverlay } from '../diff-factory-calls-DlBcMWPM.js';
|
|
2
|
+
export { C as CallSiteDiff, F as FactoryCallSite, s as FactoryCallSiteParams, t as FactoryEntitySignature, u as FactoryPageSignature, w as FactorySignature, x as FactorySignatureCatalog, y as FactorySignatureEntityField, z as FactoryTraitSignature, O as OwnershipOverlayEntry, K as PresentationNavItem, M as PresentationOverlay, S as SchemaFieldType, V as TraitOverlay, W as TraitOverlayEntry, X as TraitOverlayListener, Y as TranslationBinding, Z as TranslationResult, _ as TranslationWarning, a0 as diffFactoryCalls, a1 as translateDomainToParams, a1 as translateOverlaysToParams } from '../diff-factory-calls-DlBcMWPM.js';
|
|
3
|
+
import { B as EntityField, H as EntityPersistence, bz as TraitReference } from '../trait-BPe356_9.js';
|
|
4
|
+
import 'zod';
|
|
5
|
+
import '../expression-BVRFm0sV.js';
|
|
6
|
+
import '@almadar/patterns';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Mutation surface for the factory-call plan.
|
|
10
|
+
*
|
|
11
|
+
* Replaces the deleted `DomainMutation` + `applyMutation` reducer. The
|
|
12
|
+
* studio + questionnaire emit `FactoryCallPlanMutation[]` to express
|
|
13
|
+
* incremental edits to the agent's per-orbital params + cross-cutting
|
|
14
|
+
* overlays. The planner applies them via `applyFactoryCallPlanMutation`
|
|
15
|
+
* and re-projects to `FactoryCallSite[]`.
|
|
16
|
+
*
|
|
17
|
+
* Initial scope covers per-orbital config edits. Structural ops
|
|
18
|
+
* (add-orbital / remove-orbital / rename-orbital) ride the analysis
|
|
19
|
+
* surface directly via `analysis.orbitals` / `analysis.deletedOrbitals`
|
|
20
|
+
* / `analysis.renames`.
|
|
21
|
+
*
|
|
22
|
+
* @packageDocumentation
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* One slot the agent emits per orbital. Slim shape — agent-facing,
|
|
27
|
+
* carries only what factory dispatch needs. The studio renders forms
|
|
28
|
+
* over this; the projector turns it into a `FactoryCallSite`.
|
|
29
|
+
*/
|
|
30
|
+
interface OrbitalCallInput {
|
|
31
|
+
orbitalName: string;
|
|
32
|
+
organism?: string;
|
|
33
|
+
orbital?: string;
|
|
34
|
+
entityName?: string;
|
|
35
|
+
entityFields?: ReadonlyArray<EntityField>;
|
|
36
|
+
persistence?: EntityPersistence;
|
|
37
|
+
collection?: string;
|
|
38
|
+
pagePaths?: Readonly<Record<string, string>>;
|
|
39
|
+
traitOverlay?: Readonly<Record<string, {
|
|
40
|
+
config?: Readonly<Record<string, FactoryParamValue>>;
|
|
41
|
+
linkedEntity?: string;
|
|
42
|
+
name?: string;
|
|
43
|
+
}>>;
|
|
44
|
+
extraTraits?: ReadonlyArray<TraitReference>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Discriminated union of typed edits. Each variant carries only the
|
|
48
|
+
* payload pieces that change. The reducer is total over the union.
|
|
49
|
+
*/
|
|
50
|
+
type FactoryCallPlanMutation = {
|
|
51
|
+
kind: 'set-orbital-entity-fields';
|
|
52
|
+
orbitalName: string;
|
|
53
|
+
fields: ReadonlyArray<EntityField>;
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'set-orbital-entity-name';
|
|
56
|
+
orbitalName: string;
|
|
57
|
+
name: string;
|
|
58
|
+
} | {
|
|
59
|
+
kind: 'set-orbital-persistence';
|
|
60
|
+
orbitalName: string;
|
|
61
|
+
persistence: EntityPersistence;
|
|
62
|
+
} | {
|
|
63
|
+
kind: 'set-orbital-collection';
|
|
64
|
+
orbitalName: string;
|
|
65
|
+
collection: string;
|
|
66
|
+
} | {
|
|
67
|
+
kind: 'set-orbital-page-path';
|
|
68
|
+
orbitalName: string;
|
|
69
|
+
pageName: string;
|
|
70
|
+
path: string;
|
|
71
|
+
} | {
|
|
72
|
+
kind: 'set-trait-override-config';
|
|
73
|
+
orbitalName: string;
|
|
74
|
+
traitName: string;
|
|
75
|
+
key: string;
|
|
76
|
+
value: FactoryParamValue;
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'add-extra-trait';
|
|
79
|
+
orbitalName: string;
|
|
80
|
+
trait: TraitReference;
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'remove-extra-trait';
|
|
83
|
+
orbitalName: string;
|
|
84
|
+
ref: string;
|
|
85
|
+
} | {
|
|
86
|
+
kind: 'set-rule';
|
|
87
|
+
rule: DomainRuleOverlayEntry;
|
|
88
|
+
} | {
|
|
89
|
+
kind: 'remove-rule';
|
|
90
|
+
ruleId: string;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* State shape the reducer operates on. Mirrors the slice of the
|
|
94
|
+
* agent's analysis result that incremental edits target.
|
|
95
|
+
*/
|
|
96
|
+
interface FactoryCallPlanState {
|
|
97
|
+
orbitals: ReadonlyArray<OrbitalCallInput>;
|
|
98
|
+
ruleOverlay?: RuleOverlay;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Immutable reducer. Returns a new state; never mutates input.
|
|
102
|
+
*/
|
|
103
|
+
declare function applyFactoryCallPlanMutation(state: FactoryCallPlanState, m: FactoryCallPlanMutation): FactoryCallPlanState;
|
|
104
|
+
|
|
105
|
+
export { type FactoryCallPlanMutation, type FactoryCallPlanState, FactoryParamValue, type OrbitalCallInput, RuleOverlay, DomainRuleOverlayEntry as RuleOverlayEntry, applyFactoryCallPlanMutation };
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
// src/domain-language/types.ts
|
|
2
|
+
var DOMAIN_TO_SCHEMA_FIELD_TYPE = {
|
|
3
|
+
"text": "string",
|
|
4
|
+
"long text": "string",
|
|
5
|
+
"number": "number",
|
|
6
|
+
"currency": "number",
|
|
7
|
+
"yes/no": "boolean",
|
|
8
|
+
"date": "date",
|
|
9
|
+
"timestamp": "timestamp",
|
|
10
|
+
"datetime": "datetime",
|
|
11
|
+
"list": "array",
|
|
12
|
+
"object": "object",
|
|
13
|
+
"enum": "enum",
|
|
14
|
+
"relation": "relation"
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// src/domain-language/sync/translate-domain-to-params.ts
|
|
18
|
+
function translateDomainToParams(binding, signature, presentation, ruleOverlay, traitOverlay, catalog) {
|
|
19
|
+
const warnings = [];
|
|
20
|
+
const params = {};
|
|
21
|
+
applyEntityName(binding.entity, signature, params);
|
|
22
|
+
applyEntityFields(binding.entity, signature, params, warnings);
|
|
23
|
+
applyPersistence(binding.entity, signature, params, warnings);
|
|
24
|
+
applyCollection(binding.entity, params);
|
|
25
|
+
applyPagePaths(binding.pages ?? [], signature, params, warnings);
|
|
26
|
+
applyPresentation(presentation, signature, params, warnings);
|
|
27
|
+
applyTraitOverlay(traitOverlay, signature, params, warnings);
|
|
28
|
+
applyRuleOverlay(ruleOverlay, signature, binding, catalog, params, warnings);
|
|
29
|
+
return {
|
|
30
|
+
callSite: {
|
|
31
|
+
organism: signature.organism,
|
|
32
|
+
orbital: signature.orbital,
|
|
33
|
+
factoryPath: signature.factoryPath,
|
|
34
|
+
params
|
|
35
|
+
},
|
|
36
|
+
warnings
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function applyEntityName(entity, signature, params) {
|
|
40
|
+
if (signature.entities.length === 0) return;
|
|
41
|
+
if (entity.name === signature.entities[0].name) return;
|
|
42
|
+
params.entityName = entity.name;
|
|
43
|
+
}
|
|
44
|
+
function applyEntityFields(entity, signature, params, warnings) {
|
|
45
|
+
if (signature.entities.length === 0) {
|
|
46
|
+
if (entity.fields.length > 0) {
|
|
47
|
+
warnings.push({
|
|
48
|
+
field: `entity.${entity.name}.fields`,
|
|
49
|
+
reason: "factory signature does not advertise an entity surface"
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const canonical = new Set(signature.entities[0].fields.map((f) => f.name));
|
|
55
|
+
const extras = [];
|
|
56
|
+
for (const f of entity.fields) {
|
|
57
|
+
if (canonical.has(f.name)) continue;
|
|
58
|
+
const lowered = lowerField(f);
|
|
59
|
+
if (lowered) extras.push(lowered);
|
|
60
|
+
}
|
|
61
|
+
if (extras.length > 0) params.entityFields = extras;
|
|
62
|
+
}
|
|
63
|
+
function applyPersistence(entity, signature, params, warnings) {
|
|
64
|
+
if (!entity.persistence) return;
|
|
65
|
+
if (signature.entities.length === 0) {
|
|
66
|
+
warnings.push({
|
|
67
|
+
field: `entity.${entity.name}.persistence`,
|
|
68
|
+
reason: "factory signature has no entity to apply persistence to"
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (entity.persistence === signature.entities[0].persistence) return;
|
|
73
|
+
params.persistence = entity.persistence;
|
|
74
|
+
}
|
|
75
|
+
function applyCollection(entity, params) {
|
|
76
|
+
if (!entity.collection) return;
|
|
77
|
+
params.collection = entity.collection;
|
|
78
|
+
}
|
|
79
|
+
function applyPagePaths(pages, signature, params, warnings) {
|
|
80
|
+
if (pages.length === 0) return;
|
|
81
|
+
const sigPages = new Map(signature.pages.map((p) => [p.name, p]));
|
|
82
|
+
const overrides = {};
|
|
83
|
+
for (const p of pages) {
|
|
84
|
+
const sig = sigPages.get(p.name);
|
|
85
|
+
if (!sig) {
|
|
86
|
+
warnings.push({
|
|
87
|
+
field: `page.${p.name}.url`,
|
|
88
|
+
reason: `factory signature has no page named "${p.name}"`
|
|
89
|
+
});
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (sig.defaultPath !== p.url) overrides[p.name] = p.url;
|
|
93
|
+
}
|
|
94
|
+
if (Object.keys(overrides).length > 0) params.pagePaths = overrides;
|
|
95
|
+
}
|
|
96
|
+
function applyPresentation(overlay, signature, params, warnings) {
|
|
97
|
+
if (!overlay?.navAdditions || overlay.navAdditions.length === 0) return;
|
|
98
|
+
const target = signature.traits.find(
|
|
99
|
+
(t) => t.overridableConfigKeys.includes("navItems")
|
|
100
|
+
);
|
|
101
|
+
if (!target) {
|
|
102
|
+
warnings.push({
|
|
103
|
+
field: "presentation.navAdditions",
|
|
104
|
+
reason: "factory signature has no trait advertising a `navItems` config key"
|
|
105
|
+
});
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const existing = params.traitOverrides?.[target.name] ?? {};
|
|
109
|
+
const existingConfig = existing.config ?? {};
|
|
110
|
+
const items = overlay.navAdditions.map(
|
|
111
|
+
navItemToParamValue
|
|
112
|
+
);
|
|
113
|
+
params.traitOverrides = {
|
|
114
|
+
...params.traitOverrides,
|
|
115
|
+
[target.name]: {
|
|
116
|
+
...existing,
|
|
117
|
+
config: { ...existingConfig, navItems: items }
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function applyTraitOverlay(overlay, signature, params, warnings) {
|
|
122
|
+
if (!overlay) return;
|
|
123
|
+
const traitsByName = new Map(signature.traits.map((t) => [t.name, t]));
|
|
124
|
+
for (const [traitName, entry] of Object.entries(overlay)) {
|
|
125
|
+
const trait = traitsByName.get(traitName);
|
|
126
|
+
if (!trait) {
|
|
127
|
+
warnings.push({
|
|
128
|
+
field: `traitOverlay.${traitName}`,
|
|
129
|
+
reason: `factory signature has no trait named "${traitName}"`
|
|
130
|
+
});
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
mergeTraitOverride(traitName, entry, trait, params, warnings);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function mergeTraitOverride(traitName, entry, trait, params, warnings) {
|
|
137
|
+
const advertised = new Set(trait.overridableConfigKeys);
|
|
138
|
+
const existing = params.traitOverrides?.[traitName] ?? {};
|
|
139
|
+
const existingConfig = existing.config ?? {};
|
|
140
|
+
const mergedConfig = { ...existingConfig };
|
|
141
|
+
if (entry.config) {
|
|
142
|
+
for (const [k, v] of Object.entries(entry.config)) {
|
|
143
|
+
if (!advertised.has(k)) {
|
|
144
|
+
warnings.push({
|
|
145
|
+
field: `traitOverlay.${traitName}.config.${k}`,
|
|
146
|
+
reason: `trait does not advertise config key "${k}" (overridableConfigKeys: [${trait.overridableConfigKeys.join(", ")}])`
|
|
147
|
+
});
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
mergedConfig[k] = v;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const next = {
|
|
154
|
+
...existing,
|
|
155
|
+
...Object.keys(mergedConfig).length > 0 ? { config: mergedConfig } : {}
|
|
156
|
+
};
|
|
157
|
+
params.traitOverrides = {
|
|
158
|
+
...params.traitOverrides,
|
|
159
|
+
[traitName]: next
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function applyRuleOverlay(overlay, signature, binding, catalog, params, warnings) {
|
|
163
|
+
if (!overlay) return;
|
|
164
|
+
for (const rule of overlay.rules) {
|
|
165
|
+
if (!ruleAppliesToBinding(rule, binding)) continue;
|
|
166
|
+
if (!catalog) {
|
|
167
|
+
warnings.push({
|
|
168
|
+
field: `ruleOverlay.rules.${rule.id}`,
|
|
169
|
+
reason: "rule overlay supplied without a catalog \u2014 capability lookup requires one"
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const match = findTraitByCapability(catalog, rule.capability);
|
|
174
|
+
if (!match) {
|
|
175
|
+
warnings.push({
|
|
176
|
+
field: `ruleOverlay.rules.${rule.id}`,
|
|
177
|
+
reason: `no trait in the catalog advertises capability "${rule.capability}"`
|
|
178
|
+
});
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
appendRuleExtraTrait(rule, match, binding, params);
|
|
182
|
+
if (rule.config) {
|
|
183
|
+
threadRuleConfig(rule, match.trait, params, warnings);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (overlay.ownership) {
|
|
187
|
+
for (const entry of overlay.ownership) {
|
|
188
|
+
if (entry.entity !== binding.entity.name) continue;
|
|
189
|
+
applyOwnership(entry, params, signature, catalog, warnings);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function ruleAppliesToBinding(rule, binding) {
|
|
194
|
+
if (rule.appliesTo.length === 0) return true;
|
|
195
|
+
return rule.appliesTo.includes(binding.entity.name);
|
|
196
|
+
}
|
|
197
|
+
function findTraitByCapability(catalog, capability) {
|
|
198
|
+
for (const sig of catalog) {
|
|
199
|
+
for (const trait of sig.traits) {
|
|
200
|
+
if (trait.capabilities.includes(capability)) {
|
|
201
|
+
return { signature: sig, trait };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return void 0;
|
|
206
|
+
}
|
|
207
|
+
function appendRuleExtraTrait(rule, match, binding, params) {
|
|
208
|
+
const fromPath = `std/behaviors/${match.signature.organism}`;
|
|
209
|
+
const alias = organismToAlias(match.signature.organism);
|
|
210
|
+
const ref = {
|
|
211
|
+
from: fromPath,
|
|
212
|
+
ref: `${alias}.traits.${match.trait.name}`,
|
|
213
|
+
linkedEntity: binding.entity.name
|
|
214
|
+
};
|
|
215
|
+
const existing = params.extraTraits ?? [];
|
|
216
|
+
params.extraTraits = [...existing, ref];
|
|
217
|
+
}
|
|
218
|
+
function organismToAlias(organism) {
|
|
219
|
+
const trimmed = organism.startsWith("std-") ? organism.slice(4) : organism;
|
|
220
|
+
return trimmed.split("-").filter((s) => s.length > 0).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
221
|
+
}
|
|
222
|
+
function threadRuleConfig(rule, trait, params, warnings) {
|
|
223
|
+
if (!rule.config) return;
|
|
224
|
+
const advertised = new Set(trait.overridableConfigKeys);
|
|
225
|
+
const existing = params.traitOverrides?.[trait.name] ?? {};
|
|
226
|
+
const existingConfig = existing.config ?? {};
|
|
227
|
+
const merged = { ...existingConfig };
|
|
228
|
+
for (const [k, v] of Object.entries(rule.config)) {
|
|
229
|
+
if (!advertised.has(k)) {
|
|
230
|
+
warnings.push({
|
|
231
|
+
field: `ruleOverlay.rules.${rule.id}.config.${k}`,
|
|
232
|
+
reason: `trait "${trait.name}" does not advertise config key "${k}"`
|
|
233
|
+
});
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
merged[k] = v;
|
|
237
|
+
}
|
|
238
|
+
if (Object.keys(merged).length > 0) {
|
|
239
|
+
params.traitOverrides = {
|
|
240
|
+
...params.traitOverrides,
|
|
241
|
+
[trait.name]: { ...existing, config: merged }
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function applyOwnership(entry, params, signature, catalog, warnings) {
|
|
246
|
+
const local = signature.traits.find(
|
|
247
|
+
(t) => t.overridableConfigKeys.includes("ownerField")
|
|
248
|
+
);
|
|
249
|
+
if (local) {
|
|
250
|
+
writeOwnerField(local.name, entry.ownerField, params);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (catalog) {
|
|
254
|
+
for (const sig of catalog) {
|
|
255
|
+
const trait = sig.traits.find(
|
|
256
|
+
(t) => t.overridableConfigKeys.includes("ownerField")
|
|
257
|
+
);
|
|
258
|
+
if (trait) {
|
|
259
|
+
writeOwnerField(trait.name, entry.ownerField, params);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
warnings.push({
|
|
265
|
+
field: `ruleOverlay.ownership.${entry.entity}`,
|
|
266
|
+
reason: "no trait in the bound signature or catalog advertises an `ownerField` config knob"
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
function writeOwnerField(traitName, ownerField, params) {
|
|
270
|
+
const existing = params.traitOverrides?.[traitName] ?? {};
|
|
271
|
+
const existingConfig = existing.config ?? {};
|
|
272
|
+
params.traitOverrides = {
|
|
273
|
+
...params.traitOverrides,
|
|
274
|
+
[traitName]: {
|
|
275
|
+
...existing,
|
|
276
|
+
config: { ...existingConfig, ownerField }
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function lowerField(f) {
|
|
281
|
+
const schemaType = DOMAIN_TO_SCHEMA_FIELD_TYPE[f.fieldType];
|
|
282
|
+
if (!schemaType) return void 0;
|
|
283
|
+
const out = {
|
|
284
|
+
name: f.name,
|
|
285
|
+
type: schemaType
|
|
286
|
+
};
|
|
287
|
+
if (f.required === true) out.required = true;
|
|
288
|
+
if (f.enumValues && f.enumValues.length > 0) out.values = [...f.enumValues];
|
|
289
|
+
if (f.default !== void 0) out.default = lowerDefault(f.default);
|
|
290
|
+
if (f.items) {
|
|
291
|
+
const itemSchema = DOMAIN_TO_SCHEMA_FIELD_TYPE[f.items.type];
|
|
292
|
+
if (itemSchema) out.items = { type: itemSchema };
|
|
293
|
+
}
|
|
294
|
+
return out;
|
|
295
|
+
}
|
|
296
|
+
function lowerDefault(d) {
|
|
297
|
+
if (d === void 0 || d === null) return d;
|
|
298
|
+
if (typeof d === "string" || typeof d === "number" || typeof d === "boolean") {
|
|
299
|
+
return d;
|
|
300
|
+
}
|
|
301
|
+
if (Array.isArray(d)) {
|
|
302
|
+
return d.map(lowerDefault);
|
|
303
|
+
}
|
|
304
|
+
if (typeof d === "object") {
|
|
305
|
+
const out = {};
|
|
306
|
+
for (const [k, v] of Object.entries(d)) out[k] = lowerDefault(v);
|
|
307
|
+
return out;
|
|
308
|
+
}
|
|
309
|
+
return void 0;
|
|
310
|
+
}
|
|
311
|
+
function navItemToParamValue(item) {
|
|
312
|
+
const out = {
|
|
313
|
+
label: item.label,
|
|
314
|
+
path: item.path
|
|
315
|
+
};
|
|
316
|
+
if (item.icon) out.icon = item.icon;
|
|
317
|
+
return out;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/domain-language/sync/diff-factory-calls.ts
|
|
321
|
+
function diffFactoryCalls(prior, next) {
|
|
322
|
+
const out = [];
|
|
323
|
+
const priorByKey = new Map(prior.map((c) => [callKey(c), c]));
|
|
324
|
+
const nextByKey = new Map(next.map((c) => [callKey(c), c]));
|
|
325
|
+
for (const [key, p] of priorByKey) {
|
|
326
|
+
const n = nextByKey.get(key);
|
|
327
|
+
if (!n) {
|
|
328
|
+
out.push({ kind: "delete", orbitalName: p.orbital, prior: p });
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
if (paramsEqual(p.params, n.params)) {
|
|
332
|
+
out.push({ kind: "keep", orbitalName: p.orbital, call: n });
|
|
333
|
+
} else {
|
|
334
|
+
out.push({ kind: "edit", orbitalName: p.orbital, prior: p, next: n });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
for (const [key, n] of nextByKey) {
|
|
338
|
+
if (!priorByKey.has(key)) {
|
|
339
|
+
out.push({ kind: "add", orbitalName: n.orbital, next: n });
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
return out;
|
|
343
|
+
}
|
|
344
|
+
function callKey(c) {
|
|
345
|
+
return `${c.organism}::${c.orbital}`;
|
|
346
|
+
}
|
|
347
|
+
function paramsEqual(a, b) {
|
|
348
|
+
return canonicalParams(a) === canonicalParams(b);
|
|
349
|
+
}
|
|
350
|
+
function canonicalParams(p) {
|
|
351
|
+
const keys = [
|
|
352
|
+
"entityFields",
|
|
353
|
+
"entityName",
|
|
354
|
+
"extraTraits",
|
|
355
|
+
"pagePaths",
|
|
356
|
+
"persistence",
|
|
357
|
+
"traitOverrides"
|
|
358
|
+
];
|
|
359
|
+
const parts = [];
|
|
360
|
+
for (const k of keys) {
|
|
361
|
+
const v = p[k];
|
|
362
|
+
if (v === void 0) continue;
|
|
363
|
+
parts.push(`${k}:${canonicalNode(v)}`);
|
|
364
|
+
}
|
|
365
|
+
return `{${parts.join(",")}}`;
|
|
366
|
+
}
|
|
367
|
+
function canonicalNode(v) {
|
|
368
|
+
if (v === void 0) return "u";
|
|
369
|
+
if (typeof v === "string") return JSON.stringify(v);
|
|
370
|
+
if (Array.isArray(v)) {
|
|
371
|
+
return `[${v.map((x) => canonicalParamValue(x)).join(",")}]`;
|
|
372
|
+
}
|
|
373
|
+
const keys = Object.keys(v).sort();
|
|
374
|
+
const parts = [];
|
|
375
|
+
for (const k of keys) {
|
|
376
|
+
const child = v[k];
|
|
377
|
+
parts.push(`${JSON.stringify(k)}:${canonicalParamValue(child)}`);
|
|
378
|
+
}
|
|
379
|
+
return `{${parts.join(",")}}`;
|
|
380
|
+
}
|
|
381
|
+
function canonicalParamValue(v) {
|
|
382
|
+
if (v === null || v === void 0) return "u";
|
|
383
|
+
if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") {
|
|
384
|
+
return JSON.stringify(v);
|
|
385
|
+
}
|
|
386
|
+
if (Array.isArray(v)) {
|
|
387
|
+
return `[${v.map(canonicalParamValue).join(",")}]`;
|
|
388
|
+
}
|
|
389
|
+
const keys = Object.keys(v).sort();
|
|
390
|
+
const parts = [];
|
|
391
|
+
for (const k of keys) {
|
|
392
|
+
const child = v[k];
|
|
393
|
+
if (child === void 0) continue;
|
|
394
|
+
parts.push(`${JSON.stringify(k)}:${canonicalParamValue(child)}`);
|
|
395
|
+
}
|
|
396
|
+
return `{${parts.join(",")}}`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// src/factory/mutate.ts
|
|
400
|
+
function applyFactoryCallPlanMutation(state, m) {
|
|
401
|
+
switch (m.kind) {
|
|
402
|
+
case "set-orbital-entity-fields":
|
|
403
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
404
|
+
...o,
|
|
405
|
+
entityFields: m.fields
|
|
406
|
+
}));
|
|
407
|
+
case "set-orbital-entity-name":
|
|
408
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
409
|
+
...o,
|
|
410
|
+
entityName: m.name
|
|
411
|
+
}));
|
|
412
|
+
case "set-orbital-persistence":
|
|
413
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
414
|
+
...o,
|
|
415
|
+
persistence: m.persistence
|
|
416
|
+
}));
|
|
417
|
+
case "set-orbital-collection":
|
|
418
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
419
|
+
...o,
|
|
420
|
+
collection: m.collection
|
|
421
|
+
}));
|
|
422
|
+
case "set-orbital-page-path":
|
|
423
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
424
|
+
...o,
|
|
425
|
+
pagePaths: { ...o.pagePaths ?? {}, [m.pageName]: m.path }
|
|
426
|
+
}));
|
|
427
|
+
case "set-trait-override-config":
|
|
428
|
+
return patchOrbital(state, m.orbitalName, (o) => {
|
|
429
|
+
const overlay = o.traitOverlay ?? {};
|
|
430
|
+
const existing = overlay[m.traitName] ?? {};
|
|
431
|
+
const existingConfig = existing.config ?? {};
|
|
432
|
+
return {
|
|
433
|
+
...o,
|
|
434
|
+
traitOverlay: {
|
|
435
|
+
...overlay,
|
|
436
|
+
[m.traitName]: {
|
|
437
|
+
...existing,
|
|
438
|
+
config: { ...existingConfig, [m.key]: m.value }
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
});
|
|
443
|
+
case "add-extra-trait":
|
|
444
|
+
return patchOrbital(state, m.orbitalName, (o) => {
|
|
445
|
+
const existing = o.extraTraits ?? [];
|
|
446
|
+
if (existing.some((t) => t.ref === m.trait.ref)) return o;
|
|
447
|
+
return { ...o, extraTraits: [...existing, m.trait] };
|
|
448
|
+
});
|
|
449
|
+
case "remove-extra-trait":
|
|
450
|
+
return patchOrbital(state, m.orbitalName, (o) => ({
|
|
451
|
+
...o,
|
|
452
|
+
extraTraits: (o.extraTraits ?? []).filter((t) => t.ref !== m.ref)
|
|
453
|
+
}));
|
|
454
|
+
case "set-rule": {
|
|
455
|
+
const rules = state.ruleOverlay?.rules ?? [];
|
|
456
|
+
const idx = rules.findIndex((r) => r.id === m.rule.id);
|
|
457
|
+
const next = idx >= 0 ? rules.map((r, i) => i === idx ? m.rule : r) : [...rules, m.rule];
|
|
458
|
+
return {
|
|
459
|
+
...state,
|
|
460
|
+
ruleOverlay: { ...state.ruleOverlay ?? { rules: [] }, rules: next }
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
case "remove-rule": {
|
|
464
|
+
const rules = state.ruleOverlay?.rules ?? [];
|
|
465
|
+
const next = rules.filter((r) => r.id !== m.ruleId);
|
|
466
|
+
return {
|
|
467
|
+
...state,
|
|
468
|
+
ruleOverlay: { ...state.ruleOverlay ?? { rules: [] }, rules: next }
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
function patchOrbital(state, orbitalName, patch) {
|
|
474
|
+
return {
|
|
475
|
+
...state,
|
|
476
|
+
orbitals: state.orbitals.map(
|
|
477
|
+
(o) => o.orbitalName === orbitalName ? patch(o) : o
|
|
478
|
+
)
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export { applyFactoryCallPlanMutation, diffFactoryCalls, translateDomainToParams, translateDomainToParams as translateOverlaysToParams };
|
|
483
|
+
//# sourceMappingURL=index.js.map
|
|
484
|
+
//# sourceMappingURL=index.js.map
|