aios-core 4.2.13 → 4.2.15

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 (95) hide show
  1. package/.aios-core/core/code-intel/helpers/dev-helper.js +206 -0
  2. package/.aios-core/core/registry/registry-schema.json +166 -166
  3. package/.aios-core/core/synapse/diagnostics/collectors/hook-collector.js +3 -3
  4. package/.aios-core/data/entity-registry.yaml +27 -0
  5. package/.aios-core/development/scripts/approval-workflow.js +642 -642
  6. package/.aios-core/development/scripts/backup-manager.js +606 -606
  7. package/.aios-core/development/scripts/branch-manager.js +389 -389
  8. package/.aios-core/development/scripts/code-quality-improver.js +1311 -1311
  9. package/.aios-core/development/scripts/commit-message-generator.js +849 -849
  10. package/.aios-core/development/scripts/conflict-resolver.js +674 -674
  11. package/.aios-core/development/scripts/dependency-analyzer.js +637 -637
  12. package/.aios-core/development/scripts/diff-generator.js +351 -351
  13. package/.aios-core/development/scripts/elicitation-engine.js +384 -384
  14. package/.aios-core/development/scripts/elicitation-session-manager.js +299 -299
  15. package/.aios-core/development/scripts/git-wrapper.js +461 -461
  16. package/.aios-core/development/scripts/manifest-preview.js +244 -244
  17. package/.aios-core/development/scripts/metrics-tracker.js +775 -775
  18. package/.aios-core/development/scripts/modification-validator.js +554 -554
  19. package/.aios-core/development/scripts/pattern-learner.js +1224 -1224
  20. package/.aios-core/development/scripts/performance-analyzer.js +757 -757
  21. package/.aios-core/development/scripts/refactoring-suggester.js +1138 -1138
  22. package/.aios-core/development/scripts/rollback-handler.js +530 -530
  23. package/.aios-core/development/scripts/security-checker.js +358 -358
  24. package/.aios-core/development/scripts/template-engine.js +239 -239
  25. package/.aios-core/development/scripts/template-validator.js +278 -278
  26. package/.aios-core/development/scripts/test-generator.js +843 -843
  27. package/.aios-core/development/scripts/transaction-manager.js +589 -589
  28. package/.aios-core/development/scripts/usage-tracker.js +673 -673
  29. package/.aios-core/development/scripts/validate-filenames.js +226 -226
  30. package/.aios-core/development/scripts/version-tracker.js +526 -526
  31. package/.aios-core/development/scripts/yaml-validator.js +396 -396
  32. package/.aios-core/development/tasks/build-autonomous.md +10 -4
  33. package/.aios-core/development/tasks/create-service.md +23 -0
  34. package/.aios-core/development/tasks/dev-develop-story.md +12 -6
  35. package/.aios-core/development/tasks/dev-suggest-refactoring.md +7 -1
  36. package/.aios-core/development/tasks/publish-npm.md +3 -3
  37. package/.aios-core/hooks/unified/README.md +1 -1
  38. package/.aios-core/install-manifest.yaml +65 -61
  39. package/.aios-core/manifests/schema/manifest-schema.json +190 -190
  40. package/.aios-core/product/templates/component-react-tmpl.tsx +98 -98
  41. package/.aios-core/product/templates/engine/schemas/adr.schema.json +102 -102
  42. package/.aios-core/product/templates/engine/schemas/dbdr.schema.json +205 -205
  43. package/.aios-core/product/templates/engine/schemas/epic.schema.json +175 -175
  44. package/.aios-core/product/templates/engine/schemas/pmdr.schema.json +175 -175
  45. package/.aios-core/product/templates/engine/schemas/prd-v2.schema.json +300 -300
  46. package/.aios-core/product/templates/engine/schemas/prd.schema.json +152 -152
  47. package/.aios-core/product/templates/engine/schemas/story.schema.json +222 -222
  48. package/.aios-core/product/templates/engine/schemas/task.schema.json +154 -154
  49. package/.aios-core/product/templates/eslintrc-security.json +32 -32
  50. package/.aios-core/product/templates/github-actions-cd.yml +212 -212
  51. package/.aios-core/product/templates/github-actions-ci.yml +172 -172
  52. package/.aios-core/product/templates/shock-report-tmpl.html +502 -502
  53. package/.aios-core/product/templates/token-exports-css-tmpl.css +240 -240
  54. package/.aios-core/quality/schemas/quality-metrics.schema.json +233 -233
  55. package/.aios-core/scripts/migrate-framework-docs.sh +300 -300
  56. package/README.en.md +747 -0
  57. package/README.md +4 -2
  58. package/bin/aios.js +7 -4
  59. package/package.json +1 -1
  60. package/packages/aios-pro-cli/src/recover.js +1 -1
  61. package/packages/installer/src/wizard/ide-config-generator.js +6 -6
  62. package/packages/installer/src/wizard/pro-setup.js +3 -3
  63. package/pro/license/degradation.js +220 -220
  64. package/pro/license/errors.js +450 -450
  65. package/pro/license/feature-gate.js +354 -354
  66. package/pro/license/index.js +181 -181
  67. package/pro/license/license-cache.js +523 -523
  68. package/pro/license/license-crypto.js +303 -303
  69. package/scripts/package-synapse.js +5 -5
  70. package/scripts/validate-package-completeness.js +3 -3
  71. package/.aios-core/.session/current-session.json +0 -14
  72. package/.aios-core/data/registry-update-log.jsonl +0 -191
  73. package/.aios-core/docs/SHARD-TRANSLATION-GUIDE.md +0 -335
  74. package/.aios-core/docs/component-creation-guide.md +0 -458
  75. package/.aios-core/docs/session-update-pattern.md +0 -307
  76. package/.aios-core/docs/standards/AIOS-FRAMEWORK-MASTER.md +0 -1963
  77. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-SUMMARY.md +0 -1190
  78. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1.md +0 -439
  79. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO.md +0 -5398
  80. package/.aios-core/docs/standards/V3-ARCHITECTURAL-DECISIONS.md +0 -523
  81. package/.aios-core/docs/template-syntax.md +0 -267
  82. package/.aios-core/docs/troubleshooting-guide.md +0 -625
  83. package/.aios-core/infrastructure/tests/utilities-audit-results.json +0 -501
  84. package/.aios-core/manifests/agents.csv +0 -29
  85. package/.aios-core/manifests/tasks.csv +0 -198
  86. package/.aios-core/manifests/workers.csv +0 -204
  87. package/.claude/rules/agent-authority.md +0 -105
  88. package/.claude/rules/coderabbit-integration.md +0 -93
  89. package/.claude/rules/ids-principles.md +0 -112
  90. package/.claude/rules/story-lifecycle.md +0 -139
  91. package/.claude/rules/workflow-execution.md +0 -150
  92. package/scripts/glue/README.md +0 -355
  93. package/scripts/glue/compose-agent-prompt.cjs +0 -362
  94. /package/.claude/hooks/{precompact-session-digest.js → precompact-session-digest.cjs} +0 -0
  95. /package/.claude/hooks/{synapse-engine.js → synapse-engine.cjs} +0 -0
