code-kg 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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +100 -0
  3. package/dist/cli/index.d.ts +14 -0
  4. package/dist/cli/index.js +68 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/codekg-config.d.ts +14 -0
  7. package/dist/codekg-config.js +81 -0
  8. package/dist/codekg-config.js.map +1 -0
  9. package/dist/commands/graph.d.ts +7 -0
  10. package/dist/commands/graph.js +49 -0
  11. package/dist/commands/graph.js.map +1 -0
  12. package/dist/commands/init.d.ts +6 -0
  13. package/dist/commands/init.js +13 -0
  14. package/dist/commands/init.js.map +1 -0
  15. package/dist/commands/insights.d.ts +7 -0
  16. package/dist/commands/insights.js +31 -0
  17. package/dist/commands/insights.js.map +1 -0
  18. package/dist/commands/path.d.ts +7 -0
  19. package/dist/commands/path.js +47 -0
  20. package/dist/commands/path.js.map +1 -0
  21. package/dist/commands/reindex.d.ts +6 -0
  22. package/dist/commands/reindex.js +13 -0
  23. package/dist/commands/reindex.js.map +1 -0
  24. package/dist/commands/run.d.ts +6 -0
  25. package/dist/commands/run.js +20 -0
  26. package/dist/commands/run.js.map +1 -0
  27. package/dist/commands/serve.d.ts +8 -0
  28. package/dist/commands/serve.js +25 -0
  29. package/dist/commands/serve.js.map +1 -0
  30. package/dist/config/defaults.d.ts +6 -0
  31. package/dist/config/defaults.js +30 -0
  32. package/dist/config/defaults.js.map +1 -0
  33. package/dist/index.d.ts +52 -0
  34. package/dist/index.js +602 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/indexer/babel-fallback.d.ts +7 -0
  37. package/dist/indexer/babel-fallback.js +583 -0
  38. package/dist/indexer/babel-fallback.js.map +1 -0
  39. package/dist/indexer/file-discovery.d.ts +6 -0
  40. package/dist/indexer/file-discovery.js +106 -0
  41. package/dist/indexer/file-discovery.js.map +1 -0
  42. package/dist/indexer/indexer.d.ts +90 -0
  43. package/dist/indexer/indexer.js +620 -0
  44. package/dist/indexer/indexer.js.map +1 -0
  45. package/dist/indexer/metrics.d.ts +39 -0
  46. package/dist/indexer/metrics.js +147 -0
  47. package/dist/indexer/metrics.js.map +1 -0
  48. package/dist/indexer/structure-detector.d.ts +16 -0
  49. package/dist/indexer/structure-detector.js +159 -0
  50. package/dist/indexer/structure-detector.js.map +1 -0
  51. package/dist/indexer/ts-parser.d.ts +86 -0
  52. package/dist/indexer/ts-parser.js +437 -0
  53. package/dist/indexer/ts-parser.js.map +1 -0
  54. package/dist/model/edge.d.ts +21 -0
  55. package/dist/model/edge.js +25 -0
  56. package/dist/model/edge.js.map +1 -0
  57. package/dist/model/graph.d.ts +10 -0
  58. package/dist/model/graph.js +20 -0
  59. package/dist/model/graph.js.map +1 -0
  60. package/dist/model/node.d.ts +24 -0
  61. package/dist/model/node.js +22 -0
  62. package/dist/model/node.js.map +1 -0
  63. package/dist/query/query-dsl.d.ts +17 -0
  64. package/dist/query/query-dsl.js +75 -0
  65. package/dist/query/query-dsl.js.map +1 -0
  66. package/dist/query/query-engine.d.ts +32 -0
  67. package/dist/query/query-engine.js +126 -0
  68. package/dist/query/query-engine.js.map +1 -0
  69. package/dist/server/api.d.ts +19 -0
  70. package/dist/server/api.js +29 -0
  71. package/dist/server/api.js.map +1 -0
  72. package/dist/server/app.d.ts +7 -0
  73. package/dist/server/app.js +509 -0
  74. package/dist/server/app.js.map +1 -0
  75. package/dist/server/graph-controller.d.ts +147 -0
  76. package/dist/server/graph-controller.js +186 -0
  77. package/dist/server/graph-controller.js.map +1 -0
  78. package/dist/server/routes.d.ts +3 -0
  79. package/dist/server/routes.js +19 -0
  80. package/dist/server/routes.js.map +1 -0
  81. package/dist/server/ui.d.ts +1 -0
  82. package/dist/server/ui.js +1165 -0
  83. package/dist/server/ui.js.map +1 -0
  84. package/dist/store/sqlite-store.d.ts +83 -0
  85. package/dist/store/sqlite-store.js +647 -0
  86. package/dist/store/sqlite-store.js.map +1 -0
  87. package/dist/utils/ids.d.ts +2 -0
  88. package/dist/utils/ids.js +9 -0
  89. package/dist/utils/ids.js.map +1 -0
  90. package/dist/utils/path.d.ts +3 -0
  91. package/dist/utils/path.js +21 -0
  92. package/dist/utils/path.js.map +1 -0
  93. package/package.json +58 -0
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_EDGE_TYPES = exports.DEFAULT_NODE_TYPES = exports.DEFAULT_GRAPH_OUTPUT = exports.DEFAULT_CLI_NAME = void 0;
4
+ const edge_1 = require("../model/edge");
5
+ const node_1 = require("../model/node");
6
+ exports.DEFAULT_CLI_NAME = "codekg";
7
+ exports.DEFAULT_GRAPH_OUTPUT = "codekg.graph.json";
8
+ exports.DEFAULT_NODE_TYPES = [
9
+ node_1.NodeType.File,
10
+ node_1.NodeType.Directory,
11
+ node_1.NodeType.Function,
12
+ node_1.NodeType.Class,
13
+ node_1.NodeType.Interface,
14
+ node_1.NodeType.Variable,
15
+ node_1.NodeType.Route,
16
+ node_1.NodeType.EntryPoint
17
+ ];
18
+ exports.DEFAULT_EDGE_TYPES = [
19
+ edge_1.EdgeType.CONTAINS,
20
+ edge_1.EdgeType.IMPORTS,
21
+ edge_1.EdgeType.EXPORTS,
22
+ edge_1.EdgeType.DEFINES,
23
+ edge_1.EdgeType.REFERENCES,
24
+ edge_1.EdgeType.CALLS,
25
+ edge_1.EdgeType.EXTENDS,
26
+ edge_1.EdgeType.IMPLEMENTS,
27
+ edge_1.EdgeType.HANDLES_ROUTE,
28
+ edge_1.EdgeType.DEPENDS_ON
29
+ ];
30
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";;;AAAA,wCAAyC;AACzC,wCAAyC;AAE5B,QAAA,gBAAgB,GAAG,QAAQ,CAAC;AAC5B,QAAA,oBAAoB,GAAG,mBAAmB,CAAC;AAE3C,QAAA,kBAAkB,GAA4B;IACzD,eAAQ,CAAC,IAAI;IACb,eAAQ,CAAC,SAAS;IAClB,eAAQ,CAAC,QAAQ;IACjB,eAAQ,CAAC,KAAK;IACd,eAAQ,CAAC,SAAS;IAClB,eAAQ,CAAC,QAAQ;IACjB,eAAQ,CAAC,KAAK;IACd,eAAQ,CAAC,UAAU;CACpB,CAAC;AAEW,QAAA,kBAAkB,GAA4B;IACzD,eAAQ,CAAC,QAAQ;IACjB,eAAQ,CAAC,OAAO;IAChB,eAAQ,CAAC,OAAO;IAChB,eAAQ,CAAC,OAAO;IAChB,eAAQ,CAAC,UAAU;IACnB,eAAQ,CAAC,KAAK;IACd,eAAQ,CAAC,OAAO;IAChB,eAAQ,CAAC,UAAU;IACnB,eAAQ,CAAC,aAAa;IACtB,eAAQ,CAAC,UAAU;CACpB,CAAC"}
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ export declare function writeJsonOutput(value: unknown, outputPath?: string): Promise<void>;
3
+ export interface IndexCommandOptions {
4
+ path?: string;
5
+ }
6
+ export interface ServeCommandOptions extends IndexCommandOptions {
7
+ port: number;
8
+ }
9
+ export interface RunCommandOptions extends IndexCommandOptions {
10
+ port: number;
11
+ open?: boolean;
12
+ }
13
+ export interface InsightsCommandOptions extends IndexCommandOptions {
14
+ limit?: number;
15
+ output?: string;
16
+ }
17
+ export interface GraphCommandOptions extends IndexCommandOptions {
18
+ view?: string;
19
+ nodeTypes?: string[];
20
+ edgeTypes?: string[];
21
+ q?: string;
22
+ limit?: number;
23
+ output?: string;
24
+ }
25
+ export interface PathCommandOptions extends IndexCommandOptions {
26
+ from: string;
27
+ to: string;
28
+ maxDepth?: number;
29
+ edgeTypes?: string[];
30
+ output?: string;
31
+ }
32
+ export interface IndexResult {
33
+ projectRoot: string;
34
+ dbPath: string;
35
+ }
36
+ export interface ServeResult {
37
+ dbPath: string;
38
+ port: number;
39
+ }
40
+ export interface RunResult extends ServeResult {
41
+ projectRoot: string;
42
+ }
43
+ export declare function indexProjectToSqlite(projectRoot: string, dbPath: string): Promise<void>;
44
+ export declare function serveUsingDatabase(dbPath: string, port: number): Promise<void>;
45
+ export declare function runInit(options?: IndexCommandOptions): Promise<IndexResult>;
46
+ export declare function runReindex(options?: IndexCommandOptions): Promise<IndexResult>;
47
+ export declare function runServe(options: ServeCommandOptions): Promise<ServeResult>;
48
+ export declare function runDefault(options: RunCommandOptions): Promise<RunResult>;
49
+ export declare function runInsights(options?: InsightsCommandOptions): Promise<unknown>;
50
+ export declare function runGraphQuery(options?: GraphCommandOptions): Promise<unknown>;
51
+ export declare function runPathQuery(options: PathCommandOptions): Promise<unknown>;
52
+ export declare function main(argv?: string[]): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,602 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.writeJsonOutput = writeJsonOutput;
38
+ exports.indexProjectToSqlite = indexProjectToSqlite;
39
+ exports.serveUsingDatabase = serveUsingDatabase;
40
+ exports.runInit = runInit;
41
+ exports.runReindex = runReindex;
42
+ exports.runServe = runServe;
43
+ exports.runDefault = runDefault;
44
+ exports.runInsights = runInsights;
45
+ exports.runGraphQuery = runGraphQuery;
46
+ exports.runPathQuery = runPathQuery;
47
+ exports.main = main;
48
+ const node_child_process_1 = require("node:child_process");
49
+ const promises_1 = require("node:fs/promises");
50
+ const codekg_config_1 = require("./codekg-config");
51
+ const app_1 = require("./server/app");
52
+ const sqlite_store_1 = require("./store/sqlite-store");
53
+ const INDEXER_MODULE_CANDIDATES = [
54
+ "./indexer",
55
+ "./indexer.js",
56
+ "./indexer/index",
57
+ "./indexer/index.js",
58
+ "./indexer/indexer",
59
+ "./indexer/indexer.js",
60
+ "./application/indexer",
61
+ "./application/indexer.js",
62
+ "./core/indexer",
63
+ "./core/indexer.js",
64
+ ];
65
+ const INDEXER_EXPORT_CANDIDATES = [
66
+ "indexProject",
67
+ "runIndexer",
68
+ "indexCodebase",
69
+ "buildCodeGraph",
70
+ "buildGraph",
71
+ ];
72
+ const MAX_RESULT_WINDOW = 1_000_000;
73
+ function asRecord(value) {
74
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
75
+ return undefined;
76
+ }
77
+ return value;
78
+ }
79
+ function asString(value) {
80
+ return typeof value === "string" && value.trim().length > 0 ? value : undefined;
81
+ }
82
+ function asProps(value) {
83
+ const record = asRecord(value);
84
+ return record ?? {};
85
+ }
86
+ function readFunction(moduleRecord, exportNames) {
87
+ for (const exportName of exportNames) {
88
+ const direct = moduleRecord[exportName];
89
+ if (typeof direct === "function") {
90
+ return direct;
91
+ }
92
+ }
93
+ const defaultExport = moduleRecord.default;
94
+ if (typeof defaultExport === "function") {
95
+ return defaultExport;
96
+ }
97
+ const defaultRecord = asRecord(defaultExport);
98
+ if (!defaultRecord) {
99
+ return undefined;
100
+ }
101
+ for (const exportName of exportNames) {
102
+ const candidate = defaultRecord[exportName];
103
+ if (typeof candidate === "function") {
104
+ return candidate;
105
+ }
106
+ }
107
+ return undefined;
108
+ }
109
+ async function importFirstAvailable(candidates, label) {
110
+ let lastError;
111
+ for (const candidate of candidates) {
112
+ try {
113
+ return (await Promise.resolve(`${candidate}`).then(s => __importStar(require(s))));
114
+ }
115
+ catch (error) {
116
+ const nodeError = error;
117
+ if (nodeError.code !== "ERR_MODULE_NOT_FOUND" && nodeError.code !== "MODULE_NOT_FOUND") {
118
+ throw error;
119
+ }
120
+ lastError = error;
121
+ }
122
+ }
123
+ const suffix = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
124
+ throw new Error(`Unable to import ${label}. Tried: ${candidates.join(", ")}.${suffix}`);
125
+ }
126
+ function toQueryNode(value, index) {
127
+ const record = asRecord(value);
128
+ if (!record) {
129
+ return null;
130
+ }
131
+ const id = asString(record.id);
132
+ const type = asString(record.type);
133
+ if (!id || !type) {
134
+ return null;
135
+ }
136
+ const rawName = asString(record.name);
137
+ const rawPath = asString(record.path);
138
+ const props = asProps(record.props ?? record.json_props);
139
+ return {
140
+ id,
141
+ type,
142
+ name: rawName ?? `node_${index}`,
143
+ path: rawPath ?? null,
144
+ props,
145
+ };
146
+ }
147
+ function toQueryEdge(value, index) {
148
+ const record = asRecord(value);
149
+ if (!record) {
150
+ return null;
151
+ }
152
+ const id = asString(record.id) ?? `edge_${index}`;
153
+ const fromId = asString(record.fromId) ??
154
+ asString(record.from_id) ??
155
+ asString(record.from) ??
156
+ asString(record.source);
157
+ const toId = asString(record.toId) ??
158
+ asString(record.to_id) ??
159
+ asString(record.to) ??
160
+ asString(record.target);
161
+ const type = asString(record.type);
162
+ if (!fromId || !toId || !type) {
163
+ return null;
164
+ }
165
+ const props = asProps(record.props ?? record.json_props);
166
+ return {
167
+ id,
168
+ fromId,
169
+ toId,
170
+ type,
171
+ props,
172
+ };
173
+ }
174
+ function selectGraphPayload(payload) {
175
+ const root = asRecord(payload);
176
+ if (!root) {
177
+ return payload;
178
+ }
179
+ if (Array.isArray(root.nodes) && Array.isArray(root.edges)) {
180
+ return root;
181
+ }
182
+ for (const key of ["graph", "snapshot", "data", "result"]) {
183
+ const nested = asRecord(root[key]);
184
+ if (nested && Array.isArray(nested.nodes) && Array.isArray(nested.edges)) {
185
+ return nested;
186
+ }
187
+ }
188
+ return payload;
189
+ }
190
+ function normalizeGraphSnapshot(rawGraph) {
191
+ const payload = asRecord(selectGraphPayload(rawGraph));
192
+ const rawNodes = payload && Array.isArray(payload.nodes) ? payload.nodes : [];
193
+ const rawEdges = payload && Array.isArray(payload.edges) ? payload.edges : [];
194
+ const nodes = rawNodes
195
+ .map((value, index) => toQueryNode(value, index))
196
+ .filter((node) => Boolean(node));
197
+ const edges = rawEdges
198
+ .map((value, index) => toQueryEdge(value, index))
199
+ .filter((edge) => Boolean(edge));
200
+ return { nodes, edges };
201
+ }
202
+ function asGraphNode(node) {
203
+ return {
204
+ id: node.id,
205
+ type: node.type,
206
+ name: node.name ?? node.id,
207
+ path: node.path ?? undefined,
208
+ props: node.props,
209
+ };
210
+ }
211
+ function asGraphEdge(edge) {
212
+ return {
213
+ id: edge.id,
214
+ from: edge.fromId,
215
+ to: edge.toId,
216
+ type: edge.type,
217
+ props: edge.props,
218
+ };
219
+ }
220
+ function collectAllNodes(store) {
221
+ return store.searchNodes("", MAX_RESULT_WINDOW);
222
+ }
223
+ function collectAllEdges(store, nodes) {
224
+ const edgeById = new Map();
225
+ for (const node of nodes) {
226
+ for (const edge of store.getOutgoingEdges(node.id)) {
227
+ edgeById.set(edge.id, edge);
228
+ }
229
+ }
230
+ return [...edgeById.values()];
231
+ }
232
+ function normalizeRouteDependencies(value) {
233
+ if (!Array.isArray(value)) {
234
+ return [];
235
+ }
236
+ return value.filter((item) => typeof item === "string");
237
+ }
238
+ function createRouteMap(routes) {
239
+ return routes.map((routeNode) => {
240
+ const method = asString(routeNode.props.method)?.toUpperCase() ?? "GET";
241
+ const routePath = asString(routeNode.props.routePath) ??
242
+ asString(routeNode.props.path) ??
243
+ routeNode.path ??
244
+ routeNode.name ??
245
+ routeNode.id;
246
+ return {
247
+ id: routeNode.id,
248
+ method,
249
+ path: routePath,
250
+ handler: asString(routeNode.props.handler) ?? routeNode.name ?? routeNode.id,
251
+ file: routeNode.path ?? undefined,
252
+ dependencies: normalizeRouteDependencies(routeNode.props.dependencies),
253
+ };
254
+ });
255
+ }
256
+ function computeSeverity(size) {
257
+ if (size >= 5) {
258
+ return "high";
259
+ }
260
+ if (size >= 3) {
261
+ return "medium";
262
+ }
263
+ return "low";
264
+ }
265
+ function createGraphQueryEngine(store) {
266
+ return {
267
+ async getMeta() {
268
+ const nodes = collectAllNodes(store);
269
+ const edges = collectAllEdges(store, nodes);
270
+ const routeCount = store.getRoutes().length;
271
+ const fileCount = nodes.filter((node) => node.type.toLowerCase() === "file").length;
272
+ const symbolCount = nodes.filter((node) => ["function", "class", "interface", "variable"].includes(node.type.toLowerCase())).length;
273
+ const insights = store.getRefactorInsights(5);
274
+ return {
275
+ project: "codekg",
276
+ version: "0.1.0",
277
+ generatedAt: new Date().toISOString(),
278
+ counts: {
279
+ nodes: nodes.length,
280
+ edges: edges.length,
281
+ files: fileCount,
282
+ symbols: symbolCount,
283
+ routes: routeCount,
284
+ },
285
+ hotspots: insights.hotspots,
286
+ };
287
+ },
288
+ async search(query) {
289
+ const nodes = store.searchNodes(query, 50);
290
+ return {
291
+ query,
292
+ results: nodes.map((node) => ({
293
+ nodeId: node.id,
294
+ type: node.type,
295
+ name: node.name ?? node.id,
296
+ path: node.path ?? undefined,
297
+ score: 1,
298
+ })),
299
+ };
300
+ },
301
+ async getNode(id) {
302
+ const node = store.getNodeById(id);
303
+ if (!node) {
304
+ return null;
305
+ }
306
+ const inbound = store.getIncomingEdges(id).map(asGraphEdge);
307
+ const outbound = store.getOutgoingEdges(id).map(asGraphEdge);
308
+ return {
309
+ node: asGraphNode(node),
310
+ inbound,
311
+ outbound,
312
+ };
313
+ },
314
+ async getGraph(options) {
315
+ const graph = store.getGraph({
316
+ view: options.view,
317
+ nodeTypes: options.nodeTypes,
318
+ edgeTypes: options.edgeTypes,
319
+ q: options.q,
320
+ limit: options.limit,
321
+ });
322
+ const view = options.view || "fileDeps";
323
+ return {
324
+ view,
325
+ nodes: graph.nodes.map(asGraphNode),
326
+ edges: graph.edges.map(asGraphEdge),
327
+ };
328
+ },
329
+ async getSubgraph(seed, depth, direction) {
330
+ const graph = store.getSubgraph(seed, depth, direction);
331
+ return {
332
+ seed,
333
+ depth,
334
+ direction,
335
+ nodes: graph.nodes.map(asGraphNode),
336
+ edges: graph.edges.map(asGraphEdge),
337
+ };
338
+ },
339
+ async getPath(from, to, maxDepth, edgeTypes) {
340
+ const result = store.findShortestPath(from, to, maxDepth, edgeTypes);
341
+ return {
342
+ from: result.from,
343
+ to: result.to,
344
+ maxDepth: result.maxDepth,
345
+ found: result.found,
346
+ length: result.length,
347
+ nodeIds: result.nodeIds,
348
+ edgeIds: result.edgeIds,
349
+ nodes: result.nodes.map(asGraphNode),
350
+ edges: result.edges.map(asGraphEdge),
351
+ };
352
+ },
353
+ async getRoutes() {
354
+ return {
355
+ routes: createRouteMap(store.getRoutes()),
356
+ };
357
+ },
358
+ async getCycles() {
359
+ const cycleInfo = store.getCycles();
360
+ return {
361
+ cycles: cycleInfo.cycles.map((cycle, index) => {
362
+ const nodeIds = cycle.nodes.map((node) => node.id);
363
+ return {
364
+ id: `cycle:${index + 1}`,
365
+ nodes: nodeIds,
366
+ size: nodeIds.length,
367
+ severity: computeSeverity(nodeIds.length),
368
+ };
369
+ }),
370
+ };
371
+ },
372
+ async runQuery(query) {
373
+ if (typeof query.type === "string" && query.type === "path") {
374
+ const from = asString(query.from);
375
+ const to = asString(query.to);
376
+ const maxDepth = typeof query.maxDepth === "number" ? Math.max(1, Math.floor(query.maxDepth)) : 12;
377
+ const edgeTypes = Array.isArray(query.edgeTypes) && query.edgeTypes.every((entry) => typeof entry === "string")
378
+ ? query.edgeTypes
379
+ : undefined;
380
+ if (!from || !to) {
381
+ throw new Error("Path query requires `from` and `to`.");
382
+ }
383
+ return {
384
+ query,
385
+ result: store.findShortestPath(from, to, maxDepth, edgeTypes),
386
+ };
387
+ }
388
+ if (typeof query.type === "string" && query.type === "refactorInsights") {
389
+ const rawLimit = query.limit;
390
+ const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit)
391
+ ? Math.max(1, Math.min(50, Math.floor(rawLimit)))
392
+ : 5;
393
+ return {
394
+ query,
395
+ result: store.getRefactorInsights(limit),
396
+ };
397
+ }
398
+ return {
399
+ query,
400
+ result: store.runQuery(query),
401
+ };
402
+ },
403
+ };
404
+ }
405
+ async function loadIndexerRunner() {
406
+ const moduleRecord = await importFirstAvailable(INDEXER_MODULE_CANDIDATES, "indexer module");
407
+ const runner = readFunction(moduleRecord, INDEXER_EXPORT_CANDIDATES);
408
+ if (!runner) {
409
+ throw new Error(`Indexer module loaded, but no supported export was found. Expected one of: ${INDEXER_EXPORT_CANDIDATES.join(", ")}.`);
410
+ }
411
+ return runner;
412
+ }
413
+ async function runIndexer(projectRoot) {
414
+ const runner = await loadIndexerRunner();
415
+ try {
416
+ const rawGraph = await runner(projectRoot);
417
+ return normalizeGraphSnapshot(rawGraph);
418
+ }
419
+ catch (error) {
420
+ if (!(error instanceof TypeError)) {
421
+ throw error;
422
+ }
423
+ }
424
+ const fallbackGraph = await runner({ path: projectRoot, rootPath: projectRoot, projectRoot });
425
+ return normalizeGraphSnapshot(fallbackGraph);
426
+ }
427
+ async function persistIndexedGraph(projectRoot, dbPath) {
428
+ const snapshot = await runIndexer(projectRoot);
429
+ const store = new sqlite_store_1.SqliteStore(dbPath);
430
+ try {
431
+ store.initSchema();
432
+ store.replaceGraph(snapshot);
433
+ }
434
+ finally {
435
+ store.close();
436
+ }
437
+ }
438
+ async function listenOnPort(app, port) {
439
+ return await new Promise((resolve, reject) => {
440
+ const server = app.listen(port, () => resolve(server));
441
+ server.once("error", reject);
442
+ });
443
+ }
444
+ function attachStoreCleanup(server, store) {
445
+ let closed = false;
446
+ const closeStore = () => {
447
+ if (closed) {
448
+ return;
449
+ }
450
+ closed = true;
451
+ store.close();
452
+ };
453
+ server.once("close", closeStore);
454
+ process.once("exit", closeStore);
455
+ }
456
+ function openInBrowser(url) {
457
+ const platform = process.platform;
458
+ if (platform === "darwin") {
459
+ const child = (0, node_child_process_1.spawn)("open", [url], { stdio: "ignore", detached: true });
460
+ child.unref();
461
+ return;
462
+ }
463
+ if (platform === "win32") {
464
+ const child = (0, node_child_process_1.spawn)("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true });
465
+ child.unref();
466
+ return;
467
+ }
468
+ const child = (0, node_child_process_1.spawn)("xdg-open", [url], { stdio: "ignore", detached: true });
469
+ child.unref();
470
+ }
471
+ async function writeJsonOutput(value, outputPath) {
472
+ const serialized = `${JSON.stringify(value, null, 2)}\n`;
473
+ if (outputPath && outputPath.trim().length > 0) {
474
+ await (0, promises_1.writeFile)(outputPath, serialized, "utf8");
475
+ return;
476
+ }
477
+ process.stdout.write(serialized);
478
+ }
479
+ async function indexProjectToSqlite(projectRoot, dbPath) {
480
+ await persistIndexedGraph(projectRoot, dbPath);
481
+ }
482
+ async function serveUsingDatabase(dbPath, port) {
483
+ const store = new sqlite_store_1.SqliteStore(dbPath);
484
+ store.initSchema();
485
+ const app = (0, app_1.createApp)({ engine: createGraphQueryEngine(store) });
486
+ const server = await listenOnPort(app, port);
487
+ attachStoreCleanup(server, store);
488
+ }
489
+ async function runInit(options = {}) {
490
+ const { projectRoot, resolvedDbPath } = await (0, codekg_config_1.loadOrCreateCodekgConfig)(options.path ?? ".");
491
+ await (0, codekg_config_1.ensureDbDirectory)(resolvedDbPath);
492
+ await persistIndexedGraph(projectRoot, resolvedDbPath);
493
+ return { projectRoot, dbPath: resolvedDbPath };
494
+ }
495
+ async function runReindex(options = {}) {
496
+ const { projectRoot, resolvedDbPath } = await (0, codekg_config_1.loadOrCreateCodekgConfig)(options.path ?? ".");
497
+ await (0, codekg_config_1.ensureDbDirectory)(resolvedDbPath);
498
+ await persistIndexedGraph(projectRoot, resolvedDbPath);
499
+ return { projectRoot, dbPath: resolvedDbPath };
500
+ }
501
+ async function runServe(options) {
502
+ const { resolvedDbPath } = await (0, codekg_config_1.loadOrCreateCodekgConfig)(options.path ?? ".");
503
+ await serveUsingDatabase(resolvedDbPath, options.port);
504
+ return { dbPath: resolvedDbPath, port: options.port };
505
+ }
506
+ async function runDefault(options) {
507
+ const initResult = await runInit({ path: options.path });
508
+ const port = options.port;
509
+ await serveUsingDatabase(initResult.dbPath, port);
510
+ const uiUrl = `http://localhost:${port}`;
511
+ if (options.open) {
512
+ try {
513
+ openInBrowser(uiUrl);
514
+ }
515
+ catch {
516
+ // Best effort only.
517
+ }
518
+ }
519
+ process.stdout.write(`CodeKG UI: ${uiUrl}\n`);
520
+ process.stdout.write(`Graph DB: ${initResult.dbPath}\n`);
521
+ return {
522
+ projectRoot: initResult.projectRoot,
523
+ dbPath: initResult.dbPath,
524
+ port,
525
+ };
526
+ }
527
+ async function withReadOnlyStore(projectPath, handler) {
528
+ const { resolvedDbPath } = await (0, codekg_config_1.loadOrCreateCodekgConfig)(projectPath ?? ".");
529
+ const store = new sqlite_store_1.SqliteStore(resolvedDbPath);
530
+ try {
531
+ store.initSchema();
532
+ return await handler(store, resolvedDbPath);
533
+ }
534
+ finally {
535
+ store.close();
536
+ }
537
+ }
538
+ async function runInsights(options = {}) {
539
+ const limit = typeof options.limit === "number" ? Math.max(1, Math.floor(options.limit)) : 5;
540
+ return await withReadOnlyStore(options.path, async (store, dbPath) => ({
541
+ dbPath,
542
+ generatedAt: new Date().toISOString(),
543
+ result: store.getRefactorInsights(limit),
544
+ }));
545
+ }
546
+ async function runGraphQuery(options = {}) {
547
+ const view = options.view ?? "fileDeps";
548
+ return await withReadOnlyStore(options.path, async (store, dbPath) => {
549
+ const graph = store.getGraph({
550
+ view,
551
+ nodeTypes: options.nodeTypes,
552
+ edgeTypes: options.edgeTypes,
553
+ q: options.q,
554
+ limit: options.limit,
555
+ });
556
+ return {
557
+ dbPath,
558
+ generatedAt: new Date().toISOString(),
559
+ view,
560
+ filters: {
561
+ nodeTypes: options.nodeTypes ?? [],
562
+ edgeTypes: options.edgeTypes ?? [],
563
+ q: options.q ?? "",
564
+ limit: options.limit ?? 0,
565
+ },
566
+ nodes: graph.nodes,
567
+ edges: graph.edges,
568
+ };
569
+ });
570
+ }
571
+ async function runPathQuery(options) {
572
+ const maxDepth = typeof options.maxDepth === "number" ? Math.max(1, Math.floor(options.maxDepth)) : 12;
573
+ return await withReadOnlyStore(options.path, async (store, dbPath) => {
574
+ const pathResult = store.findShortestPath(options.from, options.to, maxDepth, options.edgeTypes);
575
+ return {
576
+ dbPath,
577
+ generatedAt: new Date().toISOString(),
578
+ result: pathResult,
579
+ };
580
+ });
581
+ }
582
+ async function main(argv = process.argv) {
583
+ const { runCli } = await Promise.resolve().then(() => __importStar(require("./cli/index.js")));
584
+ await runCli(argv, {
585
+ runInit,
586
+ runReindex,
587
+ runServe,
588
+ runDefault,
589
+ runInsights,
590
+ runGraphQuery,
591
+ runPathQuery,
592
+ writeJsonOutput,
593
+ });
594
+ }
595
+ if (typeof require !== "undefined" && require.main === module) {
596
+ void main().catch((error) => {
597
+ const message = error instanceof Error ? error.message : String(error);
598
+ process.stderr.write(`${message}\n`);
599
+ process.exitCode = 1;
600
+ });
601
+ }
602
+ //# sourceMappingURL=index.js.map