@grafema/cli 0.2.0-beta → 0.2.2-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/dist/cli.js +7 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +41 -4
- package/package.json +3 -3
- package/src/cli.ts +8 -1
- package/src/commands/analyze.ts +53 -4
package/dist/cli.js
CHANGED
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
* @grafema/cli - CLI for Grafema code analysis toolkit
|
|
4
4
|
*/
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
+
import { readFileSync } from 'fs';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
6
9
|
import { initCommand } from './commands/init.js';
|
|
7
10
|
import { analyzeCommand } from './commands/analyze.js';
|
|
8
11
|
import { overviewCommand } from './commands/overview.js';
|
|
@@ -20,11 +23,14 @@ import { coverageCommand } from './commands/coverage.js';
|
|
|
20
23
|
import { doctorCommand } from './commands/doctor.js';
|
|
21
24
|
import { schemaCommand } from './commands/schema.js';
|
|
22
25
|
import { explainCommand } from './commands/explain.js';
|
|
26
|
+
// Read version from package.json
|
|
27
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
23
29
|
const program = new Command();
|
|
24
30
|
program
|
|
25
31
|
.name('grafema')
|
|
26
32
|
.description('Grafema code analysis CLI')
|
|
27
|
-
.version(
|
|
33
|
+
.version(pkg.version);
|
|
28
34
|
// Commands in logical order
|
|
29
35
|
program.addCommand(initCommand);
|
|
30
36
|
program.addCommand(analyzeCommand);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/commands/analyze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgLpC,eAAO,MAAM,cAAc,SAqKvB,CAAC"}
|
package/dist/commands/analyze.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Command } from 'commander';
|
|
5
5
|
import { resolve, join } from 'path';
|
|
6
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
6
|
+
import { existsSync, mkdirSync, readdirSync } from 'fs';
|
|
7
|
+
import { pathToFileURL } from 'url';
|
|
7
8
|
import { Orchestrator, RFDBServerBackend, DiagnosticReporter, DiagnosticWriter, createLogger, loadConfig,
|
|
8
9
|
// Discovery
|
|
9
10
|
SimpleProjectDiscovery, MonorepoServiceDiscovery, WorkspaceDiscovery,
|
|
@@ -55,13 +56,47 @@ const BUILTIN_PLUGINS = {
|
|
|
55
56
|
TypeScriptDeadCodeValidator: () => new TypeScriptDeadCodeValidator(),
|
|
56
57
|
BrokenImportValidator: () => new BrokenImportValidator(),
|
|
57
58
|
};
|
|
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 = {}) {
|
|
59
93
|
const plugins = [];
|
|
60
94
|
const phases = ['discovery', 'indexing', 'analysis', 'enrichment', 'validation'];
|
|
61
95
|
for (const phase of phases) {
|
|
62
96
|
const names = config[phase] || [];
|
|
63
97
|
for (const name of names) {
|
|
64
|
-
|
|
98
|
+
// Check built-in first, then custom
|
|
99
|
+
const factory = BUILTIN_PLUGINS[name] || customPlugins[name];
|
|
65
100
|
if (factory) {
|
|
66
101
|
plugins.push(factory());
|
|
67
102
|
}
|
|
@@ -137,7 +172,9 @@ Examples:
|
|
|
137
172
|
log(` - ${svc.name}: ${svc.path}${entry}`);
|
|
138
173
|
}
|
|
139
174
|
}
|
|
140
|
-
|
|
175
|
+
// Load custom plugins from .grafema/plugins/
|
|
176
|
+
const customPlugins = await loadCustomPlugins(projectPath, log);
|
|
177
|
+
const plugins = createPlugins(config.plugins, customPlugins);
|
|
141
178
|
log(`Loaded ${plugins.length} plugins`);
|
|
142
179
|
// Resolve strict mode: CLI flag overrides config
|
|
143
180
|
const strictMode = options.strict ?? config.strict ?? false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafema/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2-beta",
|
|
4
4
|
"description": "CLI for Grafema code analysis toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli.js",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"ink-text-input": "^6.0.0",
|
|
38
38
|
"react": "^19.2.3",
|
|
39
39
|
"yaml": "^2.8.2",
|
|
40
|
-
"@grafema/core": "0.2.
|
|
41
|
-
"@grafema/types": "0.2.
|
|
40
|
+
"@grafema/core": "0.2.1-beta",
|
|
41
|
+
"@grafema/types": "0.2.1-beta"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^25.0.8",
|
package/src/cli.ts
CHANGED
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Command } from 'commander';
|
|
7
|
+
import { readFileSync } from 'fs';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
7
10
|
import { initCommand } from './commands/init.js';
|
|
8
11
|
import { analyzeCommand } from './commands/analyze.js';
|
|
9
12
|
import { overviewCommand } from './commands/overview.js';
|
|
@@ -22,12 +25,16 @@ import { doctorCommand } from './commands/doctor.js';
|
|
|
22
25
|
import { schemaCommand } from './commands/schema.js';
|
|
23
26
|
import { explainCommand } from './commands/explain.js';
|
|
24
27
|
|
|
28
|
+
// Read version from package.json
|
|
29
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
31
|
+
|
|
25
32
|
const program = new Command();
|
|
26
33
|
|
|
27
34
|
program
|
|
28
35
|
.name('grafema')
|
|
29
36
|
.description('Grafema code analysis CLI')
|
|
30
|
-
.version(
|
|
37
|
+
.version(pkg.version);
|
|
31
38
|
|
|
32
39
|
// Commands in logical order
|
|
33
40
|
program.addCommand(initCommand);
|
package/src/commands/analyze.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
import { resolve, join } from 'path';
|
|
7
|
-
import { existsSync, mkdirSync } from 'fs';
|
|
7
|
+
import { existsSync, mkdirSync, readdirSync } from 'fs';
|
|
8
|
+
import { pathToFileURL } from 'url';
|
|
8
9
|
import {
|
|
9
10
|
Orchestrator,
|
|
10
11
|
RFDBServerBackend,
|
|
@@ -96,14 +97,60 @@ const BUILTIN_PLUGINS: Record<string, () => Plugin> = {
|
|
|
96
97
|
BrokenImportValidator: () => new BrokenImportValidator() as Plugin,
|
|
97
98
|
};
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Load custom plugins from .grafema/plugins/ directory
|
|
102
|
+
*/
|
|
103
|
+
async function loadCustomPlugins(
|
|
104
|
+
projectPath: string,
|
|
105
|
+
log: (msg: string) => void
|
|
106
|
+
): Promise<Record<string, () => Plugin>> {
|
|
107
|
+
const pluginsDir = join(projectPath, '.grafema', 'plugins');
|
|
108
|
+
if (!existsSync(pluginsDir)) {
|
|
109
|
+
return {};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const customPlugins: Record<string, () => Plugin> = {};
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const files = readdirSync(pluginsDir).filter(
|
|
116
|
+
(f) => f.endsWith('.js') || f.endsWith('.mjs')
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
try {
|
|
121
|
+
const pluginPath = join(pluginsDir, file);
|
|
122
|
+
const pluginUrl = pathToFileURL(pluginPath).href;
|
|
123
|
+
const module = await import(pluginUrl);
|
|
124
|
+
|
|
125
|
+
const PluginClass = module.default || module[file.replace(/\.(m?js)$/, '')];
|
|
126
|
+
if (PluginClass && typeof PluginClass === 'function') {
|
|
127
|
+
const pluginName = PluginClass.name || file.replace(/\.(m?js)$/, '');
|
|
128
|
+
customPlugins[pluginName] = () => new PluginClass() as Plugin;
|
|
129
|
+
log(`Loaded custom plugin: ${pluginName}`);
|
|
130
|
+
}
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.warn(`Failed to load plugin ${file}: ${(err as Error).message}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.warn(`Error loading custom plugins: ${(err as Error).message}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return customPlugins;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function createPlugins(
|
|
143
|
+
config: GrafemaConfig['plugins'],
|
|
144
|
+
customPlugins: Record<string, () => Plugin> = {}
|
|
145
|
+
): Plugin[] {
|
|
100
146
|
const plugins: Plugin[] = [];
|
|
101
147
|
const phases: (keyof GrafemaConfig['plugins'])[] = ['discovery', 'indexing', 'analysis', 'enrichment', 'validation'];
|
|
102
148
|
|
|
103
149
|
for (const phase of phases) {
|
|
104
150
|
const names = config[phase] || [];
|
|
105
151
|
for (const name of names) {
|
|
106
|
-
|
|
152
|
+
// Check built-in first, then custom
|
|
153
|
+
const factory = BUILTIN_PLUGINS[name] || customPlugins[name];
|
|
107
154
|
if (factory) {
|
|
108
155
|
plugins.push(factory());
|
|
109
156
|
} else {
|
|
@@ -188,7 +235,9 @@ Examples:
|
|
|
188
235
|
}
|
|
189
236
|
}
|
|
190
237
|
|
|
191
|
-
|
|
238
|
+
// Load custom plugins from .grafema/plugins/
|
|
239
|
+
const customPlugins = await loadCustomPlugins(projectPath, log);
|
|
240
|
+
const plugins = createPlugins(config.plugins, customPlugins);
|
|
192
241
|
|
|
193
242
|
log(`Loaded ${plugins.length} plugins`);
|
|
194
243
|
|