baseguard 1.0.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/.eslintrc.json +25 -0
- package/.prettierrc +8 -0
- package/README.md +94 -0
- package/bin/base.js +494 -0
- package/dist/ai/fix-manager.d.ts +67 -0
- package/dist/ai/fix-manager.d.ts.map +1 -0
- package/dist/ai/fix-manager.js +326 -0
- package/dist/ai/fix-manager.js.map +1 -0
- package/dist/ai/gemini-analyzer.d.ts +116 -0
- package/dist/ai/gemini-analyzer.d.ts.map +1 -0
- package/dist/ai/gemini-analyzer.js +572 -0
- package/dist/ai/gemini-analyzer.js.map +1 -0
- package/dist/ai/index.d.ts +4 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +5 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/jules-implementer.d.ts +115 -0
- package/dist/ai/jules-implementer.d.ts.map +1 -0
- package/dist/ai/jules-implementer.js +387 -0
- package/dist/ai/jules-implementer.js.map +1 -0
- package/dist/commands/automation.d.ts +5 -0
- package/dist/commands/automation.d.ts.map +1 -0
- package/dist/commands/automation.js +305 -0
- package/dist/commands/automation.js.map +1 -0
- package/dist/commands/check.d.ts +9 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +113 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/config.d.ts +11 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +324 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/fix.d.ts +9 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +207 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/index.d.ts +6 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +125 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/core/api-key-manager.d.ts +83 -0
- package/dist/core/api-key-manager.d.ts.map +1 -0
- package/dist/core/api-key-manager.js +244 -0
- package/dist/core/api-key-manager.js.map +1 -0
- package/dist/core/baseguard.d.ts +46 -0
- package/dist/core/baseguard.d.ts.map +1 -0
- package/dist/core/baseguard.js +132 -0
- package/dist/core/baseguard.js.map +1 -0
- package/dist/core/baseline-checker.d.ts +63 -0
- package/dist/core/baseline-checker.d.ts.map +1 -0
- package/dist/core/baseline-checker.js +502 -0
- package/dist/core/baseline-checker.js.map +1 -0
- package/dist/core/cache-manager.d.ts +88 -0
- package/dist/core/cache-manager.d.ts.map +1 -0
- package/dist/core/cache-manager.js +213 -0
- package/dist/core/cache-manager.js.map +1 -0
- package/dist/core/configuration.d.ts +140 -0
- package/dist/core/configuration.d.ts.map +1 -0
- package/dist/core/configuration.js +474 -0
- package/dist/core/configuration.js.map +1 -0
- package/dist/core/directory-filter.d.ts +90 -0
- package/dist/core/directory-filter.d.ts.map +1 -0
- package/dist/core/directory-filter.js +319 -0
- package/dist/core/directory-filter.js.map +1 -0
- package/dist/core/error-handler.d.ts +110 -0
- package/dist/core/error-handler.d.ts.map +1 -0
- package/dist/core/error-handler.js +392 -0
- package/dist/core/error-handler.js.map +1 -0
- package/dist/core/file-processor.d.ts +80 -0
- package/dist/core/file-processor.d.ts.map +1 -0
- package/dist/core/file-processor.js +259 -0
- package/dist/core/file-processor.js.map +1 -0
- package/dist/core/gitignore-manager.d.ts +44 -0
- package/dist/core/gitignore-manager.d.ts.map +1 -0
- package/dist/core/gitignore-manager.js +147 -0
- package/dist/core/gitignore-manager.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +13 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/lazy-loader.d.ts +68 -0
- package/dist/core/lazy-loader.d.ts.map +1 -0
- package/dist/core/lazy-loader.js +260 -0
- package/dist/core/lazy-loader.js.map +1 -0
- package/dist/core/memory-manager.d.ts +1 -0
- package/dist/core/memory-manager.d.ts.map +1 -0
- package/dist/core/memory-manager.js +2 -0
- package/dist/core/memory-manager.js.map +1 -0
- package/dist/core/startup-optimizer.d.ts +45 -0
- package/dist/core/startup-optimizer.d.ts.map +1 -0
- package/dist/core/startup-optimizer.js +140 -0
- package/dist/core/startup-optimizer.js.map +1 -0
- package/dist/git/automation-engine.d.ts +58 -0
- package/dist/git/automation-engine.d.ts.map +1 -0
- package/dist/git/automation-engine.js +318 -0
- package/dist/git/automation-engine.js.map +1 -0
- package/dist/git/github-manager.d.ts +71 -0
- package/dist/git/github-manager.d.ts.map +1 -0
- package/dist/git/github-manager.js +226 -0
- package/dist/git/github-manager.js.map +1 -0
- package/dist/git/hook-manager.d.ts +43 -0
- package/dist/git/hook-manager.d.ts.map +1 -0
- package/dist/git/hook-manager.js +191 -0
- package/dist/git/hook-manager.js.map +1 -0
- package/dist/git/index.d.ts +4 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +5 -0
- package/dist/git/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/feature-validator.d.ts +60 -0
- package/dist/parsers/feature-validator.d.ts.map +1 -0
- package/dist/parsers/feature-validator.js +483 -0
- package/dist/parsers/feature-validator.js.map +1 -0
- package/dist/parsers/index.d.ts +8 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +9 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/parser-manager.d.ts +103 -0
- package/dist/parsers/parser-manager.d.ts.map +1 -0
- package/dist/parsers/parser-manager.js +321 -0
- package/dist/parsers/parser-manager.js.map +1 -0
- package/dist/parsers/parser.d.ts +23 -0
- package/dist/parsers/parser.d.ts.map +1 -0
- package/dist/parsers/parser.js +6 -0
- package/dist/parsers/parser.js.map +1 -0
- package/dist/parsers/react-parser.d.ts +22 -0
- package/dist/parsers/react-parser.d.ts.map +1 -0
- package/dist/parsers/react-parser.js +307 -0
- package/dist/parsers/react-parser.js.map +1 -0
- package/dist/parsers/svelte-parser.d.ts +33 -0
- package/dist/parsers/svelte-parser.d.ts.map +1 -0
- package/dist/parsers/svelte-parser.js +408 -0
- package/dist/parsers/svelte-parser.js.map +1 -0
- package/dist/parsers/vanilla-parser.d.ts +31 -0
- package/dist/parsers/vanilla-parser.d.ts.map +1 -0
- package/dist/parsers/vanilla-parser.js +590 -0
- package/dist/parsers/vanilla-parser.js.map +1 -0
- package/dist/parsers/vue-parser.d.ts +9 -0
- package/dist/parsers/vue-parser.d.ts.map +1 -0
- package/dist/parsers/vue-parser.js +16 -0
- package/dist/parsers/vue-parser.js.map +1 -0
- package/dist/terminal-header.d.ts +12 -0
- package/dist/terminal-header.js +45 -0
- package/dist/types/index.d.ts +83 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/components.d.ts +133 -0
- package/dist/ui/components.d.ts.map +1 -0
- package/dist/ui/components.js +482 -0
- package/dist/ui/components.js.map +1 -0
- package/dist/ui/help.d.ts +11 -0
- package/dist/ui/help.d.ts.map +1 -0
- package/dist/ui/help.js +161 -0
- package/dist/ui/help.js.map +1 -0
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +5 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +63 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +611 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/terminal-header.d.ts +13 -0
- package/dist/ui/terminal-header.d.ts.map +1 -0
- package/dist/ui/terminal-header.js +46 -0
- package/dist/ui/terminal-header.js.map +1 -0
- package/package.json +80 -0
- package/src/ai/__tests__/gemini-analyzer.test.ts +181 -0
- package/src/ai/fix-manager.ts +362 -0
- package/src/ai/gemini-analyzer.ts +671 -0
- package/src/ai/index.ts +4 -0
- package/src/ai/jules-implementer.ts +459 -0
- package/src/commands/automation.ts +344 -0
- package/src/commands/check.ts +299 -0
- package/src/commands/config.ts +365 -0
- package/src/commands/fix.ts +234 -0
- package/src/commands/index.ts +6 -0
- package/src/commands/init.ts +142 -0
- package/src/commands/status.ts +0 -0
- package/src/core/api-key-manager.ts +298 -0
- package/src/core/baseguard.ts +742 -0
- package/src/core/baseline-checker.ts +563 -0
- package/src/core/cache-manager.ts +270 -0
- package/src/core/configuration-recovery.ts +676 -0
- package/src/core/configuration.ts +559 -0
- package/src/core/debug-logger.ts +590 -0
- package/src/core/directory-filter.ts +421 -0
- package/src/core/error-handler.ts +517 -0
- package/src/core/file-processor.ts +331 -0
- package/src/core/gitignore-manager.ts +169 -0
- package/src/core/graceful-degradation-manager.ts +596 -0
- package/src/core/index.ts +13 -0
- package/src/core/lazy-loader.ts +307 -0
- package/src/core/logger.ts +0 -0
- package/src/core/memory-manager.ts +294 -0
- package/src/core/startup-optimizer.ts +173 -0
- package/src/core/system-error-handler.ts +746 -0
- package/src/git/automation-engine.ts +361 -0
- package/src/git/github-manager.ts +260 -0
- package/src/git/hook-manager.ts +210 -0
- package/src/git/index.ts +4 -0
- package/src/index.ts +8 -0
- package/src/parsers/feature-validator.ts +559 -0
- package/src/parsers/index.ts +8 -0
- package/src/parsers/parser-manager.ts +419 -0
- package/src/parsers/parser.ts +26 -0
- package/src/parsers/react-parser-optimized.ts +161 -0
- package/src/parsers/react-parser.ts +359 -0
- package/src/parsers/svelte-parser.ts +506 -0
- package/src/parsers/vanilla-parser.ts +682 -0
- package/src/parsers/vue-parser.ts +472 -0
- package/src/types/index.ts +92 -0
- package/src/ui/components.ts +567 -0
- package/src/ui/help.ts +193 -0
- package/src/ui/index.ts +4 -0
- package/src/ui/prompts.ts +688 -0
- package/src/ui/terminal-header.ts +59 -0
- package/test-config-commands.js +56 -0
- package/test-header-simple.js +33 -0
- package/test-terminal-header.js +12 -0
- package/test-ui.js +29 -0
- package/tests/e2e/baseguard.e2e.test.ts +516 -0
- package/tests/e2e/cross-platform.e2e.test.ts +420 -0
- package/tests/e2e/git-integration.e2e.test.ts +487 -0
- package/tests/fixtures/react-project/package.json +14 -0
- package/tests/fixtures/react-project/src/App.css +76 -0
- package/tests/fixtures/react-project/src/App.tsx +77 -0
- package/tests/fixtures/svelte-project/package.json +11 -0
- package/tests/fixtures/svelte-project/src/App.svelte +369 -0
- package/tests/fixtures/vanilla-project/index.html +76 -0
- package/tests/fixtures/vanilla-project/script.js +331 -0
- package/tests/fixtures/vanilla-project/styles.css +359 -0
- package/tests/fixtures/vue-project/package.json +12 -0
- package/tests/fixtures/vue-project/src/App.vue +216 -0
- package/tsconfig.json +36 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { UIComponents } from '../ui/index.js';
|
|
4
|
+
import { ConfigurationManager } from '../core/configuration.js';
|
|
5
|
+
import { ErrorHandler } from '../core/error-handler.js';
|
|
6
|
+
import { GitHookManager } from '../git/hook-manager.js';
|
|
7
|
+
import { AutomationEngine } from '../git/automation-engine.js';
|
|
8
|
+
import type { AutomationOptions } from '../types/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Manage git automation and hooks
|
|
12
|
+
*/
|
|
13
|
+
export async function automation(action: string, options?: any): Promise<void> {
|
|
14
|
+
try {
|
|
15
|
+
switch (action) {
|
|
16
|
+
case 'enable':
|
|
17
|
+
await enableAutomation(options);
|
|
18
|
+
break;
|
|
19
|
+
case 'disable':
|
|
20
|
+
await disableAutomation();
|
|
21
|
+
break;
|
|
22
|
+
case 'status':
|
|
23
|
+
await showAutomationStatus();
|
|
24
|
+
break;
|
|
25
|
+
case 'configure':
|
|
26
|
+
await configureAutomation();
|
|
27
|
+
break;
|
|
28
|
+
case 'run':
|
|
29
|
+
await runAutomation(options);
|
|
30
|
+
break;
|
|
31
|
+
default:
|
|
32
|
+
await showAutomationHelp();
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
const apiError = ErrorHandler.handleAPIError(error);
|
|
36
|
+
ErrorHandler.displayError(apiError);
|
|
37
|
+
|
|
38
|
+
// Provide specific help for automation command issues
|
|
39
|
+
console.log('\nš” Automation troubleshooting:');
|
|
40
|
+
if (action === 'enable') {
|
|
41
|
+
UIComponents.showList([
|
|
42
|
+
'Ensure you\'re in a git repository (run "git init" if needed)',
|
|
43
|
+
'Check that you have a package.json file',
|
|
44
|
+
'Verify write permissions for .husky directory',
|
|
45
|
+
'Make sure Husky is installed (npm install husky)'
|
|
46
|
+
]);
|
|
47
|
+
} else if (action === 'run') {
|
|
48
|
+
UIComponents.showList([
|
|
49
|
+
'This command is typically called by git hooks automatically',
|
|
50
|
+
'Check that BaseGuard configuration exists (.baseguardrc.json)',
|
|
51
|
+
'Verify git hooks are properly installed',
|
|
52
|
+
'Run "base automation status" to check setup'
|
|
53
|
+
]);
|
|
54
|
+
} else if (action === 'disable') {
|
|
55
|
+
UIComponents.showList([
|
|
56
|
+
'Check file permissions for .husky directory',
|
|
57
|
+
'Verify git repository is properly initialized',
|
|
58
|
+
'Run "base automation status" to check current state'
|
|
59
|
+
]);
|
|
60
|
+
} else {
|
|
61
|
+
UIComponents.showList([
|
|
62
|
+
'Run "base automation status" to check current setup',
|
|
63
|
+
'Use "base automation --help" to see available commands',
|
|
64
|
+
'Ensure you\'re in a git repository with BaseGuard configured'
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Enable automation with optional configuration
|
|
74
|
+
*/
|
|
75
|
+
async function enableAutomation(options?: { trigger?: string; autoFix?: boolean; autoAnalyze?: boolean }): Promise<void> {
|
|
76
|
+
console.log(chalk.cyan('š¤ Enabling BaseGuard automation...'));
|
|
77
|
+
|
|
78
|
+
const config = await ConfigurationManager.load();
|
|
79
|
+
const hookManager = new GitHookManager();
|
|
80
|
+
|
|
81
|
+
// Configure automation settings
|
|
82
|
+
let trigger: 'pre-commit' | 'pre-push' = config.automation.trigger;
|
|
83
|
+
let autoFix = config.automation.autoFix;
|
|
84
|
+
let autoAnalyze = config.automation.autoAnalyze;
|
|
85
|
+
|
|
86
|
+
// Use provided options or prompt for configuration
|
|
87
|
+
if (options?.trigger) {
|
|
88
|
+
if (options.trigger === 'pre-commit' || options.trigger === 'pre-push') {
|
|
89
|
+
trigger = options.trigger;
|
|
90
|
+
} else {
|
|
91
|
+
throw new Error('Invalid trigger. Must be "pre-commit" or "pre-push"');
|
|
92
|
+
}
|
|
93
|
+
} else if (!config.automation.enabled) {
|
|
94
|
+
// First time setup - prompt for configuration
|
|
95
|
+
const answers = await inquirer.prompt([
|
|
96
|
+
{
|
|
97
|
+
type: 'list',
|
|
98
|
+
name: 'trigger',
|
|
99
|
+
message: 'When should BaseGuard check for violations?',
|
|
100
|
+
choices: [
|
|
101
|
+
{ name: 'Before each commit (pre-commit)', value: 'pre-commit' },
|
|
102
|
+
{ name: 'Before each push (pre-push)', value: 'pre-push' }
|
|
103
|
+
],
|
|
104
|
+
default: trigger
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
type: 'confirm',
|
|
108
|
+
name: 'autoAnalyze',
|
|
109
|
+
message: 'Enable automatic AI analysis of violations?',
|
|
110
|
+
default: autoAnalyze,
|
|
111
|
+
when: () => !!config.apiKeys.gemini
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'confirm',
|
|
115
|
+
name: 'autoFix',
|
|
116
|
+
message: 'Enable automatic AI fixing of violations?',
|
|
117
|
+
default: autoFix,
|
|
118
|
+
when: () => !!config.apiKeys.jules && !!config.apiKeys.gemini
|
|
119
|
+
}
|
|
120
|
+
]);
|
|
121
|
+
|
|
122
|
+
trigger = answers.trigger;
|
|
123
|
+
autoAnalyze = answers.autoAnalyze ?? autoAnalyze;
|
|
124
|
+
autoFix = answers.autoFix ?? autoFix;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (options?.autoFix !== undefined) {
|
|
128
|
+
autoFix = options.autoFix;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (options?.autoAnalyze !== undefined) {
|
|
132
|
+
autoAnalyze = options.autoAnalyze;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Update configuration
|
|
136
|
+
config.automation.enabled = true;
|
|
137
|
+
config.automation.trigger = trigger;
|
|
138
|
+
config.automation.autoAnalyze = autoAnalyze;
|
|
139
|
+
config.automation.autoFix = autoFix;
|
|
140
|
+
|
|
141
|
+
await ConfigurationManager.save(config);
|
|
142
|
+
|
|
143
|
+
// Install git hooks
|
|
144
|
+
await hookManager.installHooks(trigger);
|
|
145
|
+
|
|
146
|
+
UIComponents.showSuccessBox(`Automation enabled with ${trigger} trigger`);
|
|
147
|
+
|
|
148
|
+
// Show configuration summary
|
|
149
|
+
console.log(chalk.cyan('\nš Automation Configuration:'));
|
|
150
|
+
console.log(` Trigger: ${chalk.white(trigger)}`);
|
|
151
|
+
console.log(` Auto-analyze: ${autoAnalyze ? chalk.green('enabled') : chalk.red('disabled')}`);
|
|
152
|
+
console.log(` Auto-fix: ${autoFix ? chalk.green('enabled') : chalk.red('disabled')}`);
|
|
153
|
+
console.log(` Block commits: ${config.automation.blockCommit ? chalk.green('enabled') : chalk.red('disabled')}`);
|
|
154
|
+
|
|
155
|
+
if (!config.apiKeys.gemini) {
|
|
156
|
+
console.log(chalk.yellow('\nā ļø Gemini API key not configured. Run "base config" to set up AI features.'));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (!config.apiKeys.jules) {
|
|
160
|
+
console.log(chalk.yellow('ā ļø Jules API key not configured. Run "base config" to set up AI fixing.'));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Disable automation
|
|
166
|
+
*/
|
|
167
|
+
async function disableAutomation(): Promise<void> {
|
|
168
|
+
console.log(chalk.cyan('š¤ Disabling BaseGuard automation...'));
|
|
169
|
+
|
|
170
|
+
const config = await ConfigurationManager.load();
|
|
171
|
+
const hookManager = new GitHookManager();
|
|
172
|
+
|
|
173
|
+
// Update configuration
|
|
174
|
+
config.automation.enabled = false;
|
|
175
|
+
await ConfigurationManager.save(config);
|
|
176
|
+
|
|
177
|
+
// Uninstall git hooks
|
|
178
|
+
await hookManager.uninstallHooks();
|
|
179
|
+
|
|
180
|
+
UIComponents.showSuccessBox('Automation disabled');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Show automation status
|
|
185
|
+
*/
|
|
186
|
+
async function showAutomationStatus(): Promise<void> {
|
|
187
|
+
const config = await ConfigurationManager.load();
|
|
188
|
+
const hookManager = new GitHookManager();
|
|
189
|
+
|
|
190
|
+
console.log(chalk.cyan('š¤ BaseGuard Automation Status\n'));
|
|
191
|
+
|
|
192
|
+
// Configuration status
|
|
193
|
+
console.log(chalk.white('Configuration:'));
|
|
194
|
+
console.log(` Enabled: ${config.automation.enabled ? chalk.green('ā') : chalk.red('ā')}`);
|
|
195
|
+
console.log(` Trigger: ${chalk.white(config.automation.trigger)}`);
|
|
196
|
+
console.log(` Auto-analyze: ${config.automation.autoAnalyze ? chalk.green('ā') : chalk.red('ā')}`);
|
|
197
|
+
console.log(` Auto-fix: ${config.automation.autoFix ? chalk.green('ā') : chalk.red('ā')}`);
|
|
198
|
+
console.log(` Block commits: ${config.automation.blockCommit ? chalk.green('ā') : chalk.red('ā')}`);
|
|
199
|
+
|
|
200
|
+
// Git hooks status
|
|
201
|
+
const hooksInstalled = await hookManager.areHooksInstalled();
|
|
202
|
+
const installedHooks = await hookManager.getInstalledHooks();
|
|
203
|
+
|
|
204
|
+
console.log(chalk.white('\nGit Hooks:'));
|
|
205
|
+
console.log(` Installed: ${hooksInstalled ? chalk.green('ā') : chalk.red('ā')}`);
|
|
206
|
+
if (installedHooks.length > 0) {
|
|
207
|
+
console.log(` Active hooks: ${chalk.white(installedHooks.join(', '))}`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// API keys status
|
|
211
|
+
console.log(chalk.white('\nAPI Keys:'));
|
|
212
|
+
console.log(` Gemini: ${config.apiKeys.gemini ? chalk.green('ā configured') : chalk.red('ā not configured')}`);
|
|
213
|
+
console.log(` Jules: ${config.apiKeys.jules ? chalk.green('ā configured') : chalk.red('ā not configured')}`);
|
|
214
|
+
|
|
215
|
+
// Recommendations
|
|
216
|
+
if (config.automation.enabled && !hooksInstalled) {
|
|
217
|
+
console.log(chalk.yellow('\nā ļø Automation is enabled but git hooks are not installed. Run "base automation enable" to fix this.'));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (config.automation.autoAnalyze && !config.apiKeys.gemini) {
|
|
221
|
+
console.log(chalk.yellow('ā ļø Auto-analyze is enabled but Gemini API key is not configured.'));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (config.automation.autoFix && (!config.apiKeys.jules || !config.apiKeys.gemini)) {
|
|
225
|
+
console.log(chalk.yellow('ā ļø Auto-fix is enabled but API keys are not configured.'));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Configure automation settings
|
|
231
|
+
*/
|
|
232
|
+
async function configureAutomation(): Promise<void> {
|
|
233
|
+
console.log(chalk.cyan('š¤ Configuring BaseGuard automation...\n'));
|
|
234
|
+
|
|
235
|
+
const config = await ConfigurationManager.load();
|
|
236
|
+
const hookManager = new GitHookManager();
|
|
237
|
+
|
|
238
|
+
const answers = await inquirer.prompt([
|
|
239
|
+
{
|
|
240
|
+
type: 'confirm',
|
|
241
|
+
name: 'enabled',
|
|
242
|
+
message: 'Enable automation?',
|
|
243
|
+
default: config.automation.enabled
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
type: 'list',
|
|
247
|
+
name: 'trigger',
|
|
248
|
+
message: 'When should BaseGuard check for violations?',
|
|
249
|
+
choices: [
|
|
250
|
+
{ name: 'Before each commit (pre-commit)', value: 'pre-commit' },
|
|
251
|
+
{ name: 'Before each push (pre-push)', value: 'pre-push' }
|
|
252
|
+
],
|
|
253
|
+
default: config.automation.trigger,
|
|
254
|
+
when: (answers) => answers.enabled
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
type: 'confirm',
|
|
258
|
+
name: 'autoAnalyze',
|
|
259
|
+
message: 'Enable automatic AI analysis of violations?',
|
|
260
|
+
default: config.automation.autoAnalyze,
|
|
261
|
+
when: (answers) => answers.enabled && !!config.apiKeys.gemini
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
type: 'confirm',
|
|
265
|
+
name: 'autoFix',
|
|
266
|
+
message: 'Enable automatic AI fixing of violations?',
|
|
267
|
+
default: config.automation.autoFix,
|
|
268
|
+
when: (answers) => answers.enabled && !!config.apiKeys.jules && !!config.apiKeys.gemini
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
type: 'confirm',
|
|
272
|
+
name: 'blockCommit',
|
|
273
|
+
message: 'Block commits when violations are found?',
|
|
274
|
+
default: config.automation.blockCommit,
|
|
275
|
+
when: (answers) => answers.enabled
|
|
276
|
+
}
|
|
277
|
+
]);
|
|
278
|
+
|
|
279
|
+
// Update configuration
|
|
280
|
+
const oldTrigger = config.automation.trigger;
|
|
281
|
+
|
|
282
|
+
config.automation.enabled = answers.enabled ?? config.automation.enabled;
|
|
283
|
+
config.automation.trigger = answers.trigger ?? config.automation.trigger;
|
|
284
|
+
config.automation.autoAnalyze = answers.autoAnalyze ?? config.automation.autoAnalyze;
|
|
285
|
+
config.automation.autoFix = answers.autoFix ?? config.automation.autoFix;
|
|
286
|
+
config.automation.blockCommit = answers.blockCommit ?? config.automation.blockCommit;
|
|
287
|
+
|
|
288
|
+
await ConfigurationManager.save(config);
|
|
289
|
+
|
|
290
|
+
// Update git hooks if needed
|
|
291
|
+
if (config.automation.enabled) {
|
|
292
|
+
if (oldTrigger !== config.automation.trigger) {
|
|
293
|
+
await hookManager.updateHookConfiguration(oldTrigger, config.automation.trigger);
|
|
294
|
+
} else {
|
|
295
|
+
await hookManager.installHooks(config.automation.trigger);
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
await hookManager.uninstallHooks();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
UIComponents.showSuccessBox('Automation configuration updated');
|
|
302
|
+
|
|
303
|
+
// Show updated status
|
|
304
|
+
await showAutomationStatus();
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Run automation manually (used by git hooks)
|
|
309
|
+
*/
|
|
310
|
+
async function runAutomation(options: { trigger?: string; strict?: boolean } = {}): Promise<void> {
|
|
311
|
+
const trigger = options.trigger as 'pre-commit' | 'pre-push' || 'pre-commit';
|
|
312
|
+
|
|
313
|
+
const automationOptions: AutomationOptions = {
|
|
314
|
+
trigger,
|
|
315
|
+
strict: options.strict
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
const engine = new AutomationEngine();
|
|
319
|
+
await engine.run(automationOptions);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Show automation help
|
|
324
|
+
*/
|
|
325
|
+
async function showAutomationHelp(): Promise<void> {
|
|
326
|
+
console.log(chalk.cyan('š¤ BaseGuard Automation Commands\n'));
|
|
327
|
+
|
|
328
|
+
console.log(chalk.white('Usage:'));
|
|
329
|
+
console.log(' base automation <command> [options]\n');
|
|
330
|
+
|
|
331
|
+
console.log(chalk.white('Commands:'));
|
|
332
|
+
console.log(' enable Enable automation with git hooks');
|
|
333
|
+
console.log(' disable Disable automation and remove git hooks');
|
|
334
|
+
console.log(' status Show current automation status');
|
|
335
|
+
console.log(' configure Interactive configuration of automation settings');
|
|
336
|
+
console.log(' run Run automation manually (used by git hooks)\n');
|
|
337
|
+
|
|
338
|
+
console.log(chalk.white('Examples:'));
|
|
339
|
+
console.log(' base automation enable');
|
|
340
|
+
console.log(' base automation enable --trigger pre-push');
|
|
341
|
+
console.log(' base automation disable');
|
|
342
|
+
console.log(' base automation status');
|
|
343
|
+
console.log(' base automation configure');
|
|
344
|
+
}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { UIComponents } from '../ui/index.js';
|
|
2
|
+
import { BaseGuard } from '../core/baseguard.js';
|
|
3
|
+
import { ConfigurationManager } from '../core/configuration.js';
|
|
4
|
+
import { ConfigurationRecovery } from '../core/configuration-recovery.js';
|
|
5
|
+
import { GracefulDegradationManager } from '../core/graceful-degradation-manager.js';
|
|
6
|
+
import { SystemErrorHandler } from '../core/system-error-handler.js';
|
|
7
|
+
import { ErrorHandler } from '../core/error-handler.js';
|
|
8
|
+
import { logger } from '../core/debug-logger.js';
|
|
9
|
+
import { glob } from 'glob';
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
import type { Violation } from '../types/index.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check for compatibility violations with enhanced error recovery
|
|
15
|
+
*/
|
|
16
|
+
export async function check(options: {
|
|
17
|
+
strict?: boolean;
|
|
18
|
+
files?: string;
|
|
19
|
+
format?: 'table' | 'json' | 'junit';
|
|
20
|
+
debug?: boolean;
|
|
21
|
+
offline?: boolean;
|
|
22
|
+
}): Promise<void> {
|
|
23
|
+
const categoryLogger = logger.createCategoryLogger('check-command');
|
|
24
|
+
const sessionId = logger.startSession('check-command');
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Enable debug logging if requested
|
|
28
|
+
if (options.debug) {
|
|
29
|
+
logger.enableDebug();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Set offline mode if requested
|
|
33
|
+
if (options.offline) {
|
|
34
|
+
SystemErrorHandler.setOfflineMode(true);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
UIComponents.showHeader();
|
|
38
|
+
categoryLogger.info('Starting compatibility check', { options });
|
|
39
|
+
|
|
40
|
+
// Load configuration with recovery
|
|
41
|
+
const config = await SystemErrorHandler.withRetry(
|
|
42
|
+
async () => {
|
|
43
|
+
try {
|
|
44
|
+
return await ConfigurationManager.load();
|
|
45
|
+
} catch (error) {
|
|
46
|
+
categoryLogger.warn('Configuration load failed, attempting recovery', { error });
|
|
47
|
+
|
|
48
|
+
// Attempt configuration recovery
|
|
49
|
+
const recoveryResult = await ConfigurationRecovery.recoverConfiguration({
|
|
50
|
+
createBackup: true,
|
|
51
|
+
validateConfig: true,
|
|
52
|
+
migrateVersion: true,
|
|
53
|
+
repairCorruption: true,
|
|
54
|
+
useDefaults: true
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (recoveryResult.success && recoveryResult.config) {
|
|
58
|
+
if (recoveryResult.warnings.length > 0) {
|
|
59
|
+
console.log(chalk.yellow('ā ļø Configuration was recovered with warnings:'));
|
|
60
|
+
recoveryResult.warnings.forEach(warning => {
|
|
61
|
+
console.log(chalk.yellow(` ⢠${warning}`));
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return recoveryResult.config;
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error(`Configuration recovery failed: ${recoveryResult.errors.join(', ')}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
{ operation: 'load_configuration' },
|
|
71
|
+
2 // max retries
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Initialize BaseGuard with error handling
|
|
75
|
+
const baseGuard = await SystemErrorHandler.handleGracefully(
|
|
76
|
+
async () => new BaseGuard(config),
|
|
77
|
+
null,
|
|
78
|
+
{ operation: 'initialize_baseguard' }
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (!baseGuard) {
|
|
82
|
+
throw new Error('Failed to initialize BaseGuard');
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const spinner = UIComponents.createSpinner('Scanning files for compatibility issues...');
|
|
86
|
+
spinner.start();
|
|
87
|
+
|
|
88
|
+
// Get files to check with error recovery
|
|
89
|
+
const filePattern = options.files || '**/*.{js,jsx,ts,tsx,vue,svelte,css,html}';
|
|
90
|
+
const files = await SystemErrorHandler.handleGracefully(
|
|
91
|
+
async () => {
|
|
92
|
+
return await glob(filePattern, {
|
|
93
|
+
ignore: [
|
|
94
|
+
'node_modules/**',
|
|
95
|
+
'dist/**',
|
|
96
|
+
'build/**',
|
|
97
|
+
'.git/**',
|
|
98
|
+
'**/*.min.js',
|
|
99
|
+
'**/*.min.css'
|
|
100
|
+
]
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
[], // fallback to empty array
|
|
104
|
+
{ operation: 'find_files', details: { pattern: filePattern } }
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
if (files.length === 0) {
|
|
108
|
+
spinner.fail('No files found to check');
|
|
109
|
+
|
|
110
|
+
// Show degradation status if in limited mode
|
|
111
|
+
const mode = GracefulDegradationManager.getCurrentMode();
|
|
112
|
+
if (mode && mode.name !== 'Full Functionality') {
|
|
113
|
+
console.log(chalk.yellow(`\nā ļø Currently in ${mode.name} mode`));
|
|
114
|
+
if (mode.limitations.length > 0) {
|
|
115
|
+
console.log(chalk.yellow('Limitations:'));
|
|
116
|
+
mode.limitations.forEach(limitation => {
|
|
117
|
+
console.log(chalk.yellow(` ⢠${limitation}`));
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
UIComponents.showWarningBox('No files matched the pattern. Try adjusting the --files option.');
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
spinner.text = `Analyzing ${files.length} files...`;
|
|
127
|
+
categoryLogger.info(`Found ${files.length} files to analyze`);
|
|
128
|
+
|
|
129
|
+
// Scan for violations with enhanced error handling
|
|
130
|
+
const violations = await SystemErrorHandler.handleGracefully(
|
|
131
|
+
async () => {
|
|
132
|
+
return await baseGuard.checkViolations(files);
|
|
133
|
+
},
|
|
134
|
+
[], // fallback to empty violations
|
|
135
|
+
{ operation: 'check_violations', details: { fileCount: files.length } },
|
|
136
|
+
{
|
|
137
|
+
logError: true,
|
|
138
|
+
showWarning: true,
|
|
139
|
+
attemptRecovery: true
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
spinner.stop();
|
|
144
|
+
categoryLogger.info(`Scan completed, found ${violations.length} violations`);
|
|
145
|
+
|
|
146
|
+
// Display results based on format with error handling
|
|
147
|
+
await SystemErrorHandler.handleGracefully(
|
|
148
|
+
async () => {
|
|
149
|
+
switch (options.format) {
|
|
150
|
+
case 'json':
|
|
151
|
+
console.log(JSON.stringify(violations, null, 2));
|
|
152
|
+
break;
|
|
153
|
+
case 'junit':
|
|
154
|
+
UIComponents.showJUnitReport(violations);
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
UIComponents.showViolations(violations);
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
undefined,
|
|
162
|
+
{ operation: 'display_results', details: { format: options.format, violationCount: violations.length } },
|
|
163
|
+
{ logError: true, showWarning: false }
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
// Show summary with degradation mode info
|
|
167
|
+
if (violations.length === 0) {
|
|
168
|
+
UIComponents.showSuccessBox('š No compatibility violations found!');
|
|
169
|
+
|
|
170
|
+
// Show mode info if not in full functionality
|
|
171
|
+
const mode = GracefulDegradationManager.getCurrentMode();
|
|
172
|
+
if (mode && mode.name !== 'Full Functionality') {
|
|
173
|
+
console.log(chalk.dim(`\nScan completed in ${mode.name} mode`));
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
const summary = {
|
|
177
|
+
total: violations.length,
|
|
178
|
+
byBrowser: violations.reduce((acc, v) => {
|
|
179
|
+
acc[v.browser] = (acc[v.browser] || 0) + 1;
|
|
180
|
+
return acc;
|
|
181
|
+
}, {} as Record<string, number>),
|
|
182
|
+
byFile: violations.reduce((acc, v) => {
|
|
183
|
+
acc[v.file] = (acc[v.file] || 0) + 1;
|
|
184
|
+
return acc;
|
|
185
|
+
}, {} as Record<string, number>)
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
console.log(chalk.yellow('\nš Summary:'));
|
|
189
|
+
console.log(` Total violations: ${summary.total}`);
|
|
190
|
+
console.log(` Files affected: ${Object.keys(summary.byFile).length}`);
|
|
191
|
+
console.log(` Browsers affected: ${Object.keys(summary.byBrowser).join(', ')}`);
|
|
192
|
+
|
|
193
|
+
// Show appropriate next steps based on current mode
|
|
194
|
+
const mode = GracefulDegradationManager.getCurrentMode();
|
|
195
|
+
if (mode?.capabilities.autoFix) {
|
|
196
|
+
UIComponents.showInfoBox('Run "base fix" to automatically fix these issues with AI assistance.');
|
|
197
|
+
} else {
|
|
198
|
+
UIComponents.showInfoBox('AI fixing is not available in current mode. Review violations manually or restore full functionality.');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (mode && mode.name !== 'Full Functionality') {
|
|
202
|
+
console.log(chalk.dim(`\nScan completed in ${mode.name} mode`));
|
|
203
|
+
if (mode.limitations.length > 0) {
|
|
204
|
+
console.log(chalk.yellow('Current limitations:'));
|
|
205
|
+
mode.limitations.forEach(limitation => {
|
|
206
|
+
console.log(chalk.yellow(` ⢠${limitation}`));
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Create auto-backup if violations found
|
|
213
|
+
if (violations.length > 0) {
|
|
214
|
+
await SystemErrorHandler.handleGracefully(
|
|
215
|
+
async () => {
|
|
216
|
+
const backup = await baseGuard.createConfigBackup();
|
|
217
|
+
if (backup) {
|
|
218
|
+
categoryLogger.debug('Created configuration backup', { backup });
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
undefined,
|
|
222
|
+
{ operation: 'create_backup' },
|
|
223
|
+
{ logError: false, showWarning: false }
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Exit with error code if violations found and strict mode
|
|
228
|
+
if (options.strict && violations.length > 0) {
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
} catch (error) {
|
|
233
|
+
categoryLogger.error('Check command failed', { error });
|
|
234
|
+
|
|
235
|
+
const apiError = ErrorHandler.handleAPIError(error);
|
|
236
|
+
ErrorHandler.displayError(apiError);
|
|
237
|
+
|
|
238
|
+
// Handle service failures gracefully
|
|
239
|
+
if (ErrorHandler.shouldUseFallbackMode(apiError)) {
|
|
240
|
+
await GracefulDegradationManager.handleServiceFailure('check', apiError.type);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Provide specific help for check command issues
|
|
244
|
+
console.log('\nš” Troubleshooting:');
|
|
245
|
+
if (apiError.type === 'configuration') {
|
|
246
|
+
UIComponents.showList([
|
|
247
|
+
'Run "base init" to set up BaseGuard configuration',
|
|
248
|
+
'Run "base config recover" to attempt automatic recovery',
|
|
249
|
+
'Check that .baseguardrc.json exists and is valid',
|
|
250
|
+
'Run "base config validate" to check configuration'
|
|
251
|
+
]);
|
|
252
|
+
} else if (options.files) {
|
|
253
|
+
UIComponents.showList([
|
|
254
|
+
`No files found matching pattern: ${options.files}`,
|
|
255
|
+
'Try a different file pattern (e.g., "src/**/*.ts")',
|
|
256
|
+
'Check that files exist in the specified locations',
|
|
257
|
+
'Use --debug flag for detailed logging'
|
|
258
|
+
]);
|
|
259
|
+
} else {
|
|
260
|
+
UIComponents.showList([
|
|
261
|
+
'Check that you\'re in a project directory',
|
|
262
|
+
'Verify file permissions for reading project files',
|
|
263
|
+
'Try running with a specific file pattern: --files "src/**/*.js"',
|
|
264
|
+
'Use --offline flag if network issues are suspected',
|
|
265
|
+
'Use --debug flag for detailed error information'
|
|
266
|
+
]);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Show fallback suggestions
|
|
270
|
+
if (ErrorHandler.shouldUseFallbackMode(apiError)) {
|
|
271
|
+
console.log('\nš Fallback options:');
|
|
272
|
+
UIComponents.showList(ErrorHandler.getFallbackSuggestions(apiError.type));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Show recovery options
|
|
276
|
+
console.log('\nš§ Recovery options:');
|
|
277
|
+
UIComponents.showList([
|
|
278
|
+
'Run "base status" to check system health',
|
|
279
|
+
'Run "base config recover" to fix configuration issues',
|
|
280
|
+
'Run with --debug flag to get detailed error information',
|
|
281
|
+
'Check logs in .baseguard/logs/ for more details'
|
|
282
|
+
]);
|
|
283
|
+
|
|
284
|
+
// Generate debug report if in debug mode
|
|
285
|
+
if (options.debug) {
|
|
286
|
+
try {
|
|
287
|
+
const reportFile = await logger.generateDebugReport();
|
|
288
|
+
console.log(chalk.dim(`\nDebug report saved to: ${reportFile}`));
|
|
289
|
+
} catch (reportError) {
|
|
290
|
+
// Ignore report generation errors
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
process.exit(1);
|
|
295
|
+
} finally {
|
|
296
|
+
// End logging session
|
|
297
|
+
await logger.endSession();
|
|
298
|
+
}
|
|
299
|
+
}
|