baseguard 1.0.4 → 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 (84) 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/dist/commands/fix.d.ts.map +1 -1
  12. package/dist/commands/fix.js +5 -1
  13. package/dist/commands/fix.js.map +1 -1
  14. package/dist/core/baseline-checker.d.ts.map +1 -1
  15. package/dist/core/baseline-checker.js +6 -4
  16. package/dist/core/baseline-checker.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/ai/__tests__/gemini-analyzer.test.ts +0 -181
  19. package/src/ai/agentkit-orchestrator.ts +0 -534
  20. package/src/ai/fix-manager.ts +0 -362
  21. package/src/ai/gemini-analyzer.ts +0 -665
  22. package/src/ai/gemini-code-fixer.ts +0 -539
  23. package/src/ai/index.ts +0 -4
  24. package/src/ai/jules-implementer.ts +0 -504
  25. package/src/ai/unified-code-fixer.ts +0 -347
  26. package/src/commands/automation.ts +0 -344
  27. package/src/commands/check.ts +0 -298
  28. package/src/commands/config.ts +0 -584
  29. package/src/commands/fix.ts +0 -264
  30. package/src/commands/index.ts +0 -7
  31. package/src/commands/init.ts +0 -156
  32. package/src/commands/status.ts +0 -307
  33. package/src/core/api-key-manager.ts +0 -298
  34. package/src/core/baseguard.ts +0 -757
  35. package/src/core/baseline-checker.ts +0 -564
  36. package/src/core/cache-manager.ts +0 -272
  37. package/src/core/configuration-recovery.ts +0 -672
  38. package/src/core/configuration.ts +0 -596
  39. package/src/core/debug-logger.ts +0 -590
  40. package/src/core/directory-filter.ts +0 -421
  41. package/src/core/error-handler.ts +0 -518
  42. package/src/core/file-processor.ts +0 -338
  43. package/src/core/gitignore-manager.ts +0 -169
  44. package/src/core/graceful-degradation-manager.ts +0 -596
  45. package/src/core/index.ts +0 -17
  46. package/src/core/lazy-loader.ts +0 -317
  47. package/src/core/logger.ts +0 -0
  48. package/src/core/memory-manager.ts +0 -290
  49. package/src/core/parser-worker.ts +0 -33
  50. package/src/core/startup-optimizer.ts +0 -246
  51. package/src/core/system-error-handler.ts +0 -755
  52. package/src/git/automation-engine.ts +0 -361
  53. package/src/git/github-manager.ts +0 -190
  54. package/src/git/hook-manager.ts +0 -210
  55. package/src/git/index.ts +0 -4
  56. package/src/index.ts +0 -8
  57. package/src/parsers/feature-validator.ts +0 -559
  58. package/src/parsers/index.ts +0 -8
  59. package/src/parsers/parser-manager.ts +0 -418
  60. package/src/parsers/parser.ts +0 -26
  61. package/src/parsers/react-parser-optimized.ts +0 -161
  62. package/src/parsers/react-parser.ts +0 -359
  63. package/src/parsers/svelte-parser.ts +0 -510
  64. package/src/parsers/vanilla-parser.ts +0 -685
  65. package/src/parsers/vue-parser.ts +0 -476
  66. package/src/types/index.ts +0 -96
  67. package/src/ui/components.ts +0 -567
  68. package/src/ui/help.ts +0 -193
  69. package/src/ui/index.ts +0 -4
  70. package/src/ui/prompts.ts +0 -681
  71. package/src/ui/terminal-header.ts +0 -59
  72. package/tests/e2e/baseguard.e2e.test.ts +0 -516
  73. package/tests/e2e/cross-platform.e2e.test.ts +0 -420
  74. package/tests/e2e/git-integration.e2e.test.ts +0 -487
  75. package/tests/fixtures/react-project/package.json +0 -14
  76. package/tests/fixtures/react-project/src/App.css +0 -76
  77. package/tests/fixtures/react-project/src/App.tsx +0 -77
  78. package/tests/fixtures/svelte-project/package.json +0 -11
  79. package/tests/fixtures/svelte-project/src/App.svelte +0 -369
  80. package/tests/fixtures/vanilla-project/index.html +0 -76
  81. package/tests/fixtures/vanilla-project/script.js +0 -331
  82. package/tests/fixtures/vanilla-project/styles.css +0 -359
  83. package/tests/fixtures/vue-project/package.json +0 -12
  84. package/tests/fixtures/vue-project/src/App.vue +0 -216
@@ -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
- }