baseguard 1.0.5 → 1.0.6

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 (80) hide show
  1. package/dist/ai/gemini-analyzer.d.ts.map +1 -1
  2. package/dist/ai/gemini-analyzer.js +1 -1
  3. package/dist/ai/gemini-analyzer.js.map +1 -1
  4. package/dist/ai/gemini-code-fixer.d.ts.map +1 -1
  5. package/dist/ai/gemini-code-fixer.js +2 -7
  6. package/dist/ai/gemini-code-fixer.js.map +1 -1
  7. package/dist/ai/jules-implementer.d.ts +8 -0
  8. package/dist/ai/jules-implementer.d.ts.map +1 -1
  9. package/dist/ai/jules-implementer.js +115 -17
  10. package/dist/ai/jules-implementer.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/ai/__tests__/gemini-analyzer.test.ts +0 -181
  13. package/src/ai/agentkit-orchestrator.ts +0 -534
  14. package/src/ai/fix-manager.ts +0 -362
  15. package/src/ai/gemini-analyzer.ts +0 -665
  16. package/src/ai/gemini-code-fixer.ts +0 -539
  17. package/src/ai/index.ts +0 -4
  18. package/src/ai/jules-implementer.ts +0 -504
  19. package/src/ai/unified-code-fixer.ts +0 -347
  20. package/src/commands/automation.ts +0 -344
  21. package/src/commands/check.ts +0 -298
  22. package/src/commands/config.ts +0 -584
  23. package/src/commands/fix.ts +0 -269
  24. package/src/commands/index.ts +0 -7
  25. package/src/commands/init.ts +0 -156
  26. package/src/commands/status.ts +0 -307
  27. package/src/core/api-key-manager.ts +0 -298
  28. package/src/core/baseguard.ts +0 -757
  29. package/src/core/baseline-checker.ts +0 -566
  30. package/src/core/cache-manager.ts +0 -272
  31. package/src/core/configuration-recovery.ts +0 -672
  32. package/src/core/configuration.ts +0 -596
  33. package/src/core/debug-logger.ts +0 -590
  34. package/src/core/directory-filter.ts +0 -421
  35. package/src/core/error-handler.ts +0 -518
  36. package/src/core/file-processor.ts +0 -338
  37. package/src/core/gitignore-manager.ts +0 -169
  38. package/src/core/graceful-degradation-manager.ts +0 -596
  39. package/src/core/index.ts +0 -17
  40. package/src/core/lazy-loader.ts +0 -317
  41. package/src/core/logger.ts +0 -0
  42. package/src/core/memory-manager.ts +0 -290
  43. package/src/core/parser-worker.ts +0 -33
  44. package/src/core/startup-optimizer.ts +0 -246
  45. package/src/core/system-error-handler.ts +0 -755
  46. package/src/git/automation-engine.ts +0 -361
  47. package/src/git/github-manager.ts +0 -190
  48. package/src/git/hook-manager.ts +0 -210
  49. package/src/git/index.ts +0 -4
  50. package/src/index.ts +0 -8
  51. package/src/parsers/feature-validator.ts +0 -559
  52. package/src/parsers/index.ts +0 -8
  53. package/src/parsers/parser-manager.ts +0 -418
  54. package/src/parsers/parser.ts +0 -26
  55. package/src/parsers/react-parser-optimized.ts +0 -161
  56. package/src/parsers/react-parser.ts +0 -359
  57. package/src/parsers/svelte-parser.ts +0 -510
  58. package/src/parsers/vanilla-parser.ts +0 -685
  59. package/src/parsers/vue-parser.ts +0 -476
  60. package/src/types/index.ts +0 -96
  61. package/src/ui/components.ts +0 -567
  62. package/src/ui/help.ts +0 -193
  63. package/src/ui/index.ts +0 -4
  64. package/src/ui/prompts.ts +0 -681
  65. package/src/ui/terminal-header.ts +0 -59
  66. package/tests/e2e/baseguard.e2e.test.ts +0 -516
  67. package/tests/e2e/cross-platform.e2e.test.ts +0 -420
  68. package/tests/e2e/git-integration.e2e.test.ts +0 -487
  69. package/tests/fixtures/react-project/package.json +0 -14
  70. package/tests/fixtures/react-project/src/App.css +0 -76
  71. package/tests/fixtures/react-project/src/App.tsx +0 -77
  72. package/tests/fixtures/svelte-project/package.json +0 -11
  73. package/tests/fixtures/svelte-project/src/App.svelte +0 -369
  74. package/tests/fixtures/vanilla-project/index.html +0 -76
  75. package/tests/fixtures/vanilla-project/script.js +0 -331
  76. package/tests/fixtures/vanilla-project/styles.css +0 -359
  77. package/tests/fixtures/vue-project/package.json +0 -12
  78. package/tests/fixtures/vue-project/src/App.vue +0 -216
  79. package/tmp-smoke/.baseguard/backups/config-2026-02-19T12-04-11-067Z-auto.json +0 -30
  80. package/tmp-smoke/src/bad.css +0 -3