@@ -1,758 +1,758 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
- const chalk = require('chalk');
4
-
5
- /**
6
- * Performance bottleneck analyzer for AIOS-FULLSTACK framework
7
- * Identifies performance issues and optimization opportunities
8
- */
9
- class PerformanceAnalyzer {
10
- constructor(options = {}) {
11
- this.rootPath = options.rootPath || process.cwd();
12
- this.thresholds = {
13
- fileSize: 50 * 1024, // 50KB
14
- functionLength: 50, // lines
15
- cyclomaticComplexity: 10,
16
- nestingDepth: 5,
17
- importCount: 20,
18
- unusedCode: 0.1 // 10% unused code ratio
19
- };
20
- this.performancePatterns = {
21
- // Sync operations that should be async
22
- syncOperations: [
23
- /fs\.readFileSync/g,
24
- /fs\.writeFileSync/g,
25
- /fs\.existsSync/g,
26
- /JSON\.parse\(\s*fs\.readFileSync/g
27
- ],
28
- // Memory-intensive patterns
29
- memoryIssues: [
30
- /\.map\(\s*.*\.map\(/g, // Nested maps
31
- /new Array\(\d{4,}\)/g, // Large arrays
32
- /JSON\.stringify.*JSON\.parse/g, // Unnecessary serialization
33
- /require\(\s*['"`][^'"`]+\.json['"`]\s*\)/g // Large JSON imports
34
- ],
35
- // Performance anti-patterns
36
- antiPatterns: [
37
- /console\.log/g, // Console logs in production
38
- /debugger/g, // Debugger statements
39
- /setTimeout\(\s*.*,\s*0\s*\)/g, // Unnecessary setTimeout
40
- /setInterval\(\s*.*,\s*[0-9]{1,2}\s*\)/g // High-frequency intervals
41
- ],
42
- // Inefficient loops
43
- inefficientLoops: [
44
- /for\s*\(\s*.*\.length\s*;/g, // Length calculated in loop condition
45
- /while\s*\(\s*true\s*\)/g, // Infinite loops
46
- /forEach.*forEach/g // Nested forEach
47
- ]
48
- };
49
- }
50
-
51
- /**
52
- * Analyze performance across all components
53
- */
54
- async analyzePerformance(components) {
55
- const analysis = {
56
- timestamp: new Date().toISOString(),
57
- overall_score: 0,
58
- bottlenecks: [],
59
- optimization_opportunities: [],
60
- memory_issues: [],
61
- async_opportunities: [],
62
- code_quality_issues: [],
63
- file_size_issues: [],
64
- complexity_issues: [],
65
- recommendations: [],
66
- metrics: {
67
- total_files_analyzed: 0,
68
- total_issues_found: 0,
69
- critical_issues: 0,
70
- high_priority_issues: 0,
71
- medium_priority_issues: 0,
72
- low_priority_issues: 0
73
- }
74
- };
75
-
76
- try {
77
- console.log(chalk.blue('🔍 Analyzing performance bottlenecks...'));
78
-
79
- // Analyze each component
80
- for (const component of components) {
81
- const componentAnalysis = await this.analyzeComponentPerformance(component);
82
-
83
- // Aggregate results
84
- analysis.bottlenecks.push(...componentAnalysis.bottlenecks);
85
- analysis.optimization_opportunities.push(...componentAnalysis.optimizations);
86
- analysis.memory_issues.push(...componentAnalysis.memory_issues);
87
- analysis.async_opportunities.push(...componentAnalysis.async_opportunities);
88
- analysis.code_quality_issues.push(...componentAnalysis.quality_issues);
89
- analysis.file_size_issues.push(...componentAnalysis.file_size_issues);
90
- analysis.complexity_issues.push(...componentAnalysis.complexity_issues);
91
-
92
- analysis.metrics.total_files_analyzed++;
93
- }
94
-
95
- // Calculate overall metrics
96
- analysis.overall_score = this.calculateOverallScore(analysis);
97
- analysis.metrics.total_issues_found = this.countTotalIssues(analysis);
98
- analysis.metrics = this.calculateIssuePriorities(analysis);
99
- analysis.recommendations = this.generatePerformanceRecommendations(analysis);
100
-
101
- console.log(chalk.green(`✅ Performance analysis completed`));
102
- console.log(chalk.gray(` Files analyzed: ${analysis.metrics.total_files_analyzed}`));
103
- console.log(chalk.gray(` Issues found: ${analysis.metrics.total_issues_found}`));
104
- console.log(chalk.gray(` Overall score: ${analysis.overall_score}/10`));
105
-
106
- return analysis;
107
-
108
- } catch (error) {
109
- console.error(chalk.red(`Performance analysis failed: ${error.message}`));
110
- throw error;
111
- }
112
- }
113
-
114
- /**
115
- * Analyze performance for a single component
116
- */
117
- async analyzeComponentPerformance(component) {
118
- const analysis = {
119
- component_id: component.id,
120
- component_type: component.type,
121
- bottlenecks: [],
122
- optimizations: [],
123
- memory_issues: [],
124
- async_opportunities: [],
125
- quality_issues: [],
126
- file_size_issues: [],
127
- complexity_issues: []
128
- };
129
-
130
- try {
131
- // Only analyze JavaScript files and executable components
132
- if (!this.shouldAnalyzeComponent(component)) {
133
- return analysis;
134
- }
135
-
136
- const filePath = path.join(this.rootPath, component.file_path);
137
- const content = await fs.readFile(filePath, 'utf-8');
138
- const stats = await fs.stat(filePath);
139
-
140
- // File size analysis
141
- if (stats.size > this.thresholds.fileSize) {
142
- analysis.file_size_issues.push({
143
- component: component.id,
144
- issue: `Large file size: ${this.formatBytes(stats.size)}`,
145
- severity: stats.size > this.thresholds.fileSize * 2 ? 'high' : 'medium',
146
- recommendation: 'Consider breaking down into smaller modules',
147
- impact: 'high',
148
- effort: 'medium'
149
- });
150
- }
151
-
152
- // Synchronous operations analysis
153
- const syncIssues = this.findSyncOperations(content, component);
154
- analysis.async_opportunities.push(...syncIssues);
155
-
156
- // Memory usage analysis
157
- const memoryIssues = this.findMemoryIssues(content, component);
158
- analysis.memory_issues.push(...memoryIssues);
159
-
160
- // Performance anti-patterns
161
- const antiPatterns = this.findAntiPatterns(content, component);
162
- analysis.quality_issues.push(...antiPatterns);
163
-
164
- // Loop efficiency analysis
165
- const loopIssues = this.findLoopIssues(content, component);
166
- analysis.bottlenecks.push(...loopIssues);
167
-
168
- // Function complexity analysis
169
- const complexityIssues = this.analyzeComplexity(content, component);
170
- analysis.complexity_issues.push(...complexityIssues);
171
-
172
- // Import/require analysis
173
- const importIssues = this.analyzeImports(content, component);
174
- analysis.optimizations.push(...importIssues);
175
-
176
- // Dead code analysis
177
- const deadCodeIssues = await this.findDeadCode(content, component);
178
- analysis.optimizations.push(...deadCodeIssues);
179
-
180
- } catch (error) {
181
- console.warn(chalk.yellow(`Failed to analyze performance for ${component.id}: ${error.message}`));
182
- }
183
-
184
- return analysis;
185
- }
186
-
187
- /**
188
- * Find synchronous operations that should be async
189
- */
190
- findSyncOperations(content, component) {
191
- const issues = [];
192
- const lines = content.split('\n');
193
-
194
- this.performancePatterns.syncOperations.forEach(pattern => {
195
- lines.forEach((line, index) => {
196
- const matches = line.match(pattern);
197
- if (matches) {
198
- matches.forEach(match => {
199
- issues.push({
200
- component: component.id,
201
- issue: `Synchronous operation: ${match}`,
202
- line: index + 1,
203
- context: line.trim(),
204
- severity: 'high',
205
- recommendation: 'Convert to async equivalent',
206
- impact: 'high',
207
- effort: 'low'
208
- });
209
- });
210
- }
211
- });
212
- });
213
-
214
- return issues;
215
- }
216
-
217
- /**
218
- * Find memory-intensive patterns
219
- */
220
- findMemoryIssues(content, component) {
221
- const issues = [];
222
- const lines = content.split('\n');
223
-
224
- this.performancePatterns.memoryIssues.forEach(pattern => {
225
- lines.forEach((line, index) => {
226
- const matches = line.match(pattern);
227
- if (matches) {
228
- matches.forEach(match => {
229
- let severity = 'medium';
230
- let recommendation = 'Optimize memory usage';
231
-
232
- if (match.includes('new Array')) {
233
- severity = 'high';
234
- recommendation = 'Use array literals or streaming for large datasets';
235
- } else if (match.includes('JSON.stringify.*JSON.parse')) {
236
- recommendation = 'Use direct object assignment or deep clone utilities';
237
- } else if (match.includes('.map(.*map(')) {
238
- recommendation = 'Combine operations or use more efficient iteration';
239
- }
240
-
241
- issues.push({
242
- component: component.id,
243
- issue: `Memory-intensive pattern: ${match}`,
244
- line: index + 1,
245
- context: line.trim(),
246
- severity,
247
- recommendation,
248
- impact: 'medium',
249
- effort: 'medium'
250
- });
251
- });
252
- }
253
- });
254
- });
255
-
256
- return issues;
257
- }
258
-
259
- /**
260
- * Find performance anti-patterns
261
- */
262
- findAntiPatterns(content, component) {
263
- const issues = [];
264
- const lines = content.split('\n');
265
-
266
- this.performancePatterns.antiPatterns.forEach(pattern => {
267
- lines.forEach((line, index) => {
268
- const matches = line.match(pattern);
269
- if (matches) {
270
- matches.forEach(match => {
271
- let severity = 'low';
272
- let recommendation = 'Remove or optimize';
273
-
274
- if (match.includes('console.log')) {
275
- recommendation = 'Remove console.log statements from production code';
276
- } else if (match.includes('debugger')) {
277
- severity = 'medium';
278
- recommendation = 'Remove debugger statements';
279
- } else if (match.includes('setTimeout')) {
280
- recommendation = 'Use proper async/await or promises instead';
281
- }
282
-
283
- issues.push({
284
- component: component.id,
285
- issue: `Performance anti-pattern: ${match}`,
286
- line: index + 1,
287
- context: line.trim(),
288
- severity,
289
- recommendation,
290
- impact: 'low',
291
- effort: 'low'
292
- });
293
- });
294
- }
295
- });
296
- });
297
-
298
- return issues;
299
- }
300
-
301
- /**
302
- * Find inefficient loop patterns
303
- */
304
- findLoopIssues(content, component) {
305
- const issues = [];
306
- const lines = content.split('\n');
307
-
308
- this.performancePatterns.inefficientLoops.forEach(pattern => {
309
- lines.forEach((line, index) => {
310
- const matches = line.match(pattern);
311
- if (matches) {
312
- matches.forEach(match => {
313
- let severity = 'medium';
314
- let recommendation = 'Optimize loop structure';
315
-
316
- if (match.includes('.length')) {
317
- recommendation = 'Cache array length in variable before loop';
318
- } else if (match.includes('while(true)')) {
319
- severity = 'high';
320
- recommendation = 'Add proper exit condition to prevent infinite loops';
321
- } else if (match.includes('forEach.*forEach')) {
322
- recommendation = 'Consider using nested for loops or array methods like flatMap';
323
- }
324
-
325
- issues.push({
326
- component: component.id,
327
- issue: `Inefficient loop: ${match}`,
328
- line: index + 1,
329
- context: line.trim(),
330
- severity,
331
- recommendation,
332
- impact: 'medium',
333
- effort: 'low'
334
- });
335
- });
336
- }
337
- });
338
- });
339
-
340
- return issues;
341
- }
342
-
343
- /**
344
- * Analyze function complexity
345
- */
346
- analyzeComplexity(content, component) {
347
- const issues = [];
348
- const functions = this.extractFunctions(content);
349
-
350
- functions.forEach(func => {
351
- // Check function length
352
- if (func.lines > this.thresholds.functionLength) {
353
- issues.push({
354
- component: component.id,
355
- issue: `Long function: ${func.name} (${func.lines} lines)`,
356
- line: func.startLine,
357
- severity: func.lines > this.thresholds.functionLength * 2 ? 'high' : 'medium',
358
- recommendation: 'Break down into smaller functions',
359
- impact: 'medium',
360
- effort: 'medium'
361
- });
362
- }
363
-
364
- // Check cyclomatic complexity
365
- if (func.complexity > this.thresholds.cyclomaticComplexity) {
366
- issues.push({
367
- component: component.id,
368
- issue: `High complexity: ${func.name} (complexity: ${func.complexity})`,
369
- line: func.startLine,
370
- severity: func.complexity > this.thresholds.cyclomaticComplexity * 1.5 ? 'high' : 'medium',
371
- recommendation: 'Reduce conditional complexity',
372
- impact: 'high',
373
- effort: 'high'
374
- });
375
- }
376
-
377
- // Check nesting depth
378
- if (func.nestingDepth > this.thresholds.nestingDepth) {
379
- issues.push({
380
- component: component.id,
381
- issue: `Deep nesting: ${func.name} (depth: ${func.nestingDepth})`,
382
- line: func.startLine,
383
- severity: 'medium',
384
- recommendation: 'Reduce nesting depth using early returns or guard clauses',
385
- impact: 'medium',
386
- effort: 'medium'
387
- });
388
- }
389
- });
390
-
391
- return issues;
392
- }
393
-
394
- /**
395
- * Analyze imports and requires
396
- */
397
- analyzeImports(content, component) {
398
- const issues = [];
399
- const imports = this.extractImports(content);
400
-
401
- if (imports.length > this.thresholds.importCount) {
402
- issues.push({
403
- component: component.id,
404
- issue: `Too many imports: ${imports.length}`,
405
- severity: 'medium',
406
- recommendation: 'Consider breaking down module or using dynamic imports',
407
- impact: 'low',
408
- effort: 'medium'
409
- });
410
- }
411
-
412
- // Find unused imports (basic heuristic)
413
- const unusedImports = imports.filter(imp => {
414
- const usage = content.split(imp.name).length - 1;
415
- return usage <= 1; // Only appears in import statement
416
- });
417
-
418
- if (unusedImports.length > 0) {
419
- issues.push({
420
- component: component.id,
421
- issue: `Unused imports: ${unusedImports.map(i => i.name).join(', ')}`,
422
- severity: 'low',
423
- recommendation: 'Remove unused imports',
424
- impact: 'low',
425
- effort: 'low'
426
- });
427
- }
428
-
429
- return issues;
430
- }
431
-
432
- /**
433
- * Find dead code (unused functions, variables)
434
- */
435
- async findDeadCode(content, component) {
436
- const issues = [];
437
-
438
- // This is a simplified implementation
439
- // A full implementation would analyze the entire codebase for usage
440
- const functions = this.extractFunctions(content);
441
- const exports = this.extractExports(content);
442
-
443
- // Check for functions that are defined but never called within the file
444
- functions.forEach(func => {
445
- if (!func.name.startsWith('_') && !exports.includes(func.name)) {
446
- const usage = content.split(func.name).length - 1;
447
- if (usage <= 1) { // Only appears in definition
448
- issues.push({
449
- component: component.id,
450
- issue: `Potentially unused function: ${func.name}`,
451
- line: func.startLine,
452
- severity: 'low',
453
- recommendation: 'Remove if truly unused or export if needed elsewhere',
454
- impact: 'low',
455
- effort: 'low'
456
- });
457
- }
458
- }
459
- });
460
-
461
- return issues;
462
- }
463
-
464
- /**
465
- * Extract function information from code
466
- */
467
- extractFunctions(content) {
468
- const functions = [];
469
- const lines = content.split('\n');
470
- const functionRegex = /(?:function\s+(\w+)|(\w+)\s*[:=]\s*(?:async\s+)?function|(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?:=>|{))/g;
471
-
472
- lines.forEach((line, index) => {
473
- const matches = [...line.matchAll(functionRegex)];
474
- matches.forEach(match => {
475
- const name = match[1] || match[2] || match[3] || 'anonymous';
476
-
477
- // Calculate function metrics (simplified)
478
- const funcInfo = {
479
- name,
480
- startLine: index + 1,
481
- lines: this.estimateFunctionLength(lines, index),
482
- complexity: this.estimateComplexity(lines, index),
483
- nestingDepth: this.estimateNestingDepth(lines, index)
484
- };
485
-
486
- functions.push(funcInfo);
487
- });
488
- });
489
-
490
- return functions;
491
- }
492
-
493
- /**
494
- * Extract import information
495
- */
496
- extractImports(content) {
497
- const imports = [];
498
- const importRegex = /(?:import\s+(?:(\w+)|\{([^}]+)\}|.*)\s+from\s+['"`]([^'"`]+)['"`]|const\s+(?:(\w+)|\{([^}]+)\})\s*=\s*require\(['"`]([^'"`]+)['"`]\))/g;
499
-
500
- const matches = [...content.matchAll(importRegex)];
501
- matches.forEach(match => {
502
- const defaultImport = match[1] || match[4];
503
- const namedImports = match[2] || match[5];
504
- const source = match[3] || match[6];
505
-
506
- if (defaultImport) {
507
- imports.push({ name: defaultImport, source, type: 'default' });
508
- }
509
-
510
- if (namedImports) {
511
- namedImports.split(',').forEach(name => {
512
- imports.push({ name: name.trim(), source, type: 'named' });
513
- });
514
- }
515
- });
516
-
517
- return imports;
518
- }
519
-
520
- /**
521
- * Extract export information
522
- */
523
- extractExports(content) {
524
- const exports = [];
525
- const exportRegex = /(?:export\s+(?:default\s+)?(?:function\s+(\w+)|class\s+(\w+)|(?:const|let|var)\s+(\w+))|module\.exports\s*=\s*(\w+))/g;
526
-
527
- const matches = [...content.matchAll(exportRegex)];
528
- matches.forEach(match => {
529
- const name = match[1] || match[2] || match[3] || match[4];
530
- if (name) exports.push(name);
531
- });
532
-
533
- return exports;
534
- }
535
-
536
- /**
537
- * Estimate function length (simplified)
538
- */
539
- estimateFunctionLength(lines, startIndex) {
540
- let braceCount = 0;
541
- let lineCount = 0;
542
- let inFunction = false;
543
-
544
- for (let i = startIndex; i < lines.length; i++) {
545
- const line = lines[i];
546
- lineCount++;
547
-
548
- // Count braces to find function end
549
- for (const char of line) {
550
- if (char === '{') {
551
- braceCount++;
552
- inFunction = true;
553
- } else if (char === '}') {
554
- braceCount--;
555
- if (inFunction && braceCount === 0) {
556
- return lineCount;
557
- }
558
- }
559
- }
560
-
561
- // Safety limit
562
- if (lineCount > 200) break;
563
- }
564
-
565
- return lineCount;
566
- }
567
-
568
- /**
569
- * Estimate cyclomatic complexity (simplified)
570
- */
571
- estimateComplexity(lines, startIndex) {
572
- let complexity = 1; // Base complexity
573
- const complexityKeywords = ['if', 'else', 'while', 'for', 'switch', 'case', 'catch', '&&', '||', '?'];
574
-
575
- const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
576
-
577
- functionLines.forEach(line => {
578
- complexityKeywords.forEach(keyword => {
579
- const matches = line.match(new RegExp(`\\b${keyword}\\b`, 'g'));
580
- if (matches) {
581
- complexity += matches.length;
582
- }
583
- });
584
- });
585
-
586
- return complexity;
587
- }
588
-
589
- /**
590
- * Estimate nesting depth (simplified)
591
- */
592
- estimateNestingDepth(lines, startIndex) {
593
- let maxDepth = 0;
594
- let currentDepth = 0;
595
-
596
- const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
597
-
598
- functionLines.forEach(line => {
599
- for (const char of line) {
600
- if (char === '{') {
601
- currentDepth++;
602
- maxDepth = Math.max(maxDepth, currentDepth);
603
- } else if (char === '}') {
604
- currentDepth--;
605
- }
606
- }
607
- });
608
-
609
- return maxDepth;
610
- }
611
-
612
- /**
613
- * Calculate overall performance score
614
- */
615
- calculateOverallScore(analysis) {
616
- let score = 10;
617
- const penalties = {
618
- critical: 2,
619
- high: 1,
620
- medium: 0.5,
621
- low: 0.1
622
- };
623
-
624
- // Apply penalties based on issue severity
625
- [...analysis.bottlenecks, ...analysis.memory_issues, ...analysis.async_opportunities,
626
- ...analysis.code_quality_issues, ...analysis.file_size_issues, ...analysis.complexity_issues]
627
- .forEach(issue => {
628
- score -= penalties[issue.severity] || 0.1;
629
- });
630
-
631
- return Math.max(0, Math.round(score * 10) / 10);
632
- }
633
-
634
- /**
635
- * Count total issues
636
- */
637
- countTotalIssues(analysis) {
638
- return analysis.bottlenecks.length +
639
- analysis.memory_issues.length +
640
- analysis.async_opportunities.length +
641
- analysis.code_quality_issues.length +
642
- analysis.file_size_issues.length +
643
- analysis.complexity_issues.length;
644
- }
645
-
646
- /**
647
- * Calculate issue priorities
648
- */
649
- calculateIssuePriorities(analysis) {
650
- const metrics = analysis.metrics;
651
- const allIssues = [
652
- ...analysis.bottlenecks,
653
- ...analysis.memory_issues,
654
- ...analysis.async_opportunities,
655
- ...analysis.code_quality_issues,
656
- ...analysis.file_size_issues,
657
- ...analysis.complexity_issues
658
- ];
659
-
660
- metrics.critical_issues = allIssues.filter(i => i.severity === 'critical').length;
661
- metrics.high_priority_issues = allIssues.filter(i => i.severity === 'high').length;
662
- metrics.medium_priority_issues = allIssues.filter(i => i.severity === 'medium').length;
663
- metrics.low_priority_issues = allIssues.filter(i => i.severity === 'low').length;
664
-
665
- return metrics;
666
- }
667
-
668
- /**
669
- * Generate performance recommendations
670
- */
671
- generatePerformanceRecommendations(analysis) {
672
- const recommendations = [];
673
-
674
- // Critical issues
675
- if (analysis.metrics.critical_issues > 0) {
676
- recommendations.push({
677
- priority: 'critical',
678
- category: 'immediate_action',
679
- message: `${analysis.metrics.critical_issues} critical performance issues require immediate attention`,
680
- action: 'Fix critical bottlenecks before deployment'
681
- });
682
- }
683
-
684
- // High severity issues
685
- if (analysis.metrics.high_priority_issues > 5) {
686
- recommendations.push({
687
- priority: 'high',
688
- category: 'performance',
689
- message: `${analysis.metrics.high_priority_issues} high-priority performance issues detected`,
690
- action: 'Address synchronous operations and complexity issues'
691
- });
692
- }
693
-
694
- // Memory issues
695
- if (analysis.memory_issues.length > 0) {
696
- recommendations.push({
697
- priority: 'medium',
698
- category: 'memory',
699
- message: `${analysis.memory_issues.length} memory optimization opportunities found`,
700
- action: 'Implement memory-efficient patterns and data structures'
701
- });
702
- }
703
-
704
- // File size issues
705
- if (analysis.file_size_issues.length > 0) {
706
- recommendations.push({
707
- priority: 'medium',
708
- category: 'modularity',
709
- message: `${analysis.file_size_issues.length} files are too large`,
710
- action: 'Break down large files into smaller, focused modules'
711
- });
712
- }
713
-
714
- // Overall score
715
- if (analysis.overall_score < 7) {
716
- recommendations.push({
717
- priority: 'high',
718
- category: 'general',
719
- message: `Overall performance score is ${analysis.overall_score}/10`,
720
- action: 'Comprehensive performance review and optimization needed'
721
- });
722
- }
723
-
724
- return recommendations;
725
- }
726
-
727
- /**
728
- * Check if component should be analyzed
729
- */
730
- shouldAnalyzeComponent(component) {
731
- const analyzableTypes = ['utility', 'task'];
732
- const analyzableExtensions = ['.js', '.mjs', '.ts'];
733
-
734
- if (!analyzableTypes.includes(component.type)) {
735
- return false;
736
- }
737
-
738
- if (component.file_path) {
739
- const ext = path.extname(component.file_path).toLowerCase();
740
- return analyzableExtensions.includes(ext);
741
- }
742
-
743
- return false;
744
- }
745
-
746
- /**
747
- * Format bytes for display
748
- */
749
- formatBytes(bytes) {
750
- if (bytes === 0) return '0 B';
751
- const k = 1024;
752
- const sizes = ['B', 'KB', 'MB', 'GB'];
753
- const i = Math.floor(Math.log(bytes) / Math.log(k));
754
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
755
- }
756
- }
757
-
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * Performance bottleneck analyzer for AIOS-FULLSTACK framework
7
+ * Identifies performance issues and optimization opportunities
8
+ */
9
+ class PerformanceAnalyzer {
10
+ constructor(options = {}) {
11
+ this.rootPath = options.rootPath || process.cwd();
12
+ this.thresholds = {
13
+ fileSize: 50 * 1024, // 50KB
14
+ functionLength: 50, // lines
15
+ cyclomaticComplexity: 10,
16
+ nestingDepth: 5,
17
+ importCount: 20,
18
+ unusedCode: 0.1 // 10% unused code ratio
19
+ };
20
+ this.performancePatterns = {
21
+ // Sync operations that should be async
22
+ syncOperations: [
23
+ /fs\.readFileSync/g,
24
+ /fs\.writeFileSync/g,
25
+ /fs\.existsSync/g,
26
+ /JSON\.parse\(\s*fs\.readFileSync/g
27
+ ],
28
+ // Memory-intensive patterns
29
+ memoryIssues: [
30
+ /\.map\(\s*.*\.map\(/g, // Nested maps
31
+ /new Array\(\d{4,}\)/g, // Large arrays
32
+ /JSON\.stringify.*JSON\.parse/g, // Unnecessary serialization
33
+ /require\(\s*['"`][^'"`]+\.json['"`]\s*\)/g // Large JSON imports
34
+ ],
35
+ // Performance anti-patterns
36
+ antiPatterns: [
37
+ /console\.log/g, // Console logs in production
38
+ /debugger/g, // Debugger statements
39
+ /setTimeout\(\s*.*,\s*0\s*\)/g, // Unnecessary setTimeout
40
+ /setInterval\(\s*.*,\s*[0-9]{1,2}\s*\)/g // High-frequency intervals
41
+ ],
42
+ // Inefficient loops
43
+ inefficientLoops: [
44
+ /for\s*\(\s*.*\.length\s*;/g, // Length calculated in loop condition
45
+ /while\s*\(\s*true\s*\)/g, // Infinite loops
46
+ /forEach.*forEach/g // Nested forEach
47
+ ]
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Analyze performance across all components
53
+ */
54
+ async analyzePerformance(components) {
55
+ const analysis = {
56
+ timestamp: new Date().toISOString(),
57
+ overall_score: 0,
58
+ bottlenecks: [],
59
+ optimization_opportunities: [],
60
+ memory_issues: [],
61
+ async_opportunities: [],
62
+ code_quality_issues: [],
63
+ file_size_issues: [],
64
+ complexity_issues: [],
65
+ recommendations: [],
66
+ metrics: {
67
+ total_files_analyzed: 0,
68
+ total_issues_found: 0,
69
+ critical_issues: 0,
70
+ high_priority_issues: 0,
71
+ medium_priority_issues: 0,
72
+ low_priority_issues: 0
73
+ }
74
+ };
75
+
76
+ try {
77
+ console.log(chalk.blue('🔍 Analyzing performance bottlenecks...'));
78
+
79
+ // Analyze each component
80
+ for (const component of components) {
81
+ const componentAnalysis = await this.analyzeComponentPerformance(component);
82
+
83
+ // Aggregate results
84
+ analysis.bottlenecks.push(...componentAnalysis.bottlenecks);
85
+ analysis.optimization_opportunities.push(...componentAnalysis.optimizations);
86
+ analysis.memory_issues.push(...componentAnalysis.memory_issues);
87
+ analysis.async_opportunities.push(...componentAnalysis.async_opportunities);
88
+ analysis.code_quality_issues.push(...componentAnalysis.quality_issues);
89
+ analysis.file_size_issues.push(...componentAnalysis.file_size_issues);
90
+ analysis.complexity_issues.push(...componentAnalysis.complexity_issues);
91
+
92
+ analysis.metrics.total_files_analyzed++;
93
+ }
94
+
95
+ // Calculate overall metrics
96
+ analysis.overall_score = this.calculateOverallScore(analysis);
97
+ analysis.metrics.total_issues_found = this.countTotalIssues(analysis);
98
+ analysis.metrics = this.calculateIssuePriorities(analysis);
99
+ analysis.recommendations = this.generatePerformanceRecommendations(analysis);
100
+
101
+ console.log(chalk.green(`✅ Performance analysis completed`));
102
+ console.log(chalk.gray(` Files analyzed: ${analysis.metrics.total_files_analyzed}`));
103
+ console.log(chalk.gray(` Issues found: ${analysis.metrics.total_issues_found}`));
104
+ console.log(chalk.gray(` Overall score: ${analysis.overall_score}/10`));
105
+
106
+ return analysis;
107
+
108
+ } catch (error) {
109
+ console.error(chalk.red(`Performance analysis failed: ${error.message}`));
110
+ throw error;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Analyze performance for a single component
116
+ */
117
+ async analyzeComponentPerformance(component) {
118
+ const analysis = {
119
+ component_id: component.id,
120
+ component_type: component.type,
121
+ bottlenecks: [],
122
+ optimizations: [],
123
+ memory_issues: [],
124
+ async_opportunities: [],
125
+ quality_issues: [],
126
+ file_size_issues: [],
127
+ complexity_issues: []
128
+ };
129
+
130
+ try {
131
+ // Only analyze JavaScript files and executable components
132
+ if (!this.shouldAnalyzeComponent(component)) {
133
+ return analysis;
134
+ }
135
+
136
+ const filePath = path.join(this.rootPath, component.file_path);
137
+ const content = await fs.readFile(filePath, 'utf-8');
138
+ const stats = await fs.stat(filePath);
139
+
140
+ // File size analysis
141
+ if (stats.size > this.thresholds.fileSize) {
142
+ analysis.file_size_issues.push({
143
+ component: component.id,
144
+ issue: `Large file size: ${this.formatBytes(stats.size)}`,
145
+ severity: stats.size > this.thresholds.fileSize * 2 ? 'high' : 'medium',
146
+ recommendation: 'Consider breaking down into smaller modules',
147
+ impact: 'high',
148
+ effort: 'medium'
149
+ });
150
+ }
151
+
152
+ // Synchronous operations analysis
153
+ const syncIssues = this.findSyncOperations(content, component);
154
+ analysis.async_opportunities.push(...syncIssues);
155
+
156
+ // Memory usage analysis
157
+ const memoryIssues = this.findMemoryIssues(content, component);
158
+ analysis.memory_issues.push(...memoryIssues);
159
+
160
+ // Performance anti-patterns
161
+ const antiPatterns = this.findAntiPatterns(content, component);
162
+ analysis.quality_issues.push(...antiPatterns);
163
+
164
+ // Loop efficiency analysis
165
+ const loopIssues = this.findLoopIssues(content, component);
166
+ analysis.bottlenecks.push(...loopIssues);
167
+
168
+ // Function complexity analysis
169
+ const complexityIssues = this.analyzeComplexity(content, component);
170
+ analysis.complexity_issues.push(...complexityIssues);
171
+
172
+ // Import/require analysis
173
+ const importIssues = this.analyzeImports(content, component);
174
+ analysis.optimizations.push(...importIssues);
175
+
176
+ // Dead code analysis
177
+ const deadCodeIssues = await this.findDeadCode(content, component);
178
+ analysis.optimizations.push(...deadCodeIssues);
179
+
180
+ } catch (error) {
181
+ console.warn(chalk.yellow(`Failed to analyze performance for ${component.id}: ${error.message}`));
182
+ }
183
+
184
+ return analysis;
185
+ }
186
+
187
+ /**
188
+ * Find synchronous operations that should be async
189
+ */
190
+ findSyncOperations(content, component) {
191
+ const issues = [];
192
+ const lines = content.split('\n');
193
+
194
+ this.performancePatterns.syncOperations.forEach(pattern => {
195
+ lines.forEach((line, index) => {
196
+ const matches = line.match(pattern);
197
+ if (matches) {
198
+ matches.forEach(match => {
199
+ issues.push({
200
+ component: component.id,
201
+ issue: `Synchronous operation: ${match}`,
202
+ line: index + 1,
203
+ context: line.trim(),
204
+ severity: 'high',
205
+ recommendation: 'Convert to async equivalent',
206
+ impact: 'high',
207
+ effort: 'low'
208
+ });
209
+ });
210
+ }
211
+ });
212
+ });
213
+
214
+ return issues;
215
+ }
216
+
217
+ /**
218
+ * Find memory-intensive patterns
219
+ */
220
+ findMemoryIssues(content, component) {
221
+ const issues = [];
222
+ const lines = content.split('\n');
223
+
224
+ this.performancePatterns.memoryIssues.forEach(pattern => {
225
+ lines.forEach((line, index) => {
226
+ const matches = line.match(pattern);
227
+ if (matches) {
228
+ matches.forEach(match => {
229
+ let severity = 'medium';
230
+ let recommendation = 'Optimize memory usage';
231
+
232
+ if (match.includes('new Array')) {
233
+ severity = 'high';
234
+ recommendation = 'Use array literals or streaming for large datasets';
235
+ } else if (match.includes('JSON.stringify.*JSON.parse')) {
236
+ recommendation = 'Use direct object assignment or deep clone utilities';
237
+ } else if (match.includes('.map(.*map(')) {
238
+ recommendation = 'Combine operations or use more efficient iteration';
239
+ }
240
+
241
+ issues.push({
242
+ component: component.id,
243
+ issue: `Memory-intensive pattern: ${match}`,
244
+ line: index + 1,
245
+ context: line.trim(),
246
+ severity,
247
+ recommendation,
248
+ impact: 'medium',
249
+ effort: 'medium'
250
+ });
251
+ });
252
+ }
253
+ });
254
+ });
255
+
256
+ return issues;
257
+ }
258
+
259
+ /**
260
+ * Find performance anti-patterns
261
+ */
262
+ findAntiPatterns(content, component) {
263
+ const issues = [];
264
+ const lines = content.split('\n');
265
+
266
+ this.performancePatterns.antiPatterns.forEach(pattern => {
267
+ lines.forEach((line, index) => {
268
+ const matches = line.match(pattern);
269
+ if (matches) {
270
+ matches.forEach(match => {
271
+ let severity = 'low';
272
+ let recommendation = 'Remove or optimize';
273
+
274
+ if (match.includes('console.log')) {
275
+ recommendation = 'Remove console.log statements from production code';
276
+ } else if (match.includes('debugger')) {
277
+ severity = 'medium';
278
+ recommendation = 'Remove debugger statements';
279
+ } else if (match.includes('setTimeout')) {
280
+ recommendation = 'Use proper async/await or promises instead';
281
+ }
282
+
283
+ issues.push({
284
+ component: component.id,
285
+ issue: `Performance anti-pattern: ${match}`,
286
+ line: index + 1,
287
+ context: line.trim(),
288
+ severity,
289
+ recommendation,
290
+ impact: 'low',
291
+ effort: 'low'
292
+ });
293
+ });
294
+ }
295
+ });
296
+ });
297
+
298
+ return issues;
299
+ }
300
+
301
+ /**
302
+ * Find inefficient loop patterns
303
+ */
304
+ findLoopIssues(content, component) {
305
+ const issues = [];
306
+ const lines = content.split('\n');
307
+
308
+ this.performancePatterns.inefficientLoops.forEach(pattern => {
309
+ lines.forEach((line, index) => {
310
+ const matches = line.match(pattern);
311
+ if (matches) {
312
+ matches.forEach(match => {
313
+ let severity = 'medium';
314
+ let recommendation = 'Optimize loop structure';
315
+
316
+ if (match.includes('.length')) {
317
+ recommendation = 'Cache array length in variable before loop';
318
+ } else if (match.includes('while(true)')) {
319
+ severity = 'high';
320
+ recommendation = 'Add proper exit condition to prevent infinite loops';
321
+ } else if (match.includes('forEach.*forEach')) {
322
+ recommendation = 'Consider using nested for loops or array methods like flatMap';
323
+ }
324
+
325
+ issues.push({
326
+ component: component.id,
327
+ issue: `Inefficient loop: ${match}`,
328
+ line: index + 1,
329
+ context: line.trim(),
330
+ severity,
331
+ recommendation,
332
+ impact: 'medium',
333
+ effort: 'low'
334
+ });
335
+ });
336
+ }
337
+ });
338
+ });
339
+
340
+ return issues;
341
+ }
342
+
343
+ /**
344
+ * Analyze function complexity
345
+ */
346
+ analyzeComplexity(content, component) {
347
+ const issues = [];
348
+ const functions = this.extractFunctions(content);
349
+
350
+ functions.forEach(func => {
351
+ // Check function length
352
+ if (func.lines > this.thresholds.functionLength) {
353
+ issues.push({
354
+ component: component.id,
355
+ issue: `Long function: ${func.name} (${func.lines} lines)`,
356
+ line: func.startLine,
357
+ severity: func.lines > this.thresholds.functionLength * 2 ? 'high' : 'medium',
358
+ recommendation: 'Break down into smaller functions',
359
+ impact: 'medium',
360
+ effort: 'medium'
361
+ });
362
+ }
363
+
364
+ // Check cyclomatic complexity
365
+ if (func.complexity > this.thresholds.cyclomaticComplexity) {
366
+ issues.push({
367
+ component: component.id,
368
+ issue: `High complexity: ${func.name} (complexity: ${func.complexity})`,
369
+ line: func.startLine,
370
+ severity: func.complexity > this.thresholds.cyclomaticComplexity * 1.5 ? 'high' : 'medium',
371
+ recommendation: 'Reduce conditional complexity',
372
+ impact: 'high',
373
+ effort: 'high'
374
+ });
375
+ }
376
+
377
+ // Check nesting depth
378
+ if (func.nestingDepth > this.thresholds.nestingDepth) {
379
+ issues.push({
380
+ component: component.id,
381
+ issue: `Deep nesting: ${func.name} (depth: ${func.nestingDepth})`,
382
+ line: func.startLine,
383
+ severity: 'medium',
384
+ recommendation: 'Reduce nesting depth using early returns or guard clauses',
385
+ impact: 'medium',
386
+ effort: 'medium'
387
+ });
388
+ }
389
+ });
390
+
391
+ return issues;
392
+ }
393
+
394
+ /**
395
+ * Analyze imports and requires
396
+ */
397
+ analyzeImports(content, component) {
398
+ const issues = [];
399
+ const imports = this.extractImports(content);
400
+
401
+ if (imports.length > this.thresholds.importCount) {
402
+ issues.push({
403
+ component: component.id,
404
+ issue: `Too many imports: ${imports.length}`,
405
+ severity: 'medium',
406
+ recommendation: 'Consider breaking down module or using dynamic imports',
407
+ impact: 'low',
408
+ effort: 'medium'
409
+ });
410
+ }
411
+
412
+ // Find unused imports (basic heuristic)
413
+ const unusedImports = imports.filter(imp => {
414
+ const usage = content.split(imp.name).length - 1;
415
+ return usage <= 1; // Only appears in import statement
416
+ });
417
+
418
+ if (unusedImports.length > 0) {
419
+ issues.push({
420
+ component: component.id,
421
+ issue: `Unused imports: ${unusedImports.map(i => i.name).join(', ')}`,
422
+ severity: 'low',
423
+ recommendation: 'Remove unused imports',
424
+ impact: 'low',
425
+ effort: 'low'
426
+ });
427
+ }
428
+
429
+ return issues;
430
+ }
431
+
432
+ /**
433
+ * Find dead code (unused functions, variables)
434
+ */
435
+ async findDeadCode(content, component) {
436
+ const issues = [];
437
+
438
+ // This is a simplified implementation
439
+ // A full implementation would analyze the entire codebase for usage
440
+ const functions = this.extractFunctions(content);
441
+ const exports = this.extractExports(content);
442
+
443
+ // Check for functions that are defined but never called within the file
444
+ functions.forEach(func => {
445
+ if (!func.name.startsWith('_') && !exports.includes(func.name)) {
446
+ const usage = content.split(func.name).length - 1;
447
+ if (usage <= 1) { // Only appears in definition
448
+ issues.push({
449
+ component: component.id,
450
+ issue: `Potentially unused function: ${func.name}`,
451
+ line: func.startLine,
452
+ severity: 'low',
453
+ recommendation: 'Remove if truly unused or export if needed elsewhere',
454
+ impact: 'low',
455
+ effort: 'low'
456
+ });
457
+ }
458
+ }
459
+ });
460
+
461
+ return issues;
462
+ }
463
+
464
+ /**
465
+ * Extract function information from code
466
+ */
467
+ extractFunctions(content) {
468
+ const functions = [];
469
+ const lines = content.split('\n');
470
+ const functionRegex = /(?:function\s+(\w+)|(\w+)\s*[:=]\s*(?:async\s+)?function|(?:async\s+)?(\w+)\s*\([^)]*\)\s*(?:=>|{))/g;
471
+
472
+ lines.forEach((line, index) => {
473
+ const matches = [...line.matchAll(functionRegex)];
474
+ matches.forEach(match => {
475
+ const name = match[1] || match[2] || match[3] || 'anonymous';
476
+
477
+ // Calculate function metrics (simplified)
478
+ const funcInfo = {
479
+ name,
480
+ startLine: index + 1,
481
+ lines: this.estimateFunctionLength(lines, index),
482
+ complexity: this.estimateComplexity(lines, index),
483
+ nestingDepth: this.estimateNestingDepth(lines, index)
484
+ };
485
+
486
+ functions.push(funcInfo);
487
+ });
488
+ });
489
+
490
+ return functions;
491
+ }
492
+
493
+ /**
494
+ * Extract import information
495
+ */
496
+ extractImports(content) {
497
+ const imports = [];
498
+ const importRegex = /(?:import\s+(?:(\w+)|\{([^}]+)\}|.*)\s+from\s+['"`]([^'"`]+)['"`]|const\s+(?:(\w+)|\{([^}]+)\})\s*=\s*require\(['"`]([^'"`]+)['"`]\))/g;
499
+
500
+ const matches = [...content.matchAll(importRegex)];
501
+ matches.forEach(match => {
502
+ const defaultImport = match[1] || match[4];
503
+ const namedImports = match[2] || match[5];
504
+ const source = match[3] || match[6];
505
+
506
+ if (defaultImport) {
507
+ imports.push({ name: defaultImport, source, type: 'default' });
508
+ }
509
+
510
+ if (namedImports) {
511
+ namedImports.split(',').forEach(name => {
512
+ imports.push({ name: name.trim(), source, type: 'named' });
513
+ });
514
+ }
515
+ });
516
+
517
+ return imports;
518
+ }
519
+
520
+ /**
521
+ * Extract export information
522
+ */
523
+ extractExports(content) {
524
+ const exports = [];
525
+ const exportRegex = /(?:export\s+(?:default\s+)?(?:function\s+(\w+)|class\s+(\w+)|(?:const|let|var)\s+(\w+))|module\.exports\s*=\s*(\w+))/g;
526
+
527
+ const matches = [...content.matchAll(exportRegex)];
528
+ matches.forEach(match => {
529
+ const name = match[1] || match[2] || match[3] || match[4];
530
+ if (name) exports.push(name);
531
+ });
532
+
533
+ return exports;
534
+ }
535
+
536
+ /**
537
+ * Estimate function length (simplified)
538
+ */
539
+ estimateFunctionLength(lines, startIndex) {
540
+ let braceCount = 0;
541
+ let lineCount = 0;
542
+ let inFunction = false;
543
+
544
+ for (let i = startIndex; i < lines.length; i++) {
545
+ const line = lines[i];
546
+ lineCount++;
547
+
548
+ // Count braces to find function end
549
+ for (const char of line) {
550
+ if (char === '{') {
551
+ braceCount++;
552
+ inFunction = true;
553
+ } else if (char === '}') {
554
+ braceCount--;
555
+ if (inFunction && braceCount === 0) {
556
+ return lineCount;
557
+ }
558
+ }
559
+ }
560
+
561
+ // Safety limit
562
+ if (lineCount > 200) break;
563
+ }
564
+
565
+ return lineCount;
566
+ }
567
+
568
+ /**
569
+ * Estimate cyclomatic complexity (simplified)
570
+ */
571
+ estimateComplexity(lines, startIndex) {
572
+ let complexity = 1; // Base complexity
573
+ const complexityKeywords = ['if', 'else', 'while', 'for', 'switch', 'case', 'catch', '&&', '||', '?'];
574
+
575
+ const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
576
+
577
+ functionLines.forEach(line => {
578
+ complexityKeywords.forEach(keyword => {
579
+ const matches = line.match(new RegExp(`\\b${keyword}\\b`, 'g'));
580
+ if (matches) {
581
+ complexity += matches.length;
582
+ }
583
+ });
584
+ });
585
+
586
+ return complexity;
587
+ }
588
+
589
+ /**
590
+ * Estimate nesting depth (simplified)
591
+ */
592
+ estimateNestingDepth(lines, startIndex) {
593
+ let maxDepth = 0;
594
+ let currentDepth = 0;
595
+
596
+ const functionLines = lines.slice(startIndex, startIndex + this.estimateFunctionLength(lines, startIndex));
597
+
598
+ functionLines.forEach(line => {
599
+ for (const char of line) {
600
+ if (char === '{') {
601
+ currentDepth++;
602
+ maxDepth = Math.max(maxDepth, currentDepth);
603
+ } else if (char === '}') {
604
+ currentDepth--;
605
+ }
606
+ }
607
+ });
608
+
609
+ return maxDepth;
610
+ }
611
+
612
+ /**
613
+ * Calculate overall performance score
614
+ */
615
+ calculateOverallScore(analysis) {
616
+ let score = 10;
617
+ const penalties = {
618
+ critical: 2,
619
+ high: 1,
620
+ medium: 0.5,
621
+ low: 0.1
622
+ };
623
+
624
+ // Apply penalties based on issue severity
625
+ [...analysis.bottlenecks, ...analysis.memory_issues, ...analysis.async_opportunities,
626
+ ...analysis.code_quality_issues, ...analysis.file_size_issues, ...analysis.complexity_issues]
627
+ .forEach(issue => {
628
+ score -= penalties[issue.severity] || 0.1;
629
+ });
630
+
631
+ return Math.max(0, Math.round(score * 10) / 10);
632
+ }
633
+
634
+ /**
635
+ * Count total issues
636
+ */
637
+ countTotalIssues(analysis) {
638
+ return analysis.bottlenecks.length +
639
+ analysis.memory_issues.length +
640
+ analysis.async_opportunities.length +
641
+ analysis.code_quality_issues.length +
642
+ analysis.file_size_issues.length +
643
+ analysis.complexity_issues.length;
644
+ }
645
+
646
+ /**
647
+ * Calculate issue priorities
648
+ */
649
+ calculateIssuePriorities(analysis) {
650
+ const metrics = analysis.metrics;
651
+ const allIssues = [
652
+ ...analysis.bottlenecks,
653
+ ...analysis.memory_issues,
654
+ ...analysis.async_opportunities,
655
+ ...analysis.code_quality_issues,
656
+ ...analysis.file_size_issues,
657
+ ...analysis.complexity_issues
658
+ ];
659
+
660
+ metrics.critical_issues = allIssues.filter(i => i.severity === 'critical').length;
661
+ metrics.high_priority_issues = allIssues.filter(i => i.severity === 'high').length;
662
+ metrics.medium_priority_issues = allIssues.filter(i => i.severity === 'medium').length;
663
+ metrics.low_priority_issues = allIssues.filter(i => i.severity === 'low').length;
664
+
665
+ return metrics;
666
+ }
667
+
668
+ /**
669
+ * Generate performance recommendations
670
+ */
671
+ generatePerformanceRecommendations(analysis) {
672
+ const recommendations = [];
673
+
674
+ // Critical issues
675
+ if (analysis.metrics.critical_issues > 0) {
676
+ recommendations.push({
677
+ priority: 'critical',
678
+ category: 'immediate_action',
679
+ message: `${analysis.metrics.critical_issues} critical performance issues require immediate attention`,
680
+ action: 'Fix critical bottlenecks before deployment'
681
+ });
682
+ }
683
+
684
+ // High severity issues
685
+ if (analysis.metrics.high_priority_issues > 5) {
686
+ recommendations.push({
687
+ priority: 'high',
688
+ category: 'performance',
689
+ message: `${analysis.metrics.high_priority_issues} high-priority performance issues detected`,
690
+ action: 'Address synchronous operations and complexity issues'
691
+ });
692
+ }
693
+
694
+ // Memory issues
695
+ if (analysis.memory_issues.length > 0) {
696
+ recommendations.push({
697
+ priority: 'medium',
698
+ category: 'memory',
699
+ message: `${analysis.memory_issues.length} memory optimization opportunities found`,
700
+ action: 'Implement memory-efficient patterns and data structures'
701
+ });
702
+ }
703
+
704
+ // File size issues
705
+ if (analysis.file_size_issues.length > 0) {
706
+ recommendations.push({
707
+ priority: 'medium',
708
+ category: 'modularity',
709
+ message: `${analysis.file_size_issues.length} files are too large`,
710
+ action: 'Break down large files into smaller, focused modules'
711
+ });
712
+ }
713
+
714
+ // Overall score
715
+ if (analysis.overall_score < 7) {
716
+ recommendations.push({
717
+ priority: 'high',
718
+ category: 'general',
719
+ message: `Overall performance score is ${analysis.overall_score}/10`,
720
+ action: 'Comprehensive performance review and optimization needed'
721
+ });
722
+ }
723
+
724
+ return recommendations;
725
+ }
726
+
727
+ /**
728
+ * Check if component should be analyzed
729
+ */
730
+ shouldAnalyzeComponent(component) {
731
+ const analyzableTypes = ['utility', 'task'];
732
+ const analyzableExtensions = ['.js', '.mjs', '.ts'];
733
+
734
+ if (!analyzableTypes.includes(component.type)) {
735
+ return false;
736
+ }
737
+
738
+ if (component.file_path) {
739
+ const ext = path.extname(component.file_path).toLowerCase();
740
+ return analyzableExtensions.includes(ext);
741
+ }
742
+
743
+ return false;
744
+ }
745
+
746
+ /**
747
+ * Format bytes for display
748
+ */
749
+ formatBytes(bytes) {
750
+ if (bytes === 0) return '0 B';
751
+ const k = 1024;
752
+ const sizes = ['B', 'KB', 'MB', 'GB'];
753
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
754
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
755
+ }
756
+ }
757
+
758
758
  module.exports = PerformanceAnalyzer;