@optave/codegraph 3.5.0 → 3.6.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 +35 -14
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +119 -127
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +14 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js +11 -13
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/db/connection.d.ts +12 -2
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +81 -53
- package/dist/db/connection.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +38 -32
- package/dist/db/migrations.js.map +1 -1
- package/dist/domain/analysis/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +51 -66
- package/dist/domain/analysis/context.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +62 -70
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/diff-impact.d.ts +9 -7
- package/dist/domain/analysis/diff-impact.d.ts.map +1 -1
- package/dist/domain/analysis/exports.d.ts.map +1 -1
- package/dist/domain/analysis/exports.js +29 -33
- package/dist/domain/analysis/exports.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +15 -17
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +35 -65
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +91 -6
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/query-helpers.d.ts +20 -0
- package/dist/domain/analysis/query-helpers.d.ts.map +1 -0
- package/dist/domain/analysis/query-helpers.js +27 -0
- package/dist/domain/analysis/query-helpers.js.map +1 -0
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +15 -9
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +3 -2
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +69 -3
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +7 -51
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-structure.js +7 -5
- package/dist/domain/graph/builder/stages/build-structure.js.map +1 -1
- package/dist/domain/graph/builder/stages/collect-files.js +2 -2
- package/dist/domain/graph/builder/stages/collect-files.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +2 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +124 -105
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +28 -15
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +3 -2
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/resolve.d.ts +0 -4
- package/dist/domain/graph/resolve.d.ts.map +1 -1
- package/dist/domain/graph/resolve.js +32 -48
- package/dist/domain/graph/resolve.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +12 -12
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +1 -1
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +164 -101
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/search/cli-formatter.d.ts.map +1 -1
- package/dist/domain/search/search/cli-formatter.js +88 -83
- package/dist/domain/search/search/cli-formatter.js.map +1 -1
- package/dist/extractors/bash.d.ts +6 -0
- package/dist/extractors/bash.d.ts.map +1 -0
- package/dist/extractors/bash.js +91 -0
- package/dist/extractors/bash.js.map +1 -0
- package/dist/extractors/c.d.ts +6 -0
- package/dist/extractors/c.d.ts.map +1 -0
- package/dist/extractors/c.js +204 -0
- package/dist/extractors/c.js.map +1 -0
- package/dist/extractors/cpp.d.ts +6 -0
- package/dist/extractors/cpp.d.ts.map +1 -0
- package/dist/extractors/cpp.js +283 -0
- package/dist/extractors/cpp.js.map +1 -0
- package/dist/extractors/csharp.d.ts.map +1 -1
- package/dist/extractors/csharp.js +42 -54
- package/dist/extractors/csharp.js.map +1 -1
- package/dist/extractors/go.d.ts.map +1 -1
- package/dist/extractors/go.js +126 -130
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/hcl.js +6 -6
- package/dist/extractors/hcl.js.map +1 -1
- package/dist/extractors/helpers.d.ts +32 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +74 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/index.d.ts +6 -0
- package/dist/extractors/index.d.ts.map +1 -1
- package/dist/extractors/index.js +6 -0
- package/dist/extractors/index.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +32 -47
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.d.ts.map +1 -1
- package/dist/extractors/javascript.js +306 -292
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.d.ts +6 -0
- package/dist/extractors/kotlin.d.ts.map +1 -0
- package/dist/extractors/kotlin.js +275 -0
- package/dist/extractors/kotlin.js.map +1 -0
- package/dist/extractors/php.d.ts.map +1 -1
- package/dist/extractors/php.js +39 -44
- package/dist/extractors/php.js.map +1 -1
- package/dist/extractors/python.d.ts.map +1 -1
- package/dist/extractors/python.js +75 -93
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/ruby.js +6 -13
- package/dist/extractors/ruby.js.map +1 -1
- package/dist/extractors/rust.d.ts.map +1 -1
- package/dist/extractors/rust.js +58 -83
- package/dist/extractors/rust.js.map +1 -1
- package/dist/extractors/scala.d.ts +6 -0
- package/dist/extractors/scala.d.ts.map +1 -0
- package/dist/extractors/scala.js +269 -0
- package/dist/extractors/scala.js.map +1 -0
- package/dist/extractors/swift.d.ts +6 -0
- package/dist/extractors/swift.d.ts.map +1 -0
- package/dist/extractors/swift.js +275 -0
- package/dist/extractors/swift.js.map +1 -0
- package/dist/features/ast.d.ts +2 -0
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +9 -24
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +17 -21
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +47 -3
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/cfg.d.ts +7 -1
- package/dist/features/cfg.d.ts.map +1 -1
- package/dist/features/cfg.js +118 -62
- package/dist/features/cfg.js.map +1 -1
- package/dist/features/check.d.ts.map +1 -1
- package/dist/features/check.js +79 -62
- package/dist/features/check.js.map +1 -1
- package/dist/features/complexity-query.d.ts.map +1 -1
- package/dist/features/complexity-query.js +142 -137
- package/dist/features/complexity-query.js.map +1 -1
- package/dist/features/complexity.d.ts +7 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +62 -1
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts +7 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +356 -188
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/graph-enrichment.d.ts.map +1 -1
- package/dist/features/graph-enrichment.js +117 -104
- package/dist/features/graph-enrichment.js.map +1 -1
- package/dist/features/sequence.d.ts.map +1 -1
- package/dist/features/sequence.js +25 -4
- package/dist/features/sequence.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +29 -4
- package/dist/features/structure-query.js.map +1 -1
- package/dist/features/structure.d.ts.map +1 -1
- package/dist/features/structure.js +35 -15
- package/dist/features/structure.js.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/adapter.js +88 -73
- package/dist/graph/algorithms/leiden/adapter.js.map +1 -1
- package/dist/graph/algorithms/leiden/index.js +43 -28
- package/dist/graph/algorithms/leiden/index.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +90 -104
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/partition.js +89 -106
- package/dist/graph/algorithms/leiden/partition.js.map +1 -1
- package/dist/graph/model.d.ts +2 -0
- package/dist/graph/model.d.ts.map +1 -1
- package/dist/graph/model.js +20 -8
- package/dist/graph/model.js.map +1 -1
- package/dist/infrastructure/config.d.ts +0 -8
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +73 -62
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +0 -8
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +12 -14
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +45 -36
- package/dist/mcp/server.js.map +1 -1
- package/dist/presentation/audit.d.ts.map +1 -1
- package/dist/presentation/audit.js +61 -57
- package/dist/presentation/audit.js.map +1 -1
- package/dist/presentation/branch-compare.d.ts.map +1 -1
- package/dist/presentation/branch-compare.js +56 -38
- package/dist/presentation/branch-compare.js.map +1 -1
- package/dist/presentation/check.d.ts.map +1 -1
- package/dist/presentation/check.js +30 -32
- package/dist/presentation/check.js.map +1 -1
- package/dist/presentation/colors.d.ts.map +1 -1
- package/dist/presentation/colors.js +2 -0
- package/dist/presentation/colors.js.map +1 -1
- package/dist/presentation/complexity.d.ts.map +1 -1
- package/dist/presentation/complexity.js +25 -19
- package/dist/presentation/complexity.js.map +1 -1
- package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
- package/dist/presentation/queries-cli/exports.js +15 -15
- package/dist/presentation/queries-cli/exports.js.map +1 -1
- package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
- package/dist/presentation/queries-cli/impact.js +29 -19
- package/dist/presentation/queries-cli/impact.js.map +1 -1
- package/dist/types.d.ts +182 -7
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-bash.wasm +0 -0
- package/grammars/tree-sitter-c.wasm +0 -0
- package/grammars/tree-sitter-cpp.wasm +0 -0
- package/grammars/tree-sitter-kotlin.wasm +0 -0
- package/grammars/tree-sitter-scala.wasm +0 -0
- package/grammars/tree-sitter-swift.wasm +0 -0
- package/package.json +13 -7
- package/src/ast-analysis/engine.ts +147 -138
- package/src/ast-analysis/visitors/ast-store-visitor.ts +15 -2
- package/src/ast-analysis/visitors/complexity-visitor.ts +11 -11
- package/src/db/connection.ts +90 -59
- package/src/db/index.ts +1 -0
- package/src/db/migrations.ts +36 -32
- package/src/domain/analysis/context.ts +73 -75
- package/src/domain/analysis/dependencies.ts +78 -68
- package/src/domain/analysis/exports.ts +45 -34
- package/src/domain/analysis/fn-impact.ts +67 -64
- package/src/domain/analysis/module-map.ts +103 -8
- package/src/domain/analysis/query-helpers.ts +35 -0
- package/src/domain/graph/builder/helpers.ts +12 -6
- package/src/domain/graph/builder/incremental.ts +3 -2
- package/src/domain/graph/builder/pipeline.ts +71 -3
- package/src/domain/graph/builder/stages/build-edges.ts +10 -75
- package/src/domain/graph/builder/stages/build-structure.ts +9 -7
- package/src/domain/graph/builder/stages/collect-files.ts +2 -2
- package/src/domain/graph/builder/stages/detect-changes.ts +7 -2
- package/src/domain/graph/builder/stages/finalize.ts +159 -125
- package/src/domain/graph/builder/stages/insert-nodes.ts +32 -21
- package/src/domain/graph/builder/stages/resolve-imports.ts +3 -2
- package/src/domain/graph/resolve.ts +34 -46
- package/src/domain/graph/watcher.ts +12 -14
- package/src/domain/parser.ts +168 -97
- package/src/domain/search/search/cli-formatter.ts +121 -94
- package/src/extractors/bash.ts +97 -0
- package/src/extractors/c.ts +212 -0
- package/src/extractors/cpp.ts +298 -0
- package/src/extractors/csharp.ts +53 -56
- package/src/extractors/go.ts +152 -134
- package/src/extractors/hcl.ts +6 -6
- package/src/extractors/helpers.ts +93 -1
- package/src/extractors/index.ts +6 -0
- package/src/extractors/java.ts +43 -48
- package/src/extractors/javascript.ts +328 -281
- package/src/extractors/kotlin.ts +293 -0
- package/src/extractors/php.ts +46 -40
- package/src/extractors/python.ts +81 -104
- package/src/extractors/ruby.ts +6 -13
- package/src/extractors/rust.ts +65 -85
- package/src/extractors/scala.ts +285 -0
- package/src/extractors/swift.ts +293 -0
- package/src/features/ast.ts +10 -25
- package/src/features/audit.ts +24 -20
- package/src/features/branch-compare.ts +51 -4
- package/src/features/cfg.ts +158 -65
- package/src/features/check.ts +90 -74
- package/src/features/complexity-query.ts +181 -163
- package/src/features/complexity.ts +64 -1
- package/src/features/dataflow.ts +462 -217
- package/src/features/graph-enrichment.ts +161 -117
- package/src/features/sequence.ts +27 -4
- package/src/features/structure-query.ts +43 -4
- package/src/features/structure.ts +50 -22
- package/src/graph/algorithms/leiden/adapter.ts +126 -71
- package/src/graph/algorithms/leiden/index.ts +67 -28
- package/src/graph/algorithms/leiden/optimiser.ts +114 -105
- package/src/graph/algorithms/leiden/partition.ts +131 -98
- package/src/graph/model.ts +19 -7
- package/src/infrastructure/config.ts +60 -58
- package/src/infrastructure/registry.ts +17 -14
- package/src/mcp/server.ts +46 -37
- package/src/presentation/audit.ts +72 -67
- package/src/presentation/branch-compare.ts +54 -50
- package/src/presentation/check.ts +34 -34
- package/src/presentation/colors.ts +2 -0
- package/src/presentation/complexity.ts +39 -33
- package/src/presentation/queries-cli/exports.ts +17 -17
- package/src/presentation/queries-cli/impact.ts +30 -22
- package/src/types.ts +189 -7
|
@@ -56,6 +56,109 @@ function u8get(a: Uint8Array, i: number): number {
|
|
|
56
56
|
return a[i] as number;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Accumulate per-community node-level totals (size, count, strength) into the
|
|
61
|
+
* provided aggregate arrays. Both `initializeAggregates` and `compactCommunityIds`
|
|
62
|
+
* share this logic — extracting it eliminates the duplication.
|
|
63
|
+
*/
|
|
64
|
+
function accumulateNodeAggregates(
|
|
65
|
+
graph: GraphAdapter,
|
|
66
|
+
nodeCommunity: Int32Array,
|
|
67
|
+
n: number,
|
|
68
|
+
totalSize: Float64Array,
|
|
69
|
+
nodeCount: Int32Array,
|
|
70
|
+
internalEdgeWeight: Float64Array,
|
|
71
|
+
totalStrength: Float64Array,
|
|
72
|
+
totalOutStrength: Float64Array,
|
|
73
|
+
totalInStrength: Float64Array,
|
|
74
|
+
): void {
|
|
75
|
+
for (let i = 0; i < n; i++) {
|
|
76
|
+
const c: number = iget(nodeCommunity, i);
|
|
77
|
+
totalSize[c] = fget(totalSize, c) + fget(graph.size, i);
|
|
78
|
+
nodeCount[c] = iget(nodeCount, c) + 1;
|
|
79
|
+
if (graph.directed) {
|
|
80
|
+
totalOutStrength[c] = fget(totalOutStrength, c) + fget(graph.strengthOut, i);
|
|
81
|
+
totalInStrength[c] = fget(totalInStrength, c) + fget(graph.strengthIn, i);
|
|
82
|
+
} else {
|
|
83
|
+
totalStrength[c] = fget(totalStrength, c) + fget(graph.strengthOut, i);
|
|
84
|
+
}
|
|
85
|
+
if (fget(graph.selfLoop, i) !== 0)
|
|
86
|
+
internalEdgeWeight[c] = fget(internalEdgeWeight, c) + fget(graph.selfLoop, i);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Accumulate intra-community edge weights. For directed graphs, counts all
|
|
92
|
+
* intra-community non-self edges. For undirected, counts each edge once (j > i).
|
|
93
|
+
*/
|
|
94
|
+
function accumulateInternalEdgeWeights(
|
|
95
|
+
graph: GraphAdapter,
|
|
96
|
+
nodeCommunity: Int32Array,
|
|
97
|
+
n: number,
|
|
98
|
+
internalEdgeWeight: Float64Array,
|
|
99
|
+
): void {
|
|
100
|
+
if (graph.directed) {
|
|
101
|
+
for (let i = 0; i < n; i++) {
|
|
102
|
+
const ci: number = iget(nodeCommunity, i);
|
|
103
|
+
const neighbors = graph.outEdges[i]!;
|
|
104
|
+
for (let k = 0; k < neighbors.length; k++) {
|
|
105
|
+
const { to: j, w } = neighbors[k]!;
|
|
106
|
+
if (i === j) continue; // self-loop already counted via graph.selfLoop[i]
|
|
107
|
+
if (ci === iget(nodeCommunity, j))
|
|
108
|
+
internalEdgeWeight[ci] = fget(internalEdgeWeight, ci) + w;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
for (let i = 0; i < n; i++) {
|
|
113
|
+
const ci: number = iget(nodeCommunity, i);
|
|
114
|
+
const neighbors = graph.outEdges[i]!;
|
|
115
|
+
for (let k = 0; k < neighbors.length; k++) {
|
|
116
|
+
const { to: j, w } = neighbors[k]!;
|
|
117
|
+
if (j <= i) continue;
|
|
118
|
+
if (ci === iget(nodeCommunity, j))
|
|
119
|
+
internalEdgeWeight[ci] = fget(internalEdgeWeight, ci) + w;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Sort community IDs according to the compaction options: preserve original
|
|
127
|
+
* order, respect a user-provided label map, or sort by descending size.
|
|
128
|
+
* Returns the sorted list of non-empty community IDs.
|
|
129
|
+
*/
|
|
130
|
+
function buildSortedCommunityIds(
|
|
131
|
+
ids: number[],
|
|
132
|
+
opts: CompactOptions,
|
|
133
|
+
communityTotalSize: Float64Array,
|
|
134
|
+
communityNodeCount: Int32Array,
|
|
135
|
+
): void {
|
|
136
|
+
if (opts.keepOldOrder) {
|
|
137
|
+
ids.sort((a, b) => a - b);
|
|
138
|
+
} else if (opts.preserveMap instanceof Map) {
|
|
139
|
+
const preserveMap = opts.preserveMap;
|
|
140
|
+
ids.sort((a, b) => {
|
|
141
|
+
const pa = preserveMap.get(a);
|
|
142
|
+
const pb = preserveMap.get(b);
|
|
143
|
+
if (pa != null && pb != null && pa !== pb) return pa - pb;
|
|
144
|
+
if (pa != null && pb == null) return -1;
|
|
145
|
+
if (pb != null && pa == null) return 1;
|
|
146
|
+
return (
|
|
147
|
+
fget(communityTotalSize, b) - fget(communityTotalSize, a) ||
|
|
148
|
+
iget(communityNodeCount, b) - iget(communityNodeCount, a) ||
|
|
149
|
+
a - b
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
ids.sort(
|
|
154
|
+
(a, b) =>
|
|
155
|
+
fget(communityTotalSize, b) - fget(communityTotalSize, a) ||
|
|
156
|
+
iget(communityNodeCount, b) - iget(communityNodeCount, a) ||
|
|
157
|
+
a - b,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
59
162
|
export function makePartition(graph: GraphAdapter): Partition {
|
|
60
163
|
const n: number = graph.n;
|
|
61
164
|
const nodeCommunity = new Int32Array(n);
|
|
@@ -94,44 +197,18 @@ export function makePartition(graph: GraphAdapter): Partition {
|
|
|
94
197
|
communityTotalStrength.fill(0);
|
|
95
198
|
communityTotalOutStrength.fill(0);
|
|
96
199
|
communityTotalInStrength.fill(0);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
communityInternalEdgeWeight[c] =
|
|
110
|
-
fget(communityInternalEdgeWeight, c) + fget(graph.selfLoop, i);
|
|
111
|
-
}
|
|
112
|
-
if (graph.directed) {
|
|
113
|
-
for (let i = 0; i < n; i++) {
|
|
114
|
-
const ci: number = iget(nodeCommunity, i);
|
|
115
|
-
const neighbors = graph.outEdges[i]!;
|
|
116
|
-
for (let k = 0; k < neighbors.length; k++) {
|
|
117
|
-
const { to: j, w } = neighbors[k]!;
|
|
118
|
-
if (i === j) continue; // self-loop already counted via graph.selfLoop[i]
|
|
119
|
-
if (ci === iget(nodeCommunity, j))
|
|
120
|
-
communityInternalEdgeWeight[ci] = fget(communityInternalEdgeWeight, ci) + w;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
} else {
|
|
124
|
-
for (let i = 0; i < n; i++) {
|
|
125
|
-
const ci: number = iget(nodeCommunity, i);
|
|
126
|
-
const neighbors = graph.outEdges[i]!;
|
|
127
|
-
for (let k = 0; k < neighbors.length; k++) {
|
|
128
|
-
const { to: j, w } = neighbors[k]!;
|
|
129
|
-
if (j <= i) continue;
|
|
130
|
-
if (ci === iget(nodeCommunity, j))
|
|
131
|
-
communityInternalEdgeWeight[ci] = fget(communityInternalEdgeWeight, ci) + w;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
200
|
+
accumulateNodeAggregates(
|
|
201
|
+
graph,
|
|
202
|
+
nodeCommunity,
|
|
203
|
+
n,
|
|
204
|
+
communityTotalSize,
|
|
205
|
+
communityNodeCount,
|
|
206
|
+
communityInternalEdgeWeight,
|
|
207
|
+
communityTotalStrength,
|
|
208
|
+
communityTotalOutStrength,
|
|
209
|
+
communityTotalInStrength,
|
|
210
|
+
);
|
|
211
|
+
accumulateInternalEdgeWeights(graph, nodeCommunity, n, communityInternalEdgeWeight);
|
|
135
212
|
}
|
|
136
213
|
|
|
137
214
|
function resetScratch(): void {
|
|
@@ -323,36 +400,15 @@ export function makePartition(graph: GraphAdapter): Partition {
|
|
|
323
400
|
function compactCommunityIds(opts: CompactOptions = {}): void {
|
|
324
401
|
const ids: number[] = [];
|
|
325
402
|
for (let c = 0; c < communityCount; c++) if (iget(communityNodeCount, c) > 0) ids.push(c);
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
} else if (opts.preserveMap instanceof Map) {
|
|
329
|
-
const preserveMap = opts.preserveMap;
|
|
330
|
-
ids.sort((a, b) => {
|
|
331
|
-
const pa = preserveMap.get(a);
|
|
332
|
-
const pb = preserveMap.get(b);
|
|
333
|
-
if (pa != null && pb != null && pa !== pb) return pa - pb;
|
|
334
|
-
if (pa != null && pb == null) return -1;
|
|
335
|
-
if (pb != null && pa == null) return 1;
|
|
336
|
-
return (
|
|
337
|
-
fget(communityTotalSize, b) - fget(communityTotalSize, a) ||
|
|
338
|
-
iget(communityNodeCount, b) - iget(communityNodeCount, a) ||
|
|
339
|
-
a - b
|
|
340
|
-
);
|
|
341
|
-
});
|
|
342
|
-
} else {
|
|
343
|
-
ids.sort(
|
|
344
|
-
(a, b) =>
|
|
345
|
-
fget(communityTotalSize, b) - fget(communityTotalSize, a) ||
|
|
346
|
-
iget(communityNodeCount, b) - iget(communityNodeCount, a) ||
|
|
347
|
-
a - b,
|
|
348
|
-
);
|
|
349
|
-
}
|
|
403
|
+
buildSortedCommunityIds(ids, opts, communityTotalSize, communityNodeCount);
|
|
404
|
+
|
|
350
405
|
const newId = new Int32Array(communityCount).fill(-1);
|
|
351
406
|
ids.forEach((c, i) => {
|
|
352
407
|
newId[c] = i;
|
|
353
408
|
});
|
|
354
409
|
for (let i = 0; i < nodeCommunity.length; i++)
|
|
355
410
|
nodeCommunity[i] = iget(newId, iget(nodeCommunity, i));
|
|
411
|
+
|
|
356
412
|
const remappedCount: number = ids.length;
|
|
357
413
|
const newTotalSize = new Float64Array(remappedCount);
|
|
358
414
|
const newNodeCount = new Int32Array(remappedCount);
|
|
@@ -360,42 +416,19 @@ export function makePartition(graph: GraphAdapter): Partition {
|
|
|
360
416
|
const newTotalStrength = new Float64Array(remappedCount);
|
|
361
417
|
const newTotalOutStrength = new Float64Array(remappedCount);
|
|
362
418
|
const newTotalInStrength = new Float64Array(remappedCount);
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
if (graph.directed) {
|
|
377
|
-
for (let i = 0; i < n; i++) {
|
|
378
|
-
const ci: number = iget(nodeCommunity, i);
|
|
379
|
-
const list = graph.outEdges[i]!;
|
|
380
|
-
for (let k = 0; k < list.length; k++) {
|
|
381
|
-
const { to: j, w } = list[k]!;
|
|
382
|
-
if (i === j) continue; // self-loop already counted via graph.selfLoop[i]
|
|
383
|
-
if (ci === iget(nodeCommunity, j))
|
|
384
|
-
newInternalEdgeWeight[ci] = fget(newInternalEdgeWeight, ci) + w;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
} else {
|
|
388
|
-
for (let i = 0; i < n; i++) {
|
|
389
|
-
const ci: number = iget(nodeCommunity, i);
|
|
390
|
-
const list = graph.outEdges[i]!;
|
|
391
|
-
for (let k = 0; k < list.length; k++) {
|
|
392
|
-
const { to: j, w } = list[k]!;
|
|
393
|
-
if (j <= i) continue;
|
|
394
|
-
if (ci === iget(nodeCommunity, j))
|
|
395
|
-
newInternalEdgeWeight[ci] = fget(newInternalEdgeWeight, ci) + w;
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
}
|
|
419
|
+
accumulateNodeAggregates(
|
|
420
|
+
graph,
|
|
421
|
+
nodeCommunity,
|
|
422
|
+
n,
|
|
423
|
+
newTotalSize,
|
|
424
|
+
newNodeCount,
|
|
425
|
+
newInternalEdgeWeight,
|
|
426
|
+
newTotalStrength,
|
|
427
|
+
newTotalOutStrength,
|
|
428
|
+
newTotalInStrength,
|
|
429
|
+
);
|
|
430
|
+
accumulateInternalEdgeWeights(graph, nodeCommunity, n, newInternalEdgeWeight);
|
|
431
|
+
|
|
399
432
|
communityCount = remappedCount;
|
|
400
433
|
communityTotalSize = newTotalSize;
|
|
401
434
|
communityNodeCount = newNodeCount;
|
package/src/graph/model.ts
CHANGED
|
@@ -103,15 +103,27 @@ export class CodeGraph {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
*edges(): Generator<[string, string, EdgeAttrs]> {
|
|
106
|
-
|
|
106
|
+
if (this._directed) {
|
|
107
|
+
yield* this._directedEdges();
|
|
108
|
+
} else {
|
|
109
|
+
yield* this._undirectedEdges();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private *_directedEdges(): Generator<[string, string, EdgeAttrs]> {
|
|
114
|
+
for (const [src, targets] of this._successors) {
|
|
115
|
+
for (const [tgt, attrs] of targets) yield [src, tgt, attrs];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private *_undirectedEdges(): Generator<[string, string, EdgeAttrs]> {
|
|
120
|
+
// \0 is safe as separator — node IDs are file paths/symbols, never contain null bytes
|
|
121
|
+
const seen = new Set<string>();
|
|
107
122
|
for (const [src, targets] of this._successors) {
|
|
108
123
|
for (const [tgt, attrs] of targets) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (seen!.has(key)) continue;
|
|
113
|
-
seen!.add(key);
|
|
114
|
-
}
|
|
124
|
+
const key = src < tgt ? `${src}\0${tgt}` : `${tgt}\0${src}`;
|
|
125
|
+
if (seen.has(key)) continue;
|
|
126
|
+
seen.add(key);
|
|
115
127
|
yield [src, tgt, attrs];
|
|
116
128
|
}
|
|
117
129
|
}
|
|
@@ -323,79 +323,70 @@ function resolveWorkspaceEntry(pkgDir: string): string | null {
|
|
|
323
323
|
* 2. package.json — `workspaces` field (npm/yarn)
|
|
324
324
|
* 3. lerna.json — `packages` array
|
|
325
325
|
*/
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const patterns: string[] = [];
|
|
329
|
-
|
|
330
|
-
// 1. pnpm-workspace.yaml
|
|
326
|
+
/** Read pnpm-workspace.yaml and return workspace glob patterns. */
|
|
327
|
+
function readPnpmWorkspacePatterns(rootDir: string): string[] {
|
|
331
328
|
const pnpmPath = path.join(rootDir, 'pnpm-workspace.yaml');
|
|
332
|
-
if (fs.existsSync(pnpmPath))
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
} catch (e) {
|
|
347
|
-
debug(`detectWorkspaces: failed to parse pnpm-workspace.yaml: ${toErrorMessage(e)}`);
|
|
329
|
+
if (!fs.existsSync(pnpmPath)) return [];
|
|
330
|
+
try {
|
|
331
|
+
const raw = fs.readFileSync(pnpmPath, 'utf-8');
|
|
332
|
+
const packagesMatch = raw.match(/^packages:\s*\n((?:\s+-\s+.+\n?)*)/m);
|
|
333
|
+
if (!packagesMatch) return [];
|
|
334
|
+
const lines = packagesMatch[1]!.match(/^\s+-\s+['"]?([^'"#\n]+)['"]?\s*$/gm);
|
|
335
|
+
if (!lines) return [];
|
|
336
|
+
const patterns: string[] = [];
|
|
337
|
+
for (const line of lines) {
|
|
338
|
+
const m = line.match(/^\s+-\s+['"]?([^'"#\n]+?)['"]?\s*$/);
|
|
339
|
+
if (m) patterns.push(m[1]!.trim());
|
|
348
340
|
}
|
|
341
|
+
return patterns;
|
|
342
|
+
} catch (e) {
|
|
343
|
+
debug(`detectWorkspaces: failed to parse pnpm-workspace.yaml: ${toErrorMessage(e)}`);
|
|
344
|
+
return [];
|
|
349
345
|
}
|
|
346
|
+
}
|
|
350
347
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
} catch (e) {
|
|
366
|
-
debug(`detectWorkspaces: failed to parse package.json workspaces: ${toErrorMessage(e)}`);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
348
|
+
/** Read package.json workspaces field (npm/yarn) and return glob patterns. */
|
|
349
|
+
function readNpmWorkspacePatterns(rootDir: string): string[] {
|
|
350
|
+
const rootPkgPath = path.join(rootDir, 'package.json');
|
|
351
|
+
if (!fs.existsSync(rootPkgPath)) return [];
|
|
352
|
+
try {
|
|
353
|
+
const raw = fs.readFileSync(rootPkgPath, 'utf-8');
|
|
354
|
+
const pkg = JSON.parse(raw);
|
|
355
|
+
const ws = pkg.workspaces;
|
|
356
|
+
if (Array.isArray(ws)) return ws;
|
|
357
|
+
if (ws && Array.isArray(ws.packages)) return ws.packages;
|
|
358
|
+
return [];
|
|
359
|
+
} catch (e) {
|
|
360
|
+
debug(`detectWorkspaces: failed to parse package.json workspaces: ${toErrorMessage(e)}`);
|
|
361
|
+
return [];
|
|
369
362
|
}
|
|
363
|
+
}
|
|
370
364
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
}
|
|
365
|
+
/** Read lerna.json packages field and return glob patterns. */
|
|
366
|
+
function readLernaPatterns(rootDir: string): string[] {
|
|
367
|
+
const lernaPath = path.join(rootDir, 'lerna.json');
|
|
368
|
+
if (!fs.existsSync(lernaPath)) return [];
|
|
369
|
+
try {
|
|
370
|
+
const raw = fs.readFileSync(lernaPath, 'utf-8');
|
|
371
|
+
const lerna = JSON.parse(raw);
|
|
372
|
+
if (Array.isArray(lerna.packages)) return lerna.packages;
|
|
373
|
+
return [];
|
|
374
|
+
} catch (e) {
|
|
375
|
+
debug(`detectWorkspaces: failed to parse lerna.json: ${toErrorMessage(e)}`);
|
|
376
|
+
return [];
|
|
385
377
|
}
|
|
378
|
+
}
|
|
386
379
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
380
|
+
/** Expand workspace patterns into concrete package entries. */
|
|
381
|
+
function expandWorkspacePatterns(patterns: string[], rootDir: string): Map<string, WorkspaceEntry> {
|
|
382
|
+
const workspaces = new Map<string, WorkspaceEntry>();
|
|
390
383
|
for (const pattern of patterns) {
|
|
391
|
-
// Check if pattern is a direct path (no glob) or a glob
|
|
392
384
|
if (pattern.includes('*')) {
|
|
393
385
|
for (const dir of expandWorkspaceGlob(pattern, rootDir)) {
|
|
394
386
|
const name = readPackageName(dir);
|
|
395
387
|
if (name) workspaces.set(name, { dir, entry: resolveWorkspaceEntry(dir) });
|
|
396
388
|
}
|
|
397
389
|
} else {
|
|
398
|
-
// Direct path like "packages/core"
|
|
399
390
|
const dir = path.resolve(rootDir, pattern);
|
|
400
391
|
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
401
392
|
const name = readPackageName(dir);
|
|
@@ -403,6 +394,17 @@ export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
|
|
|
403
394
|
}
|
|
404
395
|
}
|
|
405
396
|
}
|
|
397
|
+
return workspaces;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function detectWorkspaces(rootDir: string): Map<string, WorkspaceEntry> {
|
|
401
|
+
// Try each package manager in priority order — first match wins
|
|
402
|
+
let patterns = readPnpmWorkspacePatterns(rootDir);
|
|
403
|
+
if (patterns.length === 0) patterns = readNpmWorkspacePatterns(rootDir);
|
|
404
|
+
if (patterns.length === 0) patterns = readLernaPatterns(rootDir);
|
|
405
|
+
if (patterns.length === 0) return new Map();
|
|
406
|
+
|
|
407
|
+
const workspaces = expandWorkspacePatterns(patterns, rootDir);
|
|
406
408
|
|
|
407
409
|
if (workspaces.size > 0) {
|
|
408
410
|
debug(`Detected ${workspaces.size} workspace packages: ${[...workspaces.keys()].join(', ')}`);
|
|
@@ -56,6 +56,22 @@ export function saveRegistry(registry: Registry, registryPath: string = REGISTRY
|
|
|
56
56
|
* pointing to a different path, auto-suffixes (`api` → `api-2`, `api-3`, …).
|
|
57
57
|
* Re-registering the same path updates in place. Explicit names always overwrite.
|
|
58
58
|
*/
|
|
59
|
+
|
|
60
|
+
/** Find a unique suffixed name when the base name collides with a different path. */
|
|
61
|
+
function findAvailableName(
|
|
62
|
+
baseName: string,
|
|
63
|
+
absRoot: string,
|
|
64
|
+
repos: Record<string, RegistryEntry>,
|
|
65
|
+
): string {
|
|
66
|
+
let suffix = 2;
|
|
67
|
+
while (repos[`${baseName}-${suffix}`]) {
|
|
68
|
+
const entry = repos[`${baseName}-${suffix}`]!;
|
|
69
|
+
if (path.resolve(entry.path) === absRoot) return `${baseName}-${suffix}`;
|
|
70
|
+
suffix++;
|
|
71
|
+
}
|
|
72
|
+
return `${baseName}-${suffix}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
59
75
|
export function registerRepo(
|
|
60
76
|
rootDir: string,
|
|
61
77
|
name?: string,
|
|
@@ -71,20 +87,7 @@ export function registerRepo(
|
|
|
71
87
|
if (!name) {
|
|
72
88
|
const existing = registry.repos[baseName];
|
|
73
89
|
if (existing && path.resolve(existing.path) !== absRoot) {
|
|
74
|
-
|
|
75
|
-
let suffix = 2;
|
|
76
|
-
while (registry.repos[`${baseName}-${suffix}`]) {
|
|
77
|
-
const entry = registry.repos[`${baseName}-${suffix}`]!;
|
|
78
|
-
if (path.resolve(entry.path) === absRoot) {
|
|
79
|
-
// Already registered under this suffixed name — update in place
|
|
80
|
-
repoName = `${baseName}-${suffix}`;
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
suffix++;
|
|
84
|
-
}
|
|
85
|
-
if (repoName === baseName) {
|
|
86
|
-
repoName = `${baseName}-${suffix}`;
|
|
87
|
-
}
|
|
90
|
+
repoName = findAvailableName(baseName, absRoot, registry.repos);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
package/src/mcp/server.ts
CHANGED
|
@@ -109,6 +109,51 @@ function validateMultiRepoAccess(multiRepo: boolean, name: string, args: { repo?
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Register process-level shutdown and error handlers once per process.
|
|
114
|
+
* Ensures graceful cleanup when the MCP client disconnects or the transport
|
|
115
|
+
* encounters broken-pipe errors. Uses a globalThis flag to survive
|
|
116
|
+
* vi.resetModules() in tests.
|
|
117
|
+
*/
|
|
118
|
+
function registerShutdownHandlers(): void {
|
|
119
|
+
const g = globalThis as Record<string, unknown>;
|
|
120
|
+
if (g.__codegraph_shutdown_installed) return;
|
|
121
|
+
g.__codegraph_shutdown_installed = true;
|
|
122
|
+
|
|
123
|
+
const shutdown = async () => {
|
|
124
|
+
try {
|
|
125
|
+
await _activeServer?.close();
|
|
126
|
+
} catch (_shutdownErr: unknown) {
|
|
127
|
+
// Ignore close errors during shutdown — the transport may already be gone.
|
|
128
|
+
}
|
|
129
|
+
process.exit(0);
|
|
130
|
+
};
|
|
131
|
+
const silentExit = (err: Error & { code?: string }) => {
|
|
132
|
+
// Only suppress broken-pipe errors from closed stdio transport;
|
|
133
|
+
// let real bugs surface with a non-zero exit code.
|
|
134
|
+
if (err.code === 'EPIPE' || err.code === 'ERR_STREAM_DESTROYED') {
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
process.stderr.write(`Uncaught exception: ${err.stack ?? err.message}\n`);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
};
|
|
140
|
+
const silentReject = (reason: unknown) => {
|
|
141
|
+
const err = reason instanceof Error ? reason : new Error(String(reason));
|
|
142
|
+
const code = (err as Error & { code?: string }).code;
|
|
143
|
+
if (code === 'EPIPE' || code === 'ERR_STREAM_DESTROYED') {
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|
|
146
|
+
process.stderr.write(`Unhandled rejection: ${err.stack ?? err.message}\n`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
process.on('SIGINT', shutdown);
|
|
151
|
+
process.on('SIGTERM', shutdown);
|
|
152
|
+
process.on('SIGHUP', shutdown);
|
|
153
|
+
process.on('uncaughtException', silentExit);
|
|
154
|
+
process.on('unhandledRejection', silentReject);
|
|
155
|
+
}
|
|
156
|
+
|
|
112
157
|
export async function startMCPServer(
|
|
113
158
|
customDbPath?: string,
|
|
114
159
|
options: MCPServerOptionsInternal = {},
|
|
@@ -180,43 +225,7 @@ export async function startMCPServer(
|
|
|
180
225
|
// the latest instance (matters when tests call startMCPServer repeatedly).
|
|
181
226
|
_activeServer = server;
|
|
182
227
|
|
|
183
|
-
|
|
184
|
-
// Use a process-level flag so it survives vi.resetModules() in tests.
|
|
185
|
-
const g = globalThis as Record<string, unknown>;
|
|
186
|
-
if (!g.__codegraph_shutdown_installed) {
|
|
187
|
-
g.__codegraph_shutdown_installed = true;
|
|
188
|
-
|
|
189
|
-
const shutdown = async () => {
|
|
190
|
-
try {
|
|
191
|
-
await _activeServer?.close();
|
|
192
|
-
} catch {}
|
|
193
|
-
process.exit(0);
|
|
194
|
-
};
|
|
195
|
-
const silentExit = (err: Error & { code?: string }) => {
|
|
196
|
-
// Only suppress broken-pipe errors from closed stdio transport;
|
|
197
|
-
// let real bugs surface with a non-zero exit code.
|
|
198
|
-
if (err.code === 'EPIPE' || err.code === 'ERR_STREAM_DESTROYED') {
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
process.stderr.write(`Uncaught exception: ${err.stack ?? err.message}\n`);
|
|
202
|
-
process.exit(1);
|
|
203
|
-
};
|
|
204
|
-
const silentReject = (reason: unknown) => {
|
|
205
|
-
const err = reason instanceof Error ? reason : new Error(String(reason));
|
|
206
|
-
const code = (err as Error & { code?: string }).code;
|
|
207
|
-
if (code === 'EPIPE' || code === 'ERR_STREAM_DESTROYED') {
|
|
208
|
-
process.exit(0);
|
|
209
|
-
}
|
|
210
|
-
process.stderr.write(`Unhandled rejection: ${err.stack ?? err.message}\n`);
|
|
211
|
-
process.exit(1);
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
process.on('SIGINT', shutdown);
|
|
215
|
-
process.on('SIGTERM', shutdown);
|
|
216
|
-
process.on('SIGHUP', shutdown);
|
|
217
|
-
process.on('uncaughtException', silentExit);
|
|
218
|
-
process.on('unhandledRejection', silentReject);
|
|
219
|
-
}
|
|
228
|
+
registerShutdownHandlers();
|
|
220
229
|
|
|
221
230
|
try {
|
|
222
231
|
await server.connect(transport);
|