@istar-ts/core 0.13.2 → 0.13.4
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 -1
- package/dist/index.cjs +47 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +46 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,11 @@ writeFileSync('model.pistar', toPistar(model));
|
|
|
35
35
|
- Files saved by the piStar web tool round-trip **byte-identically** through
|
|
36
36
|
`toPistar(parsePistar(file))` when you do not edit the model.
|
|
37
37
|
- Pass `{ saveDate: new Date() }` when saving an edited model (piStar updates `saveDate` on save).
|
|
38
|
-
Omit it to preserve the model’s existing `saveDate` on a load/save cycle
|
|
38
|
+
Omit it to preserve the model’s existing `saveDate` on a load/save cycle; a file that had none
|
|
39
|
+
keeps none until a save passes one.
|
|
40
|
+
- A parsed file is written back with its own key order at every level (top level, each element,
|
|
41
|
+
link, hub entry and the diagram), so files other tools wrote stay byte-identical. `inheritSourceLayout`
|
|
42
|
+
carries that over to an edited model; the store does it on every edit.
|
|
39
43
|
|
|
40
44
|
```ts
|
|
41
45
|
toPistar(editedModel, { saveDate: new Date() });
|
package/dist/index.cjs
CHANGED
|
@@ -1235,6 +1235,12 @@ var PistarParseError = class extends Error {
|
|
|
1235
1235
|
var PistarWriteError = class extends Error {
|
|
1236
1236
|
name = "PistarWriteError";
|
|
1237
1237
|
};
|
|
1238
|
+
/** The `objects` key of a hub's entry (`{ hub, starts, end }`) in a `SourceLayout`. */
|
|
1239
|
+
function hubEntryLayoutKey(hubId) {
|
|
1240
|
+
return `${hubId}\u0000entry`;
|
|
1241
|
+
}
|
|
1242
|
+
/** The `objects` key of the diagram in a `SourceLayout`. */
|
|
1243
|
+
const DIAGRAM_LAYOUT_KEY = "\0diagram";
|
|
1238
1244
|
const layouts = /* @__PURE__ */ new WeakMap();
|
|
1239
1245
|
/** The key order recorded when `model` was parsed, if it came from `parsePistar`. */
|
|
1240
1246
|
function getSourceLayout(model) {
|
|
@@ -1342,6 +1348,7 @@ function parsePistar(input, options = {}) {
|
|
|
1342
1348
|
usedDisplay.add(id);
|
|
1343
1349
|
return entry;
|
|
1344
1350
|
};
|
|
1351
|
+
const objects = /* @__PURE__ */ new Map();
|
|
1345
1352
|
const readElement = (raw, where, known, extras) => {
|
|
1346
1353
|
if (!isRecord(raw)) throw new PistarParseError(`${where}: expected an object`);
|
|
1347
1354
|
const { id, type } = raw;
|
|
@@ -1361,6 +1368,7 @@ function parsePistar(input, options = {}) {
|
|
|
1361
1368
|
...optional("extra", extraOf(raw, known))
|
|
1362
1369
|
};
|
|
1363
1370
|
elements.set(id, element);
|
|
1371
|
+
objects.set(id, Object.keys(raw));
|
|
1364
1372
|
return element;
|
|
1365
1373
|
};
|
|
1366
1374
|
asArray(json.actors, "actors").forEach((raw, i) => {
|
|
@@ -1405,12 +1413,14 @@ function parsePistar(input, options = {}) {
|
|
|
1405
1413
|
...optional("extra", extraOf(raw, LINK_KEYS))
|
|
1406
1414
|
};
|
|
1407
1415
|
links.set(id, link);
|
|
1416
|
+
objects.set(id, Object.keys(raw));
|
|
1408
1417
|
return link;
|
|
1409
1418
|
};
|
|
1410
1419
|
const readHubEntry = (raw, where) => {
|
|
1411
1420
|
const hub = readElement(raw.hub, `${where}.hub`, HUB_KEYS, {});
|
|
1412
1421
|
const hubKind = metamodel.elements.get(hub.kind);
|
|
1413
1422
|
if (hubKind?.role !== "hub") throw new PistarParseError(`${where}.hub (${hub.id}): ${hub.kind} is not a hub kind`);
|
|
1423
|
+
objects.set(hubEntryLayoutKey(hub.id), Object.keys(raw));
|
|
1414
1424
|
const entryExtra = extraOf(raw, HUB_ENTRY_KEYS);
|
|
1415
1425
|
if (entryExtra) elements.set(hub.id, {
|
|
1416
1426
|
...hub,
|
|
@@ -1448,6 +1458,7 @@ function parsePistar(input, options = {}) {
|
|
|
1448
1458
|
...isRecord(d.customProperties) ? { customProperties: d.customProperties } : {},
|
|
1449
1459
|
...optional("extra", extraOf(d, DIAGRAM_KEYS))
|
|
1450
1460
|
};
|
|
1461
|
+
objects.set(DIAGRAM_LAYOUT_KEY, Object.keys(d));
|
|
1451
1462
|
}
|
|
1452
1463
|
const model = {
|
|
1453
1464
|
elements,
|
|
@@ -1461,7 +1472,8 @@ function parsePistar(input, options = {}) {
|
|
|
1461
1472
|
};
|
|
1462
1473
|
layouts.set(model, {
|
|
1463
1474
|
keys: Object.keys(json),
|
|
1464
|
-
display: Object.keys(display)
|
|
1475
|
+
display: Object.keys(display),
|
|
1476
|
+
objects
|
|
1465
1477
|
});
|
|
1466
1478
|
setHostMetamodel(model, host);
|
|
1467
1479
|
return withMetamodel(model, metamodel);
|
|
@@ -1534,6 +1546,19 @@ function pistarTypeOf(type, kind, metamodel) {
|
|
|
1534
1546
|
if (type === void 0) throw new PistarWriteError(`kind "${kind}" is not part of ${metamodel.name}; pass its metamodel (toPistar(model, { metamodel }) or withMetamodel)`);
|
|
1535
1547
|
return type;
|
|
1536
1548
|
}
|
|
1549
|
+
/**
|
|
1550
|
+
* `value` with its keys in the order `keys` gives (those present), then the rest as built (piStar's
|
|
1551
|
+
* order): an object read from a file is written back with the file's key order, and keys the
|
|
1552
|
+
* file lacked follow.
|
|
1553
|
+
*/
|
|
1554
|
+
function inSourceOrder(value, keys) {
|
|
1555
|
+
if (!keys) return value;
|
|
1556
|
+
const result = {};
|
|
1557
|
+
const record = value;
|
|
1558
|
+
for (const key of keys) if (key in record) result[key] = record[key];
|
|
1559
|
+
for (const key of Object.keys(record)) if (!(key in result)) result[key] = record[key];
|
|
1560
|
+
return result;
|
|
1561
|
+
}
|
|
1537
1562
|
function elementJson(element, metamodel) {
|
|
1538
1563
|
return {
|
|
1539
1564
|
id: element.id,
|
|
@@ -1554,38 +1579,40 @@ function toPistarObject(input, options = {}) {
|
|
|
1554
1579
|
const orphans = [];
|
|
1555
1580
|
const dependencies = [];
|
|
1556
1581
|
const children = /* @__PURE__ */ new Map();
|
|
1582
|
+
const layout = layouts.get(model);
|
|
1583
|
+
const sourceOrder = (id, value) => inSourceOrder(value, layout?.objects?.get(id));
|
|
1557
1584
|
for (const element of model.elements.values()) {
|
|
1558
1585
|
if (isHub(element)) continue;
|
|
1559
1586
|
if (element.parent !== void 0 && !isActorKind(element.kind)) {
|
|
1560
1587
|
let list = children.get(element.parent);
|
|
1561
1588
|
if (!list) children.set(element.parent, list = []);
|
|
1562
|
-
list.push({
|
|
1589
|
+
list.push(sourceOrder(element.id, {
|
|
1563
1590
|
...elementJson(element, metamodel),
|
|
1564
1591
|
...element.extra
|
|
1565
|
-
});
|
|
1592
|
+
}));
|
|
1566
1593
|
}
|
|
1567
1594
|
}
|
|
1568
1595
|
for (const element of model.elements.values()) {
|
|
1569
1596
|
if (isHub(element)) continue;
|
|
1570
|
-
if (isActorKind(element.kind)) actors.push({
|
|
1597
|
+
if (isActorKind(element.kind)) actors.push(sourceOrder(element.id, {
|
|
1571
1598
|
...elementJson(element, metamodel),
|
|
1572
1599
|
nodes: children.get(element.id) ?? [],
|
|
1573
1600
|
...element.extra
|
|
1574
|
-
});
|
|
1601
|
+
}));
|
|
1575
1602
|
else if (element.isDependum) {
|
|
1576
1603
|
const { inbound, outbound } = dependencyLinksOf(model, element.id);
|
|
1577
|
-
dependencies.push({
|
|
1604
|
+
dependencies.push(sourceOrder(element.id, {
|
|
1578
1605
|
...elementJson(element, metamodel),
|
|
1579
1606
|
source: inbound?.source ?? element.dependency?.source ?? "",
|
|
1580
1607
|
target: outbound?.target ?? element.dependency?.target ?? "",
|
|
1581
1608
|
...element.extra
|
|
1582
|
-
});
|
|
1583
|
-
} else if (element.parent === void 0 || !model.elements.has(element.parent)) orphans.push({
|
|
1609
|
+
}));
|
|
1610
|
+
} else if (element.parent === void 0 || !model.elements.has(element.parent)) orphans.push(sourceOrder(element.id, {
|
|
1584
1611
|
...elementJson(element, metamodel),
|
|
1585
1612
|
...element.extra
|
|
1586
|
-
});
|
|
1613
|
+
}));
|
|
1587
1614
|
}
|
|
1588
|
-
const linkJson = (link) => ({
|
|
1615
|
+
const linkJson = (link) => sourceOrder(link.id, {
|
|
1589
1616
|
id: link.id,
|
|
1590
1617
|
type: pistarTypeOf(metamodel.links.get(link.kind)?.pistarType, link.kind, metamodel),
|
|
1591
1618
|
source: link.source,
|
|
@@ -1617,19 +1644,19 @@ function toPistarObject(input, options = {}) {
|
|
|
1617
1644
|
const hubEntry = (hub) => {
|
|
1618
1645
|
const parts = hubs.get(hub.id) ?? { legs: [] };
|
|
1619
1646
|
const { [HUB_ENTRY_KEY]: entryExtra, ...hubExtra } = hub.extra ?? {};
|
|
1620
|
-
return {
|
|
1621
|
-
hub: {
|
|
1647
|
+
return sourceOrder(hubEntryLayoutKey(hub.id), {
|
|
1648
|
+
hub: sourceOrder(hub.id, {
|
|
1622
1649
|
id: hub.id,
|
|
1623
1650
|
type: pistarTypeOf(metamodel.elements.get(hub.kind)?.pistarType, hub.kind, metamodel),
|
|
1624
1651
|
x: hub.x,
|
|
1625
1652
|
y: hub.y,
|
|
1626
1653
|
...hub.customProperties ? { customProperties: { ...hub.customProperties } } : {},
|
|
1627
1654
|
...hubExtra
|
|
1628
|
-
},
|
|
1655
|
+
}),
|
|
1629
1656
|
starts: parts.legs.map(linkJson),
|
|
1630
1657
|
...parts.end ? { end: linkJson(parts.end) } : {},
|
|
1631
1658
|
...isRecord(entryExtra) ? entryExtra : {}
|
|
1632
|
-
};
|
|
1659
|
+
});
|
|
1633
1660
|
};
|
|
1634
1661
|
const links = [];
|
|
1635
1662
|
const written = /* @__PURE__ */ new Set();
|
|
@@ -1643,7 +1670,6 @@ function toPistarObject(input, options = {}) {
|
|
|
1643
1670
|
}
|
|
1644
1671
|
}
|
|
1645
1672
|
for (const element of model.elements.values()) if (isHub(element) && !written.has(element.id)) links.push(hubEntry(element));
|
|
1646
|
-
const layout = layouts.get(model);
|
|
1647
1673
|
const display = {};
|
|
1648
1674
|
const displayOf = (id) => {
|
|
1649
1675
|
const owner = model.elements.get(id) ?? model.links.get(id);
|
|
@@ -1658,15 +1684,16 @@ function toPistarObject(input, options = {}) {
|
|
|
1658
1684
|
for (const [id, entry] of Object.entries(model.extraDisplay ?? {})) if (!(id in display)) display[id] = entry;
|
|
1659
1685
|
let saveDate;
|
|
1660
1686
|
if (options.saveDate instanceof Date) saveDate = formatDate(options.saveDate);
|
|
1661
|
-
else
|
|
1687
|
+
else if (options.saveDate !== void 0 || model.saveDate !== void 0) saveDate = options.saveDate ?? model.saveDate;
|
|
1688
|
+
else if (!layout || layout.keys.includes("saveDate")) saveDate = formatDate(/* @__PURE__ */ new Date());
|
|
1662
1689
|
const d = model.diagram;
|
|
1663
|
-
const diagram = d && {
|
|
1690
|
+
const diagram = d && sourceOrder("\0diagram", {
|
|
1664
1691
|
...d.width !== void 0 ? { width: d.width } : {},
|
|
1665
1692
|
...d.height !== void 0 ? { height: d.height } : {},
|
|
1666
1693
|
...d.name !== void 0 ? { name: d.name } : {},
|
|
1667
1694
|
...d.customProperties ? { customProperties: { ...d.customProperties } } : {},
|
|
1668
1695
|
...d.extra
|
|
1669
|
-
};
|
|
1696
|
+
});
|
|
1670
1697
|
const values = {
|
|
1671
1698
|
...model.extra,
|
|
1672
1699
|
actors,
|
|
@@ -2851,6 +2878,7 @@ exports.DEFAULT_DIAGRAM = DEFAULT_DIAGRAM;
|
|
|
2851
2878
|
exports.DEFAULT_ELEMENT_SIZE = DEFAULT_ELEMENT_SIZE;
|
|
2852
2879
|
exports.DEPENDENCY_LINK_KINDS = DEPENDENCY_LINK_KINDS;
|
|
2853
2880
|
exports.DIAGNOSTIC_SEVERITIES = DIAGNOSTIC_SEVERITIES;
|
|
2881
|
+
exports.DIAGRAM_LAYOUT_KEY = DIAGRAM_LAYOUT_KEY;
|
|
2854
2882
|
exports.DSM3_FILE_KEYS = DSM3_FILE_KEYS;
|
|
2855
2883
|
exports.DSM3_TOOL = DSM3_TOOL;
|
|
2856
2884
|
exports.ELEMENT_KINDS = ELEMENT_KINDS;
|
|
@@ -2909,6 +2937,7 @@ exports.fromNodeIdDiagnostics = fromNodeIdDiagnostics;
|
|
|
2909
2937
|
exports.getSourceLayout = getSourceLayout;
|
|
2910
2938
|
exports.groupDiagnostics = groupDiagnostics;
|
|
2911
2939
|
exports.hostMetamodelOf = hostMetamodelOf;
|
|
2940
|
+
exports.hubEntryLayoutKey = hubEntryLayoutKey;
|
|
2912
2941
|
exports.hubLinkOf = hubLinkOf;
|
|
2913
2942
|
exports.hubOfLink = hubOfLink;
|
|
2914
2943
|
exports.inheritMetamodel = inheritMetamodel;
|