performance-optimizer 2.5.0__py3-none-any.whl

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.
optimizer.py ADDED
@@ -0,0 +1,339 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Performance Optimizer v2.0 - Advanced Multi-Stack Analyzer
4
+ Angular • Node.js • Seneca • SQL • AWS
5
+ NOT SonarQube — Performance-Specific Only
6
+
7
+ Usage:
8
+ python optimizer.py --frontend /path/to/angular-repo
9
+ python optimizer.py --backend /path/to/node-repo
10
+ python optimizer.py --project /path/to/monorepo
11
+ python optimizer.py --frontend ./fe --backend ./be --fail-on critical --min-score 70
12
+ """
13
+
14
+ import argparse
15
+ import json
16
+ import os
17
+ import sys
18
+ import time
19
+ from datetime import datetime
20
+ from pathlib import Path
21
+ from typing import List, Set
22
+
23
+ sys.path.insert(0, os.path.dirname(__file__))
24
+
25
+ from analyzers.angular_analyzer import AngularAnalyzer
26
+ from analyzers.react_analyzer import ReactAnalyzer
27
+ from analyzers.node_analyzer import NodeAnalyzer
28
+ from analyzers.sql_analyzer import SqlAnalyzer
29
+ from analyzers.aws_analyzer import AwsAnalyzer
30
+ from core.scorer import Scorer
31
+ from core.issue import Severity, Issue
32
+ from reporter.html_reporter import HtmlReporter
33
+
34
+ BANNER = """
35
+ ┌─────────────────────────────────────────────────────────────┐
36
+ │ PERFORMANCE OPTIMIZER v2.5 PRO │
37
+ │ Enterprise Multi-Stack Performance Intelligence │
38
+ │ Angular • React • Node.js • SQL • AWS Cloud │
39
+ │ NOT SonarQube — Performance-Specific Only │
40
+ └─────────────────────────────────────────────────────────────┘
41
+ """
42
+
43
+ DEFAULT_EXCLUDES = [
44
+ 'node_modules', '.git', 'dist', 'build', '.angular', '.next',
45
+ 'coverage', '.vscode', '.idea', 'package-lock.json', 'yarn.lock'
46
+ ]
47
+
48
+ def should_exclude(path_str: str, custom_excludes: List[str]) -> bool:
49
+ normalized = path_str.replace('\\', '/')
50
+ all_excludes = DEFAULT_EXCLUDES + custom_excludes
51
+ return any(ex in normalized for ex in all_excludes if ex)
52
+
53
+ def count_files(path: str, custom_excludes: List[str]) -> int:
54
+ p = Path(path)
55
+ count = 0
56
+ extensions = ['*.ts', '*.js', '*.jsx', '*.tsx', '*.html', '*.sql', '*.json', '*.yml', '*.yaml', '*.tf']
57
+ for ext in extensions:
58
+ for f in p.rglob(ext):
59
+ if not should_exclude(str(f), custom_excludes):
60
+ count += 1
61
+ return count
62
+
63
+ def detect_tech(frontend_path: str, backend_path: str) -> str:
64
+ techs = []
65
+ checked_paths = set(filter(None, [frontend_path, backend_path]))
66
+ for path in checked_paths:
67
+ p = Path(path)
68
+ pkg = p / 'package.json'
69
+ if pkg.exists():
70
+ try:
71
+ data = json.loads(pkg.read_text(encoding='utf-8', errors='ignore'))
72
+ deps = {**data.get('dependencies', {}), **data.get('devDependencies', {})}
73
+ if '@angular/core' in deps:
74
+ ver = deps['@angular/core'].lstrip('^~')
75
+ techs.append(f'Angular {ver.split(".")[0]}')
76
+ if 'react' in deps:
77
+ ver = deps['react'].lstrip('^~')
78
+ techs.append(f'React {ver.split(".")[0]}')
79
+ if 'next' in deps:
80
+ techs.append('Next.js')
81
+ if 'vue' in deps:
82
+ techs.append('Vue')
83
+ if 'seneca' in deps:
84
+ techs.append('Seneca.js')
85
+ if 'express' in deps:
86
+ techs.append('Express')
87
+ if 'nest' in deps or '@nestjs/core' in deps:
88
+ techs.append('NestJS')
89
+ node_ver = data.get('engines', {}).get('node', '')
90
+ if node_ver:
91
+ techs.append(f'Node {node_ver}')
92
+ except Exception:
93
+ pass
94
+
95
+ # Check for AWS Infra
96
+ if any(p.rglob('serverless.yml')) or any(p.rglob('*.tf')) or any(p.rglob('cloudformation*.yml')):
97
+ if 'AWS' not in techs:
98
+ techs.append('AWS Cloud')
99
+ # Check for SQL files
100
+ if any(p.rglob('*.sql')):
101
+ if 'SQL/RDS' not in techs:
102
+ techs.append('SQL/RDS')
103
+
104
+ return ' • '.join(techs) if techs else 'Angular • React • Node.js • SQL • AWS'
105
+
106
+ def run_analyzers(frontend_path: str, backend_path: str, verbose: bool = False) -> List[Issue]:
107
+ all_issues = []
108
+ is_monorepo = (frontend_path and backend_path and Path(frontend_path).resolve() == Path(backend_path).resolve())
109
+
110
+ if is_monorepo or (frontend_path and not backend_path):
111
+ target = frontend_path
112
+ print(f' 🔍 Analyzing unified project: {target}')
113
+ if Path(target).exists():
114
+ print(' 🅰️ Running Angular Analyzer...')
115
+ all_issues.extend(AngularAnalyzer(target).analyze())
116
+ print(' ⚛️ Running React Analyzer...')
117
+ all_issues.extend(ReactAnalyzer(target).analyze())
118
+ print(' 🟢 Running Node.js & Seneca Analyzer...')
119
+ all_issues.extend(NodeAnalyzer(target).analyze())
120
+ print(' 🗄️ Running SQL & Database Analyzer...')
121
+ all_issues.extend(SqlAnalyzer(target).analyze())
122
+ print(' ☁️ Running AWS & Infrastructure Analyzer...')
123
+ all_issues.extend(AwsAnalyzer(target).analyze())
124
+ return all_issues
125
+
126
+ # Separate frontend and backend paths
127
+ if frontend_path:
128
+ fp = Path(frontend_path)
129
+ if fp.exists():
130
+ print(f' 🅰️ Analyzing Angular/Frontend: {frontend_path}')
131
+ issues = AngularAnalyzer(frontend_path).analyze()
132
+ all_issues.extend(issues)
133
+ print(f' Found {len(issues)} Angular performance issues')
134
+
135
+ print(f' ⚛️ Analyzing React/Frontend: {frontend_path}')
136
+ react_issues = ReactAnalyzer(frontend_path).analyze()
137
+ all_issues.extend(react_issues)
138
+ print(f' Found {len(react_issues)} React performance issues')
139
+ else:
140
+ print(f' ❌ Frontend path not found: {frontend_path}')
141
+
142
+ if backend_path:
143
+ bp = Path(backend_path)
144
+ if bp.exists():
145
+ print(f' 🟢 Analyzing Node.js/Seneca: {backend_path}')
146
+ node_issues = NodeAnalyzer(backend_path).analyze()
147
+ all_issues.extend(node_issues)
148
+ print(f' Found {len(node_issues)} backend performance issues')
149
+
150
+ print(f' 🗄️ Analyzing SQL/Database: {backend_path}')
151
+ sql_issues = SqlAnalyzer(backend_path).analyze()
152
+ all_issues.extend(sql_issues)
153
+ print(f' Found {len(sql_issues)} database performance issues')
154
+
155
+ print(f' ☁️ Analyzing AWS/Infra config: {backend_path}')
156
+ aws_issues = AwsAnalyzer(backend_path).analyze()
157
+ all_issues.extend(aws_issues)
158
+ print(f' Found {len(aws_issues)} infrastructure issues')
159
+ else:
160
+ print(f' ❌ Backend path not found: {backend_path}')
161
+
162
+ return all_issues
163
+
164
+ def print_summary(scores: dict, issues: List[Issue]):
165
+ s = scores
166
+ print(f'''
167
+ ┌{'─'*58}┐
168
+ │ PERFORMANCE SCAN RESULTS │
169
+ ├{'─'*58}┤
170
+ │ Overall Score : {s['overall']:>3}/100 {'(🔴 Critical)' if s['overall']<45 else '(⚠️ Needs Work)' if s['overall']<65 else '(🟡 Fair)' if s['overall']<80 else '(✅ Good)':16}{'':13}│
171
+ │ Frontend : {s['frontend']:>3}/100{'':36}│
172
+ │ Backend : {s['backend']:>3}/100{'':36}│
173
+ │ Database : {s['database']:>3}/100{'':36}│
174
+ │ Infra : {s['infra']:>3}/100{'':36}│
175
+ ├{'─'*58}┤
176
+ │ 🔴 Critical: {s['by_severity']['critical']:<4} 🟠 High: {s['by_severity']['high']:<4} 🟡 Medium: {s['by_severity']['medium']:<4} 🟢 Low: {s['by_severity']['low']:<4} │
177
+ │ Total Issues : {s['total_issues']:>3}{'':42}│
178
+ └{'─'*58}┘''')
179
+
180
+ if s.get('top3'):
181
+ print('\n 🚨 TOP ACTIONABLE FIXES (Show to leadership):')
182
+ for idx, t in enumerate(s['top3'], 1):
183
+ line_str = f":{t['line_number']}" if t.get('line_number') else ""
184
+ print(f' {idx}. [{t["severity"].upper()}] {t["title"]}')
185
+ print(f' Location : {t["file"]}{line_str}')
186
+ print(f' Gain : {t["perf_gain"]}')
187
+
188
+ def generate_markdown_summary(out_path: str, scores: dict, meta: dict, issues: List[Issue]):
189
+ s = scores
190
+ md = f"""# Performance Optimizer Scan Summary
191
+
192
+ **Overall Health Score**: `{s['overall']}/100`
193
+ **Target Project**: `{meta.get('project', 'Application')}`
194
+ **Scan Timestamp**: `{meta.get('scan_time')}`
195
+ **Analyzed Files**: `{meta.get('files_scanned')}` in `{meta.get('duration')}s`
196
+
197
+ ---
198
+
199
+ ### 📊 Layer Breakdown
200
+ | Layer | Score | Status |
201
+ | :--- | :--- | :--- |
202
+ | **Frontend (Angular / React)** | `{s['frontend']}/100` | {'🔴 Critical' if s['frontend']<50 else '🟠 High Risk' if s['frontend']<70 else '✅ Good'} |
203
+ | **Node.js / Seneca** | `{s['backend']}/100` | {'🔴 Critical' if s['backend']<50 else '🟠 High Risk' if s['backend']<70 else '✅ Good'} |
204
+ | **SQL / Database** | `{s['database']}/100` | {'🔴 Critical' if s['database']<50 else '🟠 High Risk' if s['database']<70 else '✅ Good'} |
205
+ | **AWS / Cloud Infra** | `{s['infra']}/100` | {'🔴 Critical' if s['infra']<50 else '🟠 High Risk' if s['infra']<70 else '✅ Good'} |
206
+
207
+ ### 🚨 Top Critical Bottlenecks
208
+ """
209
+ for idx, t in enumerate(s.get('top3', []), 1):
210
+ md += f"\n{idx}. **[{t['severity'].upper()}] {t['title']}**\n"
211
+ md += f" - **File**: `{t['file']}`\n"
212
+ md += f" - **Impact**: {t['perf_gain']}\n"
213
+
214
+ md += "\n> 💡 *Generated by [Performance Optimizer v2.5 PRO](https://github.com/Ravik27280/Performance-Optimizer)*\n"
215
+
216
+ with open(out_path, 'w', encoding='utf-8') as fh:
217
+ fh.write(md)
218
+ print(f' 📝 Markdown summary saved: {out_path}')
219
+
220
+ def main():
221
+ print(BANNER)
222
+
223
+ parser = argparse.ArgumentParser(
224
+ description='Performance Optimizer v2.5 PRO - Enterprise Multi-Stack Performance Analyzer'
225
+ )
226
+ parser.add_argument('--frontend', '-f', help='Path to Angular frontend repo', default=None)
227
+ parser.add_argument('--backend', '-b', help='Path to Node.js/Seneca backend repo', default=None)
228
+ parser.add_argument('--project', '-p', help='Path to monorepo (scans entire workspace)', default=None)
229
+ parser.add_argument('--output', '-o', help='Output HTML report path', default='performance_report.html')
230
+ parser.add_argument('--json', '-j', help='Output machine-readable JSON report', action='store_true')
231
+ parser.add_argument('--markdown-summary', '-m', help='Generate markdown report summary for PR comments', default=None)
232
+ parser.add_argument('--exclude', '-e', help='Comma-separated directory patterns to exclude', default='')
233
+ parser.add_argument('--fail-on', help='Fail CI with exit 1 if issues matching severity exist (critical, high)', default=None)
234
+ parser.add_argument('--min-score', help='Fail CI with exit 1 if overall score is below threshold (0-100)', type=int, default=None)
235
+ parser.add_argument('--verbose', '-v', help='Verbose terminal output', action='store_true')
236
+ args = parser.parse_args()
237
+
238
+ frontend_path = args.frontend or args.project
239
+ backend_path = args.backend or args.project
240
+ custom_excludes = [x.strip() for x in args.exclude.split(',') if x.strip()]
241
+
242
+ if not frontend_path and not backend_path:
243
+ print(' ❌ ERROR: Provide at least one of --frontend, --backend, or --project')
244
+ print(' Example: python optimizer.py --frontend ./angular-app --backend ./node-api')
245
+ parser.print_help()
246
+ sys.exit(1)
247
+
248
+ print(f' 📁 Frontend path : {frontend_path or "(not provided)"}')
249
+ print(f' 📁 Backend path : {backend_path or "(not provided)"}')
250
+ print(f' 💾 HTML Output : {args.output}')
251
+
252
+ total_files = 0
253
+ if frontend_path and Path(frontend_path).exists():
254
+ total_files += count_files(frontend_path, custom_excludes)
255
+ if backend_path and Path(backend_path).exists() and Path(backend_path).resolve() != Path(frontend_path or '').resolve():
256
+ total_files += count_files(backend_path, custom_excludes)
257
+
258
+ tech = detect_tech(frontend_path, backend_path)
259
+ print(f' 🔎 Detected tech : {tech}')
260
+ print(f' 📁 Files to scan : {total_files}')
261
+ print('\n Running analyzers...')
262
+
263
+ start_time = time.time()
264
+ all_issues = run_analyzers(frontend_path, backend_path, verbose=args.verbose)
265
+ duration = round(time.time() - start_time, 2)
266
+
267
+ print(f'\n ✔ Scan completed in {duration}s')
268
+
269
+ # Deduplicate issues with same (id, file, line_number)
270
+ seen: Set[tuple] = set()
271
+ unique_issues = []
272
+ for issue in all_issues:
273
+ key = (issue.id, issue.file, issue.line_number)
274
+ if key not in seen:
275
+ seen.add(key)
276
+ unique_issues.append(issue)
277
+ all_issues = unique_issues
278
+
279
+ # Compute scores
280
+ scorer = Scorer()
281
+ scores = scorer.compute(all_issues)
282
+ print_summary(scores, all_issues)
283
+
284
+ # Render HTML Dashboard
285
+ scan_time = datetime.now().strftime('%d %b %Y, %I:%M %p')
286
+ project_name = Path(frontend_path or backend_path).name or "Performance Project"
287
+ meta = {
288
+ 'project': project_name,
289
+ 'scan_time': scan_time,
290
+ 'files_scanned': total_files,
291
+ 'duration': duration,
292
+ 'tech': tech,
293
+ }
294
+
295
+ reporter = HtmlReporter(all_issues, scores, meta)
296
+ reporter.render(args.output)
297
+ print(f'\n 📊 Interactive HTML Dashboard saved: {args.output}')
298
+
299
+ # JSON export
300
+ if args.json:
301
+ json_path = args.output.replace('.html', '.json') if args.output.endswith('.html') else f"{args.output}.json"
302
+ report_data = {
303
+ 'meta': meta,
304
+ 'scores': scores,
305
+ 'issues': [i.to_dict() for i in all_issues],
306
+ }
307
+ with open(json_path, 'w', encoding='utf-8') as jf:
308
+ json.dump(report_data, jf, indent=2)
309
+ print(f' 💾 Machine-readable JSON saved: {json_path}')
310
+
311
+ # Markdown summary
312
+ if args.markdown_summary:
313
+ generate_markdown_summary(args.markdown_summary, scores, meta, all_issues)
314
+
315
+ # CI/CD Quality Gate evaluation
316
+ exit_code = 0
317
+ if args.fail_on:
318
+ threshold_sev = args.fail_on.lower()
319
+ critical_count = scores['by_severity'].get('critical', 0)
320
+ high_count = scores['by_severity'].get('high', 0)
321
+
322
+ if threshold_sev == 'critical' and critical_count > 0:
323
+ print(f'\n ❌ CI QUALITY GATE FAILED: Found {critical_count} critical performance issues (--fail-on critical)')
324
+ exit_code = 1
325
+ elif threshold_sev == 'high' and (critical_count > 0 or high_count > 0):
326
+ print(f'\n ❌ CI QUALITY GATE FAILED: Found {critical_count} critical and {high_count} high issues (--fail-on high)')
327
+ exit_code = 1
328
+
329
+ if args.min_score is not None:
330
+ if scores['overall'] < args.min_score:
331
+ print(f'\n ❌ CI QUALITY GATE FAILED: Overall score {scores["overall"]} is below minimum threshold of {args.min_score} (--min-score {args.min_score})')
332
+ exit_code = 1
333
+
334
+ if exit_code == 0:
335
+ print('\n ✔ Done! All quality checks passed.\n')
336
+ sys.exit(exit_code)
337
+
338
+ if __name__ == '__main__':
339
+ main()
@@ -0,0 +1,236 @@
1
+ Metadata-Version: 2.4
2
+ Name: performance-optimizer
3
+ Version: 2.5.0
4
+ Summary: Ultra-fast zero-dependency static performance analyzer for Angular, React, Node.js, SQL, and AWS.
5
+ Author: Performance Optimizer Core Team
6
+ License: MIT
7
+ Keywords: performance,static-analysis,angular,react,nodejs,sql,aws,latency,optimizer
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Topic :: Software Development :: Quality Assurance
11
+ Classifier: Topic :: Software Development :: Bug Tracking
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.7
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Requires-Python: >=3.7
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Dynamic: license-file
24
+
25
+ # Performance Optimizer v2.5 PRO — Advanced Multi-Stack Analyzer
26
+
27
+ > **NOT SonarQube.** This is an enterprise static performance & latency intelligence engine.
28
+ > **Targeted Runtimes**: Angular (14–19+), React (17–19+) & Next.js, Node.js & Seneca.js, SQL / Database Indexes, and AWS Serverless.
29
+ > Zero external dependencies — runs in `<0.05s` with Python 3.7+ standard library.
30
+
31
+ [![Live Portal](https://img.shields.io/badge/Live_Portal-GitHub_Pages-6366f1?style=for-the-badge&logo=github)](https://ravik27280.github.io/Performance-Optimizer/)
32
+ [![Python 3.7+](https://img.shields.io/badge/Python-3.7+-06b6d4?style=for-the-badge&logo=python)](https://www.python.org/)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-10b981?style=for-the-badge)](https://opensource.org/licenses/MIT)
34
+
35
+ 🌐 **Live Interactive Web Portal & Diagnostic Scanner**: [https://ravik27280.github.io/Performance-Optimizer/](https://ravik27280.github.io/Performance-Optimizer/)
36
+
37
+ ---
38
+
39
+ ## ⚡ Installation & CLI Setup
40
+
41
+ Install locally or as an editable package for global terminal access:
42
+
43
+ ```bash
44
+ # Clone the repository
45
+ git clone https://github.com/Ravik27280/Performance-Optimizer.git
46
+ cd Performance-Optimizer
47
+
48
+ # Install package globally / in virtual environment
49
+ pip install -e .
50
+
51
+ # Verify CLI installation
52
+ perf-optimizer --help
53
+ ```
54
+
55
+ ---
56
+
57
+ ## 🚀 Quick Start Examples
58
+
59
+ ```bash
60
+ # 1. Scan current repository / monorepo
61
+ perf-optimizer --project .
62
+
63
+ # 2. Scan separate frontend and backend directories
64
+ perf-optimizer --frontend ./angular-app --backend ./node-api
65
+
66
+ # 3. Enforce CI/CD Quality Gate (Exit 1 on critical issues or score < 75)
67
+ perf-optimizer --project . --fail-on critical --min-score 75
68
+
69
+ # 4. Generate HTML dashboard, JSON audit, and PR Markdown summary
70
+ perf-optimizer --project . --json --markdown-summary pr_summary.md --output report.html
71
+
72
+ # 5. Alternatively, run directly with python (zero pip packages required)
73
+ python optimizer.py --project . --verbose
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 📊 Output Formats
79
+
80
+ - **`performance_report.html`** — Interactive executive dashboard with code diff previews, ROI impact calculations, and dark/light modes.
81
+ - **`performance_report.json`** — Machine-readable audit data with exact line numbers and defect categories for custom tooling.
82
+ - **`pr_summary.md`** — Markdown report table designed for automated Pull Request comments in GitHub Actions and GitLab CI.
83
+
84
+ ---
85
+
86
+ ## 🤖 GitHub Actions CI/CD Integration
87
+
88
+ Create `.github/workflows/perf-audit.yml` to automatically run audits on every Pull Request:
89
+
90
+ ```yaml
91
+ name: Performance Quality Gate
92
+
93
+ on:
94
+ push:
95
+ branches: [ main ]
96
+ pull_request:
97
+ branches: [ main ]
98
+
99
+ jobs:
100
+ audit:
101
+ runs-on: ubuntu-latest
102
+ steps:
103
+ - uses: actions/checkout@v4
104
+ - uses: actions/setup-python@v5
105
+ with:
106
+ python-version: '3.11'
107
+ - name: Install Performance Optimizer
108
+ run: pip install -e .
109
+ - name: Run Performance Audit
110
+ run: |
111
+ perf-optimizer --project . --fail-on critical --min-score 75
112
+ ```
113
+
114
+ ---
115
+
116
+ ## 🛡️ CLI Flags & Options
117
+
118
+ | Argument | Description | Example |
119
+ |---|---|---|
120
+ | `--project`, `-p` | Path to monorepo or project (scans entire workspace) | `--project .` |
121
+ | `--frontend`, `-f` | Path to Angular or React frontend codebase | `--frontend ./src/web` |
122
+ | `--backend`, `-b` | Path to Node.js/Seneca/Express codebase | `--backend ./src/api` |
123
+ | `--fail-on` | Fails CI with exit code `1` if issues matching severity exist | `--fail-on critical` or `--fail-on high` |
124
+ | `--min-score` | Fails CI with exit code `1` if overall score is below threshold | `--min-score 75` |
125
+ | `--exclude`, `-e` | Comma-separated directory patterns to exclude | `--exclude "legacy,tmp,e2e"` |
126
+ | `--json`, `-j` | Generates machine-readable JSON report | `--json` |
127
+ | `--markdown-summary`, `-m` | Generates PR comment summary file | `--markdown-summary pr_summary.md` |
128
+ | `--output`, `-o` | Custom HTML report output path | `--output ./dist/perf_report.html` |
129
+ | `--verbose`, `-v` | Detailed terminal output during scan | `--verbose` |
130
+
131
+ ---
132
+
133
+ ## 🔇 Inline Rule Suppression
134
+
135
+ Suppress false positives or accepted trade-offs directly in code:
136
+
137
+ ```typescript
138
+ // Angular / TypeScript / JavaScript
139
+ // perf-ignore ANG001
140
+ @Component({ ... })
141
+
142
+ // Node.js
143
+ // perf-ignore NODE001
144
+ const bootConfig = fs.readFileSync('boot.json', 'utf8');
145
+
146
+ // SQL / Schema
147
+ -- perf-ignore SQL004
148
+ CREATE TABLE temp_session ( ... );
149
+ ```
150
+
151
+ ---
152
+
153
+ ## 🔍 What It Detects (Performance-Specific)
154
+
155
+ ### Angular / Modern Frontend (Angular 16–19+)
156
+ | ID | Check | Category | Impact |
157
+ |---|---|---|---|
158
+ | **ANG001** | Missing OnPush Change Detection | DOM Re-render | 65% re-render reduction |
159
+ | **ANG002** | Direct @Input Property Mutation | Change Detection | Restores OnPush change detection |
160
+ | **ANG003** | `detectChanges()` Synchronously Inside Loop | Render Cycle | Eliminates N render cycles |
161
+ | **ANG004** | Observable Memory Leak (Missing Unsubscribe / Teardown) | Memory Leak | Eliminates heap growth per route |
162
+ | **ANG005** | Nested `subscribe()` Callback Anti-pattern | Concurrency | Eliminates race conditions & request leaks |
163
+ | **ANG006** | API Call Without Pagination (Full Collection Fetch) | Network & Heap | 70%+ TTI improvement |
164
+ | **ANG007** | Missing `debounceTime` on Reactive Form Streams | Network | Up to 85% fewer API requests |
165
+ | **ANG008** | Missing HTTP Response Caching (`shareReplay`) | Network | Eliminates duplicate network calls |
166
+ | **ANG009** | `*ngFor` Without `trackBy` or `@for` Without `track` | DOM Performance | 99% fewer DOM node recreations |
167
+ | **ANG010** | Missing Virtual Scrolling for Large Lists | DOM Performance | Renders only ~20 DOM nodes |
168
+ | **ANG011** | Method Calls in Template Interpolation | DOM Re-render | Eliminates expensive method re-evaluations |
169
+ | **ANG012** | Wildcard / Full Library Imports (`lodash`, `rxjs/Rx`) | Bundle Size | 50–80KB bundle reduction |
170
+ | **ANG013** | No Lazy Loading Routes (All Eager at Startup) | Bundle Size | 40–60% initial bundle cut |
171
+ | **ANG014** | Heavy Subcomponents Rendered Without `@defer` | Core Web Vitals | Speeds up LCP & initial chunk parse |
172
+
173
+ ### React & Next.js (React 17–19+)
174
+ | ID | Check | Category | Impact |
175
+ |---|---|---|---|
176
+ | **REACT001** | Array Index as `key` in List Rendering | Reconciliation | Enables DOM node reuse on mutations |
177
+ | **REACT002** | Direct State Mutation Anti-pattern | State Management | Prevents broken re-render schedules |
178
+ | **REACT003** | `useEffect` Missing Dependency Array | Render Loop | Eliminates runaway infinite re-render loops |
179
+ | **REACT004** | Expensive Array Calculations Without `useMemo` | CPU Efficiency | Avoids heavy sorting/filtering recalculations |
180
+ | **REACT005** | Eager Route Components Without `React.lazy()` | Bundle Size | 30–50% smaller initial JS chunks |
181
+ | **REACT006** | Context Value Recreated as New Object on Render | Re-render Cascade | Stops cascading subtree re-renders |
182
+
183
+ ### Node.js / Seneca / Express Backend
184
+ | ID | Check | Category | Impact |
185
+ |---|---|---|---|
186
+ | **NODE001** | Synchronous `fs` Calls in Runtime Execution Paths | Event Loop | Unblocks Node.js event loop |
187
+ | **NODE002** | Sequential `await` on Independent Operations | Concurrency | Up to 50% latency reduction |
188
+ | **NODE003** | Promise Chains Without `.catch()` | Stability | Prevents unhandled rejections |
189
+ | **NODE004** | **N+1 Database Query Pattern in Loop** | Database I/O | O(N) → O(1) query roundtrips |
190
+ | **NODE005** | **Database Queries Without LIMIT (Returns All Rows)** | Database I/O | Caps payload and memory bounds |
191
+ | **NODE006** | No Caching Layer for Repeated Queries (Redis) | Database I/O | 60–90% database load reduction |
192
+ | **NODE007** | API Response Over-fetching (`SELECT *` to `res.json`) | Serialization | Smaller payloads, faster JSON encode |
193
+ | **NODE008** | Express Missing Gzip/Brotli Compression | Network | 70–90% smaller response sizes |
194
+ | **NODE009** | Unbounded In-Memory Array Growth | Memory Leak | Prevents OOM crashes |
195
+ | **NODE010** | Database Connection Pool Configured Too Small | Database I/O | Eliminates connection queue delays |
196
+ | **NODE011** | **EventEmitter Memory Leak (Missing Listener Teardown)** | Memory Leak | Eliminates closure/listener leaks |
197
+ | **NODE012** | **HTTP Requests Missing Connection Reuse (`keepAlive: true`)** | Network | Saves 50–100ms TLS handshakes |
198
+ | **SEN001** | Seneca `.act()` Inside Iteration Loop | Microservice RPC | N×latency → max(latency) |
199
+ | **SEN002** | Seneca `.act()` Without Explicit Timeout | Stability | Prevents cascading request hangs |
200
+
201
+ ### SQL / RDS / Database
202
+ | ID | Check | Category | Impact |
203
+ |---|---|---|---|
204
+ | **SQL001** | `SELECT *` Column Over-fetching | Database I/O | Faster queries, less I/O |
205
+ | **SQL002** | UPDATE/DELETE Without WHERE Clause | Data Integrity | Prevents full table locks & corruption |
206
+ | **SQL003** | SELECT Without LIMIT | Result Bounds | Fixed result set size |
207
+ | **SQL004** | **Missing Index on Foreign Key Columns** | Indexing | Converts O(N) table scan to O(log N) |
208
+ | **SQL005** | SQL Query Built via String Concatenation | Plan Cache | Reuses compiled query plans |
209
+ | **SQL006** | `LIKE '%query'` Leading Wildcard (B-Tree Incompatible) | Indexing | Enables index seeks |
210
+ | **SQL007** | **Deep OFFSET Pagination Antipattern** | Query Optimization | Keyset pagination saves O(N) discard |
211
+
212
+ ### AWS / Serverless / Cloud Infrastructure
213
+ | ID | Check | Category | Impact |
214
+ |---|---|---|---|
215
+ | **AWS001** | Lambda Memory Allocated Too Low (<512MB) | CPU & Latency | 50–75% faster execution |
216
+ | **AWS002** | Static S3 Hosting Without CloudFront CDN | Edge Delivery | 300ms → 20ms global asset delivery |
217
+ | **AWS003** | Lambda Functions Without Explicit Timeout | Cost & Timeouts | Prevents runaway costs on hangs |
218
+ | **AWS005** | **Lambda Direct to RDS Without RDS Proxy** | Connection Pool | Prevents DB connection exhaustion |
219
+
220
+ ---
221
+
222
+ ## 📈 Scoring Engine
223
+
224
+ - **Asymptotic Logarithmic Curve**: Avoids artificial zero-score cliffs; accurately reflects true performance health for codebases of any size.
225
+ - **Architectural Layer Weights**:
226
+ $$\text{Overall} = 40\% \text{Frontend} + 30\% \text{Backend} + 20\% \text{Database} + 10\% \text{Infra}$$
227
+ - **Priority Rank**: Calculated via $\text{Impact} / \max(\text{Effort}, 1)$ to prioritize high-impact, low-effort wins.
228
+
229
+ ---
230
+
231
+ ## 🧪 Automated Testing
232
+
233
+ Run the included unit test suite:
234
+ ```bash
235
+ python -m unittest discover -s tests -p "test_*.py" -v
236
+ ```
@@ -0,0 +1,18 @@
1
+ optimizer.py,sha256=jYzzYY2gHi9KJZz8imEemfXB9-c9DGrgggYrVk0Oq8s,15309
2
+ analyzers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ analyzers/angular_analyzer.py,sha256=UvkfTo3TZLPr7VseslcwP3qDxqt_v-n6a37xe8HxHko,23901
4
+ analyzers/aws_analyzer.py,sha256=sEyCWv3p36deftVe2wgxNILXAt3mtV4zkUoiFTpECQ8,6670
5
+ analyzers/node_analyzer.py,sha256=AEQKtI0g_YxWsV9r4HgJdbBYKOv0FNl9g8xqli2nWfY,18093
6
+ analyzers/react_analyzer.py,sha256=PlAhlDqUllVLOgnN1CVVHtRWgbOofUrq22ACh1jd0Ao,13332
7
+ analyzers/sql_analyzer.py,sha256=FExpp-9OA2FaajmwzHIh-JlP85tM9NsxZiLtEcBRR9k,10205
8
+ core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ core/issue.py,sha256=snKmRSeNZb_wLX8uAdJ3ntMAjAKcABuVisbuxegvC1Q,1893
10
+ core/scorer.py,sha256=zLGzxBkCxE3mz9J1_h6mk41Yc1UxTxyizSow5IVjoQw,3821
11
+ performance_optimizer-2.5.0.dist-info/licenses/LICENSE,sha256=-mOdQJ_EYbSVRnT-XOh0MmAbdBFoH2w8_llqcxHs57k,1079
12
+ reporter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ reporter/html_reporter.py,sha256=i0MT232a4RC0I027XPNe6wI8Q7MD9s7dkZBkDclWeUs,51997
14
+ performance_optimizer-2.5.0.dist-info/METADATA,sha256=tgUb9YgwuMxrPH-sonB8TXWm1RzNqAF-54QkO2KqWNM,11735
15
+ performance_optimizer-2.5.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
16
+ performance_optimizer-2.5.0.dist-info/entry_points.txt,sha256=_pux5PibB9PvVJgNwAYOf0JlEV_SIRJLxdk57cg-gC8,89
17
+ performance_optimizer-2.5.0.dist-info/top_level.txt,sha256=GlwwpDftYMHkQlHF0kBSvUXtJFaARCBoPn_kCwyMEss,34
18
+ performance_optimizer-2.5.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ perf-optimizer = optimizer:main
3
+ performance-optimizer = optimizer:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ravi Kumar Vishwakarma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ analyzers
2
+ core
3
+ optimizer
4
+ reporter
reporter/__init__.py ADDED
File without changes