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.
Files changed (244) hide show
  1. package/.eslintrc.json +25 -0
  2. package/.prettierrc +8 -0
  3. package/README.md +94 -0
  4. package/bin/base.js +494 -0
  5. package/dist/ai/fix-manager.d.ts +67 -0
  6. package/dist/ai/fix-manager.d.ts.map +1 -0
  7. package/dist/ai/fix-manager.js +326 -0
  8. package/dist/ai/fix-manager.js.map +1 -0
  9. package/dist/ai/gemini-analyzer.d.ts +116 -0
  10. package/dist/ai/gemini-analyzer.d.ts.map +1 -0
  11. package/dist/ai/gemini-analyzer.js +572 -0
  12. package/dist/ai/gemini-analyzer.js.map +1 -0
  13. package/dist/ai/index.d.ts +4 -0
  14. package/dist/ai/index.d.ts.map +1 -0
  15. package/dist/ai/index.js +5 -0
  16. package/dist/ai/index.js.map +1 -0
  17. package/dist/ai/jules-implementer.d.ts +115 -0
  18. package/dist/ai/jules-implementer.d.ts.map +1 -0
  19. package/dist/ai/jules-implementer.js +387 -0
  20. package/dist/ai/jules-implementer.js.map +1 -0
  21. package/dist/commands/automation.d.ts +5 -0
  22. package/dist/commands/automation.d.ts.map +1 -0
  23. package/dist/commands/automation.js +305 -0
  24. package/dist/commands/automation.js.map +1 -0
  25. package/dist/commands/check.d.ts +9 -0
  26. package/dist/commands/check.d.ts.map +1 -0
  27. package/dist/commands/check.js +113 -0
  28. package/dist/commands/check.js.map +1 -0
  29. package/dist/commands/config.d.ts +11 -0
  30. package/dist/commands/config.d.ts.map +1 -0
  31. package/dist/commands/config.js +324 -0
  32. package/dist/commands/config.js.map +1 -0
  33. package/dist/commands/fix.d.ts +9 -0
  34. package/dist/commands/fix.d.ts.map +1 -0
  35. package/dist/commands/fix.js +207 -0
  36. package/dist/commands/fix.js.map +1 -0
  37. package/dist/commands/index.d.ts +6 -0
  38. package/dist/commands/index.d.ts.map +1 -0
  39. package/dist/commands/index.js +7 -0
  40. package/dist/commands/index.js.map +1 -0
  41. package/dist/commands/init.d.ts +9 -0
  42. package/dist/commands/init.d.ts.map +1 -0
  43. package/dist/commands/init.js +125 -0
  44. package/dist/commands/init.js.map +1 -0
  45. package/dist/core/api-key-manager.d.ts +83 -0
  46. package/dist/core/api-key-manager.d.ts.map +1 -0
  47. package/dist/core/api-key-manager.js +244 -0
  48. package/dist/core/api-key-manager.js.map +1 -0
  49. package/dist/core/baseguard.d.ts +46 -0
  50. package/dist/core/baseguard.d.ts.map +1 -0
  51. package/dist/core/baseguard.js +132 -0
  52. package/dist/core/baseguard.js.map +1 -0
  53. package/dist/core/baseline-checker.d.ts +63 -0
  54. package/dist/core/baseline-checker.d.ts.map +1 -0
  55. package/dist/core/baseline-checker.js +502 -0
  56. package/dist/core/baseline-checker.js.map +1 -0
  57. package/dist/core/cache-manager.d.ts +88 -0
  58. package/dist/core/cache-manager.d.ts.map +1 -0
  59. package/dist/core/cache-manager.js +213 -0
  60. package/dist/core/cache-manager.js.map +1 -0
  61. package/dist/core/configuration.d.ts +140 -0
  62. package/dist/core/configuration.d.ts.map +1 -0
  63. package/dist/core/configuration.js +474 -0
  64. package/dist/core/configuration.js.map +1 -0
  65. package/dist/core/directory-filter.d.ts +90 -0
  66. package/dist/core/directory-filter.d.ts.map +1 -0
  67. package/dist/core/directory-filter.js +319 -0
  68. package/dist/core/directory-filter.js.map +1 -0
  69. package/dist/core/error-handler.d.ts +110 -0
  70. package/dist/core/error-handler.d.ts.map +1 -0
  71. package/dist/core/error-handler.js +392 -0
  72. package/dist/core/error-handler.js.map +1 -0
  73. package/dist/core/file-processor.d.ts +80 -0
  74. package/dist/core/file-processor.d.ts.map +1 -0
  75. package/dist/core/file-processor.js +259 -0
  76. package/dist/core/file-processor.js.map +1 -0
  77. package/dist/core/gitignore-manager.d.ts +44 -0
  78. package/dist/core/gitignore-manager.d.ts.map +1 -0
  79. package/dist/core/gitignore-manager.js +147 -0
  80. package/dist/core/gitignore-manager.js.map +1 -0
  81. package/dist/core/index.d.ts +13 -0
  82. package/dist/core/index.d.ts.map +1 -0
  83. package/dist/core/index.js +13 -0
  84. package/dist/core/index.js.map +1 -0
  85. package/dist/core/lazy-loader.d.ts +68 -0
  86. package/dist/core/lazy-loader.d.ts.map +1 -0
  87. package/dist/core/lazy-loader.js +260 -0
  88. package/dist/core/lazy-loader.js.map +1 -0
  89. package/dist/core/memory-manager.d.ts +1 -0
  90. package/dist/core/memory-manager.d.ts.map +1 -0
  91. package/dist/core/memory-manager.js +2 -0
  92. package/dist/core/memory-manager.js.map +1 -0
  93. package/dist/core/startup-optimizer.d.ts +45 -0
  94. package/dist/core/startup-optimizer.d.ts.map +1 -0
  95. package/dist/core/startup-optimizer.js +140 -0
  96. package/dist/core/startup-optimizer.js.map +1 -0
  97. package/dist/git/automation-engine.d.ts +58 -0
  98. package/dist/git/automation-engine.d.ts.map +1 -0
  99. package/dist/git/automation-engine.js +318 -0
  100. package/dist/git/automation-engine.js.map +1 -0
  101. package/dist/git/github-manager.d.ts +71 -0
  102. package/dist/git/github-manager.d.ts.map +1 -0
  103. package/dist/git/github-manager.js +226 -0
  104. package/dist/git/github-manager.js.map +1 -0
  105. package/dist/git/hook-manager.d.ts +43 -0
  106. package/dist/git/hook-manager.d.ts.map +1 -0
  107. package/dist/git/hook-manager.js +191 -0
  108. package/dist/git/hook-manager.js.map +1 -0
  109. package/dist/git/index.d.ts +4 -0
  110. package/dist/git/index.d.ts.map +1 -0
  111. package/dist/git/index.js +5 -0
  112. package/dist/git/index.js.map +1 -0
  113. package/dist/index.d.ts +8 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +9 -0
  116. package/dist/index.js.map +1 -0
  117. package/dist/parsers/feature-validator.d.ts +60 -0
  118. package/dist/parsers/feature-validator.d.ts.map +1 -0
  119. package/dist/parsers/feature-validator.js +483 -0
  120. package/dist/parsers/feature-validator.js.map +1 -0
  121. package/dist/parsers/index.d.ts +8 -0
  122. package/dist/parsers/index.d.ts.map +1 -0
  123. package/dist/parsers/index.js +9 -0
  124. package/dist/parsers/index.js.map +1 -0
  125. package/dist/parsers/parser-manager.d.ts +103 -0
  126. package/dist/parsers/parser-manager.d.ts.map +1 -0
  127. package/dist/parsers/parser-manager.js +321 -0
  128. package/dist/parsers/parser-manager.js.map +1 -0
  129. package/dist/parsers/parser.d.ts +23 -0
  130. package/dist/parsers/parser.d.ts.map +1 -0
  131. package/dist/parsers/parser.js +6 -0
  132. package/dist/parsers/parser.js.map +1 -0
  133. package/dist/parsers/react-parser.d.ts +22 -0
  134. package/dist/parsers/react-parser.d.ts.map +1 -0
  135. package/dist/parsers/react-parser.js +307 -0
  136. package/dist/parsers/react-parser.js.map +1 -0
  137. package/dist/parsers/svelte-parser.d.ts +33 -0
  138. package/dist/parsers/svelte-parser.d.ts.map +1 -0
  139. package/dist/parsers/svelte-parser.js +408 -0
  140. package/dist/parsers/svelte-parser.js.map +1 -0
  141. package/dist/parsers/vanilla-parser.d.ts +31 -0
  142. package/dist/parsers/vanilla-parser.d.ts.map +1 -0
  143. package/dist/parsers/vanilla-parser.js +590 -0
  144. package/dist/parsers/vanilla-parser.js.map +1 -0
  145. package/dist/parsers/vue-parser.d.ts +9 -0
  146. package/dist/parsers/vue-parser.d.ts.map +1 -0
  147. package/dist/parsers/vue-parser.js +16 -0
  148. package/dist/parsers/vue-parser.js.map +1 -0
  149. package/dist/terminal-header.d.ts +12 -0
  150. package/dist/terminal-header.js +45 -0
  151. package/dist/types/index.d.ts +83 -0
  152. package/dist/types/index.d.ts.map +1 -0
  153. package/dist/types/index.js +5 -0
  154. package/dist/types/index.js.map +1 -0
  155. package/dist/ui/components.d.ts +133 -0
  156. package/dist/ui/components.d.ts.map +1 -0
  157. package/dist/ui/components.js +482 -0
  158. package/dist/ui/components.js.map +1 -0
  159. package/dist/ui/help.d.ts +11 -0
  160. package/dist/ui/help.d.ts.map +1 -0
  161. package/dist/ui/help.js +161 -0
  162. package/dist/ui/help.js.map +1 -0
  163. package/dist/ui/index.d.ts +5 -0
  164. package/dist/ui/index.d.ts.map +1 -0
  165. package/dist/ui/index.js +5 -0
  166. package/dist/ui/index.js.map +1 -0
  167. package/dist/ui/prompts.d.ts +63 -0
  168. package/dist/ui/prompts.d.ts.map +1 -0
  169. package/dist/ui/prompts.js +611 -0
  170. package/dist/ui/prompts.js.map +1 -0
  171. package/dist/ui/terminal-header.d.ts +13 -0
  172. package/dist/ui/terminal-header.d.ts.map +1 -0
  173. package/dist/ui/terminal-header.js +46 -0
  174. package/dist/ui/terminal-header.js.map +1 -0
  175. package/package.json +80 -0
  176. package/src/ai/__tests__/gemini-analyzer.test.ts +181 -0
  177. package/src/ai/fix-manager.ts +362 -0
  178. package/src/ai/gemini-analyzer.ts +671 -0
  179. package/src/ai/index.ts +4 -0
  180. package/src/ai/jules-implementer.ts +459 -0
  181. package/src/commands/automation.ts +344 -0
  182. package/src/commands/check.ts +299 -0
  183. package/src/commands/config.ts +365 -0
  184. package/src/commands/fix.ts +234 -0
  185. package/src/commands/index.ts +6 -0
  186. package/src/commands/init.ts +142 -0
  187. package/src/commands/status.ts +0 -0
  188. package/src/core/api-key-manager.ts +298 -0
  189. package/src/core/baseguard.ts +742 -0
  190. package/src/core/baseline-checker.ts +563 -0
  191. package/src/core/cache-manager.ts +270 -0
  192. package/src/core/configuration-recovery.ts +676 -0
  193. package/src/core/configuration.ts +559 -0
  194. package/src/core/debug-logger.ts +590 -0
  195. package/src/core/directory-filter.ts +421 -0
  196. package/src/core/error-handler.ts +517 -0
  197. package/src/core/file-processor.ts +331 -0
  198. package/src/core/gitignore-manager.ts +169 -0
  199. package/src/core/graceful-degradation-manager.ts +596 -0
  200. package/src/core/index.ts +13 -0
  201. package/src/core/lazy-loader.ts +307 -0
  202. package/src/core/logger.ts +0 -0
  203. package/src/core/memory-manager.ts +294 -0
  204. package/src/core/startup-optimizer.ts +173 -0
  205. package/src/core/system-error-handler.ts +746 -0
  206. package/src/git/automation-engine.ts +361 -0
  207. package/src/git/github-manager.ts +260 -0
  208. package/src/git/hook-manager.ts +210 -0
  209. package/src/git/index.ts +4 -0
  210. package/src/index.ts +8 -0
  211. package/src/parsers/feature-validator.ts +559 -0
  212. package/src/parsers/index.ts +8 -0
  213. package/src/parsers/parser-manager.ts +419 -0
  214. package/src/parsers/parser.ts +26 -0
  215. package/src/parsers/react-parser-optimized.ts +161 -0
  216. package/src/parsers/react-parser.ts +359 -0
  217. package/src/parsers/svelte-parser.ts +506 -0
  218. package/src/parsers/vanilla-parser.ts +682 -0
  219. package/src/parsers/vue-parser.ts +472 -0
  220. package/src/types/index.ts +92 -0
  221. package/src/ui/components.ts +567 -0
  222. package/src/ui/help.ts +193 -0
  223. package/src/ui/index.ts +4 -0
  224. package/src/ui/prompts.ts +688 -0
  225. package/src/ui/terminal-header.ts +59 -0
  226. package/test-config-commands.js +56 -0
  227. package/test-header-simple.js +33 -0
  228. package/test-terminal-header.js +12 -0
  229. package/test-ui.js +29 -0
  230. package/tests/e2e/baseguard.e2e.test.ts +516 -0
  231. package/tests/e2e/cross-platform.e2e.test.ts +420 -0
  232. package/tests/e2e/git-integration.e2e.test.ts +487 -0
  233. package/tests/fixtures/react-project/package.json +14 -0
  234. package/tests/fixtures/react-project/src/App.css +76 -0
  235. package/tests/fixtures/react-project/src/App.tsx +77 -0
  236. package/tests/fixtures/svelte-project/package.json +11 -0
  237. package/tests/fixtures/svelte-project/src/App.svelte +369 -0
  238. package/tests/fixtures/vanilla-project/index.html +76 -0
  239. package/tests/fixtures/vanilla-project/script.js +331 -0
  240. package/tests/fixtures/vanilla-project/styles.css +359 -0
  241. package/tests/fixtures/vue-project/package.json +12 -0
  242. package/tests/fixtures/vue-project/src/App.vue +216 -0
  243. package/tsconfig.json +36 -0
  244. package/vitest.config.ts +10 -0
