@grafema/cli 0.2.4-beta → 0.2.6-beta
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 +85 -0
- package/dist/cli.js +7 -2
- package/dist/cli.js.map +1 -0
- package/dist/commands/analyze.d.ts +3 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +8 -266
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/analyzeAction.d.ts +28 -0
- package/dist/commands/analyzeAction.d.ts.map +1 -0
- package/dist/commands/analyzeAction.js +243 -0
- package/dist/commands/analyzeAction.js.map +1 -0
- package/dist/commands/check.d.ts +2 -6
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +34 -48
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/context.d.ts +16 -0
- package/dist/commands/context.d.ts.map +1 -0
- package/dist/commands/context.js +238 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/coverage.js +1 -0
- package/dist/commands/coverage.js.map +1 -0
- package/dist/commands/doctor/checks.d.ts.map +1 -1
- package/dist/commands/doctor/checks.js +10 -6
- package/dist/commands/doctor/checks.js.map +1 -0
- package/dist/commands/doctor/output.js +1 -0
- package/dist/commands/doctor/output.js.map +1 -0
- package/dist/commands/doctor/types.js +1 -0
- package/dist/commands/doctor/types.js.map +1 -0
- package/dist/commands/doctor.js +1 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +5 -3
- package/dist/commands/explain.js.map +1 -0
- package/dist/commands/explore.d.ts.map +1 -1
- package/dist/commands/explore.js +9 -4
- package/dist/commands/explore.js.map +1 -0
- package/dist/commands/file.d.ts +15 -0
- package/dist/commands/file.d.ts.map +1 -0
- package/dist/commands/file.js +144 -0
- package/dist/commands/file.js.map +1 -0
- package/dist/commands/get.d.ts.map +1 -1
- package/dist/commands/get.js +7 -0
- package/dist/commands/get.js.map +1 -0
- package/dist/commands/impact.d.ts.map +1 -1
- package/dist/commands/impact.js +3 -3
- package/dist/commands/impact.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +20 -2
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/ls.d.ts.map +1 -1
- package/dist/commands/ls.js +10 -2
- package/dist/commands/ls.js.map +1 -0
- package/dist/commands/overview.d.ts.map +1 -1
- package/dist/commands/overview.js +1 -0
- package/dist/commands/overview.js.map +1 -0
- package/dist/commands/query.d.ts +8 -0
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +217 -43
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +4 -2
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/server.d.ts +2 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +76 -14
- package/dist/commands/server.js.map +1 -0
- package/dist/commands/setup-skill.d.ts +17 -0
- package/dist/commands/setup-skill.d.ts.map +1 -0
- package/dist/commands/setup-skill.js +131 -0
- package/dist/commands/setup-skill.js.map +1 -0
- package/dist/commands/stats.js +1 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/trace.d.ts.map +1 -1
- package/dist/commands/trace.js +21 -10
- package/dist/commands/trace.js.map +1 -0
- package/dist/commands/types.js +1 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/plugins/builtinPlugins.d.ts +10 -0
- package/dist/plugins/builtinPlugins.d.ts.map +1 -0
- package/dist/plugins/builtinPlugins.js +68 -0
- package/dist/plugins/builtinPlugins.js.map +1 -0
- package/dist/plugins/pluginLoader.d.ts +16 -0
- package/dist/plugins/pluginLoader.d.ts.map +1 -0
- package/dist/plugins/pluginLoader.js +101 -0
- package/dist/plugins/pluginLoader.js.map +1 -0
- package/dist/plugins/pluginResolver.js +38 -0
- package/dist/utils/codePreview.d.ts +1 -0
- package/dist/utils/codePreview.d.ts.map +1 -1
- package/dist/utils/codePreview.js +6 -3
- package/dist/utils/codePreview.js.map +1 -0
- package/dist/utils/errorFormatter.js +1 -0
- package/dist/utils/errorFormatter.js.map +1 -0
- package/dist/utils/formatNode.d.ts +1 -1
- package/dist/utils/formatNode.d.ts.map +1 -1
- package/dist/utils/formatNode.js +3 -2
- package/dist/utils/formatNode.js.map +1 -0
- package/dist/utils/pathUtils.d.ts +2 -0
- package/dist/utils/pathUtils.d.ts.map +1 -0
- package/dist/utils/pathUtils.js +9 -0
- package/dist/utils/pathUtils.js.map +1 -0
- package/dist/utils/progressRenderer.d.ts +119 -0
- package/dist/utils/progressRenderer.d.ts.map +1 -0
- package/dist/utils/progressRenderer.js +245 -0
- package/dist/utils/progressRenderer.js.map +1 -0
- package/dist/utils/spinner.d.ts +39 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +84 -0
- package/dist/utils/spinner.js.map +1 -0
- package/package.json +8 -9
- package/skills/grafema-codebase-analysis/SKILL.md +295 -0
- package/skills/grafema-codebase-analysis/references/node-edge-types.md +123 -0
- package/skills/grafema-codebase-analysis/references/query-patterns.md +205 -0
- package/src/cli.ts +8 -2
- package/src/commands/analyze.ts +7 -342
- package/src/commands/analyzeAction.ts +284 -0
- package/src/commands/check.ts +38 -70
- package/src/commands/context.ts +309 -0
- package/src/commands/doctor/checks.ts +9 -6
- package/src/commands/explain.ts +4 -3
- package/src/commands/explore.tsx +15 -9
- package/src/commands/file.ts +179 -0
- package/src/commands/get.ts +8 -0
- package/src/commands/impact.ts +3 -4
- package/src/commands/init.ts +19 -3
- package/src/commands/ls.ts +11 -2
- package/src/commands/overview.ts +0 -4
- package/src/commands/query.ts +235 -44
- package/src/commands/schema.ts +3 -2
- package/src/commands/server.ts +85 -15
- package/src/commands/setup-skill.ts +162 -0
- package/src/commands/trace.ts +18 -9
- package/src/plugins/builtinPlugins.ts +108 -0
- package/src/plugins/pluginLoader.ts +123 -0
- package/src/plugins/pluginResolver.js +38 -0
- package/src/utils/codePreview.ts +7 -3
- package/src/utils/formatNode.ts +3 -3
- package/src/utils/pathUtils.ts +9 -0
- package/src/utils/progressRenderer.ts +288 -0
- package/src/utils/spinner.ts +94 -0
package/README.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# @grafema/cli
|
|
2
|
+
|
|
3
|
+
> Grafema command-line interface for building and querying the code graph.
|
|
4
|
+
|
|
5
|
+
**Warning: This package is in beta stage and the API may change between minor versions.**
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx @grafema/cli init
|
|
11
|
+
npx @grafema/cli analyze
|
|
12
|
+
npx @grafema/cli overview
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### Project setup
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @grafema/cli init # Create .grafema/config.yaml
|
|
21
|
+
npx @grafema/cli analyze # Build the graph
|
|
22
|
+
npx @grafema/cli overview # Summary of nodes/edges found
|
|
23
|
+
npx @grafema/cli schema # List node and edge types
|
|
24
|
+
npx @grafema/cli types # List available node types
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Querying the graph
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx @grafema/cli query "auth" # Name search (partial match)
|
|
31
|
+
npx @grafema/cli query "function login" # Type + name
|
|
32
|
+
npx @grafema/cli query "route /api" # Route search
|
|
33
|
+
npx @grafema/cli query "token in authenticate" # Scope filtering
|
|
34
|
+
npx @grafema/cli query --type http:request "/api" # Exact type
|
|
35
|
+
npx @grafema/cli query --raw 'type(X, "FUNCTION")'
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Data flow tracing
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx @grafema/cli trace "userId" # Trace variable sources/sinks
|
|
42
|
+
npx @grafema/cli trace "userId from authenticate" # Scoped trace
|
|
43
|
+
npx @grafema/cli trace --to "addNode#0.type" # Sink-based trace
|
|
44
|
+
npx @grafema/cli trace --from-route "GET /status" # Route response trace
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Navigation helpers
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx @grafema/cli ls --type FUNCTION # List nodes by type
|
|
51
|
+
npx @grafema/cli get <semantic-id> # Get a single node by ID
|
|
52
|
+
npx @grafema/cli explain <node-id> # Explain a node (summary)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Checks & diagnostics
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx @grafema/cli check # Run all guarantees
|
|
59
|
+
npx @grafema/cli check dataflow # Run a diagnostic category
|
|
60
|
+
npx @grafema/cli check --list-categories
|
|
61
|
+
npx @grafema/cli doctor # Validate local setup
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Server management
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npx @grafema/cli server start # Start RFDB server
|
|
68
|
+
npx @grafema/cli server stop # Stop RFDB server
|
|
69
|
+
npx @grafema/cli server status # Check server status
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Misc
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx @grafema/cli coverage # Coverage stats
|
|
76
|
+
npx @grafema/cli impact # Impact analysis
|
|
77
|
+
npx @grafema/cli explore # Interactive explorer (TUI)
|
|
78
|
+
npx @grafema/cli analyze --log-file analysis.log # Log to file
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Notes
|
|
82
|
+
|
|
83
|
+
- All commands accept `--project <path>` to point at a specific repo.
|
|
84
|
+
- `npx @grafema/cli` works without global install and is preferred for docs/examples.
|
|
85
|
+
- Unknown Datalog predicates in `--raw` queries will show a warning with suggestions.
|
package/dist/cli.js
CHANGED
|
@@ -15,7 +15,7 @@ import { lsCommand } from './commands/ls.js';
|
|
|
15
15
|
import { getCommand } from './commands/get.js';
|
|
16
16
|
import { traceCommand } from './commands/trace.js';
|
|
17
17
|
import { impactCommand } from './commands/impact.js';
|
|
18
|
-
import {
|
|
18
|
+
import { contextCommand } from './commands/context.js';
|
|
19
19
|
import { statsCommand } from './commands/stats.js';
|
|
20
20
|
import { checkCommand } from './commands/check.js';
|
|
21
21
|
import { serverCommand } from './commands/server.js';
|
|
@@ -23,6 +23,8 @@ import { coverageCommand } from './commands/coverage.js';
|
|
|
23
23
|
import { doctorCommand } from './commands/doctor.js';
|
|
24
24
|
import { schemaCommand } from './commands/schema.js';
|
|
25
25
|
import { explainCommand } from './commands/explain.js';
|
|
26
|
+
import { fileCommand } from './commands/file.js';
|
|
27
|
+
import { setupSkillCommand } from './commands/setup-skill.js';
|
|
26
28
|
// Read version from package.json
|
|
27
29
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
30
|
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
@@ -36,12 +38,12 @@ program.addCommand(initCommand);
|
|
|
36
38
|
program.addCommand(analyzeCommand);
|
|
37
39
|
program.addCommand(overviewCommand);
|
|
38
40
|
program.addCommand(queryCommand);
|
|
41
|
+
program.addCommand(contextCommand);
|
|
39
42
|
program.addCommand(typesCommand);
|
|
40
43
|
program.addCommand(lsCommand);
|
|
41
44
|
program.addCommand(getCommand);
|
|
42
45
|
program.addCommand(traceCommand);
|
|
43
46
|
program.addCommand(impactCommand);
|
|
44
|
-
program.addCommand(exploreCommand);
|
|
45
47
|
program.addCommand(statsCommand); // Keep for backwards compat
|
|
46
48
|
program.addCommand(coverageCommand);
|
|
47
49
|
program.addCommand(checkCommand);
|
|
@@ -49,4 +51,7 @@ program.addCommand(serverCommand);
|
|
|
49
51
|
program.addCommand(doctorCommand);
|
|
50
52
|
program.addCommand(schemaCommand);
|
|
51
53
|
program.addCommand(explainCommand);
|
|
54
|
+
program.addCommand(fileCommand);
|
|
55
|
+
program.addCommand(setupSkillCommand);
|
|
52
56
|
program.parse();
|
|
57
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Analyze command
|
|
2
|
+
* Analyze command — Run project analysis via Orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Command definition only. Execution logic is in analyzeAction.ts.
|
|
3
5
|
*/
|
|
4
6
|
import { Command } from 'commander';
|
|
5
7
|
export declare const analyzeCommand: Command;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,cAAc,SA2BH,CAAC"}
|
package/dist/commands/analyze.js
CHANGED
|
@@ -1,129 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Analyze command
|
|
2
|
+
* Analyze command — Run project analysis via Orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Command definition only. Execution logic is in analyzeAction.ts.
|
|
3
5
|
*/
|
|
4
6
|
import { Command } from 'commander';
|
|
5
|
-
import {
|
|
6
|
-
import { existsSync, mkdirSync, readdirSync } from 'fs';
|
|
7
|
-
import { pathToFileURL } from 'url';
|
|
8
|
-
import { Orchestrator, RFDBServerBackend, DiagnosticReporter, DiagnosticWriter, createLogger, loadConfig,
|
|
9
|
-
// Discovery
|
|
10
|
-
SimpleProjectDiscovery, MonorepoServiceDiscovery, WorkspaceDiscovery,
|
|
11
|
-
// Indexing
|
|
12
|
-
JSModuleIndexer, RustModuleIndexer,
|
|
13
|
-
// Analysis
|
|
14
|
-
JSASTAnalyzer, ExpressRouteAnalyzer, ExpressResponseAnalyzer, SocketIOAnalyzer, DatabaseAnalyzer, FetchAnalyzer, ServiceLayerAnalyzer, ReactAnalyzer, RustAnalyzer,
|
|
15
|
-
// Enrichment
|
|
16
|
-
MethodCallResolver, ArgumentParameterLinker, AliasTracker, ValueDomainAnalyzer, MountPointResolver, PrefixEvaluator, InstanceOfResolver, ImportExportLinker, FunctionCallResolver, HTTPConnectionEnricher, RustFFIEnricher,
|
|
17
|
-
// Validation
|
|
18
|
-
CallResolverValidator, EvalBanValidator, SQLInjectionValidator, ShadowingDetector, GraphConnectivityValidator, DataFlowValidator, TypeScriptDeadCodeValidator, BrokenImportValidator, } from '@grafema/core';
|
|
19
|
-
const BUILTIN_PLUGINS = {
|
|
20
|
-
// Discovery
|
|
21
|
-
SimpleProjectDiscovery: () => new SimpleProjectDiscovery(),
|
|
22
|
-
MonorepoServiceDiscovery: () => new MonorepoServiceDiscovery(),
|
|
23
|
-
WorkspaceDiscovery: () => new WorkspaceDiscovery(),
|
|
24
|
-
// Indexing
|
|
25
|
-
JSModuleIndexer: () => new JSModuleIndexer(),
|
|
26
|
-
RustModuleIndexer: () => new RustModuleIndexer(),
|
|
27
|
-
// Analysis
|
|
28
|
-
JSASTAnalyzer: () => new JSASTAnalyzer(),
|
|
29
|
-
ExpressRouteAnalyzer: () => new ExpressRouteAnalyzer(),
|
|
30
|
-
ExpressResponseAnalyzer: () => new ExpressResponseAnalyzer(),
|
|
31
|
-
SocketIOAnalyzer: () => new SocketIOAnalyzer(),
|
|
32
|
-
DatabaseAnalyzer: () => new DatabaseAnalyzer(),
|
|
33
|
-
FetchAnalyzer: () => new FetchAnalyzer(),
|
|
34
|
-
ServiceLayerAnalyzer: () => new ServiceLayerAnalyzer(),
|
|
35
|
-
ReactAnalyzer: () => new ReactAnalyzer(),
|
|
36
|
-
RustAnalyzer: () => new RustAnalyzer(),
|
|
37
|
-
// Enrichment
|
|
38
|
-
MethodCallResolver: () => new MethodCallResolver(),
|
|
39
|
-
ArgumentParameterLinker: () => new ArgumentParameterLinker(),
|
|
40
|
-
AliasTracker: () => new AliasTracker(),
|
|
41
|
-
ValueDomainAnalyzer: () => new ValueDomainAnalyzer(),
|
|
42
|
-
MountPointResolver: () => new MountPointResolver(),
|
|
43
|
-
PrefixEvaluator: () => new PrefixEvaluator(),
|
|
44
|
-
InstanceOfResolver: () => new InstanceOfResolver(),
|
|
45
|
-
ImportExportLinker: () => new ImportExportLinker(),
|
|
46
|
-
FunctionCallResolver: () => new FunctionCallResolver(),
|
|
47
|
-
HTTPConnectionEnricher: () => new HTTPConnectionEnricher(),
|
|
48
|
-
RustFFIEnricher: () => new RustFFIEnricher(),
|
|
49
|
-
// Validation
|
|
50
|
-
CallResolverValidator: () => new CallResolverValidator(),
|
|
51
|
-
EvalBanValidator: () => new EvalBanValidator(),
|
|
52
|
-
SQLInjectionValidator: () => new SQLInjectionValidator(),
|
|
53
|
-
ShadowingDetector: () => new ShadowingDetector(),
|
|
54
|
-
GraphConnectivityValidator: () => new GraphConnectivityValidator(),
|
|
55
|
-
DataFlowValidator: () => new DataFlowValidator(),
|
|
56
|
-
TypeScriptDeadCodeValidator: () => new TypeScriptDeadCodeValidator(),
|
|
57
|
-
BrokenImportValidator: () => new BrokenImportValidator(),
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* Load custom plugins from .grafema/plugins/ directory
|
|
61
|
-
*/
|
|
62
|
-
async function loadCustomPlugins(projectPath, log) {
|
|
63
|
-
const pluginsDir = join(projectPath, '.grafema', 'plugins');
|
|
64
|
-
if (!existsSync(pluginsDir)) {
|
|
65
|
-
return {};
|
|
66
|
-
}
|
|
67
|
-
const customPlugins = {};
|
|
68
|
-
try {
|
|
69
|
-
const files = readdirSync(pluginsDir).filter((f) => f.endsWith('.js') || f.endsWith('.mjs'));
|
|
70
|
-
for (const file of files) {
|
|
71
|
-
try {
|
|
72
|
-
const pluginPath = join(pluginsDir, file);
|
|
73
|
-
const pluginUrl = pathToFileURL(pluginPath).href;
|
|
74
|
-
const module = await import(pluginUrl);
|
|
75
|
-
const PluginClass = module.default || module[file.replace(/\.(m?js)$/, '')];
|
|
76
|
-
if (PluginClass && typeof PluginClass === 'function') {
|
|
77
|
-
const pluginName = PluginClass.name || file.replace(/\.(m?js)$/, '');
|
|
78
|
-
customPlugins[pluginName] = () => new PluginClass();
|
|
79
|
-
log(`Loaded custom plugin: ${pluginName}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
console.warn(`Failed to load plugin ${file}: ${err.message}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
console.warn(`Error loading custom plugins: ${err.message}`);
|
|
89
|
-
}
|
|
90
|
-
return customPlugins;
|
|
91
|
-
}
|
|
92
|
-
function createPlugins(config, customPlugins = {}) {
|
|
93
|
-
const plugins = [];
|
|
94
|
-
const phases = ['discovery', 'indexing', 'analysis', 'enrichment', 'validation'];
|
|
95
|
-
for (const phase of phases) {
|
|
96
|
-
const names = config[phase] || [];
|
|
97
|
-
for (const name of names) {
|
|
98
|
-
// Check built-in first, then custom
|
|
99
|
-
const factory = BUILTIN_PLUGINS[name] || customPlugins[name];
|
|
100
|
-
if (factory) {
|
|
101
|
-
plugins.push(factory());
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
console.warn(`Unknown plugin: ${name}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return plugins;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Determine log level from CLI options.
|
|
112
|
-
* Priority: --log-level > --quiet > --verbose > default ('info')
|
|
113
|
-
*/
|
|
114
|
-
function getLogLevel(options) {
|
|
115
|
-
if (options.logLevel) {
|
|
116
|
-
const validLevels = ['silent', 'errors', 'warnings', 'info', 'debug'];
|
|
117
|
-
if (validLevels.includes(options.logLevel)) {
|
|
118
|
-
return options.logLevel;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (options.quiet)
|
|
122
|
-
return 'silent';
|
|
123
|
-
if (options.verbose)
|
|
124
|
-
return 'debug';
|
|
125
|
-
return 'info';
|
|
126
|
-
}
|
|
7
|
+
import { analyzeAction } from './analyzeAction.js';
|
|
127
8
|
export const analyzeCommand = new Command('analyze')
|
|
128
9
|
.description('Run project analysis')
|
|
129
10
|
.argument('[path]', 'Project path to analyze', '.')
|
|
@@ -134,6 +15,7 @@ export const analyzeCommand = new Command('analyze')
|
|
|
134
15
|
.option('-v, --verbose', 'Show verbose logging')
|
|
135
16
|
.option('--debug', 'Enable debug mode (writes diagnostics.log)')
|
|
136
17
|
.option('--log-level <level>', 'Set log level (silent, errors, warnings, info, debug)')
|
|
18
|
+
.option('--log-file <path>', 'Write all log output to a file')
|
|
137
19
|
.option('--strict', 'Enable strict mode (fail on unresolved references)')
|
|
138
20
|
.option('--auto-start', 'Auto-start RFDB server if not running')
|
|
139
21
|
.addHelpText('after', `
|
|
@@ -144,151 +26,11 @@ Examples:
|
|
|
144
26
|
grafema analyze -s api Analyze only "api" service (monorepo)
|
|
145
27
|
grafema analyze -v Verbose output with progress details
|
|
146
28
|
grafema analyze --debug Write diagnostics.log for debugging
|
|
29
|
+
grafema analyze --log-file out.log Write all logs to a file
|
|
147
30
|
grafema analyze --strict Fail on unresolved references (debugging)
|
|
148
31
|
grafema analyze --auto-start Auto-start server (useful for CI)
|
|
149
32
|
|
|
150
33
|
Note: Start the server first with: grafema server start
|
|
151
34
|
`)
|
|
152
|
-
.action(
|
|
153
|
-
|
|
154
|
-
const grafemaDir = join(projectPath, '.grafema');
|
|
155
|
-
const dbPath = join(grafemaDir, 'graph.rfdb');
|
|
156
|
-
if (!existsSync(grafemaDir)) {
|
|
157
|
-
mkdirSync(grafemaDir, { recursive: true });
|
|
158
|
-
}
|
|
159
|
-
const log = options.quiet ? () => { } : console.log;
|
|
160
|
-
// Create logger based on CLI flags
|
|
161
|
-
const logLevel = getLogLevel(options);
|
|
162
|
-
const logger = createLogger(logLevel);
|
|
163
|
-
log(`Analyzing project: ${projectPath}`);
|
|
164
|
-
// Connect to RFDB server
|
|
165
|
-
// Default: require explicit `grafema server start`
|
|
166
|
-
// Use --auto-start for CI or backwards compatibility
|
|
167
|
-
const backend = new RFDBServerBackend({
|
|
168
|
-
dbPath,
|
|
169
|
-
autoStart: options.autoStart ?? false
|
|
170
|
-
});
|
|
171
|
-
try {
|
|
172
|
-
await backend.connect();
|
|
173
|
-
}
|
|
174
|
-
catch (err) {
|
|
175
|
-
if (!options.autoStart && err instanceof Error && err.message.includes('not running')) {
|
|
176
|
-
console.error('');
|
|
177
|
-
console.error('RFDB server is not running.');
|
|
178
|
-
console.error('');
|
|
179
|
-
console.error('Start the server first:');
|
|
180
|
-
console.error(' grafema server start');
|
|
181
|
-
console.error('');
|
|
182
|
-
console.error('Or use --auto-start flag:');
|
|
183
|
-
console.error(' grafema analyze --auto-start');
|
|
184
|
-
console.error('');
|
|
185
|
-
process.exit(1);
|
|
186
|
-
}
|
|
187
|
-
throw err;
|
|
188
|
-
}
|
|
189
|
-
if (options.clear) {
|
|
190
|
-
log('Clearing existing database...');
|
|
191
|
-
await backend.clear();
|
|
192
|
-
}
|
|
193
|
-
const config = loadConfig(projectPath, logger);
|
|
194
|
-
// Extract services from config (REG-174)
|
|
195
|
-
if (config.services.length > 0) {
|
|
196
|
-
log(`Loaded ${config.services.length} service(s) from config`);
|
|
197
|
-
for (const svc of config.services) {
|
|
198
|
-
const entry = svc.entryPoint ? ` (entry: ${svc.entryPoint})` : '';
|
|
199
|
-
log(` - ${svc.name}: ${svc.path}${entry}`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
// Load custom plugins from .grafema/plugins/
|
|
203
|
-
const customPlugins = await loadCustomPlugins(projectPath, log);
|
|
204
|
-
const plugins = createPlugins(config.plugins, customPlugins);
|
|
205
|
-
log(`Loaded ${plugins.length} plugins`);
|
|
206
|
-
// Resolve strict mode: CLI flag overrides config
|
|
207
|
-
const strictMode = options.strict ?? config.strict ?? false;
|
|
208
|
-
if (strictMode) {
|
|
209
|
-
log('Strict mode enabled - analysis will fail on unresolved references');
|
|
210
|
-
}
|
|
211
|
-
const startTime = Date.now();
|
|
212
|
-
const orchestrator = new Orchestrator({
|
|
213
|
-
graph: backend,
|
|
214
|
-
plugins,
|
|
215
|
-
serviceFilter: options.service || null,
|
|
216
|
-
entrypoint: options.entrypoint,
|
|
217
|
-
forceAnalysis: options.clear || false,
|
|
218
|
-
logger,
|
|
219
|
-
services: config.services.length > 0 ? config.services : undefined, // Pass config services (REG-174)
|
|
220
|
-
strictMode, // REG-330: Pass strict mode flag
|
|
221
|
-
onProgress: (progress) => {
|
|
222
|
-
if (options.verbose) {
|
|
223
|
-
log(`[${progress.phase}] ${progress.message}`);
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
});
|
|
227
|
-
let exitCode = 0;
|
|
228
|
-
try {
|
|
229
|
-
await orchestrator.run(projectPath);
|
|
230
|
-
await backend.flush();
|
|
231
|
-
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
232
|
-
const stats = await backend.getStats();
|
|
233
|
-
log('');
|
|
234
|
-
log(`Analysis complete in ${elapsed}s`);
|
|
235
|
-
log(` Nodes: ${stats.nodeCount}`);
|
|
236
|
-
log(` Edges: ${stats.edgeCount}`);
|
|
237
|
-
// Get diagnostics and report summary
|
|
238
|
-
const diagnostics = orchestrator.getDiagnostics();
|
|
239
|
-
const reporter = new DiagnosticReporter(diagnostics);
|
|
240
|
-
// Print summary if there are any issues
|
|
241
|
-
if (diagnostics.count() > 0) {
|
|
242
|
-
log('');
|
|
243
|
-
log(reporter.categorizedSummary());
|
|
244
|
-
// In verbose mode, print full report
|
|
245
|
-
if (options.verbose) {
|
|
246
|
-
log('');
|
|
247
|
-
log(reporter.report({ format: 'text', includeSummary: false }));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
// Always write diagnostics.log (required for `grafema check` command)
|
|
251
|
-
const writer = new DiagnosticWriter();
|
|
252
|
-
await writer.write(diagnostics, grafemaDir);
|
|
253
|
-
if (options.debug) {
|
|
254
|
-
log(`Diagnostics written to ${writer.getLogPath(grafemaDir)}`);
|
|
255
|
-
}
|
|
256
|
-
// Determine exit code based on severity
|
|
257
|
-
if (diagnostics.hasFatal()) {
|
|
258
|
-
exitCode = 1;
|
|
259
|
-
}
|
|
260
|
-
else if (diagnostics.hasErrors()) {
|
|
261
|
-
exitCode = 2; // Completed with errors
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
exitCode = 0; // Success (maybe warnings)
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
catch (e) {
|
|
268
|
-
// Orchestrator threw (fatal error stopped analysis)
|
|
269
|
-
const error = e instanceof Error ? e : new Error(String(e));
|
|
270
|
-
const diagnostics = orchestrator.getDiagnostics();
|
|
271
|
-
const reporter = new DiagnosticReporter(diagnostics);
|
|
272
|
-
console.error('');
|
|
273
|
-
console.error(`✗ Analysis failed: ${error.message}`);
|
|
274
|
-
console.error('');
|
|
275
|
-
console.error('→ Run with --debug for detailed diagnostics');
|
|
276
|
-
if (diagnostics.count() > 0) {
|
|
277
|
-
console.error('');
|
|
278
|
-
console.error(reporter.report({ format: 'text', includeSummary: true }));
|
|
279
|
-
}
|
|
280
|
-
// Write diagnostics.log in debug mode even on failure
|
|
281
|
-
if (options.debug) {
|
|
282
|
-
const writer = new DiagnosticWriter();
|
|
283
|
-
await writer.write(diagnostics, grafemaDir);
|
|
284
|
-
console.error(`Diagnostics written to ${writer.getLogPath(grafemaDir)}`);
|
|
285
|
-
}
|
|
286
|
-
exitCode = 1;
|
|
287
|
-
}
|
|
288
|
-
await backend.close();
|
|
289
|
-
// Exit with appropriate code
|
|
290
|
-
// 0 = success, 1 = fatal, 2 = errors
|
|
291
|
-
if (exitCode !== 0) {
|
|
292
|
-
process.exit(exitCode);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
35
|
+
.action(analyzeAction);
|
|
36
|
+
//# sourceMappingURL=analyze.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,sBAAsB,CAAC;KACnC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,EAAE,GAAG,CAAC;KAClD,MAAM,CAAC,sBAAsB,EAAE,iCAAiC,CAAC;KACjE,MAAM,CAAC,yBAAyB,EAAE,+CAA+C,CAAC;KAClF,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAChE,MAAM,CAAC,aAAa,EAAE,0BAA0B,CAAC;KACjD,MAAM,CAAC,eAAe,EAAE,sBAAsB,CAAC;KAC/C,MAAM,CAAC,SAAS,EAAE,4CAA4C,CAAC;KAC/D,MAAM,CAAC,qBAAqB,EAAE,uDAAuD,CAAC;KACtF,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,CAAC;KAC7D,MAAM,CAAC,UAAU,EAAE,oDAAoD,CAAC;KACxE,MAAM,CAAC,cAAc,EAAE,uCAAuC,CAAC;KAC/D,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;CAavB,CAAC;KACC,MAAM,CAAC,aAAa,CAAC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze command action — connects to RFDB, loads plugins, runs Orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from analyze.ts (REG-435) to keep command definition separate
|
|
5
|
+
* from execution logic.
|
|
6
|
+
*/
|
|
7
|
+
export interface NodeEdgeCountBackend {
|
|
8
|
+
nodeCount: () => Promise<number>;
|
|
9
|
+
edgeCount: () => Promise<number>;
|
|
10
|
+
}
|
|
11
|
+
export declare function fetchNodeEdgeCounts(backend: NodeEdgeCountBackend): Promise<{
|
|
12
|
+
nodeCount: number;
|
|
13
|
+
edgeCount: number;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function exitWithCode(code: number, exitFn?: (code: number) => void): void;
|
|
16
|
+
export declare function analyzeAction(path: string, options: {
|
|
17
|
+
service?: string;
|
|
18
|
+
entrypoint?: string;
|
|
19
|
+
clear?: boolean;
|
|
20
|
+
quiet?: boolean;
|
|
21
|
+
verbose?: boolean;
|
|
22
|
+
debug?: boolean;
|
|
23
|
+
logLevel?: string;
|
|
24
|
+
logFile?: string;
|
|
25
|
+
strict?: boolean;
|
|
26
|
+
autoStart?: boolean;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=analyzeAction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeAction.d.ts","sourceRoot":"","sources":["../../src/commands/analyzeAction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAG1H;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAmB,GAAG,IAAI,CAE9F;AAqBD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoOrQ"}
|