@statelyai/graph 0.12.0 → 1.0.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 +26 -16
- package/dist/{adjacency-list-Ca0VjKIf.mjs → adjacency-list-VsUaH9SJ.mjs} +2 -2
- package/dist/{algorithms-BHHg7lGq.mjs → algorithms-Ba7o7niK.mjs} +35 -31
- package/dist/{algorithms-BlM-qoJb.d.mts → algorithms-fTqmvhzP.d.mts} +1 -1
- package/dist/algorithms.d.mts +1 -1
- package/dist/algorithms.mjs +1 -1
- package/dist/{converter-Dspillnn.mjs → converter-udLITX36.mjs} +2 -2
- package/dist/{edge-list-gKe8-iRa.mjs → edge-list-DP4otyPU.mjs} +1 -1
- package/dist/format-support.d.mts +6 -0
- package/dist/format-support.mjs +68 -33
- package/dist/formats/adjacency-list/index.d.mts +1 -1
- package/dist/formats/adjacency-list/index.mjs +1 -1
- package/dist/formats/converter/index.d.mts +1 -60
- package/dist/formats/converter/index.mjs +1 -1
- package/dist/formats/cytoscape/index.d.mts +1 -1
- package/dist/formats/cytoscape/index.mjs +19 -3
- package/dist/formats/d2/index.d.mts +109 -0
- package/dist/formats/d2/index.mjs +1086 -0
- package/dist/formats/d3/index.d.mts +8 -1
- package/dist/formats/d3/index.mjs +35 -7
- package/dist/formats/dot/index.d.mts +1 -1
- package/dist/formats/dot/index.mjs +3 -3
- package/dist/formats/edge-list/index.d.mts +1 -1
- package/dist/formats/edge-list/index.mjs +1 -1
- package/dist/formats/elk/index.d.mts +1 -1
- package/dist/formats/elk/index.mjs +86 -23
- package/dist/formats/gexf/index.d.mts +1 -1
- package/dist/formats/gexf/index.mjs +102 -4
- package/dist/formats/gml/index.d.mts +1 -1
- package/dist/formats/gml/index.mjs +43 -16
- package/dist/formats/graphml/index.d.mts +1 -1
- package/dist/formats/graphml/index.mjs +11 -4
- package/dist/formats/jgf/index.d.mts +1 -1
- package/dist/formats/jgf/index.mjs +19 -3
- package/dist/formats/mermaid/index.d.mts +2 -1
- package/dist/formats/mermaid/index.mjs +48 -18
- package/dist/formats/tgf/index.d.mts +1 -1
- package/dist/formats/tgf/index.mjs +2 -2
- package/dist/formats/xyflow/index.d.mts +2 -1
- package/dist/formats/xyflow/index.mjs +97 -40
- package/dist/index-CHoriXZD.d.mts +638 -0
- package/dist/index-D9Kj6Fe3.d.mts +61 -0
- package/dist/index.d.mts +6 -631
- package/dist/index.mjs +8 -7
- package/dist/{indexing-CJc-ul8e.mjs → indexing-DR8M1vBy.mjs} +18 -4
- package/dist/mode-D8OnHFBk.mjs +15 -0
- package/dist/queries-BlkA1HAN.d.mts +516 -0
- package/dist/queries.d.mts +1 -514
- package/dist/queries.mjs +17 -15
- package/dist/schemas.d.mts +29 -17
- package/dist/schemas.mjs +139 -6
- package/dist/{types-CnZ01raw.d.mts → types-3-FS9NV2.d.mts} +30 -7
- package/package.json +2 -1
- package/schemas/edge.schema.json +11 -0
- package/schemas/graph.schema.json +25 -3
- package/schemas/node.schema.json +7 -0
package/dist/schemas.d.mts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as GraphNode, b as GraphPort, p as GraphEdge, u as Graph } from "./types-3-FS9NV2.mjs";
|
|
2
2
|
import * as z from "zod";
|
|
3
3
|
|
|
4
4
|
//#region src/schemas.d.ts
|
|
5
5
|
declare const PortSchema: z.ZodObject<{
|
|
6
6
|
name: z.ZodString;
|
|
7
|
-
direction: z.
|
|
7
|
+
direction: z.ZodEnum<{
|
|
8
8
|
in: "in";
|
|
9
9
|
out: "out";
|
|
10
10
|
inout: "inout";
|
|
11
|
-
}
|
|
11
|
+
}>;
|
|
12
12
|
label: z.ZodOptional<z.ZodString>;
|
|
13
13
|
data: z.ZodAny;
|
|
14
14
|
x: z.ZodOptional<z.ZodNumber>;
|
|
15
15
|
y: z.ZodOptional<z.ZodNumber>;
|
|
16
16
|
width: z.ZodOptional<z.ZodNumber>;
|
|
17
17
|
height: z.ZodOptional<z.ZodNumber>;
|
|
18
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
18
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
19
19
|
}, z.core.$strip>;
|
|
20
20
|
declare const NodeSchema: z.ZodObject<{
|
|
21
21
|
type: z.ZodLiteral<"node">;
|
|
@@ -30,21 +30,21 @@ declare const NodeSchema: z.ZodObject<{
|
|
|
30
30
|
height: z.ZodOptional<z.ZodNumber>;
|
|
31
31
|
shape: z.ZodOptional<z.ZodString>;
|
|
32
32
|
color: z.ZodOptional<z.ZodString>;
|
|
33
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
33
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
34
34
|
ports: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
35
35
|
name: z.ZodString;
|
|
36
|
-
direction: z.
|
|
36
|
+
direction: z.ZodEnum<{
|
|
37
37
|
in: "in";
|
|
38
38
|
out: "out";
|
|
39
39
|
inout: "inout";
|
|
40
|
-
}
|
|
40
|
+
}>;
|
|
41
41
|
label: z.ZodOptional<z.ZodString>;
|
|
42
42
|
data: z.ZodAny;
|
|
43
43
|
x: z.ZodOptional<z.ZodNumber>;
|
|
44
44
|
y: z.ZodOptional<z.ZodNumber>;
|
|
45
45
|
width: z.ZodOptional<z.ZodNumber>;
|
|
46
46
|
height: z.ZodOptional<z.ZodNumber>;
|
|
47
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
47
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
48
48
|
}, z.core.$strip>>>;
|
|
49
49
|
}, z.core.$strip>;
|
|
50
50
|
declare const EdgeSchema: z.ZodObject<{
|
|
@@ -56,19 +56,25 @@ declare const EdgeSchema: z.ZodObject<{
|
|
|
56
56
|
weight: z.ZodOptional<z.ZodNumber>;
|
|
57
57
|
sourcePort: z.ZodOptional<z.ZodString>;
|
|
58
58
|
targetPort: z.ZodOptional<z.ZodString>;
|
|
59
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
60
|
+
directed: "directed";
|
|
61
|
+
undirected: "undirected";
|
|
62
|
+
bidirectional: "bidirectional";
|
|
63
|
+
}>>;
|
|
59
64
|
data: z.ZodAny;
|
|
60
65
|
x: z.ZodOptional<z.ZodNumber>;
|
|
61
66
|
y: z.ZodOptional<z.ZodNumber>;
|
|
62
67
|
width: z.ZodOptional<z.ZodNumber>;
|
|
63
68
|
height: z.ZodOptional<z.ZodNumber>;
|
|
64
69
|
color: z.ZodOptional<z.ZodString>;
|
|
65
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
70
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
66
71
|
}, z.core.$strip>;
|
|
67
72
|
declare const GraphSchema: z.ZodObject<{
|
|
68
73
|
id: z.ZodString;
|
|
69
|
-
|
|
74
|
+
mode: z.ZodEnum<{
|
|
70
75
|
directed: "directed";
|
|
71
76
|
undirected: "undirected";
|
|
77
|
+
bidirectional: "bidirectional";
|
|
72
78
|
}>;
|
|
73
79
|
initialNodeId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
74
80
|
nodes: z.ZodArray<z.ZodObject<{
|
|
@@ -84,21 +90,21 @@ declare const GraphSchema: z.ZodObject<{
|
|
|
84
90
|
height: z.ZodOptional<z.ZodNumber>;
|
|
85
91
|
shape: z.ZodOptional<z.ZodString>;
|
|
86
92
|
color: z.ZodOptional<z.ZodString>;
|
|
87
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
93
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
88
94
|
ports: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
89
95
|
name: z.ZodString;
|
|
90
|
-
direction: z.
|
|
96
|
+
direction: z.ZodEnum<{
|
|
91
97
|
in: "in";
|
|
92
98
|
out: "out";
|
|
93
99
|
inout: "inout";
|
|
94
|
-
}
|
|
100
|
+
}>;
|
|
95
101
|
label: z.ZodOptional<z.ZodString>;
|
|
96
102
|
data: z.ZodAny;
|
|
97
103
|
x: z.ZodOptional<z.ZodNumber>;
|
|
98
104
|
y: z.ZodOptional<z.ZodNumber>;
|
|
99
105
|
width: z.ZodOptional<z.ZodNumber>;
|
|
100
106
|
height: z.ZodOptional<z.ZodNumber>;
|
|
101
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
107
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
102
108
|
}, z.core.$strip>>>;
|
|
103
109
|
}, z.core.$strip>>;
|
|
104
110
|
edges: z.ZodArray<z.ZodObject<{
|
|
@@ -110,13 +116,18 @@ declare const GraphSchema: z.ZodObject<{
|
|
|
110
116
|
weight: z.ZodOptional<z.ZodNumber>;
|
|
111
117
|
sourcePort: z.ZodOptional<z.ZodString>;
|
|
112
118
|
targetPort: z.ZodOptional<z.ZodString>;
|
|
119
|
+
mode: z.ZodOptional<z.ZodEnum<{
|
|
120
|
+
directed: "directed";
|
|
121
|
+
undirected: "undirected";
|
|
122
|
+
bidirectional: "bidirectional";
|
|
123
|
+
}>>;
|
|
113
124
|
data: z.ZodAny;
|
|
114
125
|
x: z.ZodOptional<z.ZodNumber>;
|
|
115
126
|
y: z.ZodOptional<z.ZodNumber>;
|
|
116
127
|
width: z.ZodOptional<z.ZodNumber>;
|
|
117
128
|
height: z.ZodOptional<z.ZodNumber>;
|
|
118
129
|
color: z.ZodOptional<z.ZodString>;
|
|
119
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
130
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
120
131
|
}, z.core.$strip>>;
|
|
121
132
|
data: z.ZodAny;
|
|
122
133
|
direction: z.ZodOptional<z.ZodEnum<{
|
|
@@ -125,7 +136,7 @@ declare const GraphSchema: z.ZodObject<{
|
|
|
125
136
|
left: "left";
|
|
126
137
|
right: "right";
|
|
127
138
|
}>>;
|
|
128
|
-
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
|
|
139
|
+
style: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
129
140
|
}, z.core.$strip>;
|
|
130
141
|
interface GraphValidationIssue {
|
|
131
142
|
code: string;
|
|
@@ -140,5 +151,6 @@ declare function getGraphPortIssues(value: unknown): GraphValidationIssue[];
|
|
|
140
151
|
declare function getGraphNodeIssues(value: unknown): GraphValidationIssue[];
|
|
141
152
|
declare function getGraphEdgeIssues(value: unknown): GraphValidationIssue[];
|
|
142
153
|
declare function getGraphIssues(value: unknown): GraphValidationIssue[];
|
|
154
|
+
declare function validateGraph(value: unknown): GraphValidationIssue[];
|
|
143
155
|
//#endregion
|
|
144
|
-
export { EdgeSchema, GraphSchema, GraphValidationIssue, NodeSchema, PortSchema, getGraphEdgeIssues, getGraphIssues, getGraphNodeIssues, getGraphPortIssues, isGraph, isGraphEdge, isGraphNode, isGraphPort };
|
|
156
|
+
export { EdgeSchema, GraphSchema, GraphValidationIssue, NodeSchema, PortSchema, getGraphEdgeIssues, getGraphIssues, getGraphNodeIssues, getGraphPortIssues, isGraph, isGraphEdge, isGraphNode, isGraphPort, validateGraph };
|
package/dist/schemas.mjs
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
|
|
3
3
|
//#region src/schemas.ts
|
|
4
|
-
const StyleSchema = z.record(z.string(), z.union([
|
|
4
|
+
const StyleSchema = z.record(z.string(), z.union([
|
|
5
|
+
z.string(),
|
|
6
|
+
z.number(),
|
|
7
|
+
z.boolean()
|
|
8
|
+
]));
|
|
9
|
+
const ModeSchema = z.enum([
|
|
10
|
+
"directed",
|
|
11
|
+
"undirected",
|
|
12
|
+
"bidirectional"
|
|
13
|
+
]);
|
|
5
14
|
const PortDirectionSchema = z.enum([
|
|
6
15
|
"in",
|
|
7
16
|
"out",
|
|
@@ -9,7 +18,7 @@ const PortDirectionSchema = z.enum([
|
|
|
9
18
|
]);
|
|
10
19
|
const PortSchema = z.object({
|
|
11
20
|
name: z.string(),
|
|
12
|
-
direction: PortDirectionSchema
|
|
21
|
+
direction: PortDirectionSchema,
|
|
13
22
|
label: z.string().optional(),
|
|
14
23
|
data: z.any(),
|
|
15
24
|
x: z.number().optional(),
|
|
@@ -43,6 +52,7 @@ const EdgeSchema = z.object({
|
|
|
43
52
|
weight: z.number().optional(),
|
|
44
53
|
sourcePort: z.string().optional(),
|
|
45
54
|
targetPort: z.string().optional(),
|
|
55
|
+
mode: ModeSchema.optional(),
|
|
46
56
|
data: z.any(),
|
|
47
57
|
x: z.number().optional(),
|
|
48
58
|
y: z.number().optional(),
|
|
@@ -53,7 +63,7 @@ const EdgeSchema = z.object({
|
|
|
53
63
|
});
|
|
54
64
|
const GraphSchema = z.object({
|
|
55
65
|
id: z.string(),
|
|
56
|
-
|
|
66
|
+
mode: ModeSchema,
|
|
57
67
|
initialNodeId: z.string().nullable().optional(),
|
|
58
68
|
nodes: z.array(NodeSchema),
|
|
59
69
|
edges: z.array(EdgeSchema),
|
|
@@ -85,7 +95,7 @@ function isGraphEdge(value) {
|
|
|
85
95
|
return EdgeSchema.safeParse(value).success;
|
|
86
96
|
}
|
|
87
97
|
function isGraph(value) {
|
|
88
|
-
return
|
|
98
|
+
return validateGraph(value).length === 0;
|
|
89
99
|
}
|
|
90
100
|
function getGraphPortIssues(value) {
|
|
91
101
|
return getValidationIssues(PortSchema, value);
|
|
@@ -97,8 +107,131 @@ function getGraphEdgeIssues(value) {
|
|
|
97
107
|
return getValidationIssues(EdgeSchema, value);
|
|
98
108
|
}
|
|
99
109
|
function getGraphIssues(value) {
|
|
100
|
-
return
|
|
110
|
+
return validateGraph(value);
|
|
111
|
+
}
|
|
112
|
+
function createIssue(code, message, path) {
|
|
113
|
+
return {
|
|
114
|
+
code,
|
|
115
|
+
message,
|
|
116
|
+
path
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function getDuplicateIndexes(items, getKey) {
|
|
120
|
+
const indexesByKey = /* @__PURE__ */ new Map();
|
|
121
|
+
items.forEach((item, index) => {
|
|
122
|
+
const key = getKey(item);
|
|
123
|
+
if (key == null) return;
|
|
124
|
+
const indexes = indexesByKey.get(key) ?? [];
|
|
125
|
+
indexes.push(index);
|
|
126
|
+
indexesByKey.set(key, indexes);
|
|
127
|
+
});
|
|
128
|
+
for (const [key, indexes] of indexesByKey) if (indexes.length < 2) indexesByKey.delete(key);
|
|
129
|
+
return indexesByKey;
|
|
130
|
+
}
|
|
131
|
+
function getGraphInvariantIssues(graph) {
|
|
132
|
+
const issues = [];
|
|
133
|
+
const nodeIndexes = /* @__PURE__ */ new Map();
|
|
134
|
+
const nodesById = /* @__PURE__ */ new Map();
|
|
135
|
+
for (const [id, indexes] of getDuplicateIndexes(graph.nodes, (node) => node.id)) for (const index of indexes) issues.push(createIssue("duplicate_node_id", `Duplicate node id "${id}"`, [
|
|
136
|
+
"nodes",
|
|
137
|
+
index,
|
|
138
|
+
"id"
|
|
139
|
+
]));
|
|
140
|
+
for (const [id, indexes] of getDuplicateIndexes(graph.edges, (edge) => edge.id)) for (const index of indexes) issues.push(createIssue("duplicate_edge_id", `Duplicate edge id "${id}"`, [
|
|
141
|
+
"edges",
|
|
142
|
+
index,
|
|
143
|
+
"id"
|
|
144
|
+
]));
|
|
145
|
+
graph.nodes.forEach((node, index) => {
|
|
146
|
+
nodeIndexes.set(node.id, index);
|
|
147
|
+
nodesById.set(node.id, node);
|
|
148
|
+
});
|
|
149
|
+
if (graph.initialNodeId && !nodeIndexes.has(graph.initialNodeId)) issues.push(createIssue("missing_initial_node", `Initial node "${graph.initialNodeId}" does not exist`, ["initialNodeId"]));
|
|
150
|
+
graph.nodes.forEach((node, index) => {
|
|
151
|
+
if (node.id === "") issues.push(createIssue("empty_node_id", "Node id must be a non-empty string", [
|
|
152
|
+
"nodes",
|
|
153
|
+
index,
|
|
154
|
+
"id"
|
|
155
|
+
]));
|
|
156
|
+
if (node.parentId === "") issues.push(createIssue("empty_parent_id", "Node parentId must be a non-empty string", [
|
|
157
|
+
"nodes",
|
|
158
|
+
index,
|
|
159
|
+
"parentId"
|
|
160
|
+
]));
|
|
161
|
+
else if (node.parentId != null && !nodeIndexes.has(node.parentId)) issues.push(createIssue("missing_parent", `Parent node "${node.parentId}" does not exist`, [
|
|
162
|
+
"nodes",
|
|
163
|
+
index,
|
|
164
|
+
"parentId"
|
|
165
|
+
]));
|
|
166
|
+
if (node.initialNodeId && !nodeIndexes.has(node.initialNodeId)) issues.push(createIssue("missing_node_initial", `Initial node "${node.initialNodeId}" does not exist`, [
|
|
167
|
+
"nodes",
|
|
168
|
+
index,
|
|
169
|
+
"initialNodeId"
|
|
170
|
+
]));
|
|
171
|
+
for (const [name, indexes] of getDuplicateIndexes(node.ports ?? [], (port) => port.name)) for (const portIndex of indexes) issues.push(createIssue("duplicate_port_name", `Duplicate port name "${name}" on node "${node.id}"`, [
|
|
172
|
+
"nodes",
|
|
173
|
+
index,
|
|
174
|
+
"ports",
|
|
175
|
+
portIndex,
|
|
176
|
+
"name"
|
|
177
|
+
]));
|
|
178
|
+
});
|
|
179
|
+
for (const node of graph.nodes) {
|
|
180
|
+
const seen = /* @__PURE__ */ new Set();
|
|
181
|
+
let current = node.parentId;
|
|
182
|
+
while (current != null) {
|
|
183
|
+
if (current === node.id || seen.has(current)) {
|
|
184
|
+
issues.push(createIssue("parent_cycle", `Node "${node.id}" is part of a parent cycle`, [
|
|
185
|
+
"nodes",
|
|
186
|
+
nodeIndexes.get(node.id) ?? 0,
|
|
187
|
+
"parentId"
|
|
188
|
+
]));
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
seen.add(current);
|
|
192
|
+
current = nodesById.get(current)?.parentId;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
graph.edges.forEach((edge, index) => {
|
|
196
|
+
if (edge.id === "") issues.push(createIssue("empty_edge_id", "Edge id must be a non-empty string", [
|
|
197
|
+
"edges",
|
|
198
|
+
index,
|
|
199
|
+
"id"
|
|
200
|
+
]));
|
|
201
|
+
const source = nodesById.get(edge.sourceId);
|
|
202
|
+
const target = nodesById.get(edge.targetId);
|
|
203
|
+
if (!source) issues.push(createIssue("missing_source_node", `Source node "${edge.sourceId}" does not exist`, [
|
|
204
|
+
"edges",
|
|
205
|
+
index,
|
|
206
|
+
"sourceId"
|
|
207
|
+
]));
|
|
208
|
+
if (!target) issues.push(createIssue("missing_target_node", `Target node "${edge.targetId}" does not exist`, [
|
|
209
|
+
"edges",
|
|
210
|
+
index,
|
|
211
|
+
"targetId"
|
|
212
|
+
]));
|
|
213
|
+
if (source && edge.sourcePort !== void 0 && !source.ports?.some((port) => port.name === edge.sourcePort)) issues.push(createIssue("missing_source_port", `Port "${edge.sourcePort}" does not exist on source node "${edge.sourceId}"`, [
|
|
214
|
+
"edges",
|
|
215
|
+
index,
|
|
216
|
+
"sourcePort"
|
|
217
|
+
]));
|
|
218
|
+
if (target && edge.targetPort !== void 0 && !target.ports?.some((port) => port.name === edge.targetPort)) issues.push(createIssue("missing_target_port", `Port "${edge.targetPort}" does not exist on target node "${edge.targetId}"`, [
|
|
219
|
+
"edges",
|
|
220
|
+
index,
|
|
221
|
+
"targetPort"
|
|
222
|
+
]));
|
|
223
|
+
});
|
|
224
|
+
return issues;
|
|
225
|
+
}
|
|
226
|
+
function validateGraph(value) {
|
|
227
|
+
const shapeResult = GraphSchema.safeParse(value);
|
|
228
|
+
if (!shapeResult.success) return shapeResult.error.issues.map((issue) => ({
|
|
229
|
+
code: issue.code,
|
|
230
|
+
message: issue.message,
|
|
231
|
+
path: issue.path.map((segment) => typeof segment === "symbol" ? String(segment) : segment)
|
|
232
|
+
}));
|
|
233
|
+
return getGraphInvariantIssues(shapeResult.data);
|
|
101
234
|
}
|
|
102
235
|
|
|
103
236
|
//#endregion
|
|
104
|
-
export { EdgeSchema, GraphSchema, NodeSchema, PortSchema, getGraphEdgeIssues, getGraphIssues, getGraphNodeIssues, getGraphPortIssues, isGraph, isGraphEdge, isGraphNode, isGraphPort };
|
|
237
|
+
export { EdgeSchema, GraphSchema, NodeSchema, PortSchema, getGraphEdgeIssues, getGraphIssues, getGraphNodeIssues, getGraphPortIssues, isGraph, isGraphEdge, isGraphNode, isGraphPort, validateGraph };
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Directedness of a graph or an individual edge.
|
|
4
|
+
*
|
|
5
|
+
* - `'directed'` — edge points from source to target.
|
|
6
|
+
* - `'undirected'` — edge has no direction; traversable both ways.
|
|
7
|
+
* - `'bidirectional'` — edge points both ways (arrows on both ends).
|
|
8
|
+
*
|
|
9
|
+
* Set at the graph level as the default ({@link Graph.mode}); individual edges
|
|
10
|
+
* may override it ({@link GraphEdge.mode}).
|
|
11
|
+
*/
|
|
12
|
+
type GraphMode = 'directed' | 'undirected' | 'bidirectional';
|
|
2
13
|
interface EntityRect {
|
|
3
14
|
x: number;
|
|
4
15
|
y: number;
|
|
@@ -11,7 +22,7 @@ interface GraphEntity {
|
|
|
11
22
|
y?: number;
|
|
12
23
|
width?: number;
|
|
13
24
|
height?: number;
|
|
14
|
-
style?: Record<string, string | number>;
|
|
25
|
+
style?: Record<string, string | number | boolean>;
|
|
15
26
|
}
|
|
16
27
|
/** Visual entity base — required position/size. */
|
|
17
28
|
interface VisualGraphEntity {
|
|
@@ -19,7 +30,7 @@ interface VisualGraphEntity {
|
|
|
19
30
|
y: number;
|
|
20
31
|
width: number;
|
|
21
32
|
height: number;
|
|
22
|
-
style?: Record<string, string | number>;
|
|
33
|
+
style?: Record<string, string | number | boolean>;
|
|
23
34
|
}
|
|
24
35
|
type PortDirection = 'in' | 'out' | 'inout';
|
|
25
36
|
interface PortConfig<TPortData = any> extends GraphEntity {
|
|
@@ -42,13 +53,14 @@ interface VisualPort<TPortData = any> extends GraphPort<TPortData> {
|
|
|
42
53
|
}
|
|
43
54
|
interface GraphConfig<TNodeData = any, TEdgeData = any, TGraphData = any, TPortData = any> {
|
|
44
55
|
id?: string;
|
|
45
|
-
|
|
56
|
+
/** Default directedness for all edges. Defaults to `'directed'`. */
|
|
57
|
+
mode?: GraphMode;
|
|
46
58
|
initialNodeId?: string;
|
|
47
59
|
nodes?: NodeConfig<TNodeData, TPortData>[];
|
|
48
60
|
edges?: EdgeConfig<TEdgeData>[];
|
|
49
61
|
data?: TGraphData;
|
|
50
62
|
direction?: 'up' | 'down' | 'left' | 'right';
|
|
51
|
-
style?: Record<string, string | number>;
|
|
63
|
+
style?: Record<string, string | number | boolean>;
|
|
52
64
|
}
|
|
53
65
|
interface NodeConfig<TNodeData = any, TPortData = any> extends GraphEntity {
|
|
54
66
|
id: string;
|
|
@@ -87,18 +99,24 @@ interface EdgeConfig<TEdgeData = any> extends GraphEntity {
|
|
|
87
99
|
sourcePort?: string;
|
|
88
100
|
/** Port name on the target node this edge connects to. */
|
|
89
101
|
targetPort?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Per-edge directedness override. When absent, the edge inherits the graph's
|
|
104
|
+
* {@link GraphConfig.mode}.
|
|
105
|
+
*/
|
|
106
|
+
mode?: GraphMode;
|
|
90
107
|
data?: TEdgeData;
|
|
91
108
|
color?: string;
|
|
92
109
|
}
|
|
93
110
|
interface Graph<TNodeData = any, TEdgeData = any, TGraphData = any, TPortData = any> {
|
|
94
111
|
id: string;
|
|
95
|
-
|
|
112
|
+
/** Default directedness for all edges. */
|
|
113
|
+
mode: GraphMode;
|
|
96
114
|
initialNodeId?: string | null;
|
|
97
115
|
nodes: GraphNode<TNodeData, TPortData>[];
|
|
98
116
|
edges: GraphEdge<TEdgeData>[];
|
|
99
117
|
data: TGraphData;
|
|
100
118
|
direction?: 'up' | 'down' | 'left' | 'right';
|
|
101
|
-
style?: Record<string, string | number>;
|
|
119
|
+
style?: Record<string, string | number | boolean>;
|
|
102
120
|
}
|
|
103
121
|
interface GraphNode<TNodeData = any, TPortData = any> extends GraphEntity {
|
|
104
122
|
type: 'node';
|
|
@@ -127,6 +145,11 @@ interface GraphEdge<TEdgeData = any> extends GraphEntity {
|
|
|
127
145
|
sourcePort?: string;
|
|
128
146
|
/** Port name on the target node this edge connects to. */
|
|
129
147
|
targetPort?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Per-edge directedness override. When absent, the edge inherits the graph's
|
|
150
|
+
* {@link Graph.mode}.
|
|
151
|
+
*/
|
|
152
|
+
mode?: GraphMode;
|
|
130
153
|
data: TEdgeData;
|
|
131
154
|
color?: string;
|
|
132
155
|
}
|
|
@@ -352,4 +375,4 @@ interface TransitionOptions<TState, TEvent> {
|
|
|
352
375
|
id?: string;
|
|
353
376
|
}
|
|
354
377
|
//#endregion
|
|
355
|
-
export {
|
|
378
|
+
export { TraversalOptions as A, WeightedWalkOptions as B, NodeChange as C, PortDirection as D, PortConfig as E, VisualGraphFormatConverter as F, VisualNode as I, VisualPort as L, VisualGraph as M, VisualGraphConfig as N, SinglePathOptions as O, VisualGraphEntity as P, WalkContext as R, MSTOptions as S, PathOptions as T, GraphNode as _, EdgeChange as a, GraphPort as b, EntitiesUpdate as c, GraphConfig as d, GraphDiff as f, GraphMode as g, GraphFormatConverter as h, DeleteNodeOptions as i, VisualEdge as j, TransitionOptions as k, EntityRect as l, GraphEntity as m, AllPairsShortestPathsOptions as n, EdgeConfig as o, GraphEdge as p, CoverageStats as r, EntitiesConfig as s, AStarOptions as t, Graph as u, GraphPatch as v, NodeConfig as w, GraphStep as x, GraphPath as y, WalkOptions as z };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statelyai/graph",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "A TypeScript-first graph library with plain JSON-serializable objects",
|
|
6
6
|
"author": "David Khourshid <david@stately.ai>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"./adjacency-list": "./dist/formats/adjacency-list/index.mjs",
|
|
29
29
|
"./converter": "./dist/formats/converter/index.mjs",
|
|
30
30
|
"./cytoscape": "./dist/formats/cytoscape/index.mjs",
|
|
31
|
+
"./d2": "./dist/formats/d2/index.mjs",
|
|
31
32
|
"./d3": "./dist/formats/d3/index.mjs",
|
|
32
33
|
"./dot": "./dist/formats/dot/index.mjs",
|
|
33
34
|
"./edge-list": "./dist/formats/edge-list/index.mjs",
|
package/schemas/edge.schema.json
CHANGED
|
@@ -34,6 +34,14 @@
|
|
|
34
34
|
"targetPort": {
|
|
35
35
|
"type": "string"
|
|
36
36
|
},
|
|
37
|
+
"mode": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"enum": [
|
|
40
|
+
"directed",
|
|
41
|
+
"undirected",
|
|
42
|
+
"bidirectional"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
37
45
|
"data": {},
|
|
38
46
|
"x": {
|
|
39
47
|
"type": "number"
|
|
@@ -62,6 +70,9 @@
|
|
|
62
70
|
},
|
|
63
71
|
{
|
|
64
72
|
"type": "number"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "boolean"
|
|
65
76
|
}
|
|
66
77
|
]
|
|
67
78
|
}
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
"id": {
|
|
6
6
|
"type": "string"
|
|
7
7
|
},
|
|
8
|
-
"
|
|
8
|
+
"mode": {
|
|
9
9
|
"type": "string",
|
|
10
10
|
"enum": [
|
|
11
11
|
"directed",
|
|
12
|
-
"undirected"
|
|
12
|
+
"undirected",
|
|
13
|
+
"bidirectional"
|
|
13
14
|
]
|
|
14
15
|
},
|
|
15
16
|
"initialNodeId": {
|
|
@@ -95,6 +96,9 @@
|
|
|
95
96
|
},
|
|
96
97
|
{
|
|
97
98
|
"type": "number"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"type": "boolean"
|
|
98
102
|
}
|
|
99
103
|
]
|
|
100
104
|
}
|
|
@@ -143,6 +147,9 @@
|
|
|
143
147
|
},
|
|
144
148
|
{
|
|
145
149
|
"type": "number"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"type": "boolean"
|
|
146
153
|
}
|
|
147
154
|
]
|
|
148
155
|
}
|
|
@@ -150,6 +157,7 @@
|
|
|
150
157
|
},
|
|
151
158
|
"required": [
|
|
152
159
|
"name",
|
|
160
|
+
"direction",
|
|
153
161
|
"data"
|
|
154
162
|
],
|
|
155
163
|
"additionalProperties": false
|
|
@@ -201,6 +209,14 @@
|
|
|
201
209
|
"targetPort": {
|
|
202
210
|
"type": "string"
|
|
203
211
|
},
|
|
212
|
+
"mode": {
|
|
213
|
+
"type": "string",
|
|
214
|
+
"enum": [
|
|
215
|
+
"directed",
|
|
216
|
+
"undirected",
|
|
217
|
+
"bidirectional"
|
|
218
|
+
]
|
|
219
|
+
},
|
|
204
220
|
"data": {},
|
|
205
221
|
"x": {
|
|
206
222
|
"type": "number"
|
|
@@ -229,6 +245,9 @@
|
|
|
229
245
|
},
|
|
230
246
|
{
|
|
231
247
|
"type": "number"
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"type": "boolean"
|
|
232
251
|
}
|
|
233
252
|
]
|
|
234
253
|
}
|
|
@@ -266,6 +285,9 @@
|
|
|
266
285
|
},
|
|
267
286
|
{
|
|
268
287
|
"type": "number"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"type": "boolean"
|
|
269
291
|
}
|
|
270
292
|
]
|
|
271
293
|
}
|
|
@@ -273,7 +295,7 @@
|
|
|
273
295
|
},
|
|
274
296
|
"required": [
|
|
275
297
|
"id",
|
|
276
|
-
"
|
|
298
|
+
"mode",
|
|
277
299
|
"nodes",
|
|
278
300
|
"edges",
|
|
279
301
|
"data"
|
package/schemas/node.schema.json
CHANGED
|
@@ -70,6 +70,9 @@
|
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
"type": "number"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "boolean"
|
|
73
76
|
}
|
|
74
77
|
]
|
|
75
78
|
}
|
|
@@ -118,6 +121,9 @@
|
|
|
118
121
|
},
|
|
119
122
|
{
|
|
120
123
|
"type": "number"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"type": "boolean"
|
|
121
127
|
}
|
|
122
128
|
]
|
|
123
129
|
}
|
|
@@ -125,6 +131,7 @@
|
|
|
125
131
|
},
|
|
126
132
|
"required": [
|
|
127
133
|
"name",
|
|
134
|
+
"direction",
|
|
128
135
|
"data"
|
|
129
136
|
],
|
|
130
137
|
"additionalProperties": false
|