domaintrail 0.1.0 → 0.3.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/README.md +14 -8
- package/dist/dt.js +930 -387
- package/dist/web/chunk-s7gt31ry.css +1 -0
- package/dist/web/{chunk-kxmrt1q2.js → chunk-xn56ecvv.js} +99 -99
- package/dist/web/index.html +1 -1
- package/package.json +3 -3
- package/dist/web/chunk-qa46tqx1.css +0 -1
package/dist/dt.js
CHANGED
|
@@ -49,6 +49,9 @@ function isEventDecl(item) {
|
|
|
49
49
|
function isExistsExpr(item) {
|
|
50
50
|
return reflection.isInstance(item, ExistsExpr.$type);
|
|
51
51
|
}
|
|
52
|
+
function isFieldSet(item) {
|
|
53
|
+
return reflection.isInstance(item, FieldSet.$type);
|
|
54
|
+
}
|
|
52
55
|
function isIdType(item) {
|
|
53
56
|
return reflection.isInstance(item, IdType.$type);
|
|
54
57
|
}
|
|
@@ -103,10 +106,11 @@ function isUnionDecl(item) {
|
|
|
103
106
|
function isValueObject(item) {
|
|
104
107
|
return reflection.isInstance(item, ValueObject.$type);
|
|
105
108
|
}
|
|
106
|
-
var Aggregate, AggregateMember, BinaryExpr, BoolLiteral, Command, Context, ContextElement, CountExpr, DataMember, DecimalLiteral, Entity, EnumDecl, EnumValue, ErrorDecl, EventDecl, ExistsExpr, Expression, Field, IdType, IntLiteral, Invariant, LambdaParam, LengthExpr, MatchesExpr, MemberAccess, Model, Multiplicity, NameRef, NotExpr, OwnsField, Parameter, PrimitiveDecl, QuantifierExpr, RangeExpr, ReferenceField, State, StringLiteral, TermEntry, Terms, TypeDecl, TypeRef, UnionDecl, ValueObject, Variant, DomainAstReflection, reflection;
|
|
109
|
+
var Aggregate, AggregateMember, BinaryExpr, BoolLiteral, Command, Context, ContextElement, CountExpr, DataMember, DecimalLiteral, Entity, EnumDecl, EnumValue, ErrorDecl, EventDecl, ExistsExpr, Expression, Field, FieldSet, IdType, IntLiteral, Invariant, LambdaParam, LengthExpr, MatchesExpr, MemberAccess, Model, Multiplicity, NameRef, NotExpr, OwnsField, Parameter, PrimitiveDecl, QuantifierExpr, RangeExpr, ReferenceField, State, StringLiteral, TermEntry, Terms, Transition, TypeDecl, TypeRef, UnionDecl, ValueObject, Variant, DomainAstReflection, reflection;
|
|
107
110
|
var init_ast = __esm(() => {
|
|
108
111
|
Aggregate = {
|
|
109
112
|
$type: "Aggregate",
|
|
113
|
+
fieldSets: "fieldSets",
|
|
110
114
|
label: "label",
|
|
111
115
|
members: "members",
|
|
112
116
|
name: "name"
|
|
@@ -129,11 +133,10 @@ var init_ast = __esm(() => {
|
|
|
129
133
|
emits: "emits",
|
|
130
134
|
errors: "errors",
|
|
131
135
|
factory: "factory",
|
|
132
|
-
from: "from",
|
|
133
136
|
label: "label",
|
|
134
137
|
name: "name",
|
|
135
138
|
params: "params",
|
|
136
|
-
|
|
139
|
+
transitions: "transitions"
|
|
137
140
|
};
|
|
138
141
|
Context = {
|
|
139
142
|
$type: "Context",
|
|
@@ -160,6 +163,7 @@ var init_ast = __esm(() => {
|
|
|
160
163
|
};
|
|
161
164
|
Entity = {
|
|
162
165
|
$type: "Entity",
|
|
166
|
+
fieldSets: "fieldSets",
|
|
163
167
|
label: "label",
|
|
164
168
|
members: "members",
|
|
165
169
|
name: "name"
|
|
@@ -177,12 +181,14 @@ var init_ast = __esm(() => {
|
|
|
177
181
|
};
|
|
178
182
|
ErrorDecl = {
|
|
179
183
|
$type: "ErrorDecl",
|
|
184
|
+
fieldSets: "fieldSets",
|
|
180
185
|
label: "label",
|
|
181
186
|
members: "members",
|
|
182
187
|
name: "name"
|
|
183
188
|
};
|
|
184
189
|
EventDecl = {
|
|
185
190
|
$type: "EventDecl",
|
|
191
|
+
fieldSets: "fieldSets",
|
|
186
192
|
label: "label",
|
|
187
193
|
members: "members",
|
|
188
194
|
name: "name",
|
|
@@ -202,6 +208,13 @@ var init_ast = __esm(() => {
|
|
|
202
208
|
name: "name",
|
|
203
209
|
type: "type"
|
|
204
210
|
};
|
|
211
|
+
FieldSet = {
|
|
212
|
+
$type: "FieldSet",
|
|
213
|
+
fieldSets: "fieldSets",
|
|
214
|
+
label: "label",
|
|
215
|
+
members: "members",
|
|
216
|
+
name: "name"
|
|
217
|
+
};
|
|
205
218
|
IdType = {
|
|
206
219
|
$type: "IdType",
|
|
207
220
|
base: "base",
|
|
@@ -320,6 +333,11 @@ var init_ast = __esm(() => {
|
|
|
320
333
|
$type: "Terms",
|
|
321
334
|
entries: "entries"
|
|
322
335
|
};
|
|
336
|
+
Transition = {
|
|
337
|
+
$type: "Transition",
|
|
338
|
+
from: "from",
|
|
339
|
+
to: "to"
|
|
340
|
+
};
|
|
323
341
|
TypeDecl = {
|
|
324
342
|
$type: "TypeDecl"
|
|
325
343
|
};
|
|
@@ -338,6 +356,7 @@ var init_ast = __esm(() => {
|
|
|
338
356
|
};
|
|
339
357
|
ValueObject = {
|
|
340
358
|
$type: "ValueObject",
|
|
359
|
+
fieldSets: "fieldSets",
|
|
341
360
|
label: "label",
|
|
342
361
|
members: "members",
|
|
343
362
|
name: "name"
|
|
@@ -353,6 +372,12 @@ var init_ast = __esm(() => {
|
|
|
353
372
|
Aggregate: {
|
|
354
373
|
name: Aggregate.$type,
|
|
355
374
|
properties: {
|
|
375
|
+
fieldSets: {
|
|
376
|
+
name: Aggregate.fieldSets,
|
|
377
|
+
defaultValue: [],
|
|
378
|
+
referenceType: FieldSet.$type,
|
|
379
|
+
optional: true
|
|
380
|
+
},
|
|
356
381
|
label: {
|
|
357
382
|
name: Aggregate.label,
|
|
358
383
|
optional: true
|
|
@@ -417,12 +442,6 @@ var init_ast = __esm(() => {
|
|
|
417
442
|
defaultValue: false,
|
|
418
443
|
optional: true
|
|
419
444
|
},
|
|
420
|
-
from: {
|
|
421
|
-
name: Command.from,
|
|
422
|
-
defaultValue: [],
|
|
423
|
-
referenceType: State.$type,
|
|
424
|
-
optional: true
|
|
425
|
-
},
|
|
426
445
|
label: {
|
|
427
446
|
name: Command.label,
|
|
428
447
|
optional: true
|
|
@@ -435,10 +454,9 @@ var init_ast = __esm(() => {
|
|
|
435
454
|
defaultValue: [],
|
|
436
455
|
optional: true
|
|
437
456
|
},
|
|
438
|
-
|
|
439
|
-
name: Command.
|
|
457
|
+
transitions: {
|
|
458
|
+
name: Command.transitions,
|
|
440
459
|
defaultValue: [],
|
|
441
|
-
referenceType: State.$type,
|
|
442
460
|
optional: true
|
|
443
461
|
}
|
|
444
462
|
},
|
|
@@ -508,6 +526,12 @@ var init_ast = __esm(() => {
|
|
|
508
526
|
Entity: {
|
|
509
527
|
name: Entity.$type,
|
|
510
528
|
properties: {
|
|
529
|
+
fieldSets: {
|
|
530
|
+
name: Entity.fieldSets,
|
|
531
|
+
defaultValue: [],
|
|
532
|
+
referenceType: FieldSet.$type,
|
|
533
|
+
optional: true
|
|
534
|
+
},
|
|
511
535
|
label: {
|
|
512
536
|
name: Entity.label,
|
|
513
537
|
optional: true
|
|
@@ -557,6 +581,12 @@ var init_ast = __esm(() => {
|
|
|
557
581
|
ErrorDecl: {
|
|
558
582
|
name: ErrorDecl.$type,
|
|
559
583
|
properties: {
|
|
584
|
+
fieldSets: {
|
|
585
|
+
name: ErrorDecl.fieldSets,
|
|
586
|
+
defaultValue: [],
|
|
587
|
+
referenceType: FieldSet.$type,
|
|
588
|
+
optional: true
|
|
589
|
+
},
|
|
560
590
|
label: {
|
|
561
591
|
name: ErrorDecl.label,
|
|
562
592
|
optional: true
|
|
@@ -575,6 +605,12 @@ var init_ast = __esm(() => {
|
|
|
575
605
|
EventDecl: {
|
|
576
606
|
name: EventDecl.$type,
|
|
577
607
|
properties: {
|
|
608
|
+
fieldSets: {
|
|
609
|
+
name: EventDecl.fieldSets,
|
|
610
|
+
defaultValue: [],
|
|
611
|
+
referenceType: FieldSet.$type,
|
|
612
|
+
optional: true
|
|
613
|
+
},
|
|
578
614
|
label: {
|
|
579
615
|
name: EventDecl.label,
|
|
580
616
|
optional: true
|
|
@@ -629,6 +665,30 @@ var init_ast = __esm(() => {
|
|
|
629
665
|
},
|
|
630
666
|
superTypes: [DataMember.$type]
|
|
631
667
|
},
|
|
668
|
+
FieldSet: {
|
|
669
|
+
name: FieldSet.$type,
|
|
670
|
+
properties: {
|
|
671
|
+
fieldSets: {
|
|
672
|
+
name: FieldSet.fieldSets,
|
|
673
|
+
defaultValue: [],
|
|
674
|
+
referenceType: FieldSet.$type,
|
|
675
|
+
optional: true
|
|
676
|
+
},
|
|
677
|
+
label: {
|
|
678
|
+
name: FieldSet.label,
|
|
679
|
+
optional: true
|
|
680
|
+
},
|
|
681
|
+
members: {
|
|
682
|
+
name: FieldSet.members,
|
|
683
|
+
defaultValue: [],
|
|
684
|
+
optional: true
|
|
685
|
+
},
|
|
686
|
+
name: {
|
|
687
|
+
name: FieldSet.name
|
|
688
|
+
}
|
|
689
|
+
},
|
|
690
|
+
superTypes: [ContextElement.$type]
|
|
691
|
+
},
|
|
632
692
|
IdType: {
|
|
633
693
|
name: IdType.$type,
|
|
634
694
|
properties: {
|
|
@@ -951,6 +1011,23 @@ var init_ast = __esm(() => {
|
|
|
951
1011
|
},
|
|
952
1012
|
superTypes: []
|
|
953
1013
|
},
|
|
1014
|
+
Transition: {
|
|
1015
|
+
name: Transition.$type,
|
|
1016
|
+
properties: {
|
|
1017
|
+
from: {
|
|
1018
|
+
name: Transition.from,
|
|
1019
|
+
defaultValue: [],
|
|
1020
|
+
referenceType: State.$type,
|
|
1021
|
+
optional: true
|
|
1022
|
+
},
|
|
1023
|
+
to: {
|
|
1024
|
+
name: Transition.to,
|
|
1025
|
+
defaultValue: [],
|
|
1026
|
+
referenceType: State.$type
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
superTypes: []
|
|
1030
|
+
},
|
|
954
1031
|
TypeDecl: {
|
|
955
1032
|
name: TypeDecl.$type,
|
|
956
1033
|
properties: {},
|
|
@@ -1001,6 +1078,12 @@ var init_ast = __esm(() => {
|
|
|
1001
1078
|
ValueObject: {
|
|
1002
1079
|
name: ValueObject.$type,
|
|
1003
1080
|
properties: {
|
|
1081
|
+
fieldSets: {
|
|
1082
|
+
name: ValueObject.fieldSets,
|
|
1083
|
+
defaultValue: [],
|
|
1084
|
+
referenceType: FieldSet.$type,
|
|
1085
|
+
optional: true
|
|
1086
|
+
},
|
|
1004
1087
|
label: {
|
|
1005
1088
|
name: ValueObject.label,
|
|
1006
1089
|
optional: true
|
|
@@ -1093,7 +1176,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1093
1176
|
"terminal": {
|
|
1094
1177
|
"$type": "RuleCall",
|
|
1095
1178
|
"rule": {
|
|
1096
|
-
"$ref": "#/rules@
|
|
1179
|
+
"$ref": "#/rules@47"
|
|
1097
1180
|
},
|
|
1098
1181
|
"arguments": []
|
|
1099
1182
|
}
|
|
@@ -1105,7 +1188,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1105
1188
|
"terminal": {
|
|
1106
1189
|
"$type": "RuleCall",
|
|
1107
1190
|
"rule": {
|
|
1108
|
-
"$ref": "#/rules@
|
|
1191
|
+
"$ref": "#/rules@46"
|
|
1109
1192
|
},
|
|
1110
1193
|
"arguments": []
|
|
1111
1194
|
},
|
|
@@ -1205,7 +1288,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1205
1288
|
"terminal": {
|
|
1206
1289
|
"$type": "RuleCall",
|
|
1207
1290
|
"rule": {
|
|
1208
|
-
"$ref": "#/rules@
|
|
1291
|
+
"$ref": "#/rules@41"
|
|
1209
1292
|
},
|
|
1210
1293
|
"arguments": []
|
|
1211
1294
|
}
|
|
@@ -1221,7 +1304,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1221
1304
|
"terminal": {
|
|
1222
1305
|
"$type": "RuleCall",
|
|
1223
1306
|
"rule": {
|
|
1224
|
-
"$ref": "#/rules@
|
|
1307
|
+
"$ref": "#/rules@46"
|
|
1225
1308
|
},
|
|
1226
1309
|
"arguments": []
|
|
1227
1310
|
}
|
|
@@ -1269,35 +1352,42 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1269
1352
|
{
|
|
1270
1353
|
"$type": "RuleCall",
|
|
1271
1354
|
"rule": {
|
|
1272
|
-
"$ref": "#/rules@
|
|
1355
|
+
"$ref": "#/rules@13"
|
|
1273
1356
|
},
|
|
1274
1357
|
"arguments": []
|
|
1275
1358
|
},
|
|
1276
1359
|
{
|
|
1277
1360
|
"$type": "RuleCall",
|
|
1278
1361
|
"rule": {
|
|
1279
|
-
"$ref": "#/rules@
|
|
1362
|
+
"$ref": "#/rules@15"
|
|
1280
1363
|
},
|
|
1281
1364
|
"arguments": []
|
|
1282
1365
|
},
|
|
1283
1366
|
{
|
|
1284
1367
|
"$type": "RuleCall",
|
|
1285
1368
|
"rule": {
|
|
1286
|
-
"$ref": "#/rules@
|
|
1369
|
+
"$ref": "#/rules@16"
|
|
1287
1370
|
},
|
|
1288
1371
|
"arguments": []
|
|
1289
1372
|
},
|
|
1290
1373
|
{
|
|
1291
1374
|
"$type": "RuleCall",
|
|
1292
1375
|
"rule": {
|
|
1293
|
-
"$ref": "#/rules@
|
|
1376
|
+
"$ref": "#/rules@26"
|
|
1377
|
+
},
|
|
1378
|
+
"arguments": []
|
|
1379
|
+
},
|
|
1380
|
+
{
|
|
1381
|
+
"$type": "RuleCall",
|
|
1382
|
+
"rule": {
|
|
1383
|
+
"$ref": "#/rules@27"
|
|
1294
1384
|
},
|
|
1295
1385
|
"arguments": []
|
|
1296
1386
|
},
|
|
1297
1387
|
{
|
|
1298
1388
|
"$type": "RuleCall",
|
|
1299
1389
|
"rule": {
|
|
1300
|
-
"$ref": "#/rules@
|
|
1390
|
+
"$ref": "#/rules@11"
|
|
1301
1391
|
},
|
|
1302
1392
|
"arguments": []
|
|
1303
1393
|
}
|
|
@@ -1324,7 +1414,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1324
1414
|
"terminal": {
|
|
1325
1415
|
"$type": "RuleCall",
|
|
1326
1416
|
"rule": {
|
|
1327
|
-
"$ref": "#/rules@
|
|
1417
|
+
"$ref": "#/rules@47"
|
|
1328
1418
|
},
|
|
1329
1419
|
"arguments": []
|
|
1330
1420
|
}
|
|
@@ -1336,7 +1426,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1336
1426
|
"terminal": {
|
|
1337
1427
|
"$type": "RuleCall",
|
|
1338
1428
|
"rule": {
|
|
1339
|
-
"$ref": "#/rules@
|
|
1429
|
+
"$ref": "#/rules@46"
|
|
1340
1430
|
},
|
|
1341
1431
|
"arguments": []
|
|
1342
1432
|
},
|
|
@@ -1353,7 +1443,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1353
1443
|
"terminal": {
|
|
1354
1444
|
"$type": "RuleCall",
|
|
1355
1445
|
"rule": {
|
|
1356
|
-
"$ref": "#/rules@
|
|
1446
|
+
"$ref": "#/rules@29"
|
|
1357
1447
|
},
|
|
1358
1448
|
"arguments": []
|
|
1359
1449
|
}
|
|
@@ -1389,7 +1479,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1389
1479
|
"terminal": {
|
|
1390
1480
|
"$type": "RuleCall",
|
|
1391
1481
|
"rule": {
|
|
1392
|
-
"$ref": "#/rules@
|
|
1482
|
+
"$ref": "#/rules@47"
|
|
1393
1483
|
},
|
|
1394
1484
|
"arguments": []
|
|
1395
1485
|
}
|
|
@@ -1401,7 +1491,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1401
1491
|
"terminal": {
|
|
1402
1492
|
"$type": "RuleCall",
|
|
1403
1493
|
"rule": {
|
|
1404
|
-
"$ref": "#/rules@
|
|
1494
|
+
"$ref": "#/rules@46"
|
|
1405
1495
|
},
|
|
1406
1496
|
"arguments": []
|
|
1407
1497
|
},
|
|
@@ -1418,7 +1508,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1418
1508
|
"terminal": {
|
|
1419
1509
|
"$type": "RuleCall",
|
|
1420
1510
|
"rule": {
|
|
1421
|
-
"$ref": "#/rules@
|
|
1511
|
+
"$ref": "#/rules@29"
|
|
1422
1512
|
},
|
|
1423
1513
|
"arguments": []
|
|
1424
1514
|
}
|
|
@@ -1458,7 +1548,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1458
1548
|
"terminal": {
|
|
1459
1549
|
"$type": "RuleCall",
|
|
1460
1550
|
"rule": {
|
|
1461
|
-
"$ref": "#/rules@
|
|
1551
|
+
"$ref": "#/rules@31"
|
|
1462
1552
|
},
|
|
1463
1553
|
"arguments": []
|
|
1464
1554
|
},
|
|
@@ -1471,7 +1561,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1471
1561
|
"terminal": {
|
|
1472
1562
|
"$type": "RuleCall",
|
|
1473
1563
|
"rule": {
|
|
1474
|
-
"$ref": "#/rules@
|
|
1564
|
+
"$ref": "#/rules@32"
|
|
1475
1565
|
},
|
|
1476
1566
|
"arguments": []
|
|
1477
1567
|
}
|
|
@@ -1504,7 +1594,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1504
1594
|
"terminal": {
|
|
1505
1595
|
"$type": "RuleCall",
|
|
1506
1596
|
"rule": {
|
|
1507
|
-
"$ref": "#/rules@
|
|
1597
|
+
"$ref": "#/rules@47"
|
|
1508
1598
|
},
|
|
1509
1599
|
"arguments": []
|
|
1510
1600
|
}
|
|
@@ -1516,7 +1606,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1516
1606
|
"terminal": {
|
|
1517
1607
|
"$type": "RuleCall",
|
|
1518
1608
|
"rule": {
|
|
1519
|
-
"$ref": "#/rules@
|
|
1609
|
+
"$ref": "#/rules@46"
|
|
1520
1610
|
},
|
|
1521
1611
|
"arguments": []
|
|
1522
1612
|
},
|
|
@@ -1590,7 +1680,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1590
1680
|
"terminal": {
|
|
1591
1681
|
"$type": "RuleCall",
|
|
1592
1682
|
"rule": {
|
|
1593
|
-
"$ref": "#/rules@
|
|
1683
|
+
"$ref": "#/rules@47"
|
|
1594
1684
|
},
|
|
1595
1685
|
"arguments": []
|
|
1596
1686
|
}
|
|
@@ -1602,7 +1692,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1602
1692
|
"terminal": {
|
|
1603
1693
|
"$type": "RuleCall",
|
|
1604
1694
|
"rule": {
|
|
1605
|
-
"$ref": "#/rules@
|
|
1695
|
+
"$ref": "#/rules@46"
|
|
1606
1696
|
},
|
|
1607
1697
|
"arguments": []
|
|
1608
1698
|
},
|
|
@@ -1631,7 +1721,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1631
1721
|
"terminal": {
|
|
1632
1722
|
"$type": "RuleCall",
|
|
1633
1723
|
"rule": {
|
|
1634
|
-
"$ref": "#/rules@
|
|
1724
|
+
"$ref": "#/rules@47"
|
|
1635
1725
|
},
|
|
1636
1726
|
"arguments": []
|
|
1637
1727
|
}
|
|
@@ -1643,12 +1733,20 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1643
1733
|
"terminal": {
|
|
1644
1734
|
"$type": "RuleCall",
|
|
1645
1735
|
"rule": {
|
|
1646
|
-
"$ref": "#/rules@
|
|
1736
|
+
"$ref": "#/rules@46"
|
|
1647
1737
|
},
|
|
1648
1738
|
"arguments": []
|
|
1649
1739
|
},
|
|
1650
1740
|
"cardinality": "?"
|
|
1651
1741
|
},
|
|
1742
|
+
{
|
|
1743
|
+
"$type": "RuleCall",
|
|
1744
|
+
"rule": {
|
|
1745
|
+
"$ref": "#/rules@12"
|
|
1746
|
+
},
|
|
1747
|
+
"arguments": [],
|
|
1748
|
+
"cardinality": "?"
|
|
1749
|
+
},
|
|
1652
1750
|
{
|
|
1653
1751
|
"$type": "Group",
|
|
1654
1752
|
"elements": [
|
|
@@ -1663,7 +1761,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1663
1761
|
"terminal": {
|
|
1664
1762
|
"$type": "RuleCall",
|
|
1665
1763
|
"rule": {
|
|
1666
|
-
"$ref": "#/rules@
|
|
1764
|
+
"$ref": "#/rules@18"
|
|
1667
1765
|
},
|
|
1668
1766
|
"arguments": []
|
|
1669
1767
|
},
|
|
@@ -1682,6 +1780,142 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1682
1780
|
"fragment": false,
|
|
1683
1781
|
"parameters": []
|
|
1684
1782
|
},
|
|
1783
|
+
{
|
|
1784
|
+
"$type": "ParserRule",
|
|
1785
|
+
"name": "FieldSet",
|
|
1786
|
+
"definition": {
|
|
1787
|
+
"$type": "Group",
|
|
1788
|
+
"elements": [
|
|
1789
|
+
{
|
|
1790
|
+
"$type": "Keyword",
|
|
1791
|
+
"value": "fields"
|
|
1792
|
+
},
|
|
1793
|
+
{
|
|
1794
|
+
"$type": "Assignment",
|
|
1795
|
+
"feature": "name",
|
|
1796
|
+
"operator": "=",
|
|
1797
|
+
"terminal": {
|
|
1798
|
+
"$type": "RuleCall",
|
|
1799
|
+
"rule": {
|
|
1800
|
+
"$ref": "#/rules@47"
|
|
1801
|
+
},
|
|
1802
|
+
"arguments": []
|
|
1803
|
+
}
|
|
1804
|
+
},
|
|
1805
|
+
{
|
|
1806
|
+
"$type": "Assignment",
|
|
1807
|
+
"feature": "label",
|
|
1808
|
+
"operator": "=",
|
|
1809
|
+
"terminal": {
|
|
1810
|
+
"$type": "RuleCall",
|
|
1811
|
+
"rule": {
|
|
1812
|
+
"$ref": "#/rules@46"
|
|
1813
|
+
},
|
|
1814
|
+
"arguments": []
|
|
1815
|
+
},
|
|
1816
|
+
"cardinality": "?"
|
|
1817
|
+
},
|
|
1818
|
+
{
|
|
1819
|
+
"$type": "RuleCall",
|
|
1820
|
+
"rule": {
|
|
1821
|
+
"$ref": "#/rules@12"
|
|
1822
|
+
},
|
|
1823
|
+
"arguments": [],
|
|
1824
|
+
"cardinality": "?"
|
|
1825
|
+
},
|
|
1826
|
+
{
|
|
1827
|
+
"$type": "Keyword",
|
|
1828
|
+
"value": "{"
|
|
1829
|
+
},
|
|
1830
|
+
{
|
|
1831
|
+
"$type": "Assignment",
|
|
1832
|
+
"feature": "members",
|
|
1833
|
+
"operator": "+=",
|
|
1834
|
+
"terminal": {
|
|
1835
|
+
"$type": "RuleCall",
|
|
1836
|
+
"rule": {
|
|
1837
|
+
"$ref": "#/rules@18"
|
|
1838
|
+
},
|
|
1839
|
+
"arguments": []
|
|
1840
|
+
},
|
|
1841
|
+
"cardinality": "*"
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
"$type": "Keyword",
|
|
1845
|
+
"value": "}"
|
|
1846
|
+
}
|
|
1847
|
+
]
|
|
1848
|
+
},
|
|
1849
|
+
"entry": false,
|
|
1850
|
+
"fragment": false,
|
|
1851
|
+
"parameters": []
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
"$type": "ParserRule",
|
|
1855
|
+
"fragment": true,
|
|
1856
|
+
"name": "WithFieldSets",
|
|
1857
|
+
"definition": {
|
|
1858
|
+
"$type": "Group",
|
|
1859
|
+
"elements": [
|
|
1860
|
+
{
|
|
1861
|
+
"$type": "Keyword",
|
|
1862
|
+
"value": "with"
|
|
1863
|
+
},
|
|
1864
|
+
{
|
|
1865
|
+
"$type": "Assignment",
|
|
1866
|
+
"feature": "fieldSets",
|
|
1867
|
+
"operator": "+=",
|
|
1868
|
+
"terminal": {
|
|
1869
|
+
"$type": "CrossReference",
|
|
1870
|
+
"type": {
|
|
1871
|
+
"$ref": "#/rules@11"
|
|
1872
|
+
},
|
|
1873
|
+
"terminal": {
|
|
1874
|
+
"$type": "RuleCall",
|
|
1875
|
+
"rule": {
|
|
1876
|
+
"$ref": "#/rules@42"
|
|
1877
|
+
},
|
|
1878
|
+
"arguments": []
|
|
1879
|
+
},
|
|
1880
|
+
"deprecatedSyntax": false,
|
|
1881
|
+
"isMulti": false
|
|
1882
|
+
}
|
|
1883
|
+
},
|
|
1884
|
+
{
|
|
1885
|
+
"$type": "Group",
|
|
1886
|
+
"elements": [
|
|
1887
|
+
{
|
|
1888
|
+
"$type": "Keyword",
|
|
1889
|
+
"value": ","
|
|
1890
|
+
},
|
|
1891
|
+
{
|
|
1892
|
+
"$type": "Assignment",
|
|
1893
|
+
"feature": "fieldSets",
|
|
1894
|
+
"operator": "+=",
|
|
1895
|
+
"terminal": {
|
|
1896
|
+
"$type": "CrossReference",
|
|
1897
|
+
"type": {
|
|
1898
|
+
"$ref": "#/rules@11"
|
|
1899
|
+
},
|
|
1900
|
+
"terminal": {
|
|
1901
|
+
"$type": "RuleCall",
|
|
1902
|
+
"rule": {
|
|
1903
|
+
"$ref": "#/rules@42"
|
|
1904
|
+
},
|
|
1905
|
+
"arguments": []
|
|
1906
|
+
},
|
|
1907
|
+
"deprecatedSyntax": false,
|
|
1908
|
+
"isMulti": false
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
],
|
|
1912
|
+
"cardinality": "*"
|
|
1913
|
+
}
|
|
1914
|
+
]
|
|
1915
|
+
},
|
|
1916
|
+
"entry": false,
|
|
1917
|
+
"parameters": []
|
|
1918
|
+
},
|
|
1685
1919
|
{
|
|
1686
1920
|
"$type": "ParserRule",
|
|
1687
1921
|
"name": "UnionDecl",
|
|
@@ -1699,7 +1933,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1699
1933
|
"terminal": {
|
|
1700
1934
|
"$type": "RuleCall",
|
|
1701
1935
|
"rule": {
|
|
1702
|
-
"$ref": "#/rules@
|
|
1936
|
+
"$ref": "#/rules@47"
|
|
1703
1937
|
},
|
|
1704
1938
|
"arguments": []
|
|
1705
1939
|
}
|
|
@@ -1711,7 +1945,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1711
1945
|
"terminal": {
|
|
1712
1946
|
"$type": "RuleCall",
|
|
1713
1947
|
"rule": {
|
|
1714
|
-
"$ref": "#/rules@
|
|
1948
|
+
"$ref": "#/rules@46"
|
|
1715
1949
|
},
|
|
1716
1950
|
"arguments": []
|
|
1717
1951
|
},
|
|
@@ -1731,7 +1965,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1731
1965
|
"terminal": {
|
|
1732
1966
|
"$type": "RuleCall",
|
|
1733
1967
|
"rule": {
|
|
1734
|
-
"$ref": "#/rules@
|
|
1968
|
+
"$ref": "#/rules@41"
|
|
1735
1969
|
},
|
|
1736
1970
|
"arguments": []
|
|
1737
1971
|
}
|
|
@@ -1755,7 +1989,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1755
1989
|
"terminal": {
|
|
1756
1990
|
"$type": "RuleCall",
|
|
1757
1991
|
"rule": {
|
|
1758
|
-
"$ref": "#/rules@
|
|
1992
|
+
"$ref": "#/rules@42"
|
|
1759
1993
|
},
|
|
1760
1994
|
"arguments": []
|
|
1761
1995
|
},
|
|
@@ -1780,7 +2014,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1780
2014
|
"terminal": {
|
|
1781
2015
|
"$type": "RuleCall",
|
|
1782
2016
|
"rule": {
|
|
1783
|
-
"$ref": "#/rules@
|
|
2017
|
+
"$ref": "#/rules@14"
|
|
1784
2018
|
},
|
|
1785
2019
|
"arguments": []
|
|
1786
2020
|
},
|
|
@@ -1809,7 +2043,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1809
2043
|
"terminal": {
|
|
1810
2044
|
"$type": "RuleCall",
|
|
1811
2045
|
"rule": {
|
|
1812
|
-
"$ref": "#/rules@
|
|
2046
|
+
"$ref": "#/rules@47"
|
|
1813
2047
|
},
|
|
1814
2048
|
"arguments": []
|
|
1815
2049
|
}
|
|
@@ -1821,7 +2055,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1821
2055
|
"terminal": {
|
|
1822
2056
|
"$type": "RuleCall",
|
|
1823
2057
|
"rule": {
|
|
1824
|
-
"$ref": "#/rules@
|
|
2058
|
+
"$ref": "#/rules@46"
|
|
1825
2059
|
},
|
|
1826
2060
|
"arguments": []
|
|
1827
2061
|
},
|
|
@@ -1841,7 +2075,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1841
2075
|
"terminal": {
|
|
1842
2076
|
"$type": "RuleCall",
|
|
1843
2077
|
"rule": {
|
|
1844
|
-
"$ref": "#/rules@
|
|
2078
|
+
"$ref": "#/rules@18"
|
|
1845
2079
|
},
|
|
1846
2080
|
"arguments": []
|
|
1847
2081
|
},
|
|
@@ -1877,7 +2111,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1877
2111
|
"terminal": {
|
|
1878
2112
|
"$type": "RuleCall",
|
|
1879
2113
|
"rule": {
|
|
1880
|
-
"$ref": "#/rules@
|
|
2114
|
+
"$ref": "#/rules@47"
|
|
1881
2115
|
},
|
|
1882
2116
|
"arguments": []
|
|
1883
2117
|
}
|
|
@@ -1889,12 +2123,20 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1889
2123
|
"terminal": {
|
|
1890
2124
|
"$type": "RuleCall",
|
|
1891
2125
|
"rule": {
|
|
1892
|
-
"$ref": "#/rules@
|
|
2126
|
+
"$ref": "#/rules@46"
|
|
1893
2127
|
},
|
|
1894
2128
|
"arguments": []
|
|
1895
2129
|
},
|
|
1896
2130
|
"cardinality": "?"
|
|
1897
2131
|
},
|
|
2132
|
+
{
|
|
2133
|
+
"$type": "RuleCall",
|
|
2134
|
+
"rule": {
|
|
2135
|
+
"$ref": "#/rules@12"
|
|
2136
|
+
},
|
|
2137
|
+
"arguments": [],
|
|
2138
|
+
"cardinality": "?"
|
|
2139
|
+
},
|
|
1898
2140
|
{
|
|
1899
2141
|
"$type": "Keyword",
|
|
1900
2142
|
"value": "{"
|
|
@@ -1906,7 +2148,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1906
2148
|
"terminal": {
|
|
1907
2149
|
"$type": "RuleCall",
|
|
1908
2150
|
"rule": {
|
|
1909
|
-
"$ref": "#/rules@
|
|
2151
|
+
"$ref": "#/rules@18"
|
|
1910
2152
|
},
|
|
1911
2153
|
"arguments": []
|
|
1912
2154
|
},
|
|
@@ -1939,7 +2181,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1939
2181
|
"terminal": {
|
|
1940
2182
|
"$type": "RuleCall",
|
|
1941
2183
|
"rule": {
|
|
1942
|
-
"$ref": "#/rules@
|
|
2184
|
+
"$ref": "#/rules@47"
|
|
1943
2185
|
},
|
|
1944
2186
|
"arguments": []
|
|
1945
2187
|
}
|
|
@@ -1951,12 +2193,20 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1951
2193
|
"terminal": {
|
|
1952
2194
|
"$type": "RuleCall",
|
|
1953
2195
|
"rule": {
|
|
1954
|
-
"$ref": "#/rules@
|
|
2196
|
+
"$ref": "#/rules@46"
|
|
1955
2197
|
},
|
|
1956
2198
|
"arguments": []
|
|
1957
2199
|
},
|
|
1958
2200
|
"cardinality": "?"
|
|
1959
2201
|
},
|
|
2202
|
+
{
|
|
2203
|
+
"$type": "RuleCall",
|
|
2204
|
+
"rule": {
|
|
2205
|
+
"$ref": "#/rules@12"
|
|
2206
|
+
},
|
|
2207
|
+
"arguments": [],
|
|
2208
|
+
"cardinality": "?"
|
|
2209
|
+
},
|
|
1960
2210
|
{
|
|
1961
2211
|
"$type": "Keyword",
|
|
1962
2212
|
"value": "{"
|
|
@@ -1968,7 +2218,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1968
2218
|
"terminal": {
|
|
1969
2219
|
"$type": "RuleCall",
|
|
1970
2220
|
"rule": {
|
|
1971
|
-
"$ref": "#/rules@
|
|
2221
|
+
"$ref": "#/rules@17"
|
|
1972
2222
|
},
|
|
1973
2223
|
"arguments": []
|
|
1974
2224
|
},
|
|
@@ -1993,21 +2243,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1993
2243
|
{
|
|
1994
2244
|
"$type": "RuleCall",
|
|
1995
2245
|
"rule": {
|
|
1996
|
-
"$ref": "#/rules@
|
|
2246
|
+
"$ref": "#/rules@18"
|
|
1997
2247
|
},
|
|
1998
2248
|
"arguments": []
|
|
1999
2249
|
},
|
|
2000
2250
|
{
|
|
2001
2251
|
"$type": "RuleCall",
|
|
2002
2252
|
"rule": {
|
|
2003
|
-
"$ref": "#/rules@
|
|
2253
|
+
"$ref": "#/rules@19"
|
|
2004
2254
|
},
|
|
2005
2255
|
"arguments": []
|
|
2006
2256
|
},
|
|
2007
2257
|
{
|
|
2008
2258
|
"$type": "RuleCall",
|
|
2009
2259
|
"rule": {
|
|
2010
|
-
"$ref": "#/rules@
|
|
2260
|
+
"$ref": "#/rules@23"
|
|
2011
2261
|
},
|
|
2012
2262
|
"arguments": []
|
|
2013
2263
|
}
|
|
@@ -2026,28 +2276,28 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2026
2276
|
{
|
|
2027
2277
|
"$type": "RuleCall",
|
|
2028
2278
|
"rule": {
|
|
2029
|
-
"$ref": "#/rules@
|
|
2279
|
+
"$ref": "#/rules@20"
|
|
2030
2280
|
},
|
|
2031
2281
|
"arguments": []
|
|
2032
2282
|
},
|
|
2033
2283
|
{
|
|
2034
2284
|
"$type": "RuleCall",
|
|
2035
2285
|
"rule": {
|
|
2036
|
-
"$ref": "#/rules@
|
|
2286
|
+
"$ref": "#/rules@21"
|
|
2037
2287
|
},
|
|
2038
2288
|
"arguments": []
|
|
2039
2289
|
},
|
|
2040
2290
|
{
|
|
2041
2291
|
"$type": "RuleCall",
|
|
2042
2292
|
"rule": {
|
|
2043
|
-
"$ref": "#/rules@
|
|
2293
|
+
"$ref": "#/rules@22"
|
|
2044
2294
|
},
|
|
2045
2295
|
"arguments": []
|
|
2046
2296
|
},
|
|
2047
2297
|
{
|
|
2048
2298
|
"$type": "RuleCall",
|
|
2049
2299
|
"rule": {
|
|
2050
|
-
"$ref": "#/rules@
|
|
2300
|
+
"$ref": "#/rules@31"
|
|
2051
2301
|
},
|
|
2052
2302
|
"arguments": []
|
|
2053
2303
|
}
|
|
@@ -2074,7 +2324,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2074
2324
|
"terminal": {
|
|
2075
2325
|
"$type": "RuleCall",
|
|
2076
2326
|
"rule": {
|
|
2077
|
-
"$ref": "#/rules@
|
|
2327
|
+
"$ref": "#/rules@47"
|
|
2078
2328
|
},
|
|
2079
2329
|
"arguments": []
|
|
2080
2330
|
}
|
|
@@ -2086,7 +2336,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2086
2336
|
"terminal": {
|
|
2087
2337
|
"$type": "RuleCall",
|
|
2088
2338
|
"rule": {
|
|
2089
|
-
"$ref": "#/rules@
|
|
2339
|
+
"$ref": "#/rules@46"
|
|
2090
2340
|
},
|
|
2091
2341
|
"arguments": []
|
|
2092
2342
|
},
|
|
@@ -2106,7 +2356,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2106
2356
|
"terminal": {
|
|
2107
2357
|
"$type": "RuleCall",
|
|
2108
2358
|
"rule": {
|
|
2109
|
-
"$ref": "#/rules@
|
|
2359
|
+
"$ref": "#/rules@18"
|
|
2110
2360
|
},
|
|
2111
2361
|
"arguments": []
|
|
2112
2362
|
},
|
|
@@ -2138,7 +2388,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2138
2388
|
"terminal": {
|
|
2139
2389
|
"$type": "RuleCall",
|
|
2140
2390
|
"rule": {
|
|
2141
|
-
"$ref": "#/rules@
|
|
2391
|
+
"$ref": "#/rules@41"
|
|
2142
2392
|
},
|
|
2143
2393
|
"arguments": []
|
|
2144
2394
|
}
|
|
@@ -2154,7 +2404,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2154
2404
|
"terminal": {
|
|
2155
2405
|
"$type": "RuleCall",
|
|
2156
2406
|
"rule": {
|
|
2157
|
-
"$ref": "#/rules@
|
|
2407
|
+
"$ref": "#/rules@28"
|
|
2158
2408
|
},
|
|
2159
2409
|
"arguments": []
|
|
2160
2410
|
}
|
|
@@ -2166,7 +2416,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2166
2416
|
"terminal": {
|
|
2167
2417
|
"$type": "RuleCall",
|
|
2168
2418
|
"rule": {
|
|
2169
|
-
"$ref": "#/rules@
|
|
2419
|
+
"$ref": "#/rules@30"
|
|
2170
2420
|
},
|
|
2171
2421
|
"arguments": []
|
|
2172
2422
|
},
|
|
@@ -2179,7 +2429,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2179
2429
|
"terminal": {
|
|
2180
2430
|
"$type": "RuleCall",
|
|
2181
2431
|
"rule": {
|
|
2182
|
-
"$ref": "#/rules@
|
|
2432
|
+
"$ref": "#/rules@46"
|
|
2183
2433
|
},
|
|
2184
2434
|
"arguments": []
|
|
2185
2435
|
},
|
|
@@ -2208,7 +2458,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2208
2458
|
"terminal": {
|
|
2209
2459
|
"$type": "RuleCall",
|
|
2210
2460
|
"rule": {
|
|
2211
|
-
"$ref": "#/rules@
|
|
2461
|
+
"$ref": "#/rules@41"
|
|
2212
2462
|
},
|
|
2213
2463
|
"arguments": []
|
|
2214
2464
|
}
|
|
@@ -2224,7 +2474,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2224
2474
|
"terminal": {
|
|
2225
2475
|
"$type": "RuleCall",
|
|
2226
2476
|
"rule": {
|
|
2227
|
-
"$ref": "#/rules@
|
|
2477
|
+
"$ref": "#/rules@28"
|
|
2228
2478
|
},
|
|
2229
2479
|
"arguments": []
|
|
2230
2480
|
}
|
|
@@ -2236,7 +2486,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2236
2486
|
"terminal": {
|
|
2237
2487
|
"$type": "RuleCall",
|
|
2238
2488
|
"rule": {
|
|
2239
|
-
"$ref": "#/rules@
|
|
2489
|
+
"$ref": "#/rules@30"
|
|
2240
2490
|
},
|
|
2241
2491
|
"arguments": []
|
|
2242
2492
|
},
|
|
@@ -2249,7 +2499,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2249
2499
|
"terminal": {
|
|
2250
2500
|
"$type": "RuleCall",
|
|
2251
2501
|
"rule": {
|
|
2252
|
-
"$ref": "#/rules@
|
|
2502
|
+
"$ref": "#/rules@46"
|
|
2253
2503
|
},
|
|
2254
2504
|
"arguments": []
|
|
2255
2505
|
},
|
|
@@ -2278,7 +2528,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2278
2528
|
"terminal": {
|
|
2279
2529
|
"$type": "RuleCall",
|
|
2280
2530
|
"rule": {
|
|
2281
|
-
"$ref": "#/rules@
|
|
2531
|
+
"$ref": "#/rules@41"
|
|
2282
2532
|
},
|
|
2283
2533
|
"arguments": []
|
|
2284
2534
|
}
|
|
@@ -2294,7 +2544,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2294
2544
|
"terminal": {
|
|
2295
2545
|
"$type": "RuleCall",
|
|
2296
2546
|
"rule": {
|
|
2297
|
-
"$ref": "#/rules@
|
|
2547
|
+
"$ref": "#/rules@28"
|
|
2298
2548
|
},
|
|
2299
2549
|
"arguments": []
|
|
2300
2550
|
}
|
|
@@ -2306,7 +2556,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2306
2556
|
"terminal": {
|
|
2307
2557
|
"$type": "RuleCall",
|
|
2308
2558
|
"rule": {
|
|
2309
|
-
"$ref": "#/rules@
|
|
2559
|
+
"$ref": "#/rules@30"
|
|
2310
2560
|
},
|
|
2311
2561
|
"arguments": []
|
|
2312
2562
|
},
|
|
@@ -2323,12 +2573,12 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2323
2573
|
"terminal": {
|
|
2324
2574
|
"$type": "CrossReference",
|
|
2325
2575
|
"type": {
|
|
2326
|
-
"$ref": "#/rules@
|
|
2576
|
+
"$ref": "#/rules@16"
|
|
2327
2577
|
},
|
|
2328
2578
|
"terminal": {
|
|
2329
2579
|
"$type": "RuleCall",
|
|
2330
2580
|
"rule": {
|
|
2331
|
-
"$ref": "#/rules@
|
|
2581
|
+
"$ref": "#/rules@42"
|
|
2332
2582
|
},
|
|
2333
2583
|
"arguments": []
|
|
2334
2584
|
},
|
|
@@ -2343,7 +2593,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2343
2593
|
"terminal": {
|
|
2344
2594
|
"$type": "RuleCall",
|
|
2345
2595
|
"rule": {
|
|
2346
|
-
"$ref": "#/rules@
|
|
2596
|
+
"$ref": "#/rules@46"
|
|
2347
2597
|
},
|
|
2348
2598
|
"arguments": []
|
|
2349
2599
|
},
|
|
@@ -2382,7 +2632,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2382
2632
|
"terminal": {
|
|
2383
2633
|
"$type": "RuleCall",
|
|
2384
2634
|
"rule": {
|
|
2385
|
-
"$ref": "#/rules@
|
|
2635
|
+
"$ref": "#/rules@41"
|
|
2386
2636
|
},
|
|
2387
2637
|
"arguments": []
|
|
2388
2638
|
}
|
|
@@ -2401,7 +2651,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2401
2651
|
"terminal": {
|
|
2402
2652
|
"$type": "RuleCall",
|
|
2403
2653
|
"rule": {
|
|
2404
|
-
"$ref": "#/rules@
|
|
2654
|
+
"$ref": "#/rules@25"
|
|
2405
2655
|
},
|
|
2406
2656
|
"arguments": []
|
|
2407
2657
|
}
|
|
@@ -2420,7 +2670,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2420
2670
|
"terminal": {
|
|
2421
2671
|
"$type": "RuleCall",
|
|
2422
2672
|
"rule": {
|
|
2423
|
-
"$ref": "#/rules@
|
|
2673
|
+
"$ref": "#/rules@25"
|
|
2424
2674
|
},
|
|
2425
2675
|
"arguments": []
|
|
2426
2676
|
}
|
|
@@ -2442,7 +2692,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2442
2692
|
"terminal": {
|
|
2443
2693
|
"$type": "RuleCall",
|
|
2444
2694
|
"rule": {
|
|
2445
|
-
"$ref": "#/rules@
|
|
2695
|
+
"$ref": "#/rules@46"
|
|
2446
2696
|
},
|
|
2447
2697
|
"arguments": []
|
|
2448
2698
|
},
|
|
@@ -2451,28 +2701,16 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2451
2701
|
{
|
|
2452
2702
|
"$type": "Group",
|
|
2453
2703
|
"elements": [
|
|
2454
|
-
{
|
|
2455
|
-
"$type": "Keyword",
|
|
2456
|
-
"value": "from"
|
|
2457
|
-
},
|
|
2458
2704
|
{
|
|
2459
2705
|
"$type": "Assignment",
|
|
2460
|
-
"feature": "
|
|
2706
|
+
"feature": "transitions",
|
|
2461
2707
|
"operator": "+=",
|
|
2462
2708
|
"terminal": {
|
|
2463
|
-
"$type": "
|
|
2464
|
-
"
|
|
2465
|
-
"$ref": "#/rules@
|
|
2466
|
-
},
|
|
2467
|
-
"terminal": {
|
|
2468
|
-
"$type": "RuleCall",
|
|
2469
|
-
"rule": {
|
|
2470
|
-
"$ref": "#/rules@44"
|
|
2471
|
-
},
|
|
2472
|
-
"arguments": []
|
|
2709
|
+
"$type": "RuleCall",
|
|
2710
|
+
"rule": {
|
|
2711
|
+
"$ref": "#/rules@24"
|
|
2473
2712
|
},
|
|
2474
|
-
"
|
|
2475
|
-
"isMulti": false
|
|
2713
|
+
"arguments": []
|
|
2476
2714
|
}
|
|
2477
2715
|
},
|
|
2478
2716
|
{
|
|
@@ -2480,26 +2718,19 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2480
2718
|
"elements": [
|
|
2481
2719
|
{
|
|
2482
2720
|
"$type": "Keyword",
|
|
2483
|
-
"value": "
|
|
2721
|
+
"value": ",",
|
|
2722
|
+
"cardinality": "?"
|
|
2484
2723
|
},
|
|
2485
2724
|
{
|
|
2486
2725
|
"$type": "Assignment",
|
|
2487
|
-
"feature": "
|
|
2726
|
+
"feature": "transitions",
|
|
2488
2727
|
"operator": "+=",
|
|
2489
2728
|
"terminal": {
|
|
2490
|
-
"$type": "
|
|
2491
|
-
"
|
|
2492
|
-
"$ref": "#/rules@
|
|
2493
|
-
},
|
|
2494
|
-
"terminal": {
|
|
2495
|
-
"$type": "RuleCall",
|
|
2496
|
-
"rule": {
|
|
2497
|
-
"$ref": "#/rules@44"
|
|
2498
|
-
},
|
|
2499
|
-
"arguments": []
|
|
2729
|
+
"$type": "RuleCall",
|
|
2730
|
+
"rule": {
|
|
2731
|
+
"$ref": "#/rules@24"
|
|
2500
2732
|
},
|
|
2501
|
-
"
|
|
2502
|
-
"isMulti": false
|
|
2733
|
+
"arguments": []
|
|
2503
2734
|
}
|
|
2504
2735
|
}
|
|
2505
2736
|
],
|
|
@@ -2513,21 +2744,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2513
2744
|
"elements": [
|
|
2514
2745
|
{
|
|
2515
2746
|
"$type": "Keyword",
|
|
2516
|
-
"value": "
|
|
2747
|
+
"value": "emits"
|
|
2517
2748
|
},
|
|
2518
2749
|
{
|
|
2519
2750
|
"$type": "Assignment",
|
|
2520
|
-
"feature": "
|
|
2751
|
+
"feature": "emits",
|
|
2521
2752
|
"operator": "+=",
|
|
2522
2753
|
"terminal": {
|
|
2523
2754
|
"$type": "CrossReference",
|
|
2524
2755
|
"type": {
|
|
2525
|
-
"$ref": "#/rules@
|
|
2756
|
+
"$ref": "#/rules@26"
|
|
2526
2757
|
},
|
|
2527
2758
|
"terminal": {
|
|
2528
2759
|
"$type": "RuleCall",
|
|
2529
2760
|
"rule": {
|
|
2530
|
-
"$ref": "#/rules@
|
|
2761
|
+
"$ref": "#/rules@42"
|
|
2531
2762
|
},
|
|
2532
2763
|
"arguments": []
|
|
2533
2764
|
},
|
|
@@ -2540,21 +2771,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2540
2771
|
"elements": [
|
|
2541
2772
|
{
|
|
2542
2773
|
"$type": "Keyword",
|
|
2543
|
-
"value": "
|
|
2774
|
+
"value": ","
|
|
2544
2775
|
},
|
|
2545
2776
|
{
|
|
2546
2777
|
"$type": "Assignment",
|
|
2547
|
-
"feature": "
|
|
2778
|
+
"feature": "emits",
|
|
2548
2779
|
"operator": "+=",
|
|
2549
2780
|
"terminal": {
|
|
2550
2781
|
"$type": "CrossReference",
|
|
2551
2782
|
"type": {
|
|
2552
|
-
"$ref": "#/rules@
|
|
2783
|
+
"$ref": "#/rules@26"
|
|
2553
2784
|
},
|
|
2554
2785
|
"terminal": {
|
|
2555
2786
|
"$type": "RuleCall",
|
|
2556
2787
|
"rule": {
|
|
2557
|
-
"$ref": "#/rules@
|
|
2788
|
+
"$ref": "#/rules@42"
|
|
2558
2789
|
},
|
|
2559
2790
|
"arguments": []
|
|
2560
2791
|
},
|
|
@@ -2573,21 +2804,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2573
2804
|
"elements": [
|
|
2574
2805
|
{
|
|
2575
2806
|
"$type": "Keyword",
|
|
2576
|
-
"value": "
|
|
2807
|
+
"value": "errors"
|
|
2577
2808
|
},
|
|
2578
2809
|
{
|
|
2579
2810
|
"$type": "Assignment",
|
|
2580
|
-
"feature": "
|
|
2811
|
+
"feature": "errors",
|
|
2581
2812
|
"operator": "+=",
|
|
2582
2813
|
"terminal": {
|
|
2583
2814
|
"$type": "CrossReference",
|
|
2584
2815
|
"type": {
|
|
2585
|
-
"$ref": "#/rules@
|
|
2816
|
+
"$ref": "#/rules@27"
|
|
2586
2817
|
},
|
|
2587
2818
|
"terminal": {
|
|
2588
2819
|
"$type": "RuleCall",
|
|
2589
2820
|
"rule": {
|
|
2590
|
-
"$ref": "#/rules@
|
|
2821
|
+
"$ref": "#/rules@42"
|
|
2591
2822
|
},
|
|
2592
2823
|
"arguments": []
|
|
2593
2824
|
},
|
|
@@ -2604,17 +2835,17 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2604
2835
|
},
|
|
2605
2836
|
{
|
|
2606
2837
|
"$type": "Assignment",
|
|
2607
|
-
"feature": "
|
|
2838
|
+
"feature": "errors",
|
|
2608
2839
|
"operator": "+=",
|
|
2609
2840
|
"terminal": {
|
|
2610
2841
|
"$type": "CrossReference",
|
|
2611
2842
|
"type": {
|
|
2612
|
-
"$ref": "#/rules@
|
|
2843
|
+
"$ref": "#/rules@27"
|
|
2613
2844
|
},
|
|
2614
2845
|
"terminal": {
|
|
2615
2846
|
"$type": "RuleCall",
|
|
2616
2847
|
"rule": {
|
|
2617
|
-
"$ref": "#/rules@
|
|
2848
|
+
"$ref": "#/rules@42"
|
|
2618
2849
|
},
|
|
2619
2850
|
"arguments": []
|
|
2620
2851
|
},
|
|
@@ -2627,27 +2858,35 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2627
2858
|
}
|
|
2628
2859
|
],
|
|
2629
2860
|
"cardinality": "?"
|
|
2630
|
-
}
|
|
2861
|
+
}
|
|
2862
|
+
]
|
|
2863
|
+
},
|
|
2864
|
+
"entry": false,
|
|
2865
|
+
"fragment": false,
|
|
2866
|
+
"parameters": []
|
|
2867
|
+
},
|
|
2868
|
+
{
|
|
2869
|
+
"$type": "ParserRule",
|
|
2870
|
+
"name": "Transition",
|
|
2871
|
+
"definition": {
|
|
2872
|
+
"$type": "Group",
|
|
2873
|
+
"elements": [
|
|
2631
2874
|
{
|
|
2632
2875
|
"$type": "Group",
|
|
2633
2876
|
"elements": [
|
|
2634
|
-
{
|
|
2635
|
-
"$type": "Keyword",
|
|
2636
|
-
"value": "errors"
|
|
2637
|
-
},
|
|
2638
2877
|
{
|
|
2639
2878
|
"$type": "Assignment",
|
|
2640
|
-
"feature": "
|
|
2879
|
+
"feature": "from",
|
|
2641
2880
|
"operator": "+=",
|
|
2642
2881
|
"terminal": {
|
|
2643
2882
|
"$type": "CrossReference",
|
|
2644
2883
|
"type": {
|
|
2645
|
-
"$ref": "#/rules@
|
|
2884
|
+
"$ref": "#/rules@19"
|
|
2646
2885
|
},
|
|
2647
2886
|
"terminal": {
|
|
2648
2887
|
"$type": "RuleCall",
|
|
2649
2888
|
"rule": {
|
|
2650
|
-
"$ref": "#/rules@
|
|
2889
|
+
"$ref": "#/rules@47"
|
|
2651
2890
|
},
|
|
2652
2891
|
"arguments": []
|
|
2653
2892
|
},
|
|
@@ -2660,21 +2899,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2660
2899
|
"elements": [
|
|
2661
2900
|
{
|
|
2662
2901
|
"$type": "Keyword",
|
|
2663
|
-
"value": "
|
|
2902
|
+
"value": "|"
|
|
2664
2903
|
},
|
|
2665
2904
|
{
|
|
2666
2905
|
"$type": "Assignment",
|
|
2667
|
-
"feature": "
|
|
2906
|
+
"feature": "from",
|
|
2668
2907
|
"operator": "+=",
|
|
2669
2908
|
"terminal": {
|
|
2670
2909
|
"$type": "CrossReference",
|
|
2671
2910
|
"type": {
|
|
2672
|
-
"$ref": "#/rules@
|
|
2911
|
+
"$ref": "#/rules@19"
|
|
2673
2912
|
},
|
|
2674
2913
|
"terminal": {
|
|
2675
2914
|
"$type": "RuleCall",
|
|
2676
2915
|
"rule": {
|
|
2677
|
-
"$ref": "#/rules@
|
|
2916
|
+
"$ref": "#/rules@47"
|
|
2678
2917
|
},
|
|
2679
2918
|
"arguments": []
|
|
2680
2919
|
},
|
|
@@ -2687,6 +2926,60 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2687
2926
|
}
|
|
2688
2927
|
],
|
|
2689
2928
|
"cardinality": "?"
|
|
2929
|
+
},
|
|
2930
|
+
{
|
|
2931
|
+
"$type": "Keyword",
|
|
2932
|
+
"value": "->"
|
|
2933
|
+
},
|
|
2934
|
+
{
|
|
2935
|
+
"$type": "Assignment",
|
|
2936
|
+
"feature": "to",
|
|
2937
|
+
"operator": "+=",
|
|
2938
|
+
"terminal": {
|
|
2939
|
+
"$type": "CrossReference",
|
|
2940
|
+
"type": {
|
|
2941
|
+
"$ref": "#/rules@19"
|
|
2942
|
+
},
|
|
2943
|
+
"terminal": {
|
|
2944
|
+
"$type": "RuleCall",
|
|
2945
|
+
"rule": {
|
|
2946
|
+
"$ref": "#/rules@47"
|
|
2947
|
+
},
|
|
2948
|
+
"arguments": []
|
|
2949
|
+
},
|
|
2950
|
+
"deprecatedSyntax": false,
|
|
2951
|
+
"isMulti": false
|
|
2952
|
+
}
|
|
2953
|
+
},
|
|
2954
|
+
{
|
|
2955
|
+
"$type": "Group",
|
|
2956
|
+
"elements": [
|
|
2957
|
+
{
|
|
2958
|
+
"$type": "Keyword",
|
|
2959
|
+
"value": "|"
|
|
2960
|
+
},
|
|
2961
|
+
{
|
|
2962
|
+
"$type": "Assignment",
|
|
2963
|
+
"feature": "to",
|
|
2964
|
+
"operator": "+=",
|
|
2965
|
+
"terminal": {
|
|
2966
|
+
"$type": "CrossReference",
|
|
2967
|
+
"type": {
|
|
2968
|
+
"$ref": "#/rules@19"
|
|
2969
|
+
},
|
|
2970
|
+
"terminal": {
|
|
2971
|
+
"$type": "RuleCall",
|
|
2972
|
+
"rule": {
|
|
2973
|
+
"$ref": "#/rules@47"
|
|
2974
|
+
},
|
|
2975
|
+
"arguments": []
|
|
2976
|
+
},
|
|
2977
|
+
"deprecatedSyntax": false,
|
|
2978
|
+
"isMulti": false
|
|
2979
|
+
}
|
|
2980
|
+
}
|
|
2981
|
+
],
|
|
2982
|
+
"cardinality": "*"
|
|
2690
2983
|
}
|
|
2691
2984
|
]
|
|
2692
2985
|
},
|
|
@@ -2707,7 +3000,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2707
3000
|
"terminal": {
|
|
2708
3001
|
"$type": "RuleCall",
|
|
2709
3002
|
"rule": {
|
|
2710
|
-
"$ref": "#/rules@
|
|
3003
|
+
"$ref": "#/rules@41"
|
|
2711
3004
|
},
|
|
2712
3005
|
"arguments": []
|
|
2713
3006
|
}
|
|
@@ -2723,7 +3016,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2723
3016
|
"terminal": {
|
|
2724
3017
|
"$type": "RuleCall",
|
|
2725
3018
|
"rule": {
|
|
2726
|
-
"$ref": "#/rules@
|
|
3019
|
+
"$ref": "#/rules@28"
|
|
2727
3020
|
},
|
|
2728
3021
|
"arguments": []
|
|
2729
3022
|
}
|
|
@@ -2735,7 +3028,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2735
3028
|
"terminal": {
|
|
2736
3029
|
"$type": "RuleCall",
|
|
2737
3030
|
"rule": {
|
|
2738
|
-
"$ref": "#/rules@
|
|
3031
|
+
"$ref": "#/rules@30"
|
|
2739
3032
|
},
|
|
2740
3033
|
"arguments": []
|
|
2741
3034
|
},
|
|
@@ -2748,7 +3041,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2748
3041
|
"terminal": {
|
|
2749
3042
|
"$type": "RuleCall",
|
|
2750
3043
|
"rule": {
|
|
2751
|
-
"$ref": "#/rules@
|
|
3044
|
+
"$ref": "#/rules@46"
|
|
2752
3045
|
},
|
|
2753
3046
|
"arguments": []
|
|
2754
3047
|
},
|
|
@@ -2787,7 +3080,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2787
3080
|
"terminal": {
|
|
2788
3081
|
"$type": "RuleCall",
|
|
2789
3082
|
"rule": {
|
|
2790
|
-
"$ref": "#/rules@
|
|
3083
|
+
"$ref": "#/rules@47"
|
|
2791
3084
|
},
|
|
2792
3085
|
"arguments": []
|
|
2793
3086
|
}
|
|
@@ -2799,12 +3092,20 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2799
3092
|
"terminal": {
|
|
2800
3093
|
"$type": "RuleCall",
|
|
2801
3094
|
"rule": {
|
|
2802
|
-
"$ref": "#/rules@
|
|
3095
|
+
"$ref": "#/rules@46"
|
|
2803
3096
|
},
|
|
2804
3097
|
"arguments": []
|
|
2805
3098
|
},
|
|
2806
3099
|
"cardinality": "?"
|
|
2807
3100
|
},
|
|
3101
|
+
{
|
|
3102
|
+
"$type": "RuleCall",
|
|
3103
|
+
"rule": {
|
|
3104
|
+
"$ref": "#/rules@12"
|
|
3105
|
+
},
|
|
3106
|
+
"arguments": [],
|
|
3107
|
+
"cardinality": "?"
|
|
3108
|
+
},
|
|
2808
3109
|
{
|
|
2809
3110
|
"$type": "Group",
|
|
2810
3111
|
"elements": [
|
|
@@ -2819,7 +3120,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2819
3120
|
"terminal": {
|
|
2820
3121
|
"$type": "RuleCall",
|
|
2821
3122
|
"rule": {
|
|
2822
|
-
"$ref": "#/rules@
|
|
3123
|
+
"$ref": "#/rules@20"
|
|
2823
3124
|
},
|
|
2824
3125
|
"arguments": []
|
|
2825
3126
|
},
|
|
@@ -2855,7 +3156,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2855
3156
|
"terminal": {
|
|
2856
3157
|
"$type": "RuleCall",
|
|
2857
3158
|
"rule": {
|
|
2858
|
-
"$ref": "#/rules@
|
|
3159
|
+
"$ref": "#/rules@47"
|
|
2859
3160
|
},
|
|
2860
3161
|
"arguments": []
|
|
2861
3162
|
}
|
|
@@ -2867,12 +3168,20 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2867
3168
|
"terminal": {
|
|
2868
3169
|
"$type": "RuleCall",
|
|
2869
3170
|
"rule": {
|
|
2870
|
-
"$ref": "#/rules@
|
|
3171
|
+
"$ref": "#/rules@46"
|
|
2871
3172
|
},
|
|
2872
3173
|
"arguments": []
|
|
2873
3174
|
},
|
|
2874
3175
|
"cardinality": "?"
|
|
2875
3176
|
},
|
|
3177
|
+
{
|
|
3178
|
+
"$type": "RuleCall",
|
|
3179
|
+
"rule": {
|
|
3180
|
+
"$ref": "#/rules@12"
|
|
3181
|
+
},
|
|
3182
|
+
"arguments": [],
|
|
3183
|
+
"cardinality": "?"
|
|
3184
|
+
},
|
|
2876
3185
|
{
|
|
2877
3186
|
"$type": "Group",
|
|
2878
3187
|
"elements": [
|
|
@@ -2887,7 +3196,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2887
3196
|
"terminal": {
|
|
2888
3197
|
"$type": "RuleCall",
|
|
2889
3198
|
"rule": {
|
|
2890
|
-
"$ref": "#/rules@
|
|
3199
|
+
"$ref": "#/rules@20"
|
|
2891
3200
|
},
|
|
2892
3201
|
"arguments": []
|
|
2893
3202
|
},
|
|
@@ -2919,7 +3228,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2919
3228
|
"terminal": {
|
|
2920
3229
|
"$type": "RuleCall",
|
|
2921
3230
|
"rule": {
|
|
2922
|
-
"$ref": "#/rules@
|
|
3231
|
+
"$ref": "#/rules@29"
|
|
2923
3232
|
},
|
|
2924
3233
|
"arguments": []
|
|
2925
3234
|
}
|
|
@@ -2936,7 +3245,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2936
3245
|
"terminal": {
|
|
2937
3246
|
"$type": "RuleCall",
|
|
2938
3247
|
"rule": {
|
|
2939
|
-
"$ref": "#/rules@
|
|
3248
|
+
"$ref": "#/rules@42"
|
|
2940
3249
|
},
|
|
2941
3250
|
"arguments": []
|
|
2942
3251
|
},
|
|
@@ -3016,7 +3325,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3016
3325
|
"terminal": {
|
|
3017
3326
|
"$type": "RuleCall",
|
|
3018
3327
|
"rule": {
|
|
3019
|
-
"$ref": "#/rules@
|
|
3328
|
+
"$ref": "#/rules@45"
|
|
3020
3329
|
},
|
|
3021
3330
|
"arguments": []
|
|
3022
3331
|
}
|
|
@@ -3035,7 +3344,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3035
3344
|
"terminal": {
|
|
3036
3345
|
"$type": "RuleCall",
|
|
3037
3346
|
"rule": {
|
|
3038
|
-
"$ref": "#/rules@
|
|
3347
|
+
"$ref": "#/rules@45"
|
|
3039
3348
|
},
|
|
3040
3349
|
"arguments": []
|
|
3041
3350
|
}
|
|
@@ -3080,7 +3389,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3080
3389
|
"terminal": {
|
|
3081
3390
|
"$type": "RuleCall",
|
|
3082
3391
|
"rule": {
|
|
3083
|
-
"$ref": "#/rules@
|
|
3392
|
+
"$ref": "#/rules@47"
|
|
3084
3393
|
},
|
|
3085
3394
|
"arguments": []
|
|
3086
3395
|
}
|
|
@@ -3092,7 +3401,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3092
3401
|
"terminal": {
|
|
3093
3402
|
"$type": "RuleCall",
|
|
3094
3403
|
"rule": {
|
|
3095
|
-
"$ref": "#/rules@
|
|
3404
|
+
"$ref": "#/rules@46"
|
|
3096
3405
|
},
|
|
3097
3406
|
"arguments": []
|
|
3098
3407
|
},
|
|
@@ -3109,7 +3418,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3109
3418
|
"terminal": {
|
|
3110
3419
|
"$type": "RuleCall",
|
|
3111
3420
|
"rule": {
|
|
3112
|
-
"$ref": "#/rules@
|
|
3421
|
+
"$ref": "#/rules@32"
|
|
3113
3422
|
},
|
|
3114
3423
|
"arguments": []
|
|
3115
3424
|
}
|
|
@@ -3130,7 +3439,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3130
3439
|
"definition": {
|
|
3131
3440
|
"$type": "RuleCall",
|
|
3132
3441
|
"rule": {
|
|
3133
|
-
"$ref": "#/rules@
|
|
3442
|
+
"$ref": "#/rules@33"
|
|
3134
3443
|
},
|
|
3135
3444
|
"arguments": []
|
|
3136
3445
|
},
|
|
@@ -3151,7 +3460,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3151
3460
|
{
|
|
3152
3461
|
"$type": "RuleCall",
|
|
3153
3462
|
"rule": {
|
|
3154
|
-
"$ref": "#/rules@
|
|
3463
|
+
"$ref": "#/rules@34"
|
|
3155
3464
|
},
|
|
3156
3465
|
"arguments": []
|
|
3157
3466
|
},
|
|
@@ -3183,7 +3492,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3183
3492
|
"terminal": {
|
|
3184
3493
|
"$type": "RuleCall",
|
|
3185
3494
|
"rule": {
|
|
3186
|
-
"$ref": "#/rules@
|
|
3495
|
+
"$ref": "#/rules@34"
|
|
3187
3496
|
},
|
|
3188
3497
|
"arguments": []
|
|
3189
3498
|
}
|
|
@@ -3210,7 +3519,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3210
3519
|
{
|
|
3211
3520
|
"$type": "RuleCall",
|
|
3212
3521
|
"rule": {
|
|
3213
|
-
"$ref": "#/rules@
|
|
3522
|
+
"$ref": "#/rules@35"
|
|
3214
3523
|
},
|
|
3215
3524
|
"arguments": []
|
|
3216
3525
|
},
|
|
@@ -3242,7 +3551,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3242
3551
|
"terminal": {
|
|
3243
3552
|
"$type": "RuleCall",
|
|
3244
3553
|
"rule": {
|
|
3245
|
-
"$ref": "#/rules@
|
|
3554
|
+
"$ref": "#/rules@35"
|
|
3246
3555
|
},
|
|
3247
3556
|
"arguments": []
|
|
3248
3557
|
}
|
|
@@ -3269,7 +3578,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3269
3578
|
{
|
|
3270
3579
|
"$type": "RuleCall",
|
|
3271
3580
|
"rule": {
|
|
3272
|
-
"$ref": "#/rules@
|
|
3581
|
+
"$ref": "#/rules@36"
|
|
3273
3582
|
},
|
|
3274
3583
|
"arguments": []
|
|
3275
3584
|
},
|
|
@@ -3301,7 +3610,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3301
3610
|
"terminal": {
|
|
3302
3611
|
"$type": "RuleCall",
|
|
3303
3612
|
"rule": {
|
|
3304
|
-
"$ref": "#/rules@
|
|
3613
|
+
"$ref": "#/rules@36"
|
|
3305
3614
|
},
|
|
3306
3615
|
"arguments": []
|
|
3307
3616
|
}
|
|
@@ -3328,7 +3637,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3328
3637
|
{
|
|
3329
3638
|
"$type": "RuleCall",
|
|
3330
3639
|
"rule": {
|
|
3331
|
-
"$ref": "#/rules@
|
|
3640
|
+
"$ref": "#/rules@37"
|
|
3332
3641
|
},
|
|
3333
3642
|
"arguments": []
|
|
3334
3643
|
},
|
|
@@ -3388,7 +3697,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3388
3697
|
"terminal": {
|
|
3389
3698
|
"$type": "RuleCall",
|
|
3390
3699
|
"rule": {
|
|
3391
|
-
"$ref": "#/rules@
|
|
3700
|
+
"$ref": "#/rules@37"
|
|
3392
3701
|
},
|
|
3393
3702
|
"arguments": []
|
|
3394
3703
|
}
|
|
@@ -3418,7 +3727,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3418
3727
|
"terminal": {
|
|
3419
3728
|
"$type": "RuleCall",
|
|
3420
3729
|
"rule": {
|
|
3421
|
-
"$ref": "#/rules@
|
|
3730
|
+
"$ref": "#/rules@37"
|
|
3422
3731
|
},
|
|
3423
3732
|
"arguments": []
|
|
3424
3733
|
}
|
|
@@ -3434,7 +3743,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3434
3743
|
"terminal": {
|
|
3435
3744
|
"$type": "RuleCall",
|
|
3436
3745
|
"rule": {
|
|
3437
|
-
"$ref": "#/rules@
|
|
3746
|
+
"$ref": "#/rules@37"
|
|
3438
3747
|
},
|
|
3439
3748
|
"arguments": []
|
|
3440
3749
|
}
|
|
@@ -3481,7 +3790,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3481
3790
|
"terminal": {
|
|
3482
3791
|
"$type": "RuleCall",
|
|
3483
3792
|
"rule": {
|
|
3484
|
-
"$ref": "#/rules@
|
|
3793
|
+
"$ref": "#/rules@37"
|
|
3485
3794
|
},
|
|
3486
3795
|
"arguments": []
|
|
3487
3796
|
}
|
|
@@ -3491,7 +3800,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3491
3800
|
{
|
|
3492
3801
|
"$type": "RuleCall",
|
|
3493
3802
|
"rule": {
|
|
3494
|
-
"$ref": "#/rules@
|
|
3803
|
+
"$ref": "#/rules@38"
|
|
3495
3804
|
},
|
|
3496
3805
|
"arguments": []
|
|
3497
3806
|
}
|
|
@@ -3514,7 +3823,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3514
3823
|
{
|
|
3515
3824
|
"$type": "RuleCall",
|
|
3516
3825
|
"rule": {
|
|
3517
|
-
"$ref": "#/rules@
|
|
3826
|
+
"$ref": "#/rules@39"
|
|
3518
3827
|
},
|
|
3519
3828
|
"arguments": []
|
|
3520
3829
|
},
|
|
@@ -3541,7 +3850,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3541
3850
|
"terminal": {
|
|
3542
3851
|
"$type": "RuleCall",
|
|
3543
3852
|
"rule": {
|
|
3544
|
-
"$ref": "#/rules@
|
|
3853
|
+
"$ref": "#/rules@41"
|
|
3545
3854
|
},
|
|
3546
3855
|
"arguments": []
|
|
3547
3856
|
}
|
|
@@ -3575,7 +3884,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3575
3884
|
{
|
|
3576
3885
|
"$type": "RuleCall",
|
|
3577
3886
|
"rule": {
|
|
3578
|
-
"$ref": "#/rules@
|
|
3887
|
+
"$ref": "#/rules@32"
|
|
3579
3888
|
},
|
|
3580
3889
|
"arguments": []
|
|
3581
3890
|
},
|
|
@@ -3610,7 +3919,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3610
3919
|
"terminal": {
|
|
3611
3920
|
"$type": "RuleCall",
|
|
3612
3921
|
"rule": {
|
|
3613
|
-
"$ref": "#/rules@
|
|
3922
|
+
"$ref": "#/rules@32"
|
|
3614
3923
|
},
|
|
3615
3924
|
"arguments": []
|
|
3616
3925
|
}
|
|
@@ -3646,7 +3955,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3646
3955
|
"terminal": {
|
|
3647
3956
|
"$type": "RuleCall",
|
|
3648
3957
|
"rule": {
|
|
3649
|
-
"$ref": "#/rules@
|
|
3958
|
+
"$ref": "#/rules@32"
|
|
3650
3959
|
},
|
|
3651
3960
|
"arguments": []
|
|
3652
3961
|
}
|
|
@@ -3682,7 +3991,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3682
3991
|
"terminal": {
|
|
3683
3992
|
"$type": "RuleCall",
|
|
3684
3993
|
"rule": {
|
|
3685
|
-
"$ref": "#/rules@
|
|
3994
|
+
"$ref": "#/rules@32"
|
|
3686
3995
|
},
|
|
3687
3996
|
"arguments": []
|
|
3688
3997
|
}
|
|
@@ -3718,7 +4027,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3718
4027
|
"terminal": {
|
|
3719
4028
|
"$type": "RuleCall",
|
|
3720
4029
|
"rule": {
|
|
3721
|
-
"$ref": "#/rules@
|
|
4030
|
+
"$ref": "#/rules@32"
|
|
3722
4031
|
},
|
|
3723
4032
|
"arguments": []
|
|
3724
4033
|
}
|
|
@@ -3734,7 +4043,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3734
4043
|
"terminal": {
|
|
3735
4044
|
"$type": "RuleCall",
|
|
3736
4045
|
"rule": {
|
|
3737
|
-
"$ref": "#/rules@
|
|
4046
|
+
"$ref": "#/rules@46"
|
|
3738
4047
|
},
|
|
3739
4048
|
"arguments": []
|
|
3740
4049
|
}
|
|
@@ -3784,7 +4093,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3784
4093
|
"terminal": {
|
|
3785
4094
|
"$type": "RuleCall",
|
|
3786
4095
|
"rule": {
|
|
3787
|
-
"$ref": "#/rules@
|
|
4096
|
+
"$ref": "#/rules@32"
|
|
3788
4097
|
},
|
|
3789
4098
|
"arguments": []
|
|
3790
4099
|
}
|
|
@@ -3800,7 +4109,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3800
4109
|
"terminal": {
|
|
3801
4110
|
"$type": "RuleCall",
|
|
3802
4111
|
"rule": {
|
|
3803
|
-
"$ref": "#/rules@
|
|
4112
|
+
"$ref": "#/rules@40"
|
|
3804
4113
|
},
|
|
3805
4114
|
"arguments": []
|
|
3806
4115
|
}
|
|
@@ -3816,7 +4125,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3816
4125
|
"terminal": {
|
|
3817
4126
|
"$type": "RuleCall",
|
|
3818
4127
|
"rule": {
|
|
3819
|
-
"$ref": "#/rules@
|
|
4128
|
+
"$ref": "#/rules@32"
|
|
3820
4129
|
},
|
|
3821
4130
|
"arguments": []
|
|
3822
4131
|
}
|
|
@@ -3884,7 +4193,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3884
4193
|
"terminal": {
|
|
3885
4194
|
"$type": "RuleCall",
|
|
3886
4195
|
"rule": {
|
|
3887
|
-
"$ref": "#/rules@
|
|
4196
|
+
"$ref": "#/rules@44"
|
|
3888
4197
|
},
|
|
3889
4198
|
"arguments": []
|
|
3890
4199
|
}
|
|
@@ -3918,7 +4227,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3918
4227
|
"terminal": {
|
|
3919
4228
|
"$type": "RuleCall",
|
|
3920
4229
|
"rule": {
|
|
3921
|
-
"$ref": "#/rules@
|
|
4230
|
+
"$ref": "#/rules@45"
|
|
3922
4231
|
},
|
|
3923
4232
|
"arguments": []
|
|
3924
4233
|
}
|
|
@@ -3942,7 +4251,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3942
4251
|
"terminal": {
|
|
3943
4252
|
"$type": "RuleCall",
|
|
3944
4253
|
"rule": {
|
|
3945
|
-
"$ref": "#/rules@
|
|
4254
|
+
"$ref": "#/rules@46"
|
|
3946
4255
|
},
|
|
3947
4256
|
"arguments": []
|
|
3948
4257
|
}
|
|
@@ -3966,7 +4275,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3966
4275
|
"terminal": {
|
|
3967
4276
|
"$type": "RuleCall",
|
|
3968
4277
|
"rule": {
|
|
3969
|
-
"$ref": "#/rules@
|
|
4278
|
+
"$ref": "#/rules@41"
|
|
3970
4279
|
},
|
|
3971
4280
|
"arguments": []
|
|
3972
4281
|
}
|
|
@@ -3989,7 +4298,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3989
4298
|
"terminal": {
|
|
3990
4299
|
"$type": "RuleCall",
|
|
3991
4300
|
"rule": {
|
|
3992
|
-
"$ref": "#/rules@
|
|
4301
|
+
"$ref": "#/rules@41"
|
|
3993
4302
|
},
|
|
3994
4303
|
"arguments": []
|
|
3995
4304
|
}
|
|
@@ -4008,7 +4317,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4008
4317
|
{
|
|
4009
4318
|
"$type": "RuleCall",
|
|
4010
4319
|
"rule": {
|
|
4011
|
-
"$ref": "#/rules@
|
|
4320
|
+
"$ref": "#/rules@47"
|
|
4012
4321
|
},
|
|
4013
4322
|
"arguments": []
|
|
4014
4323
|
},
|
|
@@ -4027,6 +4336,14 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4027
4336
|
{
|
|
4028
4337
|
"$type": "Keyword",
|
|
4029
4338
|
"value": "persistent"
|
|
4339
|
+
},
|
|
4340
|
+
{
|
|
4341
|
+
"$type": "Keyword",
|
|
4342
|
+
"value": "fields"
|
|
4343
|
+
},
|
|
4344
|
+
{
|
|
4345
|
+
"$type": "Keyword",
|
|
4346
|
+
"value": "with"
|
|
4030
4347
|
}
|
|
4031
4348
|
]
|
|
4032
4349
|
},
|
|
@@ -4044,7 +4361,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4044
4361
|
{
|
|
4045
4362
|
"$type": "RuleCall",
|
|
4046
4363
|
"rule": {
|
|
4047
|
-
"$ref": "#/rules@
|
|
4364
|
+
"$ref": "#/rules@47"
|
|
4048
4365
|
},
|
|
4049
4366
|
"arguments": []
|
|
4050
4367
|
},
|
|
@@ -4058,7 +4375,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4058
4375
|
{
|
|
4059
4376
|
"$type": "RuleCall",
|
|
4060
4377
|
"rule": {
|
|
4061
|
-
"$ref": "#/rules@
|
|
4378
|
+
"$ref": "#/rules@47"
|
|
4062
4379
|
},
|
|
4063
4380
|
"arguments": []
|
|
4064
4381
|
}
|
|
@@ -4191,19 +4508,19 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4191
4508
|
{
|
|
4192
4509
|
"$type": "SimpleType",
|
|
4193
4510
|
"typeRef": {
|
|
4194
|
-
"$ref": "#/rules@
|
|
4511
|
+
"$ref": "#/rules@13"
|
|
4195
4512
|
}
|
|
4196
4513
|
},
|
|
4197
4514
|
{
|
|
4198
4515
|
"$type": "SimpleType",
|
|
4199
4516
|
"typeRef": {
|
|
4200
|
-
"$ref": "#/rules@
|
|
4517
|
+
"$ref": "#/rules@15"
|
|
4201
4518
|
}
|
|
4202
4519
|
},
|
|
4203
4520
|
{
|
|
4204
4521
|
"$type": "SimpleType",
|
|
4205
4522
|
"typeRef": {
|
|
4206
|
-
"$ref": "#/rules@
|
|
4523
|
+
"$ref": "#/rules@16"
|
|
4207
4524
|
}
|
|
4208
4525
|
}
|
|
4209
4526
|
]
|
|
@@ -4555,6 +4872,17 @@ class ModelIndex {
|
|
|
4555
4872
|
get errors() {
|
|
4556
4873
|
return this.elements.filter(isErrorDecl);
|
|
4557
4874
|
}
|
|
4875
|
+
get fieldSets() {
|
|
4876
|
+
return this.elements.filter(isFieldSet);
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4879
|
+
function fieldSetsOf(el) {
|
|
4880
|
+
return [...new Set(el.fieldSets.map((r) => r.ref).filter((f) => !!f))];
|
|
4881
|
+
}
|
|
4882
|
+
function includedFields(el) {
|
|
4883
|
+
if (isFieldSet(el))
|
|
4884
|
+
return [];
|
|
4885
|
+
return fieldSetsOf(el).flatMap((fieldSet) => fieldsOf(fieldSet.members).map((field) => ({ field, fieldSet })));
|
|
4558
4886
|
}
|
|
4559
4887
|
function primitiveInvariants(p) {
|
|
4560
4888
|
if (p.constraint)
|
|
@@ -4613,6 +4941,11 @@ function buildModel(index, fileOf) {
|
|
|
4613
4941
|
line: (node.$cstNode?.range.start.line ?? 0) + 1,
|
|
4614
4942
|
endLine: (node.$cstNode?.range.end.line ?? 0) + 1
|
|
4615
4943
|
});
|
|
4944
|
+
const included = (el) => includedFields(el).map(({ field: f, fieldSet }) => ({ ...field(f), fieldSet: elementId(fieldSet.$container.name, fieldSet.name) }));
|
|
4945
|
+
const withFieldSets = (el) => {
|
|
4946
|
+
const sets = fieldSetsOf(el);
|
|
4947
|
+
return sets.length && !isFieldSet(el) ? { fieldSets: sets.map((s) => elementId(s.$container.name, s.name)) } : {};
|
|
4948
|
+
};
|
|
4616
4949
|
for (const el of index.elements) {
|
|
4617
4950
|
const id = elementId(el.$container.name, el.name);
|
|
4618
4951
|
if (elements[id])
|
|
@@ -4656,14 +4989,16 @@ function buildModel(index, fileOf) {
|
|
|
4656
4989
|
};
|
|
4657
4990
|
});
|
|
4658
4991
|
} else if (isAggregate(el)) {
|
|
4659
|
-
base
|
|
4992
|
+
Object.assign(base, withFieldSets(el));
|
|
4993
|
+
base.fields = [...included(el), ...commonFields(el).map(field)];
|
|
4660
4994
|
base.invariants = invariantsOf(el.members).map(invariant);
|
|
4661
4995
|
base.states = statesOf(el).map((s) => state(id, s, loc, field));
|
|
4662
4996
|
base.commands = commandsOf(el).map((c) => command(id, c, loc, field));
|
|
4663
4997
|
} else {
|
|
4998
|
+
Object.assign(base, withFieldSets(el));
|
|
4664
4999
|
if (isEventDecl(el) && el.persistent)
|
|
4665
5000
|
base.persistent = true;
|
|
4666
|
-
base.fields = fieldsOf(el.members).map(field);
|
|
5001
|
+
base.fields = [...included(el), ...fieldsOf(el.members).map(field)];
|
|
4667
5002
|
base.invariants = invariantsOf(el.members).map(invariant);
|
|
4668
5003
|
}
|
|
4669
5004
|
elements[id] = base;
|
|
@@ -4704,6 +5039,8 @@ function kindOf(el) {
|
|
|
4704
5039
|
return "event";
|
|
4705
5040
|
if (isErrorDecl(el))
|
|
4706
5041
|
return "error";
|
|
5042
|
+
if (isFieldSet(el))
|
|
5043
|
+
return "fieldSet";
|
|
4707
5044
|
throw new Error(`unknown element ${el.$type}`);
|
|
4708
5045
|
}
|
|
4709
5046
|
function typeExpr(ref) {
|
|
@@ -4765,55 +5102,293 @@ function command(aggId, c, loc, field) {
|
|
|
4765
5102
|
...described(c),
|
|
4766
5103
|
factory: c.factory,
|
|
4767
5104
|
params: c.params.map(field),
|
|
4768
|
-
|
|
4769
|
-
to: c.to.map((r) => r.$refText),
|
|
5105
|
+
transitions: c.transitions.map((t) => ({ from: t.from.map((r) => r.$refText), to: t.to.map((r) => r.$refText) })),
|
|
4770
5106
|
emits: c.emits.map(qname),
|
|
4771
5107
|
errors: c.errors.map(qname),
|
|
4772
5108
|
location: loc(c)
|
|
4773
5109
|
};
|
|
4774
5110
|
}
|
|
4775
|
-
var optional = (key, value) => value ? { [key]: value } : {}, sourceText = (e) => e?.$cstNode?.text.replace(/\s+/g, " ").trim() ?? "";
|
|
4776
|
-
var init_build = __esm(() => {
|
|
5111
|
+
var optional = (key, value) => value ? { [key]: value } : {}, sourceText = (e) => e?.$cstNode?.text.replace(/\s+/g, " ").trim() ?? "";
|
|
5112
|
+
var init_build = __esm(() => {
|
|
5113
|
+
init_ast();
|
|
5114
|
+
init_labels();
|
|
5115
|
+
init_types();
|
|
5116
|
+
init_model_index();
|
|
5117
|
+
init_ids();
|
|
5118
|
+
});
|
|
5119
|
+
|
|
5120
|
+
// src/core/checker/commands.ts
|
|
5121
|
+
function checkCommands(index, sink) {
|
|
5122
|
+
for (const agg of index.aggregates) {
|
|
5123
|
+
const stateful = statesOf(agg).length > 0;
|
|
5124
|
+
for (const cmd of commandsOf(agg)) {
|
|
5125
|
+
const label = `${cmd.factory ? "Factory command" : "Command"} '${cmd.name}'`;
|
|
5126
|
+
if (!stateful) {
|
|
5127
|
+
if (cmd.transitions.length > 0) {
|
|
5128
|
+
sink.error("M006", `${label} declares state transitions, but aggregate '${agg.name}' has no states.`, cmd, "transitions", 0);
|
|
5129
|
+
}
|
|
5130
|
+
continue;
|
|
5131
|
+
}
|
|
5132
|
+
if (cmd.factory) {
|
|
5133
|
+
if (cmd.transitions.length !== 1) {
|
|
5134
|
+
sink.error("M006", `${label} must declare exactly one transition to its initial state(s), e.g. '-> Draft'.`, cmd, cmd.transitions.length ? "transitions" : "name", cmd.transitions.length ? 1 : undefined);
|
|
5135
|
+
}
|
|
5136
|
+
cmd.transitions.forEach((t) => {
|
|
5137
|
+
if (t.from.length > 0)
|
|
5138
|
+
sink.error("M006", `${label} creates a new '${agg.name}' and cannot have source states; write '-> ${t.to.map((r) => r.$refText).join(" | ")}'.`, t, "from");
|
|
5139
|
+
});
|
|
5140
|
+
} else {
|
|
5141
|
+
if (cmd.transitions.length === 0) {
|
|
5142
|
+
sink.error("M006", `${label} must declare its state transitions, e.g. 'Draft -> Submitted' (or be declared with 'create command').`, cmd, "name");
|
|
5143
|
+
}
|
|
5144
|
+
cmd.transitions.forEach((t) => {
|
|
5145
|
+
if (t.from.length === 0)
|
|
5146
|
+
sink.error("M006", `${label} has a transition without source states; write 'State -> ...' (only a 'create command' starts with '->').`, t);
|
|
5147
|
+
});
|
|
5148
|
+
}
|
|
5149
|
+
const sources = new Set;
|
|
5150
|
+
for (const t of cmd.transitions) {
|
|
5151
|
+
t.from.forEach((r, i) => {
|
|
5152
|
+
if (sources.has(r.$refText)) {
|
|
5153
|
+
sink.error("M006", `State '${r.$refText}' is the source of more than one transition of command '${cmd.name}'; its outcome must be decided by one transition (use 'A -> B | C').`, t, "from", i);
|
|
5154
|
+
}
|
|
5155
|
+
sources.add(r.$refText);
|
|
5156
|
+
});
|
|
5157
|
+
const targets = new Set;
|
|
5158
|
+
t.to.forEach((r, i) => {
|
|
5159
|
+
if (targets.has(r.$refText))
|
|
5160
|
+
sink.warning("M006", `State '${r.$refText}' is listed more than once.`, t, "to", i);
|
|
5161
|
+
targets.add(r.$refText);
|
|
5162
|
+
});
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5165
|
+
}
|
|
5166
|
+
}
|
|
5167
|
+
var init_commands = __esm(() => {
|
|
5168
|
+
init_model_index();
|
|
5169
|
+
});
|
|
5170
|
+
|
|
5171
|
+
// src/generator/naming.ts
|
|
5172
|
+
function generatedNames(index, ctx) {
|
|
5173
|
+
const out = [];
|
|
5174
|
+
const seen = new Set;
|
|
5175
|
+
for (const el of index.elementsOf(ctx)) {
|
|
5176
|
+
if (seen.has(el.name))
|
|
5177
|
+
continue;
|
|
5178
|
+
seen.add(el.name);
|
|
5179
|
+
if (!isAggregate(el)) {
|
|
5180
|
+
out.push({ name: el.name, origin: `${KIND_LABELS[el.$type]} '${el.name}'`, node: el });
|
|
5181
|
+
if (isIdType(el) || isPrimitiveDecl(el)) {
|
|
5182
|
+
out.push({ name: makeTypeName(el), origin: `the constructor of '${el.name}'`, node: el });
|
|
5183
|
+
if (primitiveInvariants(el).length)
|
|
5184
|
+
out.push({ name: invalidTypeName(el), origin: `the error of '${el.name}'`, node: el });
|
|
5185
|
+
}
|
|
5186
|
+
continue;
|
|
5187
|
+
}
|
|
5188
|
+
const states = firstByName(statesOf(el));
|
|
5189
|
+
out.push({ name: el.name, origin: `aggregate '${el.name}'`, node: el });
|
|
5190
|
+
if (states.length > 0) {
|
|
5191
|
+
out.push({ name: commonTypeName(el), origin: `common fields of '${el.name}'`, node: el });
|
|
5192
|
+
for (const s of states) {
|
|
5193
|
+
out.push({ name: stateTypeName(el, s), origin: `state '${el.name}.${s.name}'`, node: s });
|
|
5194
|
+
}
|
|
5195
|
+
}
|
|
5196
|
+
const commands = firstByName(commandsOf(el));
|
|
5197
|
+
if (commands.length > 0) {
|
|
5198
|
+
out.push({ name: commandsInterfaceName(el), origin: `commands of '${el.name}'`, node: el });
|
|
5199
|
+
}
|
|
5200
|
+
for (const c of commands) {
|
|
5201
|
+
out.push({ name: commandTypeName(el, c), origin: `command '${el.name}.${c.name}'`, node: c });
|
|
5202
|
+
if (states.length > 0 && targetsVary(c.factory, c.transitions.map((t) => t.to.map((r) => r.$refText)))) {
|
|
5203
|
+
out.push({ name: byStateTypeName(el, c), origin: `the handlers per state of '${el.name}.${c.name}'`, node: c });
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
if (commands.some((c) => c.emits.length > 0)) {
|
|
5207
|
+
out.push({ name: aggregateEventTypeName(el), origin: `the union of the events of '${el.name}'`, node: el });
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
const persistent = index.elementsOf(ctx).find((el) => isEventDecl(el) && el.persistent);
|
|
5211
|
+
if (persistent)
|
|
5212
|
+
out.push({ name: PERSISTENT_EVENT_TYPE, origin: "the union of persistent events", node: persistent });
|
|
5213
|
+
const event = index.elementsOf(ctx).find(isEventDecl);
|
|
5214
|
+
if (event)
|
|
5215
|
+
out.push({ name: DOMAIN_EVENT_TYPE, origin: "the union of the events", node: event });
|
|
5216
|
+
const aggregate = index.elementsOf(ctx).find(isAggregate);
|
|
5217
|
+
if (aggregate)
|
|
5218
|
+
out.push({ name: AGGREGATE_TYPE, origin: "the union of the aggregates", node: aggregate });
|
|
5219
|
+
return out;
|
|
5220
|
+
}
|
|
5221
|
+
function firstByName(items) {
|
|
5222
|
+
const seen = new Set;
|
|
5223
|
+
return items.filter((i) => !seen.has(i.name) && seen.add(i.name));
|
|
5224
|
+
}
|
|
5225
|
+
var RUNTIME_NAMES, EVENT_TAG = "type", STATE_TAG = "state", pascal = (s) => s.charAt(0).toUpperCase() + s.slice(1), camel = (s) => s.charAt(0).toLowerCase() + s.slice(1), commonTypeName = (agg) => `${agg.name}Common`, stateTypeName = (agg, state) => `${typeof state === "string" ? state : state.name}${agg.name}`, commandTypeName = (agg, cmd) => `${pascal(cmd.name)}${agg.name}`, commandsInterfaceName = (agg) => `${agg.name}Commands`, byStateTypeName = (agg, cmd) => `${commandTypeName(agg, cmd)}ByState`, targetsVary = (factory, targets) => !factory && new Set(targets.map((t) => [...new Set(t)].sort().join("|"))).size > 1, aggregateParamName = (agg) => camel(agg.name), makeTypeName = (p) => `Make${p.name}`, invalidTypeName = (p) => `Invalid${p.name}`, PERSISTENT_EVENT_TYPE = "PersistentEvent", DOMAIN_EVENT_TYPE = "DomainEvent", AGGREGATE_TYPE = "Aggregate", aggregateEventTypeName = (agg) => `${agg.name}Event`, KIND_LABELS, TS_RESERVED;
|
|
5226
|
+
var init_naming = __esm(() => {
|
|
4777
5227
|
init_ast();
|
|
4778
|
-
init_labels();
|
|
4779
|
-
init_types();
|
|
4780
5228
|
init_model_index();
|
|
4781
|
-
|
|
5229
|
+
RUNTIME_NAMES = ["Result", "Ok", "Err", "Decimal", "Timestamp", "ok", "err", "byState"];
|
|
5230
|
+
KIND_LABELS = {
|
|
5231
|
+
IdType: "id",
|
|
5232
|
+
PrimitiveDecl: "primitive",
|
|
5233
|
+
EnumDecl: "enum",
|
|
5234
|
+
ValueObject: "value object",
|
|
5235
|
+
UnionDecl: "union",
|
|
5236
|
+
Entity: "entity",
|
|
5237
|
+
EventDecl: "event",
|
|
5238
|
+
ErrorDecl: "error",
|
|
5239
|
+
FieldSet: "field set"
|
|
5240
|
+
};
|
|
5241
|
+
TS_RESERVED = new Set([
|
|
5242
|
+
"break",
|
|
5243
|
+
"case",
|
|
5244
|
+
"catch",
|
|
5245
|
+
"class",
|
|
5246
|
+
"const",
|
|
5247
|
+
"continue",
|
|
5248
|
+
"debugger",
|
|
5249
|
+
"default",
|
|
5250
|
+
"delete",
|
|
5251
|
+
"do",
|
|
5252
|
+
"else",
|
|
5253
|
+
"enum",
|
|
5254
|
+
"export",
|
|
5255
|
+
"extends",
|
|
5256
|
+
"false",
|
|
5257
|
+
"finally",
|
|
5258
|
+
"for",
|
|
5259
|
+
"function",
|
|
5260
|
+
"if",
|
|
5261
|
+
"import",
|
|
5262
|
+
"in",
|
|
5263
|
+
"instanceof",
|
|
5264
|
+
"new",
|
|
5265
|
+
"null",
|
|
5266
|
+
"return",
|
|
5267
|
+
"super",
|
|
5268
|
+
"switch",
|
|
5269
|
+
"this",
|
|
5270
|
+
"throw",
|
|
5271
|
+
"true",
|
|
5272
|
+
"try",
|
|
5273
|
+
"typeof",
|
|
5274
|
+
"var",
|
|
5275
|
+
"void",
|
|
5276
|
+
"while",
|
|
5277
|
+
"with",
|
|
5278
|
+
"yield",
|
|
5279
|
+
"let",
|
|
5280
|
+
"static",
|
|
5281
|
+
"implements",
|
|
5282
|
+
"interface",
|
|
5283
|
+
"package",
|
|
5284
|
+
"private",
|
|
5285
|
+
"protected",
|
|
5286
|
+
"public",
|
|
5287
|
+
"await",
|
|
5288
|
+
"any",
|
|
5289
|
+
"boolean",
|
|
5290
|
+
"number",
|
|
5291
|
+
"string",
|
|
5292
|
+
"symbol",
|
|
5293
|
+
"never",
|
|
5294
|
+
"unknown",
|
|
5295
|
+
"object",
|
|
5296
|
+
"undefined",
|
|
5297
|
+
"bigint"
|
|
5298
|
+
]);
|
|
4782
5299
|
});
|
|
4783
5300
|
|
|
4784
|
-
// src/core/checker/
|
|
4785
|
-
function
|
|
5301
|
+
// src/core/checker/events.ts
|
|
5302
|
+
function checkEventIds(index, sink) {
|
|
4786
5303
|
for (const agg of index.aggregates) {
|
|
4787
|
-
const
|
|
5304
|
+
const idType = identityField(agg)?.type?.decl?.ref;
|
|
5305
|
+
if (!idType || !isIdType(idType))
|
|
5306
|
+
continue;
|
|
5307
|
+
const checked = new Set;
|
|
4788
5308
|
for (const cmd of commandsOf(agg)) {
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
if (
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
5309
|
+
cmd.emits.forEach((r, i) => {
|
|
5310
|
+
const ev = r.ref;
|
|
5311
|
+
if (!ev || checked.has(ev))
|
|
5312
|
+
return;
|
|
5313
|
+
checked.add(ev);
|
|
5314
|
+
const fields = [...includedFields(ev).map((x) => x.field), ...ev.members];
|
|
5315
|
+
if (fields.some((f) => f.type?.decl?.ref === idType))
|
|
5316
|
+
return;
|
|
5317
|
+
const typeName = idType.$container.name === ev.$container.name ? idType.name : `${idType.$container.name}.${idType.name}`;
|
|
5318
|
+
sink.warning("M017", `Event '${ev.name}' emitted by '${agg.name}.${cmd.name}' has no field of type '${idType.name}' to tell which '${agg.name}' it is about (e.g. '${camel(agg.name)}Id: ${typeName}').`, cmd, "emits", i);
|
|
5319
|
+
});
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
}
|
|
5323
|
+
var init_events = __esm(() => {
|
|
5324
|
+
init_ast();
|
|
5325
|
+
init_naming();
|
|
5326
|
+
init_model_index();
|
|
5327
|
+
});
|
|
5328
|
+
|
|
5329
|
+
// src/core/checker/field-sets.ts
|
|
5330
|
+
function checkFieldSets(index, sink) {
|
|
5331
|
+
for (const fs of index.fieldSets) {
|
|
5332
|
+
for (const m of fs.members) {
|
|
5333
|
+
if (isInvariant(m)) {
|
|
5334
|
+
sink.error("M016", `Field set '${fs.name}' cannot hold invariants; write invariant '${m.name}' in the elements that use it.`, m, "name");
|
|
5335
|
+
} else if (isOwnsField(m) || isReferenceField(m)) {
|
|
5336
|
+
const keyword = isOwnsField(m) ? "owns" : "references";
|
|
5337
|
+
sink.error("M016", `A field set holds plain fields only; '${m.name}' is declared with '${keyword}'.`, m, "name");
|
|
5338
|
+
} else if (m.name === "id") {
|
|
5339
|
+
sink.error("M016", `Field set '${fs.name}' cannot declare 'id'; the identity is declared by each aggregate and entity itself.`, m, "name");
|
|
4804
5340
|
}
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
for (const el of index.elements) {
|
|
5344
|
+
if (!("fieldSets" in el) || el.fieldSets.length === 0)
|
|
5345
|
+
continue;
|
|
5346
|
+
if (isFieldSet(el) || isValueObject(el) || isErrorDecl(el)) {
|
|
5347
|
+
const what = isFieldSet(el) ? `field set '${el.name}' cannot include other field sets` : `${isValueObject(el) ? "value object" : "error"} '${el.name}' cannot take field sets`;
|
|
5348
|
+
sink.error("M016", `'with' is only for aggregates, entities and events; ${what}.`, el, "fieldSets");
|
|
5349
|
+
continue;
|
|
5350
|
+
}
|
|
5351
|
+
if (isAggregate(el) || isEntity(el) || isEventDecl(el))
|
|
5352
|
+
checkUses(el, sink);
|
|
5353
|
+
}
|
|
5354
|
+
}
|
|
5355
|
+
function checkUses(el, sink) {
|
|
5356
|
+
const seen = new Set;
|
|
5357
|
+
el.fieldSets.forEach((r, i) => {
|
|
5358
|
+
if (!r.ref)
|
|
5359
|
+
return;
|
|
5360
|
+
if (seen.has(r.ref))
|
|
5361
|
+
sink.warning("M016", `Field set '${r.$refText}' is listed more than once.`, el, "fieldSets", i);
|
|
5362
|
+
seen.add(r.ref);
|
|
5363
|
+
});
|
|
5364
|
+
const from = new Map;
|
|
5365
|
+
for (const { field, fieldSet } of includedFields(el)) {
|
|
5366
|
+
const first = from.get(field.name);
|
|
5367
|
+
if (first === undefined) {
|
|
5368
|
+
from.set(field.name, fieldSet.name);
|
|
5369
|
+
} else if (first !== fieldSet.name) {
|
|
5370
|
+
const at = el.fieldSets.findIndex((r) => r.ref === fieldSet);
|
|
5371
|
+
sink.error("M016", `Field '${field.name}' of field set '${fieldSet.name}' is also declared in field set '${first}', both used by '${el.name}'.`, el, "fieldSets", at);
|
|
5372
|
+
}
|
|
5373
|
+
}
|
|
5374
|
+
const own = isAggregate(el) ? commonFields(el) : fieldsOf(el.members);
|
|
5375
|
+
for (const f of own) {
|
|
5376
|
+
const fs = from.get(f.name);
|
|
5377
|
+
if (fs)
|
|
5378
|
+
sink.error("M016", `Field '${f.name}' of '${el.name}' is already taken from field set '${fs}'.`, f, "name");
|
|
5379
|
+
}
|
|
5380
|
+
if (isAggregate(el)) {
|
|
5381
|
+
for (const s of statesOf(el)) {
|
|
5382
|
+
for (const f of fieldsOf(s.members)) {
|
|
5383
|
+
const fs = from.get(f.name);
|
|
5384
|
+
if (fs)
|
|
5385
|
+
sink.error("M016", `Field '${f.name}' of state '${s.name}' shadows the field of field set '${fs}' in '${el.name}'.`, f, "name");
|
|
4812
5386
|
}
|
|
4813
5387
|
}
|
|
4814
5388
|
}
|
|
4815
5389
|
}
|
|
4816
|
-
var
|
|
5390
|
+
var init_field_sets = __esm(() => {
|
|
5391
|
+
init_ast();
|
|
4817
5392
|
init_model_index();
|
|
4818
5393
|
});
|
|
4819
5394
|
|
|
@@ -4826,7 +5401,7 @@ function checkInvariants(index, sink) {
|
|
|
4826
5401
|
checkAggregate(el, ctx, index, sink);
|
|
4827
5402
|
} else if (isEntity(el) || isValueObject(el)) {
|
|
4828
5403
|
const members = el.members;
|
|
4829
|
-
const fields = new Map(fieldsOf(members).map((f) => [f.name, f]));
|
|
5404
|
+
const fields = new Map([...includedFields(el).map((x) => x.field), ...fieldsOf(members)].map((f) => [f.name, f]));
|
|
4830
5405
|
for (const inv of invariantsOf(members)) {
|
|
4831
5406
|
checkInvariant(inv, { ctx, fields, stateOnly: new Map, lambdas: [], present: new Set }, index, sink);
|
|
4832
5407
|
}
|
|
@@ -4863,7 +5438,7 @@ function checkPrimitive(p, ctx, index, sink) {
|
|
|
4863
5438
|
}
|
|
4864
5439
|
}
|
|
4865
5440
|
function checkAggregate(agg, ctx, index, sink) {
|
|
4866
|
-
const common = new Map(commonFields(agg).map((f) => [f.name, f]));
|
|
5441
|
+
const common = new Map([...includedFields(agg).map((x) => x.field), ...commonFields(agg)].map((f) => [f.name, f]));
|
|
4867
5442
|
const states = statesOf(agg);
|
|
4868
5443
|
const stateOnly = (except) => {
|
|
4869
5444
|
const m = new Map;
|
|
@@ -5085,7 +5660,7 @@ class ExprChecker {
|
|
|
5085
5660
|
return ERROR;
|
|
5086
5661
|
}
|
|
5087
5662
|
case "struct": {
|
|
5088
|
-
const f = fieldsOf(recv.decl.members).find((x) => x.name === m);
|
|
5663
|
+
const f = [...includedFields(recv.decl).map((x) => x.field), ...fieldsOf(recv.decl.members)].find((x) => x.name === m);
|
|
5089
5664
|
if (f)
|
|
5090
5665
|
return narrow(memberType(f), pathOf(e) ?? "", scope);
|
|
5091
5666
|
this.sink.error("M001", `'${recv.decl.name}' has no field '${m}'.`, e, "member");
|
|
@@ -5214,11 +5789,12 @@ function checkLabels(index, sink) {
|
|
|
5214
5789
|
sameLabel(invariantsOf(v.members).map((i) => ({ node: i, name: i.name, label: i.label })), `the invariants of '${el.name}.${v.name}'`, sink);
|
|
5215
5790
|
}
|
|
5216
5791
|
} else if (isAggregate(el)) {
|
|
5792
|
+
const included = includedFields(el).map((x) => x.field);
|
|
5217
5793
|
const common = commonFields(el);
|
|
5218
5794
|
const states = statesOf(el);
|
|
5219
|
-
fieldScope(common, `'${el.name}'
|
|
5795
|
+
fieldScope(common, `'${el.name}'`, included);
|
|
5220
5796
|
for (const s of states)
|
|
5221
|
-
fieldScope(fieldsOf(s.members), `state '${el.name}.${s.name}'`, common);
|
|
5797
|
+
fieldScope(fieldsOf(s.members), `state '${el.name}.${s.name}'`, [...included, ...common]);
|
|
5222
5798
|
sameLabel(states.map((s) => ({ node: s, name: s.name, label: s.label })), `the states of '${el.name}'`, sink);
|
|
5223
5799
|
sameLabel(commandsOf(el).map((c) => ({ node: c, name: c.name, label: c.label })), `the commands of '${el.name}'`, sink);
|
|
5224
5800
|
const invariants = [...invariantsOf(el.members), ...states.flatMap((s) => invariantsOf(s.members))];
|
|
@@ -5226,7 +5802,7 @@ function checkLabels(index, sink) {
|
|
|
5226
5802
|
for (const c of commandsOf(el))
|
|
5227
5803
|
fieldScope(c.params, `command '${el.name}.${c.name}'`);
|
|
5228
5804
|
} else if ("members" in el) {
|
|
5229
|
-
fieldScope(fieldsOf(el.members), `'${el.name}'
|
|
5805
|
+
fieldScope(fieldsOf(el.members), `'${el.name}'`, includedFields(el).map((x) => x.field));
|
|
5230
5806
|
if (isEntity(el) || isValueObject(el)) {
|
|
5231
5807
|
sameLabel(invariantsOf(el.members).map((i) => ({ node: i, name: i.name, label: i.label })), `the invariants of '${el.name}'`, sink);
|
|
5232
5808
|
}
|
|
@@ -5355,7 +5931,7 @@ function checkShared(index, sink) {
|
|
|
5355
5931
|
const ctx = el.$container.name;
|
|
5356
5932
|
if (!shared.has(ctx))
|
|
5357
5933
|
continue;
|
|
5358
|
-
if (!isPrimitiveDecl(el) && !isEnumDecl(el) && !isValueObject(el) && !isUnionDecl(el)) {
|
|
5934
|
+
if (!isPrimitiveDecl(el) && !isEnumDecl(el) && !isValueObject(el) && !isUnionDecl(el) && !isFieldSet(el)) {
|
|
5359
5935
|
sink.error("M014", `Shared context '${ctx}' can only contain ${ALLOWED}; found ${kind(el)} '${el.name}'.`, el, "name");
|
|
5360
5936
|
}
|
|
5361
5937
|
for (const ref of AstUtils4.streamAllContents(el).filter(isTypeRef)) {
|
|
@@ -5384,7 +5960,7 @@ function kind(el) {
|
|
|
5384
5960
|
const names = { Aggregate: "aggregate", Entity: "entity", IdType: "ID", EventDecl: "event", ErrorDecl: "error" };
|
|
5385
5961
|
return names[el.$type] ?? el.$type;
|
|
5386
5962
|
}
|
|
5387
|
-
var ALLOWED = "domain primitives, enums, value objects, unions and terms";
|
|
5963
|
+
var ALLOWED = "domain primitives, enums, value objects, unions, field sets and terms";
|
|
5388
5964
|
var init_shared = __esm(() => {
|
|
5389
5965
|
init_ast();
|
|
5390
5966
|
});
|
|
@@ -5403,6 +5979,11 @@ function checkStructure(index, sink) {
|
|
|
5403
5979
|
for (const f of allFields2(el))
|
|
5404
5980
|
checkFieldKind(el, f, sink);
|
|
5405
5981
|
}
|
|
5982
|
+
for (const fs of index.fieldSets) {
|
|
5983
|
+
for (const f of fieldsOf(fs.members))
|
|
5984
|
+
if (f.$type === "Field")
|
|
5985
|
+
checkFieldKind(fs, f, sink);
|
|
5986
|
+
}
|
|
5406
5987
|
checkPayloads(index, sink);
|
|
5407
5988
|
checkIdentity(index, sink);
|
|
5408
5989
|
checkOwningAggregates(index, sink);
|
|
@@ -5561,123 +6142,6 @@ var init_structure = __esm(() => {
|
|
|
5561
6142
|
init_model_index();
|
|
5562
6143
|
});
|
|
5563
6144
|
|
|
5564
|
-
// src/generator/naming.ts
|
|
5565
|
-
function generatedNames(index, ctx) {
|
|
5566
|
-
const out = [];
|
|
5567
|
-
const seen = new Set;
|
|
5568
|
-
for (const el of index.elementsOf(ctx)) {
|
|
5569
|
-
if (seen.has(el.name))
|
|
5570
|
-
continue;
|
|
5571
|
-
seen.add(el.name);
|
|
5572
|
-
if (!isAggregate(el)) {
|
|
5573
|
-
out.push({ name: el.name, origin: `${KIND_LABELS[el.$type]} '${el.name}'`, node: el });
|
|
5574
|
-
if (isIdType(el) || isPrimitiveDecl(el)) {
|
|
5575
|
-
out.push({ name: makeTypeName(el), origin: `the constructor of '${el.name}'`, node: el });
|
|
5576
|
-
if (primitiveInvariants(el).length)
|
|
5577
|
-
out.push({ name: invalidTypeName(el), origin: `the error of '${el.name}'`, node: el });
|
|
5578
|
-
}
|
|
5579
|
-
continue;
|
|
5580
|
-
}
|
|
5581
|
-
const states = firstByName(statesOf(el));
|
|
5582
|
-
out.push({ name: el.name, origin: `aggregate '${el.name}'`, node: el });
|
|
5583
|
-
if (states.length > 0) {
|
|
5584
|
-
out.push({ name: commonTypeName(el), origin: `common fields of '${el.name}'`, node: el });
|
|
5585
|
-
for (const s of states) {
|
|
5586
|
-
out.push({ name: stateTypeName(el, s), origin: `state '${el.name}.${s.name}'`, node: s });
|
|
5587
|
-
}
|
|
5588
|
-
}
|
|
5589
|
-
const commands = firstByName(commandsOf(el));
|
|
5590
|
-
if (commands.length > 0) {
|
|
5591
|
-
out.push({ name: commandsInterfaceName(el), origin: `commands of '${el.name}'`, node: el });
|
|
5592
|
-
}
|
|
5593
|
-
for (const c of commands) {
|
|
5594
|
-
out.push({ name: commandTypeName(el, c), origin: `command '${el.name}.${c.name}'`, node: c });
|
|
5595
|
-
}
|
|
5596
|
-
}
|
|
5597
|
-
const persistent = index.elementsOf(ctx).find((el) => isEventDecl(el) && el.persistent);
|
|
5598
|
-
if (persistent)
|
|
5599
|
-
out.push({ name: PERSISTENT_EVENT_TYPE, origin: "the union of persistent events", node: persistent });
|
|
5600
|
-
return out;
|
|
5601
|
-
}
|
|
5602
|
-
function firstByName(items) {
|
|
5603
|
-
const seen = new Set;
|
|
5604
|
-
return items.filter((i) => !seen.has(i.name) && seen.add(i.name));
|
|
5605
|
-
}
|
|
5606
|
-
var RUNTIME_NAMES, EVENT_TAG = "type", STATE_TAG = "state", pascal = (s) => s.charAt(0).toUpperCase() + s.slice(1), camel = (s) => s.charAt(0).toLowerCase() + s.slice(1), commonTypeName = (agg) => `${agg.name}Common`, stateTypeName = (agg, state) => `${typeof state === "string" ? state : state.name}${agg.name}`, commandTypeName = (agg, cmd) => `${pascal(cmd.name)}${agg.name}`, commandsInterfaceName = (agg) => `${agg.name}Commands`, aggregateParamName = (agg) => camel(agg.name), makeTypeName = (p) => `Make${p.name}`, invalidTypeName = (p) => `Invalid${p.name}`, PERSISTENT_EVENT_TYPE = "PersistentEvent", KIND_LABELS, TS_RESERVED;
|
|
5607
|
-
var init_naming = __esm(() => {
|
|
5608
|
-
init_ast();
|
|
5609
|
-
init_model_index();
|
|
5610
|
-
RUNTIME_NAMES = ["Result", "Ok", "Err", "Decimal", "Timestamp", "ok", "err"];
|
|
5611
|
-
KIND_LABELS = {
|
|
5612
|
-
IdType: "id",
|
|
5613
|
-
PrimitiveDecl: "primitive",
|
|
5614
|
-
EnumDecl: "enum",
|
|
5615
|
-
ValueObject: "value object",
|
|
5616
|
-
UnionDecl: "union",
|
|
5617
|
-
Entity: "entity",
|
|
5618
|
-
EventDecl: "event",
|
|
5619
|
-
ErrorDecl: "error"
|
|
5620
|
-
};
|
|
5621
|
-
TS_RESERVED = new Set([
|
|
5622
|
-
"break",
|
|
5623
|
-
"case",
|
|
5624
|
-
"catch",
|
|
5625
|
-
"class",
|
|
5626
|
-
"const",
|
|
5627
|
-
"continue",
|
|
5628
|
-
"debugger",
|
|
5629
|
-
"default",
|
|
5630
|
-
"delete",
|
|
5631
|
-
"do",
|
|
5632
|
-
"else",
|
|
5633
|
-
"enum",
|
|
5634
|
-
"export",
|
|
5635
|
-
"extends",
|
|
5636
|
-
"false",
|
|
5637
|
-
"finally",
|
|
5638
|
-
"for",
|
|
5639
|
-
"function",
|
|
5640
|
-
"if",
|
|
5641
|
-
"import",
|
|
5642
|
-
"in",
|
|
5643
|
-
"instanceof",
|
|
5644
|
-
"new",
|
|
5645
|
-
"null",
|
|
5646
|
-
"return",
|
|
5647
|
-
"super",
|
|
5648
|
-
"switch",
|
|
5649
|
-
"this",
|
|
5650
|
-
"throw",
|
|
5651
|
-
"true",
|
|
5652
|
-
"try",
|
|
5653
|
-
"typeof",
|
|
5654
|
-
"var",
|
|
5655
|
-
"void",
|
|
5656
|
-
"while",
|
|
5657
|
-
"with",
|
|
5658
|
-
"yield",
|
|
5659
|
-
"let",
|
|
5660
|
-
"static",
|
|
5661
|
-
"implements",
|
|
5662
|
-
"interface",
|
|
5663
|
-
"package",
|
|
5664
|
-
"private",
|
|
5665
|
-
"protected",
|
|
5666
|
-
"public",
|
|
5667
|
-
"await",
|
|
5668
|
-
"any",
|
|
5669
|
-
"boolean",
|
|
5670
|
-
"number",
|
|
5671
|
-
"string",
|
|
5672
|
-
"symbol",
|
|
5673
|
-
"never",
|
|
5674
|
-
"unknown",
|
|
5675
|
-
"object",
|
|
5676
|
-
"undefined",
|
|
5677
|
-
"bigint"
|
|
5678
|
-
]);
|
|
5679
|
-
});
|
|
5680
|
-
|
|
5681
6145
|
// src/core/checker/tsnames.ts
|
|
5682
6146
|
function checkTsNames(index, sink) {
|
|
5683
6147
|
const contexts = index.contextNames;
|
|
@@ -5702,11 +6166,18 @@ function checkTsNames(index, sink) {
|
|
|
5702
6166
|
}
|
|
5703
6167
|
}
|
|
5704
6168
|
for (const el of [...index.events, ...index.errors]) {
|
|
6169
|
+
const kind = el.$type === "EventDecl" ? "event" : "error";
|
|
5705
6170
|
for (const f of el.members) {
|
|
5706
6171
|
if (f.name === EVENT_TAG) {
|
|
5707
|
-
sink.error("M011", `Field '${EVENT_TAG}' is reserved for the discriminant of generated ${
|
|
6172
|
+
sink.error("M011", `Field '${EVENT_TAG}' is reserved for the discriminant of generated ${kind} types.`, f, "name");
|
|
5708
6173
|
}
|
|
5709
6174
|
}
|
|
6175
|
+
for (const { field, fieldSet } of includedFields(el)) {
|
|
6176
|
+
if (field.name !== EVENT_TAG)
|
|
6177
|
+
continue;
|
|
6178
|
+
const at = el.fieldSets.findIndex((r) => r.ref === fieldSet);
|
|
6179
|
+
sink.error("M011", `Field '${EVENT_TAG}' of field set '${fieldSet.name}' is reserved for the discriminant of generated ${kind} types.`, el, "fieldSets", at);
|
|
6180
|
+
}
|
|
5710
6181
|
}
|
|
5711
6182
|
for (const agg of index.elements.filter(isAggregate)) {
|
|
5712
6183
|
const self = aggregateParamName(agg);
|
|
@@ -5857,7 +6328,9 @@ async function analyze(sources) {
|
|
|
5857
6328
|
checkShared(index, sink);
|
|
5858
6329
|
checkStructure(index, sink);
|
|
5859
6330
|
checkUnions(index, sink);
|
|
6331
|
+
checkFieldSets(index, sink);
|
|
5860
6332
|
checkCommands(index, sink);
|
|
6333
|
+
checkEventIds(index, sink);
|
|
5861
6334
|
checkInvariants(index, sink);
|
|
5862
6335
|
checkTsNames(index, sink);
|
|
5863
6336
|
checkLabels(index, sink);
|
|
@@ -5910,6 +6383,8 @@ var init_analyze = __esm(() => {
|
|
|
5910
6383
|
init_build();
|
|
5911
6384
|
init_ids();
|
|
5912
6385
|
init_commands();
|
|
6386
|
+
init_events();
|
|
6387
|
+
init_field_sets();
|
|
5913
6388
|
init_expressions();
|
|
5914
6389
|
init_labels2();
|
|
5915
6390
|
init_names();
|
|
@@ -5923,13 +6398,15 @@ var init_analyze = __esm(() => {
|
|
|
5923
6398
|
from: "M006",
|
|
5924
6399
|
to: "M006",
|
|
5925
6400
|
emits: "M007",
|
|
5926
|
-
errors: "M007"
|
|
6401
|
+
errors: "M007",
|
|
6402
|
+
fieldSets: "M016"
|
|
5927
6403
|
};
|
|
5928
6404
|
LINK_KINDS = {
|
|
5929
6405
|
from: "state",
|
|
5930
6406
|
to: "state",
|
|
5931
6407
|
emits: "event",
|
|
5932
6408
|
errors: "error",
|
|
6409
|
+
fieldSets: "field set",
|
|
5933
6410
|
target: "aggregate",
|
|
5934
6411
|
decl: "type"
|
|
5935
6412
|
};
|
|
@@ -6134,7 +6611,7 @@ var init_files = __esm(() => {
|
|
|
6134
6611
|
});
|
|
6135
6612
|
|
|
6136
6613
|
// src/model/model.ts
|
|
6137
|
-
var elementsIn = (model, ctx) => Object.values(model.elements).filter((e) => e.context === ctx), elementList = (model) => Object.values(model.elements), allFieldsOf = (el) => [
|
|
6614
|
+
var elementsIn = (model, ctx) => Object.values(model.elements).filter((e) => e.context === ctx), elementList = (model) => Object.values(model.elements), ownFields = (el) => el.fields.filter((f) => !f.fieldSet), allFieldsOf = (el) => [
|
|
6138
6615
|
...el.fields,
|
|
6139
6616
|
...(el.states ?? []).flatMap((s) => s.fields),
|
|
6140
6617
|
...(el.variants ?? []).flatMap((v) => v.fields)
|
|
@@ -6308,8 +6785,10 @@ function contextDependencies(model) {
|
|
|
6308
6785
|
else if (f.type.kind === "ref")
|
|
6309
6786
|
add(f.type.ref, path);
|
|
6310
6787
|
};
|
|
6311
|
-
for (const f of el
|
|
6788
|
+
for (const f of ownFields(el))
|
|
6312
6789
|
field(f, f.name);
|
|
6790
|
+
for (const fs of el.fieldSets ?? [])
|
|
6791
|
+
add(fs, "with");
|
|
6313
6792
|
for (const s of el.states ?? [])
|
|
6314
6793
|
for (const f of s.fields)
|
|
6315
6794
|
field(f, `${s.name}.${f.name}`);
|
|
@@ -6382,13 +6861,14 @@ function fieldLine(f, ctx, model, indent = "") {
|
|
|
6382
6861
|
label: `${marker}${f.label ?? f.name}`,
|
|
6383
6862
|
both: `${marker}${f.label ? `${f.label} ` : ""}${f.name}`
|
|
6384
6863
|
}),
|
|
6385
|
-
value: anyLang({ name: byName + f.multiplicity, label: byLabel + f.multiplicity, both: byName + f.multiplicity })
|
|
6864
|
+
value: anyLang({ name: byName + f.multiplicity, label: byLabel + f.multiplicity, both: byName + f.multiplicity }),
|
|
6865
|
+
...f.fieldSet && { origin: named(typeText({ kind: "ref", ref: f.fieldSet, text: "" }, ctx, model.sharedContexts), lookupLabel(model, f.fieldSet), (l) => l) }
|
|
6386
6866
|
};
|
|
6387
6867
|
}
|
|
6388
6868
|
function bodyUnits(lines) {
|
|
6389
6869
|
return Math.max(0, ...TEXT_VARIANTS.map(([g, m]) => {
|
|
6390
6870
|
const key = Math.max(0, ...lines.filter((l) => l.value).map((l) => textUnits(l.key[g][m])));
|
|
6391
|
-
const value = Math.max(0, ...lines.map((l) => l.value ? textUnits(l.value[g][m]) : 0));
|
|
6871
|
+
const value = Math.max(0, ...lines.map((l) => l.value ? textUnits(l.value[g][m]) + (l.origin ? COLUMN_GAP + textUnits(l.origin[g][m]) : 0) : 0));
|
|
6392
6872
|
const keyOnly = Math.max(0, ...lines.filter((l) => !l.value).map((l) => textUnits(l.key[g][m])));
|
|
6393
6873
|
return Math.max(value ? key + COLUMN_GAP + value : 0, keyOnly);
|
|
6394
6874
|
}));
|
|
@@ -6697,21 +7177,25 @@ function buildStateGraph(agg, model, labels = "both") {
|
|
|
6697
7177
|
}
|
|
6698
7178
|
const stateNode = (name) => stateful ? states.find((s) => s.name === name)?.id : agg.id;
|
|
6699
7179
|
for (const c of commands) {
|
|
6700
|
-
const
|
|
6701
|
-
|
|
7180
|
+
const pairs = stateful ? c.transitions.flatMap((t) => {
|
|
7181
|
+
const sources = c.factory ? [initialNodeId(agg.id)] : t.from.map(stateNode);
|
|
7182
|
+
return sources.flatMap((source) => t.to.map((to) => [source, stateNode(to)]));
|
|
7183
|
+
}) : [[c.factory ? initialNodeId(agg.id) : agg.id, agg.id]];
|
|
6702
7184
|
const label = commandLabel(c);
|
|
6703
7185
|
const events = eventsLabel(c, model);
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
7186
|
+
const seen = new Set;
|
|
7187
|
+
for (const [source, target] of pairs) {
|
|
7188
|
+
if (!source || !target)
|
|
7189
|
+
continue;
|
|
7190
|
+
const id = `${c.id}|${source}->${target}`;
|
|
7191
|
+
if (seen.has(id))
|
|
7192
|
+
continue;
|
|
7193
|
+
seen.add(id);
|
|
7194
|
+
const node = source === target ? nodes.find((n) => n.id === source) : undefined;
|
|
7195
|
+
if (node)
|
|
7196
|
+
(node.internal ??= []).push({ id, elementId: c.id, label, ...events && { events } });
|
|
7197
|
+
else
|
|
7198
|
+
edges.push({ id, kind: "transition", source, target, label, ...events && { events } });
|
|
6715
7199
|
}
|
|
6716
7200
|
}
|
|
6717
7201
|
const sizedNodes = nodes.map((n) => sizedState(n, labels));
|
|
@@ -6784,7 +7268,8 @@ var init_build2 = __esm(() => {
|
|
|
6784
7268
|
primitive: stereotype("ドメインプリミティブ", "primitive"),
|
|
6785
7269
|
id: stereotype("ID", "id"),
|
|
6786
7270
|
event: stereotype("ドメインイベント", "event"),
|
|
6787
|
-
error: stereotype("エラー", "error")
|
|
7271
|
+
error: stereotype("エラー", "error"),
|
|
7272
|
+
fieldSet: stereotype("項目セット", "field set")
|
|
6788
7273
|
};
|
|
6789
7274
|
});
|
|
6790
7275
|
|
|
@@ -7328,6 +7813,20 @@ export interface Err<E> {
|
|
|
7328
7813
|
export const ok = <T>(value: T): Ok<T> => ({ ok: true, value });
|
|
7329
7814
|
export const err = <E>(error: E): Err<E> => ({ ok: false, error });
|
|
7330
7815
|
|
|
7816
|
+
/** Arguments of a handler after the first. */
|
|
7817
|
+
type ArgsAfterFirst<F> = F extends (first: any, ...args: infer A) => unknown ? A : never;
|
|
7818
|
+
|
|
7819
|
+
/**
|
|
7820
|
+
* Implements a command from one handler per state (a generated \`<Command>ByState\` type): the result calls the handler
|
|
7821
|
+
* of its first argument's \`${STATE_TAG}\` with the same arguments, and is assignable to the command's contract.
|
|
7822
|
+
*
|
|
7823
|
+
* changeNote: byState<Sales.ChangeNoteOrderByState>({ Draft: (order, note) => …, Confirmed: (order, note) => … })
|
|
7824
|
+
*/
|
|
7825
|
+
export const byState =
|
|
7826
|
+
<H extends { readonly [state: string]: (subject: any, ...args: any[]) => unknown }>(handlers: H) =>
|
|
7827
|
+
<S extends { readonly ${STATE_TAG}: keyof H }>(subject: S, ...args: ArgsAfterFirst<H[keyof H]>): ReturnType<H[S['${STATE_TAG}']]> =>
|
|
7828
|
+
handlers[subject.${STATE_TAG}](subject, ...args) as ReturnType<H[S['${STATE_TAG}']]>;
|
|
7829
|
+
|
|
7331
7830
|
/** Decimal values are carried as strings so that no precision is lost. */
|
|
7332
7831
|
export type Decimal = string & { readonly __brand: 'Decimal' };
|
|
7333
7832
|
|
|
@@ -7362,6 +7861,7 @@ var oneLine = (s) => comment(s).replace(/\n+/g, " ");
|
|
|
7362
7861
|
var describedLines = (d) => [d.label, d.doc].filter((x) => !!x);
|
|
7363
7862
|
var PERSISTENT_LINE = "@persistent Persisted: storing this event is part of its contract.";
|
|
7364
7863
|
var invariantLines = (invs) => invs.map((i) => `@invariant ${i.name}${i.label ? ` (${i.label})` : ""}: ${i.source}`);
|
|
7864
|
+
var unique2 = (names) => [...new Set(names)];
|
|
7365
7865
|
|
|
7366
7866
|
class ContextEmitter {
|
|
7367
7867
|
model;
|
|
@@ -7398,7 +7898,11 @@ class ContextEmitter {
|
|
|
7398
7898
|
case "valueObject":
|
|
7399
7899
|
case "entity":
|
|
7400
7900
|
this.jsdoc([...describedLines(el), ...invariantLines(el.invariants)]);
|
|
7401
|
-
this.iface(el.name,
|
|
7901
|
+
this.iface(el.name, this.fieldSets(el), [], ownFields(el));
|
|
7902
|
+
break;
|
|
7903
|
+
case "fieldSet":
|
|
7904
|
+
this.jsdoc([...describedLines(el), `Fields taken on with \`with ${el.name}\`.`]);
|
|
7905
|
+
this.iface(el.name, [], [], el.fields);
|
|
7402
7906
|
break;
|
|
7403
7907
|
case "union":
|
|
7404
7908
|
this.union(el);
|
|
@@ -7406,7 +7910,7 @@ class ContextEmitter {
|
|
|
7406
7910
|
case "event":
|
|
7407
7911
|
case "error":
|
|
7408
7912
|
this.jsdoc([...describedLines(el), ...el.persistent ? [PERSISTENT_LINE] : []]);
|
|
7409
|
-
this.iface(el.name,
|
|
7913
|
+
this.iface(el.name, this.fieldSets(el), [`readonly ${EVENT_TAG}: '${el.name}';`], ownFields(el));
|
|
7410
7914
|
break;
|
|
7411
7915
|
case "aggregate":
|
|
7412
7916
|
this.aggregate(el);
|
|
@@ -7415,6 +7919,7 @@ class ContextEmitter {
|
|
|
7415
7919
|
this.out.push("");
|
|
7416
7920
|
}
|
|
7417
7921
|
this.persistentEvents();
|
|
7922
|
+
this.unions();
|
|
7418
7923
|
const body = this.out.join(`
|
|
7419
7924
|
`);
|
|
7420
7925
|
const runtime = ["Decimal", "Result", "Timestamp"].filter((n) => new RegExp(`\\b${n}\\b`).test(body));
|
|
@@ -7433,6 +7938,24 @@ class ContextEmitter {
|
|
|
7433
7938
|
this.line(`export type ${PERSISTENT_EVENT_TYPE} = ${events.map((e) => e.name).join(" | ")};`);
|
|
7434
7939
|
this.out.push("");
|
|
7435
7940
|
}
|
|
7941
|
+
unions() {
|
|
7942
|
+
const els = elementsIn(this.model, this.ctx);
|
|
7943
|
+
const events = els.filter((el) => el.kind === "event");
|
|
7944
|
+
if (events.length) {
|
|
7945
|
+
this.jsdoc([`Events of ${this.ctx}.`]);
|
|
7946
|
+
this.line(`export type ${DOMAIN_EVENT_TYPE} = ${events.map((e) => e.name).join(" | ")};`);
|
|
7947
|
+
this.out.push("");
|
|
7948
|
+
}
|
|
7949
|
+
const aggregates = els.filter((el) => el.kind === "aggregate");
|
|
7950
|
+
if (aggregates.length) {
|
|
7951
|
+
this.jsdoc([`Aggregates of ${this.ctx}.`]);
|
|
7952
|
+
this.line(`export type ${AGGREGATE_TYPE} = ${aggregates.map((e) => e.name).join(" | ")};`);
|
|
7953
|
+
this.out.push("");
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
fieldSets(el) {
|
|
7957
|
+
return (el.fieldSets ?? []).map((f) => this.ref(f));
|
|
7958
|
+
}
|
|
7436
7959
|
primitive(p) {
|
|
7437
7960
|
const base = PRIMITIVES[p.base ?? "String"];
|
|
7438
7961
|
const summary = p.kind === "id" && !p.label ? [`Identifier of ${p.name}.`] : [];
|
|
@@ -7487,14 +8010,14 @@ class ContextEmitter {
|
|
|
7487
8010
|
const states = agg.states ?? [];
|
|
7488
8011
|
if (states.length === 0) {
|
|
7489
8012
|
this.jsdoc([...describedLines(agg), ...invariantLines(agg.invariants)]);
|
|
7490
|
-
this.iface(agg.name,
|
|
8013
|
+
this.iface(agg.name, this.fieldSets(agg), [], ownFields(agg));
|
|
7491
8014
|
} else {
|
|
7492
8015
|
this.jsdoc([`Fields shared by every state of ${agg.label ? `${agg.label} (${agg.name})` : agg.name}.`, ...invariantLines(agg.invariants)]);
|
|
7493
|
-
this.iface(commonTypeName(agg),
|
|
8016
|
+
this.iface(commonTypeName(agg), this.fieldSets(agg), [], ownFields(agg));
|
|
7494
8017
|
for (const s of states) {
|
|
7495
8018
|
this.out.push("");
|
|
7496
8019
|
this.jsdoc([...describedLines(s), ...invariantLines(s.invariants)]);
|
|
7497
|
-
this.iface(stateTypeName(agg, s), commonTypeName(agg), [`readonly ${STATE_TAG}: '${s.name}';`], s.fields);
|
|
8020
|
+
this.iface(stateTypeName(agg, s), [commonTypeName(agg)], [`readonly ${STATE_TAG}: '${s.name}';`], s.fields);
|
|
7498
8021
|
}
|
|
7499
8022
|
this.out.push("");
|
|
7500
8023
|
this.jsdoc(describedLines(agg));
|
|
@@ -7516,33 +8039,53 @@ class ContextEmitter {
|
|
|
7516
8039
|
}
|
|
7517
8040
|
this.line("}");
|
|
7518
8041
|
}
|
|
8042
|
+
const events = [...new Set(commands.flatMap((c) => c.emits))];
|
|
8043
|
+
if (events.length > 0) {
|
|
8044
|
+
this.out.push("");
|
|
8045
|
+
this.jsdoc([`Events that the commands of ${agg.name} may emit.`]);
|
|
8046
|
+
this.line(`export type ${aggregateEventTypeName(agg)} = ${events.map((e) => this.ref(e)).join(" | ")};`);
|
|
8047
|
+
}
|
|
7519
8048
|
}
|
|
7520
8049
|
command(agg, c) {
|
|
7521
8050
|
const stateful = (agg.states ?? []).length > 0;
|
|
7522
|
-
const stateUnion = (names) => stateful ? names.map((n) => stateTypeName(agg, n)).join(" | ") : agg.name;
|
|
7523
|
-
const
|
|
7524
|
-
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
const output = stateUnion(c.to);
|
|
8051
|
+
const stateUnion = (names) => stateful ? unique2(names).map((n) => stateTypeName(agg, n)).join(" | ") : agg.name;
|
|
8052
|
+
const transitions = stateful ? c.transitions : [];
|
|
8053
|
+
const generic = stateful && targetsVary(c.factory, transitions.map((t) => t.to));
|
|
8054
|
+
const input = stateUnion(transitions.flatMap((t) => t.from));
|
|
8055
|
+
const self = aggregateParamName(agg);
|
|
8056
|
+
const params = c.params.map((p) => `${p.name}: ${this.fieldType(p)}${p.cardinality === "optional" ? " | undefined" : ""}`);
|
|
7529
8057
|
const events = c.emits.length === 0 ? "never" : c.emits.map((e) => this.ref(e)).join(" | ");
|
|
7530
8058
|
const eventArray = c.emits.length > 1 ? `readonly (${events})[]` : `readonly ${events}[]`;
|
|
7531
8059
|
const errors = c.errors.length === 0 ? "never" : c.errors.map((e) => this.ref(e)).join(" | ");
|
|
7532
|
-
const
|
|
8060
|
+
const result = (output) => `Result<readonly [${output}, ${eventArray}], ${errors}>`;
|
|
8061
|
+
const transition = c.factory ? `new -> ${transitions[0]?.to.join(" | ") || agg.name}` : transitions.map((t) => `${t.from.join(" | ")} -> ${t.to.join(" | ")}`).join("; ");
|
|
7533
8062
|
this.jsdoc([
|
|
7534
8063
|
`${agg.name}.${c.name}${transition ? ` (${transition})` : ""}${c.factory ? " — factory" : ""}`,
|
|
7535
8064
|
...describedLines(c),
|
|
7536
8065
|
...c.params.filter((p) => p.label || p.doc).map((p) => `@param ${p.name} ${[p.label, p.doc].filter(Boolean).join(" — ")}`)
|
|
7537
8066
|
]);
|
|
7538
|
-
this.line(`export type ${commandTypeName(agg, c)} = (`);
|
|
7539
|
-
for (const p of params)
|
|
8067
|
+
this.line(`export type ${commandTypeName(agg, c)} = ${generic ? `<S extends ${input}>` : ""}(`);
|
|
8068
|
+
for (const p of [...c.factory ? [] : [`${self}: ${generic ? "S" : input}`], ...params])
|
|
7540
8069
|
this.line(` ${p},`);
|
|
7541
|
-
|
|
8070
|
+
if (!generic) {
|
|
8071
|
+
this.line(`) => ${result(stateUnion(transitions[0]?.to ?? []))};`);
|
|
8072
|
+
return;
|
|
8073
|
+
}
|
|
8074
|
+
this.line(`) => ReturnType<${byStateTypeName(agg, c)}[S['${STATE_TAG}']]>;`);
|
|
8075
|
+
this.out.push("");
|
|
8076
|
+
this.jsdoc([`${agg.name}.${c.name}, one handler per source state; implement it with \`byState\` from the runtime.`]);
|
|
8077
|
+
this.line(`export type ${byStateTypeName(agg, c)} = {`);
|
|
8078
|
+
for (const t of transitions) {
|
|
8079
|
+
for (const from of t.from) {
|
|
8080
|
+
const args = [`${self}: ${stateTypeName(agg, from)}`, ...params].join(", ");
|
|
8081
|
+
this.line(` readonly ${from}: (${args}) => ${result(stateUnion(t.to))};`);
|
|
8082
|
+
}
|
|
8083
|
+
}
|
|
8084
|
+
this.line("};");
|
|
7542
8085
|
}
|
|
7543
|
-
iface(name,
|
|
8086
|
+
iface(name, bases, extra, fields) {
|
|
7544
8087
|
const lines = [...extra, ...fields.flatMap((f) => this.property(f))];
|
|
7545
|
-
const ext =
|
|
8088
|
+
const ext = bases.length ? ` extends ${bases.join(", ")}` : "";
|
|
7546
8089
|
if (lines.length === 0) {
|
|
7547
8090
|
this.line(`export interface ${name}${ext} {}`);
|
|
7548
8091
|
return;
|
|
@@ -7599,7 +8142,7 @@ class ContextEmitter {
|
|
|
7599
8142
|
}
|
|
7600
8143
|
|
|
7601
8144
|
// docs/guide.md
|
|
7602
|
-
var guide_default = "# DomainTrail guide\n\n`dt` checks domain models written in the DomainTrail DSL (`.dt` files) and generates TypeScript types and command\ncontracts from them. The DSL describes domain **structure and contracts** only — never business logic, which is written\nby hand against the generated types.\n\nThis guide is what `dt guide` prints. It is written for people and AI agents using `dt` without other documentation.\n\n## Workflow\n\n1. Write or edit `.dt` files (see [DSL](#dsl) and [File layout](#file-layout-recommended)).\n2. Run `dt check` and fix every reported problem until it exits 0.\n3. Run `dt generate ts` to write the TypeScript (it runs `check` first and writes nothing on errors).\n4. Implement the generated contracts in your own code, and type-check that code with your own TypeScript setup\n (e.g. `tsc --noEmit`). `dt` does not run the TypeScript compiler.\n\n`dt view` starts the Live View, a browser page where people watch the model update as files are saved. It is a server\nthat keeps running and never exits by itself (stop it with Ctrl+C), so do not wait for it to finish: run it in the\nbackground, or use `dt check` for a result.\n\n`dt --help` and `dt <command> --help` list the options with examples.\n\n```bash\ndt check # every *.dt file below the current directory\ndt -r domain check # below domain/ (or as configured by a domaintrail.jsonc found there or above)\ndt generate ts # into <root>/generated/domain\ndt generate ts --out src/domain/generated\ndt view --port 8080 # http://127.0.0.1:8080, until Ctrl+C\n```\n\n## Output and exit codes\n\n`check` (and `generate ts`, which checks first) prints one line per problem, sorted by file and position, then a\nsummary:\n\n```text\nsales/order.dt:2:11 - warning L002: Term 'note' (\"備考\") is not used by any field or parameter in context 'Sales'.\nsales/order.dt:8:32 - error M009: count() requires a collection, but got 'Money'.\n1 file(s) checked: 1 error(s), 1 warning(s).\n```\n\nPaths are relative to the root, lines and columns 1-based. Errors go to stderr, warnings to stdout. Fix errors first;\nwarnings do not fail the check. Other failures (missing root, invalid config, port in use, …) are one line on stderr.\n\n| Exit code | Meaning |\n|---|---|\n| 0 | success (`check`: no errors; warnings are allowed) |\n| 1 | the model has errors, no `.dt` file was found, generation was refused, or the root / a file could not be read |\n| 2 | invalid configuration (`domaintrail.jsonc` / `--config`, including a context name in `generate.ts.contexts` that the model does not have) or an unknown `generate` target |\n\nCommands that use the model look for a config file first; `--root` (`-r`, default `.`) is where that search starts.\n\n## Configuration\n\n`domaintrail.jsonc` (comments and trailing commas allowed) or `domaintrail.json` is looked up in `--root` and its\nparents, like `tsconfig.json`; `--config <file>` (`-c`) picks one explicitly. All paths in it are relative to the config\nfile, and its directory becomes the root. Without a config file, the defaults apply with `--root` as the root.\nEvery key is optional.\n\n```jsonc\n{\n \"$schema\": \"./node_modules/domaintrail/schema/domaintrail.schema.json\",\n // globs of DSL files; \"!\" excludes (node_modules, .git, .domaintrail are never scanned)\n \"sources\": [\"domain/**/*.dt\", \"!domain/drafts/**\"], // default: [\"**/*.dt\"]\n \"generate\": {\n \"ts\": {\n \"out\": \"src/domain/generated\", // default: \"generated/domain\"\n // contexts written elsewhere than \"out\" (optional)\n \"contexts\": { \"Common\": { \"out\": \"packages/shared/src/generated\" } }\n }\n },\n \"view\": { \"port\": 4321, \"host\": \"127.0.0.1\" } // defaults shown\n}\n```\n\nCLI options win over the file: `generate ts --out`, `view --port`, `view --host`. `--out` replaces `generate.ts.out`\nonly; contexts listed in `generate.ts.contexts` keep their own directories. Sources and output directories, `--out`\nincluded, must stay inside the config file's directory (the root without a config file): an absolute path or one with\n`..` is a config error, and an output directory reached through a symlink stops generation. A name in `generate.ts.contexts` that is not a context of the model is a config\nerror, reported by `generate ts` once the model has been checked.\n\n## File layout (recommended)\n\nFile names and directories carry no meaning: every matching `.dt` file belongs to the workspace, and a context may be\nsplit across any files. The recommended layout is one directory per context and one file per aggregate:\n\n```text\ncommon/context.dt shared context Common \"共通\" { ... } // a shared context has no aggregates\nsales/context.dt /// 説明 context Sales \"販売\" { terms { ... } }\nsales/order.dt context Sales { id OrderId ... aggregate Order { ... } entity OrderItem ... event OrderPlaced ... }\nsales/customer.dt context Sales { id CustomerId ... aggregate Customer { ... } }\nbilling/context.dt /// 説明 context Billing \"請求\" { terms { ... } }\nbilling/invoice.dt context Billing { id InvoiceId ... aggregate Invoice { ... } }\n```\n\n- `<context>/<aggregate>.dt` holds the aggregate and what only it uses: its ID, entities, events, errors, enums,\n primitives and values.\n- `<context>/context.dt` holds the context's name (表示名), description and `terms`, and the elements used by several\n of its aggregates or by none. The other files open the context without a name: `context Sales { ... }`.\n- An aggregate's ID stays in the aggregate's file even when other aggregates reference it.\n- Directory and file names are kebab-case: `PurchaseOrder` → `purchase-order.dt`, `OrderFulfillment` →\n `order-fulfillment/`.\n\nThis is a convention, not a rule: `check` neither requires nor warns about any layout.\n\n## DSL\n\nThe examples below are the files of one valid workspace (the file name is in the first comment).\n\n### Contexts and aggregates\n\n```dt\n// sales/order.dt\ncontext Sales { // a bounded context; may be split across files\n id OrderId: UUID // ID type with a base primitive type\n id OrderItemId: UUID\n enum CancelReason { Requested Other } // commas between values are optional\n value Address { city: String street: String }\n\n aggregate Order {\n id: OrderId // identity field of its own ID type (required)\n owns items: OrderItem[0..*] // owned entity / value inside the aggregate\n references customer: CustomerId -> Customer // another aggregate, by ID\n owns shipTo: Address? // ? = optional\n note: String?\n\n invariant quantitiesPositive { // applies to every state; sees the common fields\n all(items, item => item.quantity > 0)\n }\n\n create command place(customer: CustomerId) to Draft emits OrderPlaced // factory: no `from`\n\n state Draft\n state Confirmed {\n confirmedAt: Timestamp // exists only in this state\n invariant hasItems { count(items) > 0 and count(items) <= 100 } // sees common + Confirmed fields\n }\n state Cancelled {\n reason: CancelReason\n invariant otherNeedsNote { reason == CancelReason.Other implies exists(note) }\n }\n\n command confirm(at: Timestamp)\n from Draft\n to Confirmed // several: `to A | B`\n emits OrderConfirmed // events that MAY be emitted (0..n)\n errors EmptyOrder // errors that MAY be returned\n\n command cancel(reason: CancelReason) from Draft | Confirmed to Cancelled emits OrderCancelled\n }\n\n entity OrderItem { id: OrderItemId quantity: Quantity owns unitPrice: Money }\n\n persistent event OrderPlaced { orderId: OrderId } // storing it is part of its contract\n persistent event OrderConfirmed { orderId: OrderId confirmedAt: Timestamp }\n event OrderCancelled { orderId: OrderId reason: CancelReason } // not persisted (default)\n error EmptyOrder // payload optional: error E { field: Type }\n}\n```\n\n```dt\n// sales/customer.dt\ncontext Sales {\n id CustomerId: UUID\n\n aggregate Customer { // no states: commands have no `from` / `to`\n id: CustomerId\n email: EmailAddress // from the shared context Common\n active: Bool\n owns addresses: Address[0..*]\n\n invariant activeHasAddress { active == true implies count(addresses) > 0 }\n invariant servedArea { active == false or any(addresses, a => a.city == \"Tokyo\" or not (a.city == \"Osaka\")) }\n\n command changeEmail(email: EmailAddress) errors EmailTaken\n }\n\n error EmailTaken { email: EmailAddress }\n}\n```\n\n- Context elements: `id`, `primitive`, `enum`, `value`, `union`, `entity`, `aggregate`, `event`, `error`.\n- Fields: `name: Type`, `owns name: Type` (entities and values held by the aggregate),\n `references name: IdType -> Aggregate` (other aggregates, by ID only). Entities are owned by exactly one aggregate.\n- Primitive types: `String`, `Int`, `Decimal`, `Bool`, `Timestamp`, `UUID`.\n- Multiplicity after the type: `?`, `[0..1]`, `[0..*]`, `[1..*]`, `[n..m]`.\n- Aggregate members: fields, `invariant`, `state` (with its own fields and invariants), `command`.\n An aggregate with states needs `to` on every command and `from` on every non-`create` one; without states, neither.\n- `create command` makes a new aggregate; other commands take the aggregate in one of their `from` states.\n- `value`, `state`, `event` and `error` bodies are optional (`state Draft`, `error EmptyOrder`).\n- Other contexts' elements are referenced with qualified names: `Sales.OrderId`, `-> Sales.Order`.\n- Comments: `// …` and `/* … */`; `///` is a description (see [Names](#names-labels-and-descriptions)).\n\n### Domain primitives\n\nA single value with domain meaning and constraints, wrapping a primitive type. Values combining several fields are\nvalue objects.\n\n```dt\n// sales/primitives.dt\ncontext Sales {\n primitive Quantity \"数量\": Int { value in 1..999 } // one anonymous constraint\n primitive Sku: String { // or named invariants\n invariant format \"形式\" { matches(value, \"^[A-Z]{3}-\\d{4}$\") }\n invariant maxLength { length(value) <= 8 }\n }\n id InvoiceNo: String { matches(value, \"^INV-\\d{8}$\") } // an ID is a domain primitive used as identity\n}\n```\n\n- The base is always a primitive type; a domain primitive cannot refine another one or an enum.\n- Inside the constraint only `value` (of the base type) is visible; `length(value)`, `matches(value, \"regex\")` and\n ranges `value in 1..999` (negative literals allowed) are available there.\n- Regular expressions are written as in JavaScript: backslashes are not string escapes (`\"\\d\"` means `\\d`).\n- Elsewhere a domain primitive compares with literals and with the same domain primitive, not with another domain\n primitive or a plain field of its base type (M009).\n- Only IDs can be identity fields and reference types. Domain primitives cannot be owned.\n\n### Unions\n\nA value whose shape depends on a kind fixed when it is made (a tagged union). Use a union for a classification that\nnever changes, and aggregate states for a lifecycle that commands move through.\n\n```dt\n// sales/payment.dt\ncontext Sales {\n union Payer \"支払者\" { // discriminator `kind` by default\n CUSTOMER \"顧客\" { customerId: CustomerId }\n COMPANY \"法人\" { name: String billingEmail: EmailAddress? }\n }\n enum PaymentMethod { CARD TRANSFER }\n union PaymentDetails by method: PaymentMethod { // `by name`, optionally bound to an enum\n CARD { last4: String } // exactly the enum's values (M015)\n TRANSFER { bankCode: String }\n }\n}\n```\n\n- A union is a value type: usable like a value object (fields, `owns`, parameters, payloads, shared contexts).\n Variants hold value fields and invariants (seeing their own fields); entities and aggregates are not allowed.\n- In invariants, `payer.kind` compares with `Payer.COMPANY` (or the bound enum's values); variant fields are not\n accessible from outside the union.\n\n### Shared contexts\n\n```dt\n// common/context.dt\nshared context Common \"共通\" { // shared kernel: usable by simple name from every context\n terms { currency: \"通貨\" }\n enum Currency { JPY USD }\n value Money { amount: Decimal currency: Currency }\n primitive EmailAddress: String { matches(value, \"^[^@\\s]+@[^@\\s]+$\") }\n}\n```\n\n- `Money` and `Common.Money` both work in other contexts. A context's own element with the same name wins (M014 warning).\n- A shared context holds only domain primitives, enums, value objects, unions and terms, and depends only on shared\n contexts. Its `terms` apply to fields of every context that has no term of its own for the name.\n\n### Names (labels and descriptions)\n\n```dt\n// billing/context.dt\n/// 注文への請求と支払いを扱う。\ncontext Billing \"請求\" {\n terms { // field / parameter names, defined once per context\n /// 請求書が支払われた日時。\n paidAt: \"支払日時\"\n }\n}\n```\n\n```dt\n// billing/invoice.dt\ncontext Billing { // other files open the context without a name\n id InvoiceId \"請求書ID\": UUID\n\n /// 注文1件に対する請求。\n aggregate Invoice \"請求書\" { // declarations: a string after the name\n id: InvoiceId\n references order: Sales.OrderId -> Sales.Order \"請求対象\" // an inline label on a field\n owns amount: Money \"請求金額\"\n state Open \"未払い\"\n state Paid \"支払済み\" { paidAt: Timestamp } // → 支払日時 (from terms)\n invariant positive \"金額が正\" { amount.amount > 0 }\n create command issue(order: Sales.OrderId, amount: Money) \"請求書を発行する\" to Open\n command pay(at: Timestamp \"支払日時\") \"支払う\" from Open to Paid emits InvoicePaid\n }\n enum InvoiceKind \"請求区分\" { Regular \"通常\" Refund \"返金\" }\n event InvoicePaid \"支払完了\" { invoiceId: InvoiceId paidAt: Timestamp }\n}\n```\n\n- Declarations (context, id, primitive, enum and its values, value, union and its variants, entity, aggregate, state,\n command, invariant, event, error) take an optional string label after the name.\n- A field or parameter is named by, in order: its inline string → the context's `terms` → the name of its type\n (for `references`, the target aggregate) → the English name.\n- `///` lines directly above a declaration or term are its description.\n- Labels appear in the Live View and as JSDoc in the generated TypeScript; identifiers and generated type names stay\n English.\n\n### Invariant expressions\n\n- Literals: `true`, `false`, `42`, `-1`, `3.14`, `\"text\"`; enum values `CancelReason.Other`.\n- Field paths: `note`, `item.quantity`, `amount.amount`.\n- Operators, loosest first: `implies`, `or`, `and`, `== != < <= > >=`, `x in 1..9`, `not`.\n- Functions: `exists(x)` (an optional is present; narrows `x` on the right of `and` / `implies`), `count(c)`,\n `all(c, x => …)`, `any(c, x => …)`, and in domain primitives `length(value)`, `matches(value, \"regex\")`.\n- An invariant must be a Bool expression. Only its type is checked, not whether it holds.\n\n## Rules\n\n| Code | Check |\n|---|---|\n| SYNTAX | lexer / parser errors |\n| M001 | types, aggregates and names in invariants resolve |\n| M002 | names are unique in their scope (also across files of one context) |\n| M003 | an entity is owned by exactly one aggregate (warning when owned by none) |\n| M004 | no ownership across aggregate boundaries (entities need `owns`, aggregates need `references`, …) |\n| M005 | a reference's ID type matches the identity of the target aggregate |\n| M006 | command input/output states exist and fit the aggregate (factory / stateful / stateless) |\n| M007 | `emits` / `errors` refer to existing events / errors |\n| M008 | an invariant is a Bool expression |\n| M009 | operators and operands have compatible types |\n| M010 | state-specific fields are used only in their own state's invariants |\n| M011 | generated TypeScript names do not collide |\n| M012 | the ownership graph has no cycles |\n| M013 | aggregates and entities have an `id` field of their own ID type |\n| M014 | shared contexts: only value types, no dependency on other contexts, consistent `shared`, unambiguous names (shadowing is a warning) |\n| M015 | unions: at least one variant, variants match the bound enum exactly, no variant field named like the discriminator |\n| L001 | (warning) an inline field label disagrees with the term, or context fragments disagree on the context name |\n| L002 | (warning) a term is not used by any field or parameter |\n| L003 | (warning) different things in one scope share a Japanese name |\n\n## Generated TypeScript\n\nPer context a module (`Sales.ts`, …) with ID brands, enums, value objects, entities, unions, a discriminated union per\nstateful aggregate (`DraftOrder | ConfirmedOrder | …`), event / error types with a `type` tag, a function type per\ncommand and an `<Aggregate>Commands` interface to implement, plus `index.ts` and `_runtime.ts`. A domain primitive\ngets a branded type and a constructor contract `Make<Name>` to implement by hand.\n\n```ts\nexport type ConfirmOrder = (\n order: DraftOrder,\n at: Timestamp,\n) => Result<readonly [ConfirmedOrder, readonly OrderConfirmed[]], EmptyOrder>;\n```\n\n### Generated code and your code\n\nThe generated files are the **contract**, your code is the **implementation**:\n\n- Generated: types only — the shapes of the model, the command signatures (`ConfirmOrder`, `OrderCommands`) and the\n constructor signatures of domain primitives (`MakeQuantity`). Invariants appear as JSDoc (`@invariant`); nothing in\n the generated code checks them.\n- Yours: everything that runs — command implementations, `Make<Name>` constructors, invariant checks — in your own\n files, which import the generated modules (never the other way round) and are type-checked against them.\n\n```ts\n// src/primitives.ts — your code\nimport { err, ok, type Sales } from '../generated/domain/index.js';\n\nexport const makeQuantity: Sales.MakeQuantity = (value) =>\n Number.isInteger(value) && value >= 1 && value <= 999 ? ok(value as Sales.Quantity) : err({ type: 'InvalidQuantity', value, invariant: 'valid' });\n```\n\nDo not edit generated files: change the `.dt` sources and generate again. Adding properties or methods to generated\ntypes (declaration merging, editing the output) is not supported; write functions that take the generated types.\n\n### Output directories\n\nBy default every context goes to `generate.ts.out`. Contexts listed in `generate.ts.contexts` go to their own\ndirectory instead, e.g. a shared context into a package used by several applications. Each directory written to gets\nits own `_runtime.ts` and an `index.ts` re-exporting only the contexts in it; a module imports other contexts by\nrelative path (`import type * as Common from '../../packages/shared/src/generated/Common.js'`). The runtimes are\nidentical, so values typed with one are accepted where the other is expected.\n\nEach run replaces the files generated before (recognized by their header). The files written are recorded in\n`.domaintrail/generated.json` under the root, and generated files of earlier runs that are no longer written (an output\ndirectory moved, a context removed) are deleted, along with a directory left empty. Only recorded paths inside the root\nand not reached through a symlink are deleted; other entries in that file are ignored. Other files are never deleted —\nneither hand-written files nor generated files you edited — and generation stops instead of overwriting one.\n";
|
|
8145
|
+
var guide_default = "# DomainTrail guide\n\n`dt` checks domain models written in the DomainTrail DSL (`.dt` files) and generates TypeScript types and command\ncontracts from them. The DSL describes domain **structure and contracts** only — never business logic, which is written\nby hand against the generated types.\n\nThis guide is what `dt guide` prints. It is written for people and AI agents using `dt` without other documentation.\n\n## Workflow\n\n1. Write or edit `.dt` files (see [DSL](#dsl) and [File layout](#file-layout-recommended)).\n2. Run `dt check` and fix every reported problem until it exits 0.\n3. Run `dt generate ts` to write the TypeScript (it runs `check` first and writes nothing on errors).\n4. Implement the generated contracts in your own code, and type-check that code with your own TypeScript setup\n (e.g. `tsc --noEmit`). `dt` does not run the TypeScript compiler.\n\n`dt view` starts the Live View, a browser page where people watch the model update as files are saved. It is a server\nthat keeps running and never exits by itself (stop it with Ctrl+C), so do not wait for it to finish: run it in the\nbackground, or use `dt check` for a result.\n\n`dt --help` and `dt <command> --help` list the options with examples.\n\n```bash\ndt check # every *.dt file below the current directory\ndt -r domain check # below domain/ (or as configured by a domaintrail.jsonc found there or above)\ndt generate ts # into <root>/generated/domain\ndt generate ts --out src/domain/generated\ndt view --port 8080 # http://127.0.0.1:8080, until Ctrl+C\n```\n\n## Output and exit codes\n\n`check` (and `generate ts`, which checks first) prints one line per problem, sorted by file and position, then a\nsummary:\n\n```text\nsales/order.dt:2:11 - warning L002: Term 'note' (\"備考\") is not used by any field or parameter in context 'Sales'.\nsales/order.dt:8:32 - error M009: count() requires a collection, but got 'Money'.\n1 file(s) checked: 1 error(s), 1 warning(s).\n```\n\nPaths are relative to the root, lines and columns 1-based. Errors go to stderr, warnings to stdout. Fix errors first;\nwarnings do not fail the check. Other failures (missing root, invalid config, port in use, …) are one line on stderr.\n\n| Exit code | Meaning |\n|---|---|\n| 0 | success (`check`: no errors; warnings are allowed) |\n| 1 | the model has errors, no `.dt` file was found, generation was refused, or the root / a file could not be read |\n| 2 | invalid configuration (`domaintrail.jsonc` / `--config`, including a context name in `generate.ts.contexts` that the model does not have) or an unknown `generate` target |\n\nCommands that use the model look for a config file first; `--root` (`-r`, default `.`) is where that search starts.\n\n## Configuration\n\n`domaintrail.jsonc` (comments and trailing commas allowed) or `domaintrail.json` is looked up in `--root` and its\nparents, like `tsconfig.json`; `--config <file>` (`-c`) picks one explicitly. All paths in it are relative to the config\nfile, and its directory becomes the root. Without a config file, the defaults apply with `--root` as the root.\nEvery key is optional.\n\n```jsonc\n{\n \"$schema\": \"./node_modules/domaintrail/schema/domaintrail.schema.json\",\n // globs of DSL files; \"!\" excludes (node_modules, .git, .domaintrail are never scanned)\n \"sources\": [\"domain/**/*.dt\", \"!domain/drafts/**\"], // default: [\"**/*.dt\"]\n \"generate\": {\n \"ts\": {\n \"out\": \"src/domain/generated\", // default: \"generated/domain\"\n // contexts written elsewhere than \"out\" (optional)\n \"contexts\": { \"Common\": { \"out\": \"packages/shared/src/generated\" } }\n }\n },\n \"view\": { \"port\": 4321, \"host\": \"127.0.0.1\" } // defaults shown\n}\n```\n\nCLI options win over the file: `generate ts --out`, `view --port`, `view --host`. `--out` replaces `generate.ts.out`\nonly; contexts listed in `generate.ts.contexts` keep their own directories. Sources and output directories, `--out`\nincluded, must stay inside the config file's directory (the root without a config file): an absolute path or one with\n`..` is a config error, and an output directory reached through a symlink stops generation. A name in `generate.ts.contexts` that is not a context of the model is a config\nerror, reported by `generate ts` once the model has been checked.\n\n## File layout (recommended)\n\nFile names and directories carry no meaning: every matching `.dt` file belongs to the workspace, and a context may be\nsplit across any files. The recommended layout is one directory per context and one file per aggregate:\n\n```text\ncommon/context.dt shared context Common \"共通\" { ... } // a shared context has no aggregates\nsales/context.dt /// 説明 context Sales \"販売\" { terms { ... } }\nsales/order.dt context Sales { id OrderId ... aggregate Order { ... } entity OrderItem ... event OrderPlaced ... }\nsales/customer.dt context Sales { id CustomerId ... aggregate Customer { ... } }\nbilling/context.dt /// 説明 context Billing \"請求\" { terms { ... } }\nbilling/invoice.dt context Billing { id InvoiceId ... aggregate Invoice { ... } }\n```\n\n- `<context>/<aggregate>.dt` holds the aggregate and what only it uses: its ID, entities, events, errors, enums,\n primitives and values.\n- `<context>/context.dt` holds the context's name (表示名), description and `terms`, and the elements used by several\n of its aggregates or by none (field sets, for example). The other files open the context without a name: `context Sales { ... }`.\n- An aggregate's ID stays in the aggregate's file even when other aggregates reference it.\n- Directory and file names are kebab-case: `PurchaseOrder` → `purchase-order.dt`, `OrderFulfillment` →\n `order-fulfillment/`.\n\nThis is a convention, not a rule: `check` neither requires nor warns about any layout.\n\n## DSL\n\nThe examples below are the files of one valid workspace (the file name is in the first comment).\n\n### Contexts and aggregates\n\n```dt\n// sales/order.dt\ncontext Sales { // a bounded context; may be split across files\n id OrderId: UUID // ID type with a base primitive type\n id OrderItemId: UUID\n enum CancelReason { Requested Other } // commas between values are optional\n value Address { city: String street: String }\n\n aggregate Order {\n id: OrderId // identity field of its own ID type (required)\n owns items: OrderItem[0..*] // owned entity / value inside the aggregate\n references customer: CustomerId -> Customer // another aggregate, by ID\n owns shipTo: Address? // ? = optional\n note: String?\n\n invariant quantitiesPositive { // applies to every state; sees the common fields\n all(items, item => item.quantity > 0)\n }\n\n create command place(customer: CustomerId) -> Draft emits OrderPlaced // factory: `-> State`, no source\n\n state Draft\n state Confirmed {\n confirmedAt: Timestamp // exists only in this state\n invariant hasItems { count(items) > 0 and count(items) <= 100 } // sees common + Confirmed fields\n }\n state Cancelled {\n reason: CancelReason\n invariant otherNeedsNote { reason == CancelReason.Other implies exists(note) }\n }\n\n command confirm(at: Timestamp)\n Draft -> Confirmed // a transition: source state(s) -> target state(s)\n emits OrderConfirmed // events that MAY be emitted (0..n)\n errors EmptyOrder // errors that MAY be returned\n\n command cancel(reason: CancelReason) Draft | Confirmed -> Cancelled emits OrderCancelled // from either\n\n command changeNote(note: String?) // one transition per input state: the output depends on the input\n Draft -> Draft\n Confirmed -> Confirmed // also on one line: `Draft -> Draft, Confirmed -> Confirmed`\n }\n\n entity OrderItem { id: OrderItemId quantity: Quantity owns unitPrice: Money }\n\n persistent event OrderPlaced { orderId: OrderId } // storing it is part of its contract\n persistent event OrderConfirmed { orderId: OrderId confirmedAt: Timestamp }\n event OrderCancelled { orderId: OrderId reason: CancelReason } // not persisted (default)\n error EmptyOrder // payload optional: error E { field: Type }\n}\n```\n\n```dt\n// sales/customer.dt\ncontext Sales {\n id CustomerId: UUID\n\n aggregate Customer { // no states: commands have no transitions\n id: CustomerId\n email: EmailAddress // from the shared context Common\n active: Bool\n owns addresses: Address[0..*]\n\n invariant activeHasAddress { active == true implies count(addresses) > 0 }\n invariant servedArea { active == false or any(addresses, a => a.city == \"Tokyo\" or not (a.city == \"Osaka\")) }\n\n command changeEmail(email: EmailAddress) errors EmailTaken\n }\n\n error EmailTaken { email: EmailAddress }\n}\n```\n\n- Context elements: `id`, `primitive`, `enum`, `value`, `union`, `entity`, `aggregate`, `event`, `error`, and `fields`\n (see [Field sets](#field-sets)).\n- Fields: `name: Type`, `owns name: Type` (entities and values held by the aggregate),\n `references name: IdType -> Aggregate` (other aggregates, by ID only). Entities are owned by exactly one aggregate.\n- Primitive types: `String`, `Int`, `Decimal`, `Bool`, `Timestamp`, `UUID`.\n- Multiplicity after the type: `?`, `[0..1]`, `[0..*]`, `[1..*]`, `[n..m]`.\n- Aggregate members: fields, `invariant`, `state` (with its own fields and invariants), `command`.\n- Command transitions follow the parameters (and label), before `emits` / `errors`: `A | B -> C | D` means \"in `A` or\n `B`, the command ends in `C` or `D`\". Separate several transitions by line breaks or commas. A state may be the\n source of one transition of a command only, so the input state decides the possible outputs; for several possible\n outcomes, list them on the right: `InProgress -> InProgress | Completed`.\n- In an aggregate with states, a `create command` makes a new aggregate and has exactly one transition without\n sources (`-> Draft`, or `-> A | B`); every other command has one or more transitions, each with sources. Without\n states, commands have no transitions. A command that keeps the state writes it out: `Draft -> Draft`.\n- `value`, `state`, `event` and `error` bodies are optional (`state Draft`, `error EmptyOrder`).\n- Other contexts' elements are referenced with qualified names: `Sales.OrderId`, `-> Sales.Order`.\n- Comments: `// …` and `/* … */`; `///` is a description (see [Names](#names-labels-and-descriptions)).\n\n### Domain primitives\n\nA single value with domain meaning and constraints, wrapping a primitive type. Values combining several fields are\nvalue objects.\n\n```dt\n// sales/primitives.dt\ncontext Sales {\n primitive Quantity \"数量\": Int { value in 1..999 } // one anonymous constraint\n primitive Sku: String { // or named invariants\n invariant format \"形式\" { matches(value, \"^[A-Z]{3}-\\d{4}$\") }\n invariant maxLength { length(value) <= 8 }\n }\n id InvoiceNo: String { matches(value, \"^INV-\\d{8}$\") } // an ID is a domain primitive used as identity\n}\n```\n\n- The base is always a primitive type; a domain primitive cannot refine another one or an enum.\n- Inside the constraint only `value` (of the base type) is visible; `length(value)`, `matches(value, \"regex\")` and\n ranges `value in 1..999` (negative literals allowed) are available there.\n- Regular expressions are written as in JavaScript: backslashes are not string escapes (`\"\\d\"` means `\\d`).\n- Elsewhere a domain primitive compares with literals and with the same domain primitive, not with another domain\n primitive or a plain field of its base type (M009).\n- Only IDs can be identity fields and reference types. Domain primitives cannot be owned.\n\n### Unions\n\nA value whose shape depends on a kind fixed when it is made (a tagged union). Use a union for a classification that\nnever changes, and aggregate states for a lifecycle that commands move through.\n\n```dt\n// sales/payment.dt\ncontext Sales {\n union Payer \"支払者\" { // discriminator `kind` by default\n CUSTOMER \"顧客\" { customerId: CustomerId }\n COMPANY \"法人\" { name: String billingEmail: EmailAddress? }\n }\n enum PaymentMethod { CARD TRANSFER }\n union PaymentDetails by method: PaymentMethod { // `by name`, optionally bound to an enum\n CARD { last4: String } // exactly the enum's values (M015)\n TRANSFER { bankCode: String }\n }\n}\n```\n\n- A union is a value type: usable like a value object (fields, `owns`, parameters, payloads, shared contexts).\n Variants hold value fields and invariants (seeing their own fields); entities and aggregates are not allowed.\n- In invariants, `payer.kind` compares with `Payer.COMPANY` (or the bound enum's values); variant fields are not\n accessible from outside the union.\n\n### Shared contexts\n\n```dt\n// common/context.dt\nshared context Common \"共通\" { // shared kernel: usable by simple name from every context\n terms { currency: \"通貨\" }\n enum Currency { JPY USD }\n value Money { amount: Decimal currency: Currency }\n primitive EmailAddress: String { matches(value, \"^[^@\\s]+@[^@\\s]+$\") }\n}\n```\n\n- `Money` and `Common.Money` both work in other contexts. A context's own element with the same name wins (M014 warning).\n- A shared context holds only domain primitives, enums, value objects, unions, field sets and terms, and depends only on\n shared contexts. Its `terms` apply to fields of every context that has no term of its own for the name.\n\n### Field sets\n\nFields that several aggregates, entities or events have for the same domain reason are written once as a field set\nand taken on with `with`.\n\n```dt\n// common/tenancy.dt\nshared context Common {\n /// 契約者(テナント)。業務データはテナントごとに分かれる。\n primitive TenantId \"テナントID\": UUID\n fields Tenanted \"テナント所属\" { // a field set: plain fields only\n tenant: TenantId \"テナント\"\n }\n}\n```\n\n```dt\n// expenses/expense.dt\ncontext Expenses \"経費\" {\n id ExpenseId \"経費申請ID\": UUID\n id StaffId \"職員ID\": UUID\n\n /// 規程により、申請の受付には実施者を記録する。\n fields Performed \"実施記録\" {\n performedBy: StaffId \"実施者\"\n }\n\n aggregate Expense \"経費申請\" with Tenanted { // tenant first, then its own fields\n id: ExpenseId\n applicant: StaffId \"申請者\"\n approver: StaffId? \"承認者\"\n invariant notSelfApproved \"申請者は承認できない\" { exists(approver) implies approver != applicant }\n\n create command submit(applicant: StaffId \"申請者\") \"申請する\" emits ExpenseSubmitted\n command approve(approver: StaffId \"承認者\", approvedAt: Timestamp \"承認日時\") \"承認する\" emits ExpenseApproved\n }\n\n event ExpenseSubmitted \"申請受付\" with Tenanted, Performed { expenseId: ExpenseId }\n event ExpenseApproved \"承認\" with Tenanted {\n expenseId: ExpenseId\n approver: StaffId \"承認者\" // a business role, named by the role\n approvedAt: Timestamp \"承認日時\" // when it happened in business terms\n }\n}\n```\n\n- `fields Name \"label\" { ... }` holds plain fields, written like any other field (type, multiplicity, label, `///`).\n No `owns`, `references`, invariants, `with` or `id` inside (M016).\n- `with A, B` after the name and label of an `aggregate`, `entity` or `event` (only those, M016). A field set is\n referenced like a type: by name in its own context and from shared contexts, as `Context.Name` otherwise.\n- The fields come first, in the order of `with`, and then count as the element's own: invariants see them, and an\n aggregate's states share them. A name may come from one place only, the element or one of its field sets (M016).\n- The identity of aggregates and entities is never a field set: every aggregate and entity declares `id` itself (M013).\n- A command's event should say which aggregate it is about: it needs a field of the aggregate's ID type, its own or\n from a field set (M017 warning). An event emitted by several aggregates needs the ID type of each (optional fields\n count).\n\n### Domain fields and technical fields\n\nWrite a field in the DSL when **domain experts talk about it, or a business rule (an invariant, a transition, a\ncommand's decision) refers to it**. A field that is neither is technical: leave it out of the DSL and of the generated\ncode, and add it in your own code around the generated types (see [Technical metadata](#technical-metadata)).\n\n- **Required by the kind of element** (the ID of an aggregate or entity): enforced by the language (M013), not a field\n set.\n- **Chosen for some elements** (a tenant, a recorded performer): a field set and `with`.\n- **Technical**: event ID, the time the system recorded something (`recordedAt`), optimistic-lock `version`,\n `createdAt` / `updatedAt`, correlation / causation IDs, the system's acting account, schema versions.\n\nTwo cases look alike but are not:\n\n- **When**: the time something happened in business terms is domain — rules refer to it (\"within 30 days of\n confirmation\"). Name it by its meaning (`confirmedAt: Timestamp \"確定日時\"`). If every event is to carry its business\n time, say so with a field set: `fields Occurred { occurredAt: Timestamp \"発生日時\" }`. The time the system recorded it\n is technical. The two differ with late entry, offline work and imports.\n- **Who**: a business role (approver, person in charge) is domain — rules refer to it (\"the applicant cannot\n approve\"). Name it by the role (`approvedBy: StaffId \"承認者\"`), usually passed from the command's parameters to the\n event. If regulations require recording the performer of every operation,\n `fields Performed { performedBy: StaffId \"実施者\" }`. The login account, service account or IP address is technical; it differs with proxy entry and batches.\n\n### Names (labels and descriptions)\n\n```dt\n// billing/context.dt\n/// 注文への請求と支払いを扱う。\ncontext Billing \"請求\" {\n terms { // field / parameter names, defined once per context\n /// 請求書が支払われた日時。\n paidAt: \"支払日時\"\n }\n}\n```\n\n```dt\n// billing/invoice.dt\ncontext Billing { // other files open the context without a name\n id InvoiceId \"請求書ID\": UUID\n\n /// 注文1件に対する請求。\n aggregate Invoice \"請求書\" { // declarations: a string after the name\n id: InvoiceId\n references order: Sales.OrderId -> Sales.Order \"請求対象\" // an inline label on a field\n owns amount: Money \"請求金額\"\n state Open \"未払い\"\n state Paid \"支払済み\" { paidAt: Timestamp } // → 支払日時 (from terms)\n invariant positive \"金額が正\" { amount.amount > 0 }\n create command issue(order: Sales.OrderId, amount: Money) \"請求書を発行する\" -> Open\n command pay(at: Timestamp \"支払日時\") \"支払う\" Open -> Paid emits InvoicePaid\n }\n enum InvoiceKind \"請求区分\" { Regular \"通常\" Refund \"返金\" }\n event InvoicePaid \"支払完了\" { invoiceId: InvoiceId paidAt: Timestamp }\n}\n```\n\n- Declarations (context, id, primitive, enum and its values, value, union and its variants, entity, aggregate, state,\n command, invariant, event, error) take an optional string label after the name.\n- A field or parameter is named by, in order: its inline string → the context's `terms` → the name of its type\n (for `references`, the target aggregate) → the English name.\n- `///` lines directly above a declaration or term are its description.\n- Labels appear in the Live View and as JSDoc in the generated TypeScript; identifiers and generated type names stay\n English.\n\n### Invariant expressions\n\n- Literals: `true`, `false`, `42`, `-1`, `3.14`, `\"text\"`; enum values `CancelReason.Other`.\n- Field paths: `note`, `item.quantity`, `amount.amount`.\n- Operators, loosest first: `implies`, `or`, `and`, `== != < <= > >=`, `x in 1..9`, `not`.\n- Functions: `exists(x)` (an optional is present; narrows `x` on the right of `and` / `implies`), `count(c)`,\n `all(c, x => …)`, `any(c, x => …)`, and in domain primitives `length(value)`, `matches(value, \"regex\")`.\n- An invariant must be a Bool expression. Only its type is checked, not whether it holds.\n\n## Rules\n\n| Code | Check |\n|---|---|\n| SYNTAX | lexer / parser errors |\n| M001 | types, aggregates and names in invariants resolve |\n| M002 | names are unique in their scope (also across files of one context) |\n| M003 | an entity is owned by exactly one aggregate (warning when owned by none) |\n| M004 | no ownership across aggregate boundaries (entities need `owns`, aggregates need `references`, …) |\n| M005 | a reference's ID type matches the identity of the target aggregate |\n| M006 | command transitions: states exist; stateful: `create` has one `-> X`, others one or more `A -> B` with sources; a state is the source of one transition per command; stateless: none |\n| M007 | `emits` / `errors` refer to existing events / errors |\n| M008 | an invariant is a Bool expression |\n| M009 | operators and operands have compatible types |\n| M010 | state-specific fields are used only in their own state's invariants |\n| M011 | generated TypeScript names do not collide |\n| M012 | the ownership graph has no cycles |\n| M013 | aggregates and entities have an `id` field of their own ID type |\n| M014 | shared contexts: only value types, no dependency on other contexts, consistent `shared`, unambiguous names (shadowing is a warning) |\n| M015 | unions: at least one variant, variants match the bound enum exactly, no variant field named like the discriminator |\n| M016 | field sets: plain fields only (no `id`), `with` only on aggregates, entities and events, each field name from one place |\n| M017 | (warning) an event emitted by an aggregate's command has a field of that aggregate's ID type |\n| L001 | (warning) an inline field label disagrees with the term, or context fragments disagree on the context name |\n| L002 | (warning) a term is not used by any field or parameter |\n| L003 | (warning) different things in one scope share a Japanese name |\n\n## Generated TypeScript\n\nPer context a module (`Sales.ts`, …) with ID brands, enums, value objects, entities, unions, a discriminated union per\nstateful aggregate (`DraftOrder | ConfirmedOrder | …`), event / error types with a `type` tag, a function type per\ncommand and an `<Aggregate>Commands` interface to implement, plus `index.ts` and `_runtime.ts`. A domain primitive\ngets a branded type and a constructor contract `Make<Name>` to implement by hand. A field set is an interface that the\nelements using it extend (`interface Expense extends Common.Tenanted`; for a stateful aggregate, its `…Common`).\n\nUnions to name groups of them, each generated only when it has a member:\n\n| Type | Members |\n|---|---|\n| `DomainEvent` | every event of the context |\n| `PersistentEvent` | the events declared `persistent` |\n| `Aggregate` | every aggregate of the context |\n| `<Aggregate>Event` (`OrderEvent`) | the events the aggregate's commands may emit (also of other contexts) |\n\n```ts\nexport type ConfirmOrder = (\n order: DraftOrder,\n at: Timestamp,\n) => Result<readonly [ConfirmedOrder, readonly OrderConfirmed[]], EmptyOrder>;\n```\n\nA command takes the aggregate in any source state of its transitions. When every transition has the same targets\n(`Draft | Confirmed -> Cancelled`), it returns them, as above. When the targets differ by transition, the command\nalso gets a `<Command>ByState` type with one handler per source state (keyed by the state's name), and the command is\ngeneric over the input state, returning what the handler of that state returns. A caller with a `DraftOrder` gets a\n`DraftOrder` back, never a `ConfirmedOrder`; a caller with `DraftOrder | ConfirmedOrder` gets either:\n\n```ts\nexport type ChangeNoteOrder = <S extends DraftOrder | ConfirmedOrder>(\n order: S,\n note: string | undefined,\n) => ReturnType<ChangeNoteOrderByState[S['state']]>;\n\nexport type ChangeNoteOrderByState = {\n readonly Draft: (order: DraftOrder, note: string | undefined) => Result<readonly [DraftOrder, readonly never[]], never>;\n readonly Confirmed: (order: ConfirmedOrder, note: string | undefined) => Result<readonly [ConfirmedOrder, readonly never[]], never>;\n};\n```\n\nImplement such a command with `byState` from the runtime: it takes the handlers and calls the one of the aggregate's\n`state`. Each handler is checked against its own transition — returning a `ConfirmedOrder` from the `Draft` handler,\nor leaving a handler out, is a compile error — and no type assertion is needed. Pass the `…ByState` type as the type\nargument so that the handlers' parameters are typed from it:\n\n```ts\n// src/note.ts — your code\nimport { byState, ok, type Sales } from '../generated/domain/index.js';\n\nexport const changeNote: Sales.OrderCommands['changeNote'] = byState<Sales.ChangeNoteOrderByState>({\n Draft: (order, note) => ok([{ ...order, note }, []] as const),\n Confirmed: (order, note) => ok([{ ...order, note }, []] as const),\n});\n```\n\n(TypeScript does not narrow `S` inside a hand-written implementation of the generic contract, which is why the\nhandlers exist: written directly, the implementation needs a type assertion on its result.)\n\n### Generated code and your code\n\nThe generated files are the **contract**, your code is the **implementation**:\n\n- Generated: types only — the shapes of the model, the command signatures (`ConfirmOrder`, `OrderCommands`,\n `ChangeNoteOrderByState`) and the constructor signatures of domain primitives (`MakeQuantity`). Invariants appear as\n JSDoc (`@invariant`); nothing in the generated code checks them. The one exception is `_runtime.ts`, whose few\n helpers (`ok`, `err`, `byState`) are the same for every model.\n- Yours: everything that runs — command implementations, `Make<Name>` constructors, invariant checks — in your own\n files, which import the generated modules (never the other way round) and are type-checked against them.\n\n```ts\n// src/primitives.ts — your code\nimport { err, ok, type Sales } from '../generated/domain/index.js';\n\nexport const makeQuantity: Sales.MakeQuantity = (value) =>\n Number.isInteger(value) && value >= 1 && value <= 999 ? ok(value as Sales.Quantity) : err({ type: 'InvalidQuantity', value, invariant: 'valid' });\n```\n\nDo not edit generated files: change the `.dt` sources and generate again. Adding properties or methods to generated\ntypes (declaration merging, editing the output) is not supported; write functions that take the generated types.\n\n### Technical metadata\n\nTechnical fields (see [Domain fields and technical fields](#domain-fields-and-technical-fields)) are added by your code,\naround the generated types. Keep the two apart in an envelope, `{ event, meta }`, rather than an intersection\n(`E & Meta`): names cannot clash, and domain and technical fields stay separate. `dt` generates no envelope type.\n\n```ts\n// src/stored.ts — your code: metadata of stored events and aggregates\nimport type { Sales } from '../generated/domain/index.js';\n\nexport interface EventMeta {\n readonly eventId: string;\n readonly recordedAt: Date;\n readonly correlationId?: string;\n readonly causationId?: string;\n}\n\n/** What Sales records in addition. */\nexport interface SalesEventMeta extends EventMeta {\n readonly accountId: string;\n}\n\nexport type Stored<E, M extends EventMeta = EventMeta> = { readonly event: E; readonly meta: M };\n\nexport type StoredSalesEvent = Stored<Sales.PersistentEvent, SalesEventMeta>;\n\nexport interface AggregateMeta {\n readonly version: number;\n readonly createdAt: Date;\n readonly updatedAt: Date;\n}\n\nexport type Versioned<A, M extends AggregateMeta = AggregateMeta> = { readonly aggregate: A; readonly meta: M };\n\nexport interface OrderRepository {\n load(id: Sales.OrderId): Promise<Versioned<Sales.Order> | undefined>;\n save(order: Versioned<Sales.Order>, events: readonly Sales.OrderEvent[]): Promise<void>;\n}\n```\n\nMetadata that only some kinds of event carry can be keyed by the event's `type`:\n\n```ts\n// src/meta-by-event.ts — your code\nimport type { Sales } from '../generated/domain/index.js';\nimport type { EventMeta } from './stored.js';\n\ninterface MetaByEvent {\n OrderPlaced: { readonly channel: 'web' | 'store' };\n}\n\nexport type MetaOf<E extends { type: string }> = EventMeta & (E['type'] extends keyof MetaByEvent ? MetaByEvent[E['type']] : {});\n\n/** One envelope per kind of event, so that a union of events gives a union of envelopes. */\nexport type StoredEvent<E extends { type: string }> = E extends unknown ? { readonly event: E; readonly meta: MetaOf<E> } : never;\n\nexport const channelOf = (s: StoredEvent<Sales.OrderPlaced>): 'web' | 'store' => s.meta.channel;\nexport type StoredSalesEvents = StoredEvent<Sales.DomainEvent>;\n```\n\n### Output directories\n\nBy default every context goes to `generate.ts.out`. Contexts listed in `generate.ts.contexts` go to their own\ndirectory instead, e.g. a shared context into a package used by several applications. Each directory written to gets\nits own `_runtime.ts` and an `index.ts` re-exporting only the contexts in it; a module imports other contexts by\nrelative path (`import type * as Common from '../../packages/shared/src/generated/Common.js'`). The runtimes are\nidentical, so values typed with one are accepted where the other is expected.\n\nEach run replaces the files generated before (recognized by their header). The files written are recorded in\n`.domaintrail/generated.json` under the root, and generated files of earlier runs that are no longer written (an output\ndirectory moved, a context removed) are deleted, along with a directory left empty. Only recorded paths inside the root\nand not reached through a symlink are deleted; other entries in that file are ignored. Other files are never deleted —\nneither hand-written files nor generated files you edited — and generation stops instead of overwriting one.\n";
|
|
7603
8146
|
|
|
7604
8147
|
// src/cli/main.ts
|
|
7605
8148
|
var defaultIO = {
|