@the-package-labs/idocs-core 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +2 -2
- package/dist/{chunk-3QBMUILO.js → chunk-P2X2XSBM.js} +1 -1
- package/dist/{chunk-S7M3BRFI.js → chunk-Q2NHZ6TV.js} +181 -9
- package/dist/{chunk-ITBBPZE6.js → chunk-ZYFFV7Y7.js} +6 -2
- package/dist/defaults.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +91 -6
- package/dist/nested-layout.d.ts +4 -1
- package/dist/node.js +3 -3
- package/dist/schema.d.ts +47 -0
- package/dist/scrubber.d.ts +34 -0
- package/dist/start.d.ts +22 -0
- package/dist/types.d.ts +32 -0
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BUILTIN_EDGE_KINDS,
|
|
3
3
|
BUILTIN_KINDS,
|
|
4
|
+
DEFAULT_ENTITY_WIDTH,
|
|
4
5
|
didYouMean,
|
|
5
6
|
letterKey
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZYFFV7Y7.js";
|
|
7
8
|
|
|
8
9
|
// src/icon-resolver.ts
|
|
9
10
|
import { getIconData, iconToSVG } from "@iconify/utils";
|
|
@@ -215,10 +216,28 @@ var ChipSchema = z.union([
|
|
|
215
216
|
z.string(),
|
|
216
217
|
z.strictObject({ label: z.string(), sub: z.string().optional() })
|
|
217
218
|
]);
|
|
219
|
+
var FieldProps = z.strictObject({
|
|
220
|
+
type: z.string().optional().describe("Its type: `keyword`, `uuid`, `string[]`."),
|
|
221
|
+
key: z.boolean().optional().describe("Part of the primary key. Shown with a `#` in front."),
|
|
222
|
+
ref: z.string().optional().describe(
|
|
223
|
+
"The `node` or `node.field` this one points at, like a foreign key. Draws a relation between the two cards."
|
|
224
|
+
),
|
|
225
|
+
note: z.string().optional().describe("Shown on hover and in the drawer.")
|
|
226
|
+
});
|
|
227
|
+
var FieldSchema = z.union([
|
|
228
|
+
z.string().min(1),
|
|
229
|
+
z.record(z.string().min(1), z.union([z.string(), z.null(), FieldProps])).refine((o) => Object.keys(o).length === 1, {
|
|
230
|
+
message: "One field per list item: `- name: type`"
|
|
231
|
+
})
|
|
232
|
+
]);
|
|
218
233
|
var NodeSchema = z.strictObject({
|
|
219
234
|
title: z.string().optional().describe("Display name. Defaults to the node id."),
|
|
220
235
|
sub: z.string().optional().describe("One line under the title, rendered in mono (ports, stack, version)."),
|
|
236
|
+
pill: z.string().optional().describe("Short label in the card header, like `TABLE` or `ES INDEX`."),
|
|
221
237
|
lines: z.array(z.string()).optional().describe("Short body lines inside the card."),
|
|
238
|
+
fields: z.array(FieldSchema).optional().describe(
|
|
239
|
+
"Makes the card an entity: a table of fields, each `name: type`. `ref` points a field at another entity."
|
|
240
|
+
),
|
|
222
241
|
icon: z.string().optional().describe("`postgresql`, `logos:redis`, `lucide:server` or ./path/to.svg."),
|
|
223
242
|
kind: z.string().optional().describe("Gives a default icon and colour family. See `kinds`."),
|
|
224
243
|
family: FamilySchema.optional().describe("Accent colour family; overrides the kind default."),
|
|
@@ -354,10 +373,31 @@ var ScenarioSchema = ScenarioBase.refine(
|
|
|
354
373
|
(s) => (s.phases?.length ?? 0) + (s.steps?.length ?? 0) > 0,
|
|
355
374
|
{ message: "A scenario needs `steps` or `phases`" }
|
|
356
375
|
);
|
|
376
|
+
var DefaultsSchema = z.strictObject({
|
|
377
|
+
view: Id.optional().describe(
|
|
378
|
+
"View shown first. Defaults to the view of `scenario`, or else the first view."
|
|
379
|
+
),
|
|
380
|
+
scenario: Id.optional().describe(
|
|
381
|
+
"Scenario selected first. Without it the diagram opens on its overview. It does not play until a reader presses play, unless `autoplay` is on."
|
|
382
|
+
),
|
|
383
|
+
mode: z.enum(["flow", "sequence", "story"]).optional().describe(
|
|
384
|
+
"How a scenario is drawn when it has no `mode` of its own: packets over the diagram, a sequence diagram, or a swimlane story."
|
|
385
|
+
),
|
|
386
|
+
sidebar: z.boolean().optional().describe(
|
|
387
|
+
"Whether the panel over the picture starts open. By default it does when there is a scenario or another view to choose, and the frame is wide enough."
|
|
388
|
+
),
|
|
389
|
+
subtitles: z.boolean().optional().describe("Words over the picture saying what the scenario is doing. On by default."),
|
|
390
|
+
autoplay: z.boolean().optional().describe(
|
|
391
|
+
"Play `scenario` as soon as the diagram is on screen. Needs `scenario`, and is ignored when the system asks for reduced motion."
|
|
392
|
+
)
|
|
393
|
+
});
|
|
357
394
|
var RootSchema = z.strictObject({
|
|
358
395
|
$schema: z.string().optional(),
|
|
359
396
|
title: z.string(),
|
|
360
397
|
description: z.string().optional().describe("Markdown shown above the first view."),
|
|
398
|
+
defaults: DefaultsSchema.optional().describe(
|
|
399
|
+
"How the diagram opens: its view, scenario and mode, and whether the panel and subtitles show. A page can still choose otherwise with the props of `<Diagram>`."
|
|
400
|
+
),
|
|
361
401
|
kinds: z.record(Id, z.strictObject({ icon: z.string().optional(), family: FamilySchema.optional() })).optional(),
|
|
362
402
|
edgeKinds: z.record(
|
|
363
403
|
Id,
|
|
@@ -380,7 +420,8 @@ var KNOWN_KEYS = {
|
|
|
380
420
|
group: Object.keys(GroupSchema.shape),
|
|
381
421
|
edge: Object.keys(EdgeSchema.shape),
|
|
382
422
|
view: Object.keys(ViewSchema.shape),
|
|
383
|
-
scenario: Object.keys(ScenarioBase.shape)
|
|
423
|
+
scenario: Object.keys(ScenarioBase.shape),
|
|
424
|
+
defaults: Object.keys(DefaultsSchema.shape)
|
|
384
425
|
};
|
|
385
426
|
function authoringJsonSchema() {
|
|
386
427
|
const schema = z.toJSONSchema(RootSchema, { io: "input", unrepresentable: "any" });
|
|
@@ -589,6 +630,7 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
589
630
|
const fixParents = Object.values(groups);
|
|
590
631
|
for (const g of fixParents) g.style = g.parent ? "frame" : "zone";
|
|
591
632
|
const nodes = {};
|
|
633
|
+
const refTexts = [];
|
|
592
634
|
for (const [id, n] of Object.entries(data.nodes)) {
|
|
593
635
|
if (n.kind && !kinds[n.kind]) {
|
|
594
636
|
warn(
|
|
@@ -617,11 +659,26 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
617
659
|
if (n.doc && docText === void 0)
|
|
618
660
|
warn(`Doc file "${n.doc}" was not found`, ["nodes", id, "doc"]);
|
|
619
661
|
const docHtml = [n.description, docText].filter((t) => !!t).map(renderMarkdown).join("");
|
|
662
|
+
const fields = (n.fields ?? []).map(toField);
|
|
663
|
+
const seenFields = /* @__PURE__ */ new Set();
|
|
664
|
+
fields.forEach((f, i) => {
|
|
665
|
+
if (seenFields.has(f.name)) {
|
|
666
|
+
error(`Field "${f.name}" appears twice in "${id}"`, ["nodes", id, "fields", i]);
|
|
667
|
+
}
|
|
668
|
+
seenFields.add(f.name);
|
|
669
|
+
});
|
|
670
|
+
n.fields?.forEach((item, i) => {
|
|
671
|
+
const ref = typeof item === "object" && item ? Object.values(item)[0] : void 0;
|
|
672
|
+
if (ref && typeof ref === "object" && ref.ref !== void 0)
|
|
673
|
+
refTexts.push({ node: id, index: i, text: ref.ref });
|
|
674
|
+
});
|
|
620
675
|
nodes[id] = {
|
|
621
676
|
id,
|
|
622
677
|
title: n.title ?? id,
|
|
623
678
|
sub: n.sub,
|
|
679
|
+
pill: n.pill,
|
|
624
680
|
lines: n.lines ?? [],
|
|
681
|
+
fields,
|
|
625
682
|
icon: iconFor(n.icon ?? kind?.icon, ["nodes", id, n.icon ? "icon" : "kind"]),
|
|
626
683
|
kind: n.kind,
|
|
627
684
|
family: n.family ?? kind?.family,
|
|
@@ -630,7 +687,7 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
630
687
|
badge: n.badge === void 0 ? void 0 : String(n.badge),
|
|
631
688
|
uses: n.uses ?? [],
|
|
632
689
|
chips: (n.chips ?? []).map((c) => typeof c === "string" ? { label: c } : c),
|
|
633
|
-
w: n.w,
|
|
690
|
+
w: n.w ?? (fields.length ? DEFAULT_ENTITY_WIDTH : void 0),
|
|
634
691
|
docHtml: docHtml || void 0,
|
|
635
692
|
links: n.links ?? [],
|
|
636
693
|
refs: n.refs ?? [],
|
|
@@ -638,18 +695,39 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
638
695
|
diagram: typeof n.diagram === "string" ? { name: n.diagram } : n.diagram
|
|
639
696
|
};
|
|
640
697
|
}
|
|
698
|
+
for (const { node: id, index, text } of refTexts) {
|
|
699
|
+
const found = resolveEnd(text, nodes);
|
|
700
|
+
if ("end" in found) {
|
|
701
|
+
nodes[id].fields[index].ref = found.end;
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
const name = nodes[id].fields[index].name;
|
|
705
|
+
error(
|
|
706
|
+
found.message ?? `Field "${name}" points at "${text}", which is not a node`,
|
|
707
|
+
["nodes", id, "fields", index, name, "ref"],
|
|
708
|
+
found.hint ?? didYouMean(text, Object.keys(nodes))
|
|
709
|
+
);
|
|
710
|
+
}
|
|
641
711
|
const edges = {};
|
|
642
712
|
const nodeIds = Object.keys(nodes);
|
|
643
713
|
(data.edges ?? []).forEach((e, i) => {
|
|
644
714
|
const path = ["edges", i];
|
|
645
715
|
let ok = true;
|
|
716
|
+
const ends = {};
|
|
646
717
|
for (const end of ["from", "to"]) {
|
|
647
|
-
|
|
648
|
-
|
|
718
|
+
const found = resolveEnd(e[end], nodes);
|
|
719
|
+
if ("end" in found) ends[end] = found.end;
|
|
720
|
+
else {
|
|
721
|
+
error(
|
|
722
|
+
found.message ?? `Edge ${end} "${e[end]}" is not a node`,
|
|
723
|
+
[...path, end],
|
|
724
|
+
found.hint ?? didYouMean(e[end], nodeIds)
|
|
725
|
+
);
|
|
649
726
|
ok = false;
|
|
650
727
|
}
|
|
651
728
|
}
|
|
652
|
-
const
|
|
729
|
+
const between = ends.from && ends.to && [ends.from, ends.to].every((x) => nodes[x.node].fields.length);
|
|
730
|
+
const kind = e.kind ?? (between ? "relation" : "http");
|
|
653
731
|
if (!edgeKinds[kind]) {
|
|
654
732
|
error(
|
|
655
733
|
`Unknown edge kind "${kind}"`,
|
|
@@ -658,7 +736,7 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
658
736
|
);
|
|
659
737
|
ok = false;
|
|
660
738
|
}
|
|
661
|
-
if (
|
|
739
|
+
if (ok && ends.from.node === ends.to.node) {
|
|
662
740
|
warn("Edge connects a node to itself and is not drawn", path);
|
|
663
741
|
ok = false;
|
|
664
742
|
}
|
|
@@ -670,8 +748,10 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
670
748
|
}
|
|
671
749
|
edges[id] = {
|
|
672
750
|
id,
|
|
673
|
-
from:
|
|
674
|
-
to:
|
|
751
|
+
from: ends.from.node,
|
|
752
|
+
to: ends.to.node,
|
|
753
|
+
fromField: ends.from.field,
|
|
754
|
+
toField: ends.to.field,
|
|
675
755
|
label: e.label,
|
|
676
756
|
kind,
|
|
677
757
|
both: e.both ?? false,
|
|
@@ -684,6 +764,32 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
684
764
|
noteHtml: e.note ? renderMarkdown(e.note) : void 0
|
|
685
765
|
};
|
|
686
766
|
});
|
|
767
|
+
const written = new Set(
|
|
768
|
+
Object.values(edges).flatMap((e) => {
|
|
769
|
+
const a = `${e.from}.${e.fromField ?? ""}`;
|
|
770
|
+
const b = `${e.to}.${e.toField ?? ""}`;
|
|
771
|
+
return [`${a}>${b}`, `${b}>${a}`];
|
|
772
|
+
})
|
|
773
|
+
);
|
|
774
|
+
for (const node of Object.values(nodes)) {
|
|
775
|
+
for (const f of node.fields) {
|
|
776
|
+
if (!f.ref || f.ref.node === node.id) continue;
|
|
777
|
+
const key = `${node.id}.${f.name}>${f.ref.node}.${f.ref.field ?? ""}`;
|
|
778
|
+
if (written.has(key)) continue;
|
|
779
|
+
const id = `ref:${node.id}.${f.name}`;
|
|
780
|
+
edges[id] = {
|
|
781
|
+
id,
|
|
782
|
+
from: node.id,
|
|
783
|
+
to: f.ref.node,
|
|
784
|
+
fromField: f.name,
|
|
785
|
+
toField: f.ref.field,
|
|
786
|
+
kind: "relation",
|
|
787
|
+
both: false,
|
|
788
|
+
hidden: false,
|
|
789
|
+
status: "built"
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
}
|
|
687
793
|
const viewDefs = Object.keys(data.views ?? {}).length ? data.views : { main: { title: data.title } };
|
|
688
794
|
const views = Object.entries(viewDefs).map(
|
|
689
795
|
([id, v]) => buildView(
|
|
@@ -701,10 +807,12 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
701
807
|
const sc = buildScenario(id, s, views, nodes, edges, error, warn);
|
|
702
808
|
if (sc) scenarios.push(sc);
|
|
703
809
|
}
|
|
810
|
+
const defaults = buildDefaults(data.defaults, views, scenarios, error);
|
|
704
811
|
return {
|
|
705
812
|
name: src.name,
|
|
706
813
|
title: data.title,
|
|
707
814
|
descriptionHtml: data.description ? renderMarkdown(data.description) : void 0,
|
|
815
|
+
defaults,
|
|
708
816
|
nodes,
|
|
709
817
|
groups,
|
|
710
818
|
edges,
|
|
@@ -713,6 +821,37 @@ function build(data, src, error, warn, { resolveIcon }) {
|
|
|
713
821
|
scenarios
|
|
714
822
|
};
|
|
715
823
|
}
|
|
824
|
+
function toField(item) {
|
|
825
|
+
if (typeof item === "string") return { name: item };
|
|
826
|
+
const [name, value] = Object.entries(item)[0];
|
|
827
|
+
if (value == null) return { name };
|
|
828
|
+
if (typeof value === "string") return { name, type: value };
|
|
829
|
+
const { ref: _ref, ...rest } = value;
|
|
830
|
+
return { name, ...rest };
|
|
831
|
+
}
|
|
832
|
+
function resolveEnd(text, nodes) {
|
|
833
|
+
if (nodes[text]) return { end: { node: text } };
|
|
834
|
+
const matches = [];
|
|
835
|
+
let known;
|
|
836
|
+
for (let i = text.indexOf("."); i > 0; i = text.indexOf(".", i + 1)) {
|
|
837
|
+
const node = nodes[text.slice(0, i)];
|
|
838
|
+
if (!node) continue;
|
|
839
|
+
known ??= node;
|
|
840
|
+
const field2 = text.slice(i + 1);
|
|
841
|
+
if (node.fields.some((f) => f.name === field2)) matches.push({ node: node.id, field: field2 });
|
|
842
|
+
}
|
|
843
|
+
if (matches.length === 1) return { end: matches[0] };
|
|
844
|
+
if (matches.length > 1) {
|
|
845
|
+
return { message: `"${text}" could be more than one field`, hint: "Rename a node or a field." };
|
|
846
|
+
}
|
|
847
|
+
if (!known) return {};
|
|
848
|
+
const field = text.slice(known.id.length + 1);
|
|
849
|
+
const names = known.fields.map((f) => f.name);
|
|
850
|
+
return {
|
|
851
|
+
message: `Node "${known.id}" has no field "${field}"`,
|
|
852
|
+
hint: didYouMean(field, names) ?? (names.length ? `Fields: ${names.join(", ")}` : void 0)
|
|
853
|
+
};
|
|
854
|
+
}
|
|
716
855
|
function buildView(id, v, diagramTitle, nodes, groups, edges, error) {
|
|
717
856
|
const known = [...Object.keys(nodes), ...Object.keys(groups)];
|
|
718
857
|
const members = (gid, out) => {
|
|
@@ -765,6 +904,38 @@ function buildView(id, v, diagramTitle, nodes, groups, edges, error) {
|
|
|
765
904
|
interfaces: v.interfaces ?? false
|
|
766
905
|
};
|
|
767
906
|
}
|
|
907
|
+
function buildDefaults(d, views, scenarios, error) {
|
|
908
|
+
if (!d) return void 0;
|
|
909
|
+
const ids = (list) => list.map((x) => x.id);
|
|
910
|
+
const view = views.find((v) => v.id === d.view);
|
|
911
|
+
if (d.view !== void 0 && !view) {
|
|
912
|
+
error(
|
|
913
|
+
`defaults.view "${d.view}" is not a view`,
|
|
914
|
+
["defaults", "view"],
|
|
915
|
+
didYouMean(d.view, ids(views))
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
const scenario = scenarios.find((s) => s.id === d.scenario);
|
|
919
|
+
if (d.scenario !== void 0 && !scenario) {
|
|
920
|
+
error(
|
|
921
|
+
`defaults.scenario "${d.scenario}" is not a scenario`,
|
|
922
|
+
["defaults", "scenario"],
|
|
923
|
+
didYouMean(d.scenario, ids(scenarios))
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
if (view && scenario && scenario.view !== view.id) {
|
|
927
|
+
error(
|
|
928
|
+
`defaults.scenario "${scenario.id}" plays on view "${scenario.view}", not "${view.id}"`,
|
|
929
|
+
["defaults", "scenario"],
|
|
930
|
+
`Drop \`view\` and the diagram opens on "${scenario.view}", or pick a scenario of "${view.id}".`
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
if (d.autoplay && d.scenario === void 0) {
|
|
934
|
+
error("defaults.autoplay needs a defaults.scenario to play", ["defaults", "autoplay"]);
|
|
935
|
+
}
|
|
936
|
+
const out = Object.fromEntries(Object.entries(d).filter(([, v]) => v !== void 0));
|
|
937
|
+
return Object.keys(out).length ? out : void 0;
|
|
938
|
+
}
|
|
768
939
|
function buildScenario(id, s, views, nodes, edges, error, warn) {
|
|
769
940
|
const viewId = s.view ?? views[0].id;
|
|
770
941
|
const view = views.find((v) => v.id === viewId);
|
|
@@ -1042,6 +1213,7 @@ function describeIssue(issue) {
|
|
|
1042
1213
|
function allowedKeysFor(path) {
|
|
1043
1214
|
const [section] = path;
|
|
1044
1215
|
if (path.length === 0) return KNOWN_KEYS.root;
|
|
1216
|
+
if (path.length === 1) return section === "defaults" ? KNOWN_KEYS.defaults : void 0;
|
|
1045
1217
|
if (path.length !== 2) return void 0;
|
|
1046
1218
|
switch (section) {
|
|
1047
1219
|
case "nodes":
|
|
@@ -17,7 +17,8 @@ var BUILTIN_KINDS = {
|
|
|
17
17
|
network: { icon: "lucide:network", family: "violet" },
|
|
18
18
|
vm: { icon: "lucide:box", family: "violet" },
|
|
19
19
|
auth: { icon: "lucide:key-round", family: "teal" },
|
|
20
|
-
monitor: { icon: "lucide:activity", family: "teal" }
|
|
20
|
+
monitor: { icon: "lucide:activity", family: "teal" },
|
|
21
|
+
entity: { icon: "lucide:table-2", family: "blue" }
|
|
21
22
|
};
|
|
22
23
|
var BUILTIN_EDGE_KINDS = {
|
|
23
24
|
http: { label: "HTTP request / response", color: "ink", width: 1.5 },
|
|
@@ -25,7 +26,8 @@ var BUILTIN_EDGE_KINDS = {
|
|
|
25
26
|
tunnel: { label: "Overlay tunnel", color: "tunnel", width: 5 },
|
|
26
27
|
queue: { label: "Queue / broker", color: "ok", width: 2, dash: "2 4" },
|
|
27
28
|
ws: { label: "WebSocket", color: "ink", width: 1.6, dash: "7 4" },
|
|
28
|
-
data: { label: "Data access", color: "muted", width: 1.3 }
|
|
29
|
+
data: { label: "Data access", color: "muted", width: 1.3 },
|
|
30
|
+
relation: { label: "Relation between entities", color: "muted", width: 1.4 }
|
|
29
31
|
};
|
|
30
32
|
var STEP_KIND_COLORS = {
|
|
31
33
|
request: "accent",
|
|
@@ -35,6 +37,7 @@ var STEP_KIND_COLORS = {
|
|
|
35
37
|
event: "warn"
|
|
36
38
|
};
|
|
37
39
|
var DEFAULT_NODE_WIDTH = 178;
|
|
40
|
+
var DEFAULT_ENTITY_WIDTH = 280;
|
|
38
41
|
|
|
39
42
|
// src/geometry.ts
|
|
40
43
|
function polylineLength(points) {
|
|
@@ -136,6 +139,7 @@ export {
|
|
|
136
139
|
BUILTIN_EDGE_KINDS,
|
|
137
140
|
STEP_KIND_COLORS,
|
|
138
141
|
DEFAULT_NODE_WIDTH,
|
|
142
|
+
DEFAULT_ENTITY_WIDTH,
|
|
139
143
|
polylineLength,
|
|
140
144
|
dist,
|
|
141
145
|
pointAt,
|
package/dist/defaults.d.ts
CHANGED
|
@@ -8,3 +8,5 @@ export declare const BUILTIN_KINDS: Record<string, KindDef>;
|
|
|
8
8
|
export declare const BUILTIN_EDGE_KINDS: Record<string, EdgeKindDef>;
|
|
9
9
|
export declare const STEP_KIND_COLORS: Record<string, string>;
|
|
10
10
|
export declare const DEFAULT_NODE_WIDTH = 178;
|
|
11
|
+
/** Cards with fields need room for a name and a type side by side. */
|
|
12
|
+
export declare const DEFAULT_ENTITY_WIDTH = 280;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,10 +2,11 @@ import {
|
|
|
2
2
|
attachNested,
|
|
3
3
|
linkDiagrams,
|
|
4
4
|
nestedDiagrams
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-P2X2XSBM.js";
|
|
6
6
|
import {
|
|
7
7
|
BUILTIN_EDGE_KINDS,
|
|
8
8
|
BUILTIN_KINDS,
|
|
9
|
+
DEFAULT_ENTITY_WIDTH,
|
|
9
10
|
DEFAULT_NODE_WIDTH,
|
|
10
11
|
STEP_KIND_COLORS,
|
|
11
12
|
dist,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
pointAt,
|
|
14
15
|
polylineLength,
|
|
15
16
|
roundedPath
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-ZYFFV7Y7.js";
|
|
17
18
|
|
|
18
19
|
// src/layout.ts
|
|
19
20
|
import ELK from "elkjs/lib/elk.bundled.js";
|
|
@@ -960,9 +961,10 @@ function overlap(a, b, pad) {
|
|
|
960
961
|
var INLINE_PAD = { top: 40, left: 4, right: 4, bottom: 4 };
|
|
961
962
|
function openingView(diagram, ref) {
|
|
962
963
|
const has = (id) => diagram.views.some((v) => v.id === id);
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
964
|
+
const of = (scenario) => diagram.scenarios.find((s) => s.id === scenario)?.view;
|
|
965
|
+
return [ref.view, of(ref.scenario), of(diagram.defaults?.scenario), diagram.defaults?.view].find(
|
|
966
|
+
has
|
|
967
|
+
) ?? diagram.views[0].id;
|
|
966
968
|
}
|
|
967
969
|
var canExpand = (ref, diagrams) => !!ref && ref.mode !== "open" && !!diagrams[ref.name];
|
|
968
970
|
var canOpen = (ref, diagrams) => !!ref && ref.mode !== "expand" && !!diagrams[ref.name];
|
|
@@ -1186,6 +1188,81 @@ function phaseSpans(scenario) {
|
|
|
1186
1188
|
return out;
|
|
1187
1189
|
}
|
|
1188
1190
|
|
|
1191
|
+
// src/scrubber.ts
|
|
1192
|
+
function buildScrubber(tl) {
|
|
1193
|
+
const steps = tl.scenario.steps;
|
|
1194
|
+
const slots = [];
|
|
1195
|
+
let i = 0;
|
|
1196
|
+
while (i < steps.length) {
|
|
1197
|
+
let j = i + 1;
|
|
1198
|
+
const par = steps[i].par;
|
|
1199
|
+
if (par !== void 0) while (j < steps.length && steps[j].par === par) j++;
|
|
1200
|
+
const run = tl.steps.slice(i, j);
|
|
1201
|
+
slots.push({ from: i, to: j - 1, t0: Math.min(...run.map((s) => s.start)), t1: 0 });
|
|
1202
|
+
i = j;
|
|
1203
|
+
}
|
|
1204
|
+
slots.forEach((slot, k) => {
|
|
1205
|
+
slot.t1 = slots[k + 1]?.t0 ?? tl.duration;
|
|
1206
|
+
});
|
|
1207
|
+
if (slots[0]) slots[0].t0 = 0;
|
|
1208
|
+
const slotOf = (step) => slots.findIndex((s) => s.from <= step && step <= s.to);
|
|
1209
|
+
const sections = phaseSpans(tl.scenario).map((span) => ({
|
|
1210
|
+
phase: span.index,
|
|
1211
|
+
title: span.title,
|
|
1212
|
+
caption: span.caption,
|
|
1213
|
+
from: slotOf(span.from),
|
|
1214
|
+
to: slotOf(span.to)
|
|
1215
|
+
}));
|
|
1216
|
+
return { slots, sections, duration: tl.duration };
|
|
1217
|
+
}
|
|
1218
|
+
var clamp01 = (n) => Math.min(1, Math.max(0, n));
|
|
1219
|
+
function positionAt(s, t) {
|
|
1220
|
+
const n = s.slots.length;
|
|
1221
|
+
if (!n) return 0;
|
|
1222
|
+
let k = 0;
|
|
1223
|
+
s.slots.forEach((slot2, i) => {
|
|
1224
|
+
if (slot2.t0 <= t) k = i;
|
|
1225
|
+
});
|
|
1226
|
+
const slot = s.slots[k];
|
|
1227
|
+
const length = slot.t1 - slot.t0;
|
|
1228
|
+
return (k + (length > 0 ? clamp01((t - slot.t0) / length) : 0)) / n;
|
|
1229
|
+
}
|
|
1230
|
+
function timeAt(s, position) {
|
|
1231
|
+
const n = s.slots.length;
|
|
1232
|
+
if (!n) return 0;
|
|
1233
|
+
const x = clamp01(position) * n;
|
|
1234
|
+
const k = Math.min(n - 1, Math.floor(x));
|
|
1235
|
+
const slot = s.slots[k];
|
|
1236
|
+
return slot.t0 + (x - k) * (slot.t1 - slot.t0);
|
|
1237
|
+
}
|
|
1238
|
+
function slotAt(s, position) {
|
|
1239
|
+
const n = s.slots.length;
|
|
1240
|
+
return n ? Math.min(n - 1, Math.floor(clamp01(position) * n)) : -1;
|
|
1241
|
+
}
|
|
1242
|
+
function slotOfStep(s, index) {
|
|
1243
|
+
return s.slots.findIndex((slot) => slot.from <= index && index <= slot.to);
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// src/start.ts
|
|
1247
|
+
var defaultMode = (diagram) => diagram.defaults?.mode ?? "flow";
|
|
1248
|
+
function startOf(diagram, want = {}) {
|
|
1249
|
+
const d = diagram.defaults ?? {};
|
|
1250
|
+
const scenarioById = (id) => diagram.scenarios.find((s) => s.id === id);
|
|
1251
|
+
const hasView = (id) => diagram.views.some((v) => v.id === id);
|
|
1252
|
+
const first = diagram.views[0].id;
|
|
1253
|
+
let view;
|
|
1254
|
+
let scenario;
|
|
1255
|
+
if (want.view !== void 0 || want.scenario !== void 0) {
|
|
1256
|
+
view = [want.view, scenarioById(want.scenario)?.view].find(hasView) ?? first;
|
|
1257
|
+
scenario = scenarioById(want.scenario)?.id ?? (scenarioById(d.scenario)?.view === view ? d.scenario ?? null : null);
|
|
1258
|
+
} else {
|
|
1259
|
+
scenario = scenarioById(d.scenario)?.id ?? null;
|
|
1260
|
+
view = [scenarioById(scenario ?? void 0)?.view, d.view].find(hasView) ?? first;
|
|
1261
|
+
}
|
|
1262
|
+
const mode = want.mode ?? scenarioById(scenario ?? void 0)?.mode ?? defaultMode(diagram);
|
|
1263
|
+
return { view, scenario, mode };
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1189
1266
|
// src/story.ts
|
|
1190
1267
|
function buildStory(diagram, scenario) {
|
|
1191
1268
|
const steps = scenario.steps;
|
|
@@ -1484,16 +1561,19 @@ function runBounds(tl, index) {
|
|
|
1484
1561
|
export {
|
|
1485
1562
|
BUILTIN_EDGE_KINDS,
|
|
1486
1563
|
BUILTIN_KINDS,
|
|
1564
|
+
DEFAULT_ENTITY_WIDTH,
|
|
1487
1565
|
DEFAULT_NODE_WIDTH,
|
|
1488
1566
|
INLINE_PAD,
|
|
1489
1567
|
STEP_KIND_COLORS,
|
|
1490
1568
|
attachNested,
|
|
1491
1569
|
buildOutline,
|
|
1570
|
+
buildScrubber,
|
|
1492
1571
|
buildStory,
|
|
1493
1572
|
buildTimeline,
|
|
1494
1573
|
canExpand,
|
|
1495
1574
|
canOpen,
|
|
1496
1575
|
defaultExpanded,
|
|
1576
|
+
defaultMode,
|
|
1497
1577
|
dist,
|
|
1498
1578
|
frameAt,
|
|
1499
1579
|
hasPhases,
|
|
@@ -1511,12 +1591,17 @@ export {
|
|
|
1511
1591
|
phaseSpans,
|
|
1512
1592
|
pointAt,
|
|
1513
1593
|
polylineLength,
|
|
1594
|
+
positionAt,
|
|
1514
1595
|
rectOfPath,
|
|
1515
1596
|
roundedPath,
|
|
1516
1597
|
routeEdges,
|
|
1517
1598
|
runBounds,
|
|
1518
1599
|
scopeSvgIds,
|
|
1600
|
+
slotAt,
|
|
1601
|
+
slotOfStep,
|
|
1602
|
+
startOf,
|
|
1519
1603
|
stepAt,
|
|
1520
1604
|
stepEnd,
|
|
1521
|
-
stepStart
|
|
1605
|
+
stepStart,
|
|
1606
|
+
timeAt
|
|
1522
1607
|
};
|
package/dist/nested-layout.d.ts
CHANGED
|
@@ -25,7 +25,10 @@ export interface InnerLayout {
|
|
|
25
25
|
layout: NestedLayout;
|
|
26
26
|
}
|
|
27
27
|
export type Diagrams = Record<string, CompiledDiagram | undefined>;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* The view a node's diagram shows when opened: the one the node names, its scenario's, the one the
|
|
30
|
+
* diagram opens on by itself, or the first.
|
|
31
|
+
*/
|
|
29
32
|
export declare function openingView(diagram: CompiledDiagram, ref: NodeDiagram): string;
|
|
30
33
|
/** Whether a reader may show this node's diagram in place: it is at hand and not limited to `open`. */
|
|
31
34
|
export declare const canExpand: (ref: NodeDiagram | undefined, diagrams: Diagrams) => boolean;
|
package/dist/node.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
attachNested,
|
|
3
3
|
linkDiagrams,
|
|
4
4
|
nestedDiagrams
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-P2X2XSBM.js";
|
|
6
6
|
import {
|
|
7
7
|
FamilySchema,
|
|
8
8
|
KNOWN_KEYS,
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
compileDiagram,
|
|
12
12
|
createIconResolver,
|
|
13
13
|
renderMarkdown
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-Q2NHZ6TV.js";
|
|
15
|
+
import "./chunk-ZYFFV7Y7.js";
|
|
16
16
|
|
|
17
17
|
// src/node.ts
|
|
18
18
|
import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
package/dist/schema.d.ts
CHANGED
|
@@ -28,10 +28,24 @@ export declare const DirectionSchema: z.ZodEnum<{
|
|
|
28
28
|
RIGHT: "RIGHT";
|
|
29
29
|
UP: "UP";
|
|
30
30
|
}>;
|
|
31
|
+
/** One field per list item: `- name`, `- name: type` or `- name: { type, key, ref, note }`. */
|
|
32
|
+
declare const FieldSchema: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
|
|
33
|
+
type: z.ZodOptional<z.ZodString>;
|
|
34
|
+
key: z.ZodOptional<z.ZodBoolean>;
|
|
35
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
36
|
+
note: z.ZodOptional<z.ZodString>;
|
|
37
|
+
}, z.core.$strict>]>>]>;
|
|
31
38
|
export declare const NodeSchema: z.ZodObject<{
|
|
32
39
|
title: z.ZodOptional<z.ZodString>;
|
|
33
40
|
sub: z.ZodOptional<z.ZodString>;
|
|
41
|
+
pill: z.ZodOptional<z.ZodString>;
|
|
34
42
|
lines: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
43
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
|
|
44
|
+
type: z.ZodOptional<z.ZodString>;
|
|
45
|
+
key: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
47
|
+
note: z.ZodOptional<z.ZodString>;
|
|
48
|
+
}, z.core.$strict>]>>]>>>;
|
|
35
49
|
icon: z.ZodOptional<z.ZodString>;
|
|
36
50
|
kind: z.ZodOptional<z.ZodString>;
|
|
37
51
|
family: z.ZodOptional<z.ZodEnum<{
|
|
@@ -440,10 +454,34 @@ export declare const ScenarioSchema: z.ZodObject<{
|
|
|
440
454
|
}, z.core.$strict>], "type">>;
|
|
441
455
|
}, z.core.$strict>], "type">>>;
|
|
442
456
|
}, z.core.$strict>;
|
|
457
|
+
export declare const DefaultsSchema: z.ZodObject<{
|
|
458
|
+
view: z.ZodOptional<z.ZodString>;
|
|
459
|
+
scenario: z.ZodOptional<z.ZodString>;
|
|
460
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
461
|
+
flow: "flow";
|
|
462
|
+
sequence: "sequence";
|
|
463
|
+
story: "story";
|
|
464
|
+
}>>;
|
|
465
|
+
sidebar: z.ZodOptional<z.ZodBoolean>;
|
|
466
|
+
subtitles: z.ZodOptional<z.ZodBoolean>;
|
|
467
|
+
autoplay: z.ZodOptional<z.ZodBoolean>;
|
|
468
|
+
}, z.core.$strict>;
|
|
443
469
|
export declare const RootSchema: z.ZodObject<{
|
|
444
470
|
$schema: z.ZodOptional<z.ZodString>;
|
|
445
471
|
title: z.ZodString;
|
|
446
472
|
description: z.ZodOptional<z.ZodString>;
|
|
473
|
+
defaults: z.ZodOptional<z.ZodObject<{
|
|
474
|
+
view: z.ZodOptional<z.ZodString>;
|
|
475
|
+
scenario: z.ZodOptional<z.ZodString>;
|
|
476
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
477
|
+
flow: "flow";
|
|
478
|
+
sequence: "sequence";
|
|
479
|
+
story: "story";
|
|
480
|
+
}>>;
|
|
481
|
+
sidebar: z.ZodOptional<z.ZodBoolean>;
|
|
482
|
+
subtitles: z.ZodOptional<z.ZodBoolean>;
|
|
483
|
+
autoplay: z.ZodOptional<z.ZodBoolean>;
|
|
484
|
+
}, z.core.$strict>>;
|
|
447
485
|
kinds: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
448
486
|
icon: z.ZodOptional<z.ZodString>;
|
|
449
487
|
family: z.ZodOptional<z.ZodEnum<{
|
|
@@ -498,7 +536,14 @@ export declare const RootSchema: z.ZodObject<{
|
|
|
498
536
|
nodes: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
499
537
|
title: z.ZodOptional<z.ZodString>;
|
|
500
538
|
sub: z.ZodOptional<z.ZodString>;
|
|
539
|
+
pill: z.ZodOptional<z.ZodString>;
|
|
501
540
|
lines: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
541
|
+
fields: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNull, z.ZodObject<{
|
|
542
|
+
type: z.ZodOptional<z.ZodString>;
|
|
543
|
+
key: z.ZodOptional<z.ZodBoolean>;
|
|
544
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
545
|
+
note: z.ZodOptional<z.ZodString>;
|
|
546
|
+
}, z.core.$strict>]>>]>>>;
|
|
502
547
|
icon: z.ZodOptional<z.ZodString>;
|
|
503
548
|
kind: z.ZodOptional<z.ZodString>;
|
|
504
549
|
family: z.ZodOptional<z.ZodEnum<{
|
|
@@ -784,6 +829,7 @@ export declare const RootSchema: z.ZodObject<{
|
|
|
784
829
|
}, z.core.$strict>>>;
|
|
785
830
|
}, z.core.$strict>;
|
|
786
831
|
export type RootInput = z.infer<typeof RootSchema>;
|
|
832
|
+
export type FieldInput = z.infer<typeof FieldSchema>;
|
|
787
833
|
export type Step = z.infer<typeof StepSchema>;
|
|
788
834
|
export declare const KNOWN_KEYS: {
|
|
789
835
|
readonly root: string[];
|
|
@@ -792,6 +838,7 @@ export declare const KNOWN_KEYS: {
|
|
|
792
838
|
readonly edge: string[];
|
|
793
839
|
readonly view: string[];
|
|
794
840
|
readonly scenario: string[];
|
|
841
|
+
readonly defaults: string[];
|
|
795
842
|
};
|
|
796
843
|
type Json = Record<string, unknown>;
|
|
797
844
|
/**
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Timeline } from './timeline';
|
|
2
|
+
/** One stop of the slider: a step, or the steps of a `par` block that start together. */
|
|
3
|
+
export interface Slot {
|
|
4
|
+
/** First and last step of the slot, as indexes into `scenario.steps`. */
|
|
5
|
+
from: number;
|
|
6
|
+
to: number;
|
|
7
|
+
/** The time it covers. A slot runs until the next one starts, so pauses belong to the step before. */
|
|
8
|
+
t0: number;
|
|
9
|
+
t1: number;
|
|
10
|
+
}
|
|
11
|
+
/** A run of slots under one phase. A scenario without named phases is one section with no title. */
|
|
12
|
+
export interface Section {
|
|
13
|
+
/** Index in `scenario.phases`. */
|
|
14
|
+
phase: number;
|
|
15
|
+
title: string;
|
|
16
|
+
caption?: string;
|
|
17
|
+
/** First and last slot. */
|
|
18
|
+
from: number;
|
|
19
|
+
to: number;
|
|
20
|
+
}
|
|
21
|
+
export interface Scrubber {
|
|
22
|
+
slots: Slot[];
|
|
23
|
+
sections: Section[];
|
|
24
|
+
duration: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function buildScrubber(tl: Timeline): Scrubber;
|
|
27
|
+
/** Where on the slider, 0 to 1, the moment `t` falls. */
|
|
28
|
+
export declare function positionAt(s: Scrubber, t: number): number;
|
|
29
|
+
/** The moment a place on the slider stands for. The inverse of `positionAt`. */
|
|
30
|
+
export declare function timeAt(s: Scrubber, position: number): number;
|
|
31
|
+
/** The slot a place on the slider falls in. */
|
|
32
|
+
export declare function slotAt(s: Scrubber, position: number): number;
|
|
33
|
+
/** The slot that holds step `index`, or -1. */
|
|
34
|
+
export declare function slotOfStep(s: Scrubber, index: number): number;
|
package/dist/start.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CompiledDiagram, ScenarioMode } from './types';
|
|
2
|
+
/** What the page that shows a diagram asked for, if anything. Its choices win over the diagram's. */
|
|
3
|
+
export interface StartWant {
|
|
4
|
+
view?: string;
|
|
5
|
+
scenario?: string;
|
|
6
|
+
mode?: ScenarioMode;
|
|
7
|
+
}
|
|
8
|
+
export interface Start {
|
|
9
|
+
/** Always one of the diagram's views. */
|
|
10
|
+
view: string;
|
|
11
|
+
/** The scenario selected first, or null for the overview. */
|
|
12
|
+
scenario: string | null;
|
|
13
|
+
mode: ScenarioMode;
|
|
14
|
+
}
|
|
15
|
+
/** The mode a scenario is drawn in when neither it nor the page says: the diagram's, then `flow`. */
|
|
16
|
+
export declare const defaultMode: (diagram: CompiledDiagram) => ScenarioMode;
|
|
17
|
+
/**
|
|
18
|
+
* Where a diagram opens. The page's props come first, then what the diagram's author wrote under
|
|
19
|
+
* `defaults`, then the first view with nothing selected. The page choosing a scenario takes its
|
|
20
|
+
* view along, and one choosing a view leaves the default scenario out unless it plays there.
|
|
21
|
+
*/
|
|
22
|
+
export declare function startOf(diagram: CompiledDiagram, want?: StartWant): Start;
|
package/dist/types.d.ts
CHANGED
|
@@ -29,11 +29,27 @@ export interface NodeDiagram {
|
|
|
29
29
|
/** Starts shown in place. */
|
|
30
30
|
expanded?: boolean;
|
|
31
31
|
}
|
|
32
|
+
/** A row of an entity card: one column, property or attribute of what the node stores. */
|
|
33
|
+
export interface CompiledField {
|
|
34
|
+
name: string;
|
|
35
|
+
type?: string;
|
|
36
|
+
/** Part of the primary key. */
|
|
37
|
+
key?: boolean;
|
|
38
|
+
/** The node (and field) this one points at, like a foreign key. Each one draws a relation. */
|
|
39
|
+
ref?: {
|
|
40
|
+
node: string;
|
|
41
|
+
field?: string;
|
|
42
|
+
};
|
|
43
|
+
note?: string;
|
|
44
|
+
}
|
|
32
45
|
export interface CompiledNode {
|
|
33
46
|
id: string;
|
|
34
47
|
title: string;
|
|
35
48
|
sub?: string;
|
|
49
|
+
/** A short label in the card header, like `TABLE` or `ES INDEX`. */
|
|
50
|
+
pill?: string;
|
|
36
51
|
lines: string[];
|
|
52
|
+
fields: CompiledField[];
|
|
37
53
|
icon?: IconData;
|
|
38
54
|
kind?: string;
|
|
39
55
|
family?: Family;
|
|
@@ -76,6 +92,9 @@ export interface CompiledEdge {
|
|
|
76
92
|
id: string;
|
|
77
93
|
from: string;
|
|
78
94
|
to: string;
|
|
95
|
+
/** Set when the edge starts or ends on one field of an entity card. */
|
|
96
|
+
fromField?: string;
|
|
97
|
+
toField?: string;
|
|
79
98
|
label?: string;
|
|
80
99
|
kind: string;
|
|
81
100
|
both: boolean;
|
|
@@ -147,10 +166,23 @@ export interface CompiledScenario {
|
|
|
147
166
|
phases: CompiledPhase[];
|
|
148
167
|
steps: CompiledStep[];
|
|
149
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* How a diagram opens, as its author wrote it. A page's own choices (the props of `<Diagram>`) win
|
|
171
|
+
* over these. Validated by the compiler: the view and the scenario exist, and agree.
|
|
172
|
+
*/
|
|
173
|
+
export interface DiagramDefaults {
|
|
174
|
+
view?: string;
|
|
175
|
+
scenario?: string;
|
|
176
|
+
mode?: ScenarioMode;
|
|
177
|
+
sidebar?: boolean;
|
|
178
|
+
subtitles?: boolean;
|
|
179
|
+
autoplay?: boolean;
|
|
180
|
+
}
|
|
150
181
|
export interface CompiledDiagram {
|
|
151
182
|
name: string;
|
|
152
183
|
title: string;
|
|
153
184
|
descriptionHtml?: string;
|
|
185
|
+
defaults?: DiagramDefaults;
|
|
154
186
|
nodes: Record<string, CompiledNode>;
|
|
155
187
|
groups: Record<string, CompiledGroup>;
|
|
156
188
|
edges: Record<string, CompiledEdge>;
|