@zvk/graphs 0.1.1 → 0.1.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @zvk/graphs Changelog
2
2
 
3
+ ## [0.1.3](https://github.com/brandon-schabel/zvk/compare/graphs-v0.1.2...graphs-v0.1.3) (2026-06-20)
4
+
5
+
6
+ ### Features
7
+
8
+ * improve package release workflow and repo maintainability ([#22](https://github.com/brandon-schabel/zvk/issues/22)) ([a41cb66](https://github.com/brandon-schabel/zvk/commit/a41cb66554496f241c5a8e30b29a76c8b8ca92b3))
9
+
10
+ ## [0.1.2](https://github.com/brandon-schabel/zvk/compare/graphs-v0.1.1...graphs-v0.1.2) (2026-06-19)
11
+
12
+
13
+ ### Features
14
+
15
+ * add theme presets and package improvements ([#19](https://github.com/brandon-schabel/zvk/issues/19)) ([867f955](https://github.com/brandon-schabel/zvk/commit/867f9556f7a60144cad4e747f2c032f2d5ede353))
16
+
3
17
  ## [0.1.1](https://github.com/brandon-schabel/zvk/compare/graphs-v0.1.0...graphs-v0.1.1) (2026-06-18)
4
18
 
5
19
 
package/README.md CHANGED
@@ -15,13 +15,22 @@ import "@zvk/graphs/styles.css";
15
15
  ```
16
16
 
17
17
  Public subpaths are `@zvk/graphs`, `@zvk/graphs/model`,
18
- `@zvk/graphs/diagnostics`, `@zvk/graphs/algorithms`, `@zvk/graphs/layout`,
19
- `@zvk/graphs/svg`, `@zvk/graphs/styles.css`, and
18
+ `@zvk/graphs/diagnostics`, `@zvk/graphs/algorithms`,
19
+ `@zvk/graphs/serialization`, `@zvk/graphs/layout`, `@zvk/graphs/svg`,
20
+ `@zvk/graphs/styles.css`, and
20
21
  `@zvk/graphs/package.json`.
21
22
 
22
23
  Do not import from `src`, `dist`, package internals, or private relative paths.
23
24
  Treat `packages/graphs/package.json` `exports` as the public API contract.
24
25
 
26
+ ## Package Docs And Examples
27
+
28
+ Package-local guides live in `packages/graphs/docs/README.md`. They cover
29
+ modeling, algorithms, diagnostics, serialization, deterministic layout, static
30
+ SVG rendering, accessibility, app composition boundaries, and anti-goals.
31
+ Runnable examples live in `packages/graphs/examples/` and must use only public
32
+ `@zvk/graphs` imports.
33
+
25
34
  ## Styles
26
35
 
27
36
  Import graph styles once from the public stylesheet:
@@ -43,6 +52,11 @@ and graph-specific `data-*` attributes. It may fall back to `--zvk-ui-*` tokens
43
52
  when present, but package source must not import `@zvk/ui` JavaScript or
44
53
  component internals for styling.
45
54
 
55
+ Graph typography uses `--zvk-graphs-font-primary`, `--zvk-graphs-font-secondary`,
56
+ and `--zvk-graphs-font-tertiary`. These inherit `--zvk-ui-font-family-primary`,
57
+ `--zvk-ui-font-family-secondary`, and `--zvk-ui-font-family-tertiary` when UI
58
+ styles are present.
59
+
46
60
  ## Accessibility And SSR
47
61
 
48
62
  - Require a graph title, node labels, and meaningful edge labels or derivable
@@ -57,6 +71,281 @@ component internals for styling.
57
71
  - Use deterministic IDs and layout output. Do not use random IDs, timestamps, or
58
72
  DOM measurement for default layout.
59
73
 
74
+ ## Fallback Details
75
+
76
+ `GraphFigure` renders structured fallback content by default. Node fallback
77
+ details include documented summary fields such as `summary`, `accessibility`,
78
+ `ariaDescription`, `kind`, `groupId`, `status`, `presentation`, structured
79
+ primitive `metadata`, and primitive string/number/boolean `data` values. Edge
80
+ fallback details include source and target labels, route kind, accessibility
81
+ text, status, summary, structured primitive metadata, and primitive edge data.
82
+ Arbitrary object data is not dumped into the DOM by default.
83
+
84
+ Use `fallbackMode="tree"` when a graph is a one-root tree and should expose a
85
+ nested fallback. Invalid or multi-root trees degrade to the list fallback. Use
86
+ `fallbackMode="none"` only when the host application renders equivalent graph
87
+ details elsewhere.
88
+
89
+ ## Static Metadata And Presentation
90
+
91
+ Nodes and edges can expose app-owned details through serializable metadata and
92
+ accessibility fields:
93
+
94
+ ```ts
95
+ const graph = {
96
+ title: "Deploy graph",
97
+ description: "Release approval flow.",
98
+ nodes: [
99
+ {
100
+ id: "gate",
101
+ label: "Deploy gate",
102
+ labelLines: ["Deploy", "gate"],
103
+ metadata: [
104
+ { key: "owner", label: "Owner", value: "Platform", visibility: "summary", tone: "info" },
105
+ { key: "risk", label: "Risk", value: "Medium", visibility: "detail", tone: "warning" }
106
+ ],
107
+ accessibility: {
108
+ label: "Deploy gate decision",
109
+ description: "Decision node for deployment approval."
110
+ },
111
+ presentation: {
112
+ shape: "diamond",
113
+ density: "compact",
114
+ tone: "warning",
115
+ badge: "Gate",
116
+ glyph: "?"
117
+ },
118
+ status: "warning",
119
+ position: { x: 0, y: 0 }
120
+ }
121
+ ],
122
+ edges: []
123
+ };
124
+ ```
125
+
126
+ The SVG renderer only displays metadata marked `visibility: "summary"` so
127
+ callers have to opt into compact visible details. Fallback content renders all
128
+ primitive metadata values. Use `renderNode` for advanced custom SVG output, but
129
+ prefer built-in `shape`, `badge`, `glyph`, `labelLines`, and metadata summaries
130
+ for common static graph details.
131
+
132
+ ## Static Groups
133
+
134
+ Graphs can define static groups and attach nodes through `groupId`:
135
+
136
+ ```ts
137
+ const graph = {
138
+ title: "Service map",
139
+ groups: [
140
+ {
141
+ id: "backend",
142
+ label: "Backend services",
143
+ summary: "Platform-owned services.",
144
+ tone: "info",
145
+ status: "active"
146
+ }
147
+ ],
148
+ nodes: [
149
+ { id: "api", label: "API", groupId: "backend", position: { x: 0, y: 0 } },
150
+ { id: "worker", label: "Worker", groupId: "backend", position: { x: 140, y: 0 } }
151
+ ],
152
+ edges: []
153
+ };
154
+ ```
155
+
156
+ Static groups render as non-interactive SVG containers beneath edges and nodes.
157
+ When a group has explicit `position` and `size`, those bounds are used;
158
+ otherwise `deriveGraphGroupBounds` derives padded bounds from positioned member
159
+ nodes. Group fallback details include summaries, metadata, status, tone, and
160
+ member labels.
161
+
162
+ Groups are visual and fallback organization only. They do not provide compound
163
+ layout, nested group layout, port constraints, edge routing around group
164
+ boundaries, collapse/expand behavior, or editor workflows.
165
+
166
+ ## Edge Labels And Routes
167
+
168
+ Static SVG edges include accessible titles and descriptions derived from
169
+ `accessibility.label`, `ariaLabel`, `label`, source label, target label, status,
170
+ `accessibility.description`, and summary where available. Visible edge labels
171
+ render at deterministic label anchors and include a tokenized background
172
+ rectangle for contrast. Use `deriveGraphEdgeLabelAnchor` when applications need
173
+ the same estimated label bounds and anchor metadata before rendering.
174
+ Use `getGraphEdgeLabelOverlapDiagnostics` on positioned graphs, or set
175
+ `warnEdgeLabelOverlaps` on layout helpers, when applications need opt-in
176
+ warnings for estimated label bounds that overlap. This diagnostic is a
177
+ deterministic risk signal; it does not measure rendered text, relocate labels,
178
+ or solve collisions.
179
+
180
+ The layout helpers expose deterministic straight, curved, elbow, self-loop, and
181
+ parallel-offset route primitives. These are simple SVG path primitives, not
182
+ full orthogonal routing, port routing, obstacle avoidance, edge bundling, or
183
+ Graphviz/ELK-style label placement.
184
+
185
+ Use `edgeRouteKind` for a layout-wide default route kind and `routeByEdgeId`
186
+ when a specific edge needs a different route:
187
+
188
+ ```ts
189
+ const layout = layoutManualGraph(graph, {
190
+ edgeRouteKind: "straight",
191
+ routeByEdgeId: {
192
+ "audit-edge": "curve",
193
+ "fallback-edge": "elbow"
194
+ }
195
+ });
196
+ ```
197
+
198
+ Per-edge route hints take precedence over the layout default. Self-loop edges
199
+ still render with the `self-loop` route kind so loops remain recognizable.
200
+
201
+ Label anchors are deterministic estimates based on the label text length and
202
+ route label position. They do not use DOM measurement, `getBBox`, label
203
+ collision solving, obstacle avoidance, or route-aware label placement.
204
+
205
+ ## Layout Diagnostics And Bounds
206
+
207
+ Manual, tree, and narrow DAG layouts return diagnostics rather than throwing for
208
+ expected graph-shape limits. Layout options can warn about large graphs, dense
209
+ graphs, missing explicit node sizes, duplicate manual positions, self-loops, and
210
+ parallel edges. `estimateGraphRenderCost` returns deterministic counts for
211
+ nodes, edges, groups, fallback rows, visible labels, summary metadata, route
212
+ points, complex routes, and a rough SVG element estimate. Use threshold options
213
+ such as `warnFallbackRowsAt`, `warnVisibleLabelsAt`, `warnRoutePointsAt`, and
214
+ `warnMetadataSummariesAt` to surface opt-in performance warnings when a static
215
+ graph should be filtered, collapsed, summarized, or delegated to a specialized
216
+ graph engine.
217
+
218
+ DAG layout supports `rankStrategy: "longest-path"` and `"source-depth"` for
219
+ small acyclic graphs. Apps can also provide
220
+ `rankByNodeId` and `orderByNodeId` hints when a workflow or dependency view has
221
+ known phases or stable author-defined ordering:
222
+
223
+ ```ts
224
+ import { layoutDagGraph } from "@zvk/graphs";
225
+
226
+ const layout = layoutDagGraph(workflowGraph, {
227
+ direction: "left-right",
228
+ rankByNodeId: {
229
+ change: 0,
230
+ preflight: 1,
231
+ review: 1,
232
+ release: 2
233
+ },
234
+ orderByNodeId: {
235
+ review: 0,
236
+ preflight: 1
237
+ }
238
+ });
239
+ ```
240
+
241
+ Rank hints override computed DAG ranks for matching node IDs. Order hints sort
242
+ nodes within their resolved rank; missing order hints fall back to graph input
243
+ order. Unknown hint keys are ignored. These hints are deterministic layout
244
+ inputs, not a crossing-minimization engine, compound layout system, or
245
+ Graphviz/ELK replacement.
246
+
247
+ Use `validateGraph(graph, { auditAccessibility: true })` for opt-in
248
+ accessibility audit info entries about missing graph descriptions, node
249
+ descriptions, and edge descriptions. These diagnostics are guidance for complex
250
+ static diagrams; they do not turn ordinary validation failures into throws.
251
+
252
+ Use `getGraphBounds` as a pure static helper for `viewBox` sizing with padding
253
+ and minimum dimensions. It does not own pan/zoom state, fit-to-screen behavior,
254
+ viewport persistence, or responsive layout state.
255
+
256
+ ## Pure Graph Transforms
257
+
258
+ Use algorithm transform helpers when an application needs focused graph views
259
+ without moving search, filters, routing, or detail panels into the package:
260
+
261
+ ```ts
262
+ import { getGraphNeighborhood, mapGraphNodes, pickGraphSubgraph } from "@zvk/graphs";
263
+
264
+ const neighborhood = getGraphNeighborhood(graph, {
265
+ rootId: "model",
266
+ direction: "outgoing",
267
+ maxDepth: 2
268
+ });
269
+
270
+ const selectedPath = pickGraphSubgraph(graph, {
271
+ nodeIds: ["model", "diagnostics", "layout"]
272
+ });
273
+
274
+ const highlighted = mapGraphNodes(neighborhood, (node) => ({
275
+ ...node,
276
+ status: node.id === "model" ? "success" : node.status
277
+ }));
278
+ ```
279
+
280
+ `pickGraphSubgraph` preserves node and edge input order while pruning edges to
281
+ selected nodes by default. `includeConnectedEdges: false` returns node-only
282
+ projections, and `includeDanglingEdges: true` keeps edges touching selected
283
+ nodes for app-owned inspection flows. `getGraphNeighborhood` returns a
284
+ depth-limited incoming, outgoing, or bidirectional projection. `mapGraphNodes`
285
+ and `mapGraphEdges` preserve graph metadata while letting applications annotate
286
+ nodes or edges for a derived view.
287
+
288
+ ## Edge And Adjacency Interop
289
+
290
+ Use edge-list and adjacency-list helpers when an app imports relationship data
291
+ from a database query, config file, or debug fixture and needs a graph model
292
+ without adopting a graph language parser:
293
+
294
+ ```ts
295
+ import { graphFromAdjacencyList, graphFromEdgeList, graphToAdjacencyList } from "@zvk/graphs";
296
+
297
+ const importedGraph = graphFromEdgeList(
298
+ [
299
+ { id: "api-db", source: "api", target: "db", label: "queries" },
300
+ { source: "api", target: "cache", label: "reads" }
301
+ ],
302
+ {
303
+ title: "Service dependencies",
304
+ getNodeLabel: (nodeId) => nodeId.toUpperCase()
305
+ }
306
+ );
307
+
308
+ const adjacencyList = graphToAdjacencyList(importedGraph);
309
+ const debugGraph = graphFromAdjacencyList(adjacencyList, {
310
+ title: "Debug dependency graph"
311
+ });
312
+ ```
313
+
314
+ `graphFromEdgeList` preserves explicit edge fields and appends missing nodes in
315
+ first-seen edge order. Missing edge IDs are generated deterministically from the
316
+ source and target IDs, with numeric suffixes for repeated pairs. Provide stable
317
+ edge IDs when IDs are persisted, linked, or shown to users.
318
+
319
+ `graphToAdjacencyList` returns ordered `{ source, targets }` items in graph node
320
+ order, including isolated nodes. This format is intentionally structural and
321
+ lossy: it preserves source IDs, ordered target IDs, and duplicate targets, but
322
+ not edge labels, metadata, data, kind, status, or IDs.
323
+
324
+ ## Stable JSON Serialization
325
+
326
+ Use serialization helpers when an app needs deterministic graph JSON for
327
+ storage, debug exports, snapshots, or support bundles:
328
+
329
+ ```ts
330
+ import { normalizeGraphForJson, stringifyGraphForJson } from "@zvk/graphs/serialization";
331
+
332
+ const portableGraph = normalizeGraphForJson(graph);
333
+ const stableJson = stringifyGraphForJson(graph, {
334
+ sortItems: true,
335
+ space: 2
336
+ });
337
+ ```
338
+
339
+ `normalizeGraphForJson` removes unsupported object properties such as
340
+ `undefined`, functions, symbols, and bigints. Object keys are sorted for stable
341
+ diffs. Graph groups, nodes, and edges preserve input order by default; set
342
+ `sortItems: true` to sort those arrays by `id` for persisted output.
343
+
344
+ `stringifyGraphForJson` serializes the normalized graph. It is not a runtime
345
+ validator and does not parse or emit DOT, Mermaid, Graphviz, or layout-engine
346
+ formats. Use `validateGraph` and `validateGraphLayout` for imported data that
347
+ must be checked before rendering.
348
+
60
349
  ## Package Boundaries
61
350
 
62
351
  `@zvk/graphs` owns:
@@ -64,8 +353,9 @@ component internals for styling.
64
353
  - serializable graph model types;
65
354
  - graph diagnostics and validation reports;
66
355
  - pure graph algorithms such as adjacency, degree, cycle, topological,
67
- reachability, component, and tree helpers;
68
- - deterministic manual, tree, and narrow DAG layout utilities;
356
+ reachability, component, tree, subgraph, neighborhood, and mapping helpers;
357
+ - deterministic manual, tree, narrow DAG, bounds, and static group-bound
358
+ utilities;
69
359
  - static React/SVG graph rendering;
70
360
  - graph CSS and token inheritance contracts.
71
361
 
@@ -74,6 +364,75 @@ domain entities, and any editor or viewport state. Use `@zvk/charts` for axes,
74
364
  scales, numeric series, legends, bars, lines, areas, scatterplots, sparklines,
75
365
  pie/donut charts, and other quantitative visualization.
76
366
 
367
+ App-owned detail panel composition should keep state in the application:
368
+
369
+ ```tsx
370
+ import { GraphFigure, layoutManualGraph } from "@zvk/graphs";
371
+ import "@zvk/graphs/styles.css";
372
+
373
+ const layout = layoutManualGraph(graph);
374
+ const selectedNode = layout.graph.nodes.find((node) => node.id === selectedNodeId);
375
+
376
+ return (
377
+ <>
378
+ <GraphFigure graph={layout.graph} selectedNodeIds={selectedNodeId ? [selectedNodeId] : []} />
379
+ <aside>{selectedNode ? selectedNode.label : "No node selected"}</aside>
380
+ </>
381
+ );
382
+ ```
383
+
384
+ This pattern is application composition. `@zvk/graphs` does not own product
385
+ detail fields, routes, filtering, search, keyboard selection, or client state.
386
+
387
+ ## Client Boundary Decision
388
+
389
+ There is no `@zvk/graphs/client` public subpath yet. Keep client behavior
390
+ app-owned until the static core needs shared helpers that cannot be expressed
391
+ with public model, layout, SVG, and CSS contracts.
392
+
393
+ A future client subpath must stay narrow: focusable nodes and edges, roving
394
+ focus or tab-order helpers, controlled selection helpers, keyboard shortcuts,
395
+ persistent inspector helpers, and live-region guidance. Product detail panels,
396
+ filters, search, routing, editing, drag-to-connect, pan/zoom, minimaps, and
397
+ viewport persistence remain application responsibilities.
398
+
399
+ ## CSS Contract
400
+
401
+ Graph styles use `.zvk-graphs*` classes, `data-zvk-graphs`, `data-node-id`,
402
+ `data-edge-id`, `data-kind`, `data-node-shape`, `data-edge-kind`,
403
+ `data-edge-label-anchor`, `data-edge-label-side`, `data-edge-route-kind`,
404
+ `data-density`, `data-tone`, `data-status`, and `data-selected` hooks. Treat
405
+ these as styling and diagnostics hooks, not a replacement for accessible labels
406
+ or public imports.
407
+
408
+ Important variables include:
409
+
410
+ - `--zvk-graphs-canvas-bg`
411
+ - `--zvk-graphs-group-bg`
412
+ - `--zvk-graphs-group-border`
413
+ - `--zvk-graphs-group-label-text`
414
+ - `--zvk-graphs-node-bg`
415
+ - `--zvk-graphs-node-border`
416
+ - `--zvk-graphs-node-text`
417
+ - `--zvk-graphs-node-badge-text`
418
+ - `--zvk-graphs-muted-text`
419
+ - `--zvk-graphs-edge-stroke`
420
+ - `--zvk-graphs-edge-label-bg`
421
+ - `--zvk-graphs-edge-label-border`
422
+ - `--zvk-graphs-selected-bg`
423
+ - `--zvk-graphs-selected-stroke`
424
+ - `--zvk-graphs-success`
425
+ - `--zvk-graphs-warning`
426
+ - `--zvk-graphs-destructive`
427
+ - `--zvk-graphs-info`
428
+ - `--zvk-graphs-font-primary`
429
+ - `--zvk-graphs-font-secondary`
430
+ - `--zvk-graphs-font-tertiary`
431
+
432
+ The default CSS adds non-color cues for several statuses with dash patterns,
433
+ stroke width changes, and fallback/status text. Host applications should still
434
+ verify contrast and forced-colors behavior in their own theme context.
435
+
77
436
  ## Anti-Goals
78
437
 
79
438
  - No runtime dependencies.
@@ -84,3 +443,20 @@ pie/donut charts, and other quantitative visualization.
84
443
  node rendering in the core package.
85
444
  - No unlabeled graph nodes, inaccessible edge relationships, color-only states,
86
445
  or browser-only behavior leaking into SSR-safe imports.
446
+
447
+ ## Source Policy Validation
448
+
449
+ `bun run --filter @zvk/graphs validate:source-policy` checks the static package
450
+ boundary. It fails on browser globals or forbidden graph/runtime dependency
451
+ imports in production graph source, nondeterministic time/random APIs, graph CSS
452
+ that escapes the token contract, and private `src` or `dist` graph imports in
453
+ the README, package docs, or examples. The package `preflight` runs this check
454
+ after export validation.
455
+
456
+ `bun run --filter @zvk/graphs verify:style-contract` checks the positive style
457
+ surface: graph layers, public `.zvk-graphs*` selectors, graph token definitions,
458
+ UI-token inheritance, state selectors, and forced-colors coverage.
459
+
460
+ ## Repo Skill
461
+
462
+ Use `.codex/skills/use-zvk-graphs/SKILL.md` when maintaining this package.
@@ -1,5 +1,5 @@
1
1
  import type { GraphDiagnostic } from "./diagnostics.js";
2
- import type { GraphEdge, GraphId, GraphModel, GraphNode } from "./model.js";
2
+ import type { GraphDirection, GraphEdge, GraphGroup, GraphId, GraphModel, GraphNode } from "./model.js";
3
3
  export interface GraphIndex {
4
4
  readonly nodeById: ReadonlyMap<GraphId, GraphNode>;
5
5
  readonly edgeById: ReadonlyMap<GraphId, GraphEdge>;
@@ -11,8 +11,71 @@ export interface GraphDegree {
11
11
  readonly out: number;
12
12
  readonly total: number;
13
13
  }
14
+ export type GraphAdjacencyList = readonly GraphAdjacencyListItem[];
15
+ export interface GraphAdjacencyListItem {
16
+ readonly source: GraphId;
17
+ readonly targets: readonly GraphId[];
18
+ }
19
+ export interface GraphEdgeListItem<TEdgeData = unknown, TEdgeKind extends string = string> extends Omit<GraphEdge<TEdgeData, TEdgeKind>, "id"> {
20
+ readonly id?: GraphId;
21
+ }
22
+ export interface GraphNodeLabelContext {
23
+ readonly nodeId: GraphId;
24
+ readonly index: number;
25
+ }
26
+ export interface GraphEdgeIdContext<TEdgeData = unknown, TEdgeKind extends string = string> {
27
+ readonly entry: GraphEdgeListItem<TEdgeData, TEdgeKind>;
28
+ readonly index: number;
29
+ readonly proposedId: GraphId;
30
+ }
31
+ export interface GraphFromEdgeListOptions<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string> {
32
+ readonly id?: GraphId;
33
+ readonly title: string;
34
+ readonly description?: string;
35
+ readonly direction?: GraphDirection;
36
+ readonly groups?: readonly GraphGroup[];
37
+ readonly nodes?: readonly GraphNode<TNodeData, TNodeKind>[];
38
+ readonly getNodeLabel?: (nodeId: GraphId, context: GraphNodeLabelContext) => string;
39
+ readonly getEdgeId?: (entry: GraphEdgeListItem<TEdgeData, TEdgeKind>, context: GraphEdgeIdContext<TEdgeData, TEdgeKind>) => GraphId;
40
+ }
41
+ export interface GraphFromAdjacencyListOptions<TNodeData = unknown, TNodeKind extends string = string> {
42
+ readonly id?: GraphId;
43
+ readonly title: string;
44
+ readonly description?: string;
45
+ readonly direction?: GraphDirection;
46
+ readonly groups?: readonly GraphGroup[];
47
+ readonly nodes?: readonly GraphNode<TNodeData, TNodeKind>[];
48
+ readonly getNodeLabel?: (nodeId: GraphId, context: GraphNodeLabelContext) => string;
49
+ }
50
+ export interface GraphSubgraphOptions {
51
+ readonly nodeIds: readonly GraphId[];
52
+ readonly includeConnectedEdges?: boolean;
53
+ readonly includeDanglingEdges?: boolean;
54
+ }
55
+ export type GraphNeighborhoodDirection = "outgoing" | "incoming" | "both";
56
+ export interface GraphNeighborhoodOptions {
57
+ readonly rootId: GraphId;
58
+ readonly direction?: GraphNeighborhoodDirection;
59
+ readonly maxDepth: number;
60
+ }
61
+ export interface GraphNodeMapperContext<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string> {
62
+ readonly graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>;
63
+ readonly index: number;
64
+ }
65
+ export interface GraphEdgeMapperContext<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string> {
66
+ readonly graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>;
67
+ readonly index: number;
68
+ }
14
69
  export declare function createGraphIndex(graph: GraphModel): GraphIndex;
15
70
  export declare function getGraphDegrees(graph: GraphModel): Record<string, GraphDegree>;
71
+ export declare function graphFromEdgeList<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string>(edgeList: readonly GraphEdgeListItem<TEdgeData, TEdgeKind>[], options: GraphFromEdgeListOptions<TNodeData, TEdgeData, TNodeKind, TEdgeKind>): GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>;
72
+ export declare function graphToEdgeList<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string>(graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>): readonly GraphEdge<TEdgeData, TEdgeKind>[];
73
+ export declare function graphToAdjacencyList(graph: GraphModel): GraphAdjacencyList;
74
+ export declare function graphFromAdjacencyList<TNodeData = unknown, TNodeKind extends string = string>(adjacencyList: GraphAdjacencyList, options: GraphFromAdjacencyListOptions<TNodeData, TNodeKind>): GraphModel<TNodeData, unknown, TNodeKind, string>;
75
+ export declare function pickGraphSubgraph<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string>(graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>, options: GraphSubgraphOptions): GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>;
76
+ export declare function getGraphNeighborhood<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string>(graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>, options: GraphNeighborhoodOptions): GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>;
77
+ export declare function mapGraphNodes<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string, TNextNodeData = TNodeData, TNextNodeKind extends string = TNodeKind>(graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>, mapper: (node: GraphNode<TNodeData, TNodeKind>, context: GraphNodeMapperContext<TNodeData, TEdgeData, TNodeKind, TEdgeKind>) => GraphNode<TNextNodeData, TNextNodeKind>): GraphModel<TNextNodeData, TEdgeData, TNextNodeKind, TEdgeKind>;
78
+ export declare function mapGraphEdges<TNodeData = unknown, TEdgeData = unknown, TNodeKind extends string = string, TEdgeKind extends string = string, TNextEdgeData = TEdgeData, TNextEdgeKind extends string = TEdgeKind>(graph: GraphModel<TNodeData, TEdgeData, TNodeKind, TEdgeKind>, mapper: (edge: GraphEdge<TEdgeData, TEdgeKind>, context: GraphEdgeMapperContext<TNodeData, TEdgeData, TNodeKind, TEdgeKind>) => GraphEdge<TNextEdgeData, TNextEdgeKind>): GraphModel<TNodeData, TNextEdgeData, TNodeKind, TNextEdgeKind>;
16
79
  export declare function detectGraphCycle(graph: GraphModel): readonly GraphId[] | null;
17
80
  export interface TopologicalSortResult {
18
81
  readonly nodeIds: readonly GraphId[];
@@ -20,6 +83,15 @@ export interface TopologicalSortResult {
20
83
  }
21
84
  export declare function topologicalSortGraph(graph: GraphModel): TopologicalSortResult;
22
85
  export declare function getReachableNodeIds(graph: GraphModel, startId: GraphId): readonly GraphId[];
86
+ export declare function getUnreachableNodeIds(graph: GraphModel, startId: GraphId): readonly GraphId[];
87
+ export declare function getIsolatedNodeIds(graph: GraphModel): readonly GraphId[];
88
+ export declare function getShortestPath(graph: GraphModel, sourceId: GraphId, targetId: GraphId): readonly GraphId[] | null;
89
+ export declare function getStronglyConnectedComponents(graph: GraphModel): readonly (readonly GraphId[])[];
90
+ export interface TransitiveReductionResult {
91
+ readonly edges: readonly GraphEdge[];
92
+ readonly diagnostics: readonly GraphDiagnostic[];
93
+ }
94
+ export declare function getTransitiveReductionEdges(graph: GraphModel): TransitiveReductionResult;
23
95
  export declare function getWeaklyConnectedComponents(graph: GraphModel): readonly (readonly GraphId[])[];
24
96
  export interface ValidateTreeGraphOptions {
25
97
  readonly rootId?: GraphId;