@@ -0,0 +1,365 @@
1
+ import { UIComponents, Prompts } from '../ui/index.js';
2
+ import { ConfigurationManager, ApiKeyManager, GitignoreManager } from '../core/index.js';
3
+ import { ErrorHandler } from '../core/error-handler.js';
4
+
5
+ /**
6
+ * Manage BaseGuard configuration
7
+ */
8
+ export async function config(action: string, options?: {
9
+ add?: string;
10
+ remove?: string;
11
+ preset?: string;
12
+ file?: string;
13
+ format?: string;
14
+ }): Promise<void> {
15
+ try {
16
+ switch (action) {
17
+ case 'show':
18
+ await showConfiguration();
19
+ break;
20
+ case 'list':
21
+ await listConfiguration(options?.format);
22
+ break;
23
+ case 'set-keys':
24
+ await setupApiKeys();
25
+ break;
26
+ case 'targets':
27
+ await updateTargets(options);
28
+ break;
29
+ case 'automation':
30
+ await updateAutomation();
31
+ break;
32
+ case 'update':
33
+ await updateConfiguration();
34
+ break;
35
+ case 'validate':
36
+ await validateConfiguration();
37
+ break;
38
+ case 'security':
39
+ await checkSecurity();
40
+ break;
41
+ case 'backup':
42
+ await backupConfiguration();
43
+ break;
44
+ case 'restore':
45
+ await restoreConfiguration(options?.file);
46
+ break;
47
+ default:
48
+ UIComponents.showErrorBox(`Unknown config action: ${action}`);
49
+ showConfigHelp();
50
+ process.exit(1);
51
+ }
52
+
53
+ } catch (error) {
54
+ const apiError = ErrorHandler.handleAPIError(error);
55
+ ErrorHandler.displayError(apiError);
56
+
57
+ // Provide specific help for config command issues
58
+ console.log('\nšŸ’” Configuration help:');
59
+ if (action === 'set-keys') {
60
+ UIComponents.showList([
61
+ 'Get Gemini API key from https://aistudio.google.com',
62
+ 'Get Jules API key from https://jules.google.com',
63
+ 'Ensure API keys are valid and have proper permissions',
64
+ 'Check your internet connection for key validation'
65
+ ]);
66
+ } else if (action === 'targets') {
67
+ UIComponents.showList([
68
+ 'Use format "browser version" (e.g., "chrome 100")',
69
+ 'Available browsers: chrome, safari, firefox, edge',
70
+ 'Use "baseline" for Baseline-only support',
71
+ 'Check available presets with "base config targets --help"'
72
+ ]);
73
+ } else if (action === 'validate') {
74
+ UIComponents.showList([
75
+ 'Check .baseguardrc.json file exists',
76
+ 'Verify JSON syntax is correct',
77
+ 'Run "base init" to recreate configuration if needed'
78
+ ]);
79
+ } else {
80
+ UIComponents.showList([
81
+ 'Run "base config show" to see current configuration',
82
+ 'Use "base config --help" to see available commands',
83
+ 'Check file permissions in the current directory'
84
+ ]);
85
+ }
86
+
87
+ process.exit(1);
88
+ }
89
+ }
90
+
91
+ async function showConfiguration(): Promise<void> {
92
+ const display = await ConfigurationManager.getConfigurationDisplay();
93
+
94
+ UIComponents.showConfiguration(display.config);
95
+
96
+ // Show security status
97
+ if (!display.security.configIgnored) {
98
+ UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
99
+
100
+ if (display.security.recommendations.length > 0) {
101
+ console.log('\nSecurity recommendations:');
102
+ UIComponents.showList(display.security.recommendations);
103
+ }
104
+ }
105
+
106
+ // Show validation errors if any
107
+ if (!display.validation.valid) {
108
+ UIComponents.showErrorBox('Configuration validation failed');
109
+ UIComponents.showList(display.validation.errors);
110
+ }
111
+ }
112
+
113
+ async function listConfiguration(format?: string): Promise<void> {
114
+ const display = await ConfigurationManager.getConfigurationDisplay();
115
+
116
+ if (format === 'json') {
117
+ // Output as JSON for programmatic use
118
+ const output = {
119
+ configuration: display.config,
120
+ security: display.security,
121
+ validation: display.validation,
122
+ status: {
123
+ configured: display.config.apiKeys.jules !== null || display.config.apiKeys.gemini !== null,
124
+ automationEnabled: display.config.automation.enabled,
125
+ targetCount: display.config.targets.length
126
+ }
127
+ };
128
+ console.log(JSON.stringify(output, null, 2));
129
+ return;
130
+ }
131
+
132
+ // Default table format
133
+ UIComponents.showSectionHeader('BaseGuard Configuration Summary');
134
+
135
+ // Configuration overview
136
+ console.log('šŸ“‹ Configuration:');
137
+ console.log(` Version: ${display.config.version}`);
138
+ console.log(` Targets: ${display.config.targets.length} browser(s)`);
139
+ console.log(` API Keys: ${display.config.apiKeys.jules ? 'āœ“' : 'āœ—'} Jules, ${display.config.apiKeys.gemini ? 'āœ“' : 'āœ—'} Gemini`);
140
+ console.log(` Automation: ${display.config.automation.enabled ? 'āœ“ enabled' : 'āœ— disabled'}`);
141
+
142
+ // Browser targets
143
+ console.log('\nšŸŽÆ Browser Targets:');
144
+ display.config.targets.forEach(target => {
145
+ console.log(` • ${target.browser} ${target.minVersion}`);
146
+ });
147
+
148
+ // Automation settings
149
+ console.log('\nšŸ¤– Automation Settings:');
150
+ console.log(` Enabled: ${display.config.automation.enabled ? 'āœ“' : 'āœ—'}`);
151
+ console.log(` Trigger: ${display.config.automation.trigger}`);
152
+ console.log(` Auto-analyze: ${display.config.automation.autoAnalyze ? 'āœ“' : 'āœ—'}`);
153
+ console.log(` Auto-fix: ${display.config.automation.autoFix ? 'āœ“' : 'āœ—'}`);
154
+ console.log(` Block commits: ${display.config.automation.blockCommit ? 'āœ“' : 'āœ—'}`);
155
+
156
+ // Security status
157
+ console.log('\nšŸ”’ Security Status:');
158
+ console.log(` .gitignore exists: ${display.security.gitignoreExists ? 'āœ“' : 'āœ—'}`);
159
+ console.log(` Config file ignored: ${display.security.configIgnored ? 'āœ“' : 'āœ—'}`);
160
+
161
+ // Validation status
162
+ console.log('\nāœ… Validation Status:');
163
+ console.log(` Configuration valid: ${display.validation.valid ? 'āœ“' : 'āœ—'}`);
164
+
165
+ // Show warnings/errors
166
+ if (!display.security.configIgnored) {
167
+ UIComponents.showWarningBox('Configuration file is not in .gitignore - API keys may be exposed!');
168
+ }
169
+
170
+ if (!display.validation.valid) {
171
+ UIComponents.showErrorBox('Configuration validation failed');
172
+ UIComponents.showList(display.validation.errors);
173
+ }
174
+
175
+ if (display.security.recommendations.length > 0) {
176
+ console.log('\nšŸ’” Recommendations:');
177
+ UIComponents.showList(display.security.recommendations);
178
+ }
179
+ }
180
+
181
+ async function setupApiKeys(): Promise<void> {
182
+ const apiKeys = await Prompts.setupApiKeys();
183
+
184
+ if (apiKeys.julesApiKey || apiKeys.geminiApiKey) {
185
+ await ApiKeyManager.storeApiKeys({
186
+ jules: apiKeys.julesApiKey,
187
+ gemini: apiKeys.geminiApiKey
188
+ });
189
+
190
+ UIComponents.showSuccessBox('API keys updated successfully');
191
+
192
+ // Show security reminder
193
+ const security = await GitignoreManager.isConfigSecure();
194
+ if (!security.configIgnored) {
195
+ UIComponents.showWarningBox('Remember to add .baseguardrc.json to .gitignore to protect your API keys');
196
+ }
197
+ } else {
198
+ UIComponents.showInfoBox('No API keys were configured');
199
+ }
200
+ }
201
+
202
+ async function updateTargets(options?: { add?: string; remove?: string; preset?: string }): Promise<void> {
203
+ if (options?.add) {
204
+ // Add a specific browser target
205
+ const target = ConfigurationManager.parseBrowserTarget(options.add);
206
+ if (!target) {
207
+ UIComponents.showErrorBox(`Invalid browser target format: ${options.add}`);
208
+ UIComponents.showInfoBox('Format: "browser version" (e.g., "chrome 100", "safari baseline")');
209
+ return;
210
+ }
211
+
212
+ await ConfigurationManager.addBrowserTarget(target);
213
+ UIComponents.showSuccessBox(`Added browser target: ${target.browser} ${target.minVersion}`);
214
+ return;
215
+ }
216
+
217
+ if (options?.remove) {
218
+ // Remove a specific browser target
219
+ await ConfigurationManager.removeBrowserTarget(options.remove);
220
+ UIComponents.showSuccessBox(`Removed browser target: ${options.remove}`);
221
+ return;
222
+ }
223
+
224
+ if (options?.preset) {
225
+ // Set preset targets
226
+ const presetName = options.preset as any;
227
+ const availablePresets = ConfigurationManager.getAvailablePresets();
228
+
229
+ if (!availablePresets.includes(presetName)) {
230
+ UIComponents.showErrorBox(`Invalid preset: ${options.preset}`);
231
+ UIComponents.showInfoBox(`Available presets: ${availablePresets.join(', ')}`);
232
+ return;
233
+ }
234
+
235
+ await ConfigurationManager.updateWithPreset(presetName);
236
+ UIComponents.showSuccessBox(`Updated to ${presetName} preset`);
237
+ UIComponents.showInfoBox(ConfigurationManager.getPresetDescription(presetName));
238
+ return;
239
+ }
240
+
241
+ // Interactive target configuration
242
+ const targets = await Prompts.promptCustomTargets();
243
+ await ConfigurationManager.updateWithCustomTargets(targets);
244
+ UIComponents.showSuccessBox('Browser targets updated successfully');
245
+ }
246
+
247
+ async function updateAutomation(): Promise<void> {
248
+ const automation = await Prompts.promptAutomationSettings();
249
+ const config = await ConfigurationManager.load();
250
+ config.automation = { ...config.automation, ...automation };
251
+ await ConfigurationManager.save(config);
252
+ UIComponents.showSuccessBox('Automation settings updated successfully');
253
+ }
254
+
255
+ async function updateConfiguration(): Promise<void> {
256
+ const currentConfig = await ConfigurationManager.load();
257
+ const updates = await Prompts.promptConfigUpdate(currentConfig);
258
+
259
+ if (Object.keys(updates).length === 0) {
260
+ UIComponents.showInfoBox('No changes made');
261
+ return;
262
+ }
263
+
264
+ let config = currentConfig;
265
+
266
+ // Apply updates
267
+ for (const [key, value] of Object.entries(updates)) {
268
+ switch (key) {
269
+ case 'targets':
270
+ await ConfigurationManager.updateWithCustomTargets(value as any);
271
+ config = await ConfigurationManager.load(); // Reload after update
272
+ break;
273
+ case 'apiKeys':
274
+ const apiKeys = value as any;
275
+ if (apiKeys.julesApiKey) config.apiKeys.jules = apiKeys.julesApiKey;
276
+ if (apiKeys.geminiApiKey) config.apiKeys.gemini = apiKeys.geminiApiKey;
277
+ break;
278
+ case 'automation':
279
+ config.automation = { ...config.automation, ...(value as any) };
280
+ break;
281
+ }
282
+ }
283
+
284
+ await ConfigurationManager.save(config);
285
+ UIComponents.showSuccessBox('Configuration updated successfully');
286
+ }
287
+
288
+ async function validateConfiguration(): Promise<void> {
289
+ const display = await ConfigurationManager.getConfigurationDisplay();
290
+
291
+ if (display.validation.valid) {
292
+ UIComponents.showSuccessBox('Configuration is valid');
293
+ } else {
294
+ UIComponents.showErrorBox('Configuration validation failed');
295
+ UIComponents.showList(display.validation.errors);
296
+ process.exit(1);
297
+ }
298
+ }
299
+
300
+ async function checkSecurity(): Promise<void> {
301
+ const security = await GitignoreManager.isConfigSecure();
302
+
303
+ UIComponents.showSectionHeader('Security Status');
304
+
305
+ console.log(`āœ“ .gitignore exists: ${security.gitignoreExists ? 'Yes' : 'No'}`);
306
+ console.log(`āœ“ Config file ignored: ${security.configIgnored ? 'Yes' : 'No'}`);
307
+
308
+ if (security.recommendations.length > 0) {
309
+ console.log('\nRecommendations:');
310
+ UIComponents.showList(security.recommendations);
311
+ } else {
312
+ UIComponents.showSuccessBox('Configuration is secure');
313
+ }
314
+ }
315
+
316
+ async function backupConfiguration(): Promise<void> {
317
+ try {
318
+ const backupFile = await ConfigurationManager.backupConfiguration();
319
+ UIComponents.showSuccessBox(`Configuration backed up to: ${backupFile}`);
320
+ } catch (error) {
321
+ UIComponents.showErrorBox(`Backup failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
322
+ process.exit(1);
323
+ }
324
+ }
325
+
326
+ async function restoreConfiguration(backupFile?: string): Promise<void> {
327
+ if (!backupFile) {
328
+ UIComponents.showErrorBox('Backup file path is required');
329
+ console.log('Usage: base config restore --file <backup-file>');
330
+ process.exit(1);
331
+ }
332
+
333
+ try {
334
+ await ConfigurationManager.restoreConfiguration(backupFile);
335
+ UIComponents.showSuccessBox('Configuration restored successfully');
336
+ } catch (error) {
337
+ UIComponents.showErrorBox(`Restore failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
338
+ process.exit(1);
339
+ }
340
+ }
341
+
342
+ function showConfigHelp(): void {
343
+ UIComponents.showSectionHeader('Configuration Commands');
344
+ UIComponents.showList([
345
+ 'base config show - Display current configuration',
346
+ 'base config list - List configuration summary',
347
+ 'base config list --format json - List configuration as JSON',
348
+ 'base config set-keys - Set up API keys for AI services',
349
+ 'base config targets - Configure browser targets',
350
+ 'base config targets --add "chrome 100" - Add browser target',
351
+ 'base config targets --remove chrome - Remove browser target',
352
+ 'base config targets --preset baseline-widely - Set preset targets',
353
+ 'base config automation - Configure git automation',
354
+ 'base config update - Interactive configuration update',
355
+ 'base config validate - Validate configuration file',
356
+ 'base config security - Check configuration security',
357
+ 'base config backup - Create configuration backup',
358
+ 'base config restore --file <backup> - Restore from backup',
359
+ '',
360
+ 'Shorthand commands:',
361
+ 'base add "chrome 100" - Add browser target',
362
+ 'base remove chrome - Remove browser target',
363
+ 'base list - List configuration summary'
364
+ ]);
365
+ }
@@ -0,0 +1,234 @@
1
+ import chalk from 'chalk';
2
+ import { UIComponents } from '../ui/index.js';
3
+ import { BaseGuard } from '../core/index.js';
4
+ import { ConfigurationManager } from '../core/configuration.js';
5
+ import { ErrorHandler } from '../core/error-handler.js';
6
+ import { JulesImplementer } from '../ai/jules-implementer.js';
7
+ import { GeminiAnalyzer } from '../ai/gemini-analyzer.js';
8
+ import { glob } from 'glob';
9
+
10
+ /**
11
+ * Fix violations with AI analysis and implementation
12
+ */
13
+ export async function fix(options: {
14
+ auto?: boolean;
15
+ analyzeOnly?: boolean;
16
+ files?: string;
17
+ }): Promise<void> {
18
+ try {
19
+ console.log(chalk.cyan('šŸ”§ BaseGuard AI Fix\n'));
20
+
21
+ // Load configuration
22
+ const config = await ConfigurationManager.load();
23
+
24
+ // Check API keys
25
+ if (!config.apiKeys.jules) {
26
+ UIComponents.showErrorBox('Jules API key not configured. Run "base init" to set up API keys.');
27
+ process.exit(1);
28
+ }
29
+
30
+ if (!config.apiKeys.gemini) {
31
+ UIComponents.showErrorBox('Gemini API key not configured. Run "base init" to set up API keys.');
32
+ process.exit(1);
33
+ }
34
+
35
+ // Initialize services
36
+ const baseGuard = new BaseGuard(config);
37
+ const julesImplementer = new JulesImplementer(config.apiKeys.jules);
38
+ const geminiAnalyzer = new GeminiAnalyzer(config.apiKeys.gemini);
39
+
40
+ // Check GitHub integration
41
+ const isGitHubSetup = await julesImplementer.isGitHubIntegrationSetup();
42
+ if (!isGitHubSetup) {
43
+ console.log(chalk.yellow('āš ļø Jules GitHub integration not set up'));
44
+
45
+ const { default: inquirer } = await import('inquirer');
46
+ const { setupNow } = await inquirer.prompt([
47
+ {
48
+ type: 'confirm',
49
+ name: 'setupNow',
50
+ message: 'Would you like to set up Jules GitHub integration now?',
51
+ default: true
52
+ }
53
+ ]);
54
+
55
+ if (setupNow) {
56
+ await julesImplementer.setupGitHubIntegration();
57
+ } else {
58
+ console.log(chalk.yellow('GitHub integration required for Jules fixing. Exiting.'));
59
+ process.exit(0);
60
+ }
61
+ }
62
+
63
+ // Step 1: Check for violations
64
+ console.log(chalk.cyan('šŸ” Scanning for compatibility violations...'));
65
+
66
+ // Get files to fix
67
+ const filePattern = options.files || '**/*.{js,jsx,ts,tsx,vue,svelte,css,html}';
68
+ const files = await glob(filePattern, {
69
+ ignore: [
70
+ 'node_modules/**',
71
+ 'dist/**',
72
+ 'build/**',
73
+ '.git/**',
74
+ '**/*.min.js',
75
+ '**/*.min.css'
76
+ ]
77
+ });
78
+
79
+ const violations = await baseGuard.checkViolations(files);
80
+
81
+ if (violations.length === 0) {
82
+ UIComponents.showSuccessBox('No compatibility violations found!');
83
+ return;
84
+ }
85
+
86
+ console.log(chalk.yellow(`\nāš ļø Found ${violations.length} compatibility violations\n`));
87
+ UIComponents.showViolations(violations);
88
+
89
+ // Step 2: Analyze violations with Gemini
90
+ console.log(chalk.cyan('\n🧠 Analyzing violations with AI...'));
91
+ const analyses = await geminiAnalyzer.analyzeViolations(violations);
92
+
93
+ // If analyze-only mode, show analysis and exit
94
+ if (options.analyzeOnly) {
95
+ console.log(chalk.cyan('\nšŸ“‹ Analysis Results:\n'));
96
+ analyses.forEach((analysis, index) => {
97
+ console.log(chalk.yellow(`${index + 1}. ${analysis.violation.feature} in ${analysis.violation.file}`));
98
+ console.log(` Impact: ${analysis.userImpact}`);
99
+ console.log(` Strategy: ${analysis.fixStrategy}`);
100
+ console.log(` Confidence: ${Math.round(analysis.confidence * 100)}%\n`);
101
+ });
102
+ return;
103
+ }
104
+
105
+ // Step 3: Generate and apply fixes with Jules
106
+ console.log(chalk.cyan('\nšŸ¤– Generating fixes with Jules AI...'));
107
+ const results = await julesImplementer.generateAndApplyFixes(violations, analyses);
108
+
109
+ // Show results
110
+ console.log(chalk.cyan('\nšŸ“Š Fix Results:\n'));
111
+
112
+ if (results.applied.length > 0) {
113
+ console.log(chalk.green(`āœ… Applied ${results.applied.length} fixes:`));
114
+ results.applied.forEach(fix => {
115
+ console.log(chalk.green(` • ${fix.filePath} - ${fix.violation.feature}`));
116
+ });
117
+ console.log();
118
+ }
119
+
120
+ if (results.skipped.length > 0) {
121
+ console.log(chalk.yellow(`ā­ļø Skipped ${results.skipped.length} fixes:`));
122
+ results.skipped.forEach(fix => {
123
+ console.log(chalk.yellow(` • ${fix.filePath} - ${fix.violation.feature}`));
124
+ });
125
+ console.log();
126
+ }
127
+
128
+ if (results.failed.length > 0) {
129
+ console.log(chalk.red(`āŒ Failed ${results.failed.length} fixes:`));
130
+ results.failed.forEach(({ fix, error }) => {
131
+ console.log(chalk.red(` • ${fix.filePath} - ${fix.violation.feature}: ${error}`));
132
+ });
133
+ console.log();
134
+ }
135
+
136
+ // Show rollback option if fixes were applied
137
+ if (results.applied.length > 0) {
138
+ const { default: inquirer } = await import('inquirer');
139
+ const { showRollback } = await inquirer.prompt([
140
+ {
141
+ type: 'confirm',
142
+ name: 'showRollback',
143
+ message: 'Would you like to see rollback options?',
144
+ default: false
145
+ }
146
+ ]);
147
+
148
+ if (showRollback) {
149
+ const { rollbackAction } = await inquirer.prompt([
150
+ {
151
+ type: 'list',
152
+ name: 'rollbackAction',
153
+ message: 'Rollback options:',
154
+ choices: [
155
+ { name: 'Keep all fixes', value: 'keep' },
156
+ { name: 'Rollback all fixes', value: 'rollback_all' },
157
+ { name: 'Rollback specific fixes', value: 'rollback_specific' }
158
+ ]
159
+ }
160
+ ]);
161
+
162
+ if (rollbackAction === 'rollback_all') {
163
+ await julesImplementer.rollbackAllFixes();
164
+ UIComponents.showSuccessBox('All fixes have been rolled back');
165
+ } else if (rollbackAction === 'rollback_specific') {
166
+ const appliedFiles = julesImplementer.getAppliedFixes();
167
+ const { filesToRollback } = await inquirer.prompt([
168
+ {
169
+ type: 'checkbox',
170
+ name: 'filesToRollback',
171
+ message: 'Select fixes to rollback:',
172
+ choices: appliedFiles.map(file => ({ name: file, value: file }))
173
+ }
174
+ ]);
175
+
176
+ for (const file of filesToRollback) {
177
+ await julesImplementer.rollbackFix(file);
178
+ }
179
+
180
+ if (filesToRollback.length > 0) {
181
+ UIComponents.showSuccessBox(`Rolled back ${filesToRollback.length} fixes`);
182
+ }
183
+ }
184
+ }
185
+ }
186
+
187
+ UIComponents.showSuccessBox('Fix process completed!');
188
+
189
+ } catch (error) {
190
+ const apiError = ErrorHandler.handleAPIError(error);
191
+ ErrorHandler.displayError(apiError);
192
+
193
+ // Provide specific help for fix command issues
194
+ console.log('\nšŸ’” Troubleshooting:');
195
+ if (apiError.type === 'authentication') {
196
+ UIComponents.showList([
197
+ 'Check your API keys with "base config show"',
198
+ 'Update API keys with "base config set-keys"',
199
+ 'Verify API keys are valid and not expired',
200
+ 'Ensure you have proper permissions for Jules and Gemini'
201
+ ]);
202
+ } else if (apiError.type === 'configuration') {
203
+ UIComponents.showList([
204
+ 'Run "base init" to set up BaseGuard configuration',
205
+ 'Configure API keys with "base config set-keys"',
206
+ 'Check GitHub integration for Jules fixing'
207
+ ]);
208
+ } else if (apiError.type === 'network') {
209
+ UIComponents.showList([
210
+ 'Check your internet connection',
211
+ 'Verify firewall allows access to AI services',
212
+ 'Try again when network connection is stable'
213
+ ]);
214
+ } else {
215
+ UIComponents.showList([
216
+ 'Try running "base check" for basic violation detection',
217
+ 'Verify your API keys are configured correctly',
218
+ 'Check the documentation for troubleshooting steps'
219
+ ]);
220
+ }
221
+
222
+ // Show fallback suggestions
223
+ if (ErrorHandler.shouldUseFallbackMode(apiError)) {
224
+ console.log('\nšŸ”„ Alternative options:');
225
+ UIComponents.showList([
226
+ 'Run "base check" for offline compatibility checking',
227
+ 'Review violations manually using browser compatibility tables',
228
+ 'Try AI features again when services are available'
229
+ ]);
230
+ }
231
+
232
+ process.exit(1);
233
+ }
234
+ }
@@ -0,0 +1,6 @@
1
+ // CLI command exports
2
+ export * from './init.js';
3
+ export * from './check.js';
4
+ export * from './fix.js';
5
+ export * from './config.js';
6
+ export * from './automation.js';