@statelyai/graph 0.1.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 +191 -0
- package/dist/adjacency-list-CXpOCibq.mjs +49 -0
- package/dist/adjacency-list-DW-lAUe8.d.mts +10 -0
- package/dist/algorithms-R35X6ro4.mjs +1197 -0
- package/dist/algorithms.d.mts +82 -0
- package/dist/algorithms.mjs +3 -0
- package/dist/dot-BRtq3e3c.mjs +59 -0
- package/dist/dot-HmJeUMsj.d.mts +6 -0
- package/dist/edge-list-BRujEnnU.mjs +39 -0
- package/dist/edge-list-CJmfoNu2.d.mts +10 -0
- package/dist/formats/adjacency-list.d.mts +2 -0
- package/dist/formats/adjacency-list.mjs +3 -0
- package/dist/formats/dot.d.mts +2 -0
- package/dist/formats/dot.mjs +3 -0
- package/dist/formats/edge-list.d.mts +2 -0
- package/dist/formats/edge-list.mjs +3 -0
- package/dist/formats/graphml.d.mts +2 -0
- package/dist/formats/graphml.mjs +3 -0
- package/dist/graphml-CMjPzSfY.d.mts +7 -0
- package/dist/graphml-CUTNRXqd.mjs +240 -0
- package/dist/index.d.mts +142 -0
- package/dist/index.mjs +356 -0
- package/dist/indexing-BHg1VhqN.mjs +93 -0
- package/dist/queries.d.mts +37 -0
- package/dist/queries.mjs +221 -0
- package/dist/schemas.d.mts +46 -0
- package/dist/schemas.mjs +30 -0
- package/dist/types-XV3S5Jnh.d.mts +219 -0
- package/package.json +77 -0
- package/schemas/edge.schema.json +32 -0
- package/schemas/graph.schema.json +96 -0
- package/schemas/node.schema.json +35 -0
package/dist/queries.mjs
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { t as getIndex } from "./indexing-BHg1VhqN.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/queries.ts
|
|
4
|
+
function getEdgesOf(graph, nodeId) {
|
|
5
|
+
const idx = getIndex(graph);
|
|
6
|
+
const outIds = idx.outEdges.get(nodeId) ?? [];
|
|
7
|
+
const inIds = idx.inEdges.get(nodeId) ?? [];
|
|
8
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9
|
+
const result = [];
|
|
10
|
+
for (const eid of outIds) {
|
|
11
|
+
seen.add(eid);
|
|
12
|
+
const ai = idx.edgeById.get(eid);
|
|
13
|
+
if (ai !== void 0) result.push(graph.edges[ai]);
|
|
14
|
+
}
|
|
15
|
+
for (const eid of inIds) if (!seen.has(eid)) {
|
|
16
|
+
const ai = idx.edgeById.get(eid);
|
|
17
|
+
if (ai !== void 0) result.push(graph.edges[ai]);
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
function getInEdges(graph, nodeId) {
|
|
22
|
+
const idx = getIndex(graph);
|
|
23
|
+
return (idx.inEdges.get(nodeId) ?? []).map((eid) => graph.edges[idx.edgeById.get(eid)]);
|
|
24
|
+
}
|
|
25
|
+
function getOutEdges(graph, nodeId) {
|
|
26
|
+
const idx = getIndex(graph);
|
|
27
|
+
return (idx.outEdges.get(nodeId) ?? []).map((eid) => graph.edges[idx.edgeById.get(eid)]);
|
|
28
|
+
}
|
|
29
|
+
function getEdgeBetween(graph, sourceId, targetId) {
|
|
30
|
+
const idx = getIndex(graph);
|
|
31
|
+
const outIds = idx.outEdges.get(sourceId) ?? [];
|
|
32
|
+
for (const eid of outIds) {
|
|
33
|
+
const ai = idx.edgeById.get(eid);
|
|
34
|
+
const e = graph.edges[ai];
|
|
35
|
+
if (e.targetId === targetId) return e;
|
|
36
|
+
}
|
|
37
|
+
if (graph.type === "undirected") {
|
|
38
|
+
const outIds2 = idx.outEdges.get(targetId) ?? [];
|
|
39
|
+
for (const eid of outIds2) {
|
|
40
|
+
const ai = idx.edgeById.get(eid);
|
|
41
|
+
const e = graph.edges[ai];
|
|
42
|
+
if (e.targetId === sourceId) return e;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function getSuccessors(graph, nodeId) {
|
|
47
|
+
const idx = getIndex(graph);
|
|
48
|
+
const edgeIds = idx.outEdges.get(nodeId) ?? [];
|
|
49
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50
|
+
const result = [];
|
|
51
|
+
for (const eid of edgeIds) {
|
|
52
|
+
const e = graph.edges[idx.edgeById.get(eid)];
|
|
53
|
+
if (!seen.has(e.targetId)) {
|
|
54
|
+
seen.add(e.targetId);
|
|
55
|
+
const ni = idx.nodeById.get(e.targetId);
|
|
56
|
+
if (ni !== void 0) result.push(graph.nodes[ni]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
function getPredecessors(graph, nodeId) {
|
|
62
|
+
const idx = getIndex(graph);
|
|
63
|
+
const edgeIds = idx.inEdges.get(nodeId) ?? [];
|
|
64
|
+
const seen = /* @__PURE__ */ new Set();
|
|
65
|
+
const result = [];
|
|
66
|
+
for (const eid of edgeIds) {
|
|
67
|
+
const e = graph.edges[idx.edgeById.get(eid)];
|
|
68
|
+
if (!seen.has(e.sourceId)) {
|
|
69
|
+
seen.add(e.sourceId);
|
|
70
|
+
const ni = idx.nodeById.get(e.sourceId);
|
|
71
|
+
if (ni !== void 0) result.push(graph.nodes[ni]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
function getNeighbors(graph, nodeId) {
|
|
77
|
+
const idx = getIndex(graph);
|
|
78
|
+
const ids = /* @__PURE__ */ new Set();
|
|
79
|
+
for (const eid of idx.outEdges.get(nodeId) ?? []) ids.add(graph.edges[idx.edgeById.get(eid)].targetId);
|
|
80
|
+
for (const eid of idx.inEdges.get(nodeId) ?? []) ids.add(graph.edges[idx.edgeById.get(eid)].sourceId);
|
|
81
|
+
return [...ids].map((id) => graph.nodes[idx.nodeById.get(id)]).filter(Boolean);
|
|
82
|
+
}
|
|
83
|
+
function getDegree(graph, nodeId) {
|
|
84
|
+
const idx = getIndex(graph);
|
|
85
|
+
if (graph.type === "undirected") {
|
|
86
|
+
const out = idx.outEdges.get(nodeId) ?? [];
|
|
87
|
+
const inE = idx.inEdges.get(nodeId) ?? [];
|
|
88
|
+
return new Set([...out, ...inE]).size;
|
|
89
|
+
}
|
|
90
|
+
return (idx.inEdges.get(nodeId)?.length ?? 0) + (idx.outEdges.get(nodeId)?.length ?? 0);
|
|
91
|
+
}
|
|
92
|
+
function getInDegree(graph, nodeId) {
|
|
93
|
+
return getIndex(graph).inEdges.get(nodeId)?.length ?? 0;
|
|
94
|
+
}
|
|
95
|
+
function getOutDegree(graph, nodeId) {
|
|
96
|
+
return getIndex(graph).outEdges.get(nodeId)?.length ?? 0;
|
|
97
|
+
}
|
|
98
|
+
function getChildren(graph, nodeId) {
|
|
99
|
+
const idx = getIndex(graph);
|
|
100
|
+
return (idx.childNodes.get(nodeId) ?? []).map((id) => graph.nodes[idx.nodeById.get(id)]).filter(Boolean);
|
|
101
|
+
}
|
|
102
|
+
function getParent(graph, nodeId) {
|
|
103
|
+
const idx = getIndex(graph);
|
|
104
|
+
const ni = idx.nodeById.get(nodeId);
|
|
105
|
+
if (ni === void 0) return void 0;
|
|
106
|
+
const node = graph.nodes[ni];
|
|
107
|
+
if (node.parentId === null) return void 0;
|
|
108
|
+
const pi = idx.nodeById.get(node.parentId);
|
|
109
|
+
return pi !== void 0 ? graph.nodes[pi] : void 0;
|
|
110
|
+
}
|
|
111
|
+
function getAncestors(graph, nodeId) {
|
|
112
|
+
const idx = getIndex(graph);
|
|
113
|
+
const result = [];
|
|
114
|
+
let ni = idx.nodeById.get(nodeId);
|
|
115
|
+
if (ni === void 0) return result;
|
|
116
|
+
let current = graph.nodes[ni];
|
|
117
|
+
while (current && current.parentId !== null) {
|
|
118
|
+
const pi = idx.nodeById.get(current.parentId);
|
|
119
|
+
if (pi === void 0) break;
|
|
120
|
+
const p = graph.nodes[pi];
|
|
121
|
+
result.push(p);
|
|
122
|
+
current = p;
|
|
123
|
+
}
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
function getDescendants(graph, nodeId) {
|
|
127
|
+
const idx = getIndex(graph);
|
|
128
|
+
const result = [];
|
|
129
|
+
const collect = (id) => {
|
|
130
|
+
const childIds = idx.childNodes.get(id) ?? [];
|
|
131
|
+
for (const childId of childIds) {
|
|
132
|
+
const ci = idx.nodeById.get(childId);
|
|
133
|
+
if (ci !== void 0) {
|
|
134
|
+
result.push(graph.nodes[ci]);
|
|
135
|
+
collect(childId);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
collect(nodeId);
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
function getRoots(graph) {
|
|
143
|
+
const idx = getIndex(graph);
|
|
144
|
+
return idx.childNodes.get(null)?.map((id) => graph.nodes[idx.nodeById.get(id)]).filter(Boolean) ?? [];
|
|
145
|
+
}
|
|
146
|
+
/** Whether a node has children (is a compound/group node). */
|
|
147
|
+
function isCompound(graph, nodeId) {
|
|
148
|
+
return (getIndex(graph).childNodes.get(nodeId) ?? []).length > 0;
|
|
149
|
+
}
|
|
150
|
+
/** Whether a node has no children (is a leaf/atomic node). */
|
|
151
|
+
function isLeaf(graph, nodeId) {
|
|
152
|
+
return !isCompound(graph, nodeId);
|
|
153
|
+
}
|
|
154
|
+
/** Depth of a node in the hierarchy (root = 0). */
|
|
155
|
+
function getDepth(graph, nodeId) {
|
|
156
|
+
const idx = getIndex(graph);
|
|
157
|
+
let d = 0;
|
|
158
|
+
let ni = idx.nodeById.get(nodeId);
|
|
159
|
+
if (ni === void 0) return -1;
|
|
160
|
+
let current = graph.nodes[ni];
|
|
161
|
+
while (current.parentId !== null) {
|
|
162
|
+
d++;
|
|
163
|
+
const pi = idx.nodeById.get(current.parentId);
|
|
164
|
+
if (pi === void 0) break;
|
|
165
|
+
current = graph.nodes[pi];
|
|
166
|
+
}
|
|
167
|
+
return d;
|
|
168
|
+
}
|
|
169
|
+
/** Sibling nodes (same parentId, excluding the node itself). */
|
|
170
|
+
function getSiblings(graph, nodeId) {
|
|
171
|
+
const idx = getIndex(graph);
|
|
172
|
+
const ni = idx.nodeById.get(nodeId);
|
|
173
|
+
if (ni === void 0) return [];
|
|
174
|
+
const node = graph.nodes[ni];
|
|
175
|
+
return (idx.childNodes.get(node.parentId) ?? []).filter((id) => id !== nodeId).map((id) => graph.nodes[idx.nodeById.get(id)]).filter(Boolean);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Least Common Ancestor — deepest proper ancestor of all given nodes.
|
|
179
|
+
* A proper ancestor excludes the input nodes themselves.
|
|
180
|
+
*/
|
|
181
|
+
function getLCA(graph, ...nodeIds) {
|
|
182
|
+
if (nodeIds.length === 0) return void 0;
|
|
183
|
+
const idx = getIndex(graph);
|
|
184
|
+
const getAncestorChain = (id) => {
|
|
185
|
+
const result = [id];
|
|
186
|
+
let ni$1 = idx.nodeById.get(id);
|
|
187
|
+
if (ni$1 === void 0) return result;
|
|
188
|
+
let current = graph.nodes[ni$1];
|
|
189
|
+
while (current.parentId !== null) {
|
|
190
|
+
result.push(current.parentId);
|
|
191
|
+
const pi = idx.nodeById.get(current.parentId);
|
|
192
|
+
if (pi === void 0) break;
|
|
193
|
+
current = graph.nodes[pi];
|
|
194
|
+
}
|
|
195
|
+
return result;
|
|
196
|
+
};
|
|
197
|
+
let common = getAncestorChain(nodeIds[0]);
|
|
198
|
+
for (let i = 1; i < nodeIds.length; i++) {
|
|
199
|
+
const set = new Set(getAncestorChain(nodeIds[i]));
|
|
200
|
+
common = common.filter((id) => set.has(id));
|
|
201
|
+
}
|
|
202
|
+
const inputSet = new Set(nodeIds);
|
|
203
|
+
common = common.filter((id) => !inputSet.has(id));
|
|
204
|
+
if (common.length === 0) return void 0;
|
|
205
|
+
const lcaId = common[0];
|
|
206
|
+
const ni = idx.nodeById.get(lcaId);
|
|
207
|
+
return ni !== void 0 ? graph.nodes[ni] : void 0;
|
|
208
|
+
}
|
|
209
|
+
/** Nodes with no incoming edges (inDegree 0). */
|
|
210
|
+
function getSources(graph) {
|
|
211
|
+
const idx = getIndex(graph);
|
|
212
|
+
return graph.nodes.filter((n) => (idx.inEdges.get(n.id)?.length ?? 0) === 0);
|
|
213
|
+
}
|
|
214
|
+
/** Nodes with no outgoing edges (outDegree 0). */
|
|
215
|
+
function getSinks(graph) {
|
|
216
|
+
const idx = getIndex(graph);
|
|
217
|
+
return graph.nodes.filter((n) => (idx.outEdges.get(n.id)?.length ?? 0) === 0);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
//#endregion
|
|
221
|
+
export { getAncestors, getChildren, getDegree, getDepth, getDescendants, getEdgeBetween, getEdgesOf, getInDegree, getInEdges, getLCA, getNeighbors, getOutDegree, getOutEdges, getParent, getPredecessors, getRoots, getSiblings, getSinks, getSources, getSuccessors, isCompound, isLeaf };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas.d.ts
|
|
4
|
+
declare const NodeSchema: z.ZodObject<{
|
|
5
|
+
type: z.ZodLiteral<"node">;
|
|
6
|
+
id: z.ZodString;
|
|
7
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
8
|
+
initialNodeId: z.ZodNullable<z.ZodString>;
|
|
9
|
+
label: z.ZodString;
|
|
10
|
+
data: z.ZodAny;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
declare const EdgeSchema: z.ZodObject<{
|
|
13
|
+
type: z.ZodLiteral<"edge">;
|
|
14
|
+
id: z.ZodString;
|
|
15
|
+
sourceId: z.ZodString;
|
|
16
|
+
targetId: z.ZodString;
|
|
17
|
+
label: z.ZodString;
|
|
18
|
+
data: z.ZodAny;
|
|
19
|
+
}, z.core.$strip>;
|
|
20
|
+
declare const GraphSchema: z.ZodObject<{
|
|
21
|
+
id: z.ZodString;
|
|
22
|
+
type: z.ZodEnum<{
|
|
23
|
+
directed: "directed";
|
|
24
|
+
undirected: "undirected";
|
|
25
|
+
}>;
|
|
26
|
+
initialNodeId: z.ZodNullable<z.ZodString>;
|
|
27
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
28
|
+
type: z.ZodLiteral<"node">;
|
|
29
|
+
id: z.ZodString;
|
|
30
|
+
parentId: z.ZodNullable<z.ZodString>;
|
|
31
|
+
initialNodeId: z.ZodNullable<z.ZodString>;
|
|
32
|
+
label: z.ZodString;
|
|
33
|
+
data: z.ZodAny;
|
|
34
|
+
}, z.core.$strip>>;
|
|
35
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
36
|
+
type: z.ZodLiteral<"edge">;
|
|
37
|
+
id: z.ZodString;
|
|
38
|
+
sourceId: z.ZodString;
|
|
39
|
+
targetId: z.ZodString;
|
|
40
|
+
label: z.ZodString;
|
|
41
|
+
data: z.ZodAny;
|
|
42
|
+
}, z.core.$strip>>;
|
|
43
|
+
data: z.ZodAny;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { EdgeSchema, GraphSchema, NodeSchema };
|
package/dist/schemas.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as z from "zod";
|
|
2
|
+
|
|
3
|
+
//#region src/schemas.ts
|
|
4
|
+
const NodeSchema = z.object({
|
|
5
|
+
type: z.literal("node"),
|
|
6
|
+
id: z.string(),
|
|
7
|
+
parentId: z.string().nullable(),
|
|
8
|
+
initialNodeId: z.string().nullable(),
|
|
9
|
+
label: z.string(),
|
|
10
|
+
data: z.any()
|
|
11
|
+
});
|
|
12
|
+
const EdgeSchema = z.object({
|
|
13
|
+
type: z.literal("edge"),
|
|
14
|
+
id: z.string(),
|
|
15
|
+
sourceId: z.string(),
|
|
16
|
+
targetId: z.string(),
|
|
17
|
+
label: z.string(),
|
|
18
|
+
data: z.any()
|
|
19
|
+
});
|
|
20
|
+
const GraphSchema = z.object({
|
|
21
|
+
id: z.string(),
|
|
22
|
+
type: z.enum(["directed", "undirected"]),
|
|
23
|
+
initialNodeId: z.string().nullable(),
|
|
24
|
+
nodes: z.array(NodeSchema),
|
|
25
|
+
edges: z.array(EdgeSchema),
|
|
26
|
+
data: z.any()
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { EdgeSchema, GraphSchema, NodeSchema };
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
interface EntityRect {
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
}
|
|
8
|
+
interface GraphConfig<TNodeData = any, TEdgeData = any, TGraphData = any> {
|
|
9
|
+
id?: string;
|
|
10
|
+
type?: 'directed' | 'undirected';
|
|
11
|
+
initialNodeId?: string;
|
|
12
|
+
nodes?: NodeConfig<TNodeData>[];
|
|
13
|
+
edges?: EdgeConfig<TEdgeData>[];
|
|
14
|
+
data?: TGraphData;
|
|
15
|
+
direction?: 'up' | 'down' | 'left' | 'right';
|
|
16
|
+
style?: Record<string, string | number>;
|
|
17
|
+
}
|
|
18
|
+
interface NodeConfig<TNodeData = any> {
|
|
19
|
+
id: string;
|
|
20
|
+
parentId?: string | null;
|
|
21
|
+
initialNodeId?: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
data?: TNodeData;
|
|
24
|
+
x?: number;
|
|
25
|
+
y?: number;
|
|
26
|
+
width?: number;
|
|
27
|
+
height?: number;
|
|
28
|
+
shape?: string;
|
|
29
|
+
color?: string;
|
|
30
|
+
style?: Record<string, string | number>;
|
|
31
|
+
}
|
|
32
|
+
interface EdgeConfig<TEdgeData = any> {
|
|
33
|
+
/**
|
|
34
|
+
* The id of the edge.
|
|
35
|
+
*/
|
|
36
|
+
id: string;
|
|
37
|
+
/**
|
|
38
|
+
* The id of the source node.
|
|
39
|
+
*/
|
|
40
|
+
sourceId: string;
|
|
41
|
+
/**
|
|
42
|
+
* The id of the target node.
|
|
43
|
+
*/
|
|
44
|
+
targetId: string;
|
|
45
|
+
/**
|
|
46
|
+
* The label of the edge.
|
|
47
|
+
*/
|
|
48
|
+
label?: string;
|
|
49
|
+
data?: TEdgeData;
|
|
50
|
+
x?: number;
|
|
51
|
+
y?: number;
|
|
52
|
+
width?: number;
|
|
53
|
+
height?: number;
|
|
54
|
+
color?: string;
|
|
55
|
+
style?: Record<string, string | number>;
|
|
56
|
+
}
|
|
57
|
+
interface Graph<TNodeData = any, TEdgeData = any, TGraphData = any> {
|
|
58
|
+
id: string;
|
|
59
|
+
type: 'directed' | 'undirected';
|
|
60
|
+
initialNodeId: string | null;
|
|
61
|
+
nodes: GraphNode<TNodeData>[];
|
|
62
|
+
edges: GraphEdge<TEdgeData>[];
|
|
63
|
+
data: TGraphData;
|
|
64
|
+
direction?: 'up' | 'down' | 'left' | 'right';
|
|
65
|
+
style?: Record<string, string | number>;
|
|
66
|
+
}
|
|
67
|
+
interface GraphNode<TNodeData = any> {
|
|
68
|
+
type: 'node';
|
|
69
|
+
id: string;
|
|
70
|
+
parentId: string | null;
|
|
71
|
+
initialNodeId: string | null;
|
|
72
|
+
label: string;
|
|
73
|
+
data: TNodeData;
|
|
74
|
+
x?: number;
|
|
75
|
+
y?: number;
|
|
76
|
+
width?: number;
|
|
77
|
+
height?: number;
|
|
78
|
+
shape?: string;
|
|
79
|
+
color?: string;
|
|
80
|
+
style?: Record<string, string | number>;
|
|
81
|
+
}
|
|
82
|
+
interface GraphEdge<TEdgeData = any> {
|
|
83
|
+
type: 'edge';
|
|
84
|
+
id: string;
|
|
85
|
+
sourceId: string;
|
|
86
|
+
targetId: string;
|
|
87
|
+
label: string;
|
|
88
|
+
data: TEdgeData;
|
|
89
|
+
x?: number;
|
|
90
|
+
y?: number;
|
|
91
|
+
width?: number;
|
|
92
|
+
height?: number;
|
|
93
|
+
color?: string;
|
|
94
|
+
style?: Record<string, string | number>;
|
|
95
|
+
}
|
|
96
|
+
interface VisualNode<TNodeData = any> extends Omit<GraphNode<TNodeData>, keyof EntityRect>, EntityRect {
|
|
97
|
+
shape: string;
|
|
98
|
+
}
|
|
99
|
+
interface VisualEdge<TEdgeData = any> extends Omit<GraphEdge<TEdgeData>, keyof EntityRect>, EntityRect {}
|
|
100
|
+
interface VisualGraph<TNodeData = any, TEdgeData = any, TGraphData = any> extends Omit<Graph<TNodeData, TEdgeData, TGraphData>, 'nodes' | 'edges'> {
|
|
101
|
+
nodes: VisualNode<TNodeData>[];
|
|
102
|
+
edges: VisualEdge<TEdgeData>[];
|
|
103
|
+
direction: 'up' | 'down' | 'left' | 'right';
|
|
104
|
+
}
|
|
105
|
+
interface VisualGraphConfig<TNodeData = any, TEdgeData = any, TGraphData = any> extends GraphConfig<TNodeData, TEdgeData, TGraphData> {
|
|
106
|
+
direction?: 'up' | 'down' | 'left' | 'right';
|
|
107
|
+
}
|
|
108
|
+
interface DeleteNodeOptions {
|
|
109
|
+
reparent?: boolean;
|
|
110
|
+
}
|
|
111
|
+
interface EntitiesConfig<TNodeData = any, TEdgeData = any> {
|
|
112
|
+
nodes?: NodeConfig<TNodeData>[];
|
|
113
|
+
edges?: EdgeConfig<TEdgeData>[];
|
|
114
|
+
}
|
|
115
|
+
interface EntitiesUpdate<TNodeData = any, TEdgeData = any> {
|
|
116
|
+
nodes?: (Partial<Omit<NodeConfig<TNodeData>, 'id'>> & {
|
|
117
|
+
id: string;
|
|
118
|
+
})[];
|
|
119
|
+
edges?: (Partial<Omit<EdgeConfig<TEdgeData>, 'id'>> & {
|
|
120
|
+
id: string;
|
|
121
|
+
})[];
|
|
122
|
+
}
|
|
123
|
+
interface GraphStep<TNodeData = any, TEdgeData = any> {
|
|
124
|
+
/** Edge traversed to reach this node */
|
|
125
|
+
edge: GraphEdge<TEdgeData>;
|
|
126
|
+
/** Node reached after traversing the edge */
|
|
127
|
+
node: GraphNode<TNodeData>;
|
|
128
|
+
}
|
|
129
|
+
interface GraphPath<TNodeData = any, TEdgeData = any> {
|
|
130
|
+
/** The source node where this path begins. */
|
|
131
|
+
source: GraphNode<TNodeData>;
|
|
132
|
+
/** Ordered steps from source to target.
|
|
133
|
+
* `path.steps.at(-1)?.node` is the final/target node.
|
|
134
|
+
* Empty steps = source-only path. */
|
|
135
|
+
steps: GraphStep<TNodeData, TEdgeData>[];
|
|
136
|
+
}
|
|
137
|
+
interface PathOptions<TEdgeData = any> {
|
|
138
|
+
/** Source node ID. Default: graph.initialNodeId, else sole inDegree-0 node */
|
|
139
|
+
from?: string;
|
|
140
|
+
/** Target node ID. If omitted → paths to all reachable nodes */
|
|
141
|
+
to?: string;
|
|
142
|
+
/** Edge weight function. Default: every edge = 1. */
|
|
143
|
+
getWeight?: (edge: GraphEdge<TEdgeData>) => number;
|
|
144
|
+
}
|
|
145
|
+
interface SinglePathOptions<TEdgeData = any> {
|
|
146
|
+
/** Source node ID. Default: graph.initialNodeId, else sole inDegree-0 node */
|
|
147
|
+
from?: string;
|
|
148
|
+
/** Target node ID. Required for single-path queries. */
|
|
149
|
+
to: string;
|
|
150
|
+
/** Edge weight function. Default: every edge = 1. */
|
|
151
|
+
getWeight?: (edge: GraphEdge<TEdgeData>) => number;
|
|
152
|
+
}
|
|
153
|
+
interface TraversalOptions {
|
|
154
|
+
/** Source node ID. Default: graph.initialNodeId, else sole inDegree-0 node */
|
|
155
|
+
from?: string;
|
|
156
|
+
}
|
|
157
|
+
interface MSTOptions<TEdgeData = any> {
|
|
158
|
+
/** Algorithm to use. Default: 'prim'. */
|
|
159
|
+
algorithm?: 'prim' | 'kruskal';
|
|
160
|
+
/** Edge weight function. Default: every edge = 1. */
|
|
161
|
+
getWeight?: (edge: GraphEdge<TEdgeData>) => number;
|
|
162
|
+
}
|
|
163
|
+
interface AllPairsShortestPathsOptions<TEdgeData = any> {
|
|
164
|
+
/** Algorithm to use. Default: 'dijkstra'. */
|
|
165
|
+
algorithm?: 'floyd-warshall' | 'dijkstra';
|
|
166
|
+
/** Edge weight function. Default: every edge = 1. */
|
|
167
|
+
getWeight?: (edge: GraphEdge<TEdgeData>) => number;
|
|
168
|
+
}
|
|
169
|
+
interface NodeChange<TNodeData = any> {
|
|
170
|
+
id: string;
|
|
171
|
+
old: Partial<GraphNode<TNodeData>>;
|
|
172
|
+
new: Partial<GraphNode<TNodeData>>;
|
|
173
|
+
}
|
|
174
|
+
interface EdgeChange<TEdgeData = any> {
|
|
175
|
+
id: string;
|
|
176
|
+
old: Partial<GraphEdge<TEdgeData>>;
|
|
177
|
+
new: Partial<GraphEdge<TEdgeData>>;
|
|
178
|
+
}
|
|
179
|
+
interface GraphDiff<TNodeData = any, TEdgeData = any> {
|
|
180
|
+
nodes: {
|
|
181
|
+
added: NodeConfig<TNodeData>[];
|
|
182
|
+
removed: NodeConfig<TNodeData>[];
|
|
183
|
+
updated: NodeChange<TNodeData>[];
|
|
184
|
+
};
|
|
185
|
+
edges: {
|
|
186
|
+
added: EdgeConfig<TEdgeData>[];
|
|
187
|
+
removed: EdgeConfig<TEdgeData>[];
|
|
188
|
+
updated: EdgeChange<TEdgeData>[];
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
type GraphPatch<TNodeData = any, TEdgeData = any> = {
|
|
192
|
+
op: 'addNode';
|
|
193
|
+
node: NodeConfig<TNodeData>;
|
|
194
|
+
description?: string;
|
|
195
|
+
} | {
|
|
196
|
+
op: 'updateNode';
|
|
197
|
+
id: string;
|
|
198
|
+
data: Partial<Omit<NodeConfig<TNodeData>, 'id'>>;
|
|
199
|
+
description?: string;
|
|
200
|
+
} | {
|
|
201
|
+
op: 'deleteNode';
|
|
202
|
+
id: string;
|
|
203
|
+
description?: string;
|
|
204
|
+
} | {
|
|
205
|
+
op: 'addEdge';
|
|
206
|
+
edge: EdgeConfig<TEdgeData>;
|
|
207
|
+
description?: string;
|
|
208
|
+
} | {
|
|
209
|
+
op: 'updateEdge';
|
|
210
|
+
id: string;
|
|
211
|
+
data: Partial<Omit<EdgeConfig<TEdgeData>, 'id'>>;
|
|
212
|
+
description?: string;
|
|
213
|
+
} | {
|
|
214
|
+
op: 'deleteEdge';
|
|
215
|
+
id: string;
|
|
216
|
+
description?: string;
|
|
217
|
+
};
|
|
218
|
+
//#endregion
|
|
219
|
+
export { VisualGraph as C, VisualEdge as S, VisualNode as T, NodeChange as _, EntitiesConfig as a, SinglePathOptions as b, Graph as c, GraphEdge as d, GraphNode as f, MSTOptions as g, GraphStep as h, EdgeConfig as i, GraphConfig as l, GraphPath as m, DeleteNodeOptions as n, EntitiesUpdate as o, GraphPatch as p, EdgeChange as r, EntityRect as s, AllPairsShortestPathsOptions as t, GraphDiff as u, NodeConfig as v, VisualGraphConfig as w, TraversalOptions as x, PathOptions as y };
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@statelyai/graph",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "A TypeScript-first graph library with plain JSON-serializable objects",
|
|
6
|
+
"author": "David Khourshid <david@stately.ai>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/statelyai/graph#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/statelyai/graph.git"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/statelyai/graph/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"graph",
|
|
18
|
+
"directed",
|
|
19
|
+
"undirected",
|
|
20
|
+
"dag",
|
|
21
|
+
"algorithms",
|
|
22
|
+
"typescript"
|
|
23
|
+
],
|
|
24
|
+
"exports": {
|
|
25
|
+
".": "./dist/index.mjs",
|
|
26
|
+
"./algorithms": "./dist/algorithms.mjs",
|
|
27
|
+
"./formats/adjacency-list": "./dist/formats/adjacency-list.mjs",
|
|
28
|
+
"./formats/dot": "./dist/formats/dot.mjs",
|
|
29
|
+
"./formats/edge-list": "./dist/formats/edge-list.mjs",
|
|
30
|
+
"./formats/graphml": "./dist/formats/graphml.mjs",
|
|
31
|
+
"./queries": "./dist/queries.mjs",
|
|
32
|
+
"./schemas": "./dist/schemas.mjs",
|
|
33
|
+
"./package.json": "./package.json"
|
|
34
|
+
},
|
|
35
|
+
"main": "./dist/index.mjs",
|
|
36
|
+
"module": "./dist/index.mjs",
|
|
37
|
+
"types": "./dist/index.d.mts",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"schemas"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsdown",
|
|
44
|
+
"dev": "tsdown --watch",
|
|
45
|
+
"test": "vitest",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"generate-schema": "tsx scripts/generate-json-schema.ts",
|
|
48
|
+
"changeset": "changeset",
|
|
49
|
+
"version": "changeset version",
|
|
50
|
+
"release": "pnpm run build && changeset publish",
|
|
51
|
+
"prepublishOnly": "pnpm run build"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@changesets/changelog-github": "^0.5.2",
|
|
55
|
+
"@changesets/cli": "^2.29.8",
|
|
56
|
+
"@types/node": "^25.0.3",
|
|
57
|
+
"bumpp": "^10.3.2",
|
|
58
|
+
"fast-xml-parser": "^5.3.4",
|
|
59
|
+
"tsdown": "^0.18.1",
|
|
60
|
+
"tsx": "^4.21.0",
|
|
61
|
+
"typescript": "^5.9.3",
|
|
62
|
+
"vitest": "^4.0.16",
|
|
63
|
+
"zod": "^4.3.6"
|
|
64
|
+
},
|
|
65
|
+
"peerDependencies": {
|
|
66
|
+
"fast-xml-parser": "^5.0.0",
|
|
67
|
+
"zod": "^4.0.0"
|
|
68
|
+
},
|
|
69
|
+
"peerDependenciesMeta": {
|
|
70
|
+
"fast-xml-parser": {
|
|
71
|
+
"optional": true
|
|
72
|
+
},
|
|
73
|
+
"zod": {
|
|
74
|
+
"optional": true
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"properties": {
|
|
5
|
+
"type": {
|
|
6
|
+
"type": "string",
|
|
7
|
+
"const": "edge"
|
|
8
|
+
},
|
|
9
|
+
"id": {
|
|
10
|
+
"type": "string"
|
|
11
|
+
},
|
|
12
|
+
"sourceId": {
|
|
13
|
+
"type": "string"
|
|
14
|
+
},
|
|
15
|
+
"targetId": {
|
|
16
|
+
"type": "string"
|
|
17
|
+
},
|
|
18
|
+
"label": {
|
|
19
|
+
"type": "string"
|
|
20
|
+
},
|
|
21
|
+
"data": {}
|
|
22
|
+
},
|
|
23
|
+
"required": [
|
|
24
|
+
"type",
|
|
25
|
+
"id",
|
|
26
|
+
"sourceId",
|
|
27
|
+
"targetId",
|
|
28
|
+
"label",
|
|
29
|
+
"data"
|
|
30
|
+
],
|
|
31
|
+
"additionalProperties": false
|
|
32
|
+
}
|