@procedures/dag 0.45.0 → 0.47.1
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 +31 -0
- package/README.md +15 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/graph/hub-order.d.ts +19 -0
- package/dist/graph/hub-order.d.ts.map +1 -0
- package/dist/graph/hub-order.js +52 -0
- package/dist/graph/hub-order.js.map +1 -0
- package/dist/graph/index.d.ts +6 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +6 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/procedures/types.d.ts +1 -1
- package/dist/procedures/types.d.ts.map +1 -1
- package/dist/procedures/types.js +1 -1
- package/dist/procedures/types.js.map +1 -1
- package/package.json +11 -4
- package/src/graph/hub-order.ts +53 -0
- package/src/graph/index.ts +6 -0
- package/src/index.ts +3 -0
- package/src/procedures/types.ts +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** An undirected edge between the nodes `a` and `b`. The default weight is 1. */
|
|
2
|
+
export interface WeightedEdge {
|
|
3
|
+
readonly a: number;
|
|
4
|
+
readonly b: number;
|
|
5
|
+
readonly weight?: number | undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* This function gives a breadth-first order of the nodes `0` to `n - 1` of an undirected weighted graph.
|
|
9
|
+
*
|
|
10
|
+
* - The hub of a component is the node with the largest sum of edge weights. `compare`, then the lower index, breaks a tie.
|
|
11
|
+
* - The order starts at the hub of each component, and goes breadth-first. `compare`, then the lower index, orders the neighbours of a node.
|
|
12
|
+
* - Without edges, each node is a component, so the order is the order of `compare`.
|
|
13
|
+
* - An edge from a node to itself adds no weight.
|
|
14
|
+
* - A bad `n`, an index outside the nodes, or a weight that is not a finite number above 0, throws a `RangeError`.
|
|
15
|
+
*
|
|
16
|
+
* The function is pure. It keeps no state, and it does not change its arguments.
|
|
17
|
+
*/
|
|
18
|
+
export declare function hubBreadthFirstOrder(n: number, edges?: readonly WeightedEdge[], compare?: (i: number, j: number) => number): number[];
|
|
19
|
+
//# sourceMappingURL=hub-order.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-order.d.ts","sourceRoot":"","sources":["../../src/graph/hub-order.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,YAAY,EAAO,EAAE,OAAO,GAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAgB,GAAG,MAAM,EAAE,CAkClJ"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This function gives a breadth-first order of the nodes `0` to `n - 1` of an undirected weighted graph.
|
|
3
|
+
*
|
|
4
|
+
* - The hub of a component is the node with the largest sum of edge weights. `compare`, then the lower index, breaks a tie.
|
|
5
|
+
* - The order starts at the hub of each component, and goes breadth-first. `compare`, then the lower index, orders the neighbours of a node.
|
|
6
|
+
* - Without edges, each node is a component, so the order is the order of `compare`.
|
|
7
|
+
* - An edge from a node to itself adds no weight.
|
|
8
|
+
* - A bad `n`, an index outside the nodes, or a weight that is not a finite number above 0, throws a `RangeError`.
|
|
9
|
+
*
|
|
10
|
+
* The function is pure. It keeps no state, and it does not change its arguments.
|
|
11
|
+
*/
|
|
12
|
+
export function hubBreadthFirstOrder(n, edges = [], compare = () => 0) {
|
|
13
|
+
if (!Number.isInteger(n) || n < 0)
|
|
14
|
+
throw new RangeError(`The count of the nodes is a whole number from 0, not ${n}.`);
|
|
15
|
+
const degree = new Float64Array(n);
|
|
16
|
+
const next = Array.from({ length: n }, () => []);
|
|
17
|
+
for (const { a, b, weight = 1 } of edges) {
|
|
18
|
+
if (!Number.isInteger(a) || !Number.isInteger(b) || a < 0 || b < 0 || a >= n || b >= n) {
|
|
19
|
+
throw new RangeError(`An edge joins the nodes ${a} and ${b}, but the indexes go from 0 to ${n - 1}.`);
|
|
20
|
+
}
|
|
21
|
+
if (!Number.isFinite(weight) || weight <= 0)
|
|
22
|
+
throw new RangeError(`The weight of an edge is a finite number above 0, not ${weight}.`);
|
|
23
|
+
if (a === b)
|
|
24
|
+
continue;
|
|
25
|
+
degree[a] = degree[a] + weight;
|
|
26
|
+
degree[b] = degree[b] + weight;
|
|
27
|
+
next[a].push(b);
|
|
28
|
+
next[b].push(a);
|
|
29
|
+
}
|
|
30
|
+
const order = (i, j) => compare(i, j) || i - j;
|
|
31
|
+
const hubs = Array.from({ length: n }, (_, i) => i).sort((i, j) => degree[j] - degree[i] || order(i, j));
|
|
32
|
+
const seen = new Uint8Array(n);
|
|
33
|
+
const out = [];
|
|
34
|
+
for (const hub of hubs) {
|
|
35
|
+
if (seen[hub] === 1)
|
|
36
|
+
continue;
|
|
37
|
+
seen[hub] = 1;
|
|
38
|
+
const queue = [hub];
|
|
39
|
+
for (let k = 0; k < queue.length; k++) {
|
|
40
|
+
const i = queue[k];
|
|
41
|
+
out.push(i);
|
|
42
|
+
for (const j of next[i].toSorted(order)) {
|
|
43
|
+
if (seen[j] === 1)
|
|
44
|
+
continue;
|
|
45
|
+
seen[j] = 1;
|
|
46
|
+
queue.push(j);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=hub-order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-order.js","sourceRoot":"","sources":["../../src/graph/hub-order.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry `@procedures/dag/graph` holds pure graph functions. It imports no other package, so a browser bundle or a
|
|
3
|
+
* general package can use it without `@procedures/client` and zod.
|
|
4
|
+
*/
|
|
5
|
+
export { hubBreadthFirstOrder, type WeightedEdge } from "./hub-order.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry `@procedures/dag/graph` holds pure graph functions. It imports no other package, so a browser bundle or a
|
|
3
|
+
* general package can use it without `@procedures/client` and zod.
|
|
4
|
+
*/
|
|
5
|
+
export { hubBreadthFirstOrder } from "./hub-order.js";
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,oBAAoB,EAAqB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
*/
|
|
40
40
|
export type { DAGNode, DependencyDAG, DAGExecutionOptions, NodeResult, DAGResult, NodeProcessor, } from "./types.js";
|
|
41
41
|
export { buildLeveledDAG, getTopologicalOrder, visualizeDAG, executeDAG, executeDAGSequential, createProcessor, filterDAGFromRoot, getAncestors, getDescendants, createNode, buildNodeMap, } from "./dag/index.js";
|
|
42
|
+
export { hubBreadthFirstOrder, type WeightedEdge } from "./graph/index.js";
|
|
42
43
|
export * from "./module.js";
|
|
43
44
|
export { DagTraverseInputSchema, DagTraverseOutputSchema, type DagTraverseInput, type DagTraverseOutput, type TraverseNodeResult, type ScannedPackage, type ScanOutput, type PackageNode, } from "./procedures/types.js";
|
|
44
45
|
export { dagTraverse, packageNodes, callsGit, keyedLock, repositoryRoot } from "./procedures/traverse.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,YAAY,EACV,OAAO,EACP,aAAa,EACb,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,GACb,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,YAAY,EACV,OAAO,EACP,aAAa,EACb,mBAAmB,EACnB,UAAU,EACV,SAAS,EACT,aAAa,GACd,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,GACb,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAI3E,cAAc,aAAa,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,WAAW,GACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
*/
|
|
40
40
|
// DAG utilities
|
|
41
41
|
export { buildLeveledDAG, getTopologicalOrder, visualizeDAG, executeDAG, executeDAGSequential, createProcessor, filterDAGFromRoot, getAncestors, getDescendants, createNode, buildNodeMap, } from "./dag/index.js";
|
|
42
|
+
// Pure graph functions. The entry "@procedures/dag/graph" gives them without @procedures/client and zod.
|
|
43
|
+
export { hubBreadthFirstOrder } from "./graph/index.js";
|
|
42
44
|
// The procedure dag.traverse. The root registers nothing: import "@procedures/dag/register", or
|
|
43
45
|
// give the module to createRegistry() with the module of @procedures/lib.
|
|
44
46
|
export * from "./module.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAYH,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,gGAAgG;AAChG,0EAA0E;AAC1E,cAAc,aAAa,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAOxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAYH,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,UAAU,EACV,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,yGAAyG;AACzG,OAAO,EAAE,oBAAoB,EAAqB,MAAM,kBAAkB,CAAC;AAE3E,gGAAgG;AAChG,0EAA0E;AAC1E,cAAc,aAAa,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,uBAAuB,GAOxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* The procedure came from `@procedures/lib` (roadmap, items for a decision). Its name stays
|
|
5
5
|
* `dag.traverse`.
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
7
|
+
import * as z from "zod";
|
|
8
8
|
import type { DAGNode } from "../types.js";
|
|
9
9
|
/**
|
|
10
10
|
* Schema for $proc references with $when control.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/procedures/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/procedures/types.ts"],"names":[],"mappings":"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"}
|
package/dist/procedures/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/procedures/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/procedures/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package",
|
|
3
3
|
"name": "@procedures/dag",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.47.1",
|
|
5
5
|
"description": "Dependency graph algorithms for TypeScript: build a DAG, detect cycles, compute topological levels and traverse in parallel with a concurrency limit. The procedure dag.traverse visits workspace packages in dependency order.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"dag",
|
|
@@ -31,6 +31,10 @@
|
|
|
31
31
|
"types": "./dist/index.d.ts",
|
|
32
32
|
"import": "./dist/index.js"
|
|
33
33
|
},
|
|
34
|
+
"./graph": {
|
|
35
|
+
"types": "./dist/graph/index.d.ts",
|
|
36
|
+
"import": "./dist/graph/index.js"
|
|
37
|
+
},
|
|
34
38
|
"./module": {
|
|
35
39
|
"types": "./dist/module.d.ts",
|
|
36
40
|
"import": "./dist/module.js"
|
|
@@ -61,19 +65,22 @@
|
|
|
61
65
|
"devDependencies": {
|
|
62
66
|
"typescript": "^7.0.2",
|
|
63
67
|
"@types/node": "^22.0.0",
|
|
64
|
-
"@mark1russell7/cue": "^1.
|
|
68
|
+
"@mark1russell7/cue": "^1.1.0",
|
|
65
69
|
"vitest": "^5.0.3"
|
|
66
70
|
},
|
|
67
71
|
"dependencies": {
|
|
68
|
-
"@procedures/client": "0.
|
|
72
|
+
"@procedures/client": "0.47.1",
|
|
69
73
|
"zod": "^4.6.5"
|
|
70
74
|
},
|
|
71
75
|
"client": {
|
|
76
|
+
"browser": [
|
|
77
|
+
"./graph"
|
|
78
|
+
],
|
|
72
79
|
"procedures": "./dist/register.js"
|
|
73
80
|
},
|
|
74
81
|
"scripts": {
|
|
75
82
|
"build": "tsc -b",
|
|
76
|
-
"typecheck": "tsc --noEmit",
|
|
83
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.test.json",
|
|
77
84
|
"clean": "rm -rf dist .tsbuildinfo",
|
|
78
85
|
"test": "vitest run",
|
|
79
86
|
"test:watch": "vitest",
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** An undirected edge between the nodes `a` and `b`. The default weight is 1. */
|
|
2
|
+
export interface WeightedEdge {
|
|
3
|
+
readonly a: number;
|
|
4
|
+
readonly b: number;
|
|
5
|
+
readonly weight?: number | undefined;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This function gives a breadth-first order of the nodes `0` to `n - 1` of an undirected weighted graph.
|
|
10
|
+
*
|
|
11
|
+
* - The hub of a component is the node with the largest sum of edge weights. `compare`, then the lower index, breaks a tie.
|
|
12
|
+
* - The order starts at the hub of each component, and goes breadth-first. `compare`, then the lower index, orders the neighbours of a node.
|
|
13
|
+
* - Without edges, each node is a component, so the order is the order of `compare`.
|
|
14
|
+
* - An edge from a node to itself adds no weight.
|
|
15
|
+
* - A bad `n`, an index outside the nodes, or a weight that is not a finite number above 0, throws a `RangeError`.
|
|
16
|
+
*
|
|
17
|
+
* The function is pure. It keeps no state, and it does not change its arguments.
|
|
18
|
+
*/
|
|
19
|
+
export function hubBreadthFirstOrder(n: number, edges: readonly WeightedEdge[] = [], compare: (i: number, j: number) => number = () => 0): number[] {
|
|
20
|
+
if (!Number.isInteger(n) || n < 0) throw new RangeError(`The count of the nodes is a whole number from 0, not ${n}.`);
|
|
21
|
+
const degree = new Float64Array(n);
|
|
22
|
+
const next: number[][] = Array.from({ length: n }, () => []);
|
|
23
|
+
for (const { a, b, weight = 1 } of edges) {
|
|
24
|
+
if (!Number.isInteger(a) || !Number.isInteger(b) || a < 0 || b < 0 || a >= n || b >= n) {
|
|
25
|
+
throw new RangeError(`An edge joins the nodes ${a} and ${b}, but the indexes go from 0 to ${n - 1}.`);
|
|
26
|
+
}
|
|
27
|
+
if (!Number.isFinite(weight) || weight <= 0) throw new RangeError(`The weight of an edge is a finite number above 0, not ${weight}.`);
|
|
28
|
+
if (a === b) continue;
|
|
29
|
+
degree[a] = degree[a]! + weight;
|
|
30
|
+
degree[b] = degree[b]! + weight;
|
|
31
|
+
next[a]!.push(b);
|
|
32
|
+
next[b]!.push(a);
|
|
33
|
+
}
|
|
34
|
+
const order = (i: number, j: number): number => compare(i, j) || i - j;
|
|
35
|
+
const hubs = Array.from({ length: n }, (_, i) => i).sort((i, j) => degree[j]! - degree[i]! || order(i, j));
|
|
36
|
+
const seen = new Uint8Array(n);
|
|
37
|
+
const out: number[] = [];
|
|
38
|
+
for (const hub of hubs) {
|
|
39
|
+
if (seen[hub] === 1) continue;
|
|
40
|
+
seen[hub] = 1;
|
|
41
|
+
const queue = [hub];
|
|
42
|
+
for (let k = 0; k < queue.length; k++) {
|
|
43
|
+
const i = queue[k]!;
|
|
44
|
+
out.push(i);
|
|
45
|
+
for (const j of next[i]!.toSorted(order)) {
|
|
46
|
+
if (seen[j] === 1) continue;
|
|
47
|
+
seen[j] = 1;
|
|
48
|
+
queue.push(j);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The entry `@procedures/dag/graph` holds pure graph functions. It imports no other package, so a browser bundle or a
|
|
3
|
+
* general package can use it without `@procedures/client` and zod.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { hubBreadthFirstOrder, type WeightedEdge } from "./hub-order.js";
|
package/src/index.ts
CHANGED
|
@@ -63,6 +63,9 @@ export {
|
|
|
63
63
|
buildNodeMap,
|
|
64
64
|
} from "./dag/index.js";
|
|
65
65
|
|
|
66
|
+
// Pure graph functions. The entry "@procedures/dag/graph" gives them without @procedures/client and zod.
|
|
67
|
+
export { hubBreadthFirstOrder, type WeightedEdge } from "./graph/index.js";
|
|
68
|
+
|
|
66
69
|
// The procedure dag.traverse. The root registers nothing: import "@procedures/dag/register", or
|
|
67
70
|
// give the module to createRegistry() with the module of @procedures/lib.
|
|
68
71
|
export * from "./module.js";
|