@grafema/cli 0.2.5-beta → 0.2.7
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 +12 -0
- package/dist/cli.js +6 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts +3 -10
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +5 -347
- package/dist/commands/analyze.js.map +1 -1
- 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.js +2 -2
- package/dist/commands/check.js.map +1 -1
- 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/doctor/checks.js +1 -1
- package/dist/commands/doctor/checks.js.map +1 -1
- package/dist/commands/explain.d.ts.map +1 -1
- package/dist/commands/explain.js +4 -3
- package/dist/commands/explain.js.map +1 -1
- 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/impact.d.ts.map +1 -1
- package/dist/commands/impact.js +2 -3
- package/dist/commands/impact.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +13 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/ls.d.ts.map +1 -1
- package/dist/commands/ls.js +3 -2
- package/dist/commands/ls.js.map +1 -1
- package/dist/commands/query.d.ts +8 -0
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +158 -51
- package/dist/commands/query.js.map +1 -1
- package/dist/commands/schema.d.ts.map +1 -1
- package/dist/commands/schema.js +3 -2
- package/dist/commands/schema.js.map +1 -1
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +8 -59
- package/dist/commands/server.js.map +1 -1
- 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/trace.d.ts.map +1 -1
- package/dist/commands/trace.js +20 -10
- package/dist/commands/trace.js.map +1 -1
- 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 +5 -3
- package/dist/utils/codePreview.js.map +1 -1
- package/dist/utils/formatNode.d.ts +1 -1
- package/dist/utils/formatNode.d.ts.map +1 -1
- package/dist/utils/formatNode.js +2 -2
- package/dist/utils/formatNode.js.map +1 -1
- 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 +4 -0
- package/dist/utils/progressRenderer.d.ts.map +1 -1
- package/dist/utils/progressRenderer.js +23 -4
- package/dist/utils/progressRenderer.js.map +1 -1
- package/package.json +7 -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 +5 -435
- package/src/commands/analyzeAction.ts +284 -0
- package/src/commands/check.ts +2 -2
- package/src/commands/context.ts +309 -0
- package/src/commands/doctor/checks.ts +1 -1
- package/src/commands/explain.ts +4 -3
- package/src/commands/explore.tsx +7 -5
- package/src/commands/file.ts +179 -0
- package/src/commands/impact.ts +2 -3
- package/src/commands/init.ts +13 -1
- package/src/commands/ls.ts +3 -2
- package/src/commands/query.ts +167 -52
- package/src/commands/schema.ts +3 -2
- package/src/commands/server.ts +8 -64
- 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 +25 -4
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File command - Show structured overview of a file's entities and relationships
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Give a file-level summary with imports, exports, classes, functions,
|
|
5
|
+
* and their key relationships (calls, extends, assigned-from).
|
|
6
|
+
*
|
|
7
|
+
* This fills the gap between:
|
|
8
|
+
* - explain (lists ALL nodes flat, no relationships)
|
|
9
|
+
* - context (shows ONE node's full neighborhood)
|
|
10
|
+
*
|
|
11
|
+
* @see REG-412
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { Command } from 'commander';
|
|
15
|
+
import { resolve, join, relative, normalize } from 'path';
|
|
16
|
+
import { existsSync, realpathSync } from 'fs';
|
|
17
|
+
import { RFDBServerBackend, FileOverview } from '@grafema/core';
|
|
18
|
+
import type { FileOverviewResult, FunctionOverview } from '@grafema/core';
|
|
19
|
+
import { exitWithError } from '../utils/errorFormatter.js';
|
|
20
|
+
import { Spinner } from '../utils/spinner.js';
|
|
21
|
+
|
|
22
|
+
interface FileOptions {
|
|
23
|
+
project: string;
|
|
24
|
+
json?: boolean;
|
|
25
|
+
edges?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const fileCommand = new Command('file')
|
|
29
|
+
.description(
|
|
30
|
+
'Show structured overview of a file: imports, exports, classes, functions with relationships'
|
|
31
|
+
)
|
|
32
|
+
.argument('<path>', 'File path to analyze')
|
|
33
|
+
.option('-p, --project <path>', 'Project path', '.')
|
|
34
|
+
.option('-j, --json', 'Output as JSON')
|
|
35
|
+
.option('--no-edges', 'Skip edge resolution (faster, just list entities)')
|
|
36
|
+
.addHelpText('after', `
|
|
37
|
+
Examples:
|
|
38
|
+
grafema file src/app.ts Show file overview with relationships
|
|
39
|
+
grafema file src/app.ts --json Output as JSON for scripting
|
|
40
|
+
grafema file src/app.ts --no-edges Fast mode: just list entities
|
|
41
|
+
grafema file ./src/utils.js Works with relative paths
|
|
42
|
+
|
|
43
|
+
Output shows:
|
|
44
|
+
- Imports (module sources and specifiers)
|
|
45
|
+
- Exports (named and default)
|
|
46
|
+
- Classes with methods and their calls
|
|
47
|
+
- Functions with their calls
|
|
48
|
+
- Variables with assignment sources
|
|
49
|
+
|
|
50
|
+
Use 'grafema context <id>' to dive deeper into any specific entity.
|
|
51
|
+
`)
|
|
52
|
+
.action(async (file: string, options: FileOptions) => {
|
|
53
|
+
const projectPath = resolve(options.project);
|
|
54
|
+
const grafemaDir = join(projectPath, '.grafema');
|
|
55
|
+
const dbPath = join(grafemaDir, 'graph.rfdb');
|
|
56
|
+
|
|
57
|
+
if (!existsSync(dbPath)) {
|
|
58
|
+
exitWithError('No graph database found', [
|
|
59
|
+
'Run: grafema init && grafema analyze',
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Path resolution (same as explain command)
|
|
64
|
+
let filePath = file;
|
|
65
|
+
|
|
66
|
+
if (file.startsWith('./') || file.startsWith('../')) {
|
|
67
|
+
filePath = normalize(file).replace(/^\.\//, '');
|
|
68
|
+
} else if (resolve(file) === file) {
|
|
69
|
+
filePath = relative(projectPath, file);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const resolvedPath = resolve(projectPath, filePath);
|
|
73
|
+
if (!existsSync(resolvedPath)) {
|
|
74
|
+
exitWithError(`File not found: ${file}`, [
|
|
75
|
+
'Check the file path and try again',
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const absoluteFilePath = realpathSync(resolvedPath);
|
|
80
|
+
const relativeFilePath = relative(projectPath, absoluteFilePath);
|
|
81
|
+
|
|
82
|
+
const backend = new RFDBServerBackend({ dbPath });
|
|
83
|
+
await backend.connect();
|
|
84
|
+
|
|
85
|
+
const spinner = new Spinner('Loading file overview...');
|
|
86
|
+
spinner.start();
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const overview = new FileOverview(backend);
|
|
90
|
+
const result = await overview.getOverview(relativeFilePath, {
|
|
91
|
+
includeEdges: options.edges !== false,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
result.file = relativeFilePath;
|
|
95
|
+
|
|
96
|
+
spinner.stop();
|
|
97
|
+
|
|
98
|
+
if (options.json) {
|
|
99
|
+
console.log(JSON.stringify(result, null, 2));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
printFileOverview(result);
|
|
104
|
+
} finally {
|
|
105
|
+
spinner.stop();
|
|
106
|
+
await backend.close();
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
function printFileOverview(result: FileOverviewResult): void {
|
|
111
|
+
console.log(`Module: ${result.file}`);
|
|
112
|
+
|
|
113
|
+
if (result.status === 'NOT_ANALYZED') {
|
|
114
|
+
console.log('Status: NOT_ANALYZED');
|
|
115
|
+
console.log('');
|
|
116
|
+
console.log('This file has not been analyzed yet.');
|
|
117
|
+
console.log('Run: grafema analyze');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (result.imports.length > 0) {
|
|
122
|
+
const importSources = result.imports.map(i => i.source);
|
|
123
|
+
console.log(`Imports: ${importSources.join(', ')}`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (result.exports.length > 0) {
|
|
127
|
+
const exportNames = result.exports.map(e =>
|
|
128
|
+
e.isDefault ? `${e.name} (default)` : e.name
|
|
129
|
+
);
|
|
130
|
+
console.log(`Exports: ${exportNames.join(', ')}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (result.classes.length > 0) {
|
|
134
|
+
console.log('');
|
|
135
|
+
console.log('Classes:');
|
|
136
|
+
for (const cls of result.classes) {
|
|
137
|
+
const extendsStr = cls.extends ? ` extends ${cls.extends}` : '';
|
|
138
|
+
const lineStr = cls.line ? ` (line ${cls.line})` : '';
|
|
139
|
+
console.log(` ${cls.name}${extendsStr}${lineStr}`);
|
|
140
|
+
|
|
141
|
+
for (const method of cls.methods) {
|
|
142
|
+
printFunctionLine(method, ' ');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (result.functions.length > 0) {
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log('Functions:');
|
|
150
|
+
for (const fn of result.functions) {
|
|
151
|
+
printFunctionLine(fn, ' ');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (result.variables.length > 0) {
|
|
156
|
+
console.log('');
|
|
157
|
+
console.log('Variables:');
|
|
158
|
+
for (const v of result.variables) {
|
|
159
|
+
const lineStr = v.line ? `(line ${v.line})` : '';
|
|
160
|
+
const assignStr = v.assignedFrom ? ` = ${v.assignedFrom}` : '';
|
|
161
|
+
console.log(` ${v.kind} ${v.name}${assignStr} ${lineStr}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function printFunctionLine(fn: FunctionOverview, indent: string): void {
|
|
167
|
+
const asyncStr = fn.async ? 'async ' : '';
|
|
168
|
+
const paramsStr = fn.params ? `(${fn.params.join(', ')})` : '()';
|
|
169
|
+
const lineStr = fn.line ? `(line ${fn.line})` : '';
|
|
170
|
+
|
|
171
|
+
let callsStr = '';
|
|
172
|
+
if (fn.calls.length > 0) {
|
|
173
|
+
callsStr = ` -> ${fn.calls.join(', ')}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log(
|
|
177
|
+
`${indent}${asyncStr}${fn.name}${paramsStr}${callsStr} ${lineStr}`
|
|
178
|
+
);
|
|
179
|
+
}
|
package/src/commands/impact.ts
CHANGED
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { Command } from 'commander';
|
|
10
|
-
import { resolve, join, dirname } from 'path';
|
|
11
|
-
import { relative } from 'path';
|
|
10
|
+
import { isAbsolute, resolve, join, dirname, relative } from 'path';
|
|
12
11
|
import { existsSync } from 'fs';
|
|
13
12
|
import { RFDBServerBackend, findContainingFunction as findContainingFunctionCore } from '@grafema/core';
|
|
14
13
|
import { formatNodeDisplay, formatNodeInline } from '../utils/formatNode.js';
|
|
@@ -313,7 +312,7 @@ async function findCallsToNode(
|
|
|
313
312
|
*/
|
|
314
313
|
function getModulePath(file: string, projectPath: string): string {
|
|
315
314
|
if (!file) return '<unknown>';
|
|
316
|
-
const relPath = relative(projectPath, file);
|
|
315
|
+
const relPath = isAbsolute(file) ? relative(projectPath, file) : file;
|
|
317
316
|
const dir = dirname(relPath);
|
|
318
317
|
return dir === '.' ? relPath : `${dir}/*`;
|
|
319
318
|
}
|
package/src/commands/init.ts
CHANGED
|
@@ -9,7 +9,8 @@ import { spawn } from 'child_process';
|
|
|
9
9
|
import { createInterface } from 'readline';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import { stringify as stringifyYAML } from 'yaml';
|
|
12
|
-
import { DEFAULT_CONFIG } from '@grafema/core';
|
|
12
|
+
import { DEFAULT_CONFIG, GRAFEMA_VERSION, getSchemaVersion } from '@grafema/core';
|
|
13
|
+
import { installSkill } from './setup-skill.js';
|
|
13
14
|
|
|
14
15
|
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
15
16
|
|
|
@@ -20,6 +21,7 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
|
20
21
|
function generateConfigYAML(): string {
|
|
21
22
|
// Start with working default config
|
|
22
23
|
const config = {
|
|
24
|
+
version: getSchemaVersion(GRAFEMA_VERSION),
|
|
23
25
|
// Plugin list (fully implemented)
|
|
24
26
|
plugins: DEFAULT_CONFIG.plugins,
|
|
25
27
|
};
|
|
@@ -184,6 +186,16 @@ Examples:
|
|
|
184
186
|
}
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
// Auto-install Agent Skill for AI-assisted development
|
|
190
|
+
try {
|
|
191
|
+
const installed = installSkill(projectPath);
|
|
192
|
+
if (installed) {
|
|
193
|
+
console.log('✓ Installed Agent Skill (.claude/skills/grafema-codebase-analysis/)');
|
|
194
|
+
}
|
|
195
|
+
} catch {
|
|
196
|
+
// Non-critical — don't fail init if skill install fails
|
|
197
|
+
}
|
|
198
|
+
|
|
187
199
|
printNextSteps();
|
|
188
200
|
|
|
189
201
|
// Prompt to run analyze in interactive mode
|
package/src/commands/ls.ts
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { Command } from 'commander';
|
|
14
|
-
import { resolve, join
|
|
14
|
+
import { resolve, join } from 'path';
|
|
15
|
+
import { toRelativeDisplay } from '../utils/pathUtils.js';
|
|
15
16
|
import { existsSync } from 'fs';
|
|
16
17
|
import { RFDBServerBackend } from '@grafema/core';
|
|
17
18
|
import { exitWithError } from '../utils/errorFormatter.js';
|
|
@@ -142,7 +143,7 @@ Discover available types:
|
|
|
142
143
|
* Different types show different fields.
|
|
143
144
|
*/
|
|
144
145
|
function formatNodeForList(node: NodeInfo, nodeType: string, projectPath: string): string {
|
|
145
|
-
const relFile = node.file ?
|
|
146
|
+
const relFile = node.file ? toRelativeDisplay(node.file, projectPath) : '';
|
|
146
147
|
const loc = node.line ? `${relFile}:${node.line}` : relFile;
|
|
147
148
|
|
|
148
149
|
// HTTP routes: METHOD PATH (location)
|