codexia 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -0
- package/LICENSE +663 -0
- package/README.md +392 -0
- package/dist/adapters/github/index.d.ts +66 -0
- package/dist/adapters/github/index.d.ts.map +1 -0
- package/dist/adapters/github/index.js +84 -0
- package/dist/adapters/github/index.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +5 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cli/commands/changelog.d.ts +3 -0
- package/dist/cli/commands/changelog.d.ts.map +1 -0
- package/dist/cli/commands/changelog.js +221 -0
- package/dist/cli/commands/changelog.js.map +1 -0
- package/dist/cli/commands/check.d.ts +3 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +35 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/complexity.d.ts +3 -0
- package/dist/cli/commands/complexity.d.ts.map +1 -0
- package/dist/cli/commands/complexity.js +103 -0
- package/dist/cli/commands/complexity.js.map +1 -0
- package/dist/cli/commands/graph.d.ts +3 -0
- package/dist/cli/commands/graph.d.ts.map +1 -0
- package/dist/cli/commands/graph.js +46 -0
- package/dist/cli/commands/graph.js.map +1 -0
- package/dist/cli/commands/history.d.ts +3 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +127 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/hotpaths.d.ts +3 -0
- package/dist/cli/commands/hotpaths.d.ts.map +1 -0
- package/dist/cli/commands/hotpaths.js +153 -0
- package/dist/cli/commands/hotpaths.js.map +1 -0
- package/dist/cli/commands/impact.d.ts +3 -0
- package/dist/cli/commands/impact.d.ts.map +1 -0
- package/dist/cli/commands/impact.js +37 -0
- package/dist/cli/commands/impact.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +167 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/invariants.d.ts +3 -0
- package/dist/cli/commands/invariants.d.ts.map +1 -0
- package/dist/cli/commands/invariants.js +176 -0
- package/dist/cli/commands/invariants.js.map +1 -0
- package/dist/cli/commands/mcp-server.d.ts +3 -0
- package/dist/cli/commands/mcp-server.d.ts.map +1 -0
- package/dist/cli/commands/mcp-server.js +64 -0
- package/dist/cli/commands/mcp-server.js.map +1 -0
- package/dist/cli/commands/monorepo.d.ts +3 -0
- package/dist/cli/commands/monorepo.d.ts.map +1 -0
- package/dist/cli/commands/monorepo.js +156 -0
- package/dist/cli/commands/monorepo.js.map +1 -0
- package/dist/cli/commands/pr-report.d.ts +3 -0
- package/dist/cli/commands/pr-report.d.ts.map +1 -0
- package/dist/cli/commands/pr-report.js +32 -0
- package/dist/cli/commands/pr-report.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +3 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +25 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/signals.d.ts +3 -0
- package/dist/cli/commands/signals.d.ts.map +1 -0
- package/dist/cli/commands/signals.js +34 -0
- package/dist/cli/commands/signals.js.map +1 -0
- package/dist/cli/commands/tests.d.ts +3 -0
- package/dist/cli/commands/tests.d.ts.map +1 -0
- package/dist/cli/commands/tests.js +30 -0
- package/dist/cli/commands/tests.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +3 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +131 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/engine.d.ts +162 -0
- package/dist/cli/engine.d.ts.map +1 -0
- package/dist/cli/engine.js +564 -0
- package/dist/cli/engine.js.map +1 -0
- package/dist/cli/formatter.d.ts +39 -0
- package/dist/cli/formatter.d.ts.map +1 -0
- package/dist/cli/formatter.js +444 -0
- package/dist/cli/formatter.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +63 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/interactive.d.ts +7 -0
- package/dist/cli/interactive.d.ts.map +1 -0
- package/dist/cli/interactive.js +644 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/core/dependency-graph.d.ts +54 -0
- package/dist/core/dependency-graph.d.ts.map +1 -0
- package/dist/core/dependency-graph.js +190 -0
- package/dist/core/dependency-graph.js.map +1 -0
- package/dist/core/dependency-graph.test.d.ts +2 -0
- package/dist/core/dependency-graph.test.d.ts.map +1 -0
- package/dist/core/dependency-graph.test.js +106 -0
- package/dist/core/dependency-graph.test.js.map +1 -0
- package/dist/core/git-analyzer.d.ts +52 -0
- package/dist/core/git-analyzer.d.ts.map +1 -0
- package/dist/core/git-analyzer.js +250 -0
- package/dist/core/git-analyzer.js.map +1 -0
- package/dist/core/git-analyzer.test.d.ts +2 -0
- package/dist/core/git-analyzer.test.d.ts.map +1 -0
- package/dist/core/git-analyzer.test.js +71 -0
- package/dist/core/git-analyzer.test.js.map +1 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/repo-indexer.d.ts +57 -0
- package/dist/core/repo-indexer.d.ts.map +1 -0
- package/dist/core/repo-indexer.js +356 -0
- package/dist/core/repo-indexer.js.map +1 -0
- package/dist/core/repo-indexer.test.d.ts +2 -0
- package/dist/core/repo-indexer.test.d.ts.map +1 -0
- package/dist/core/repo-indexer.test.js +89 -0
- package/dist/core/repo-indexer.test.js.map +1 -0
- package/dist/core/signals-engine.d.ts +38 -0
- package/dist/core/signals-engine.d.ts.map +1 -0
- package/dist/core/signals-engine.js +142 -0
- package/dist/core/signals-engine.js.map +1 -0
- package/dist/core/signals-engine.test.d.ts +2 -0
- package/dist/core/signals-engine.test.d.ts.map +1 -0
- package/dist/core/signals-engine.test.js +129 -0
- package/dist/core/signals-engine.test.js.map +1 -0
- package/dist/core/symbol-map.d.ts +45 -0
- package/dist/core/symbol-map.d.ts.map +1 -0
- package/dist/core/symbol-map.js +187 -0
- package/dist/core/symbol-map.js.map +1 -0
- package/dist/core/types.d.ts +514 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +5 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/types.test.d.ts +2 -0
- package/dist/core/types.test.d.ts.map +1 -0
- package/dist/core/types.test.js +20 -0
- package/dist/core/types.test.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/server.d.ts +89 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +549 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/modules/changelog-generator.d.ts +82 -0
- package/dist/modules/changelog-generator.d.ts.map +1 -0
- package/dist/modules/changelog-generator.js +350 -0
- package/dist/modules/changelog-generator.js.map +1 -0
- package/dist/modules/complexity-engine.d.ts +86 -0
- package/dist/modules/complexity-engine.d.ts.map +1 -0
- package/dist/modules/complexity-engine.js +355 -0
- package/dist/modules/complexity-engine.js.map +1 -0
- package/dist/modules/convention-checker.d.ts +24 -0
- package/dist/modules/convention-checker.d.ts.map +1 -0
- package/dist/modules/convention-checker.js +181 -0
- package/dist/modules/convention-checker.js.map +1 -0
- package/dist/modules/graph-utils.d.ts +38 -0
- package/dist/modules/graph-utils.d.ts.map +1 -0
- package/dist/modules/graph-utils.js +40 -0
- package/dist/modules/graph-utils.js.map +1 -0
- package/dist/modules/hot-path-detector.d.ts +105 -0
- package/dist/modules/hot-path-detector.d.ts.map +1 -0
- package/dist/modules/hot-path-detector.js +332 -0
- package/dist/modules/hot-path-detector.js.map +1 -0
- package/dist/modules/impact-analyzer.d.ts +40 -0
- package/dist/modules/impact-analyzer.d.ts.map +1 -0
- package/dist/modules/impact-analyzer.js +218 -0
- package/dist/modules/impact-analyzer.js.map +1 -0
- package/dist/modules/impact-analyzer.test.d.ts +2 -0
- package/dist/modules/impact-analyzer.test.d.ts.map +1 -0
- package/dist/modules/impact-analyzer.test.js +308 -0
- package/dist/modules/impact-analyzer.test.js.map +1 -0
- package/dist/modules/index.d.ts +14 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +20 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/invariant-engine.d.ts +119 -0
- package/dist/modules/invariant-engine.d.ts.map +1 -0
- package/dist/modules/invariant-engine.js +457 -0
- package/dist/modules/invariant-engine.js.map +1 -0
- package/dist/modules/memory-loader.d.ts +34 -0
- package/dist/modules/memory-loader.d.ts.map +1 -0
- package/dist/modules/memory-loader.js +313 -0
- package/dist/modules/memory-loader.js.map +1 -0
- package/dist/modules/memory-loader.test.d.ts +2 -0
- package/dist/modules/memory-loader.test.d.ts.map +1 -0
- package/dist/modules/memory-loader.test.js +120 -0
- package/dist/modules/memory-loader.test.js.map +1 -0
- package/dist/modules/monorepo-analyzer.d.ts +141 -0
- package/dist/modules/monorepo-analyzer.d.ts.map +1 -0
- package/dist/modules/monorepo-analyzer.js +453 -0
- package/dist/modules/monorepo-analyzer.js.map +1 -0
- package/dist/modules/plugin-system.d.ts +144 -0
- package/dist/modules/plugin-system.d.ts.map +1 -0
- package/dist/modules/plugin-system.js +428 -0
- package/dist/modules/plugin-system.js.map +1 -0
- package/dist/modules/smart-test-prioritizer.d.ts +95 -0
- package/dist/modules/smart-test-prioritizer.d.ts.map +1 -0
- package/dist/modules/smart-test-prioritizer.js +328 -0
- package/dist/modules/smart-test-prioritizer.js.map +1 -0
- package/dist/modules/temporal-analyzer.d.ts +71 -0
- package/dist/modules/temporal-analyzer.d.ts.map +1 -0
- package/dist/modules/temporal-analyzer.js +301 -0
- package/dist/modules/temporal-analyzer.js.map +1 -0
- package/dist/modules/test-suggester.d.ts +22 -0
- package/dist/modules/test-suggester.d.ts.map +1 -0
- package/dist/modules/test-suggester.js +145 -0
- package/dist/modules/test-suggester.js.map +1 -0
- package/dist/modules/visualizer.d.ts +49 -0
- package/dist/modules/visualizer.d.ts.map +1 -0
- package/dist/modules/visualizer.js +302 -0
- package/dist/modules/visualizer.js.map +1 -0
- package/dist/modules/watcher.d.ts +82 -0
- package/dist/modules/watcher.d.ts.map +1 -0
- package/dist/modules/watcher.js +298 -0
- package/dist/modules/watcher.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
import { select, confirm, input } from '@inquirer/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import boxen from 'boxen';
|
|
4
|
+
import gradient from 'gradient-string';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { CodexiaEngine } from './engine.js';
|
|
7
|
+
import { Formatter } from './formatter.js';
|
|
8
|
+
import { Visualizer } from '../modules/visualizer.js';
|
|
9
|
+
import { transformGraphData } from '../modules/graph-utils.js';
|
|
10
|
+
const categories = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Analyze Repository',
|
|
13
|
+
value: 'analyze',
|
|
14
|
+
description: 'Scan, index, and analyze your codebase',
|
|
15
|
+
icon: '🔍',
|
|
16
|
+
commands: [
|
|
17
|
+
{ name: 'scan', value: 'scan', description: 'Scan and index the repository' },
|
|
18
|
+
{ name: 'graph', value: 'graph', description: 'Visualize dependency graph' },
|
|
19
|
+
{ name: 'complexity', value: 'complexity', description: 'Analyze code complexity' },
|
|
20
|
+
{ name: 'hotpaths', value: 'hotpaths', description: 'Find frequently changed files' },
|
|
21
|
+
{ name: 'history', value: 'history', description: 'Analyze git history patterns' },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'Generate Reports',
|
|
26
|
+
value: 'reports',
|
|
27
|
+
description: 'Create reports and changelogs',
|
|
28
|
+
icon: '📊',
|
|
29
|
+
commands: [
|
|
30
|
+
{ name: 'impact', value: 'impact', description: 'Analyze change impact' },
|
|
31
|
+
{ name: 'pr-report', value: 'pr-report', description: 'Generate PR summary report' },
|
|
32
|
+
{ name: 'changelog', value: 'changelog', description: 'Generate changelog from commits' },
|
|
33
|
+
{ name: 'signals', value: 'signals', description: 'Show engineering signals' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'Quality & Invariants',
|
|
38
|
+
value: 'quality',
|
|
39
|
+
description: 'Check code quality and architectural rules',
|
|
40
|
+
icon: '🛡️',
|
|
41
|
+
commands: [
|
|
42
|
+
{ name: 'check', value: 'check', description: 'Run convention checks' },
|
|
43
|
+
{ name: 'invariants', value: 'invariants', description: 'Verify architectural invariants' },
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Testing',
|
|
48
|
+
value: 'testing',
|
|
49
|
+
description: 'Test prioritization and suggestions',
|
|
50
|
+
icon: '🧪',
|
|
51
|
+
commands: [
|
|
52
|
+
{ name: 'tests', value: 'tests', description: 'Prioritize and suggest tests' },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'Setup & Tools',
|
|
57
|
+
value: 'setup',
|
|
58
|
+
description: 'Initialize and configure Codexia',
|
|
59
|
+
icon: '⚙️',
|
|
60
|
+
commands: [
|
|
61
|
+
{ name: 'init', value: 'init', description: 'Initialize Codexia configuration' },
|
|
62
|
+
{ name: 'watch', value: 'watch', description: 'Watch for file changes' },
|
|
63
|
+
{ name: 'monorepo', value: 'monorepo', description: 'Analyze monorepo structure' },
|
|
64
|
+
{ name: 'mcp-server', value: 'mcp-server', description: 'Start MCP server for AI tools' },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
// Custom gradient for Codexia branding
|
|
69
|
+
const codexiaGradient = gradient(['#6366f1', '#8b5cf6', '#a855f7']);
|
|
70
|
+
function printBanner() {
|
|
71
|
+
const logo = `
|
|
72
|
+
██████╗ ██████╗ ██████╗ ███████╗██╗ ██╗██╗ █████╗
|
|
73
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝╚██╗██╔╝██║██╔══██╗
|
|
74
|
+
██║ ██║ ██║██║ ██║█████╗ ╚███╔╝ ██║███████║
|
|
75
|
+
██║ ██║ ██║██║ ██║██╔══╝ ██╔██╗ ██║██╔══██║
|
|
76
|
+
╚██████╗╚██████╔╝██████╔╝███████╗██╔╝ ██╗██║██║ ██║
|
|
77
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝`;
|
|
78
|
+
console.log();
|
|
79
|
+
console.log(codexiaGradient(logo));
|
|
80
|
+
console.log();
|
|
81
|
+
const tagline = boxen(chalk.white('🧠 Engineering Intelligence Layer'), {
|
|
82
|
+
padding: { left: 2, right: 2, top: 0, bottom: 0 },
|
|
83
|
+
borderStyle: 'round',
|
|
84
|
+
borderColor: 'magenta',
|
|
85
|
+
dimBorder: true,
|
|
86
|
+
});
|
|
87
|
+
console.log(tagline);
|
|
88
|
+
console.log();
|
|
89
|
+
}
|
|
90
|
+
export async function selectCategory() {
|
|
91
|
+
return select({
|
|
92
|
+
message: chalk.bold('What would you like to do?'),
|
|
93
|
+
choices: categories.map((cat) => ({
|
|
94
|
+
name: `${cat.icon} ${chalk.bold(cat.name.padEnd(22))} ${chalk.gray('│')} ${chalk.dim(cat.description)}`,
|
|
95
|
+
value: cat.value,
|
|
96
|
+
})),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
export async function selectCommand(categoryValue) {
|
|
100
|
+
const category = categories.find((c) => c.value === categoryValue);
|
|
101
|
+
if (!category)
|
|
102
|
+
throw new Error('Invalid category');
|
|
103
|
+
console.log();
|
|
104
|
+
console.log(chalk.dim(` ${category.icon} ${category.name}`));
|
|
105
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
106
|
+
return select({
|
|
107
|
+
message: chalk.bold('Choose a command:'),
|
|
108
|
+
choices: [
|
|
109
|
+
...category.commands.map((cmd) => ({
|
|
110
|
+
name: ` ${chalk.cyan('▸')} ${chalk.white.bold(cmd.name.padEnd(14))} ${chalk.dim(cmd.description)}`,
|
|
111
|
+
value: cmd.value,
|
|
112
|
+
})),
|
|
113
|
+
{ name: ` ${chalk.yellow('◀')} ${chalk.yellow('Back to categories')}`, value: 'back' },
|
|
114
|
+
],
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export async function getCommandOptions(command) {
|
|
118
|
+
const options = {};
|
|
119
|
+
// Command-specific prompts
|
|
120
|
+
switch (command) {
|
|
121
|
+
case 'impact':
|
|
122
|
+
options.staged = await confirm({
|
|
123
|
+
message: 'Analyze staged changes only?',
|
|
124
|
+
default: false,
|
|
125
|
+
});
|
|
126
|
+
break;
|
|
127
|
+
case 'graph':
|
|
128
|
+
options.file = await input({
|
|
129
|
+
message: 'File to analyze (leave empty for full graph):',
|
|
130
|
+
default: '',
|
|
131
|
+
});
|
|
132
|
+
break;
|
|
133
|
+
case 'changelog':
|
|
134
|
+
options.from = await input({
|
|
135
|
+
message: 'From ref (tag/commit, leave empty for auto-detect):',
|
|
136
|
+
default: '',
|
|
137
|
+
});
|
|
138
|
+
options.to = await input({
|
|
139
|
+
message: 'To ref (leave empty for HEAD):',
|
|
140
|
+
default: 'HEAD',
|
|
141
|
+
});
|
|
142
|
+
break;
|
|
143
|
+
case 'history':
|
|
144
|
+
options.file = await input({
|
|
145
|
+
message: 'File to analyze (leave empty for full repo):',
|
|
146
|
+
default: '',
|
|
147
|
+
});
|
|
148
|
+
break;
|
|
149
|
+
case 'complexity':
|
|
150
|
+
options.file = await input({
|
|
151
|
+
message: 'File or directory (leave empty for full repo):',
|
|
152
|
+
default: '',
|
|
153
|
+
});
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
// Ask about output format for most commands
|
|
157
|
+
const formatCommands = ['scan', 'impact', 'complexity', 'signals', 'tests', 'hotpaths', 'invariants'];
|
|
158
|
+
if (formatCommands.includes(command)) {
|
|
159
|
+
const wantsJson = await confirm({
|
|
160
|
+
message: 'Output as JSON?',
|
|
161
|
+
default: false,
|
|
162
|
+
});
|
|
163
|
+
if (wantsJson) {
|
|
164
|
+
options.json = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return options;
|
|
168
|
+
}
|
|
169
|
+
function createSpinner(text) {
|
|
170
|
+
return ora({
|
|
171
|
+
text,
|
|
172
|
+
spinner: 'dots',
|
|
173
|
+
color: 'magenta',
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
export async function executeCommand(command, options) {
|
|
177
|
+
const formatter = new Formatter(options.json);
|
|
178
|
+
const engine = new CodexiaEngine();
|
|
179
|
+
console.log();
|
|
180
|
+
console.log(boxen(chalk.dim(`codexia ${command}${options.json ? ' --json' : ''}`), {
|
|
181
|
+
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
182
|
+
borderStyle: 'round',
|
|
183
|
+
borderColor: 'gray',
|
|
184
|
+
dimBorder: true,
|
|
185
|
+
}));
|
|
186
|
+
console.log();
|
|
187
|
+
try {
|
|
188
|
+
switch (command) {
|
|
189
|
+
case 'scan': {
|
|
190
|
+
const spinner = createSpinner('Scanning repository...').start();
|
|
191
|
+
const result = await engine.scan();
|
|
192
|
+
spinner.succeed(chalk.green('Scan complete'));
|
|
193
|
+
console.log();
|
|
194
|
+
console.log(formatter.formatScan(result));
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
case 'impact': {
|
|
198
|
+
const staged = options.staged || false;
|
|
199
|
+
const spinner = createSpinner(`Analyzing impact${staged ? ' (staged changes)' : ''}...`).start();
|
|
200
|
+
const diff = staged ? await engine.getStagedDiff() : await engine.getDiff();
|
|
201
|
+
const result = await engine.analyzeImpact({ staged });
|
|
202
|
+
spinner.succeed(chalk.green('Impact analysis complete'));
|
|
203
|
+
console.log();
|
|
204
|
+
console.log(formatter.formatImpact(result, diff));
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case 'signals': {
|
|
208
|
+
const spinner = createSpinner('Analyzing signals...').start();
|
|
209
|
+
const result = await engine.analyzeSignals();
|
|
210
|
+
spinner.succeed(chalk.green('Signal analysis complete'));
|
|
211
|
+
console.log();
|
|
212
|
+
console.log(formatter.formatSignals(result));
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case 'check': {
|
|
216
|
+
const spinner = createSpinner('Running convention checks...').start();
|
|
217
|
+
const result = await engine.checkConventions();
|
|
218
|
+
spinner.succeed(chalk.green('Convention check complete'));
|
|
219
|
+
console.log();
|
|
220
|
+
console.log(formatter.formatConventions(result));
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
case 'tests': {
|
|
224
|
+
const spinner = createSpinner('Suggesting tests...').start();
|
|
225
|
+
const result = await engine.suggestTests();
|
|
226
|
+
spinner.succeed(chalk.green('Test suggestions ready'));
|
|
227
|
+
console.log();
|
|
228
|
+
console.log(formatter.formatTests(result));
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case 'graph': {
|
|
232
|
+
const file = options.file || undefined;
|
|
233
|
+
const spinner = createSpinner('Generating dependency graph...').start();
|
|
234
|
+
await engine.initialize();
|
|
235
|
+
const rawData = await engine.getGraphData(file);
|
|
236
|
+
// Transform engine's format to Visualizer's expected format using utility
|
|
237
|
+
const graphData = transformGraphData(rawData);
|
|
238
|
+
spinner.succeed(chalk.green('Graph generated'));
|
|
239
|
+
console.log();
|
|
240
|
+
const visualizer = new Visualizer();
|
|
241
|
+
const output = visualizer.visualize(graphData, {
|
|
242
|
+
format: 'ascii',
|
|
243
|
+
depth: 5,
|
|
244
|
+
direction: 'TB',
|
|
245
|
+
});
|
|
246
|
+
console.log(output);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case 'complexity': {
|
|
250
|
+
const file = options.file || undefined;
|
|
251
|
+
const spinner = createSpinner('Analyzing complexity...').start();
|
|
252
|
+
const result = await engine.analyzeComplexity(file);
|
|
253
|
+
spinner.succeed(chalk.green('Complexity analysis complete'));
|
|
254
|
+
console.log();
|
|
255
|
+
if (options.json) {
|
|
256
|
+
console.log(JSON.stringify(result, null, 2));
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
formatComplexityResult(result);
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
case 'history': {
|
|
264
|
+
const file = options.file || undefined;
|
|
265
|
+
const spinner = createSpinner('Analyzing git history...').start();
|
|
266
|
+
const result = await engine.analyzeHistory({ file });
|
|
267
|
+
spinner.succeed(chalk.green('History analysis complete'));
|
|
268
|
+
console.log();
|
|
269
|
+
if (options.json) {
|
|
270
|
+
console.log(JSON.stringify(result, null, 2));
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
formatHistoryResult(result);
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
case 'invariants': {
|
|
278
|
+
const spinner = createSpinner('Checking architectural invariants...').start();
|
|
279
|
+
const result = await engine.checkInvariants();
|
|
280
|
+
spinner.succeed(chalk.green('Invariants check complete'));
|
|
281
|
+
console.log();
|
|
282
|
+
if (options.json) {
|
|
283
|
+
console.log(JSON.stringify(result, null, 2));
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
formatInvariantsResult(result);
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 'hotpaths': {
|
|
291
|
+
const spinner = createSpinner('Finding hot paths...').start();
|
|
292
|
+
const result = await engine.analyzeHotPaths();
|
|
293
|
+
spinner.succeed(chalk.green('Hot path analysis complete'));
|
|
294
|
+
console.log();
|
|
295
|
+
if (options.json) {
|
|
296
|
+
console.log(JSON.stringify(result, null, 2));
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
formatHotPathsResult(result);
|
|
300
|
+
}
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
case 'changelog': {
|
|
304
|
+
let from = options.from || undefined;
|
|
305
|
+
const to = options.to || 'HEAD';
|
|
306
|
+
const spinner = createSpinner('Generating changelog...').start();
|
|
307
|
+
// Auto-detect from ref if not provided
|
|
308
|
+
if (!from) {
|
|
309
|
+
const latestTag = await engine.getLatestTag();
|
|
310
|
+
if (latestTag) {
|
|
311
|
+
from = latestTag;
|
|
312
|
+
spinner.text = `Using latest tag: ${latestTag}`;
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
// Get the root commit as fallback
|
|
316
|
+
const { simpleGit } = await import('simple-git');
|
|
317
|
+
const git = simpleGit(process.cwd());
|
|
318
|
+
try {
|
|
319
|
+
const rootCommit = await git.raw(['rev-list', '--max-parents=0', 'HEAD']);
|
|
320
|
+
from = rootCommit.trim();
|
|
321
|
+
spinner.text = 'Generating changelog from all commits...';
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
from = 'HEAD~3';
|
|
325
|
+
spinner.text = 'Using last 3 commits...';
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
try {
|
|
330
|
+
const result = await engine.generateChangelog({ from, to });
|
|
331
|
+
spinner.succeed(chalk.green('Changelog generated'));
|
|
332
|
+
console.log();
|
|
333
|
+
if (options.json) {
|
|
334
|
+
console.log(JSON.stringify(result, null, 2));
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
formatChangelogResult(result);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch (error) {
|
|
341
|
+
spinner.fail(chalk.red('Could not generate changelog'));
|
|
342
|
+
console.error(chalk.dim(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
343
|
+
console.log(chalk.yellow('Try specifying a valid --from ref.'));
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
case 'monorepo': {
|
|
348
|
+
const spinner = createSpinner('Analyzing monorepo structure...').start();
|
|
349
|
+
const result = await engine.analyzeMonorepo();
|
|
350
|
+
spinner.succeed(chalk.green('Monorepo analysis complete'));
|
|
351
|
+
console.log();
|
|
352
|
+
if (options.json) {
|
|
353
|
+
console.log(JSON.stringify(result, null, 2));
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
formatMonorepoResult(result);
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
case 'pr-report': {
|
|
361
|
+
const spinner = createSpinner('Generating PR report...').start();
|
|
362
|
+
const result = await engine.generatePrReport();
|
|
363
|
+
spinner.succeed(chalk.green('PR report generated'));
|
|
364
|
+
console.log();
|
|
365
|
+
console.log(formatter.formatPrReport(result));
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
case 'init': {
|
|
369
|
+
const spinner = createSpinner('Initializing Codexia...').start();
|
|
370
|
+
// Create default invariants file
|
|
371
|
+
const fs = await import('node:fs/promises');
|
|
372
|
+
const path = await import('node:path');
|
|
373
|
+
const invariantsPath = path.join(process.cwd(), 'codexia.invariants.yaml');
|
|
374
|
+
const defaultContent = `# Codexia Invariants Configuration
|
|
375
|
+
# Define architectural rules and boundaries
|
|
376
|
+
|
|
377
|
+
rules:
|
|
378
|
+
- id: no-circular-imports
|
|
379
|
+
description: Prevent circular dependencies
|
|
380
|
+
severity: error
|
|
381
|
+
pattern: circular-dependency
|
|
382
|
+
|
|
383
|
+
- id: layer-boundaries
|
|
384
|
+
description: Enforce layer separation
|
|
385
|
+
severity: warning
|
|
386
|
+
from: "src/core/**"
|
|
387
|
+
cannotImport: "src/cli/**"
|
|
388
|
+
`;
|
|
389
|
+
try {
|
|
390
|
+
await fs.access(invariantsPath);
|
|
391
|
+
spinner.warn(chalk.yellow('codexia.invariants.yaml already exists'));
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
await fs.writeFile(invariantsPath, defaultContent);
|
|
395
|
+
spinner.succeed(chalk.green('Created codexia.invariants.yaml'));
|
|
396
|
+
}
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
case 'watch': {
|
|
400
|
+
console.log();
|
|
401
|
+
console.log(boxen(`${chalk.blue('👀')} ${chalk.bold('Watch Mode')}\n\n` +
|
|
402
|
+
`${chalk.dim('Directory:')} ${process.cwd()}\n` +
|
|
403
|
+
`${chalk.dim('Status:')} ${chalk.yellow('Interactive mode cannot run watch')}\n\n` +
|
|
404
|
+
`${chalk.dim('Run directly:')} ${chalk.cyan('codexia watch')}`, {
|
|
405
|
+
padding: 1,
|
|
406
|
+
borderStyle: 'round',
|
|
407
|
+
borderColor: 'blue',
|
|
408
|
+
}));
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
case 'mcp-server': {
|
|
412
|
+
console.log();
|
|
413
|
+
console.log(boxen(`${chalk.magenta('🔌')} ${chalk.bold('MCP Server')}\n\n` +
|
|
414
|
+
`${chalk.dim('For AI tool integration (Claude, etc.)')}\n\n` +
|
|
415
|
+
`${chalk.dim('Run directly:')} ${chalk.cyan('codexia mcp-server')}`, {
|
|
416
|
+
padding: 1,
|
|
417
|
+
borderStyle: 'round',
|
|
418
|
+
borderColor: 'magenta',
|
|
419
|
+
}));
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
default:
|
|
423
|
+
console.log(chalk.yellow(`Command '${command}' not yet implemented in interactive mode.`));
|
|
424
|
+
console.log(chalk.dim(`Try running: codexia ${command}`));
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
console.error(formatter.formatError(error));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Helper formatters for commands without dedicated formatter methods
|
|
432
|
+
function formatComplexityResult(result) {
|
|
433
|
+
const maintainability = result.summary.averageMaintainability;
|
|
434
|
+
const maintColor = maintainability >= 70 ? 'green' : maintainability >= 50 ? 'yellow' : 'red';
|
|
435
|
+
console.log(boxen(`${chalk.bold('📊 Complexity Analysis')}\n\n` +
|
|
436
|
+
` Files analyzed ${chalk.cyan(result.summary.totalFiles)}\n` +
|
|
437
|
+
` Avg maintainability ${chalk[maintColor](maintainability.toFixed(1))}\n` +
|
|
438
|
+
` Needs attention ${chalk.yellow(result.summary.filesNeedingAttention)}\n` +
|
|
439
|
+
` Critical files ${chalk.red(result.summary.criticalFiles)}`, {
|
|
440
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
441
|
+
borderStyle: 'round',
|
|
442
|
+
borderColor: 'cyan',
|
|
443
|
+
}));
|
|
444
|
+
if (result.recommendations.length > 0) {
|
|
445
|
+
console.log();
|
|
446
|
+
console.log(chalk.bold(' 💡 Recommendations'));
|
|
447
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
448
|
+
for (const rec of result.recommendations) {
|
|
449
|
+
console.log(` ${chalk.yellow('▸')} ${rec}`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
console.log();
|
|
453
|
+
}
|
|
454
|
+
function formatHistoryResult(result) {
|
|
455
|
+
console.log(boxen(`${chalk.bold('📜 History Analysis')}\n\n` +
|
|
456
|
+
` Files analyzed ${chalk.cyan(result.summary.filesAnalyzed)}\n` +
|
|
457
|
+
` Hotspots ${chalk.yellow(result.summary.hotspotCount)}\n` +
|
|
458
|
+
` Risk files ${chalk.red(result.summary.riskFileCount)}\n` +
|
|
459
|
+
` Stale files ${chalk.gray(result.summary.staleFileCount)}`, {
|
|
460
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
461
|
+
borderStyle: 'round',
|
|
462
|
+
borderColor: 'yellow',
|
|
463
|
+
}));
|
|
464
|
+
console.log();
|
|
465
|
+
}
|
|
466
|
+
function formatInvariantsResult(result) {
|
|
467
|
+
const statusIcon = result.passed ? chalk.green('✓') : chalk.red('✗');
|
|
468
|
+
const statusText = result.passed ? chalk.green('All invariants passed') : chalk.red('Violations found');
|
|
469
|
+
const borderColor = result.passed ? 'green' : 'red';
|
|
470
|
+
console.log(boxen(`${chalk.bold('🛡️ Architectural Invariants')}\n\n` +
|
|
471
|
+
` Status ${statusIcon} ${statusText}\n` +
|
|
472
|
+
` Rules checked ${chalk.cyan(result.rulesChecked)}\n` +
|
|
473
|
+
` Rules passed ${chalk.green(result.passedRules)}\n` +
|
|
474
|
+
` Violations ${result.violations.length > 0 ? chalk.red(result.violations.length) : chalk.green(0)}`, {
|
|
475
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
476
|
+
borderStyle: 'round',
|
|
477
|
+
borderColor,
|
|
478
|
+
}));
|
|
479
|
+
if (result.violations.length > 0) {
|
|
480
|
+
console.log();
|
|
481
|
+
console.log(chalk.bold(' ⚠️ Violations'));
|
|
482
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
483
|
+
for (const v of result.violations.slice(0, 10)) {
|
|
484
|
+
const icon = v.severity === 'error' ? chalk.red('✗') : chalk.yellow('⚠');
|
|
485
|
+
console.log(` ${icon} ${v.message}`);
|
|
486
|
+
console.log(chalk.dim(` ${v.file}:${v.line || 0}`));
|
|
487
|
+
}
|
|
488
|
+
if (result.violations.length > 10) {
|
|
489
|
+
console.log(chalk.gray(` ... and ${result.violations.length - 10} more`));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
console.log();
|
|
493
|
+
}
|
|
494
|
+
function formatHotPathsResult(result) {
|
|
495
|
+
console.log(boxen(`${chalk.bold('🔥 Hot Paths Analysis')}\n\n` +
|
|
496
|
+
` Total paths ${chalk.cyan(result.summary.totalPaths)}\n` +
|
|
497
|
+
` Critical ${chalk.red(result.summary.criticalPaths)}\n` +
|
|
498
|
+
` High ${chalk.yellow(result.summary.highPaths)}\n` +
|
|
499
|
+
` Medium ${chalk.blue(result.summary.mediumPaths)}`, {
|
|
500
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
501
|
+
borderStyle: 'round',
|
|
502
|
+
borderColor: 'red',
|
|
503
|
+
}));
|
|
504
|
+
console.log();
|
|
505
|
+
}
|
|
506
|
+
function formatChangelogResult(result) {
|
|
507
|
+
let statsLine = '';
|
|
508
|
+
if (result.stats) {
|
|
509
|
+
statsLine = ` ${chalk.cyan(result.stats.commits)} commits ${chalk.green('+' + result.stats.additions)} ${chalk.red('-' + result.stats.deletions)}`;
|
|
510
|
+
if (result.stats.contributors.length > 0) {
|
|
511
|
+
statsLine += `\n Contributors: ${chalk.dim(result.stats.contributors.join(', '))}`;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
console.log(boxen(`${chalk.bold('📝 Generated Changelog')}\n\n${statsLine}`, {
|
|
515
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
516
|
+
borderStyle: 'round',
|
|
517
|
+
borderColor: 'green',
|
|
518
|
+
}));
|
|
519
|
+
if (result.sections && result.sections.length > 0) {
|
|
520
|
+
for (const section of result.sections) {
|
|
521
|
+
if (section.items.length > 0) {
|
|
522
|
+
console.log();
|
|
523
|
+
console.log(chalk.bold(` ${section.title || section.type}`));
|
|
524
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
525
|
+
for (const item of section.items.slice(0, 10)) {
|
|
526
|
+
const breaking = item.breaking ? chalk.red(' [BREAKING]') : '';
|
|
527
|
+
console.log(` ${chalk.gray('•')} ${item.description || item.message}${breaking}`);
|
|
528
|
+
}
|
|
529
|
+
if (section.items.length > 10) {
|
|
530
|
+
console.log(chalk.gray(` ... and ${section.items.length - 10} more`));
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else if (result.entries && result.entries.length > 0) {
|
|
536
|
+
console.log();
|
|
537
|
+
for (const entry of result.entries.slice(0, 20)) {
|
|
538
|
+
console.log(` ${chalk.gray('•')} ${entry.message || entry.description}`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
console.log(chalk.gray('\n No changelog entries found'));
|
|
543
|
+
}
|
|
544
|
+
console.log();
|
|
545
|
+
}
|
|
546
|
+
function formatMonorepoResult(result) {
|
|
547
|
+
if (!result.type) {
|
|
548
|
+
console.log(boxen(`${chalk.bold('📦 Monorepo Analysis')}\n\n` +
|
|
549
|
+
` ${chalk.yellow('This does not appear to be a monorepo')}`, {
|
|
550
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
551
|
+
borderStyle: 'round',
|
|
552
|
+
borderColor: 'yellow',
|
|
553
|
+
}));
|
|
554
|
+
console.log();
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
console.log(boxen(`${chalk.bold('📦 Monorepo Analysis')}\n\n` +
|
|
558
|
+
` Type ${chalk.cyan(result.type)}\n` +
|
|
559
|
+
` Packages ${chalk.cyan(result.packages?.length || 0)}\n` +
|
|
560
|
+
` Internal deps ${chalk.cyan(result.summary?.internalDeps || 0)}\n` +
|
|
561
|
+
` Shared deps ${chalk.cyan(result.summary?.sharedDeps || 0)}`, {
|
|
562
|
+
padding: { left: 1, right: 3, top: 0, bottom: 0 },
|
|
563
|
+
borderStyle: 'round',
|
|
564
|
+
borderColor: 'blue',
|
|
565
|
+
}));
|
|
566
|
+
if (result.packages && result.packages.length > 0) {
|
|
567
|
+
console.log();
|
|
568
|
+
console.log(chalk.bold(' 📁 Packages'));
|
|
569
|
+
console.log(chalk.dim(' ' + '─'.repeat(40)));
|
|
570
|
+
for (const pkg of result.packages.slice(0, 10)) {
|
|
571
|
+
const pkgName = typeof pkg === 'string' ? pkg : (pkg.name || 'unknown');
|
|
572
|
+
console.log(` ${chalk.cyan('▸')} ${pkgName}`);
|
|
573
|
+
}
|
|
574
|
+
if (result.packages.length > 10) {
|
|
575
|
+
console.log(chalk.gray(` ... and ${result.packages.length - 10} more`));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
console.log();
|
|
579
|
+
}
|
|
580
|
+
export async function runInteractiveWizard() {
|
|
581
|
+
printBanner();
|
|
582
|
+
let running = true;
|
|
583
|
+
while (running) {
|
|
584
|
+
try {
|
|
585
|
+
const category = await selectCategory();
|
|
586
|
+
const command = await selectCommand(category);
|
|
587
|
+
if (command === 'back') {
|
|
588
|
+
console.log();
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
const options = await getCommandOptions(command);
|
|
592
|
+
await executeCommand(command, options);
|
|
593
|
+
console.log();
|
|
594
|
+
const again = await confirm({
|
|
595
|
+
message: 'Run another command?',
|
|
596
|
+
default: true,
|
|
597
|
+
});
|
|
598
|
+
if (!again) {
|
|
599
|
+
running = false;
|
|
600
|
+
}
|
|
601
|
+
console.log();
|
|
602
|
+
}
|
|
603
|
+
catch (error) {
|
|
604
|
+
// User pressed Ctrl+C or escaped
|
|
605
|
+
if (error.name === 'ExitPromptError') {
|
|
606
|
+
running = false;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
throw error;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
console.log();
|
|
614
|
+
console.log(boxen(`${chalk.dim('Thanks for using')} ${codexiaGradient('Codexia')} ${chalk.dim('👋')}\n\n` +
|
|
615
|
+
`${chalk.dim('Run')} ${chalk.cyan('codexia --help')} ${chalk.dim('for all commands')}`, {
|
|
616
|
+
padding: { left: 2, right: 2, top: 0, bottom: 0 },
|
|
617
|
+
borderStyle: 'round',
|
|
618
|
+
borderColor: 'magenta',
|
|
619
|
+
dimBorder: true,
|
|
620
|
+
}));
|
|
621
|
+
console.log();
|
|
622
|
+
}
|
|
623
|
+
// Quick command for direct access without category selection
|
|
624
|
+
export async function runQuickCommand() {
|
|
625
|
+
printBanner();
|
|
626
|
+
const allCommands = categories.flatMap((cat) => cat.commands.map((cmd) => ({
|
|
627
|
+
name: `${chalk.green(cmd.name.padEnd(12))} ${chalk.dim(cmd.description)}`,
|
|
628
|
+
value: cmd.value,
|
|
629
|
+
})));
|
|
630
|
+
try {
|
|
631
|
+
const command = await select({
|
|
632
|
+
message: 'Choose a command:',
|
|
633
|
+
choices: allCommands,
|
|
634
|
+
});
|
|
635
|
+
const options = await getCommandOptions(command);
|
|
636
|
+
await executeCommand(command, options);
|
|
637
|
+
}
|
|
638
|
+
catch (error) {
|
|
639
|
+
if (error.name !== 'ExitPromptError') {
|
|
640
|
+
throw error;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
//# sourceMappingURL=interactive.js.map
|