@@ -1,418 +0,0 @@
1
- import type { DetectedFeature } from '../types/index.js';
2
- import { Parser } from './parser.js';
3
- import { FeatureValidator } from './feature-validator.js';
4
- import { MemoryManager } from '../core/memory-manager.js';
5
- import { readFile, stat } from 'fs/promises';
6
- import { join } from 'path';
7
-
8
- /**
9
- * Parser manager that coordinates all parsers and provides concurrent processing
10
- * for large codebases with advanced web APIs using lazy loading
11
- */
12
- export class ParserManager {
13
- private parsers: Map<string, Parser> = new Map();
14
- private readonly validator: FeatureValidator;
15
- private readonly maxConcurrency: number;
16
- private initialized = false;
17
-
18
- constructor(maxConcurrency: number = 10) {
19
- this.validator = new FeatureValidator();
20
- this.maxConcurrency = maxConcurrency;
21
- // Don't initialize parsers immediately - use lazy loading
22
- }
23
-
24
- /**
25
- * Lazy load parsers only when needed
26
- */
27
- private async ensureParsersLoaded(): Promise<void> {
28
- if (this.initialized) {
29
- return;
30
- }
31
-
32
- try {
33
- // Dynamically import parsers to reduce startup time
34
- const [
35
- { ReactParser },
36
- { VueParser },
37
- { SvelteParser },
38
- { VanillaParser }
39
- ] = await Promise.all([
40
- import('./react-parser.js'),
41
- import('./vue-parser.js'),
42
- import('./svelte-parser.js'),
43
- import('./vanilla-parser.js')
44
- ]);
45
-
46
- this.parsers.set('react', new ReactParser());
47
- this.parsers.set('vue', new VueParser());
48
- this.parsers.set('svelte', new SvelteParser());
49
- this.parsers.set('vanilla', new VanillaParser());
50
-
51
- this.initialized = true;
52
- } catch (error) {
53
- console.warn('Failed to load some parsers:', error);
54
- this.initialized = true;
55
- }
56
- }
57
-
58
- /**
59
- * Get parser for file type with lazy loading
60
- */
61
- private async getParserForFile(filePath: string): Promise<Parser | null> {
62
- await this.ensureParsersLoaded();
63
-
64
- for (const parser of this.parsers.values()) {
65
- if (parser.canParse(filePath)) {
66
- return parser;
67
- }
68
- }
69
-
70
- return null;
71
- }
72
-
73
- /**
74
- * Parse multiple files concurrently with error handling
75
- */
76
- async parseFiles(filePaths: string[]): Promise<DetectedFeature[]> {
77
- const allFeatures: DetectedFeature[] = [];
78
-
79
- // Filter out unsupported files
80
- const supportedFiles = await this.filterSupportedFiles(filePaths);
81
-
82
- if (supportedFiles.length === 0) {
83
- return [];
84
- }
85
-
86
- // Process files in batches for better performance
87
- const batches = this.createBatches(supportedFiles, this.maxConcurrency);
88
-
89
- for (const batch of batches) {
90
- try {
91
- const batchResults = await Promise.allSettled(
92
- batch.map(filePath => this.parseFile(filePath))
93
- );
94
-
95
- batchResults.forEach((result, index) => {
96
- if (result.status === 'fulfilled') {
97
- allFeatures.push(...result.value);
98
- } else {
99
- console.warn(`Failed to parse ${batch[index]}: ${result.reason}`);
100
- }
101
- });
102
-
103
- // Small delay between batches to prevent overwhelming the system
104
- if (batches.length > 1) {
105
- await this.sleep(10);
106
- }
107
-
108
- } catch (error) {
109
- console.error(`Error processing batch: ${error instanceof Error ? error.message : 'Unknown error'}`);
110
- }
111
- }
112
-
113
- // Validate and filter features
114
- return this.validator.validateFeatures(allFeatures, this.maxConcurrency);
115
- }
116
-
117
- /**
118
- * Parse a single file with memory optimization
119
- */
120
- async parseFile(filePath: string): Promise<DetectedFeature[]> {
121
- try {
122
- // Find appropriate parser
123
- const parser = await this.getParserForFile(filePath);
124
- if (!parser) {
125
- return [];
126
- }
127
-
128
- // Check file size and use streaming for large files
129
- const fileStats = await stat(filePath);
130
-
131
- if (MemoryManager.shouldStream(fileStats.size)) {
132
- return await this.parseFileStreaming(filePath, parser);
133
- }
134
-
135
- // Read file content for smaller files
136
- const content = await readFile(filePath, 'utf-8');
137
-
138
- // Parse features
139
- const features = await parser.parseFeatures(content, filePath);
140
-
141
- // Add file path to features for tracking and optimize memory
142
- return features.map(feature => MemoryManager.optimizeObject({
143
- ...feature,
144
- file: filePath
145
- }));
146
-
147
- } catch (error) {
148
- // Graceful error handling for unsupported files and syntax errors
149
- if (error instanceof Error) {
150
- if (error.message.includes('ENOENT')) {
151
- console.warn(`File not found: ${filePath}`);
152
- } else if (error.message.includes('SyntaxError') || error.message.includes('Unexpected token')) {
153
- console.warn(`Syntax error in ${filePath}: ${error.message}`);
154
- } else {
155
- console.warn(`Error parsing ${filePath}: ${error.message}`);
156
- }
157
- } else {
158
- console.warn(`Unknown error parsing ${filePath}`);
159
- }
160
- return [];
161
- }
162
- }
163
-
164
- /**
165
- * Parse large files using streaming to reduce memory usage
166
- */
167
- private async parseFileStreaming(filePath: string, parser: Parser): Promise<DetectedFeature[]> {
168
- const features: DetectedFeature[] = [];
169
-
170
- await MemoryManager.readFileStreaming(filePath, async (chunk, startLine) => {
171
- try {
172
- const chunkFeatures = await parser.parseFeatures(chunk, filePath);
173
-
174
- // Adjust line numbers for chunk offset
175
- const adjustedFeatures = chunkFeatures.map(feature => ({
176
- ...feature,
177
- line: feature.line + startLine - 1,
178
- file: filePath
179
- }));
180
-
181
- features.push(...adjustedFeatures);
182
- } catch (error) {
183
- // Continue processing other chunks even if one fails
184
- console.warn(`Error parsing chunk in ${filePath}: ${error}`);
185
- }
186
- });
187
-
188
- return features;
189
- }
190
-
191
- /**
192
- * Check if a file can be parsed by any available parser
193
- */
194
- async canParseFile(filePath: string): Promise<boolean> {
195
- await this.ensureParsersLoaded();
196
-
197
- for (const parser of this.parsers.values()) {
198
- if (parser.canParse(filePath)) {
199
- return true;
200
- }
201
- }
202
-
203
- return false;
204
- }
205
-
206
- /**
207
- * Get all supported file extensions
208
- */
209
- async getSupportedExtensions(): Promise<string[]> {
210
- await this.ensureParsersLoaded();
211
-
212
- const extensions = new Set<string>();
213
- this.parsers.forEach(parser => {
214
- parser.getSupportedExtensions().forEach(ext => extensions.add(ext));
215
- });
216
- return Array.from(extensions);
217
- }
218
-
219
- /**
220
- * Get parser information for debugging
221
- */
222
- async getParserInfo(): Promise<Array<{ name: string; extensions: string[] }>> {
223
- await this.ensureParsersLoaded();
224
-
225
- return Array.from(this.parsers.values()).map(parser => ({
226
- name: parser.getName(),
227
- extensions: parser.getSupportedExtensions()
228
- }));
229
- }
230
-
231
- /**
232
- * Filter files by supported extensions
233
- */
234
- async filterSupportedFiles(filePaths: string[]): Promise<string[]> {
235
- const supportedExtensions = await this.getSupportedExtensions();
236
- return filePaths.filter(filePath => {
237
- const extension = this.getFileExtension(filePath);
238
- return supportedExtensions.includes(extension);
239
- });
240
- }
241
-
242
- /**
243
- * Scan directory for supported files (recursive)
244
- */
245
- async scanDirectory(
246
- directoryPath: string,
247
- options: {
248
- recursive?: boolean;
249
- excludePatterns?: string[];
250
- maxDepth?: number;
251
- } = {}
252
- ): Promise<string[]> {
253
- const {
254
- recursive = true,
255
- excludePatterns = ['node_modules', '.git', 'dist', 'build', '.next', '.nuxt'],
256
- maxDepth = 10
257
- } = options;
258
-
259
- const supportedFiles: string[] = [];
260
-
261
- try {
262
- await this.scanDirectoryRecursive(
263
- directoryPath,
264
- supportedFiles,
265
- excludePatterns,
266
- recursive,
267
- 0,
268
- maxDepth
269
- );
270
- } catch (error) {
271
- console.error(`Error scanning directory ${directoryPath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
272
- }
273
-
274
- return supportedFiles;
275
- }
276
-
277
- /**
278
- * Recursive directory scanning helper
279
- */
280
- private async scanDirectoryRecursive(
281
- currentPath: string,
282
- results: string[],
283
- excludePatterns: string[],
284
- recursive: boolean,
285
- currentDepth: number,
286
- maxDepth: number
287
- ): Promise<void> {
288
- if (currentDepth >= maxDepth) {
289
- return;
290
- }
291
-
292
- try {
293
- const { readdir, stat } = await import('fs/promises');
294
- const entries = await readdir(currentPath);
295
-
296
- for (const entry of entries) {
297
- const fullPath = join(currentPath, entry);
298
-
299
- // Skip excluded patterns
300
- if (excludePatterns.some(pattern => entry.includes(pattern))) {
301
- continue;
302
- }
303
-
304
- try {
305
- const stats = await stat(fullPath);
306
-
307
- if (stats.isFile()) {
308
- if (await this.canParseFile(fullPath)) {
309
- results.push(fullPath);
310
- }
311
- } else if (stats.isDirectory() && recursive) {
312
- await this.scanDirectoryRecursive(
313
- fullPath,
314
- results,
315
- excludePatterns,
316
- recursive,
317
- currentDepth + 1,
318
- maxDepth
319
- );
320
- }
321
- } catch (error) {
322
- // Skip files/directories that can't be accessed
323
- continue;
324
- }
325
- }
326
- } catch (error) {
327
- console.warn(`Could not read directory ${currentPath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
328
- }
329
- }
330
-
331
- /**
332
- * Get processing statistics
333
- */
334
- async getProcessingStats(filePaths: string[]): Promise<{
335
- totalFiles: number;
336
- supportedFiles: number;
337
- filesByType: Record<string, number>;
338
- estimatedProcessingTime: number;
339
- memoryEstimate: string;
340
- }> {
341
- const supportedFiles = await this.filterSupportedFiles(filePaths);
342
- const filesByType: Record<string, number> = {};
343
-
344
- supportedFiles.forEach(filePath => {
345
- const extension = this.getFileExtension(filePath);
346
- filesByType[extension] = (filesByType[extension] || 0) + 1;
347
- });
348
-
349
- // Rough estimation: 10ms per file on average
350
- const estimatedProcessingTime = Math.ceil(supportedFiles.length * 10 / this.maxConcurrency);
351
-
352
- // Memory estimate: ~50KB per file on average
353
- const memoryEstimate = `${Math.round(supportedFiles.length * 50 / 1024)}MB`;
354
-
355
- return {
356
- totalFiles: filePaths.length,
357
- supportedFiles: supportedFiles.length,
358
- filesByType,
359
- estimatedProcessingTime,
360
- memoryEstimate
361
- };
362
- }
363
-
364
- /**
365
- * Get memory and performance statistics
366
- */
367
- getStats(): {
368
- parsersLoaded: number;
369
- maxConcurrency: number;
370
- memoryStats: any;
371
- } {
372
- return {
373
- parsersLoaded: this.parsers.size,
374
- maxConcurrency: this.maxConcurrency,
375
- memoryStats: MemoryManager.getMemoryStats()
376
- };
377
- }
378
-
379
- /**
380
- * Create batches for concurrent processing
381
- */
382
- private createBatches<T>(items: T[], batchSize: number): T[][] {
383
- const batches: T[][] = [];
384
- for (let i = 0; i < items.length; i += batchSize) {
385
- batches.push(items.slice(i, i + batchSize));
386
- }
387
- return batches;
388
- }
389
-
390
- /**
391
- * Get file extension
392
- */
393
- private getFileExtension(filePath: string): string {
394
- const match = filePath.match(/\.[^.]+$/);
395
- return match ? match[0] : '';
396
- }
397
-
398
- /**
399
- * Sleep utility for batch processing
400
- */
401
- private sleep(ms: number): Promise<void> {
402
- return new Promise(resolve => setTimeout(resolve, ms));
403
- }
404
-
405
- /**
406
- * Get feature validator instance
407
- */
408
- getValidator(): FeatureValidator {
409
- return this.validator;
410
- }
411
-
412
- /**
413
- * Validate features without parsing (for external use)
414
- */
415
- async validateFeatures(features: DetectedFeature[]): Promise<DetectedFeature[]> {
416
- return this.validator.validateFeatures(features, this.maxConcurrency);
417
- }
418
- }
@@ -1,26 +0,0 @@
1
- import type { DetectedFeature } from '../types/index.js';
2
-
3
- /**
4
- * Abstract base class for all code parsers
5
- */
6
- export abstract class Parser {
7
- /**
8
- * Check if this parser can handle the given file
9
- */
10
- abstract canParse(filePath: string): boolean;
11
-
12
- /**
13
- * Parse features from file content
14
- */
15
- abstract parseFeatures(content: string, filePath: string): Promise<DetectedFeature[]>;
16
-
17
- /**
18
- * Get supported file extensions for this parser
19
- */
20
- abstract getSupportedExtensions(): string[];
21
-
22
- /**
23
- * Get parser name for identification
24
- */
25
- abstract getName(): string;
26
- }
@@ -1,161 +0,0 @@
1
- import { Parser } from './parser.js';
2
- import type { DetectedFeature } from '../types/index.js';
3
- import { LazyLoader } from '../core/lazy-loader.js';
4
-
5
- /**
6
- * Optimized React/JSX parser using lazy loading
7
- */
8
- export class ReactParser extends Parser {
9
- getName(): string {
10
- return 'ReactParser';
11
- }
12
-
13
- getSupportedExtensions(): string[] {
14
- return ['.jsx', '.tsx'];
15
- }
16
-
17
- canParse(filePath: string): boolean {
18
- return /\.(jsx|tsx)$/.test(filePath);
19
- }
20
-
21
- async parseFeatures(content: string, filePath: string): Promise<DetectedFeature[]> {
22
- const features: DetectedFeature[] = [];
23
-
24
- try {
25
- // Lazy load Babel dependencies only when needed
26
- const [parser, traverse] = await Promise.all([
27
- LazyLoader.getBabelParser(),
28
- LazyLoader.getBabelTraverse()
29
- ]);
30
-
31
- const ast = parser.parse(content, {
32
- sourceType: 'module',
33
- plugins: [
34
- 'jsx',
35
- 'typescript',
36
- 'decorators-legacy',
37
- 'classProperties',
38
- 'objectRestSpread',
39
- 'asyncGenerators',
40
- 'functionBind',
41
- 'exportDefaultFrom',
42
- 'exportNamespaceFrom',
43
- 'dynamicImport',
44
- 'nullishCoalescingOperator',
45
- 'optionalChaining',
46
- 'topLevelAwait'
47
- ]
48
- });
49
-
50
- // Simple feature extraction optimized for performance
51
- traverse(ast, {
52
- MemberExpression: (path: any) => {
53
- const apiName = this.extractAPIName(path.node);
54
- if (apiName && this.isWebPlatformAPI(apiName)) {
55
- features.push({
56
- feature: apiName,
57
- type: 'js',
58
- context: this.getContext(content, path.node.loc?.start.line || 0),
59
- line: path.node.loc?.start.line || 0,
60
- column: path.node.loc?.start.column || 0,
61
- file: filePath
62
- });
63
- }
64
- },
65
-
66
- CallExpression: (path: any) => {
67
- const apiName = this.extractCallName(path.node);
68
- if (apiName && this.isWebPlatformAPI(apiName)) {
69
- features.push({
70
- feature: apiName,
71
- type: 'js',
72
- context: this.getContext(content, path.node.loc?.start.line || 0),
73
- line: path.node.loc?.start.line || 0,
74
- column: path.node.loc?.start.column || 0,
75
- file: filePath
76
- });
77
- }
78
- },
79
-
80
- OptionalMemberExpression: (path: any) => {
81
- features.push({
82
- feature: 'optional-chaining',
83
- type: 'js',
84
- context: this.getContext(content, path.node.loc?.start.line || 0),
85
- line: path.node.loc?.start.line || 0,
86
- column: path.node.loc?.start.column || 0,
87
- file: filePath
88
- });
89
- },
90
-
91
- LogicalExpression: (path: any) => {
92
- if (path.node.operator === '??') {
93
- features.push({
94
- feature: 'nullish-coalescing',
95
- type: 'js',
96
- context: this.getContext(content, path.node.loc?.start.line || 0),
97
- line: path.node.loc?.start.line || 0,
98
- column: path.node.loc?.start.column || 0,
99
- file: filePath
100
- });
101
- }
102
- }
103
- });
104
-
105
- } catch (error) {
106
- console.warn(`Warning: Could not parse React file ${filePath}: ${error instanceof Error ? error.message : 'Unknown error'}`);
107
- }
108
-
109
- return features;
110
- }
111
-
112
- private extractAPIName(node: any): string | null {
113
- try {
114
- if (node.object && node.property) {
115
- const objectName = node.object.name || 'unknown';
116
- const propertyName = node.property.name || node.property.value || 'unknown';
117
- return `${objectName}.${propertyName}`;
118
- }
119
- } catch {
120
- // Ignore errors
121
- }
122
- return null;
123
- }
124
-
125
- private extractCallName(node: any): string | null {
126
- try {
127
- if (node.callee) {
128
- if (node.callee.name) {
129
- return node.callee.name;
130
- }
131
- if (node.callee.object && node.callee.property) {
132
- const objectName = node.callee.object.name || 'unknown';
133
- const propertyName = node.callee.property.name || node.callee.property.value || 'unknown';
134
- return `${objectName}.${propertyName}`;
135
- }
136
- }
137
- } catch {
138
- // Ignore errors
139
- }
140
- return null;
141
- }
142
-
143
- private isWebPlatformAPI(apiName: string): boolean {
144
- const webAPIs = [
145
- 'fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource',
146
- 'navigator.serviceWorker', 'caches', 'Cache',
147
- 'ResizeObserver', 'IntersectionObserver', 'MutationObserver',
148
- 'canvas.getContext', 'WebGLRenderingContext', 'WebGL2RenderingContext',
149
- 'RTCPeerConnection', 'getUserMedia', 'MediaStream',
150
- 'WebAssembly', 'structuredClone', 'queueMicrotask',
151
- 'requestAnimationFrame', 'requestIdleCallback'
152
- ];
153
-
154
- return webAPIs.some(api => apiName.includes(api) || api.includes(apiName));
155
- }
156
-
157
- private getContext(content: string, line: number): string {
158
- const lines = content.split('\n');
159
- return lines[line - 1]?.trim() || '';
160
- }
161
- }