ts-knowledge-graph 0.1.1 → 0.1.4
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 +104 -43
- package/contribs/web_visualisation/README.md +83 -0
- package/contribs/web_visualisation/web/css/style.css +219 -0
- package/contribs/web_visualisation/web/data/.gitignore +3 -0
- package/contribs/web_visualisation/web/data/kind_descriptions.js +38 -0
- package/contribs/web_visualisation/web/index.html +74 -0
- package/contribs/web_visualisation/web/js/app.js +910 -0
- package/contribs/web_visualisation/web/tsconfig.json +18 -0
- package/contribs/web_visualisation/web/types/app_globals.d.ts +146 -0
- package/dist/benchmark/benchmark_stats.d.ts +41 -0
- package/dist/benchmark/benchmark_stats.d.ts.map +1 -0
- package/dist/benchmark/benchmark_stats.js +61 -0
- package/dist/benchmark/benchmark_stats.js.map +1 -0
- package/dist/benchmark/node_benchmark.d.ts +78 -0
- package/dist/benchmark/node_benchmark.d.ts.map +1 -0
- package/dist/benchmark/node_benchmark.js +112 -0
- package/dist/benchmark/node_benchmark.js.map +1 -0
- package/dist/cli.d.ts +0 -9
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +32 -208
- package/dist/cli.js.map +1 -1
- package/dist/commands/benchmark_command.d.ts +11 -0
- package/dist/commands/benchmark_command.d.ts.map +1 -0
- package/dist/commands/benchmark_command.js +91 -0
- package/dist/commands/benchmark_command.js.map +1 -0
- package/dist/commands/blast_radius_command.d.ts +5 -0
- package/dist/commands/blast_radius_command.d.ts.map +1 -0
- package/dist/commands/blast_radius_command.js +18 -0
- package/dist/commands/blast_radius_command.js.map +1 -0
- package/dist/commands/calls_command.d.ts +5 -0
- package/dist/commands/calls_command.d.ts.map +1 -0
- package/dist/commands/calls_command.js +7 -0
- package/dist/commands/calls_command.js.map +1 -0
- package/dist/commands/command_helpers.d.ts +15 -0
- package/dist/commands/command_helpers.d.ts.map +1 -0
- package/dist/commands/command_helpers.js +61 -0
- package/dist/commands/command_helpers.js.map +1 -0
- package/dist/commands/cost_command.d.ts +13 -0
- package/dist/commands/cost_command.d.ts.map +1 -0
- package/dist/commands/cost_command.js +122 -0
- package/dist/commands/cost_command.js.map +1 -0
- package/dist/commands/dead_exports_command.d.ts +5 -0
- package/dist/commands/dead_exports_command.d.ts.map +1 -0
- package/dist/commands/dead_exports_command.js +7 -0
- package/dist/commands/dead_exports_command.js.map +1 -0
- package/dist/commands/enrich_command.d.ts +7 -0
- package/dist/commands/enrich_command.d.ts.map +1 -0
- package/dist/commands/enrich_command.js +62 -0
- package/dist/commands/enrich_command.js.map +1 -0
- package/dist/commands/extract_command.d.ts +8 -0
- package/dist/commands/extract_command.d.ts.map +1 -0
- package/dist/commands/extract_command.js +49 -0
- package/dist/commands/extract_command.js.map +1 -0
- package/dist/commands/find_command.d.ts +5 -0
- package/dist/commands/find_command.d.ts.map +1 -0
- package/dist/commands/find_command.js +7 -0
- package/dist/commands/find_command.js.map +1 -0
- package/dist/commands/hotspots_command.d.ts +7 -0
- package/dist/commands/hotspots_command.d.ts.map +1 -0
- package/dist/commands/hotspots_command.js +67 -0
- package/dist/commands/hotspots_command.js.map +1 -0
- package/dist/commands/install_command.d.ts +15 -0
- package/dist/commands/install_command.d.ts.map +1 -0
- package/dist/commands/install_command.js +41 -0
- package/dist/commands/install_command.js.map +1 -0
- package/dist/commands/load_command.d.ts +6 -0
- package/dist/commands/load_command.d.ts.map +1 -0
- package/dist/commands/load_command.js +30 -0
- package/dist/commands/load_command.js.map +1 -0
- package/dist/commands/neighbors_command.d.ts +5 -0
- package/dist/commands/neighbors_command.d.ts.map +1 -0
- package/dist/commands/neighbors_command.js +17 -0
- package/dist/commands/neighbors_command.js.map +1 -0
- package/dist/commands/references_command.d.ts +5 -0
- package/dist/commands/references_command.d.ts.map +1 -0
- package/dist/commands/references_command.js +17 -0
- package/dist/commands/references_command.js.map +1 -0
- package/dist/commands/verify_command.d.ts +8 -0
- package/dist/commands/verify_command.d.ts.map +1 -0
- package/dist/commands/verify_command.js +57 -0
- package/dist/commands/verify_command.js.map +1 -0
- package/dist/commands/web_command.d.ts +46 -0
- package/dist/commands/web_command.d.ts.map +1 -0
- package/dist/commands/web_command.js +226 -0
- package/dist/commands/web_command.js.map +1 -0
- package/dist/commands/who_calls_command.d.ts +5 -0
- package/dist/commands/who_calls_command.d.ts.map +1 -0
- package/dist/commands/who_calls_command.js +7 -0
- package/dist/commands/who_calls_command.js.map +1 -0
- package/dist/enrich/cpu_profile.d.ts +127 -0
- package/dist/enrich/cpu_profile.d.ts.map +1 -0
- package/dist/enrich/cpu_profile.js +97 -0
- package/dist/enrich/cpu_profile.js.map +1 -0
- package/dist/enrich/runtime_enricher.d.ts +56 -0
- package/dist/enrich/runtime_enricher.d.ts.map +1 -0
- package/dist/enrich/runtime_enricher.js +80 -0
- package/dist/enrich/runtime_enricher.js.map +1 -0
- package/dist/enrich/runtime_join.d.ts +100 -0
- package/dist/enrich/runtime_join.d.ts.map +1 -0
- package/dist/enrich/runtime_join.js +227 -0
- package/dist/enrich/runtime_join.js.map +1 -0
- package/dist/extract/api_extractor.d.ts +24 -0
- package/dist/extract/api_extractor.d.ts.map +1 -0
- package/dist/extract/api_extractor.js +71 -0
- package/dist/extract/api_extractor.js.map +1 -0
- package/dist/extract/config_extractor.d.ts +22 -0
- package/dist/extract/config_extractor.d.ts.map +1 -0
- package/dist/extract/config_extractor.js +61 -0
- package/dist/extract/config_extractor.js.map +1 -0
- package/dist/extract/endpoint_extractor.d.ts +36 -0
- package/dist/extract/endpoint_extractor.d.ts.map +1 -0
- package/dist/extract/endpoint_extractor.js +117 -0
- package/dist/extract/endpoint_extractor.js.map +1 -0
- package/dist/extract/{graph-builder.d.ts → graph_builder.d.ts} +9 -1
- package/dist/extract/graph_builder.d.ts.map +1 -0
- package/dist/extract/graph_builder.js +61 -0
- package/dist/extract/graph_builder.js.map +1 -0
- package/dist/extract/node_id.d.ts +24 -0
- package/dist/extract/node_id.d.ts.map +1 -0
- package/dist/extract/node_id.js +44 -0
- package/dist/extract/node_id.js.map +1 -0
- package/dist/extract/{project-loader.d.ts → project_loader.d.ts} +1 -1
- package/dist/extract/project_loader.d.ts.map +1 -0
- package/dist/extract/{project-loader.js → project_loader.js} +1 -1
- package/dist/extract/{project-loader.js.map → project_loader.js.map} +1 -1
- package/dist/extract/scope_resolver.d.ts +22 -0
- package/dist/extract/scope_resolver.d.ts.map +1 -0
- package/dist/extract/scope_resolver.js +53 -0
- package/dist/extract/scope_resolver.js.map +1 -0
- package/dist/extract/semantic_extractor.d.ts +47 -0
- package/dist/extract/semantic_extractor.d.ts.map +1 -0
- package/dist/extract/{semantic-extractor.js → semantic_extractor.js} +98 -4
- package/dist/extract/semantic_extractor.js.map +1 -0
- package/dist/extract/{structural-extractor.d.ts → structural_extractor.d.ts} +7 -1
- package/dist/extract/{structural-extractor.d.ts.map → structural_extractor.d.ts.map} +1 -1
- package/dist/extract/{structural-extractor.js → structural_extractor.js} +24 -14
- package/dist/extract/structural_extractor.js.map +1 -0
- package/dist/project_root.d.ts +7 -0
- package/dist/project_root.d.ts.map +1 -0
- package/dist/project_root.js +9 -0
- package/dist/project_root.js.map +1 -0
- package/dist/query/graph_query.d.ts +262 -0
- package/dist/query/graph_query.d.ts.map +1 -0
- package/dist/query/graph_query.js +604 -0
- package/dist/query/graph_query.js.map +1 -0
- package/dist/schema/edge.d.ts +40 -5
- package/dist/schema/edge.d.ts.map +1 -1
- package/dist/schema/edge.js +70 -0
- package/dist/schema/edge.js.map +1 -1
- package/dist/schema/node.d.ts +20 -5
- package/dist/schema/node.d.ts.map +1 -1
- package/dist/schema/node.js +36 -0
- package/dist/schema/node.js.map +1 -1
- package/dist/schema/runtime_manifest.d.ts +36 -0
- package/dist/schema/runtime_manifest.d.ts.map +1 -0
- package/dist/schema/runtime_manifest.js +23 -0
- package/dist/schema/runtime_manifest.js.map +1 -0
- package/dist/store/{jsonl-reader.d.ts → jsonl_reader.d.ts} +1 -1
- package/dist/store/{jsonl-reader.d.ts.map → jsonl_reader.d.ts.map} +1 -1
- package/dist/store/{jsonl-reader.js → jsonl_reader.js} +1 -1
- package/dist/store/{jsonl-reader.js.map → jsonl_reader.js.map} +1 -1
- package/dist/store/{jsonl-store.d.ts → jsonl_store.d.ts} +1 -1
- package/dist/store/{jsonl-store.d.ts.map → jsonl_store.d.ts.map} +1 -1
- package/dist/store/{jsonl-store.js → jsonl_store.js} +1 -1
- package/dist/store/{jsonl-store.js.map → jsonl_store.js.map} +1 -1
- package/dist/store/kuzu_store.d.ts +66 -0
- package/dist/store/kuzu_store.d.ts.map +1 -0
- package/dist/store/kuzu_store.js +156 -0
- package/dist/store/kuzu_store.js.map +1 -0
- package/dist/verify/project_verifier.d.ts +85 -0
- package/dist/verify/project_verifier.d.ts.map +1 -0
- package/dist/verify/project_verifier.js +138 -0
- package/dist/verify/project_verifier.js.map +1 -0
- package/dotclaude_folder/skills/code-graph-query/SKILL.md +91 -0
- package/package.json +88 -5
- package/.env-sample +0 -34
- package/dist/agent/agent-tools.d.ts +0 -13
- package/dist/agent/agent-tools.d.ts.map +0 -1
- package/dist/agent/agent-tools.js +0 -153
- package/dist/agent/agent-tools.js.map +0 -1
- package/dist/agent/code-editor.d.ts +0 -18
- package/dist/agent/code-editor.d.ts.map +0 -1
- package/dist/agent/code-editor.js +0 -43
- package/dist/agent/code-editor.js.map +0 -1
- package/dist/agent/optimizer-agent.d.ts +0 -30
- package/dist/agent/optimizer-agent.d.ts.map +0 -1
- package/dist/agent/optimizer-agent.js +0 -97
- package/dist/agent/optimizer-agent.js.map +0 -1
- package/dist/agent/verifier.d.ts +0 -9
- package/dist/agent/verifier.d.ts.map +0 -1
- package/dist/agent/verifier.js +0 -19
- package/dist/agent/verifier.js.map +0 -1
- package/dist/extract/graph-builder.d.ts.map +0 -1
- package/dist/extract/graph-builder.js +0 -39
- package/dist/extract/graph-builder.js.map +0 -1
- package/dist/extract/node-id.d.ts +0 -8
- package/dist/extract/node-id.d.ts.map +0 -1
- package/dist/extract/node-id.js +0 -22
- package/dist/extract/node-id.js.map +0 -1
- package/dist/extract/project-loader.d.ts.map +0 -1
- package/dist/extract/semantic-extractor.d.ts +0 -22
- package/dist/extract/semantic-extractor.d.ts.map +0 -1
- package/dist/extract/semantic-extractor.js.map +0 -1
- package/dist/extract/structural-extractor.js.map +0 -1
- package/dist/query/graph-query.d.ts +0 -28
- package/dist/query/graph-query.d.ts.map +0 -1
- package/dist/query/graph-query.js +0 -93
- package/dist/query/graph-query.js.map +0 -1
- package/dist/store/kuzu-store.d.ts +0 -14
- package/dist/store/kuzu-store.d.ts.map +0 -1
- package/dist/store/kuzu-store.js +0 -52
- package/dist/store/kuzu-store.js.map +0 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
|
|
3
|
+
const METRICS = ['self-time', 'samples'];
|
|
4
|
+
const NO_RUNTIME_NOTICE = '! no runtime data in graph — run `enrich` first. Inclusive cost needs measured self cost to propagate.';
|
|
5
|
+
export class CostCommand {
|
|
6
|
+
static register(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('cost')
|
|
9
|
+
.description('propagate runtime self cost into inclusive cost and rank nodes by share of total')
|
|
10
|
+
.argument('[id]', 'node id to break down causally; omit to rank the whole graph')
|
|
11
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
12
|
+
.option('--by <metric>', `cost metric: ${METRICS.join(', ')}`, 'self-time')
|
|
13
|
+
.option('--limit <n>', 'maximum number of ranked nodes to return', '20')
|
|
14
|
+
.option('--json', 'emit raw JSON', false)
|
|
15
|
+
.action(async (id, options) => {
|
|
16
|
+
if (options.by !== undefined && METRICS.includes(options.by) === false) {
|
|
17
|
+
console.error(chalk.red(`unknown metric '${options.by}' — choose one of: ${METRICS.join(', ')}`));
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const by = options.by;
|
|
22
|
+
await CommandHelpers.withQuery(options.db, async (query) => {
|
|
23
|
+
if (id === undefined) {
|
|
24
|
+
const report = await query.costRanking({ by, limit: Number(options.limit) });
|
|
25
|
+
CostCommand.printRanking(report, options.json === true);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const attribution = await query.costAttribution(id, { by });
|
|
29
|
+
CostCommand.printAttribution(attribution, options.json === true);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
static printRanking(report, json) {
|
|
34
|
+
if (json === true) {
|
|
35
|
+
console.log(JSON.stringify(report, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (report.enriched === false) {
|
|
39
|
+
console.log(chalk.yellow(NO_RUNTIME_NOTICE));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const total = CostCommand.formatAmount(report.metric, report.totalSelf);
|
|
43
|
+
const coverage = CostCommand.formatCoverage(report.coverage);
|
|
44
|
+
console.log(chalk.bold(`Inclusive cost by ${report.metric}`) + chalk.gray(` (total self ${total} · coverage ${coverage})`));
|
|
45
|
+
if (report.nodes.length === 0) {
|
|
46
|
+
console.log(chalk.yellow('(no results)'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
report.nodes.forEach((node, index) => {
|
|
50
|
+
const rank = chalk.gray(`${String(index + 1).padStart(2)}.`);
|
|
51
|
+
const inclusive = chalk.cyan(CostCommand.formatAmount(report.metric, node.inclusiveCost).padStart(14));
|
|
52
|
+
const share = chalk.green(CostCommand.formatShare(node.shareOfTotal).padStart(7));
|
|
53
|
+
const mark = node.cyclic === true ? chalk.magenta(' ↺') : '';
|
|
54
|
+
console.log(`${rank} ${inclusive} ${share} ${chalk.gray(node.kind.padEnd(10))} ${chalk.bold(node.name)}${mark} ${chalk.gray(`${node.filePath}:${node.startLine}`)}`);
|
|
55
|
+
});
|
|
56
|
+
console.log(chalk.gray(`\n${report.nodes.length} node(s) · share is of total self cost · ↺ = in a call cycle`));
|
|
57
|
+
CostCommand.printCoverageHint(report.coverage, report.metric);
|
|
58
|
+
}
|
|
59
|
+
static printAttribution(attribution, json) {
|
|
60
|
+
if (json === true) {
|
|
61
|
+
console.log(JSON.stringify(attribution, null, 2));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (attribution.node === null) {
|
|
65
|
+
console.log(chalk.yellow('(no such node — resolve an id with `find` first)'));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (attribution.enriched === false) {
|
|
69
|
+
console.log(chalk.yellow(NO_RUNTIME_NOTICE));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const node = attribution.node;
|
|
73
|
+
const metric = attribution.metric;
|
|
74
|
+
console.log(chalk.bold(node.name) + chalk.gray(` ${node.kind} · ${node.filePath}:${node.startLine}`));
|
|
75
|
+
console.log(` self ${chalk.cyan(CostCommand.formatAmount(metric, node.selfCost))}`
|
|
76
|
+
+ ` · inclusive ${chalk.cyan(CostCommand.formatAmount(metric, node.inclusiveCost))}`
|
|
77
|
+
+ ` · share of total ${chalk.green(CostCommand.formatShare(node.shareOfTotal))}`);
|
|
78
|
+
const coverageLine = attribution.coverage === null
|
|
79
|
+
? 'graph coverage: unknown — re-run `enrich` to record it'
|
|
80
|
+
: `graph coverage: ${CostCommand.formatCoverage(attribution.coverage)} of profiled ${metric} is attributed to nodes`;
|
|
81
|
+
console.log(chalk.gray(` ${coverageLine}`));
|
|
82
|
+
if (node.cyclic === true) {
|
|
83
|
+
console.log(chalk.magenta(` ↺ part of a ${node.cycleSize}-node call cycle — inclusive cost is the cycle total, shared by its members`));
|
|
84
|
+
}
|
|
85
|
+
CostCommand.printFlows('Cost flows into (callees)', attribution.callees, metric, '->');
|
|
86
|
+
CostCommand.printFlows('Attributed to callers', attribution.callers, metric, '<-');
|
|
87
|
+
}
|
|
88
|
+
static printFlows(title, flows, metric, arrow) {
|
|
89
|
+
console.log(chalk.bold(`\n${title}`));
|
|
90
|
+
if (flows.length === 0) {
|
|
91
|
+
console.log(chalk.gray(' (none)'));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
for (const flow of flows) {
|
|
95
|
+
const amount = chalk.cyan(CostCommand.formatAmount(metric, flow.amount).padStart(14));
|
|
96
|
+
const share = chalk.green(CostCommand.formatShare(flow.share).padStart(7));
|
|
97
|
+
console.log(` ${chalk.gray(arrow)} ${amount} ${share} ${chalk.bold(flow.name)} ${chalk.gray(`${flow.filePath}:${flow.startLine}`)}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
static formatAmount(metric, value) {
|
|
101
|
+
const rounded = Math.round(value * 1000) / 1000;
|
|
102
|
+
return metric === 'self-time' ? `${rounded} ms` : `${rounded} samples`;
|
|
103
|
+
}
|
|
104
|
+
static formatShare(share) {
|
|
105
|
+
return `${(share * 100).toFixed(1)}%`;
|
|
106
|
+
}
|
|
107
|
+
static formatCoverage(coverage) {
|
|
108
|
+
return coverage === null ? 'unknown' : `${(coverage * 100).toFixed(0)}%`;
|
|
109
|
+
}
|
|
110
|
+
/** A one-line gloss under the ranking: what coverage means, or how to record it when missing. */
|
|
111
|
+
static printCoverageHint(coverage, metric) {
|
|
112
|
+
if (coverage === null) {
|
|
113
|
+
console.log(chalk.gray('coverage unknown — re-run `enrich` to record what fraction of the profile lands on the graph'));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const outsidePct = Math.round((1 - coverage) * 100);
|
|
117
|
+
if (outsidePct > 0) {
|
|
118
|
+
console.log(chalk.gray(`coverage = ${CostCommand.formatCoverage(coverage)} of profiled ${metric} attributed to the graph; ${outsidePct}% fell outside it (dropped by the join)`));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=cost_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost_command.js","sourceRoot":"","sources":["../../src/commands/cost_command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dead_exports_command.d.ts","sourceRoot":"","sources":["../../src/commands/dead_exports_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qBAAa,kBAAkB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAIvC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CommandHelpers } from './command_helpers.js';
|
|
2
|
+
export class DeadExportsCommand {
|
|
3
|
+
static register(program) {
|
|
4
|
+
CommandHelpers.registerSymbolQuery(program, 'dead-exports', '', 'list exported symbols with no inbound references', (query) => query.deadExports());
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=dead_exports_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dead_exports_command.js","sourceRoot":"","sources":["../../src/commands/dead_exports_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,kBAAkB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,cAAc,CAAC,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,EAAE,kDAAkD,EAAE,CAAC,KAAK,EAAE,EAAE,CAC7H,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACvB,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich_command.d.ts","sourceRoot":"","sources":["../../src/commands/enrich_command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,qBAAa,aAAa;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAalB,GAAG;IAaxB,OAAO,CAAC,MAAM,CAAC,KAAK;CAqCpB"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { RuntimeEnricher } from '../enrich/runtime_enricher.js';
|
|
5
|
+
import { KuzuStore } from '../store/kuzu_store.js';
|
|
6
|
+
import { DEFAULT_DB_PATH } from './command_helpers.js';
|
|
7
|
+
export class EnrichCommand {
|
|
8
|
+
static register(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('enrich')
|
|
11
|
+
.description('ingest a V8 CPU profile and attach runtime metrics onto graph nodes')
|
|
12
|
+
.argument('<profile>', 'path to a V8 .cpuprofile file (node --cpu-prof)')
|
|
13
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
14
|
+
.option('-r, --root <path>', 'project root the profile paths resolve against', process.cwd())
|
|
15
|
+
.option('--json', 'emit the enrichment report as JSON', false)
|
|
16
|
+
.action(async (profile, options) => {
|
|
17
|
+
await EnrichCommand.run(profile, options);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
static async run(profile, options) {
|
|
21
|
+
const profilePath = resolve(profile);
|
|
22
|
+
const profileText = await readFile(profilePath, 'utf8');
|
|
23
|
+
const store = new KuzuStore(resolve(options.db));
|
|
24
|
+
await store.initSchema();
|
|
25
|
+
try {
|
|
26
|
+
const report = await RuntimeEnricher.enrich(store, profileText, { root: resolve(options.root) });
|
|
27
|
+
EnrichCommand.print(report, options.json === true);
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await store.close();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
static print(report, json) {
|
|
34
|
+
if (json === true) {
|
|
35
|
+
console.log(JSON.stringify(report, null, 2));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const coverage = report.totalSamples > 0
|
|
39
|
+
? Math.round((report.matchedSamples / report.totalSamples) * 100)
|
|
40
|
+
: 0;
|
|
41
|
+
console.log(chalk.green(`✓ enriched ${report.matchedNodes} node(s) with metadata.runtime`));
|
|
42
|
+
console.log(` attributed ${chalk.bold(report.matchedSamples)} / ${report.totalSamples} samples (${coverage}%), ` +
|
|
43
|
+
`${chalk.bold(`${report.matchedSelfMs} ms`)} self time`);
|
|
44
|
+
console.log(` joined ${chalk.bold(report.matchedFrames)} frame(s): ` +
|
|
45
|
+
`${report.matchedByName} by name, ${report.matchedByRange} by range`);
|
|
46
|
+
console.log(` dropped ${chalk.bold(report.droppedFrames)} frame(s), ${report.droppedSamples} sample(s) — not in graph`);
|
|
47
|
+
if (report.hotspots.length > 0) {
|
|
48
|
+
console.log(chalk.bold('\nTop self time'));
|
|
49
|
+
for (const hotspot of report.hotspots.slice(0, 10)) {
|
|
50
|
+
console.log(` ${chalk.gray(`${hotspot.selfMs} ms`.padStart(10))} ${chalk.bold(hotspot.name)} ` +
|
|
51
|
+
`${chalk.gray(`(${hotspot.samples} samples)`)} ${chalk.gray(hotspot.filePath)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (report.dropped.length > 0) {
|
|
55
|
+
console.log(chalk.bold('\nTop unattributed'));
|
|
56
|
+
for (const group of report.dropped.slice(0, 5)) {
|
|
57
|
+
console.log(` ${chalk.gray(`${group.samples} samples`.padStart(12))} ${chalk.gray(group.label)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=enrich_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich_command.js","sourceRoot":"","sources":["../../src/commands/enrich_command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract_command.d.ts","sourceRoot":"","sources":["../../src/commands/extract_command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,qBAAa,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;IAkBxB,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B,OAAO,CAAC,MAAM,CAAC,OAAO;CAOtB"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { GraphBuilder } from '../extract/graph_builder.js';
|
|
4
|
+
import { ProjectLoader } from '../extract/project_loader.js';
|
|
5
|
+
import { JsonlStore } from '../store/jsonl_store.js';
|
|
6
|
+
import { DEFAULT_GRAPH_DIR } from './command_helpers.js';
|
|
7
|
+
export class ExtractCommand {
|
|
8
|
+
static register(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('extract')
|
|
11
|
+
.argument('<root>', 'path to the TypeScript project to parse')
|
|
12
|
+
.option('-o, --out <dir>', 'output directory for the JSONL graph', DEFAULT_GRAPH_DIR)
|
|
13
|
+
.option('--semantic', 'resolve heritage and CALLS edges (slower)', false)
|
|
14
|
+
.action(async (root, options) => {
|
|
15
|
+
await ExtractCommand.run(root, options);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
static async run(root, options) {
|
|
19
|
+
const rootPath = resolve(root);
|
|
20
|
+
const outPath = resolve(options.out);
|
|
21
|
+
console.log(chalk.cyan(`Loading project at ${rootPath} ...`));
|
|
22
|
+
const project = ProjectLoader.load(rootPath);
|
|
23
|
+
const builder = new GraphBuilder();
|
|
24
|
+
builder.build(project, rootPath, { semantic: options.semantic });
|
|
25
|
+
const nodes = builder.getNodes();
|
|
26
|
+
const edges = builder.getEdges();
|
|
27
|
+
await JsonlStore.write(outPath, nodes, edges);
|
|
28
|
+
console.log(chalk.green(`✓ ${nodes.length} nodes, ${edges.length} edges -> ${outPath}`));
|
|
29
|
+
ExtractCommand.printBreakdown(nodes, edges);
|
|
30
|
+
}
|
|
31
|
+
static printBreakdown(nodes, edges) {
|
|
32
|
+
console.log(chalk.bold('\nNodes'));
|
|
33
|
+
for (const [kind, count] of ExtractCommand.countBy(nodes.map((node) => node.kind))) {
|
|
34
|
+
console.log(` ${kind.padEnd(16)} ${count}`);
|
|
35
|
+
}
|
|
36
|
+
console.log(chalk.bold('\nEdges'));
|
|
37
|
+
for (const [kind, count] of ExtractCommand.countBy(edges.map((edge) => edge.kind))) {
|
|
38
|
+
console.log(` ${kind.padEnd(16)} ${count}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
static countBy(values) {
|
|
42
|
+
const counts = new Map();
|
|
43
|
+
for (const value of values) {
|
|
44
|
+
counts.set(value, (counts.get(value) ?? 0) + 1);
|
|
45
|
+
}
|
|
46
|
+
return [...counts.entries()].sort((a, b) => b[1] - a[1]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=extract_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract_command.js","sourceRoot":"","sources":["../../src/commands/extract_command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find_command.d.ts","sourceRoot":"","sources":["../../src/commands/find_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qBAAa,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAIvC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CommandHelpers } from './command_helpers.js';
|
|
2
|
+
export class FindCommand {
|
|
3
|
+
static register(program) {
|
|
4
|
+
CommandHelpers.registerSymbolQuery(program, 'find', '<pattern>', 'find symbols whose name contains <pattern>', (query, arg) => query.find(arg));
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=find_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find_command.js","sourceRoot":"","sources":["../../src/commands/find_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,cAAc,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAC7H,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACnB,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotspots_command.d.ts","sourceRoot":"","sources":["../../src/commands/hotspots_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,qBAAa,eAAe;IAC3B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IA0BvC,OAAO,CAAC,MAAM,CAAC,KAAK;IAsBpB,OAAO,CAAC,MAAM,CAAC,WAAW;CAe1B"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
|
|
3
|
+
const METRICS = ['self-time', 'samples', 'callers', 'call-count', 'blast-radius'];
|
|
4
|
+
export class HotspotsCommand {
|
|
5
|
+
static register(program) {
|
|
6
|
+
program
|
|
7
|
+
.command('hotspots')
|
|
8
|
+
.description('rank nodes by optimization leverage (runtime self-time, fan-in, call-count, or blast radius)')
|
|
9
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
10
|
+
.option('--by <metric>', `ranking metric: ${METRICS.join(', ')} (default: self-time when enriched, else callers)`)
|
|
11
|
+
.option('--limit <n>', 'maximum number of hotspots to return', '20')
|
|
12
|
+
.option('--measured-only', 'restrict ranking to nodes that carry runtime metrics', false)
|
|
13
|
+
.option('--json', 'emit raw JSON', false)
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
if (options.by !== undefined && METRICS.includes(options.by) === false) {
|
|
16
|
+
console.error(chalk.red(`unknown metric '${options.by}' — choose one of: ${METRICS.join(', ')}`));
|
|
17
|
+
process.exitCode = 1;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
await CommandHelpers.withQuery(options.db, async (query) => {
|
|
21
|
+
const report = await query.hotspots({
|
|
22
|
+
by: options.by,
|
|
23
|
+
limit: Number(options.limit),
|
|
24
|
+
measuredOnly: options.measuredOnly === true,
|
|
25
|
+
});
|
|
26
|
+
HotspotsCommand.print(report, options.json === true);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
static print(report, json) {
|
|
31
|
+
if (json === true) {
|
|
32
|
+
console.log(JSON.stringify(report, null, 2));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (report.fellBack === true) {
|
|
36
|
+
console.log(chalk.yellow('! no runtime data in graph — run `enrich` first. Ranking by `callers` (static fan-in) instead.'));
|
|
37
|
+
}
|
|
38
|
+
const scope = report.measuredOnly === true ? chalk.gray(' (measured nodes only)') : '';
|
|
39
|
+
console.log(chalk.bold(`Hotspots by ${report.metric}`) + scope);
|
|
40
|
+
if (report.hotspots.length === 0) {
|
|
41
|
+
console.log(chalk.yellow('(no results)'));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
report.hotspots.forEach((hotspot, index) => {
|
|
45
|
+
const rank = chalk.gray(`${String(index + 1).padStart(2)}.`);
|
|
46
|
+
const score = chalk.cyan(HotspotsCommand.formatScore(report.metric, hotspot.score).padStart(14));
|
|
47
|
+
console.log(`${rank} ${score} ${chalk.gray(hotspot.kind.padEnd(10))} ${chalk.bold(hotspot.name)} ${chalk.gray(`${hotspot.filePath}:${hotspot.startLine}`)}`);
|
|
48
|
+
});
|
|
49
|
+
console.log(chalk.gray(`\n${report.hotspots.length} hotspot(s)`));
|
|
50
|
+
}
|
|
51
|
+
static formatScore(metric, score) {
|
|
52
|
+
if (metric === 'self-time') {
|
|
53
|
+
return `${score} ms`;
|
|
54
|
+
}
|
|
55
|
+
if (metric === 'samples') {
|
|
56
|
+
return `${score} samples`;
|
|
57
|
+
}
|
|
58
|
+
if (metric === 'callers') {
|
|
59
|
+
return `${score} callers`;
|
|
60
|
+
}
|
|
61
|
+
if (metric === 'call-count') {
|
|
62
|
+
return `${score} calls`;
|
|
63
|
+
}
|
|
64
|
+
return `${score} impacted`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=hotspots_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotspots_command.js","sourceRoot":"","sources":["../../src/commands/hotspots_command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
/**
|
|
3
|
+
* Installs the bundled Claude Code skill into a target project so an agent can
|
|
4
|
+
* query the knowledge graph through the ts-knowledge-graph CLI.
|
|
5
|
+
*/
|
|
6
|
+
export declare class InstallCommand {
|
|
7
|
+
static register(program: Command): void;
|
|
8
|
+
private static run;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the bundled SKILL.md from the package root, which works whether
|
|
11
|
+
* running via tsx from `src` or from the built `dist` output.
|
|
12
|
+
*/
|
|
13
|
+
private static sourceSkillPath;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=install_command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install_command.d.ts","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC;;;GAGG;AACH,qBAAa,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;IAcxB;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;CAG9B"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { PROJECT_ROOT } from '../project_root.js';
|
|
5
|
+
const SKILL_SOURCE_PATH = 'dotclaude_folder/skills/code-graph-query/SKILL.md';
|
|
6
|
+
const SKILL_TARGET_PATH = 'skills/code-graph-query/SKILL.md';
|
|
7
|
+
/**
|
|
8
|
+
* Installs the bundled Claude Code skill into a target project so an agent can
|
|
9
|
+
* query the knowledge graph through the ts-knowledge-graph CLI.
|
|
10
|
+
*/
|
|
11
|
+
export class InstallCommand {
|
|
12
|
+
static register(program) {
|
|
13
|
+
program
|
|
14
|
+
.command('install')
|
|
15
|
+
.description('install the ts-knowledge-graph Claude Code skill into a project')
|
|
16
|
+
.argument('[destFolder]', 'project root to install the skill into', process.cwd())
|
|
17
|
+
.option('--force', 'overwrite an existing SKILL.md', false)
|
|
18
|
+
.action(async (destFolder, options) => {
|
|
19
|
+
await InstallCommand.run(destFolder, options);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
static async run(destFolder, options) {
|
|
23
|
+
const source = InstallCommand.sourceSkillPath();
|
|
24
|
+
const target = resolve(destFolder, SKILL_TARGET_PATH);
|
|
25
|
+
if (existsSync(target) === true && options.force === false) {
|
|
26
|
+
console.log(chalk.yellow(`✗ ${target} already exists — pass --force to overwrite`));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
30
|
+
copyFileSync(source, target);
|
|
31
|
+
console.log(chalk.green(`✓ installed skill -> ${target}`));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves the bundled SKILL.md from the package root, which works whether
|
|
35
|
+
* running via tsx from `src` or from the built `dist` output.
|
|
36
|
+
*/
|
|
37
|
+
static sourceSkillPath() {
|
|
38
|
+
return resolve(PROJECT_ROOT, SKILL_SOURCE_PATH);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=install_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install_command.js","sourceRoot":"","sources":["../../src/commands/install_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,iBAAiB,GAAG,mDAAmD,CAAC;AAC9E,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAM7D;;;GAGG;AACH,MAAM,OAAO,cAAc;IAC1B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,SAAS,CAAC;aAClB,WAAW,CAAC,iEAAiE,CAAC;aAC9E,QAAQ,CAAC,cAAc,EAAE,wCAAwC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;aACjF,MAAM,CAAC,SAAS,EAAE,gCAAgC,EAAE,KAAK,CAAC;aAC1D,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAAuB,EAAE,EAAE;YAC7D,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAkB,EAAE,OAAuB;QACnE,MAAM,MAAM,GAAG,cAAc,CAAC,eAAe,EAAE,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;QAEtD,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,MAAM,6CAA6C,CAAC,CAAC,CAAC;YACpF,OAAO;QACR,CAAC;QAED,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,eAAe;QAC7B,OAAO,OAAO,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;IACjD,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load_command.d.ts","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,qBAAa,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;mBAWlB,GAAG;CAWxB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { RUNTIME_MANIFEST_KEY } from '../schema/runtime_manifest.js';
|
|
4
|
+
import { JsonlReader } from '../store/jsonl_reader.js';
|
|
5
|
+
import { KuzuStore } from '../store/kuzu_store.js';
|
|
6
|
+
import { DEFAULT_DB_PATH, DEFAULT_GRAPH_DIR } from './command_helpers.js';
|
|
7
|
+
export class LoadCommand {
|
|
8
|
+
static register(program) {
|
|
9
|
+
program
|
|
10
|
+
.command('load')
|
|
11
|
+
.description('load a JSONL graph into an embedded Kùzu database')
|
|
12
|
+
.argument('[graphDir]', 'directory holding nodes.jsonl and edges.jsonl', DEFAULT_GRAPH_DIR)
|
|
13
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
14
|
+
.action(async (graphDir, options) => {
|
|
15
|
+
await LoadCommand.run(graphDir, options.db);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
static async run(graphDir, dbPath) {
|
|
19
|
+
const resolvedDb = resolve(dbPath);
|
|
20
|
+
console.log(chalk.cyan(`Loading ${resolve(graphDir)} into ${resolvedDb} ...`));
|
|
21
|
+
const { nodes, edges } = await JsonlReader.read(resolve(graphDir));
|
|
22
|
+
const store = new KuzuStore(resolvedDb);
|
|
23
|
+
await store.initSchema();
|
|
24
|
+
await store.load(nodes, edges);
|
|
25
|
+
await store.clearGraphMeta(RUNTIME_MANIFEST_KEY);
|
|
26
|
+
await store.close();
|
|
27
|
+
console.log(chalk.green(`✓ loaded ${nodes.length} nodes, ${edges.length} edges`));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=load_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load_command.js","sourceRoot":"","sources":["../../src/commands/load_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,MAAM,OAAO,WAAW;IACvB,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,MAAM,CAAC;aACf,WAAW,CAAC,mDAAmD,CAAC;aAChE,QAAQ,CAAC,YAAY,EAAE,+CAA+C,EAAE,iBAAiB,CAAC;aAC1F,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,OAAuB,EAAE,EAAE;YAC3D,MAAM,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,MAAc;QACxD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,CAAC,QAAQ,CAAC,SAAS,UAAU,MAAM,CAAC,CAAC,CAAC;QAC/E,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,MAAM,KAAK,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;QACjD,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,MAAM,WAAW,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC,CAAC;IACnF,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neighbors_command.d.ts","sourceRoot":"","sources":["../../src/commands/neighbors_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qBAAa,gBAAgB;IAC5B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAavC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
|
|
2
|
+
export class NeighborsCommand {
|
|
3
|
+
static register(program) {
|
|
4
|
+
program
|
|
5
|
+
.command('neighbors')
|
|
6
|
+
.description('show the one-hop neighbourhood of <id>')
|
|
7
|
+
.argument('<id>', 'node id to inspect')
|
|
8
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
9
|
+
.option('--json', 'emit raw JSON', false)
|
|
10
|
+
.action(async (id, options) => {
|
|
11
|
+
await CommandHelpers.withQuery(options.db, async (query) => {
|
|
12
|
+
CommandHelpers.printNeighbors(await query.neighborhood(id), options.json === true);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=neighbors_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"neighbors_command.js","sourceRoot":"","sources":["../../src/commands/neighbors_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AAErF,MAAM,OAAO,gBAAgB;IAC5B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,WAAW,CAAC;aACpB,WAAW,CAAC,wCAAwC,CAAC;aACrD,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;aACtC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACxC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAAqB,EAAE,EAAE;YACnD,MAAM,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1D,cAAc,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YACpF,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"references_command.d.ts","sourceRoot":"","sources":["../../src/commands/references_command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,qBAAa,iBAAiB;IAC7B,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAavC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommandHelpers, DEFAULT_DB_PATH } from './command_helpers.js';
|
|
2
|
+
export class ReferencesCommand {
|
|
3
|
+
static register(program) {
|
|
4
|
+
program
|
|
5
|
+
.command('references')
|
|
6
|
+
.description('list everything that references <id> (calls, type usage, heritage, new)')
|
|
7
|
+
.argument('<id>', 'node id to inspect')
|
|
8
|
+
.option('-d, --db <path>', 'Kùzu database path', DEFAULT_DB_PATH)
|
|
9
|
+
.option('--json', 'emit raw JSON', false)
|
|
10
|
+
.action(async (id, options) => {
|
|
11
|
+
await CommandHelpers.withQuery(options.db, async (query) => {
|
|
12
|
+
CommandHelpers.printNeighbors(await query.references(id), options.json === true);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=references_command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"references_command.js","sourceRoot":"","sources":["../../src/commands/references_command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AAErF,MAAM,OAAO,iBAAiB;IAC7B,MAAM,CAAC,QAAQ,CAAC,OAAgB;QAC/B,OAAO;aACL,OAAO,CAAC,YAAY,CAAC;aACrB,WAAW,CAAC,yEAAyE,CAAC;aACtF,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;aACtC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;aAChE,MAAM,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;aACxC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,OAAqB,EAAE,EAAE;YACnD,MAAM,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBAC1D,cAAc,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;YAClF,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACD"}
|