@almadar/core 2.9.1 → 2.10.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/{compose-behaviors-C42E5T3f.d.ts → adapt-behavior-WWazE3lN.d.ts} +44 -2
- package/dist/builders.d.ts +1 -1
- package/dist/builders.js +159 -1
- package/dist/builders.js.map +1 -1
- package/dist/domain-language/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +159 -1
- package/dist/index.js.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { O as OrbitalDefinition, b as OrbitalSchema } from './schema-B2HUtPrQ.js';
|
|
1
|
+
import { O as OrbitalDefinition, b as OrbitalSchema, a as EntityPersistence } from './schema-B2HUtPrQ.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Event Wiring
|
|
@@ -116,4 +116,46 @@ interface ComposeBehaviorsResult {
|
|
|
116
116
|
*/
|
|
117
117
|
declare function composeBehaviors(input: ComposeBehaviorsInput): ComposeBehaviorsResult;
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Adapt Behavior Builder
|
|
121
|
+
*
|
|
122
|
+
* Deterministically rebinds a behavior's entity, fields, traits, and pages
|
|
123
|
+
* to a target entity. No LLM involved. Render-UI trees stay from the behavior.
|
|
124
|
+
*
|
|
125
|
+
* Uses core types (OrbitalDefinition, Entity, EntityField, Trait, Page)
|
|
126
|
+
* instead of untyped Record<string, unknown>.
|
|
127
|
+
*
|
|
128
|
+
* @packageDocumentation
|
|
129
|
+
*/
|
|
130
|
+
|
|
131
|
+
interface AdaptBehaviorInput {
|
|
132
|
+
/** Source orbital definition (from a golden behavior) */
|
|
133
|
+
source: OrbitalDefinition;
|
|
134
|
+
/** Target entity name (PascalCase) */
|
|
135
|
+
entityName: string;
|
|
136
|
+
/** Target fields */
|
|
137
|
+
fields: Array<{
|
|
138
|
+
name: string;
|
|
139
|
+
type: string;
|
|
140
|
+
required?: boolean;
|
|
141
|
+
}>;
|
|
142
|
+
/** Target collection name (defaults to plural lowercase of entityName) */
|
|
143
|
+
collection?: string;
|
|
144
|
+
/** Persistence mode (defaults to "persistent") */
|
|
145
|
+
persistence?: EntityPersistence;
|
|
146
|
+
}
|
|
147
|
+
interface AdaptBehaviorResult {
|
|
148
|
+
/** The adapted orbital definition */
|
|
149
|
+
orbital: OrbitalDefinition;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Adapt a behavior orbital to a new entity.
|
|
153
|
+
*
|
|
154
|
+
* Rebinds: entity name, collection, fields, trait names, page names/paths,
|
|
155
|
+
* entity references in render-ui trees and effects.
|
|
156
|
+
*
|
|
157
|
+
* Preserves: state machine structure, transitions, render-ui trees, event wiring.
|
|
158
|
+
*/
|
|
159
|
+
declare function adaptBehavior(input: AdaptBehaviorInput): AdaptBehaviorResult;
|
|
160
|
+
|
|
161
|
+
export { type AdaptBehaviorInput as A, type ComposeBehaviorsInput as C, type EventWiringEntry as E, type LayoutStrategy as L, type AdaptBehaviorResult as a, type ComposeBehaviorsResult as b, adaptBehavior as c, applyEventWiring as d, composeBehaviors as e, detectLayoutStrategy as f };
|
package/dist/builders.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { T as TraitEventContract, E as EntityField, a as EntityPersistence, O as OrbitalDefinition, b as OrbitalSchema, c as Trait, d as Entity, P as Page } from './schema-B2HUtPrQ.js';
|
|
2
|
-
export { C as ComposeBehaviorsInput,
|
|
2
|
+
export { A as AdaptBehaviorInput, a as AdaptBehaviorResult, C as ComposeBehaviorsInput, b as ComposeBehaviorsResult, E as EventWiringEntry, L as LayoutStrategy, c as adaptBehavior, d as applyEventWiring, e as composeBehaviors, f as detectLayoutStrategy } from './adapt-behavior-WWazE3lN.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import '@almadar/patterns';
|
|
5
5
|
|
package/dist/builders.js
CHANGED
|
@@ -411,6 +411,164 @@ function composeBehaviors(input) {
|
|
|
411
411
|
};
|
|
412
412
|
}
|
|
413
413
|
|
|
414
|
+
// src/builders/adapt-behavior.ts
|
|
415
|
+
var VALID_FIELD_TYPES = /* @__PURE__ */ new Set([
|
|
416
|
+
"string",
|
|
417
|
+
"number",
|
|
418
|
+
"boolean",
|
|
419
|
+
"date",
|
|
420
|
+
"timestamp",
|
|
421
|
+
"datetime",
|
|
422
|
+
"array",
|
|
423
|
+
"object",
|
|
424
|
+
"enum",
|
|
425
|
+
"relation"
|
|
426
|
+
]);
|
|
427
|
+
function normalizeFieldType(type) {
|
|
428
|
+
if (type.endsWith("[]")) return "array";
|
|
429
|
+
const lower = type.toLowerCase();
|
|
430
|
+
if (VALID_FIELD_TYPES.has(lower)) return lower;
|
|
431
|
+
return "string";
|
|
432
|
+
}
|
|
433
|
+
function deriveTraitSuffix(originalEntityName, traits) {
|
|
434
|
+
if (!traits.length) return "Management";
|
|
435
|
+
const traitName = traits[0].name;
|
|
436
|
+
if (traitName.startsWith(originalEntityName)) {
|
|
437
|
+
const suffix = traitName.slice(originalEntityName.length);
|
|
438
|
+
if (suffix && suffix.toLowerCase() !== originalEntityName.toLowerCase()) {
|
|
439
|
+
return suffix;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const lower = originalEntityName.toLowerCase();
|
|
443
|
+
const traitLower = traitName.toLowerCase();
|
|
444
|
+
if (traitLower.startsWith(lower)) {
|
|
445
|
+
const suffix = traitName.slice(lower.length);
|
|
446
|
+
if (suffix && suffix.toLowerCase() !== originalEntityName.toLowerCase()) {
|
|
447
|
+
return suffix;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return "Management";
|
|
451
|
+
}
|
|
452
|
+
function replaceEntityRefs(obj, oldEntity, newEntity) {
|
|
453
|
+
if (typeof obj === "string") {
|
|
454
|
+
return obj === oldEntity ? newEntity : obj.replace(new RegExp(oldEntity, "g"), newEntity);
|
|
455
|
+
}
|
|
456
|
+
if (Array.isArray(obj)) {
|
|
457
|
+
return obj.map((item) => replaceEntityRefs(item, oldEntity, newEntity));
|
|
458
|
+
}
|
|
459
|
+
if (obj && typeof obj === "object") {
|
|
460
|
+
const result = {};
|
|
461
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
462
|
+
result[key] = replaceEntityRefs(value, oldEntity, newEntity);
|
|
463
|
+
}
|
|
464
|
+
return result;
|
|
465
|
+
}
|
|
466
|
+
return obj;
|
|
467
|
+
}
|
|
468
|
+
function cleanStaleBindings(stateMachine, validFields) {
|
|
469
|
+
const sm = stateMachine;
|
|
470
|
+
const transitions = sm.transitions;
|
|
471
|
+
if (!transitions) return;
|
|
472
|
+
for (const transition of transitions) {
|
|
473
|
+
const effects = transition.effects;
|
|
474
|
+
if (!effects) continue;
|
|
475
|
+
transition.effects = effects.filter((effect) => {
|
|
476
|
+
if (!Array.isArray(effect)) return true;
|
|
477
|
+
return !hasStaleBinding(effect, validFields);
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
function hasStaleBinding(value, validFields) {
|
|
482
|
+
if (typeof value === "string") {
|
|
483
|
+
if (value.startsWith("@entity.")) {
|
|
484
|
+
const field = value.slice("@entity.".length).split(".")[0];
|
|
485
|
+
return !validFields.has(field);
|
|
486
|
+
}
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
if (Array.isArray(value)) {
|
|
490
|
+
return value.some((item) => hasStaleBinding(item, validFields));
|
|
491
|
+
}
|
|
492
|
+
if (value && typeof value === "object") {
|
|
493
|
+
return Object.values(value).some((v) => hasStaleBinding(v, validFields));
|
|
494
|
+
}
|
|
495
|
+
return false;
|
|
496
|
+
}
|
|
497
|
+
function adaptBehavior(input) {
|
|
498
|
+
const { source, entityName, fields, collection, persistence } = input;
|
|
499
|
+
const orbital = JSON.parse(JSON.stringify(source));
|
|
500
|
+
const originalEntity = typeof orbital.entity === "string" ? orbital.entity : orbital.entity.name;
|
|
501
|
+
const targetCollection = collection ?? entityName.toLowerCase() + "s";
|
|
502
|
+
orbital.entity = {
|
|
503
|
+
name: entityName,
|
|
504
|
+
collection: targetCollection,
|
|
505
|
+
persistence: persistence ?? "persistent",
|
|
506
|
+
fields: [
|
|
507
|
+
{ name: "id", type: "string", required: true },
|
|
508
|
+
...fields.map((f) => ({
|
|
509
|
+
name: f.name,
|
|
510
|
+
type: normalizeFieldType(f.type),
|
|
511
|
+
...f.required ? { required: true } : {}
|
|
512
|
+
}))
|
|
513
|
+
].filter((f, i, arr) => arr.findIndex((x) => x.name === f.name) === i)
|
|
514
|
+
// dedupe id
|
|
515
|
+
};
|
|
516
|
+
const inlineTraits = orbital.traits.filter((t) => isInlineTrait(t));
|
|
517
|
+
const firstTraitSuffix = deriveTraitSuffix(originalEntity, inlineTraits);
|
|
518
|
+
const traitNameMap = /* @__PURE__ */ new Map();
|
|
519
|
+
for (const trait of inlineTraits) {
|
|
520
|
+
const oldTraitName = trait.name;
|
|
521
|
+
let newTraitName;
|
|
522
|
+
if (trait.name.toLowerCase().startsWith(originalEntity.toLowerCase())) {
|
|
523
|
+
const suffix = trait.name.slice(originalEntity.length) || firstTraitSuffix;
|
|
524
|
+
newTraitName = entityName + suffix;
|
|
525
|
+
} else {
|
|
526
|
+
newTraitName = entityName + trait.name;
|
|
527
|
+
}
|
|
528
|
+
traitNameMap.set(oldTraitName, newTraitName);
|
|
529
|
+
trait.name = newTraitName;
|
|
530
|
+
trait.linkedEntity = entityName;
|
|
531
|
+
if (trait.stateMachine) {
|
|
532
|
+
trait.stateMachine = replaceEntityRefs(
|
|
533
|
+
trait.stateMachine,
|
|
534
|
+
originalEntity,
|
|
535
|
+
entityName
|
|
536
|
+
);
|
|
537
|
+
trait.stateMachine = replaceEntityRefs(
|
|
538
|
+
trait.stateMachine,
|
|
539
|
+
oldTraitName,
|
|
540
|
+
newTraitName
|
|
541
|
+
);
|
|
542
|
+
const newFieldNames = new Set(fields.map((f) => f.name));
|
|
543
|
+
newFieldNames.add("id");
|
|
544
|
+
cleanStaleBindings(trait.stateMachine, newFieldNames);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
orbital.name = entityName + firstTraitSuffix;
|
|
548
|
+
if (orbital.pages) {
|
|
549
|
+
for (const page of orbital.pages) {
|
|
550
|
+
if (typeof page === "string") continue;
|
|
551
|
+
const p = page;
|
|
552
|
+
if (p.name) p.name = entityName + "Page";
|
|
553
|
+
if (p.path) p.path = "/" + targetCollection;
|
|
554
|
+
if (p.traits) {
|
|
555
|
+
for (const ref of p.traits) {
|
|
556
|
+
if (typeof ref === "object" && "ref" in ref) {
|
|
557
|
+
ref.ref = traitNameMap.get(ref.ref) ?? entityName + firstTraitSuffix;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if ("domainContext" in orbital) {
|
|
564
|
+
const ctx = orbital.domainContext;
|
|
565
|
+
if (ctx?.vocabulary && typeof ctx.vocabulary === "object") {
|
|
566
|
+
ctx.vocabulary.item = entityName.toLowerCase();
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return { orbital };
|
|
570
|
+
}
|
|
571
|
+
|
|
414
572
|
// src/builders.ts
|
|
415
573
|
function ensureIdField(fields) {
|
|
416
574
|
if (fields.some((f) => f.name === "id")) return fields;
|
|
@@ -570,6 +728,6 @@ function pipe(orbitals, events, appName) {
|
|
|
570
728
|
};
|
|
571
729
|
}
|
|
572
730
|
|
|
573
|
-
export { applyEventWiring, compose, composeBehaviors, connect, detectLayoutStrategy, ensureIdField, extractTrait, makeEntity, makeOrbital, makePage, mergeOrbitals, pipe, plural, wire };
|
|
731
|
+
export { adaptBehavior, applyEventWiring, compose, composeBehaviors, connect, detectLayoutStrategy, ensureIdField, extractTrait, makeEntity, makeOrbital, makePage, mergeOrbitals, pipe, plural, wire };
|
|
574
732
|
//# sourceMappingURL=builders.js.map
|
|
575
733
|
//# sourceMappingURL=builders.js.map
|