@almadar/core 7.16.0 → 7.17.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 +2 -2
- package/dist/{compose-behaviors-D2vPjRpX.d.ts → compose-behaviors-DWMFJEz3.d.ts} +1 -1
- package/dist/domain-language/index.d.ts +46 -3
- package/dist/domain-language/index.js +180 -85
- package/dist/domain-language/index.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +180 -85
- package/dist/index.js.map +1 -1
- package/dist/{schema-DJzXvJHi.d.ts → schema-WX5fN1Ra.d.ts} +1 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/builders.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d7 as UISlot, Z as Effect, cE as Trait, bN as RenderUIEffect, cQ as TraitEventContract, a2 as Entity, cS as TraitEventListener, cH as TraitConfig, a6 as EntityField, a9 as EntityPersistence, ag as EntityRow, dc as UseDeclaration, ab as EntityRef, cV as TraitRef, bs as PageRef, b6 as OrbitalDefinition, bh as OrbitalSchema, br as Page, bt as PageRefObject, cX as TraitReference } from './schema-WX5fN1Ra.js';
|
|
2
2
|
import { S as SExpr } from './expression-BVRFm0sV.js';
|
|
3
|
-
export { C as ComposeBehaviorsInput, a as ComposeBehaviorsResult, E as EventWiringEntry, L as LayoutStrategy, b as applyEventWiring, c as composeBehaviors, d as detectLayoutStrategy } from './compose-behaviors-
|
|
3
|
+
export { C as ComposeBehaviorsInput, a as ComposeBehaviorsResult, E as EventWiringEntry, L as LayoutStrategy, b as applyEventWiring, c as composeBehaviors, d as detectLayoutStrategy } from './compose-behaviors-DWMFJEz3.js';
|
|
4
4
|
import { AnyPatternConfig } from '@almadar/patterns';
|
|
5
5
|
import 'zod';
|
|
6
6
|
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
+
import { c$ as TraitScope, a9 as EntityPersistence, a2 as Entity, br as Page, bh as OrbitalSchema, cE as Trait } from '../schema-WX5fN1Ra.js';
|
|
1
2
|
import { S as SExpr } from '../expression-BVRFm0sV.js';
|
|
2
|
-
import { a2 as Entity, br as Page, bh as OrbitalSchema, cE as Trait } from '../schema-DJzXvJHi.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
import '@almadar/patterns';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Domain Language Types
|
|
8
|
+
*
|
|
9
|
+
* AST node types for the domain language that maps to KFlow schema.
|
|
10
|
+
* All entity references use explicit names (e.g., Order, Task, CurrentUser)
|
|
11
|
+
* per GAP-002 - no magic variables like `entity.` or `context.`.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
|
|
6
16
|
/**
|
|
7
17
|
* Effect operator mapping: Both systems use the same operator names
|
|
8
18
|
*/
|
|
@@ -31,6 +41,23 @@ interface ASTNode {
|
|
|
31
41
|
* Note: These map to OrbitalSchema types via DOMAIN_TO_SCHEMA_FIELD_TYPE
|
|
32
42
|
*/
|
|
33
43
|
type DomainFieldType = 'text' | 'long text' | 'number' | 'currency' | 'date' | 'timestamp' | 'datetime' | 'yes/no' | 'enum' | 'list' | 'object' | 'relation';
|
|
44
|
+
/**
|
|
45
|
+
* Default value for a `DomainField`. Mirrors the JSON-leaf shape an
|
|
46
|
+
* `EntityField.default` may carry on `OrbitalSchema`: scalar, list, or
|
|
47
|
+
* nested object (when the field type is `'object'` or `'list'`).
|
|
48
|
+
*/
|
|
49
|
+
type DomainFieldDefault = string | number | boolean | null | DomainFieldDefault[] | {
|
|
50
|
+
[k: string]: DomainFieldDefault;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* For `fieldType: 'list'`, the typed shape of each item. Mirrors
|
|
54
|
+
* `EntityField.items` on `OrbitalSchema`. Currently a single-level
|
|
55
|
+
* type tag (matching how the schema uses it); extend if/when nested
|
|
56
|
+
* list-of-list / list-of-object signatures are required.
|
|
57
|
+
*/
|
|
58
|
+
interface DomainFieldItems {
|
|
59
|
+
type: DomainFieldType;
|
|
60
|
+
}
|
|
34
61
|
interface DomainField extends ASTNode {
|
|
35
62
|
type: 'field';
|
|
36
63
|
name: string;
|
|
@@ -38,8 +65,10 @@ interface DomainField extends ASTNode {
|
|
|
38
65
|
required: boolean;
|
|
39
66
|
unique: boolean;
|
|
40
67
|
auto: boolean;
|
|
41
|
-
default?:
|
|
68
|
+
default?: DomainFieldDefault;
|
|
42
69
|
enumValues?: string[];
|
|
70
|
+
/** List-of-X item type when `fieldType === 'list'`. */
|
|
71
|
+
items?: DomainFieldItems;
|
|
43
72
|
}
|
|
44
73
|
type RelationshipType = 'belongs_to' | 'has_many' | 'has_one';
|
|
45
74
|
interface DomainRelationship extends ASTNode {
|
|
@@ -56,6 +85,13 @@ interface DomainEntity extends ASTNode {
|
|
|
56
85
|
relationships: DomainRelationship[];
|
|
57
86
|
states?: string[];
|
|
58
87
|
initialState?: string;
|
|
88
|
+
/**
|
|
89
|
+
* Storage mode on the resolved schema. Mirrors `EntityPersistence` in
|
|
90
|
+
* `@almadar/core/types/entity.ts`. Omitted ⇒ projector defaults to
|
|
91
|
+
* `'persistent'`. Domain text syntax: `Persistence: <value>` line in
|
|
92
|
+
* the entity section.
|
|
93
|
+
*/
|
|
94
|
+
persistence?: EntityPersistence;
|
|
59
95
|
}
|
|
60
96
|
interface DomainPageSection extends ASTNode {
|
|
61
97
|
type: 'page_section';
|
|
@@ -146,6 +182,13 @@ interface DomainBehavior extends ASTNode {
|
|
|
146
182
|
transitions: DomainTransition[];
|
|
147
183
|
ticks: DomainTick[];
|
|
148
184
|
rules: string[];
|
|
185
|
+
/**
|
|
186
|
+
* Instance- vs collection-scoped state machine. Mirrors
|
|
187
|
+
* `Trait.scope: TraitScope` in `@almadar/core/types/trait.ts`.
|
|
188
|
+
* Omitted ⇒ projector defaults to `'instance'`. Domain text syntax:
|
|
189
|
+
* `Scope: instance|collection` line in the behavior section.
|
|
190
|
+
*/
|
|
191
|
+
scope?: TraitScope;
|
|
149
192
|
}
|
|
150
193
|
interface DomainDocument extends ASTNode {
|
|
151
194
|
type: 'document';
|
|
@@ -926,4 +969,4 @@ declare function getRegistryStats(): {
|
|
|
926
969
|
*/
|
|
927
970
|
declare function generateDomainLanguageReference(): string;
|
|
928
971
|
|
|
929
|
-
export { type ASTNode, type ComparisonCondition, type ComparisonOperator, type DomainBehavior, type DomainChunk, type DomainDocument, type DomainEffect, type DomainEntity, type DomainField, type DomainFieldType, type DomainGuard, type DomainPage, type DomainPageAction, type DomainPageSection, type DomainRelationship, type DomainTick, type DomainToSchemaResult, type DomainTransition, EFFECT_REGISTRY, type EffectMapping, type EffectType, FIELD_TYPE_REGISTRY, type FieldCheckCondition, type FieldReference, type FieldTypeMapping, GUARD_REGISTRY, type GuardCondition, type GuardMapping, KEYWORDS, Lexer, type LogicalCondition, type LogicalOperator, MULTI_WORD_KEYWORDS, type MappingStore, type MergeResult, type ParseError, type ParseResult, type RelationshipType, type SchemaToDomainResult, type SectionMapping, type SourceLocation, type SourceRange, type Token, TokenType, type UserCheckCondition, applySectionUpdate, computeSchemaHash, convertDomainToSchema, convertEntitiesToDomain, convertPagesToDomain, convertSchemaToDomain, convertTraitsToDomain, createMappingStore, deleteSection, detectChanges, domainKeywordToSchemaType, findMapping, findMappingByPath, findMappingsByType, formatBehaviorToDomain, formatBehaviorToSchema, formatDomainGuardToSchema, formatEntityToDomain, formatEntityToSchema, formatGuardConditionToDomain, formatGuardToDomain, formatGuardToSchema, formatMergeSummary, formatPageToDomain, formatPageToSchema, formatSchemaEntityToDomain, formatSchemaGuardToDomain, formatSchemaPageToDomain, formatSchemaTraitToDomain, generateDomainLanguageReference, generateSectionId, getEffectMapping, getFieldTypeMapping, getGuardMapping, getRegisteredEffects, getRegisteredFieldTypes, getRegisteredGuards, getRegistryStats, getSchemaPath, hasSchemaChanged, isEffectRegistered, isFieldTypeRegistered, isGuardRegistered, mergeDomainChunks, parseBehavior, parseDomainEffect, parseDomainEffects, parseDomainGuard, parseEntity, parseGuard, parsePage, parseSectionId, removeMapping, resolveConflict, schemaEntityToDomainEntity, schemaPageToDomainPage, schemaTraitToDomainBehavior, schemaTypeToDomainKeyword, tokenize, updateMappingRange, updateSchemaHash, upsertMapping, validateDomainChunk };
|
|
972
|
+
export { type ASTNode, type ComparisonCondition, type ComparisonOperator, type DomainBehavior, type DomainChunk, type DomainDocument, type DomainEffect, type DomainEntity, type DomainField, type DomainFieldDefault, type DomainFieldItems, type DomainFieldType, type DomainGuard, type DomainPage, type DomainPageAction, type DomainPageSection, type DomainRelationship, type DomainTick, type DomainToSchemaResult, type DomainTransition, EFFECT_REGISTRY, type EffectMapping, type EffectType, EntityPersistence, FIELD_TYPE_REGISTRY, type FieldCheckCondition, type FieldReference, type FieldTypeMapping, GUARD_REGISTRY, type GuardCondition, type GuardMapping, KEYWORDS, Lexer, type LogicalCondition, type LogicalOperator, MULTI_WORD_KEYWORDS, type MappingStore, type MergeResult, type ParseError, type ParseResult, type RelationshipType, type SchemaToDomainResult, type SectionMapping, type SourceLocation, type SourceRange, type Token, TokenType, TraitScope, type UserCheckCondition, applySectionUpdate, computeSchemaHash, convertDomainToSchema, convertEntitiesToDomain, convertPagesToDomain, convertSchemaToDomain, convertTraitsToDomain, createMappingStore, deleteSection, detectChanges, domainKeywordToSchemaType, findMapping, findMappingByPath, findMappingsByType, formatBehaviorToDomain, formatBehaviorToSchema, formatDomainGuardToSchema, formatEntityToDomain, formatEntityToSchema, formatGuardConditionToDomain, formatGuardToDomain, formatGuardToSchema, formatMergeSummary, formatPageToDomain, formatPageToSchema, formatSchemaEntityToDomain, formatSchemaGuardToDomain, formatSchemaPageToDomain, formatSchemaTraitToDomain, generateDomainLanguageReference, generateSectionId, getEffectMapping, getFieldTypeMapping, getGuardMapping, getRegisteredEffects, getRegisteredFieldTypes, getRegisteredGuards, getRegistryStats, getSchemaPath, hasSchemaChanged, isEffectRegistered, isFieldTypeRegistered, isGuardRegistered, mergeDomainChunks, parseBehavior, parseDomainEffect, parseDomainEffects, parseDomainGuard, parseEntity, parseGuard, parsePage, parseSectionId, removeMapping, resolveConflict, schemaEntityToDomainEntity, schemaPageToDomainPage, schemaTraitToDomainBehavior, schemaTypeToDomainKeyword, tokenize, updateMappingRange, updateSchemaHash, upsertMapping, validateDomainChunk };
|
|
@@ -445,6 +445,7 @@ function parseEntity(text) {
|
|
|
445
445
|
const tokens = lexer.tokenize();
|
|
446
446
|
let pos = 0;
|
|
447
447
|
const current = () => tokens[pos] || { type: "EOF" /* EOF */, value: "", line: 0, column: 0, offset: 0 };
|
|
448
|
+
const peek = (offset = 0) => tokens[pos + offset] || { type: "EOF" /* EOF */, value: "", line: 0, column: 0, offset: 0 };
|
|
448
449
|
const advance = () => tokens[pos++];
|
|
449
450
|
const isAtEnd = () => current().type === "EOF" /* EOF */;
|
|
450
451
|
const skip = (type) => {
|
|
@@ -526,6 +527,21 @@ function parseEntity(text) {
|
|
|
526
527
|
}
|
|
527
528
|
function parseSection(entity2) {
|
|
528
529
|
const token = current();
|
|
530
|
+
if (token.type === "IDENTIFIER" /* IDENTIFIER */ && peek(1).type === "COLON" /* COLON */) {
|
|
531
|
+
const propName = token.value.toLowerCase();
|
|
532
|
+
if (propName === "persistence") {
|
|
533
|
+
advance();
|
|
534
|
+
advance();
|
|
535
|
+
if (current().type === "IDENTIFIER" /* IDENTIFIER */) {
|
|
536
|
+
const val = current().value.toLowerCase();
|
|
537
|
+
if (val === "persistent" || val === "runtime" || val === "singleton" || val === "instance" || val === "local") {
|
|
538
|
+
entity2.persistence = val;
|
|
539
|
+
advance();
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
529
545
|
if (token.type === "INDENT" /* INDENT */) {
|
|
530
546
|
advance();
|
|
531
547
|
parseIndentedFields(entity2);
|
|
@@ -759,36 +775,71 @@ function parseEntity(text) {
|
|
|
759
775
|
};
|
|
760
776
|
const parts = [];
|
|
761
777
|
while (!isAtEnd() && current().type !== "NEWLINE" /* NEWLINE */) {
|
|
762
|
-
|
|
778
|
+
const tok = current();
|
|
779
|
+
parts.push(tok.type === "STRING" /* STRING */ ? `"${tok.value}"` : tok.value);
|
|
763
780
|
advance();
|
|
764
781
|
}
|
|
765
782
|
const content = parts.join(" ").trim();
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
else
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
else if (
|
|
786
|
-
else if (
|
|
787
|
-
|
|
783
|
+
const segments = content.split(",").map((s) => s.trim());
|
|
784
|
+
if (segments.length === 0) return field;
|
|
785
|
+
const typeSpec = segments[0];
|
|
786
|
+
if (typeSpec.includes("|")) {
|
|
787
|
+
field.fieldType = "text";
|
|
788
|
+
field.enumValues = typeSpec.split("|").map((v) => v.trim()).filter((v) => v.length > 0);
|
|
789
|
+
} else {
|
|
790
|
+
const lower = typeSpec.toLowerCase();
|
|
791
|
+
if (lower.startsWith("list of ")) {
|
|
792
|
+
field.fieldType = "list";
|
|
793
|
+
field.items = { type: parseDomainFieldType(lower.slice("list of ".length).trim()) };
|
|
794
|
+
} else {
|
|
795
|
+
field.fieldType = parseDomainFieldType(lower);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
for (let i = 1; i < segments.length; i++) {
|
|
799
|
+
const segment = segments[i];
|
|
800
|
+
const lower = segment.toLowerCase();
|
|
801
|
+
if (lower === "required") field.required = true;
|
|
802
|
+
else if (lower === "unique") field.unique = true;
|
|
803
|
+
else if (lower === "auto") field.auto = true;
|
|
804
|
+
else if (lower.startsWith("default ")) {
|
|
805
|
+
field.default = parseDefaultLiteral(segment.slice("default ".length).trim());
|
|
788
806
|
}
|
|
789
807
|
}
|
|
790
808
|
return field;
|
|
791
809
|
}
|
|
810
|
+
function parseDomainFieldType(keyword) {
|
|
811
|
+
if (keyword === "long text") return "long text";
|
|
812
|
+
if (keyword === "text" || keyword === "string") return "text";
|
|
813
|
+
if (keyword === "number" || keyword === "integer") return "number";
|
|
814
|
+
if (keyword === "currency") return "currency";
|
|
815
|
+
if (keyword === "date") return "date";
|
|
816
|
+
if (keyword === "timestamp") return "timestamp";
|
|
817
|
+
if (keyword === "datetime") return "datetime";
|
|
818
|
+
if (keyword === "yes/no" || keyword === "boolean") return "yes/no";
|
|
819
|
+
if (keyword === "list" || keyword === "array") return "list";
|
|
820
|
+
if (keyword === "object") return "object";
|
|
821
|
+
if (keyword === "enum") return "enum";
|
|
822
|
+
if (keyword === "relation") return "relation";
|
|
823
|
+
return "text";
|
|
824
|
+
}
|
|
825
|
+
function parseDefaultLiteral(text2) {
|
|
826
|
+
const trimmed = text2.trim();
|
|
827
|
+
if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
|
|
828
|
+
return trimmed.slice(1, -1);
|
|
829
|
+
}
|
|
830
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]") || trimmed.startsWith("{") && trimmed.endsWith("}")) {
|
|
831
|
+
try {
|
|
832
|
+
return JSON.parse(trimmed);
|
|
833
|
+
} catch {
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
if (trimmed.toLowerCase() === "true") return true;
|
|
837
|
+
if (trimmed.toLowerCase() === "false") return false;
|
|
838
|
+
if (trimmed.toLowerCase() === "null") return null;
|
|
839
|
+
const num = Number(trimmed);
|
|
840
|
+
if (!Number.isNaN(num) && trimmed !== "") return num;
|
|
841
|
+
return trimmed;
|
|
842
|
+
}
|
|
792
843
|
function parseRelationship(entity2, relType) {
|
|
793
844
|
if (current().type !== "IDENTIFIER" /* IDENTIFIER */) {
|
|
794
845
|
return;
|
|
@@ -859,27 +910,32 @@ function formatEntityToDomain(entity) {
|
|
|
859
910
|
return lines.join("\n");
|
|
860
911
|
}
|
|
861
912
|
function formatEntityToSchema(entity) {
|
|
862
|
-
const fields = entity.fields.map((field) =>
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
913
|
+
const fields = entity.fields.map((field) => {
|
|
914
|
+
const schemaType = field.enumValues && field.enumValues.length > 0 ? mapFieldTypeToSchema(field.fieldType === "enum" ? "text" : field.fieldType) : mapFieldTypeToSchema(field.fieldType);
|
|
915
|
+
const out2 = {
|
|
916
|
+
name: field.name,
|
|
917
|
+
type: schemaType
|
|
918
|
+
};
|
|
919
|
+
if (field.required) out2.required = true;
|
|
920
|
+
if (field.unique) out2.unique = true;
|
|
921
|
+
if (field.auto) out2.auto = true;
|
|
922
|
+
if (field.enumValues && field.enumValues.length > 0) {
|
|
923
|
+
out2.values = field.enumValues;
|
|
924
|
+
}
|
|
925
|
+
if (field.items) {
|
|
926
|
+
out2.items = { type: mapFieldTypeToSchema(field.items.type) };
|
|
927
|
+
}
|
|
928
|
+
if (field.default !== void 0) {
|
|
929
|
+
out2.default = field.default;
|
|
930
|
+
}
|
|
931
|
+
return out2;
|
|
932
|
+
});
|
|
872
933
|
for (const rel of entity.relationships) {
|
|
873
934
|
if (rel.relationshipType === "belongs_to") {
|
|
874
935
|
const fieldName = rel.alias ? toCamelCase(rel.alias) + "Id" : toCamelCase(rel.targetEntity) + "Id";
|
|
875
936
|
fields.push({
|
|
876
937
|
name: fieldName,
|
|
877
938
|
type: "relation",
|
|
878
|
-
required: void 0,
|
|
879
|
-
unique: void 0,
|
|
880
|
-
auto: void 0,
|
|
881
|
-
values: void 0,
|
|
882
|
-
default: void 0,
|
|
883
939
|
relation: {
|
|
884
940
|
entity: rel.targetEntity,
|
|
885
941
|
type: "many-to-one"
|
|
@@ -887,13 +943,15 @@ function formatEntityToSchema(entity) {
|
|
|
887
943
|
});
|
|
888
944
|
}
|
|
889
945
|
}
|
|
890
|
-
|
|
946
|
+
const out = {
|
|
891
947
|
name: entity.name,
|
|
892
948
|
collection: toKebabCase(entity.name) + "s",
|
|
893
|
-
fields: fields.filter((f) => Object.keys(f).length > 0)
|
|
894
|
-
states: entity.states,
|
|
895
|
-
initialState: entity.initialState
|
|
949
|
+
fields: fields.filter((f) => Object.keys(f).length > 0)
|
|
896
950
|
};
|
|
951
|
+
if (entity.states && entity.states.length > 0) out.states = entity.states;
|
|
952
|
+
if (entity.initialState !== void 0) out.initialState = entity.initialState;
|
|
953
|
+
if (entity.persistence !== void 0) out.persistence = entity.persistence;
|
|
954
|
+
return out;
|
|
897
955
|
}
|
|
898
956
|
function toCamelCase(text) {
|
|
899
957
|
return text.toLowerCase().split(/\s+/).map(
|
|
@@ -916,14 +974,6 @@ function startsWithVowel(text) {
|
|
|
916
974
|
}
|
|
917
975
|
return /^[aeiou]/i.test(text);
|
|
918
976
|
}
|
|
919
|
-
function parseValue(text) {
|
|
920
|
-
text = text.trim();
|
|
921
|
-
if (text.toLowerCase() === "true") return true;
|
|
922
|
-
if (text.toLowerCase() === "false") return false;
|
|
923
|
-
const num = parseFloat(text);
|
|
924
|
-
if (!isNaN(num)) return num;
|
|
925
|
-
return text.replace(/^["']|["']$/g, "");
|
|
926
|
-
}
|
|
927
977
|
function formatFieldType(field) {
|
|
928
978
|
const parts = [];
|
|
929
979
|
if (field.enumValues && field.enumValues.length > 0) {
|
|
@@ -1523,7 +1573,7 @@ function parseFieldCheck(text, ctx) {
|
|
|
1523
1573
|
type: "field_check",
|
|
1524
1574
|
field,
|
|
1525
1575
|
check: "equals",
|
|
1526
|
-
value:
|
|
1576
|
+
value: parseValue(value)
|
|
1527
1577
|
};
|
|
1528
1578
|
}
|
|
1529
1579
|
}
|
|
@@ -1546,7 +1596,7 @@ function parseComparison(text, ctx) {
|
|
|
1546
1596
|
type: "comparison",
|
|
1547
1597
|
field,
|
|
1548
1598
|
operator: "!=",
|
|
1549
|
-
value:
|
|
1599
|
+
value: parseValue(isNotMatch[2])
|
|
1550
1600
|
};
|
|
1551
1601
|
}
|
|
1552
1602
|
}
|
|
@@ -1559,7 +1609,7 @@ function parseComparison(text, ctx) {
|
|
|
1559
1609
|
type: "comparison",
|
|
1560
1610
|
field,
|
|
1561
1611
|
operator,
|
|
1562
|
-
value:
|
|
1612
|
+
value: parseValue(match[2])
|
|
1563
1613
|
};
|
|
1564
1614
|
}
|
|
1565
1615
|
}
|
|
@@ -1583,7 +1633,7 @@ function parseFieldReference(text, ctx) {
|
|
|
1583
1633
|
fieldName
|
|
1584
1634
|
};
|
|
1585
1635
|
}
|
|
1586
|
-
function
|
|
1636
|
+
function parseValue(text) {
|
|
1587
1637
|
text = text.trim();
|
|
1588
1638
|
if (text.startsWith('"') && text.endsWith('"') || text.startsWith("'") && text.endsWith("'")) {
|
|
1589
1639
|
return text.slice(1, -1);
|
|
@@ -1866,37 +1916,37 @@ function parseComparison2(text, ctx) {
|
|
|
1866
1916
|
const atLeastMatch = text.match(/^(.+?)\s+is\s+at\s+least\s+(.+)$/i);
|
|
1867
1917
|
if (atLeastMatch) {
|
|
1868
1918
|
const field = parseFieldRef(atLeastMatch[1]);
|
|
1869
|
-
const value =
|
|
1919
|
+
const value = parseValue2(atLeastMatch[2]);
|
|
1870
1920
|
return [">=", field, value];
|
|
1871
1921
|
}
|
|
1872
1922
|
const atMostMatch = text.match(/^(.+?)\s+is\s+at\s+most\s+(.+)$/i);
|
|
1873
1923
|
if (atMostMatch) {
|
|
1874
1924
|
const field = parseFieldRef(atMostMatch[1]);
|
|
1875
|
-
const value =
|
|
1925
|
+
const value = parseValue2(atMostMatch[2]);
|
|
1876
1926
|
return ["<=", field, value];
|
|
1877
1927
|
}
|
|
1878
1928
|
const greaterThanMatch = text.match(/^(.+?)\s+is\s+greater\s+than\s+(.+)$/i);
|
|
1879
1929
|
if (greaterThanMatch) {
|
|
1880
1930
|
const field = parseFieldRef(greaterThanMatch[1]);
|
|
1881
|
-
const value =
|
|
1931
|
+
const value = parseValue2(greaterThanMatch[2]);
|
|
1882
1932
|
return [">", field, value];
|
|
1883
1933
|
}
|
|
1884
1934
|
const lessThanMatch = text.match(/^(.+?)\s+is\s+less\s+than\s+(.+)$/i);
|
|
1885
1935
|
if (lessThanMatch) {
|
|
1886
1936
|
const field = parseFieldRef(lessThanMatch[1]);
|
|
1887
|
-
const value =
|
|
1937
|
+
const value = parseValue2(lessThanMatch[2]);
|
|
1888
1938
|
return ["<", field, value];
|
|
1889
1939
|
}
|
|
1890
1940
|
const isNotMatch = text.match(/^(.+?)\s+is\s+not\s+(.+)$/i);
|
|
1891
1941
|
if (isNotMatch) {
|
|
1892
1942
|
const field = parseFieldRef(isNotMatch[1]);
|
|
1893
|
-
const value =
|
|
1943
|
+
const value = parseValue2(isNotMatch[2]);
|
|
1894
1944
|
return ["!=", field, value];
|
|
1895
1945
|
}
|
|
1896
1946
|
const isMatch = text.match(/^(.+?)\s+is\s+(.+)$/i);
|
|
1897
1947
|
if (isMatch) {
|
|
1898
1948
|
const field = parseFieldRef(isMatch[1]);
|
|
1899
|
-
const value =
|
|
1949
|
+
const value = parseValue2(isMatch[2]);
|
|
1900
1950
|
return ["=", field, value];
|
|
1901
1951
|
}
|
|
1902
1952
|
const opPatterns = [
|
|
@@ -1911,7 +1961,7 @@ function parseComparison2(text, ctx) {
|
|
|
1911
1961
|
const match = text.match(pattern);
|
|
1912
1962
|
if (match) {
|
|
1913
1963
|
const left = parseFieldRef(match[1]);
|
|
1914
|
-
const right =
|
|
1964
|
+
const right = parseValue2(match[2]);
|
|
1915
1965
|
return [op, left, right];
|
|
1916
1966
|
}
|
|
1917
1967
|
}
|
|
@@ -2072,7 +2122,7 @@ function parseFieldRef(text, ctx) {
|
|
|
2072
2122
|
const fieldName = toCamelCase3(text);
|
|
2073
2123
|
return `@entity.${fieldName}`;
|
|
2074
2124
|
}
|
|
2075
|
-
function
|
|
2125
|
+
function parseValue2(text) {
|
|
2076
2126
|
text = text.trim();
|
|
2077
2127
|
if (text.startsWith('"') && text.endsWith('"') || text.startsWith("'") && text.endsWith("'")) {
|
|
2078
2128
|
return text.slice(1, -1);
|
|
@@ -2120,7 +2170,7 @@ function parseEffectValue(text, ctx) {
|
|
|
2120
2170
|
if (text.includes(".") || text.toLowerCase().startsWith("incoming ") || text.match(/^\w+'s\s+/) || /^[a-z]/.test(text)) {
|
|
2121
2171
|
return parseFieldRef(text);
|
|
2122
2172
|
}
|
|
2123
|
-
return
|
|
2173
|
+
return parseValue2(text);
|
|
2124
2174
|
}
|
|
2125
2175
|
function processBindingsInObject(obj) {
|
|
2126
2176
|
if (obj === null || obj === void 0) {
|
|
@@ -2378,6 +2428,18 @@ function parseBehavior(text, entityName) {
|
|
|
2378
2428
|
}
|
|
2379
2429
|
return true;
|
|
2380
2430
|
}
|
|
2431
|
+
if (token.type === "IDENTIFIER" /* IDENTIFIER */ && token.value.toLowerCase() === "scope") {
|
|
2432
|
+
advance();
|
|
2433
|
+
skip("COLON" /* COLON */);
|
|
2434
|
+
if (current().type === "IDENTIFIER" /* IDENTIFIER */) {
|
|
2435
|
+
const val = current().value.toLowerCase();
|
|
2436
|
+
if (val === "instance" || val === "collection") {
|
|
2437
|
+
behavior2.scope = val;
|
|
2438
|
+
advance();
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
return true;
|
|
2442
|
+
}
|
|
2381
2443
|
if (token.type === "STATES" /* STATES */) {
|
|
2382
2444
|
advance();
|
|
2383
2445
|
skip("COLON" /* COLON */);
|
|
@@ -2869,6 +2931,9 @@ function formatBehaviorToSchema(behavior) {
|
|
|
2869
2931
|
name: behavior.name.replace(/\s+/g, ""),
|
|
2870
2932
|
description: behavior.name
|
|
2871
2933
|
};
|
|
2934
|
+
if (behavior.scope !== void 0) {
|
|
2935
|
+
trait.scope = behavior.scope;
|
|
2936
|
+
}
|
|
2872
2937
|
if (behavior.states.length > 0) {
|
|
2873
2938
|
trait.stateMachine = {
|
|
2874
2939
|
states: behavior.states.map((state, index) => ({
|
|
@@ -2883,21 +2948,30 @@ function formatBehaviorToSchema(behavior) {
|
|
|
2883
2948
|
event: t.event
|
|
2884
2949
|
};
|
|
2885
2950
|
if (t.guards.length > 0) {
|
|
2886
|
-
const guardExprs =
|
|
2887
|
-
|
|
2888
|
-
|
|
2951
|
+
const guardExprs = [];
|
|
2952
|
+
for (const g of t.guards) {
|
|
2953
|
+
const raw = g.raw ?? formatGuardToCondition(g);
|
|
2954
|
+
try {
|
|
2955
|
+
guardExprs.push(parseDomainGuard(raw, behavior.entityName));
|
|
2956
|
+
} catch {
|
|
2889
2957
|
}
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2958
|
+
}
|
|
2959
|
+
if (guardExprs.length === 1) transition.guard = guardExprs[0];
|
|
2960
|
+
else if (guardExprs.length > 1) transition.guard = ["and", ...guardExprs];
|
|
2893
2961
|
}
|
|
2894
2962
|
if (t.effects.length > 0) {
|
|
2895
|
-
|
|
2963
|
+
const effectExprs = [];
|
|
2964
|
+
for (const e of t.effects) {
|
|
2896
2965
|
if (e.config && "_rawSExpr" in e.config && Array.isArray(e.config._rawSExpr)) {
|
|
2897
|
-
|
|
2966
|
+
effectExprs.push(e.config._rawSExpr);
|
|
2967
|
+
continue;
|
|
2898
2968
|
}
|
|
2899
|
-
|
|
2900
|
-
|
|
2969
|
+
try {
|
|
2970
|
+
effectExprs.push(parseDomainEffect(e.description, behavior.entityName));
|
|
2971
|
+
} catch {
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
if (effectExprs.length > 0) transition.effects = effectExprs;
|
|
2901
2975
|
}
|
|
2902
2976
|
return transition;
|
|
2903
2977
|
})
|
|
@@ -3018,11 +3092,13 @@ function schemaEntityToDomainEntity(entity) {
|
|
|
3018
3092
|
unique: field.unique || false,
|
|
3019
3093
|
auto: field.auto || false
|
|
3020
3094
|
};
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3095
|
+
const enumValues = field.enumValues ?? field.values;
|
|
3096
|
+
if (enumValues && enumValues.length > 0) {
|
|
3097
|
+
domainField.enumValues = enumValues;
|
|
3098
|
+
}
|
|
3099
|
+
const items = field.items;
|
|
3100
|
+
if (items && typeof items.type === "string") {
|
|
3101
|
+
domainField.items = { type: mapSchemaTypeToDomain(items.type) };
|
|
3026
3102
|
}
|
|
3027
3103
|
if (field.default !== void 0) {
|
|
3028
3104
|
domainField.default = field.default;
|
|
@@ -3031,6 +3107,7 @@ function schemaEntityToDomainEntity(entity) {
|
|
|
3031
3107
|
}
|
|
3032
3108
|
const states = entity.states;
|
|
3033
3109
|
const initialState = entity.initialState;
|
|
3110
|
+
const persistence = entity.persistence;
|
|
3034
3111
|
return {
|
|
3035
3112
|
type: "entity",
|
|
3036
3113
|
name,
|
|
@@ -3038,13 +3115,17 @@ function schemaEntityToDomainEntity(entity) {
|
|
|
3038
3115
|
fields,
|
|
3039
3116
|
relationships,
|
|
3040
3117
|
states,
|
|
3041
|
-
initialState
|
|
3118
|
+
initialState,
|
|
3119
|
+
persistence
|
|
3042
3120
|
};
|
|
3043
3121
|
}
|
|
3044
3122
|
function formatEntityText(entity) {
|
|
3045
3123
|
const lines = [];
|
|
3046
3124
|
const article = startsWithVowel2(entity.name) ? "An" : "A";
|
|
3047
3125
|
lines.push(`${article} ${entity.name} is ${entity.description}`);
|
|
3126
|
+
if (entity.persistence !== void 0 && entity.persistence !== "persistent") {
|
|
3127
|
+
lines.push(`Persistence: ${entity.persistence}`);
|
|
3128
|
+
}
|
|
3048
3129
|
if (entity.fields.length > 0) {
|
|
3049
3130
|
lines.push("");
|
|
3050
3131
|
lines.push("It has:");
|
|
@@ -3091,6 +3172,8 @@ function formatFieldType2(field) {
|
|
|
3091
3172
|
const parts = [];
|
|
3092
3173
|
if (field.enumValues && field.enumValues.length > 0) {
|
|
3093
3174
|
parts.push(field.enumValues.join(" | "));
|
|
3175
|
+
} else if (field.fieldType === "list" && field.items) {
|
|
3176
|
+
parts.push(`list of ${field.items.type}`);
|
|
3094
3177
|
} else {
|
|
3095
3178
|
parts.push(field.fieldType);
|
|
3096
3179
|
}
|
|
@@ -3098,11 +3181,17 @@ function formatFieldType2(field) {
|
|
|
3098
3181
|
if (field.unique) parts.push("unique");
|
|
3099
3182
|
if (field.auto) parts.push("auto");
|
|
3100
3183
|
if (field.default !== void 0) {
|
|
3101
|
-
|
|
3102
|
-
parts.push(`default ${defaultStr}`);
|
|
3184
|
+
parts.push(`default ${formatDefaultValue(field.default)}`);
|
|
3103
3185
|
}
|
|
3104
3186
|
return parts.join(", ");
|
|
3105
3187
|
}
|
|
3188
|
+
function formatDefaultValue(value) {
|
|
3189
|
+
if (typeof value === "string") return `"${value}"`;
|
|
3190
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") {
|
|
3191
|
+
return String(value);
|
|
3192
|
+
}
|
|
3193
|
+
return JSON.stringify(value);
|
|
3194
|
+
}
|
|
3106
3195
|
function toSpaceSeparated3(text) {
|
|
3107
3196
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase();
|
|
3108
3197
|
}
|
|
@@ -5069,6 +5158,7 @@ function schemaTraitToDomainBehavior(trait, entityName) {
|
|
|
5069
5158
|
effects
|
|
5070
5159
|
});
|
|
5071
5160
|
}
|
|
5161
|
+
const scope = trait.scope;
|
|
5072
5162
|
return {
|
|
5073
5163
|
type: "behavior",
|
|
5074
5164
|
name: formatBehaviorName(name),
|
|
@@ -5077,13 +5167,18 @@ function schemaTraitToDomainBehavior(trait, entityName) {
|
|
|
5077
5167
|
initialState,
|
|
5078
5168
|
transitions,
|
|
5079
5169
|
ticks,
|
|
5080
|
-
rules: []
|
|
5170
|
+
rules: [],
|
|
5171
|
+
scope
|
|
5081
5172
|
};
|
|
5082
5173
|
}
|
|
5083
5174
|
function formatBehaviorText(behavior) {
|
|
5084
5175
|
const lines = [];
|
|
5085
5176
|
lines.push(behavior.name);
|
|
5086
5177
|
lines.push("");
|
|
5178
|
+
if (behavior.scope !== void 0 && behavior.scope !== "instance") {
|
|
5179
|
+
lines.push(`Scope: ${behavior.scope}`);
|
|
5180
|
+
lines.push("");
|
|
5181
|
+
}
|
|
5087
5182
|
if (behavior.states.length > 0) {
|
|
5088
5183
|
lines.push(`States: ${behavior.states.join(", ")}`);
|
|
5089
5184
|
lines.push("");
|
|
@@ -5394,7 +5489,7 @@ function parseSchemaCondition(condition, defaultEntityName) {
|
|
|
5394
5489
|
type: "comparison",
|
|
5395
5490
|
field: fieldRef,
|
|
5396
5491
|
operator: comparisonMatch[2],
|
|
5397
|
-
value:
|
|
5492
|
+
value: parseValue3(comparisonMatch[3])
|
|
5398
5493
|
};
|
|
5399
5494
|
}
|
|
5400
5495
|
}
|
|
@@ -5422,7 +5517,7 @@ function parseFieldReference2(text, defaultEntityName) {
|
|
|
5422
5517
|
}
|
|
5423
5518
|
return null;
|
|
5424
5519
|
}
|
|
5425
|
-
function
|
|
5520
|
+
function parseValue3(text) {
|
|
5426
5521
|
text = text.trim();
|
|
5427
5522
|
if (text.startsWith('"') && text.endsWith('"') || text.startsWith("'") && text.endsWith("'")) {
|
|
5428
5523
|
return text.slice(1, -1);
|
|
@@ -5796,7 +5891,7 @@ function convertDomainToSchema(domainText, baseSchema) {
|
|
|
5796
5891
|
const entity = {
|
|
5797
5892
|
name: entityRecord.name,
|
|
5798
5893
|
fields: entityRecord.fields || [],
|
|
5799
|
-
persistence: "persistent"
|
|
5894
|
+
persistence: entityRecord.persistence ?? "persistent"
|
|
5800
5895
|
};
|
|
5801
5896
|
parsedEntities.push({
|
|
5802
5897
|
name: result.data.name,
|