domaintrail 0.2.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 +5 -3
- package/dist/dt.js +323 -216
- package/dist/web/{chunk-13zkn5c3.js → chunk-xn56ecvv.js} +2 -2
- package/dist/web/index.html +1 -1
- package/package.json +3 -3
package/dist/dt.js
CHANGED
|
@@ -106,7 +106,7 @@ function isUnionDecl(item) {
|
|
|
106
106
|
function isValueObject(item) {
|
|
107
107
|
return reflection.isInstance(item, ValueObject.$type);
|
|
108
108
|
}
|
|
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, 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;
|
|
110
110
|
var init_ast = __esm(() => {
|
|
111
111
|
Aggregate = {
|
|
112
112
|
$type: "Aggregate",
|
|
@@ -133,11 +133,10 @@ var init_ast = __esm(() => {
|
|
|
133
133
|
emits: "emits",
|
|
134
134
|
errors: "errors",
|
|
135
135
|
factory: "factory",
|
|
136
|
-
from: "from",
|
|
137
136
|
label: "label",
|
|
138
137
|
name: "name",
|
|
139
138
|
params: "params",
|
|
140
|
-
|
|
139
|
+
transitions: "transitions"
|
|
141
140
|
};
|
|
142
141
|
Context = {
|
|
143
142
|
$type: "Context",
|
|
@@ -334,6 +333,11 @@ var init_ast = __esm(() => {
|
|
|
334
333
|
$type: "Terms",
|
|
335
334
|
entries: "entries"
|
|
336
335
|
};
|
|
336
|
+
Transition = {
|
|
337
|
+
$type: "Transition",
|
|
338
|
+
from: "from",
|
|
339
|
+
to: "to"
|
|
340
|
+
};
|
|
337
341
|
TypeDecl = {
|
|
338
342
|
$type: "TypeDecl"
|
|
339
343
|
};
|
|
@@ -438,12 +442,6 @@ var init_ast = __esm(() => {
|
|
|
438
442
|
defaultValue: false,
|
|
439
443
|
optional: true
|
|
440
444
|
},
|
|
441
|
-
from: {
|
|
442
|
-
name: Command.from,
|
|
443
|
-
defaultValue: [],
|
|
444
|
-
referenceType: State.$type,
|
|
445
|
-
optional: true
|
|
446
|
-
},
|
|
447
445
|
label: {
|
|
448
446
|
name: Command.label,
|
|
449
447
|
optional: true
|
|
@@ -456,10 +454,9 @@ var init_ast = __esm(() => {
|
|
|
456
454
|
defaultValue: [],
|
|
457
455
|
optional: true
|
|
458
456
|
},
|
|
459
|
-
|
|
460
|
-
name: Command.
|
|
457
|
+
transitions: {
|
|
458
|
+
name: Command.transitions,
|
|
461
459
|
defaultValue: [],
|
|
462
|
-
referenceType: State.$type,
|
|
463
460
|
optional: true
|
|
464
461
|
}
|
|
465
462
|
},
|
|
@@ -1014,6 +1011,23 @@ var init_ast = __esm(() => {
|
|
|
1014
1011
|
},
|
|
1015
1012
|
superTypes: []
|
|
1016
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
|
+
},
|
|
1017
1031
|
TypeDecl: {
|
|
1018
1032
|
name: TypeDecl.$type,
|
|
1019
1033
|
properties: {},
|
|
@@ -1162,7 +1176,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1162
1176
|
"terminal": {
|
|
1163
1177
|
"$type": "RuleCall",
|
|
1164
1178
|
"rule": {
|
|
1165
|
-
"$ref": "#/rules@
|
|
1179
|
+
"$ref": "#/rules@47"
|
|
1166
1180
|
},
|
|
1167
1181
|
"arguments": []
|
|
1168
1182
|
}
|
|
@@ -1174,7 +1188,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1174
1188
|
"terminal": {
|
|
1175
1189
|
"$type": "RuleCall",
|
|
1176
1190
|
"rule": {
|
|
1177
|
-
"$ref": "#/rules@
|
|
1191
|
+
"$ref": "#/rules@46"
|
|
1178
1192
|
},
|
|
1179
1193
|
"arguments": []
|
|
1180
1194
|
},
|
|
@@ -1274,7 +1288,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1274
1288
|
"terminal": {
|
|
1275
1289
|
"$type": "RuleCall",
|
|
1276
1290
|
"rule": {
|
|
1277
|
-
"$ref": "#/rules@
|
|
1291
|
+
"$ref": "#/rules@41"
|
|
1278
1292
|
},
|
|
1279
1293
|
"arguments": []
|
|
1280
1294
|
}
|
|
@@ -1290,7 +1304,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1290
1304
|
"terminal": {
|
|
1291
1305
|
"$type": "RuleCall",
|
|
1292
1306
|
"rule": {
|
|
1293
|
-
"$ref": "#/rules@
|
|
1307
|
+
"$ref": "#/rules@46"
|
|
1294
1308
|
},
|
|
1295
1309
|
"arguments": []
|
|
1296
1310
|
}
|
|
@@ -1359,14 +1373,14 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1359
1373
|
{
|
|
1360
1374
|
"$type": "RuleCall",
|
|
1361
1375
|
"rule": {
|
|
1362
|
-
"$ref": "#/rules@
|
|
1376
|
+
"$ref": "#/rules@26"
|
|
1363
1377
|
},
|
|
1364
1378
|
"arguments": []
|
|
1365
1379
|
},
|
|
1366
1380
|
{
|
|
1367
1381
|
"$type": "RuleCall",
|
|
1368
1382
|
"rule": {
|
|
1369
|
-
"$ref": "#/rules@
|
|
1383
|
+
"$ref": "#/rules@27"
|
|
1370
1384
|
},
|
|
1371
1385
|
"arguments": []
|
|
1372
1386
|
},
|
|
@@ -1400,7 +1414,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1400
1414
|
"terminal": {
|
|
1401
1415
|
"$type": "RuleCall",
|
|
1402
1416
|
"rule": {
|
|
1403
|
-
"$ref": "#/rules@
|
|
1417
|
+
"$ref": "#/rules@47"
|
|
1404
1418
|
},
|
|
1405
1419
|
"arguments": []
|
|
1406
1420
|
}
|
|
@@ -1412,7 +1426,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1412
1426
|
"terminal": {
|
|
1413
1427
|
"$type": "RuleCall",
|
|
1414
1428
|
"rule": {
|
|
1415
|
-
"$ref": "#/rules@
|
|
1429
|
+
"$ref": "#/rules@46"
|
|
1416
1430
|
},
|
|
1417
1431
|
"arguments": []
|
|
1418
1432
|
},
|
|
@@ -1429,7 +1443,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1429
1443
|
"terminal": {
|
|
1430
1444
|
"$type": "RuleCall",
|
|
1431
1445
|
"rule": {
|
|
1432
|
-
"$ref": "#/rules@
|
|
1446
|
+
"$ref": "#/rules@29"
|
|
1433
1447
|
},
|
|
1434
1448
|
"arguments": []
|
|
1435
1449
|
}
|
|
@@ -1465,7 +1479,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1465
1479
|
"terminal": {
|
|
1466
1480
|
"$type": "RuleCall",
|
|
1467
1481
|
"rule": {
|
|
1468
|
-
"$ref": "#/rules@
|
|
1482
|
+
"$ref": "#/rules@47"
|
|
1469
1483
|
},
|
|
1470
1484
|
"arguments": []
|
|
1471
1485
|
}
|
|
@@ -1477,7 +1491,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1477
1491
|
"terminal": {
|
|
1478
1492
|
"$type": "RuleCall",
|
|
1479
1493
|
"rule": {
|
|
1480
|
-
"$ref": "#/rules@
|
|
1494
|
+
"$ref": "#/rules@46"
|
|
1481
1495
|
},
|
|
1482
1496
|
"arguments": []
|
|
1483
1497
|
},
|
|
@@ -1494,7 +1508,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1494
1508
|
"terminal": {
|
|
1495
1509
|
"$type": "RuleCall",
|
|
1496
1510
|
"rule": {
|
|
1497
|
-
"$ref": "#/rules@
|
|
1511
|
+
"$ref": "#/rules@29"
|
|
1498
1512
|
},
|
|
1499
1513
|
"arguments": []
|
|
1500
1514
|
}
|
|
@@ -1534,7 +1548,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1534
1548
|
"terminal": {
|
|
1535
1549
|
"$type": "RuleCall",
|
|
1536
1550
|
"rule": {
|
|
1537
|
-
"$ref": "#/rules@
|
|
1551
|
+
"$ref": "#/rules@31"
|
|
1538
1552
|
},
|
|
1539
1553
|
"arguments": []
|
|
1540
1554
|
},
|
|
@@ -1547,7 +1561,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1547
1561
|
"terminal": {
|
|
1548
1562
|
"$type": "RuleCall",
|
|
1549
1563
|
"rule": {
|
|
1550
|
-
"$ref": "#/rules@
|
|
1564
|
+
"$ref": "#/rules@32"
|
|
1551
1565
|
},
|
|
1552
1566
|
"arguments": []
|
|
1553
1567
|
}
|
|
@@ -1580,7 +1594,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1580
1594
|
"terminal": {
|
|
1581
1595
|
"$type": "RuleCall",
|
|
1582
1596
|
"rule": {
|
|
1583
|
-
"$ref": "#/rules@
|
|
1597
|
+
"$ref": "#/rules@47"
|
|
1584
1598
|
},
|
|
1585
1599
|
"arguments": []
|
|
1586
1600
|
}
|
|
@@ -1592,7 +1606,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1592
1606
|
"terminal": {
|
|
1593
1607
|
"$type": "RuleCall",
|
|
1594
1608
|
"rule": {
|
|
1595
|
-
"$ref": "#/rules@
|
|
1609
|
+
"$ref": "#/rules@46"
|
|
1596
1610
|
},
|
|
1597
1611
|
"arguments": []
|
|
1598
1612
|
},
|
|
@@ -1666,7 +1680,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1666
1680
|
"terminal": {
|
|
1667
1681
|
"$type": "RuleCall",
|
|
1668
1682
|
"rule": {
|
|
1669
|
-
"$ref": "#/rules@
|
|
1683
|
+
"$ref": "#/rules@47"
|
|
1670
1684
|
},
|
|
1671
1685
|
"arguments": []
|
|
1672
1686
|
}
|
|
@@ -1678,7 +1692,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1678
1692
|
"terminal": {
|
|
1679
1693
|
"$type": "RuleCall",
|
|
1680
1694
|
"rule": {
|
|
1681
|
-
"$ref": "#/rules@
|
|
1695
|
+
"$ref": "#/rules@46"
|
|
1682
1696
|
},
|
|
1683
1697
|
"arguments": []
|
|
1684
1698
|
},
|
|
@@ -1707,7 +1721,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1707
1721
|
"terminal": {
|
|
1708
1722
|
"$type": "RuleCall",
|
|
1709
1723
|
"rule": {
|
|
1710
|
-
"$ref": "#/rules@
|
|
1724
|
+
"$ref": "#/rules@47"
|
|
1711
1725
|
},
|
|
1712
1726
|
"arguments": []
|
|
1713
1727
|
}
|
|
@@ -1719,7 +1733,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1719
1733
|
"terminal": {
|
|
1720
1734
|
"$type": "RuleCall",
|
|
1721
1735
|
"rule": {
|
|
1722
|
-
"$ref": "#/rules@
|
|
1736
|
+
"$ref": "#/rules@46"
|
|
1723
1737
|
},
|
|
1724
1738
|
"arguments": []
|
|
1725
1739
|
},
|
|
@@ -1783,7 +1797,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1783
1797
|
"terminal": {
|
|
1784
1798
|
"$type": "RuleCall",
|
|
1785
1799
|
"rule": {
|
|
1786
|
-
"$ref": "#/rules@
|
|
1800
|
+
"$ref": "#/rules@47"
|
|
1787
1801
|
},
|
|
1788
1802
|
"arguments": []
|
|
1789
1803
|
}
|
|
@@ -1795,7 +1809,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1795
1809
|
"terminal": {
|
|
1796
1810
|
"$type": "RuleCall",
|
|
1797
1811
|
"rule": {
|
|
1798
|
-
"$ref": "#/rules@
|
|
1812
|
+
"$ref": "#/rules@46"
|
|
1799
1813
|
},
|
|
1800
1814
|
"arguments": []
|
|
1801
1815
|
},
|
|
@@ -1859,7 +1873,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1859
1873
|
"terminal": {
|
|
1860
1874
|
"$type": "RuleCall",
|
|
1861
1875
|
"rule": {
|
|
1862
|
-
"$ref": "#/rules@
|
|
1876
|
+
"$ref": "#/rules@42"
|
|
1863
1877
|
},
|
|
1864
1878
|
"arguments": []
|
|
1865
1879
|
},
|
|
@@ -1886,7 +1900,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1886
1900
|
"terminal": {
|
|
1887
1901
|
"$type": "RuleCall",
|
|
1888
1902
|
"rule": {
|
|
1889
|
-
"$ref": "#/rules@
|
|
1903
|
+
"$ref": "#/rules@42"
|
|
1890
1904
|
},
|
|
1891
1905
|
"arguments": []
|
|
1892
1906
|
},
|
|
@@ -1919,7 +1933,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1919
1933
|
"terminal": {
|
|
1920
1934
|
"$type": "RuleCall",
|
|
1921
1935
|
"rule": {
|
|
1922
|
-
"$ref": "#/rules@
|
|
1936
|
+
"$ref": "#/rules@47"
|
|
1923
1937
|
},
|
|
1924
1938
|
"arguments": []
|
|
1925
1939
|
}
|
|
@@ -1931,7 +1945,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1931
1945
|
"terminal": {
|
|
1932
1946
|
"$type": "RuleCall",
|
|
1933
1947
|
"rule": {
|
|
1934
|
-
"$ref": "#/rules@
|
|
1948
|
+
"$ref": "#/rules@46"
|
|
1935
1949
|
},
|
|
1936
1950
|
"arguments": []
|
|
1937
1951
|
},
|
|
@@ -1951,7 +1965,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1951
1965
|
"terminal": {
|
|
1952
1966
|
"$type": "RuleCall",
|
|
1953
1967
|
"rule": {
|
|
1954
|
-
"$ref": "#/rules@
|
|
1968
|
+
"$ref": "#/rules@41"
|
|
1955
1969
|
},
|
|
1956
1970
|
"arguments": []
|
|
1957
1971
|
}
|
|
@@ -1975,7 +1989,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
1975
1989
|
"terminal": {
|
|
1976
1990
|
"$type": "RuleCall",
|
|
1977
1991
|
"rule": {
|
|
1978
|
-
"$ref": "#/rules@
|
|
1992
|
+
"$ref": "#/rules@42"
|
|
1979
1993
|
},
|
|
1980
1994
|
"arguments": []
|
|
1981
1995
|
},
|
|
@@ -2029,7 +2043,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2029
2043
|
"terminal": {
|
|
2030
2044
|
"$type": "RuleCall",
|
|
2031
2045
|
"rule": {
|
|
2032
|
-
"$ref": "#/rules@
|
|
2046
|
+
"$ref": "#/rules@47"
|
|
2033
2047
|
},
|
|
2034
2048
|
"arguments": []
|
|
2035
2049
|
}
|
|
@@ -2041,7 +2055,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2041
2055
|
"terminal": {
|
|
2042
2056
|
"$type": "RuleCall",
|
|
2043
2057
|
"rule": {
|
|
2044
|
-
"$ref": "#/rules@
|
|
2058
|
+
"$ref": "#/rules@46"
|
|
2045
2059
|
},
|
|
2046
2060
|
"arguments": []
|
|
2047
2061
|
},
|
|
@@ -2097,7 +2111,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2097
2111
|
"terminal": {
|
|
2098
2112
|
"$type": "RuleCall",
|
|
2099
2113
|
"rule": {
|
|
2100
|
-
"$ref": "#/rules@
|
|
2114
|
+
"$ref": "#/rules@47"
|
|
2101
2115
|
},
|
|
2102
2116
|
"arguments": []
|
|
2103
2117
|
}
|
|
@@ -2109,7 +2123,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2109
2123
|
"terminal": {
|
|
2110
2124
|
"$type": "RuleCall",
|
|
2111
2125
|
"rule": {
|
|
2112
|
-
"$ref": "#/rules@
|
|
2126
|
+
"$ref": "#/rules@46"
|
|
2113
2127
|
},
|
|
2114
2128
|
"arguments": []
|
|
2115
2129
|
},
|
|
@@ -2167,7 +2181,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2167
2181
|
"terminal": {
|
|
2168
2182
|
"$type": "RuleCall",
|
|
2169
2183
|
"rule": {
|
|
2170
|
-
"$ref": "#/rules@
|
|
2184
|
+
"$ref": "#/rules@47"
|
|
2171
2185
|
},
|
|
2172
2186
|
"arguments": []
|
|
2173
2187
|
}
|
|
@@ -2179,7 +2193,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2179
2193
|
"terminal": {
|
|
2180
2194
|
"$type": "RuleCall",
|
|
2181
2195
|
"rule": {
|
|
2182
|
-
"$ref": "#/rules@
|
|
2196
|
+
"$ref": "#/rules@46"
|
|
2183
2197
|
},
|
|
2184
2198
|
"arguments": []
|
|
2185
2199
|
},
|
|
@@ -2283,7 +2297,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2283
2297
|
{
|
|
2284
2298
|
"$type": "RuleCall",
|
|
2285
2299
|
"rule": {
|
|
2286
|
-
"$ref": "#/rules@
|
|
2300
|
+
"$ref": "#/rules@31"
|
|
2287
2301
|
},
|
|
2288
2302
|
"arguments": []
|
|
2289
2303
|
}
|
|
@@ -2310,7 +2324,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2310
2324
|
"terminal": {
|
|
2311
2325
|
"$type": "RuleCall",
|
|
2312
2326
|
"rule": {
|
|
2313
|
-
"$ref": "#/rules@
|
|
2327
|
+
"$ref": "#/rules@47"
|
|
2314
2328
|
},
|
|
2315
2329
|
"arguments": []
|
|
2316
2330
|
}
|
|
@@ -2322,7 +2336,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2322
2336
|
"terminal": {
|
|
2323
2337
|
"$type": "RuleCall",
|
|
2324
2338
|
"rule": {
|
|
2325
|
-
"$ref": "#/rules@
|
|
2339
|
+
"$ref": "#/rules@46"
|
|
2326
2340
|
},
|
|
2327
2341
|
"arguments": []
|
|
2328
2342
|
},
|
|
@@ -2374,7 +2388,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2374
2388
|
"terminal": {
|
|
2375
2389
|
"$type": "RuleCall",
|
|
2376
2390
|
"rule": {
|
|
2377
|
-
"$ref": "#/rules@
|
|
2391
|
+
"$ref": "#/rules@41"
|
|
2378
2392
|
},
|
|
2379
2393
|
"arguments": []
|
|
2380
2394
|
}
|
|
@@ -2390,7 +2404,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2390
2404
|
"terminal": {
|
|
2391
2405
|
"$type": "RuleCall",
|
|
2392
2406
|
"rule": {
|
|
2393
|
-
"$ref": "#/rules@
|
|
2407
|
+
"$ref": "#/rules@28"
|
|
2394
2408
|
},
|
|
2395
2409
|
"arguments": []
|
|
2396
2410
|
}
|
|
@@ -2402,7 +2416,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2402
2416
|
"terminal": {
|
|
2403
2417
|
"$type": "RuleCall",
|
|
2404
2418
|
"rule": {
|
|
2405
|
-
"$ref": "#/rules@
|
|
2419
|
+
"$ref": "#/rules@30"
|
|
2406
2420
|
},
|
|
2407
2421
|
"arguments": []
|
|
2408
2422
|
},
|
|
@@ -2415,7 +2429,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2415
2429
|
"terminal": {
|
|
2416
2430
|
"$type": "RuleCall",
|
|
2417
2431
|
"rule": {
|
|
2418
|
-
"$ref": "#/rules@
|
|
2432
|
+
"$ref": "#/rules@46"
|
|
2419
2433
|
},
|
|
2420
2434
|
"arguments": []
|
|
2421
2435
|
},
|
|
@@ -2444,7 +2458,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2444
2458
|
"terminal": {
|
|
2445
2459
|
"$type": "RuleCall",
|
|
2446
2460
|
"rule": {
|
|
2447
|
-
"$ref": "#/rules@
|
|
2461
|
+
"$ref": "#/rules@41"
|
|
2448
2462
|
},
|
|
2449
2463
|
"arguments": []
|
|
2450
2464
|
}
|
|
@@ -2460,7 +2474,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2460
2474
|
"terminal": {
|
|
2461
2475
|
"$type": "RuleCall",
|
|
2462
2476
|
"rule": {
|
|
2463
|
-
"$ref": "#/rules@
|
|
2477
|
+
"$ref": "#/rules@28"
|
|
2464
2478
|
},
|
|
2465
2479
|
"arguments": []
|
|
2466
2480
|
}
|
|
@@ -2472,7 +2486,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2472
2486
|
"terminal": {
|
|
2473
2487
|
"$type": "RuleCall",
|
|
2474
2488
|
"rule": {
|
|
2475
|
-
"$ref": "#/rules@
|
|
2489
|
+
"$ref": "#/rules@30"
|
|
2476
2490
|
},
|
|
2477
2491
|
"arguments": []
|
|
2478
2492
|
},
|
|
@@ -2485,7 +2499,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2485
2499
|
"terminal": {
|
|
2486
2500
|
"$type": "RuleCall",
|
|
2487
2501
|
"rule": {
|
|
2488
|
-
"$ref": "#/rules@
|
|
2502
|
+
"$ref": "#/rules@46"
|
|
2489
2503
|
},
|
|
2490
2504
|
"arguments": []
|
|
2491
2505
|
},
|
|
@@ -2514,7 +2528,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2514
2528
|
"terminal": {
|
|
2515
2529
|
"$type": "RuleCall",
|
|
2516
2530
|
"rule": {
|
|
2517
|
-
"$ref": "#/rules@
|
|
2531
|
+
"$ref": "#/rules@41"
|
|
2518
2532
|
},
|
|
2519
2533
|
"arguments": []
|
|
2520
2534
|
}
|
|
@@ -2530,7 +2544,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2530
2544
|
"terminal": {
|
|
2531
2545
|
"$type": "RuleCall",
|
|
2532
2546
|
"rule": {
|
|
2533
|
-
"$ref": "#/rules@
|
|
2547
|
+
"$ref": "#/rules@28"
|
|
2534
2548
|
},
|
|
2535
2549
|
"arguments": []
|
|
2536
2550
|
}
|
|
@@ -2542,7 +2556,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2542
2556
|
"terminal": {
|
|
2543
2557
|
"$type": "RuleCall",
|
|
2544
2558
|
"rule": {
|
|
2545
|
-
"$ref": "#/rules@
|
|
2559
|
+
"$ref": "#/rules@30"
|
|
2546
2560
|
},
|
|
2547
2561
|
"arguments": []
|
|
2548
2562
|
},
|
|
@@ -2564,7 +2578,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2564
2578
|
"terminal": {
|
|
2565
2579
|
"$type": "RuleCall",
|
|
2566
2580
|
"rule": {
|
|
2567
|
-
"$ref": "#/rules@
|
|
2581
|
+
"$ref": "#/rules@42"
|
|
2568
2582
|
},
|
|
2569
2583
|
"arguments": []
|
|
2570
2584
|
},
|
|
@@ -2579,7 +2593,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2579
2593
|
"terminal": {
|
|
2580
2594
|
"$type": "RuleCall",
|
|
2581
2595
|
"rule": {
|
|
2582
|
-
"$ref": "#/rules@
|
|
2596
|
+
"$ref": "#/rules@46"
|
|
2583
2597
|
},
|
|
2584
2598
|
"arguments": []
|
|
2585
2599
|
},
|
|
@@ -2618,7 +2632,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2618
2632
|
"terminal": {
|
|
2619
2633
|
"$type": "RuleCall",
|
|
2620
2634
|
"rule": {
|
|
2621
|
-
"$ref": "#/rules@
|
|
2635
|
+
"$ref": "#/rules@41"
|
|
2622
2636
|
},
|
|
2623
2637
|
"arguments": []
|
|
2624
2638
|
}
|
|
@@ -2637,7 +2651,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2637
2651
|
"terminal": {
|
|
2638
2652
|
"$type": "RuleCall",
|
|
2639
2653
|
"rule": {
|
|
2640
|
-
"$ref": "#/rules@
|
|
2654
|
+
"$ref": "#/rules@25"
|
|
2641
2655
|
},
|
|
2642
2656
|
"arguments": []
|
|
2643
2657
|
}
|
|
@@ -2656,7 +2670,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2656
2670
|
"terminal": {
|
|
2657
2671
|
"$type": "RuleCall",
|
|
2658
2672
|
"rule": {
|
|
2659
|
-
"$ref": "#/rules@
|
|
2673
|
+
"$ref": "#/rules@25"
|
|
2660
2674
|
},
|
|
2661
2675
|
"arguments": []
|
|
2662
2676
|
}
|
|
@@ -2678,7 +2692,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2678
2692
|
"terminal": {
|
|
2679
2693
|
"$type": "RuleCall",
|
|
2680
2694
|
"rule": {
|
|
2681
|
-
"$ref": "#/rules@
|
|
2695
|
+
"$ref": "#/rules@46"
|
|
2682
2696
|
},
|
|
2683
2697
|
"arguments": []
|
|
2684
2698
|
},
|
|
@@ -2687,28 +2701,16 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2687
2701
|
{
|
|
2688
2702
|
"$type": "Group",
|
|
2689
2703
|
"elements": [
|
|
2690
|
-
{
|
|
2691
|
-
"$type": "Keyword",
|
|
2692
|
-
"value": "from"
|
|
2693
|
-
},
|
|
2694
2704
|
{
|
|
2695
2705
|
"$type": "Assignment",
|
|
2696
|
-
"feature": "
|
|
2706
|
+
"feature": "transitions",
|
|
2697
2707
|
"operator": "+=",
|
|
2698
2708
|
"terminal": {
|
|
2699
|
-
"$type": "
|
|
2700
|
-
"
|
|
2701
|
-
"$ref": "#/rules@
|
|
2702
|
-
},
|
|
2703
|
-
"terminal": {
|
|
2704
|
-
"$type": "RuleCall",
|
|
2705
|
-
"rule": {
|
|
2706
|
-
"$ref": "#/rules@46"
|
|
2707
|
-
},
|
|
2708
|
-
"arguments": []
|
|
2709
|
+
"$type": "RuleCall",
|
|
2710
|
+
"rule": {
|
|
2711
|
+
"$ref": "#/rules@24"
|
|
2709
2712
|
},
|
|
2710
|
-
"
|
|
2711
|
-
"isMulti": false
|
|
2713
|
+
"arguments": []
|
|
2712
2714
|
}
|
|
2713
2715
|
},
|
|
2714
2716
|
{
|
|
@@ -2716,26 +2718,19 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2716
2718
|
"elements": [
|
|
2717
2719
|
{
|
|
2718
2720
|
"$type": "Keyword",
|
|
2719
|
-
"value": "
|
|
2721
|
+
"value": ",",
|
|
2722
|
+
"cardinality": "?"
|
|
2720
2723
|
},
|
|
2721
2724
|
{
|
|
2722
2725
|
"$type": "Assignment",
|
|
2723
|
-
"feature": "
|
|
2726
|
+
"feature": "transitions",
|
|
2724
2727
|
"operator": "+=",
|
|
2725
2728
|
"terminal": {
|
|
2726
|
-
"$type": "
|
|
2727
|
-
"
|
|
2728
|
-
"$ref": "#/rules@
|
|
2729
|
-
},
|
|
2730
|
-
"terminal": {
|
|
2731
|
-
"$type": "RuleCall",
|
|
2732
|
-
"rule": {
|
|
2733
|
-
"$ref": "#/rules@46"
|
|
2734
|
-
},
|
|
2735
|
-
"arguments": []
|
|
2729
|
+
"$type": "RuleCall",
|
|
2730
|
+
"rule": {
|
|
2731
|
+
"$ref": "#/rules@24"
|
|
2736
2732
|
},
|
|
2737
|
-
"
|
|
2738
|
-
"isMulti": false
|
|
2733
|
+
"arguments": []
|
|
2739
2734
|
}
|
|
2740
2735
|
}
|
|
2741
2736
|
],
|
|
@@ -2749,21 +2744,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2749
2744
|
"elements": [
|
|
2750
2745
|
{
|
|
2751
2746
|
"$type": "Keyword",
|
|
2752
|
-
"value": "
|
|
2747
|
+
"value": "emits"
|
|
2753
2748
|
},
|
|
2754
2749
|
{
|
|
2755
2750
|
"$type": "Assignment",
|
|
2756
|
-
"feature": "
|
|
2751
|
+
"feature": "emits",
|
|
2757
2752
|
"operator": "+=",
|
|
2758
2753
|
"terminal": {
|
|
2759
2754
|
"$type": "CrossReference",
|
|
2760
2755
|
"type": {
|
|
2761
|
-
"$ref": "#/rules@
|
|
2756
|
+
"$ref": "#/rules@26"
|
|
2762
2757
|
},
|
|
2763
2758
|
"terminal": {
|
|
2764
2759
|
"$type": "RuleCall",
|
|
2765
2760
|
"rule": {
|
|
2766
|
-
"$ref": "#/rules@
|
|
2761
|
+
"$ref": "#/rules@42"
|
|
2767
2762
|
},
|
|
2768
2763
|
"arguments": []
|
|
2769
2764
|
},
|
|
@@ -2776,21 +2771,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2776
2771
|
"elements": [
|
|
2777
2772
|
{
|
|
2778
2773
|
"$type": "Keyword",
|
|
2779
|
-
"value": "
|
|
2774
|
+
"value": ","
|
|
2780
2775
|
},
|
|
2781
2776
|
{
|
|
2782
2777
|
"$type": "Assignment",
|
|
2783
|
-
"feature": "
|
|
2778
|
+
"feature": "emits",
|
|
2784
2779
|
"operator": "+=",
|
|
2785
2780
|
"terminal": {
|
|
2786
2781
|
"$type": "CrossReference",
|
|
2787
2782
|
"type": {
|
|
2788
|
-
"$ref": "#/rules@
|
|
2783
|
+
"$ref": "#/rules@26"
|
|
2789
2784
|
},
|
|
2790
2785
|
"terminal": {
|
|
2791
2786
|
"$type": "RuleCall",
|
|
2792
2787
|
"rule": {
|
|
2793
|
-
"$ref": "#/rules@
|
|
2788
|
+
"$ref": "#/rules@42"
|
|
2794
2789
|
},
|
|
2795
2790
|
"arguments": []
|
|
2796
2791
|
},
|
|
@@ -2809,21 +2804,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2809
2804
|
"elements": [
|
|
2810
2805
|
{
|
|
2811
2806
|
"$type": "Keyword",
|
|
2812
|
-
"value": "
|
|
2807
|
+
"value": "errors"
|
|
2813
2808
|
},
|
|
2814
2809
|
{
|
|
2815
2810
|
"$type": "Assignment",
|
|
2816
|
-
"feature": "
|
|
2811
|
+
"feature": "errors",
|
|
2817
2812
|
"operator": "+=",
|
|
2818
2813
|
"terminal": {
|
|
2819
2814
|
"$type": "CrossReference",
|
|
2820
2815
|
"type": {
|
|
2821
|
-
"$ref": "#/rules@
|
|
2816
|
+
"$ref": "#/rules@27"
|
|
2822
2817
|
},
|
|
2823
2818
|
"terminal": {
|
|
2824
2819
|
"$type": "RuleCall",
|
|
2825
2820
|
"rule": {
|
|
2826
|
-
"$ref": "#/rules@
|
|
2821
|
+
"$ref": "#/rules@42"
|
|
2827
2822
|
},
|
|
2828
2823
|
"arguments": []
|
|
2829
2824
|
},
|
|
@@ -2840,17 +2835,17 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2840
2835
|
},
|
|
2841
2836
|
{
|
|
2842
2837
|
"$type": "Assignment",
|
|
2843
|
-
"feature": "
|
|
2838
|
+
"feature": "errors",
|
|
2844
2839
|
"operator": "+=",
|
|
2845
2840
|
"terminal": {
|
|
2846
2841
|
"$type": "CrossReference",
|
|
2847
2842
|
"type": {
|
|
2848
|
-
"$ref": "#/rules@
|
|
2843
|
+
"$ref": "#/rules@27"
|
|
2849
2844
|
},
|
|
2850
2845
|
"terminal": {
|
|
2851
2846
|
"$type": "RuleCall",
|
|
2852
2847
|
"rule": {
|
|
2853
|
-
"$ref": "#/rules@
|
|
2848
|
+
"$ref": "#/rules@42"
|
|
2854
2849
|
},
|
|
2855
2850
|
"arguments": []
|
|
2856
2851
|
},
|
|
@@ -2863,27 +2858,35 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2863
2858
|
}
|
|
2864
2859
|
],
|
|
2865
2860
|
"cardinality": "?"
|
|
2866
|
-
}
|
|
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": [
|
|
2867
2874
|
{
|
|
2868
2875
|
"$type": "Group",
|
|
2869
2876
|
"elements": [
|
|
2870
|
-
{
|
|
2871
|
-
"$type": "Keyword",
|
|
2872
|
-
"value": "errors"
|
|
2873
|
-
},
|
|
2874
2877
|
{
|
|
2875
2878
|
"$type": "Assignment",
|
|
2876
|
-
"feature": "
|
|
2879
|
+
"feature": "from",
|
|
2877
2880
|
"operator": "+=",
|
|
2878
2881
|
"terminal": {
|
|
2879
2882
|
"$type": "CrossReference",
|
|
2880
2883
|
"type": {
|
|
2881
|
-
"$ref": "#/rules@
|
|
2884
|
+
"$ref": "#/rules@19"
|
|
2882
2885
|
},
|
|
2883
2886
|
"terminal": {
|
|
2884
2887
|
"$type": "RuleCall",
|
|
2885
2888
|
"rule": {
|
|
2886
|
-
"$ref": "#/rules@
|
|
2889
|
+
"$ref": "#/rules@47"
|
|
2887
2890
|
},
|
|
2888
2891
|
"arguments": []
|
|
2889
2892
|
},
|
|
@@ -2896,21 +2899,21 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2896
2899
|
"elements": [
|
|
2897
2900
|
{
|
|
2898
2901
|
"$type": "Keyword",
|
|
2899
|
-
"value": "
|
|
2902
|
+
"value": "|"
|
|
2900
2903
|
},
|
|
2901
2904
|
{
|
|
2902
2905
|
"$type": "Assignment",
|
|
2903
|
-
"feature": "
|
|
2906
|
+
"feature": "from",
|
|
2904
2907
|
"operator": "+=",
|
|
2905
2908
|
"terminal": {
|
|
2906
2909
|
"$type": "CrossReference",
|
|
2907
2910
|
"type": {
|
|
2908
|
-
"$ref": "#/rules@
|
|
2911
|
+
"$ref": "#/rules@19"
|
|
2909
2912
|
},
|
|
2910
2913
|
"terminal": {
|
|
2911
2914
|
"$type": "RuleCall",
|
|
2912
2915
|
"rule": {
|
|
2913
|
-
"$ref": "#/rules@
|
|
2916
|
+
"$ref": "#/rules@47"
|
|
2914
2917
|
},
|
|
2915
2918
|
"arguments": []
|
|
2916
2919
|
},
|
|
@@ -2923,6 +2926,60 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2923
2926
|
}
|
|
2924
2927
|
],
|
|
2925
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": "*"
|
|
2926
2983
|
}
|
|
2927
2984
|
]
|
|
2928
2985
|
},
|
|
@@ -2943,7 +3000,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2943
3000
|
"terminal": {
|
|
2944
3001
|
"$type": "RuleCall",
|
|
2945
3002
|
"rule": {
|
|
2946
|
-
"$ref": "#/rules@
|
|
3003
|
+
"$ref": "#/rules@41"
|
|
2947
3004
|
},
|
|
2948
3005
|
"arguments": []
|
|
2949
3006
|
}
|
|
@@ -2959,7 +3016,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2959
3016
|
"terminal": {
|
|
2960
3017
|
"$type": "RuleCall",
|
|
2961
3018
|
"rule": {
|
|
2962
|
-
"$ref": "#/rules@
|
|
3019
|
+
"$ref": "#/rules@28"
|
|
2963
3020
|
},
|
|
2964
3021
|
"arguments": []
|
|
2965
3022
|
}
|
|
@@ -2971,7 +3028,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2971
3028
|
"terminal": {
|
|
2972
3029
|
"$type": "RuleCall",
|
|
2973
3030
|
"rule": {
|
|
2974
|
-
"$ref": "#/rules@
|
|
3031
|
+
"$ref": "#/rules@30"
|
|
2975
3032
|
},
|
|
2976
3033
|
"arguments": []
|
|
2977
3034
|
},
|
|
@@ -2984,7 +3041,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
2984
3041
|
"terminal": {
|
|
2985
3042
|
"$type": "RuleCall",
|
|
2986
3043
|
"rule": {
|
|
2987
|
-
"$ref": "#/rules@
|
|
3044
|
+
"$ref": "#/rules@46"
|
|
2988
3045
|
},
|
|
2989
3046
|
"arguments": []
|
|
2990
3047
|
},
|
|
@@ -3023,7 +3080,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3023
3080
|
"terminal": {
|
|
3024
3081
|
"$type": "RuleCall",
|
|
3025
3082
|
"rule": {
|
|
3026
|
-
"$ref": "#/rules@
|
|
3083
|
+
"$ref": "#/rules@47"
|
|
3027
3084
|
},
|
|
3028
3085
|
"arguments": []
|
|
3029
3086
|
}
|
|
@@ -3035,7 +3092,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3035
3092
|
"terminal": {
|
|
3036
3093
|
"$type": "RuleCall",
|
|
3037
3094
|
"rule": {
|
|
3038
|
-
"$ref": "#/rules@
|
|
3095
|
+
"$ref": "#/rules@46"
|
|
3039
3096
|
},
|
|
3040
3097
|
"arguments": []
|
|
3041
3098
|
},
|
|
@@ -3099,7 +3156,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3099
3156
|
"terminal": {
|
|
3100
3157
|
"$type": "RuleCall",
|
|
3101
3158
|
"rule": {
|
|
3102
|
-
"$ref": "#/rules@
|
|
3159
|
+
"$ref": "#/rules@47"
|
|
3103
3160
|
},
|
|
3104
3161
|
"arguments": []
|
|
3105
3162
|
}
|
|
@@ -3111,7 +3168,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3111
3168
|
"terminal": {
|
|
3112
3169
|
"$type": "RuleCall",
|
|
3113
3170
|
"rule": {
|
|
3114
|
-
"$ref": "#/rules@
|
|
3171
|
+
"$ref": "#/rules@46"
|
|
3115
3172
|
},
|
|
3116
3173
|
"arguments": []
|
|
3117
3174
|
},
|
|
@@ -3171,7 +3228,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3171
3228
|
"terminal": {
|
|
3172
3229
|
"$type": "RuleCall",
|
|
3173
3230
|
"rule": {
|
|
3174
|
-
"$ref": "#/rules@
|
|
3231
|
+
"$ref": "#/rules@29"
|
|
3175
3232
|
},
|
|
3176
3233
|
"arguments": []
|
|
3177
3234
|
}
|
|
@@ -3188,7 +3245,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3188
3245
|
"terminal": {
|
|
3189
3246
|
"$type": "RuleCall",
|
|
3190
3247
|
"rule": {
|
|
3191
|
-
"$ref": "#/rules@
|
|
3248
|
+
"$ref": "#/rules@42"
|
|
3192
3249
|
},
|
|
3193
3250
|
"arguments": []
|
|
3194
3251
|
},
|
|
@@ -3268,7 +3325,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3268
3325
|
"terminal": {
|
|
3269
3326
|
"$type": "RuleCall",
|
|
3270
3327
|
"rule": {
|
|
3271
|
-
"$ref": "#/rules@
|
|
3328
|
+
"$ref": "#/rules@45"
|
|
3272
3329
|
},
|
|
3273
3330
|
"arguments": []
|
|
3274
3331
|
}
|
|
@@ -3287,7 +3344,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3287
3344
|
"terminal": {
|
|
3288
3345
|
"$type": "RuleCall",
|
|
3289
3346
|
"rule": {
|
|
3290
|
-
"$ref": "#/rules@
|
|
3347
|
+
"$ref": "#/rules@45"
|
|
3291
3348
|
},
|
|
3292
3349
|
"arguments": []
|
|
3293
3350
|
}
|
|
@@ -3332,7 +3389,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3332
3389
|
"terminal": {
|
|
3333
3390
|
"$type": "RuleCall",
|
|
3334
3391
|
"rule": {
|
|
3335
|
-
"$ref": "#/rules@
|
|
3392
|
+
"$ref": "#/rules@47"
|
|
3336
3393
|
},
|
|
3337
3394
|
"arguments": []
|
|
3338
3395
|
}
|
|
@@ -3344,7 +3401,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3344
3401
|
"terminal": {
|
|
3345
3402
|
"$type": "RuleCall",
|
|
3346
3403
|
"rule": {
|
|
3347
|
-
"$ref": "#/rules@
|
|
3404
|
+
"$ref": "#/rules@46"
|
|
3348
3405
|
},
|
|
3349
3406
|
"arguments": []
|
|
3350
3407
|
},
|
|
@@ -3361,7 +3418,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3361
3418
|
"terminal": {
|
|
3362
3419
|
"$type": "RuleCall",
|
|
3363
3420
|
"rule": {
|
|
3364
|
-
"$ref": "#/rules@
|
|
3421
|
+
"$ref": "#/rules@32"
|
|
3365
3422
|
},
|
|
3366
3423
|
"arguments": []
|
|
3367
3424
|
}
|
|
@@ -3382,7 +3439,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3382
3439
|
"definition": {
|
|
3383
3440
|
"$type": "RuleCall",
|
|
3384
3441
|
"rule": {
|
|
3385
|
-
"$ref": "#/rules@
|
|
3442
|
+
"$ref": "#/rules@33"
|
|
3386
3443
|
},
|
|
3387
3444
|
"arguments": []
|
|
3388
3445
|
},
|
|
@@ -3403,7 +3460,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3403
3460
|
{
|
|
3404
3461
|
"$type": "RuleCall",
|
|
3405
3462
|
"rule": {
|
|
3406
|
-
"$ref": "#/rules@
|
|
3463
|
+
"$ref": "#/rules@34"
|
|
3407
3464
|
},
|
|
3408
3465
|
"arguments": []
|
|
3409
3466
|
},
|
|
@@ -3435,7 +3492,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3435
3492
|
"terminal": {
|
|
3436
3493
|
"$type": "RuleCall",
|
|
3437
3494
|
"rule": {
|
|
3438
|
-
"$ref": "#/rules@
|
|
3495
|
+
"$ref": "#/rules@34"
|
|
3439
3496
|
},
|
|
3440
3497
|
"arguments": []
|
|
3441
3498
|
}
|
|
@@ -3462,7 +3519,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3462
3519
|
{
|
|
3463
3520
|
"$type": "RuleCall",
|
|
3464
3521
|
"rule": {
|
|
3465
|
-
"$ref": "#/rules@
|
|
3522
|
+
"$ref": "#/rules@35"
|
|
3466
3523
|
},
|
|
3467
3524
|
"arguments": []
|
|
3468
3525
|
},
|
|
@@ -3494,7 +3551,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3494
3551
|
"terminal": {
|
|
3495
3552
|
"$type": "RuleCall",
|
|
3496
3553
|
"rule": {
|
|
3497
|
-
"$ref": "#/rules@
|
|
3554
|
+
"$ref": "#/rules@35"
|
|
3498
3555
|
},
|
|
3499
3556
|
"arguments": []
|
|
3500
3557
|
}
|
|
@@ -3521,7 +3578,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3521
3578
|
{
|
|
3522
3579
|
"$type": "RuleCall",
|
|
3523
3580
|
"rule": {
|
|
3524
|
-
"$ref": "#/rules@
|
|
3581
|
+
"$ref": "#/rules@36"
|
|
3525
3582
|
},
|
|
3526
3583
|
"arguments": []
|
|
3527
3584
|
},
|
|
@@ -3553,7 +3610,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3553
3610
|
"terminal": {
|
|
3554
3611
|
"$type": "RuleCall",
|
|
3555
3612
|
"rule": {
|
|
3556
|
-
"$ref": "#/rules@
|
|
3613
|
+
"$ref": "#/rules@36"
|
|
3557
3614
|
},
|
|
3558
3615
|
"arguments": []
|
|
3559
3616
|
}
|
|
@@ -3580,7 +3637,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3580
3637
|
{
|
|
3581
3638
|
"$type": "RuleCall",
|
|
3582
3639
|
"rule": {
|
|
3583
|
-
"$ref": "#/rules@
|
|
3640
|
+
"$ref": "#/rules@37"
|
|
3584
3641
|
},
|
|
3585
3642
|
"arguments": []
|
|
3586
3643
|
},
|
|
@@ -3640,7 +3697,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3640
3697
|
"terminal": {
|
|
3641
3698
|
"$type": "RuleCall",
|
|
3642
3699
|
"rule": {
|
|
3643
|
-
"$ref": "#/rules@
|
|
3700
|
+
"$ref": "#/rules@37"
|
|
3644
3701
|
},
|
|
3645
3702
|
"arguments": []
|
|
3646
3703
|
}
|
|
@@ -3670,7 +3727,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3670
3727
|
"terminal": {
|
|
3671
3728
|
"$type": "RuleCall",
|
|
3672
3729
|
"rule": {
|
|
3673
|
-
"$ref": "#/rules@
|
|
3730
|
+
"$ref": "#/rules@37"
|
|
3674
3731
|
},
|
|
3675
3732
|
"arguments": []
|
|
3676
3733
|
}
|
|
@@ -3686,7 +3743,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3686
3743
|
"terminal": {
|
|
3687
3744
|
"$type": "RuleCall",
|
|
3688
3745
|
"rule": {
|
|
3689
|
-
"$ref": "#/rules@
|
|
3746
|
+
"$ref": "#/rules@37"
|
|
3690
3747
|
},
|
|
3691
3748
|
"arguments": []
|
|
3692
3749
|
}
|
|
@@ -3733,7 +3790,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3733
3790
|
"terminal": {
|
|
3734
3791
|
"$type": "RuleCall",
|
|
3735
3792
|
"rule": {
|
|
3736
|
-
"$ref": "#/rules@
|
|
3793
|
+
"$ref": "#/rules@37"
|
|
3737
3794
|
},
|
|
3738
3795
|
"arguments": []
|
|
3739
3796
|
}
|
|
@@ -3743,7 +3800,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3743
3800
|
{
|
|
3744
3801
|
"$type": "RuleCall",
|
|
3745
3802
|
"rule": {
|
|
3746
|
-
"$ref": "#/rules@
|
|
3803
|
+
"$ref": "#/rules@38"
|
|
3747
3804
|
},
|
|
3748
3805
|
"arguments": []
|
|
3749
3806
|
}
|
|
@@ -3766,7 +3823,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3766
3823
|
{
|
|
3767
3824
|
"$type": "RuleCall",
|
|
3768
3825
|
"rule": {
|
|
3769
|
-
"$ref": "#/rules@
|
|
3826
|
+
"$ref": "#/rules@39"
|
|
3770
3827
|
},
|
|
3771
3828
|
"arguments": []
|
|
3772
3829
|
},
|
|
@@ -3793,7 +3850,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3793
3850
|
"terminal": {
|
|
3794
3851
|
"$type": "RuleCall",
|
|
3795
3852
|
"rule": {
|
|
3796
|
-
"$ref": "#/rules@
|
|
3853
|
+
"$ref": "#/rules@41"
|
|
3797
3854
|
},
|
|
3798
3855
|
"arguments": []
|
|
3799
3856
|
}
|
|
@@ -3827,7 +3884,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3827
3884
|
{
|
|
3828
3885
|
"$type": "RuleCall",
|
|
3829
3886
|
"rule": {
|
|
3830
|
-
"$ref": "#/rules@
|
|
3887
|
+
"$ref": "#/rules@32"
|
|
3831
3888
|
},
|
|
3832
3889
|
"arguments": []
|
|
3833
3890
|
},
|
|
@@ -3862,7 +3919,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3862
3919
|
"terminal": {
|
|
3863
3920
|
"$type": "RuleCall",
|
|
3864
3921
|
"rule": {
|
|
3865
|
-
"$ref": "#/rules@
|
|
3922
|
+
"$ref": "#/rules@32"
|
|
3866
3923
|
},
|
|
3867
3924
|
"arguments": []
|
|
3868
3925
|
}
|
|
@@ -3898,7 +3955,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3898
3955
|
"terminal": {
|
|
3899
3956
|
"$type": "RuleCall",
|
|
3900
3957
|
"rule": {
|
|
3901
|
-
"$ref": "#/rules@
|
|
3958
|
+
"$ref": "#/rules@32"
|
|
3902
3959
|
},
|
|
3903
3960
|
"arguments": []
|
|
3904
3961
|
}
|
|
@@ -3934,7 +3991,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3934
3991
|
"terminal": {
|
|
3935
3992
|
"$type": "RuleCall",
|
|
3936
3993
|
"rule": {
|
|
3937
|
-
"$ref": "#/rules@
|
|
3994
|
+
"$ref": "#/rules@32"
|
|
3938
3995
|
},
|
|
3939
3996
|
"arguments": []
|
|
3940
3997
|
}
|
|
@@ -3970,7 +4027,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3970
4027
|
"terminal": {
|
|
3971
4028
|
"$type": "RuleCall",
|
|
3972
4029
|
"rule": {
|
|
3973
|
-
"$ref": "#/rules@
|
|
4030
|
+
"$ref": "#/rules@32"
|
|
3974
4031
|
},
|
|
3975
4032
|
"arguments": []
|
|
3976
4033
|
}
|
|
@@ -3986,7 +4043,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
3986
4043
|
"terminal": {
|
|
3987
4044
|
"$type": "RuleCall",
|
|
3988
4045
|
"rule": {
|
|
3989
|
-
"$ref": "#/rules@
|
|
4046
|
+
"$ref": "#/rules@46"
|
|
3990
4047
|
},
|
|
3991
4048
|
"arguments": []
|
|
3992
4049
|
}
|
|
@@ -4036,7 +4093,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4036
4093
|
"terminal": {
|
|
4037
4094
|
"$type": "RuleCall",
|
|
4038
4095
|
"rule": {
|
|
4039
|
-
"$ref": "#/rules@
|
|
4096
|
+
"$ref": "#/rules@32"
|
|
4040
4097
|
},
|
|
4041
4098
|
"arguments": []
|
|
4042
4099
|
}
|
|
@@ -4052,7 +4109,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4052
4109
|
"terminal": {
|
|
4053
4110
|
"$type": "RuleCall",
|
|
4054
4111
|
"rule": {
|
|
4055
|
-
"$ref": "#/rules@
|
|
4112
|
+
"$ref": "#/rules@40"
|
|
4056
4113
|
},
|
|
4057
4114
|
"arguments": []
|
|
4058
4115
|
}
|
|
@@ -4068,7 +4125,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4068
4125
|
"terminal": {
|
|
4069
4126
|
"$type": "RuleCall",
|
|
4070
4127
|
"rule": {
|
|
4071
|
-
"$ref": "#/rules@
|
|
4128
|
+
"$ref": "#/rules@32"
|
|
4072
4129
|
},
|
|
4073
4130
|
"arguments": []
|
|
4074
4131
|
}
|
|
@@ -4136,7 +4193,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4136
4193
|
"terminal": {
|
|
4137
4194
|
"$type": "RuleCall",
|
|
4138
4195
|
"rule": {
|
|
4139
|
-
"$ref": "#/rules@
|
|
4196
|
+
"$ref": "#/rules@44"
|
|
4140
4197
|
},
|
|
4141
4198
|
"arguments": []
|
|
4142
4199
|
}
|
|
@@ -4170,7 +4227,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4170
4227
|
"terminal": {
|
|
4171
4228
|
"$type": "RuleCall",
|
|
4172
4229
|
"rule": {
|
|
4173
|
-
"$ref": "#/rules@
|
|
4230
|
+
"$ref": "#/rules@45"
|
|
4174
4231
|
},
|
|
4175
4232
|
"arguments": []
|
|
4176
4233
|
}
|
|
@@ -4194,7 +4251,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4194
4251
|
"terminal": {
|
|
4195
4252
|
"$type": "RuleCall",
|
|
4196
4253
|
"rule": {
|
|
4197
|
-
"$ref": "#/rules@
|
|
4254
|
+
"$ref": "#/rules@46"
|
|
4198
4255
|
},
|
|
4199
4256
|
"arguments": []
|
|
4200
4257
|
}
|
|
@@ -4218,7 +4275,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4218
4275
|
"terminal": {
|
|
4219
4276
|
"$type": "RuleCall",
|
|
4220
4277
|
"rule": {
|
|
4221
|
-
"$ref": "#/rules@
|
|
4278
|
+
"$ref": "#/rules@41"
|
|
4222
4279
|
},
|
|
4223
4280
|
"arguments": []
|
|
4224
4281
|
}
|
|
@@ -4241,7 +4298,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4241
4298
|
"terminal": {
|
|
4242
4299
|
"$type": "RuleCall",
|
|
4243
4300
|
"rule": {
|
|
4244
|
-
"$ref": "#/rules@
|
|
4301
|
+
"$ref": "#/rules@41"
|
|
4245
4302
|
},
|
|
4246
4303
|
"arguments": []
|
|
4247
4304
|
}
|
|
@@ -4260,7 +4317,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4260
4317
|
{
|
|
4261
4318
|
"$type": "RuleCall",
|
|
4262
4319
|
"rule": {
|
|
4263
|
-
"$ref": "#/rules@
|
|
4320
|
+
"$ref": "#/rules@47"
|
|
4264
4321
|
},
|
|
4265
4322
|
"arguments": []
|
|
4266
4323
|
},
|
|
@@ -4304,7 +4361,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4304
4361
|
{
|
|
4305
4362
|
"$type": "RuleCall",
|
|
4306
4363
|
"rule": {
|
|
4307
|
-
"$ref": "#/rules@
|
|
4364
|
+
"$ref": "#/rules@47"
|
|
4308
4365
|
},
|
|
4309
4366
|
"arguments": []
|
|
4310
4367
|
},
|
|
@@ -4318,7 +4375,7 @@ var loadedDomainGrammar, DomainGrammar = () => loadedDomainGrammar ?? (loadedDom
|
|
|
4318
4375
|
{
|
|
4319
4376
|
"$type": "RuleCall",
|
|
4320
4377
|
"rule": {
|
|
4321
|
-
"$ref": "#/rules@
|
|
4378
|
+
"$ref": "#/rules@47"
|
|
4322
4379
|
},
|
|
4323
4380
|
"arguments": []
|
|
4324
4381
|
}
|
|
@@ -5045,8 +5102,7 @@ function command(aggId, c, loc, field) {
|
|
|
5045
5102
|
...described(c),
|
|
5046
5103
|
factory: c.factory,
|
|
5047
5104
|
params: c.params.map(field),
|
|
5048
|
-
|
|
5049
|
-
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) })),
|
|
5050
5106
|
emits: c.emits.map(qname),
|
|
5051
5107
|
errors: c.errors.map(qname),
|
|
5052
5108
|
location: loc(c)
|
|
@@ -5068,26 +5124,41 @@ function checkCommands(index, sink) {
|
|
|
5068
5124
|
for (const cmd of commandsOf(agg)) {
|
|
5069
5125
|
const label = `${cmd.factory ? "Factory command" : "Command"} '${cmd.name}'`;
|
|
5070
5126
|
if (!stateful) {
|
|
5071
|
-
if (cmd.
|
|
5072
|
-
sink.error("M006", `${label} declares
|
|
5127
|
+
if (cmd.transitions.length > 0) {
|
|
5128
|
+
sink.error("M006", `${label} declares state transitions, but aggregate '${agg.name}' has no states.`, cmd, "transitions", 0);
|
|
5073
5129
|
}
|
|
5074
5130
|
continue;
|
|
5075
5131
|
}
|
|
5076
|
-
if (cmd.factory
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
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
|
+
});
|
|
5084
5148
|
}
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
if (
|
|
5089
|
-
sink.
|
|
5090
|
-
|
|
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);
|
|
5091
5162
|
});
|
|
5092
5163
|
}
|
|
5093
5164
|
}
|
|
@@ -5128,6 +5199,9 @@ function generatedNames(index, ctx) {
|
|
|
5128
5199
|
}
|
|
5129
5200
|
for (const c of commands) {
|
|
5130
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
|
+
}
|
|
5131
5205
|
}
|
|
5132
5206
|
if (commands.some((c) => c.emits.length > 0)) {
|
|
5133
5207
|
out.push({ name: aggregateEventTypeName(el), origin: `the union of the events of '${el.name}'`, node: el });
|
|
@@ -5148,11 +5222,11 @@ function firstByName(items) {
|
|
|
5148
5222
|
const seen = new Set;
|
|
5149
5223
|
return items.filter((i) => !seen.has(i.name) && seen.add(i.name));
|
|
5150
5224
|
}
|
|
5151
|
-
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", DOMAIN_EVENT_TYPE = "DomainEvent", AGGREGATE_TYPE = "Aggregate", aggregateEventTypeName = (agg) => `${agg.name}Event`, KIND_LABELS, TS_RESERVED;
|
|
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;
|
|
5152
5226
|
var init_naming = __esm(() => {
|
|
5153
5227
|
init_ast();
|
|
5154
5228
|
init_model_index();
|
|
5155
|
-
RUNTIME_NAMES = ["Result", "Ok", "Err", "Decimal", "Timestamp", "ok", "err"];
|
|
5229
|
+
RUNTIME_NAMES = ["Result", "Ok", "Err", "Decimal", "Timestamp", "ok", "err", "byState"];
|
|
5156
5230
|
KIND_LABELS = {
|
|
5157
5231
|
IdType: "id",
|
|
5158
5232
|
PrimitiveDecl: "primitive",
|
|
@@ -7103,21 +7177,25 @@ function buildStateGraph(agg, model, labels = "both") {
|
|
|
7103
7177
|
}
|
|
7104
7178
|
const stateNode = (name) => stateful ? states.find((s) => s.name === name)?.id : agg.id;
|
|
7105
7179
|
for (const c of commands) {
|
|
7106
|
-
const
|
|
7107
|
-
|
|
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]];
|
|
7108
7184
|
const label = commandLabel(c);
|
|
7109
7185
|
const events = eventsLabel(c, model);
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
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 } });
|
|
7121
7199
|
}
|
|
7122
7200
|
}
|
|
7123
7201
|
const sizedNodes = nodes.map((n) => sizedState(n, labels));
|
|
@@ -7735,6 +7813,20 @@ export interface Err<E> {
|
|
|
7735
7813
|
export const ok = <T>(value: T): Ok<T> => ({ ok: true, value });
|
|
7736
7814
|
export const err = <E>(error: E): Err<E> => ({ ok: false, error });
|
|
7737
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
|
+
|
|
7738
7830
|
/** Decimal values are carried as strings so that no precision is lost. */
|
|
7739
7831
|
export type Decimal = string & { readonly __brand: 'Decimal' };
|
|
7740
7832
|
|
|
@@ -7769,6 +7861,7 @@ var oneLine = (s) => comment(s).replace(/\n+/g, " ");
|
|
|
7769
7861
|
var describedLines = (d) => [d.label, d.doc].filter((x) => !!x);
|
|
7770
7862
|
var PERSISTENT_LINE = "@persistent Persisted: storing this event is part of its contract.";
|
|
7771
7863
|
var invariantLines = (invs) => invs.map((i) => `@invariant ${i.name}${i.label ? ` (${i.label})` : ""}: ${i.source}`);
|
|
7864
|
+
var unique2 = (names) => [...new Set(names)];
|
|
7772
7865
|
|
|
7773
7866
|
class ContextEmitter {
|
|
7774
7867
|
model;
|
|
@@ -7955,26 +8048,40 @@ class ContextEmitter {
|
|
|
7955
8048
|
}
|
|
7956
8049
|
command(agg, c) {
|
|
7957
8050
|
const stateful = (agg.states ?? []).length > 0;
|
|
7958
|
-
const stateUnion = (names) => stateful ? names.map((n) => stateTypeName(agg, n)).join(" | ") : agg.name;
|
|
7959
|
-
const
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
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" : ""}`);
|
|
7965
8057
|
const events = c.emits.length === 0 ? "never" : c.emits.map((e) => this.ref(e)).join(" | ");
|
|
7966
8058
|
const eventArray = c.emits.length > 1 ? `readonly (${events})[]` : `readonly ${events}[]`;
|
|
7967
8059
|
const errors = c.errors.length === 0 ? "never" : c.errors.map((e) => this.ref(e)).join(" | ");
|
|
7968
|
-
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("; ");
|
|
7969
8062
|
this.jsdoc([
|
|
7970
8063
|
`${agg.name}.${c.name}${transition ? ` (${transition})` : ""}${c.factory ? " — factory" : ""}`,
|
|
7971
8064
|
...describedLines(c),
|
|
7972
8065
|
...c.params.filter((p) => p.label || p.doc).map((p) => `@param ${p.name} ${[p.label, p.doc].filter(Boolean).join(" — ")}`)
|
|
7973
8066
|
]);
|
|
7974
|
-
this.line(`export type ${commandTypeName(agg, c)} = (`);
|
|
7975
|
-
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])
|
|
7976
8069
|
this.line(` ${p},`);
|
|
7977
|
-
|
|
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("};");
|
|
7978
8085
|
}
|
|
7979
8086
|
iface(name, bases, extra, fields) {
|
|
7980
8087
|
const lines = [...extra, ...fields.flatMap((f) => this.property(f))];
|
|
@@ -8035,7 +8142,7 @@ class ContextEmitter {
|
|
|
8035
8142
|
}
|
|
8036
8143
|
|
|
8037
8144
|
// docs/guide.md
|
|
8038
|
-
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) 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`, 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 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, 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) \"請求書を発行する\" 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| 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\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### 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";
|
|
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";
|
|
8039
8146
|
|
|
8040
8147
|
// src/cli/main.ts
|
|
8041
8148
|
var defaultIO = {
|