lambda-doctor 0.1.0 → 0.1.2
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.
- package/README.md +101 -19
- package/dist/cli.js +48 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.js +24 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Static analysis CLI that scans your Node.js Lambda project and tells you exactly
|
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
[](https://www.typescriptlang.org/)
|
|
12
12
|
|
|
13
|
-
[Quick Start](#quick-start) · [What It Checks](#what-it-checks) · [
|
|
13
|
+
[Quick Start](#quick-start) · [What It Checks](#what-it-checks) · [Real-World Results](#real-world-results) · [CLI Options](#cli-options)
|
|
14
14
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
@@ -39,38 +39,88 @@ That's it. You get a full diagnosis in seconds.
|
|
|
39
39
|
| Analyzer | What it does | Severity |
|
|
40
40
|
|---|---|---|
|
|
41
41
|
| **Bundle Size** | Scans `node_modules`, reports total size and top 10 largest packages | 🔴 >50MB, ⚠️ >10MB |
|
|
42
|
-
| **Heavy Dependencies** | Flags known heavy packages (moment, lodash, axios, etc.) and dev tools in production | 🔴 dev tools in prod, ⚠️ heavy deps |
|
|
42
|
+
| **Heavy Dependencies** | Flags known heavy packages (moment, lodash, axios, mongoose, etc.) and dev tools in production | 🔴 dev tools in prod, ⚠️ heavy deps |
|
|
43
43
|
| **Import Analysis** | Detects `import *` (tree-shaking blocker) and top-level heavy imports | ⚠️ per pattern |
|
|
44
44
|
| **AWS SDK** | Detects v2 usage, incomplete v2→v3 migration, unnecessary clients (e.g. SSO in Lambda) | 🔴 v2, ⚠️ mixed |
|
|
45
45
|
| **Bundler Detection** | Checks for esbuild/webpack/rollup/tsup — no bundler = biggest improvement opportunity | 🔴 no bundler |
|
|
46
46
|
|
|
47
|
-
##
|
|
47
|
+
## Real-World Results
|
|
48
|
+
|
|
49
|
+
We tested Lambda Doctor against popular open-source serverless projects:
|
|
50
|
+
|
|
51
|
+
| Project | ⭐ Stars | Critical | Warnings | Est. Improvement |
|
|
52
|
+
|---|---|---|---|---|
|
|
53
|
+
| [webiny/webiny-js](https://github.com/webiny/webiny-js) | 7.9k | 1 | 225 | **~4.7s** |
|
|
54
|
+
| [aws-powertools/powertools-lambda-typescript](https://github.com/aws-powertools/powertools-lambda-typescript) | 1.8k | 1 | 3 | ~920ms |
|
|
55
|
+
| [anomalyco/demo-notes-app](https://github.com/anomalyco/demo-notes-app) (SST Guide) | 195 | 1 | 2 | ~542ms |
|
|
56
|
+
| [adamjq/production-ready-serverless-nestjs](https://github.com/adamjq/production-ready-serverless-nestjs) | 40 | 0 | 5 | ~350ms |
|
|
57
|
+
|
|
58
|
+
### Example: NestJS Lambda API
|
|
59
|
+
|
|
60
|
+
Running against [adamjq/production-ready-serverless-nestjs](https://github.com/adamjq/production-ready-serverless-nestjs) — a production-ready NestJS GraphQL API on AWS Lambda with Prisma and Webpack:
|
|
48
61
|
|
|
49
62
|
```
|
|
50
63
|
🩺 Lambda Doctor — Diagnosis Report
|
|
64
|
+
Target: ./production-ready-serverless-nestjs
|
|
51
65
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
🔍 Diagnostics
|
|
67
|
+
|
|
68
|
+
⚠️ WARNING Heavy dependency: @nestjs/core (package.json)
|
|
69
|
+
NestJS is a heavy framework (5MB+). Decorator metadata and DI container add cold start overhead.
|
|
70
|
+
→ Use lighter patterns for Lambda: plain handlers or lambda-api.
|
|
71
|
+
⏱ Est. improvement: ~150ms
|
|
72
|
+
|
|
73
|
+
⚠️ WARNING Heavy dependency: express (package.json)
|
|
74
|
+
Express has 30+ dependencies. Heavy for a single Lambda function.
|
|
75
|
+
→ Use lambda-api (zero deps) or direct API Gateway event parsing.
|
|
76
|
+
⏱ Est. improvement: ~20ms
|
|
77
|
+
|
|
78
|
+
⚠️ WARNING Top-level import of heavy package "@nestjs/core" (src/lambda.ts:1)
|
|
79
|
+
"@nestjs/core" is imported at the top level in src/lambda.ts.
|
|
80
|
+
→ Consider lazy-loading: move the import inside the function that uses it.
|
|
81
|
+
⏱ Est. improvement: ~75ms
|
|
82
|
+
|
|
83
|
+
💡 INFO Bundler detected: webpack
|
|
84
|
+
Found bundler setup: packages=[webpack], configs=[webpack.config.js].
|
|
85
|
+
→ Ensure your bundler is configured for tree-shaking and minification.
|
|
55
86
|
|
|
56
|
-
|
|
57
|
-
→
|
|
58
|
-
⏱ Est. improvement: ~
|
|
87
|
+
💡 INFO Project is not using ESM
|
|
88
|
+
→ Consider setting "type": "module" in package.json for better tree-shaking support.
|
|
89
|
+
⏱ Est. improvement: ~20ms
|
|
90
|
+
|
|
91
|
+
────────────────────────────────────────────────────────────
|
|
92
|
+
Summary: 0 critical | 5 warnings | 2 info
|
|
93
|
+
|
|
94
|
+
🚀 Total estimated cold start improvement: ~350ms
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Example: SST Demo Notes App
|
|
98
|
+
|
|
99
|
+
Running against [anomalyco/demo-notes-app](https://github.com/anomalyco/demo-notes-app) — the official SST Guide demo app:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
🩺 Lambda Doctor — Diagnosis Report
|
|
103
|
+
Target: ./demo-notes-app
|
|
59
104
|
|
|
60
|
-
|
|
105
|
+
🔍 Diagnostics
|
|
106
|
+
|
|
107
|
+
🔴 CRITICAL No bundler detected
|
|
108
|
+
No bundler (esbuild, webpack, rollup, etc.) was found in this project.
|
|
61
109
|
→ Add esbuild (fastest) or webpack to bundle your Lambda function.
|
|
62
110
|
⏱ Est. improvement: ~500ms
|
|
63
111
|
|
|
64
|
-
⚠️ WARNING
|
|
65
|
-
→ Use
|
|
66
|
-
⏱ Est. improvement: ~50ms
|
|
67
|
-
|
|
68
|
-
⚠️ WARNING Wildcard import of "aws-sdk" prevents tree-shaking
|
|
69
|
-
→ Use named imports: import { specificFunction } from "aws-sdk"
|
|
112
|
+
⚠️ WARNING Wildcard import of "uuid" prevents tree-shaking (packages/functions/src/create.ts:1)
|
|
113
|
+
→ Use named imports: import { specificFunction } from "uuid"
|
|
70
114
|
⏱ Est. improvement: ~20ms
|
|
71
115
|
|
|
72
|
-
|
|
73
|
-
|
|
116
|
+
⚠️ WARNING Top-level import of heavy package "uuid" (packages/functions/src/create.ts:1)
|
|
117
|
+
→ Use crypto.randomUUID() (built-in Node 18+).
|
|
118
|
+
⏱ Est. improvement: ~2.5ms
|
|
119
|
+
|
|
120
|
+
────────────────────────────────────────────────────────────
|
|
121
|
+
Summary: 1 critical | 2 warnings | 1 info
|
|
122
|
+
|
|
123
|
+
🚀 Total estimated cold start improvement: ~542.5ms
|
|
74
124
|
```
|
|
75
125
|
|
|
76
126
|
## How It Works
|
|
@@ -114,13 +164,45 @@ lambda-doctor analyze ./my-lambda
|
|
|
114
164
|
|
|
115
165
|
# JSON output (for CI/CD pipelines)
|
|
116
166
|
lambda-doctor analyze ./my-lambda --format json
|
|
167
|
+
|
|
168
|
+
# Add custom exclude patterns
|
|
169
|
+
lambda-doctor analyze ./my-lambda --exclude "scripts/**,packages/frontend/**"
|
|
170
|
+
|
|
171
|
+
# Disable default excludes (scan everything including tests)
|
|
172
|
+
lambda-doctor analyze ./my-lambda --no-default-excludes
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Smart Defaults
|
|
176
|
+
|
|
177
|
+
Lambda Doctor automatically excludes test and build files that don't run in Lambda:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
__tests__/ *.test.* *.spec.* test/ tests/
|
|
181
|
+
cypress/ coverage/ dist/ build/ cdk.out/ .serverless/
|
|
117
182
|
```
|
|
118
183
|
|
|
184
|
+
You can override this with `--no-default-excludes` or add more patterns with `--exclude`.
|
|
185
|
+
|
|
119
186
|
### Exit Codes
|
|
120
187
|
|
|
121
188
|
- `0` — No critical issues found
|
|
122
189
|
- `1` — Critical issues detected (useful for CI gates)
|
|
123
190
|
|
|
191
|
+
### Programmatic API
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { analyze } from 'lambda-doctor';
|
|
195
|
+
|
|
196
|
+
const report = await analyze({
|
|
197
|
+
targetPath: './my-lambda',
|
|
198
|
+
format: 'json',
|
|
199
|
+
exclude: ['scripts/**', 'frontend/**'],
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
console.log(report.summary);
|
|
203
|
+
// { totalIssues: 7, critical: 1, warnings: 5, info: 1, estimatedTotalImpactMs: 820 }
|
|
204
|
+
```
|
|
205
|
+
|
|
124
206
|
## Requirements
|
|
125
207
|
|
|
126
208
|
- Node.js >= 18
|
|
@@ -147,4 +229,4 @@ npm test
|
|
|
147
229
|
|
|
148
230
|
Built by [Ozer](https://github.com/ozers) — because staring at CloudWatch cold start metrics at 2am shouldn't be a regular thing.
|
|
149
231
|
|
|
150
|
-
</div>
|
|
232
|
+
</div>
|
package/dist/cli.js
CHANGED
|
@@ -5,10 +5,28 @@ import { Command } from "commander";
|
|
|
5
5
|
import ora from "ora";
|
|
6
6
|
import fs6 from "fs/promises";
|
|
7
7
|
import path7 from "path";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
8
9
|
|
|
9
10
|
// src/index.ts
|
|
10
11
|
import path6 from "path";
|
|
11
12
|
|
|
13
|
+
// types.ts
|
|
14
|
+
var DEFAULT_EXCLUDE_PATTERNS = [
|
|
15
|
+
"node_modules/**",
|
|
16
|
+
"dist/**",
|
|
17
|
+
"build/**",
|
|
18
|
+
"coverage/**",
|
|
19
|
+
"**/*.d.ts",
|
|
20
|
+
"**/__tests__/**",
|
|
21
|
+
"**/*.test.*",
|
|
22
|
+
"**/*.spec.*",
|
|
23
|
+
"**/test/**",
|
|
24
|
+
"**/tests/**",
|
|
25
|
+
"**/cypress/**",
|
|
26
|
+
"**/.serverless/**",
|
|
27
|
+
"**/cdk.out/**"
|
|
28
|
+
];
|
|
29
|
+
|
|
12
30
|
// src/analyzers/bundle-size.ts
|
|
13
31
|
import fg from "fast-glob";
|
|
14
32
|
import fs from "fs/promises";
|
|
@@ -232,10 +250,10 @@ var HEAVY_PACKAGES = [
|
|
|
232
250
|
}
|
|
233
251
|
];
|
|
234
252
|
function findHeavyPackage(name) {
|
|
235
|
-
return HEAVY_PACKAGES.find((
|
|
253
|
+
return HEAVY_PACKAGES.find((pkg2) => pkg2.name === name);
|
|
236
254
|
}
|
|
237
255
|
function isHeavyPackage(name) {
|
|
238
|
-
return HEAVY_PACKAGES.some((
|
|
256
|
+
return HEAVY_PACKAGES.some((pkg2) => pkg2.name === name);
|
|
239
257
|
}
|
|
240
258
|
|
|
241
259
|
// src/analyzers/heavy-dependencies.ts
|
|
@@ -319,13 +337,13 @@ function isTopLevel(line) {
|
|
|
319
337
|
var importAnalysisAnalyzer = {
|
|
320
338
|
name: "import-analysis",
|
|
321
339
|
description: "Analyzes import patterns for tree-shaking issues and heavy top-level imports",
|
|
322
|
-
async analyze(targetPath) {
|
|
340
|
+
async analyze(targetPath, exclude) {
|
|
323
341
|
const start = performance.now();
|
|
324
342
|
const diagnostics = [];
|
|
325
343
|
try {
|
|
326
344
|
const files = await fg2(["**/*.ts", "**/*.js", "**/*.mjs"], {
|
|
327
345
|
cwd: targetPath,
|
|
328
|
-
ignore:
|
|
346
|
+
ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,
|
|
329
347
|
absolute: false
|
|
330
348
|
});
|
|
331
349
|
for (const file of files) {
|
|
@@ -337,12 +355,12 @@ var importAnalysisAnalyzer = {
|
|
|
337
355
|
let match;
|
|
338
356
|
WILDCARD_IMPORT.lastIndex = 0;
|
|
339
357
|
while ((match = WILDCARD_IMPORT.exec(line)) !== null) {
|
|
340
|
-
const
|
|
341
|
-
if (
|
|
358
|
+
const pkg2 = getPackageName2(match[1]);
|
|
359
|
+
if (pkg2) {
|
|
342
360
|
diagnostics.push({
|
|
343
361
|
analyzer: "import-analysis",
|
|
344
362
|
severity: "warning",
|
|
345
|
-
title: `Wildcard import of "${
|
|
363
|
+
title: `Wildcard import of "${pkg2}" prevents tree-shaking`,
|
|
346
364
|
description: `"import * as ..." from "${match[1]}" imports the entire module, preventing bundlers from removing unused code.`,
|
|
347
365
|
recommendation: `Use named imports: import { specificFunction } from "${match[1]}"`,
|
|
348
366
|
estimatedImpactMs: 20,
|
|
@@ -355,14 +373,14 @@ var importAnalysisAnalyzer = {
|
|
|
355
373
|
for (const regex of [ESM_IMPORT, CJS_REQUIRE]) {
|
|
356
374
|
regex.lastIndex = 0;
|
|
357
375
|
while ((match = regex.exec(line)) !== null) {
|
|
358
|
-
const
|
|
359
|
-
if (
|
|
360
|
-
const heavy = findHeavyPackage(
|
|
376
|
+
const pkg2 = getPackageName2(match[1]);
|
|
377
|
+
if (pkg2 && isHeavyPackage(pkg2)) {
|
|
378
|
+
const heavy = findHeavyPackage(pkg2);
|
|
361
379
|
diagnostics.push({
|
|
362
380
|
analyzer: "import-analysis",
|
|
363
381
|
severity: "warning",
|
|
364
|
-
title: `Top-level import of heavy package "${
|
|
365
|
-
description: `"${
|
|
382
|
+
title: `Top-level import of heavy package "${pkg2}"`,
|
|
383
|
+
description: `"${pkg2}" is imported at the top level in ${file}. This forces it to load during cold start even if not needed for every invocation.`,
|
|
366
384
|
recommendation: `Consider lazy-loading: move the import inside the function that uses it. ${heavy.alternative}`,
|
|
367
385
|
estimatedImpactMs: heavy.estimatedSavingsMs / 2,
|
|
368
386
|
filePath: file,
|
|
@@ -398,7 +416,7 @@ import path4 from "path";
|
|
|
398
416
|
var awsSdkAnalyzer = {
|
|
399
417
|
name: "aws-sdk",
|
|
400
418
|
description: "Checks AWS SDK version usage and migration status",
|
|
401
|
-
async analyze(targetPath) {
|
|
419
|
+
async analyze(targetPath, exclude) {
|
|
402
420
|
const start = performance.now();
|
|
403
421
|
const diagnostics = [];
|
|
404
422
|
try {
|
|
@@ -442,7 +460,7 @@ var awsSdkAnalyzer = {
|
|
|
442
460
|
}
|
|
443
461
|
const sourceFiles = await fg3(["**/*.ts", "**/*.js", "**/*.mjs"], {
|
|
444
462
|
cwd: targetPath,
|
|
445
|
-
ignore:
|
|
463
|
+
ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,
|
|
446
464
|
absolute: false
|
|
447
465
|
});
|
|
448
466
|
for (const file of sourceFiles) {
|
|
@@ -671,9 +689,10 @@ var ALL_ANALYZERS = [
|
|
|
671
689
|
async function analyze(config) {
|
|
672
690
|
const targetPath = path6.resolve(config.targetPath);
|
|
673
691
|
const start = performance.now();
|
|
692
|
+
const excludePatterns = config.exclude ?? DEFAULT_EXCLUDE_PATTERNS;
|
|
674
693
|
const analyzersToRun = config.analyzers ? ALL_ANALYZERS.filter((a) => config.analyzers.includes(a.name)) : ALL_ANALYZERS;
|
|
675
694
|
const results = await Promise.all(
|
|
676
|
-
analyzersToRun.map((a) => a.analyze(targetPath))
|
|
695
|
+
analyzersToRun.map((a) => a.analyze(targetPath, excludePatterns))
|
|
677
696
|
);
|
|
678
697
|
const allDiagnostics = results.flatMap((r) => r.diagnostics);
|
|
679
698
|
const summary = {
|
|
@@ -695,9 +714,11 @@ async function analyze(config) {
|
|
|
695
714
|
}
|
|
696
715
|
|
|
697
716
|
// src/bin/cli.ts
|
|
717
|
+
var __dirname = path7.dirname(fileURLToPath(import.meta.url));
|
|
718
|
+
var pkg = JSON.parse(await fs6.readFile(path7.join(__dirname, "..", "package.json"), "utf-8"));
|
|
698
719
|
var program = new Command();
|
|
699
|
-
program.name("lambda-doctor").description("Diagnose and fix AWS Lambda cold start performance issues").version(
|
|
700
|
-
program.command("analyze").description("Analyze a Lambda project directory").argument("<path>", "Path to the Lambda project directory").option("--format <format>", "Output format: console or json", "console").option("--verbose", "Show verbose output", false).action(async (targetPath, options) => {
|
|
720
|
+
program.name("lambda-doctor").description("Diagnose and fix AWS Lambda cold start performance issues").version(pkg.version);
|
|
721
|
+
program.command("analyze").description("Analyze a Lambda project directory").argument("<path>", "Path to the Lambda project directory").option("--format <format>", "Output format: console or json", "console").option("--verbose", "Show verbose output", false).option("--exclude <patterns>", "Comma-separated glob patterns to exclude (default: tests, dist, build, cypress, coverage)").option("--no-default-excludes", "Disable default exclude patterns (tests, cypress, etc.)").action(async (targetPath, options) => {
|
|
701
722
|
const resolvedPath = path7.resolve(targetPath);
|
|
702
723
|
try {
|
|
703
724
|
await fs6.access(resolvedPath);
|
|
@@ -711,12 +732,21 @@ program.command("analyze").description("Analyze a Lambda project directory").arg
|
|
|
711
732
|
console.error(`Error: No package.json found in ${resolvedPath}`);
|
|
712
733
|
process.exit(1);
|
|
713
734
|
}
|
|
735
|
+
let excludePatterns;
|
|
736
|
+
if (!options.defaultExcludes) {
|
|
737
|
+
excludePatterns = ["node_modules/**", "dist/**", "**/*.d.ts"];
|
|
738
|
+
}
|
|
739
|
+
if (options.exclude) {
|
|
740
|
+
const userPatterns = options.exclude.split(",").map((p) => p.trim());
|
|
741
|
+
excludePatterns = [...excludePatterns ?? [], ...userPatterns];
|
|
742
|
+
}
|
|
714
743
|
const spinner = ora("Analyzing Lambda project...").start();
|
|
715
744
|
try {
|
|
716
745
|
const report = await analyze({
|
|
717
746
|
targetPath: resolvedPath,
|
|
718
747
|
format: options.format,
|
|
719
|
-
verbose: options.verbose
|
|
748
|
+
verbose: options.verbose,
|
|
749
|
+
exclude: excludePatterns
|
|
720
750
|
});
|
|
721
751
|
spinner.stop();
|
|
722
752
|
if (options.format === "json") {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bin/cli.ts","../src/index.ts","../src/analyzers/bundle-size.ts","../src/analyzers/heavy-dependencies.ts","../known-heavy-packages.ts","../src/analyzers/import-analysis.ts","../src/analyzers/aws-sdk.ts","../src/analyzers/bundler-detection.ts","../src/reporters/console.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { analyze, printReport } from '../index.js';\n\nconst program = new Command();\n\nprogram\n .name('lambda-doctor')\n .description('Diagnose and fix AWS Lambda cold start performance issues')\n .version('0.1.0');\n\nprogram\n .command('analyze')\n .description('Analyze a Lambda project directory')\n .argument('<path>', 'Path to the Lambda project directory')\n .option('--format <format>', 'Output format: console or json', 'console')\n .option('--verbose', 'Show verbose output', false)\n .action(async (targetPath: string, options: { format: string; verbose: boolean }) => {\n const resolvedPath = path.resolve(targetPath);\n\n // Validate path exists\n try {\n await fs.access(resolvedPath);\n } catch {\n console.error(`Error: Path does not exist: ${resolvedPath}`);\n process.exit(1);\n }\n\n // Validate package.json exists\n try {\n await fs.access(path.join(resolvedPath, 'package.json'));\n } catch {\n console.error(`Error: No package.json found in ${resolvedPath}`);\n process.exit(1);\n }\n\n const spinner = ora('Analyzing Lambda project...').start();\n\n try {\n const report = await analyze({\n targetPath: resolvedPath,\n format: options.format as 'console' | 'json',\n verbose: options.verbose,\n });\n\n spinner.stop();\n\n if (options.format === 'json') {\n console.log(JSON.stringify(report, null, 2));\n } else {\n printReport(report);\n }\n\n if (report.summary.critical > 0) {\n process.exit(1);\n }\n } catch (error) {\n spinner.fail('Analysis failed');\n console.error(error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import path from 'path';\nimport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nimport { bundleSizeAnalyzer } from './analyzers/bundle-size.js';\nimport { heavyDependenciesAnalyzer } from './analyzers/heavy-dependencies.js';\nimport { importAnalysisAnalyzer } from './analyzers/import-analysis.js';\nimport { awsSdkAnalyzer } from './analyzers/aws-sdk.js';\nimport { bundlerDetectionAnalyzer } from './analyzers/bundler-detection.js';\n\nexport { printReport } from './reporters/console.js';\n\nconst ALL_ANALYZERS: Analyzer[] = [\n bundleSizeAnalyzer,\n heavyDependenciesAnalyzer,\n importAnalysisAnalyzer,\n awsSdkAnalyzer,\n bundlerDetectionAnalyzer,\n];\n\nexport async function analyze(config: AnalyzeConfig): Promise<DiagnosisReport> {\n const targetPath = path.resolve(config.targetPath);\n const start = performance.now();\n\n const analyzersToRun = config.analyzers\n ? ALL_ANALYZERS.filter((a) => config.analyzers!.includes(a.name))\n : ALL_ANALYZERS;\n\n const results = await Promise.all(\n analyzersToRun.map((a) => a.analyze(targetPath)),\n );\n\n const allDiagnostics = results.flatMap((r) => r.diagnostics);\n const summary: ReportSummary = {\n totalIssues: allDiagnostics.length,\n critical: allDiagnostics.filter((d) => d.severity === 'critical').length,\n warnings: allDiagnostics.filter((d) => d.severity === 'warning').length,\n info: allDiagnostics.filter((d) => d.severity === 'info').length,\n estimatedTotalImpactMs: allDiagnostics.reduce((sum, d) => sum + d.estimatedImpactMs, 0),\n heavyDependencies: results.find((r) => r.analyzer === 'heavy-dependencies')?.metadata?.heavyCount as number ?? 0,\n bundleSizeBytes: results.find((r) => r.analyzer === 'bundle-size')?.metadata?.totalSizeBytes as number ?? undefined,\n };\n\n return {\n targetPath,\n timestamp: new Date().toISOString(),\n totalDurationMs: performance.now() - start,\n results,\n summary,\n };\n}\n\nexport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic, DependencyInfo } from '../../types.js';\n\nfunction getPackageName(filePath: string): string {\n // filePath is relative to node_modules, e.g. \"@aws-sdk/client-s3/dist/index.js\"\n const parts = filePath.split('/');\n if (parts[0].startsWith('@')) {\n return `${parts[0]}/${parts[1]}`;\n }\n return parts[0];\n}\n\nexport const bundleSizeAnalyzer: Analyzer = {\n name: 'bundle-size',\n description: 'Analyzes total node_modules size and identifies the largest dependencies',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n const nodeModulesPath = path.join(targetPath, 'node_modules');\n\n try {\n await fs.access(nodeModulesPath);\n } catch {\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n\n try {\n const files = await fg('**/*', {\n cwd: nodeModulesPath,\n stats: true,\n onlyFiles: true,\n dot: true,\n });\n\n const packageSizes = new Map<string, number>();\n\n for (const entry of files) {\n const pkgName = getPackageName(entry.path);\n const size = entry.stats?.size ?? 0;\n packageSizes.set(pkgName, (packageSizes.get(pkgName) ?? 0) + size);\n }\n\n const totalSizeBytes = [...packageSizes.values()].reduce((a, b) => a + b, 0);\n const sorted = [...packageSizes.entries()]\n .sort((a, b) => b[1] - a[1]);\n const top10 = sorted.slice(0, 10);\n\n const topDependencies: DependencyInfo[] = top10.map(([name, sizeBytes]) => ({\n name,\n version: '',\n sizeBytes,\n isHeavy: false,\n }));\n\n // Total bundle size diagnostics\n const totalMB = totalSizeBytes / (1024 * 1024);\n if (totalMB > 50) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: 'Bundle size is critically large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. AWS Lambda has a 250MB unzipped limit and large bundles severely impact cold start times.`,\n recommendation: 'Use a bundler (esbuild/webpack) to tree-shake and bundle only what you need. Remove unused dependencies.',\n estimatedImpactMs: Math.min(totalMB * 10, 2000),\n });\n } else if (totalMB > 10) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: 'Bundle size is large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. This adds unnecessary cold start latency.`,\n recommendation: 'Consider using a bundler to reduce the deployment package size.',\n estimatedImpactMs: Math.min(totalMB * 5, 500),\n });\n }\n\n // Individual dependency size diagnostics\n for (const [name, sizeBytes] of sorted) {\n const depMB = sizeBytes / (1024 * 1024);\n if (depMB > 5) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: `Dependency \"${name}\" is very large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Look for a lighter alternative to \"${name}\" or ensure it's being tree-shaken.`,\n estimatedImpactMs: Math.min(depMB * 8, 500),\n });\n } else if (depMB > 1) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: `Dependency \"${name}\" is large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Consider replacing \"${name}\" with a lighter alternative.`,\n estimatedImpactMs: Math.min(depMB * 5, 200),\n });\n }\n }\n\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { totalSizeBytes, topDependencies },\n };\n } catch (error) {\n console.warn('bundle-size analyzer warning:', error);\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { findHeavyPackage, HEAVY_PACKAGES } from '../../known-heavy-packages.js';\n\nconst DEV_ONLY_PACKAGES = ['typescript', 'ts-node', 'ts-jest', 'jest', 'mocha', 'eslint', 'prettier', 'tsup', 'webpack', 'rollup', 'esbuild'];\n\nexport const heavyDependenciesAnalyzer: Analyzer = {\n name: 'heavy-dependencies',\n description: 'Detects known heavy dependencies and dev tools in production',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const deps = pkgJson.dependencies ?? {};\n const devDeps = pkgJson.devDependencies ?? {};\n let heavyCount = 0;\n\n // Check production dependencies against heavy packages list\n for (const depName of Object.keys(deps)) {\n const heavy = findHeavyPackage(depName);\n if (heavy) {\n heavyCount++;\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'warning',\n title: `Heavy dependency: ${depName}`,\n description: heavy.reason,\n recommendation: heavy.alternative,\n estimatedImpactMs: heavy.estimatedSavingsMs,\n filePath: 'package.json',\n });\n }\n }\n\n // Check if dev-only tools are in production dependencies\n for (const depName of Object.keys(deps)) {\n if (DEV_ONLY_PACKAGES.includes(depName)) {\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'critical',\n title: `Dev tool \"${depName}\" in production dependencies`,\n description: `\"${depName}\" is a development tool that should not be in \"dependencies\". It adds unnecessary size and cold start time.`,\n recommendation: `Move \"${depName}\" from \"dependencies\" to \"devDependencies\".`,\n estimatedImpactMs: findHeavyPackage(depName)?.estimatedSavingsMs ?? 100,\n filePath: 'package.json',\n });\n }\n }\n\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { heavyCount, totalDependencies: Object.keys(deps).length },\n };\n } catch (error) {\n console.warn('heavy-dependencies analyzer warning:', error);\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","// ============================================================\n// Database of known heavy npm packages and their alternatives\n// Used by heavy-dependencies and bundle-size analyzers\n// ============================================================\n\nexport interface HeavyPackage {\n /** Package name */\n name: string;\n /** Typical size on disk (bytes, approximate) */\n typicalSizeBytes: number;\n /** Why it's problematic for Lambda */\n reason: string;\n /** Suggested replacement */\n alternative: string;\n /** Estimated cold start savings if replaced (ms) */\n estimatedSavingsMs: number;\n}\n\n/**\n * Known heavy packages that hurt Lambda cold starts.\n * Sources:\n * - https://speedrun.nobackspacecrew.com/blog/2023/09/23/optimizing-lambda-coldstarts.html\n * - https://aws.amazon.com/blogs/compute/optimizing-node-js-dependencies-in-aws-lambda/\n * - Community benchmarks\n */\nexport const HEAVY_PACKAGES: HeavyPackage[] = [\n {\n name: 'aws-sdk',\n typicalSizeBytes: 65_000_000,\n reason: 'AWS SDK v2 is 65MB+ and loads all service clients. Lambda runtime includes it, but it\\'s slow.',\n alternative: 'Use @aws-sdk/client-* (v3) with selective imports. Only import clients you need.',\n estimatedSavingsMs: 400,\n },\n {\n name: 'moment',\n typicalSizeBytes: 4_800_000,\n reason: 'Moment.js is 4.8MB with locales. Not tree-shakeable.',\n alternative: 'Use dayjs (2KB) or date-fns with tree-shaking.',\n estimatedSavingsMs: 50,\n },\n {\n name: 'moment-timezone',\n typicalSizeBytes: 8_200_000,\n reason: 'Moment-timezone adds 8MB+ of timezone data on top of Moment.',\n alternative: 'Use dayjs/plugin/timezone or Intl.DateTimeFormat (built-in).',\n estimatedSavingsMs: 80,\n },\n {\n name: 'lodash',\n typicalSizeBytes: 1_400_000,\n reason: 'Full lodash is 1.4MB. Not tree-shakeable with CommonJS.',\n alternative: 'Use lodash-es (tree-shakeable) or individual packages like lodash.get.',\n estimatedSavingsMs: 30,\n },\n {\n name: 'axios',\n typicalSizeBytes: 450_000,\n reason: 'Axios is 450KB. Overkill for Lambda where you can use native fetch (Node 18+).',\n alternative: 'Use native fetch (Node 18+) or undici.',\n estimatedSavingsMs: 15,\n },\n {\n name: 'express',\n typicalSizeBytes: 550_000,\n reason: 'Express has 30+ dependencies. Heavy for a single Lambda function.',\n alternative: 'Use lambda-api (zero deps) or direct API Gateway event parsing.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'bluebird',\n typicalSizeBytes: 350_000,\n reason: 'Bluebird is unnecessary in Node 18+ which has native Promise with good performance.',\n alternative: 'Use native Promise (built-in).',\n estimatedSavingsMs: 10,\n },\n {\n name: 'uuid',\n typicalSizeBytes: 150_000,\n reason: 'UUID package is 150KB. Node 18+ has crypto.randomUUID() built-in.',\n alternative: 'Use crypto.randomUUID() (built-in Node 18+).',\n estimatedSavingsMs: 5,\n },\n {\n name: 'winston',\n typicalSizeBytes: 2_500_000,\n reason: 'Winston is 2.5MB with many transports. Too heavy for Lambda.',\n alternative: 'Use @aws-lambda-powertools/logger or pino.',\n estimatedSavingsMs: 40,\n },\n {\n name: 'joi',\n typicalSizeBytes: 950_000,\n reason: 'Joi is ~1MB. Heavy for Lambda validation.',\n alternative: 'Use zod (lighter, TypeScript-native) or ajv.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'mongoose',\n typicalSizeBytes: 3_800_000,\n reason: 'Mongoose is 3.8MB. Extremely heavy for Lambda.',\n alternative: 'Use native MongoDB driver or Dynamoose for DynamoDB.',\n estimatedSavingsMs: 100,\n },\n {\n name: 'typescript',\n typicalSizeBytes: 65_000_000,\n reason: 'TypeScript compiler in production bundle is 65MB. Should only be a devDependency.',\n alternative: 'Move to devDependencies. Deploy compiled JavaScript only.',\n estimatedSavingsMs: 500,\n },\n {\n name: 'ts-node',\n typicalSizeBytes: 3_500_000,\n reason: 'ts-node adds 200-500ms cold start. Should not be in production.',\n alternative: 'Transpile to JavaScript before deployment.',\n estimatedSavingsMs: 350,\n },\n {\n name: '@nestjs/core',\n typicalSizeBytes: 5_200_000,\n reason: 'NestJS is a heavy framework (5MB+). Decorator metadata and DI container add cold start overhead.',\n alternative: 'Use lighter patterns for Lambda: plain handlers or lambda-api.',\n estimatedSavingsMs: 150,\n },\n {\n name: 'puppeteer',\n typicalSizeBytes: 300_000_000,\n reason: 'Puppeteer bundles Chromium (300MB+). Exceeds Lambda package limits.',\n alternative: 'Use @sparticuz/chromium with puppeteer-core for Lambda.',\n estimatedSavingsMs: 2000,\n },\n];\n\n/**\n * Lookup a package by name.\n */\nexport function findHeavyPackage(name: string): HeavyPackage | undefined {\n return HEAVY_PACKAGES.find((pkg) => pkg.name === name);\n}\n\n/**\n * Check if a package is known to be heavy.\n */\nexport function isHeavyPackage(name: string): boolean {\n return HEAVY_PACKAGES.some((pkg) => pkg.name === name);\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { isHeavyPackage, findHeavyPackage } from '../../known-heavy-packages.js';\n\nconst ESM_IMPORT = /^import\\s+.*\\s+from\\s+['\"](.+)['\"]/gm;\nconst CJS_REQUIRE = /^(?:const|let|var)\\s+.*=\\s*require\\(['\"](.+)['\"]\\)/gm;\nconst WILDCARD_IMPORT = /^import\\s+\\*\\s+as\\s+\\w+\\s+from\\s+['\"](.+)['\"]/gm;\n\nfunction getPackageName(specifier: string): string | null {\n if (specifier.startsWith('.') || specifier.startsWith('/')) return null;\n const parts = specifier.split('/');\n if (parts[0].startsWith('@')) {\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;\n }\n return parts[0];\n}\n\nfunction isTopLevel(line: string): boolean {\n const indent = line.length - line.trimStart().length;\n return indent <= 1;\n}\n\nexport const importAnalysisAnalyzer: Analyzer = {\n name: 'import-analysis',\n description: 'Analyzes import patterns for tree-shaking issues and heavy top-level imports',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const files = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: ['node_modules/**', 'dist/**', '**/*.d.ts'],\n absolute: false,\n });\n\n for (const file of files) {\n const filePath = path.join(targetPath, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check wildcard imports (tree-shaking issue)\n let match: RegExpExecArray | null;\n WILDCARD_IMPORT.lastIndex = 0;\n while ((match = WILDCARD_IMPORT.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg) {\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Wildcard import of \"${pkg}\" prevents tree-shaking`,\n description: `\"import * as ...\" from \"${match[1]}\" imports the entire module, preventing bundlers from removing unused code.`,\n recommendation: `Use named imports: import { specificFunction } from \"${match[1]}\"`,\n estimatedImpactMs: 20,\n filePath: file,\n line: i + 1,\n });\n }\n }\n\n // Check top-level heavy imports\n if (isTopLevel(line)) {\n for (const regex of [ESM_IMPORT, CJS_REQUIRE]) {\n regex.lastIndex = 0;\n while ((match = regex.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg && isHeavyPackage(pkg)) {\n const heavy = findHeavyPackage(pkg)!;\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Top-level import of heavy package \"${pkg}\"`,\n description: `\"${pkg}\" is imported at the top level in ${file}. This forces it to load during cold start even if not needed for every invocation.`,\n recommendation: `Consider lazy-loading: move the import inside the function that uses it. ${heavy.alternative}`,\n estimatedImpactMs: heavy.estimatedSavingsMs / 2,\n filePath: file,\n line: i + 1,\n });\n }\n }\n }\n }\n }\n }\n\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { filesScanned: files.length },\n };\n } catch (error) {\n console.warn('import-analysis analyzer warning:', error);\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nexport const awsSdkAnalyzer: Analyzer = {\n name: 'aws-sdk',\n description: 'Checks AWS SDK version usage and migration status',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...(pkgJson.dependencies ?? {}), ...(pkgJson.devDependencies ?? {}) };\n\n const hasV2 = 'aws-sdk' in allDeps;\n const v3Clients = Object.keys(allDeps).filter((d) => d.startsWith('@aws-sdk/client-'));\n const hasV3 = v3Clients.length > 0;\n\n if (hasV2 && !hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'critical',\n title: 'Using AWS SDK v2 (aws-sdk)',\n description: 'AWS SDK v2 is 65MB+ and loads all service clients. It adds 400ms+ to cold starts.',\n recommendation: 'Migrate to AWS SDK v3 (@aws-sdk/client-*). Only import the clients you need.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (hasV2 && hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Incomplete AWS SDK v2 to v3 migration',\n description: 'Both aws-sdk (v2) and @aws-sdk/client-* (v3) are present. This means v2 is still bundled alongside v3.',\n recommendation: 'Complete the migration to SDK v3 and remove the \"aws-sdk\" dependency.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (v3Clients.length > 5) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'info',\n title: `${v3Clients.length} AWS SDK v3 clients detected`,\n description: `This Lambda uses ${v3Clients.length} AWS SDK clients: ${v3Clients.join(', ')}. Each client adds to bundle size.`,\n recommendation: 'Verify all clients are necessary. Consider splitting into multiple Lambdas if responsibilities are too broad.',\n estimatedImpactMs: v3Clients.length * 5,\n });\n }\n\n // Check source files for unnecessary SSO client\n const sourceFiles = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: ['node_modules/**', 'dist/**', '**/*.d.ts'],\n absolute: false,\n });\n\n for (const file of sourceFiles) {\n const content = await fs.readFile(path.join(targetPath, file), 'utf-8');\n if (content.includes('@aws-sdk/client-sso')) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Unnecessary SSO client in Lambda',\n description: '@aws-sdk/client-sso is imported but Lambda functions use IAM roles, not SSO authentication.',\n recommendation: 'Remove the @aws-sdk/client-sso import. Lambda uses IAM execution roles for authentication.',\n estimatedImpactMs: 15,\n filePath: file,\n });\n break;\n }\n }\n\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { hasV2, hasV3, v3ClientCount: v3Clients.length },\n };\n } catch (error) {\n console.warn('aws-sdk analyzer warning:', error);\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nconst BUNDLER_PACKAGES = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel'];\nconst BUNDLER_CONFIGS = [\n 'webpack.config.*',\n 'rollup.config.*',\n 'tsup.config.*',\n 'esbuild.config.*',\n '.parcelrc',\n];\nconst BUNDLER_KEYWORDS = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel', 'bundle'];\n\nexport const bundlerDetectionAnalyzer: Analyzer = {\n name: 'bundler-detection',\n description: 'Detects whether a bundler is configured and checks ESM/bundler setup',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const devDeps = pkgJson.devDependencies ?? {};\n const deps = pkgJson.dependencies ?? {};\n const allDeps = { ...deps, ...devDeps };\n const scripts = pkgJson.scripts ?? {};\n\n // Check for bundler packages\n const detectedBundlers: string[] = [];\n for (const bundler of BUNDLER_PACKAGES) {\n if (bundler in allDeps) {\n detectedBundlers.push(bundler);\n }\n }\n\n // Check for config files\n const configFiles = await fg(BUNDLER_CONFIGS, {\n cwd: targetPath,\n dot: true,\n });\n\n // Check scripts for bundler keywords\n const bundlerScripts: string[] = [];\n for (const [name, script] of Object.entries(scripts)) {\n if (typeof script === 'string' && BUNDLER_KEYWORDS.some((kw) => script.includes(kw))) {\n bundlerScripts.push(name);\n }\n }\n\n // Check serverless.yml for bundler plugins\n let serverlessPlugin: string | null = null;\n try {\n const slsPath = path.join(targetPath, 'serverless.yml');\n const slsContent = await fs.readFile(slsPath, 'utf-8');\n if (slsContent.includes('serverless-esbuild')) serverlessPlugin = 'serverless-esbuild';\n else if (slsContent.includes('serverless-webpack')) serverlessPlugin = 'serverless-webpack';\n } catch {\n // serverless.yml not found, that's fine\n }\n\n // Check ESM\n const isESM = pkgJson.type === 'module';\n\n const hasBundler = detectedBundlers.length > 0 || configFiles.length > 0 || serverlessPlugin !== null;\n\n if (!hasBundler) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'critical',\n title: 'No bundler detected',\n description: 'No bundler (esbuild, webpack, rollup, etc.) was found in this project. Without a bundler, the entire node_modules directory is deployed, causing large bundle sizes and slow cold starts.',\n recommendation: 'Add esbuild (fastest) or webpack to bundle your Lambda function. This is typically the single biggest cold start improvement you can make.',\n estimatedImpactMs: 500,\n });\n } else {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: `Bundler detected: ${detectedBundlers.join(', ') || serverlessPlugin || 'config found'}`,\n description: `Found bundler setup: packages=[${detectedBundlers.join(', ')}], configs=[${configFiles.join(', ')}]${serverlessPlugin ? `, serverless plugin=${serverlessPlugin}` : ''}.`,\n recommendation: 'Ensure your bundler is configured for tree-shaking and minification.',\n estimatedImpactMs: 0,\n });\n }\n\n if (!isESM) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: 'Project is not using ESM',\n description: '\"type\": \"module\" is not set in package.json. ESM enables better tree-shaking with bundlers.',\n recommendation: 'Consider setting \"type\": \"module\" in package.json for better tree-shaking support.',\n estimatedImpactMs: 20,\n });\n }\n\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: {\n detectedBundlers,\n configFiles,\n bundlerScripts,\n serverlessPlugin,\n isESM,\n hasBundler,\n },\n };\n } catch (error) {\n console.warn('bundler-detection analyzer warning:', error);\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import chalk from 'chalk';\nimport type { DiagnosisReport, Diagnostic, DependencyInfo } from '../../types.js';\n\nconst SEVERITY_ICON: Record<string, string> = {\n critical: '🔴',\n warning: '⚠️',\n info: '💡',\n};\n\nconst SEVERITY_COLOR: Record<string, (s: string) => string> = {\n critical: chalk.red,\n warning: chalk.yellow,\n info: chalk.blue,\n};\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${bytes}B`;\n}\n\nexport function printReport(report: DiagnosisReport): void {\n console.log();\n console.log(chalk.bold.cyan('🩺 Lambda Doctor — Diagnosis Report'));\n console.log(chalk.gray(` Target: ${report.targetPath}`));\n console.log(chalk.gray(` Date: ${report.timestamp}`));\n console.log();\n\n // Bundle size breakdown\n const bundleSizeResult = report.results.find((r) => r.analyzer === 'bundle-size');\n if (bundleSizeResult?.metadata) {\n const { totalSizeBytes, topDependencies } = bundleSizeResult.metadata as {\n totalSizeBytes: number;\n topDependencies: DependencyInfo[];\n };\n if (totalSizeBytes > 0) {\n console.log(chalk.bold('📦 Bundle Size Breakdown'));\n console.log(chalk.gray(` Total: ${formatBytes(totalSizeBytes)}`));\n console.log();\n if (topDependencies && topDependencies.length > 0) {\n console.log(chalk.gray(' Top Dependencies:'));\n for (const dep of topDependencies) {\n const bar = '█'.repeat(Math.max(1, Math.round((dep.sizeBytes / totalSizeBytes) * 30)));\n console.log(` ${chalk.white(dep.name.padEnd(35))} ${formatBytes(dep.sizeBytes).padStart(10)} ${chalk.green(bar)}`);\n }\n console.log();\n }\n }\n }\n\n // Diagnostics sorted by severity\n const allDiagnostics = report.results.flatMap((r) => r.diagnostics);\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n const sorted = [...allDiagnostics].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity],\n );\n\n if (sorted.length === 0) {\n console.log(chalk.green.bold('✅ No issues found! Your Lambda looks healthy.'));\n console.log();\n return;\n }\n\n console.log(chalk.bold('🔍 Diagnostics'));\n console.log();\n\n for (const diag of sorted) {\n const icon = SEVERITY_ICON[diag.severity];\n const colorFn = SEVERITY_COLOR[diag.severity];\n const location = diag.filePath ? chalk.gray(` (${diag.filePath}${diag.line ? `:${diag.line}` : ''})`) : '';\n\n console.log(`${icon} ${colorFn(diag.severity.toUpperCase())} ${chalk.bold(diag.title)}${location}`);\n console.log(chalk.gray(` ${diag.description}`));\n console.log(chalk.green(` → ${diag.recommendation}`));\n if (diag.estimatedImpactMs > 0) {\n console.log(chalk.cyan(` ⏱ Est. improvement: ~${diag.estimatedImpactMs}ms`));\n }\n console.log();\n }\n\n // Footer summary\n const { summary } = report;\n console.log(chalk.bold('─'.repeat(60)));\n console.log(\n chalk.bold('Summary: ') +\n chalk.red(`${summary.critical} critical`) +\n chalk.gray(' | ') +\n chalk.yellow(`${summary.warnings} warnings`) +\n chalk.gray(' | ') +\n chalk.blue(`${summary.info} info`),\n );\n if (summary.estimatedTotalImpactMs > 0) {\n console.log(\n chalk.bold.green(`\\n🚀 Total estimated cold start improvement: ~${summary.estimatedTotalImpactMs}ms`),\n );\n }\n console.log();\n}\n"],"mappings":"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","names":["fs","path","path","fs","path","path","fs","fg","fs","path","getPackageName","fg","path","fs","fs","fg","path","fs","fg","path","path","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/bin/cli.ts","../src/index.ts","../types.ts","../src/analyzers/bundle-size.ts","../src/analyzers/heavy-dependencies.ts","../known-heavy-packages.ts","../src/analyzers/import-analysis.ts","../src/analyzers/aws-sdk.ts","../src/analyzers/bundler-detection.ts","../src/reporters/console.ts"],"sourcesContent":["import { Command } from 'commander';\nimport ora from 'ora';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { analyze, printReport } from '../index.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst pkg = JSON.parse(await fs.readFile(path.join(__dirname, '..', 'package.json'), 'utf-8'));\n\nconst program = new Command();\n\nprogram\n .name('lambda-doctor')\n .description('Diagnose and fix AWS Lambda cold start performance issues')\n .version(pkg.version);\n\nprogram\n .command('analyze')\n .description('Analyze a Lambda project directory')\n .argument('<path>', 'Path to the Lambda project directory')\n .option('--format <format>', 'Output format: console or json', 'console')\n .option('--verbose', 'Show verbose output', false)\n .option('--exclude <patterns>', 'Comma-separated glob patterns to exclude (default: tests, dist, build, cypress, coverage)')\n .option('--no-default-excludes', 'Disable default exclude patterns (tests, cypress, etc.)')\n .action(async (targetPath: string, options: { format: string; verbose: boolean; exclude?: string; defaultExcludes: boolean }) => {\n const resolvedPath = path.resolve(targetPath);\n\n // Validate path exists\n try {\n await fs.access(resolvedPath);\n } catch {\n console.error(`Error: Path does not exist: ${resolvedPath}`);\n process.exit(1);\n }\n\n // Validate package.json exists\n try {\n await fs.access(path.join(resolvedPath, 'package.json'));\n } catch {\n console.error(`Error: No package.json found in ${resolvedPath}`);\n process.exit(1);\n }\n\n // Build exclude patterns\n let excludePatterns: string[] | undefined;\n if (!options.defaultExcludes) {\n // Only basic excludes when --no-default-excludes is used\n excludePatterns = ['node_modules/**', 'dist/**', '**/*.d.ts'];\n }\n if (options.exclude) {\n const userPatterns = options.exclude.split(',').map((p) => p.trim());\n excludePatterns = [...(excludePatterns ?? []), ...userPatterns];\n }\n\n const spinner = ora('Analyzing Lambda project...').start();\n\n try {\n const report = await analyze({\n targetPath: resolvedPath,\n format: options.format as 'console' | 'json',\n verbose: options.verbose,\n exclude: excludePatterns,\n });\n\n spinner.stop();\n\n if (options.format === 'json') {\n console.log(JSON.stringify(report, null, 2));\n } else {\n printReport(report);\n }\n\n if (report.summary.critical > 0) {\n process.exit(1);\n }\n } catch (error) {\n spinner.fail('Analysis failed');\n console.error(error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n","import path from 'path';\nimport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../types.js';\nimport { bundleSizeAnalyzer } from './analyzers/bundle-size.js';\nimport { heavyDependenciesAnalyzer } from './analyzers/heavy-dependencies.js';\nimport { importAnalysisAnalyzer } from './analyzers/import-analysis.js';\nimport { awsSdkAnalyzer } from './analyzers/aws-sdk.js';\nimport { bundlerDetectionAnalyzer } from './analyzers/bundler-detection.js';\n\nexport { printReport } from './reporters/console.js';\n\nconst ALL_ANALYZERS: Analyzer[] = [\n bundleSizeAnalyzer,\n heavyDependenciesAnalyzer,\n importAnalysisAnalyzer,\n awsSdkAnalyzer,\n bundlerDetectionAnalyzer,\n];\n\nexport async function analyze(config: AnalyzeConfig): Promise<DiagnosisReport> {\n const targetPath = path.resolve(config.targetPath);\n const start = performance.now();\n\n const excludePatterns = config.exclude ?? DEFAULT_EXCLUDE_PATTERNS;\n\n const analyzersToRun = config.analyzers\n ? ALL_ANALYZERS.filter((a) => config.analyzers!.includes(a.name))\n : ALL_ANALYZERS;\n\n const results = await Promise.all(\n analyzersToRun.map((a) => a.analyze(targetPath, excludePatterns)),\n );\n\n const allDiagnostics = results.flatMap((r) => r.diagnostics);\n const summary: ReportSummary = {\n totalIssues: allDiagnostics.length,\n critical: allDiagnostics.filter((d) => d.severity === 'critical').length,\n warnings: allDiagnostics.filter((d) => d.severity === 'warning').length,\n info: allDiagnostics.filter((d) => d.severity === 'info').length,\n estimatedTotalImpactMs: allDiagnostics.reduce((sum, d) => sum + d.estimatedImpactMs, 0),\n heavyDependencies: results.find((r) => r.analyzer === 'heavy-dependencies')?.metadata?.heavyCount as number ?? 0,\n bundleSizeBytes: results.find((r) => r.analyzer === 'bundle-size')?.metadata?.totalSizeBytes as number ?? undefined,\n };\n\n return {\n targetPath,\n timestamp: new Date().toISOString(),\n totalDurationMs: performance.now() - start,\n results,\n summary,\n };\n}\n\nexport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nexport { DEFAULT_EXCLUDE_PATTERNS } from '../types.js';\n","// ============================================================\n// lambda-doctor core types\n// ============================================================\n\n/** Severity of a diagnostic finding */\nexport type Severity = 'critical' | 'warning' | 'info';\n\n/** Category of analysis */\nexport type AnalyzerName =\n | 'bundle-size'\n | 'heavy-dependencies'\n | 'import-analysis'\n | 'aws-sdk'\n | 'bundler-detection';\n\n/** A single diagnostic finding */\nexport interface Diagnostic {\n /** Which analyzer produced this */\n analyzer: AnalyzerName;\n /** Severity level */\n severity: Severity;\n /** Short human-readable title */\n title: string;\n /** Detailed description of the issue */\n description: string;\n /** Actionable fix recommendation */\n recommendation: string;\n /** Estimated cold start improvement in ms (0 if unknown) */\n estimatedImpactMs: number;\n /** File path related to this finding (optional) */\n filePath?: string;\n /** Line number (optional) */\n line?: number;\n}\n\n/** Summary of a dependency */\nexport interface DependencyInfo {\n /** Package name */\n name: string;\n /** Version string */\n version: string;\n /** Size on disk in bytes */\n sizeBytes: number;\n /** Whether it's a known heavy package */\n isHeavy: boolean;\n /** Suggested lighter alternative (if any) */\n alternative?: string;\n}\n\n/** Result from a single analyzer */\nexport interface AnalyzerResult {\n /** Analyzer name */\n analyzer: AnalyzerName;\n /** Time taken to run in ms */\n durationMs: number;\n /** Findings */\n diagnostics: Diagnostic[];\n /** Analyzer-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/** Full diagnosis report */\nexport interface DiagnosisReport {\n /** Path that was analyzed */\n targetPath: string;\n /** Timestamp */\n timestamp: string;\n /** Total analysis duration in ms */\n totalDurationMs: number;\n /** Results from each analyzer */\n results: AnalyzerResult[];\n /** Aggregated summary */\n summary: ReportSummary;\n}\n\n/** Aggregated summary across all analyzers */\nexport interface ReportSummary {\n /** Total number of diagnostics */\n totalIssues: number;\n /** Count by severity */\n critical: number;\n warnings: number;\n info: number;\n /** Total estimated cold start improvement in ms */\n estimatedTotalImpactMs: number;\n /** Total bundle size in bytes (if detected) */\n bundleSizeBytes?: number;\n /** Number of heavy dependencies found */\n heavyDependencies: number;\n}\n\n/** Configuration for the analyze command */\nexport interface AnalyzeConfig {\n /** Path to the Lambda project directory */\n targetPath: string;\n /** Which analyzers to run (default: all) */\n analyzers?: AnalyzerName[];\n /** Output format */\n format?: 'console' | 'json';\n /** Whether to show verbose output */\n verbose?: boolean;\n /** Glob patterns to exclude from file scanning */\n exclude?: string[];\n}\n\n/** Default glob patterns excluded from scanning */\nexport const DEFAULT_EXCLUDE_PATTERNS: string[] = [\n 'node_modules/**',\n 'dist/**',\n 'build/**',\n 'coverage/**',\n '**/*.d.ts',\n '**/__tests__/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/test/**',\n '**/tests/**',\n '**/cypress/**',\n '**/.serverless/**',\n '**/cdk.out/**',\n];\n\n/** Interface that all analyzers must implement */\nexport interface Analyzer {\n /** Unique name */\n name: AnalyzerName;\n /** Human-readable description */\n description: string;\n /** Run the analysis */\n analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult>;\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic, DependencyInfo } from '../../types.js';\n\nfunction getPackageName(filePath: string): string {\n // filePath is relative to node_modules, e.g. \"@aws-sdk/client-s3/dist/index.js\"\n const parts = filePath.split('/');\n if (parts[0].startsWith('@')) {\n return `${parts[0]}/${parts[1]}`;\n }\n return parts[0];\n}\n\nexport const bundleSizeAnalyzer: Analyzer = {\n name: 'bundle-size',\n description: 'Analyzes total node_modules size and identifies the largest dependencies',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n const nodeModulesPath = path.join(targetPath, 'node_modules');\n\n try {\n await fs.access(nodeModulesPath);\n } catch {\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n\n try {\n const files = await fg('**/*', {\n cwd: nodeModulesPath,\n stats: true,\n onlyFiles: true,\n dot: true,\n });\n\n const packageSizes = new Map<string, number>();\n\n for (const entry of files) {\n const pkgName = getPackageName(entry.path);\n const size = entry.stats?.size ?? 0;\n packageSizes.set(pkgName, (packageSizes.get(pkgName) ?? 0) + size);\n }\n\n const totalSizeBytes = [...packageSizes.values()].reduce((a, b) => a + b, 0);\n const sorted = [...packageSizes.entries()]\n .sort((a, b) => b[1] - a[1]);\n const top10 = sorted.slice(0, 10);\n\n const topDependencies: DependencyInfo[] = top10.map(([name, sizeBytes]) => ({\n name,\n version: '',\n sizeBytes,\n isHeavy: false,\n }));\n\n // Total bundle size diagnostics\n const totalMB = totalSizeBytes / (1024 * 1024);\n if (totalMB > 50) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: 'Bundle size is critically large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. AWS Lambda has a 250MB unzipped limit and large bundles severely impact cold start times.`,\n recommendation: 'Use a bundler (esbuild/webpack) to tree-shake and bundle only what you need. Remove unused dependencies.',\n estimatedImpactMs: Math.min(totalMB * 10, 2000),\n });\n } else if (totalMB > 10) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: 'Bundle size is large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. This adds unnecessary cold start latency.`,\n recommendation: 'Consider using a bundler to reduce the deployment package size.',\n estimatedImpactMs: Math.min(totalMB * 5, 500),\n });\n }\n\n // Individual dependency size diagnostics\n for (const [name, sizeBytes] of sorted) {\n const depMB = sizeBytes / (1024 * 1024);\n if (depMB > 5) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: `Dependency \"${name}\" is very large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Look for a lighter alternative to \"${name}\" or ensure it's being tree-shaken.`,\n estimatedImpactMs: Math.min(depMB * 8, 500),\n });\n } else if (depMB > 1) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: `Dependency \"${name}\" is large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Consider replacing \"${name}\" with a lighter alternative.`,\n estimatedImpactMs: Math.min(depMB * 5, 200),\n });\n }\n }\n\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { totalSizeBytes, topDependencies },\n };\n } catch (error) {\n console.warn('bundle-size analyzer warning:', error);\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { findHeavyPackage, HEAVY_PACKAGES } from '../../known-heavy-packages.js';\n\nconst DEV_ONLY_PACKAGES = ['typescript', 'ts-node', 'ts-jest', 'jest', 'mocha', 'eslint', 'prettier', 'tsup', 'webpack', 'rollup', 'esbuild'];\n\nexport const heavyDependenciesAnalyzer: Analyzer = {\n name: 'heavy-dependencies',\n description: 'Detects known heavy dependencies and dev tools in production',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const deps = pkgJson.dependencies ?? {};\n const devDeps = pkgJson.devDependencies ?? {};\n let heavyCount = 0;\n\n // Check production dependencies against heavy packages list\n for (const depName of Object.keys(deps)) {\n const heavy = findHeavyPackage(depName);\n if (heavy) {\n heavyCount++;\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'warning',\n title: `Heavy dependency: ${depName}`,\n description: heavy.reason,\n recommendation: heavy.alternative,\n estimatedImpactMs: heavy.estimatedSavingsMs,\n filePath: 'package.json',\n });\n }\n }\n\n // Check if dev-only tools are in production dependencies\n for (const depName of Object.keys(deps)) {\n if (DEV_ONLY_PACKAGES.includes(depName)) {\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'critical',\n title: `Dev tool \"${depName}\" in production dependencies`,\n description: `\"${depName}\" is a development tool that should not be in \"dependencies\". It adds unnecessary size and cold start time.`,\n recommendation: `Move \"${depName}\" from \"dependencies\" to \"devDependencies\".`,\n estimatedImpactMs: findHeavyPackage(depName)?.estimatedSavingsMs ?? 100,\n filePath: 'package.json',\n });\n }\n }\n\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { heavyCount, totalDependencies: Object.keys(deps).length },\n };\n } catch (error) {\n console.warn('heavy-dependencies analyzer warning:', error);\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","// ============================================================\n// Database of known heavy npm packages and their alternatives\n// Used by heavy-dependencies and bundle-size analyzers\n// ============================================================\n\nexport interface HeavyPackage {\n /** Package name */\n name: string;\n /** Typical size on disk (bytes, approximate) */\n typicalSizeBytes: number;\n /** Why it's problematic for Lambda */\n reason: string;\n /** Suggested replacement */\n alternative: string;\n /** Estimated cold start savings if replaced (ms) */\n estimatedSavingsMs: number;\n}\n\n/**\n * Known heavy packages that hurt Lambda cold starts.\n * Sources:\n * - https://speedrun.nobackspacecrew.com/blog/2023/09/23/optimizing-lambda-coldstarts.html\n * - https://aws.amazon.com/blogs/compute/optimizing-node-js-dependencies-in-aws-lambda/\n * - Community benchmarks\n */\nexport const HEAVY_PACKAGES: HeavyPackage[] = [\n {\n name: 'aws-sdk',\n typicalSizeBytes: 65_000_000,\n reason: 'AWS SDK v2 is 65MB+ and loads all service clients. Lambda runtime includes it, but it\\'s slow.',\n alternative: 'Use @aws-sdk/client-* (v3) with selective imports. Only import clients you need.',\n estimatedSavingsMs: 400,\n },\n {\n name: 'moment',\n typicalSizeBytes: 4_800_000,\n reason: 'Moment.js is 4.8MB with locales. Not tree-shakeable.',\n alternative: 'Use dayjs (2KB) or date-fns with tree-shaking.',\n estimatedSavingsMs: 50,\n },\n {\n name: 'moment-timezone',\n typicalSizeBytes: 8_200_000,\n reason: 'Moment-timezone adds 8MB+ of timezone data on top of Moment.',\n alternative: 'Use dayjs/plugin/timezone or Intl.DateTimeFormat (built-in).',\n estimatedSavingsMs: 80,\n },\n {\n name: 'lodash',\n typicalSizeBytes: 1_400_000,\n reason: 'Full lodash is 1.4MB. Not tree-shakeable with CommonJS.',\n alternative: 'Use lodash-es (tree-shakeable) or individual packages like lodash.get.',\n estimatedSavingsMs: 30,\n },\n {\n name: 'axios',\n typicalSizeBytes: 450_000,\n reason: 'Axios is 450KB. Overkill for Lambda where you can use native fetch (Node 18+).',\n alternative: 'Use native fetch (Node 18+) or undici.',\n estimatedSavingsMs: 15,\n },\n {\n name: 'express',\n typicalSizeBytes: 550_000,\n reason: 'Express has 30+ dependencies. Heavy for a single Lambda function.',\n alternative: 'Use lambda-api (zero deps) or direct API Gateway event parsing.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'bluebird',\n typicalSizeBytes: 350_000,\n reason: 'Bluebird is unnecessary in Node 18+ which has native Promise with good performance.',\n alternative: 'Use native Promise (built-in).',\n estimatedSavingsMs: 10,\n },\n {\n name: 'uuid',\n typicalSizeBytes: 150_000,\n reason: 'UUID package is 150KB. Node 18+ has crypto.randomUUID() built-in.',\n alternative: 'Use crypto.randomUUID() (built-in Node 18+).',\n estimatedSavingsMs: 5,\n },\n {\n name: 'winston',\n typicalSizeBytes: 2_500_000,\n reason: 'Winston is 2.5MB with many transports. Too heavy for Lambda.',\n alternative: 'Use @aws-lambda-powertools/logger or pino.',\n estimatedSavingsMs: 40,\n },\n {\n name: 'joi',\n typicalSizeBytes: 950_000,\n reason: 'Joi is ~1MB. Heavy for Lambda validation.',\n alternative: 'Use zod (lighter, TypeScript-native) or ajv.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'mongoose',\n typicalSizeBytes: 3_800_000,\n reason: 'Mongoose is 3.8MB. Extremely heavy for Lambda.',\n alternative: 'Use native MongoDB driver or Dynamoose for DynamoDB.',\n estimatedSavingsMs: 100,\n },\n {\n name: 'typescript',\n typicalSizeBytes: 65_000_000,\n reason: 'TypeScript compiler in production bundle is 65MB. Should only be a devDependency.',\n alternative: 'Move to devDependencies. Deploy compiled JavaScript only.',\n estimatedSavingsMs: 500,\n },\n {\n name: 'ts-node',\n typicalSizeBytes: 3_500_000,\n reason: 'ts-node adds 200-500ms cold start. Should not be in production.',\n alternative: 'Transpile to JavaScript before deployment.',\n estimatedSavingsMs: 350,\n },\n {\n name: '@nestjs/core',\n typicalSizeBytes: 5_200_000,\n reason: 'NestJS is a heavy framework (5MB+). Decorator metadata and DI container add cold start overhead.',\n alternative: 'Use lighter patterns for Lambda: plain handlers or lambda-api.',\n estimatedSavingsMs: 150,\n },\n {\n name: 'puppeteer',\n typicalSizeBytes: 300_000_000,\n reason: 'Puppeteer bundles Chromium (300MB+). Exceeds Lambda package limits.',\n alternative: 'Use @sparticuz/chromium with puppeteer-core for Lambda.',\n estimatedSavingsMs: 2000,\n },\n];\n\n/**\n * Lookup a package by name.\n */\nexport function findHeavyPackage(name: string): HeavyPackage | undefined {\n return HEAVY_PACKAGES.find((pkg) => pkg.name === name);\n}\n\n/**\n * Check if a package is known to be heavy.\n */\nexport function isHeavyPackage(name: string): boolean {\n return HEAVY_PACKAGES.some((pkg) => pkg.name === name);\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../../types.js';\nimport { isHeavyPackage, findHeavyPackage } from '../../known-heavy-packages.js';\n\nconst ESM_IMPORT = /^import\\s+.*\\s+from\\s+['\"](.+)['\"]/gm;\nconst CJS_REQUIRE = /^(?:const|let|var)\\s+.*=\\s*require\\(['\"](.+)['\"]\\)/gm;\nconst WILDCARD_IMPORT = /^import\\s+\\*\\s+as\\s+\\w+\\s+from\\s+['\"](.+)['\"]/gm;\n\nfunction getPackageName(specifier: string): string | null {\n if (specifier.startsWith('.') || specifier.startsWith('/')) return null;\n const parts = specifier.split('/');\n if (parts[0].startsWith('@')) {\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;\n }\n return parts[0];\n}\n\nfunction isTopLevel(line: string): boolean {\n const indent = line.length - line.trimStart().length;\n return indent <= 1;\n}\n\nexport const importAnalysisAnalyzer: Analyzer = {\n name: 'import-analysis',\n description: 'Analyzes import patterns for tree-shaking issues and heavy top-level imports',\n\n async analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const files = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,\n absolute: false,\n });\n\n for (const file of files) {\n const filePath = path.join(targetPath, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check wildcard imports (tree-shaking issue)\n let match: RegExpExecArray | null;\n WILDCARD_IMPORT.lastIndex = 0;\n while ((match = WILDCARD_IMPORT.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg) {\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Wildcard import of \"${pkg}\" prevents tree-shaking`,\n description: `\"import * as ...\" from \"${match[1]}\" imports the entire module, preventing bundlers from removing unused code.`,\n recommendation: `Use named imports: import { specificFunction } from \"${match[1]}\"`,\n estimatedImpactMs: 20,\n filePath: file,\n line: i + 1,\n });\n }\n }\n\n // Check top-level heavy imports\n if (isTopLevel(line)) {\n for (const regex of [ESM_IMPORT, CJS_REQUIRE]) {\n regex.lastIndex = 0;\n while ((match = regex.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg && isHeavyPackage(pkg)) {\n const heavy = findHeavyPackage(pkg)!;\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Top-level import of heavy package \"${pkg}\"`,\n description: `\"${pkg}\" is imported at the top level in ${file}. This forces it to load during cold start even if not needed for every invocation.`,\n recommendation: `Consider lazy-loading: move the import inside the function that uses it. ${heavy.alternative}`,\n estimatedImpactMs: heavy.estimatedSavingsMs / 2,\n filePath: file,\n line: i + 1,\n });\n }\n }\n }\n }\n }\n }\n\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { filesScanned: files.length },\n };\n } catch (error) {\n console.warn('import-analysis analyzer warning:', error);\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../../types.js';\n\nexport const awsSdkAnalyzer: Analyzer = {\n name: 'aws-sdk',\n description: 'Checks AWS SDK version usage and migration status',\n\n async analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...(pkgJson.dependencies ?? {}), ...(pkgJson.devDependencies ?? {}) };\n\n const hasV2 = 'aws-sdk' in allDeps;\n const v3Clients = Object.keys(allDeps).filter((d) => d.startsWith('@aws-sdk/client-'));\n const hasV3 = v3Clients.length > 0;\n\n if (hasV2 && !hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'critical',\n title: 'Using AWS SDK v2 (aws-sdk)',\n description: 'AWS SDK v2 is 65MB+ and loads all service clients. It adds 400ms+ to cold starts.',\n recommendation: 'Migrate to AWS SDK v3 (@aws-sdk/client-*). Only import the clients you need.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (hasV2 && hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Incomplete AWS SDK v2 to v3 migration',\n description: 'Both aws-sdk (v2) and @aws-sdk/client-* (v3) are present. This means v2 is still bundled alongside v3.',\n recommendation: 'Complete the migration to SDK v3 and remove the \"aws-sdk\" dependency.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (v3Clients.length > 5) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'info',\n title: `${v3Clients.length} AWS SDK v3 clients detected`,\n description: `This Lambda uses ${v3Clients.length} AWS SDK clients: ${v3Clients.join(', ')}. Each client adds to bundle size.`,\n recommendation: 'Verify all clients are necessary. Consider splitting into multiple Lambdas if responsibilities are too broad.',\n estimatedImpactMs: v3Clients.length * 5,\n });\n }\n\n // Check source files for unnecessary SSO client\n const sourceFiles = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,\n absolute: false,\n });\n\n for (const file of sourceFiles) {\n const content = await fs.readFile(path.join(targetPath, file), 'utf-8');\n if (content.includes('@aws-sdk/client-sso')) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Unnecessary SSO client in Lambda',\n description: '@aws-sdk/client-sso is imported but Lambda functions use IAM roles, not SSO authentication.',\n recommendation: 'Remove the @aws-sdk/client-sso import. Lambda uses IAM execution roles for authentication.',\n estimatedImpactMs: 15,\n filePath: file,\n });\n break;\n }\n }\n\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { hasV2, hasV3, v3ClientCount: v3Clients.length },\n };\n } catch (error) {\n console.warn('aws-sdk analyzer warning:', error);\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nconst BUNDLER_PACKAGES = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel'];\nconst BUNDLER_CONFIGS = [\n 'webpack.config.*',\n 'rollup.config.*',\n 'tsup.config.*',\n 'esbuild.config.*',\n '.parcelrc',\n];\nconst BUNDLER_KEYWORDS = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel', 'bundle'];\n\nexport const bundlerDetectionAnalyzer: Analyzer = {\n name: 'bundler-detection',\n description: 'Detects whether a bundler is configured and checks ESM/bundler setup',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const devDeps = pkgJson.devDependencies ?? {};\n const deps = pkgJson.dependencies ?? {};\n const allDeps = { ...deps, ...devDeps };\n const scripts = pkgJson.scripts ?? {};\n\n // Check for bundler packages\n const detectedBundlers: string[] = [];\n for (const bundler of BUNDLER_PACKAGES) {\n if (bundler in allDeps) {\n detectedBundlers.push(bundler);\n }\n }\n\n // Check for config files\n const configFiles = await fg(BUNDLER_CONFIGS, {\n cwd: targetPath,\n dot: true,\n });\n\n // Check scripts for bundler keywords\n const bundlerScripts: string[] = [];\n for (const [name, script] of Object.entries(scripts)) {\n if (typeof script === 'string' && BUNDLER_KEYWORDS.some((kw) => script.includes(kw))) {\n bundlerScripts.push(name);\n }\n }\n\n // Check serverless.yml for bundler plugins\n let serverlessPlugin: string | null = null;\n try {\n const slsPath = path.join(targetPath, 'serverless.yml');\n const slsContent = await fs.readFile(slsPath, 'utf-8');\n if (slsContent.includes('serverless-esbuild')) serverlessPlugin = 'serverless-esbuild';\n else if (slsContent.includes('serverless-webpack')) serverlessPlugin = 'serverless-webpack';\n } catch {\n // serverless.yml not found, that's fine\n }\n\n // Check ESM\n const isESM = pkgJson.type === 'module';\n\n const hasBundler = detectedBundlers.length > 0 || configFiles.length > 0 || serverlessPlugin !== null;\n\n if (!hasBundler) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'critical',\n title: 'No bundler detected',\n description: 'No bundler (esbuild, webpack, rollup, etc.) was found in this project. Without a bundler, the entire node_modules directory is deployed, causing large bundle sizes and slow cold starts.',\n recommendation: 'Add esbuild (fastest) or webpack to bundle your Lambda function. This is typically the single biggest cold start improvement you can make.',\n estimatedImpactMs: 500,\n });\n } else {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: `Bundler detected: ${detectedBundlers.join(', ') || serverlessPlugin || 'config found'}`,\n description: `Found bundler setup: packages=[${detectedBundlers.join(', ')}], configs=[${configFiles.join(', ')}]${serverlessPlugin ? `, serverless plugin=${serverlessPlugin}` : ''}.`,\n recommendation: 'Ensure your bundler is configured for tree-shaking and minification.',\n estimatedImpactMs: 0,\n });\n }\n\n if (!isESM) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: 'Project is not using ESM',\n description: '\"type\": \"module\" is not set in package.json. ESM enables better tree-shaking with bundlers.',\n recommendation: 'Consider setting \"type\": \"module\" in package.json for better tree-shaking support.',\n estimatedImpactMs: 20,\n });\n }\n\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: {\n detectedBundlers,\n configFiles,\n bundlerScripts,\n serverlessPlugin,\n isESM,\n hasBundler,\n },\n };\n } catch (error) {\n console.warn('bundler-detection analyzer warning:', error);\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import chalk from 'chalk';\nimport type { DiagnosisReport, Diagnostic, DependencyInfo } from '../../types.js';\n\nconst SEVERITY_ICON: Record<string, string> = {\n critical: '🔴',\n warning: '⚠️',\n info: '💡',\n};\n\nconst SEVERITY_COLOR: Record<string, (s: string) => string> = {\n critical: chalk.red,\n warning: chalk.yellow,\n info: chalk.blue,\n};\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${bytes}B`;\n}\n\nexport function printReport(report: DiagnosisReport): void {\n console.log();\n console.log(chalk.bold.cyan('🩺 Lambda Doctor — Diagnosis Report'));\n console.log(chalk.gray(` Target: ${report.targetPath}`));\n console.log(chalk.gray(` Date: ${report.timestamp}`));\n console.log();\n\n // Bundle size breakdown\n const bundleSizeResult = report.results.find((r) => r.analyzer === 'bundle-size');\n if (bundleSizeResult?.metadata) {\n const { totalSizeBytes, topDependencies } = bundleSizeResult.metadata as {\n totalSizeBytes: number;\n topDependencies: DependencyInfo[];\n };\n if (totalSizeBytes > 0) {\n console.log(chalk.bold('📦 Bundle Size Breakdown'));\n console.log(chalk.gray(` Total: ${formatBytes(totalSizeBytes)}`));\n console.log();\n if (topDependencies && topDependencies.length > 0) {\n console.log(chalk.gray(' Top Dependencies:'));\n for (const dep of topDependencies) {\n const bar = '█'.repeat(Math.max(1, Math.round((dep.sizeBytes / totalSizeBytes) * 30)));\n console.log(` ${chalk.white(dep.name.padEnd(35))} ${formatBytes(dep.sizeBytes).padStart(10)} ${chalk.green(bar)}`);\n }\n console.log();\n }\n }\n }\n\n // Diagnostics sorted by severity\n const allDiagnostics = report.results.flatMap((r) => r.diagnostics);\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n const sorted = [...allDiagnostics].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity],\n );\n\n if (sorted.length === 0) {\n console.log(chalk.green.bold('✅ No issues found! Your Lambda looks healthy.'));\n console.log();\n return;\n }\n\n console.log(chalk.bold('🔍 Diagnostics'));\n console.log();\n\n for (const diag of sorted) {\n const icon = SEVERITY_ICON[diag.severity];\n const colorFn = SEVERITY_COLOR[diag.severity];\n const location = diag.filePath ? chalk.gray(` (${diag.filePath}${diag.line ? `:${diag.line}` : ''})`) : '';\n\n console.log(`${icon} ${colorFn(diag.severity.toUpperCase())} ${chalk.bold(diag.title)}${location}`);\n console.log(chalk.gray(` ${diag.description}`));\n console.log(chalk.green(` → ${diag.recommendation}`));\n if (diag.estimatedImpactMs > 0) {\n console.log(chalk.cyan(` ⏱ Est. improvement: ~${diag.estimatedImpactMs}ms`));\n }\n console.log();\n }\n\n // Footer summary\n const { summary } = report;\n console.log(chalk.bold('─'.repeat(60)));\n console.log(\n chalk.bold('Summary: ') +\n chalk.red(`${summary.critical} critical`) +\n chalk.gray(' | ') +\n chalk.yellow(`${summary.warnings} warnings`) +\n chalk.gray(' | ') +\n chalk.blue(`${summary.info} info`),\n );\n if (summary.estimatedTotalImpactMs > 0) {\n console.log(\n chalk.bold.green(`\\n🚀 Total estimated cold start improvement: ~${summary.estimatedTotalImpactMs}ms`),\n );\n }\n console.log();\n}\n"],"mappings":"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","names":["fs","path","path","fs","path","pkg","path","fs","fg","fs","path","getPackageName","fg","path","fs","pkg","fs","fg","path","path","fs","fg","fs","fg","path","path","path","fs"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -70,7 +70,11 @@ interface AnalyzeConfig {
|
|
|
70
70
|
format?: 'console' | 'json';
|
|
71
71
|
/** Whether to show verbose output */
|
|
72
72
|
verbose?: boolean;
|
|
73
|
+
/** Glob patterns to exclude from file scanning */
|
|
74
|
+
exclude?: string[];
|
|
73
75
|
}
|
|
76
|
+
/** Default glob patterns excluded from scanning */
|
|
77
|
+
declare const DEFAULT_EXCLUDE_PATTERNS: string[];
|
|
74
78
|
/** Interface that all analyzers must implement */
|
|
75
79
|
interface Analyzer {
|
|
76
80
|
/** Unique name */
|
|
@@ -78,11 +82,11 @@ interface Analyzer {
|
|
|
78
82
|
/** Human-readable description */
|
|
79
83
|
description: string;
|
|
80
84
|
/** Run the analysis */
|
|
81
|
-
analyze(targetPath: string): Promise<AnalyzerResult>;
|
|
85
|
+
analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult>;
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
declare function printReport(report: DiagnosisReport): void;
|
|
85
89
|
|
|
86
90
|
declare function analyze(config: AnalyzeConfig): Promise<DiagnosisReport>;
|
|
87
91
|
|
|
88
|
-
export { type AnalyzeConfig, type Analyzer, type DiagnosisReport, type ReportSummary, analyze, printReport };
|
|
92
|
+
export { type AnalyzeConfig, type Analyzer, DEFAULT_EXCLUDE_PATTERNS, type DiagnosisReport, type ReportSummary, analyze, printReport };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import path6 from "path";
|
|
3
3
|
|
|
4
|
+
// types.ts
|
|
5
|
+
var DEFAULT_EXCLUDE_PATTERNS = [
|
|
6
|
+
"node_modules/**",
|
|
7
|
+
"dist/**",
|
|
8
|
+
"build/**",
|
|
9
|
+
"coverage/**",
|
|
10
|
+
"**/*.d.ts",
|
|
11
|
+
"**/__tests__/**",
|
|
12
|
+
"**/*.test.*",
|
|
13
|
+
"**/*.spec.*",
|
|
14
|
+
"**/test/**",
|
|
15
|
+
"**/tests/**",
|
|
16
|
+
"**/cypress/**",
|
|
17
|
+
"**/.serverless/**",
|
|
18
|
+
"**/cdk.out/**"
|
|
19
|
+
];
|
|
20
|
+
|
|
4
21
|
// src/analyzers/bundle-size.ts
|
|
5
22
|
import fg from "fast-glob";
|
|
6
23
|
import fs from "fs/promises";
|
|
@@ -311,13 +328,13 @@ function isTopLevel(line) {
|
|
|
311
328
|
var importAnalysisAnalyzer = {
|
|
312
329
|
name: "import-analysis",
|
|
313
330
|
description: "Analyzes import patterns for tree-shaking issues and heavy top-level imports",
|
|
314
|
-
async analyze(targetPath) {
|
|
331
|
+
async analyze(targetPath, exclude) {
|
|
315
332
|
const start = performance.now();
|
|
316
333
|
const diagnostics = [];
|
|
317
334
|
try {
|
|
318
335
|
const files = await fg2(["**/*.ts", "**/*.js", "**/*.mjs"], {
|
|
319
336
|
cwd: targetPath,
|
|
320
|
-
ignore:
|
|
337
|
+
ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,
|
|
321
338
|
absolute: false
|
|
322
339
|
});
|
|
323
340
|
for (const file of files) {
|
|
@@ -390,7 +407,7 @@ import path4 from "path";
|
|
|
390
407
|
var awsSdkAnalyzer = {
|
|
391
408
|
name: "aws-sdk",
|
|
392
409
|
description: "Checks AWS SDK version usage and migration status",
|
|
393
|
-
async analyze(targetPath) {
|
|
410
|
+
async analyze(targetPath, exclude) {
|
|
394
411
|
const start = performance.now();
|
|
395
412
|
const diagnostics = [];
|
|
396
413
|
try {
|
|
@@ -434,7 +451,7 @@ var awsSdkAnalyzer = {
|
|
|
434
451
|
}
|
|
435
452
|
const sourceFiles = await fg3(["**/*.ts", "**/*.js", "**/*.mjs"], {
|
|
436
453
|
cwd: targetPath,
|
|
437
|
-
ignore:
|
|
454
|
+
ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,
|
|
438
455
|
absolute: false
|
|
439
456
|
});
|
|
440
457
|
for (const file of sourceFiles) {
|
|
@@ -663,9 +680,10 @@ var ALL_ANALYZERS = [
|
|
|
663
680
|
async function analyze(config) {
|
|
664
681
|
const targetPath = path6.resolve(config.targetPath);
|
|
665
682
|
const start = performance.now();
|
|
683
|
+
const excludePatterns = config.exclude ?? DEFAULT_EXCLUDE_PATTERNS;
|
|
666
684
|
const analyzersToRun = config.analyzers ? ALL_ANALYZERS.filter((a) => config.analyzers.includes(a.name)) : ALL_ANALYZERS;
|
|
667
685
|
const results = await Promise.all(
|
|
668
|
-
analyzersToRun.map((a) => a.analyze(targetPath))
|
|
686
|
+
analyzersToRun.map((a) => a.analyze(targetPath, excludePatterns))
|
|
669
687
|
);
|
|
670
688
|
const allDiagnostics = results.flatMap((r) => r.diagnostics);
|
|
671
689
|
const summary = {
|
|
@@ -686,6 +704,7 @@ async function analyze(config) {
|
|
|
686
704
|
};
|
|
687
705
|
}
|
|
688
706
|
export {
|
|
707
|
+
DEFAULT_EXCLUDE_PATTERNS,
|
|
689
708
|
analyze,
|
|
690
709
|
printReport
|
|
691
710
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/analyzers/bundle-size.ts","../src/analyzers/heavy-dependencies.ts","../known-heavy-packages.ts","../src/analyzers/import-analysis.ts","../src/analyzers/aws-sdk.ts","../src/analyzers/bundler-detection.ts","../src/reporters/console.ts"],"sourcesContent":["import path from 'path';\nimport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nimport { bundleSizeAnalyzer } from './analyzers/bundle-size.js';\nimport { heavyDependenciesAnalyzer } from './analyzers/heavy-dependencies.js';\nimport { importAnalysisAnalyzer } from './analyzers/import-analysis.js';\nimport { awsSdkAnalyzer } from './analyzers/aws-sdk.js';\nimport { bundlerDetectionAnalyzer } from './analyzers/bundler-detection.js';\n\nexport { printReport } from './reporters/console.js';\n\nconst ALL_ANALYZERS: Analyzer[] = [\n bundleSizeAnalyzer,\n heavyDependenciesAnalyzer,\n importAnalysisAnalyzer,\n awsSdkAnalyzer,\n bundlerDetectionAnalyzer,\n];\n\nexport async function analyze(config: AnalyzeConfig): Promise<DiagnosisReport> {\n const targetPath = path.resolve(config.targetPath);\n const start = performance.now();\n\n const analyzersToRun = config.analyzers\n ? ALL_ANALYZERS.filter((a) => config.analyzers!.includes(a.name))\n : ALL_ANALYZERS;\n\n const results = await Promise.all(\n analyzersToRun.map((a) => a.analyze(targetPath)),\n );\n\n const allDiagnostics = results.flatMap((r) => r.diagnostics);\n const summary: ReportSummary = {\n totalIssues: allDiagnostics.length,\n critical: allDiagnostics.filter((d) => d.severity === 'critical').length,\n warnings: allDiagnostics.filter((d) => d.severity === 'warning').length,\n info: allDiagnostics.filter((d) => d.severity === 'info').length,\n estimatedTotalImpactMs: allDiagnostics.reduce((sum, d) => sum + d.estimatedImpactMs, 0),\n heavyDependencies: results.find((r) => r.analyzer === 'heavy-dependencies')?.metadata?.heavyCount as number ?? 0,\n bundleSizeBytes: results.find((r) => r.analyzer === 'bundle-size')?.metadata?.totalSizeBytes as number ?? undefined,\n };\n\n return {\n targetPath,\n timestamp: new Date().toISOString(),\n totalDurationMs: performance.now() - start,\n results,\n summary,\n };\n}\n\nexport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic, DependencyInfo } from '../../types.js';\n\nfunction getPackageName(filePath: string): string {\n // filePath is relative to node_modules, e.g. \"@aws-sdk/client-s3/dist/index.js\"\n const parts = filePath.split('/');\n if (parts[0].startsWith('@')) {\n return `${parts[0]}/${parts[1]}`;\n }\n return parts[0];\n}\n\nexport const bundleSizeAnalyzer: Analyzer = {\n name: 'bundle-size',\n description: 'Analyzes total node_modules size and identifies the largest dependencies',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n const nodeModulesPath = path.join(targetPath, 'node_modules');\n\n try {\n await fs.access(nodeModulesPath);\n } catch {\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n\n try {\n const files = await fg('**/*', {\n cwd: nodeModulesPath,\n stats: true,\n onlyFiles: true,\n dot: true,\n });\n\n const packageSizes = new Map<string, number>();\n\n for (const entry of files) {\n const pkgName = getPackageName(entry.path);\n const size = entry.stats?.size ?? 0;\n packageSizes.set(pkgName, (packageSizes.get(pkgName) ?? 0) + size);\n }\n\n const totalSizeBytes = [...packageSizes.values()].reduce((a, b) => a + b, 0);\n const sorted = [...packageSizes.entries()]\n .sort((a, b) => b[1] - a[1]);\n const top10 = sorted.slice(0, 10);\n\n const topDependencies: DependencyInfo[] = top10.map(([name, sizeBytes]) => ({\n name,\n version: '',\n sizeBytes,\n isHeavy: false,\n }));\n\n // Total bundle size diagnostics\n const totalMB = totalSizeBytes / (1024 * 1024);\n if (totalMB > 50) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: 'Bundle size is critically large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. AWS Lambda has a 250MB unzipped limit and large bundles severely impact cold start times.`,\n recommendation: 'Use a bundler (esbuild/webpack) to tree-shake and bundle only what you need. Remove unused dependencies.',\n estimatedImpactMs: Math.min(totalMB * 10, 2000),\n });\n } else if (totalMB > 10) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: 'Bundle size is large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. This adds unnecessary cold start latency.`,\n recommendation: 'Consider using a bundler to reduce the deployment package size.',\n estimatedImpactMs: Math.min(totalMB * 5, 500),\n });\n }\n\n // Individual dependency size diagnostics\n for (const [name, sizeBytes] of sorted) {\n const depMB = sizeBytes / (1024 * 1024);\n if (depMB > 5) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: `Dependency \"${name}\" is very large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Look for a lighter alternative to \"${name}\" or ensure it's being tree-shaken.`,\n estimatedImpactMs: Math.min(depMB * 8, 500),\n });\n } else if (depMB > 1) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: `Dependency \"${name}\" is large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Consider replacing \"${name}\" with a lighter alternative.`,\n estimatedImpactMs: Math.min(depMB * 5, 200),\n });\n }\n }\n\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { totalSizeBytes, topDependencies },\n };\n } catch (error) {\n console.warn('bundle-size analyzer warning:', error);\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { findHeavyPackage, HEAVY_PACKAGES } from '../../known-heavy-packages.js';\n\nconst DEV_ONLY_PACKAGES = ['typescript', 'ts-node', 'ts-jest', 'jest', 'mocha', 'eslint', 'prettier', 'tsup', 'webpack', 'rollup', 'esbuild'];\n\nexport const heavyDependenciesAnalyzer: Analyzer = {\n name: 'heavy-dependencies',\n description: 'Detects known heavy dependencies and dev tools in production',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const deps = pkgJson.dependencies ?? {};\n const devDeps = pkgJson.devDependencies ?? {};\n let heavyCount = 0;\n\n // Check production dependencies against heavy packages list\n for (const depName of Object.keys(deps)) {\n const heavy = findHeavyPackage(depName);\n if (heavy) {\n heavyCount++;\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'warning',\n title: `Heavy dependency: ${depName}`,\n description: heavy.reason,\n recommendation: heavy.alternative,\n estimatedImpactMs: heavy.estimatedSavingsMs,\n filePath: 'package.json',\n });\n }\n }\n\n // Check if dev-only tools are in production dependencies\n for (const depName of Object.keys(deps)) {\n if (DEV_ONLY_PACKAGES.includes(depName)) {\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'critical',\n title: `Dev tool \"${depName}\" in production dependencies`,\n description: `\"${depName}\" is a development tool that should not be in \"dependencies\". It adds unnecessary size and cold start time.`,\n recommendation: `Move \"${depName}\" from \"dependencies\" to \"devDependencies\".`,\n estimatedImpactMs: findHeavyPackage(depName)?.estimatedSavingsMs ?? 100,\n filePath: 'package.json',\n });\n }\n }\n\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { heavyCount, totalDependencies: Object.keys(deps).length },\n };\n } catch (error) {\n console.warn('heavy-dependencies analyzer warning:', error);\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","// ============================================================\n// Database of known heavy npm packages and their alternatives\n// Used by heavy-dependencies and bundle-size analyzers\n// ============================================================\n\nexport interface HeavyPackage {\n /** Package name */\n name: string;\n /** Typical size on disk (bytes, approximate) */\n typicalSizeBytes: number;\n /** Why it's problematic for Lambda */\n reason: string;\n /** Suggested replacement */\n alternative: string;\n /** Estimated cold start savings if replaced (ms) */\n estimatedSavingsMs: number;\n}\n\n/**\n * Known heavy packages that hurt Lambda cold starts.\n * Sources:\n * - https://speedrun.nobackspacecrew.com/blog/2023/09/23/optimizing-lambda-coldstarts.html\n * - https://aws.amazon.com/blogs/compute/optimizing-node-js-dependencies-in-aws-lambda/\n * - Community benchmarks\n */\nexport const HEAVY_PACKAGES: HeavyPackage[] = [\n {\n name: 'aws-sdk',\n typicalSizeBytes: 65_000_000,\n reason: 'AWS SDK v2 is 65MB+ and loads all service clients. Lambda runtime includes it, but it\\'s slow.',\n alternative: 'Use @aws-sdk/client-* (v3) with selective imports. Only import clients you need.',\n estimatedSavingsMs: 400,\n },\n {\n name: 'moment',\n typicalSizeBytes: 4_800_000,\n reason: 'Moment.js is 4.8MB with locales. Not tree-shakeable.',\n alternative: 'Use dayjs (2KB) or date-fns with tree-shaking.',\n estimatedSavingsMs: 50,\n },\n {\n name: 'moment-timezone',\n typicalSizeBytes: 8_200_000,\n reason: 'Moment-timezone adds 8MB+ of timezone data on top of Moment.',\n alternative: 'Use dayjs/plugin/timezone or Intl.DateTimeFormat (built-in).',\n estimatedSavingsMs: 80,\n },\n {\n name: 'lodash',\n typicalSizeBytes: 1_400_000,\n reason: 'Full lodash is 1.4MB. Not tree-shakeable with CommonJS.',\n alternative: 'Use lodash-es (tree-shakeable) or individual packages like lodash.get.',\n estimatedSavingsMs: 30,\n },\n {\n name: 'axios',\n typicalSizeBytes: 450_000,\n reason: 'Axios is 450KB. Overkill for Lambda where you can use native fetch (Node 18+).',\n alternative: 'Use native fetch (Node 18+) or undici.',\n estimatedSavingsMs: 15,\n },\n {\n name: 'express',\n typicalSizeBytes: 550_000,\n reason: 'Express has 30+ dependencies. Heavy for a single Lambda function.',\n alternative: 'Use lambda-api (zero deps) or direct API Gateway event parsing.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'bluebird',\n typicalSizeBytes: 350_000,\n reason: 'Bluebird is unnecessary in Node 18+ which has native Promise with good performance.',\n alternative: 'Use native Promise (built-in).',\n estimatedSavingsMs: 10,\n },\n {\n name: 'uuid',\n typicalSizeBytes: 150_000,\n reason: 'UUID package is 150KB. Node 18+ has crypto.randomUUID() built-in.',\n alternative: 'Use crypto.randomUUID() (built-in Node 18+).',\n estimatedSavingsMs: 5,\n },\n {\n name: 'winston',\n typicalSizeBytes: 2_500_000,\n reason: 'Winston is 2.5MB with many transports. Too heavy for Lambda.',\n alternative: 'Use @aws-lambda-powertools/logger or pino.',\n estimatedSavingsMs: 40,\n },\n {\n name: 'joi',\n typicalSizeBytes: 950_000,\n reason: 'Joi is ~1MB. Heavy for Lambda validation.',\n alternative: 'Use zod (lighter, TypeScript-native) or ajv.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'mongoose',\n typicalSizeBytes: 3_800_000,\n reason: 'Mongoose is 3.8MB. Extremely heavy for Lambda.',\n alternative: 'Use native MongoDB driver or Dynamoose for DynamoDB.',\n estimatedSavingsMs: 100,\n },\n {\n name: 'typescript',\n typicalSizeBytes: 65_000_000,\n reason: 'TypeScript compiler in production bundle is 65MB. Should only be a devDependency.',\n alternative: 'Move to devDependencies. Deploy compiled JavaScript only.',\n estimatedSavingsMs: 500,\n },\n {\n name: 'ts-node',\n typicalSizeBytes: 3_500_000,\n reason: 'ts-node adds 200-500ms cold start. Should not be in production.',\n alternative: 'Transpile to JavaScript before deployment.',\n estimatedSavingsMs: 350,\n },\n {\n name: '@nestjs/core',\n typicalSizeBytes: 5_200_000,\n reason: 'NestJS is a heavy framework (5MB+). Decorator metadata and DI container add cold start overhead.',\n alternative: 'Use lighter patterns for Lambda: plain handlers or lambda-api.',\n estimatedSavingsMs: 150,\n },\n {\n name: 'puppeteer',\n typicalSizeBytes: 300_000_000,\n reason: 'Puppeteer bundles Chromium (300MB+). Exceeds Lambda package limits.',\n alternative: 'Use @sparticuz/chromium with puppeteer-core for Lambda.',\n estimatedSavingsMs: 2000,\n },\n];\n\n/**\n * Lookup a package by name.\n */\nexport function findHeavyPackage(name: string): HeavyPackage | undefined {\n return HEAVY_PACKAGES.find((pkg) => pkg.name === name);\n}\n\n/**\n * Check if a package is known to be heavy.\n */\nexport function isHeavyPackage(name: string): boolean {\n return HEAVY_PACKAGES.some((pkg) => pkg.name === name);\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { isHeavyPackage, findHeavyPackage } from '../../known-heavy-packages.js';\n\nconst ESM_IMPORT = /^import\\s+.*\\s+from\\s+['\"](.+)['\"]/gm;\nconst CJS_REQUIRE = /^(?:const|let|var)\\s+.*=\\s*require\\(['\"](.+)['\"]\\)/gm;\nconst WILDCARD_IMPORT = /^import\\s+\\*\\s+as\\s+\\w+\\s+from\\s+['\"](.+)['\"]/gm;\n\nfunction getPackageName(specifier: string): string | null {\n if (specifier.startsWith('.') || specifier.startsWith('/')) return null;\n const parts = specifier.split('/');\n if (parts[0].startsWith('@')) {\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;\n }\n return parts[0];\n}\n\nfunction isTopLevel(line: string): boolean {\n const indent = line.length - line.trimStart().length;\n return indent <= 1;\n}\n\nexport const importAnalysisAnalyzer: Analyzer = {\n name: 'import-analysis',\n description: 'Analyzes import patterns for tree-shaking issues and heavy top-level imports',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const files = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: ['node_modules/**', 'dist/**', '**/*.d.ts'],\n absolute: false,\n });\n\n for (const file of files) {\n const filePath = path.join(targetPath, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check wildcard imports (tree-shaking issue)\n let match: RegExpExecArray | null;\n WILDCARD_IMPORT.lastIndex = 0;\n while ((match = WILDCARD_IMPORT.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg) {\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Wildcard import of \"${pkg}\" prevents tree-shaking`,\n description: `\"import * as ...\" from \"${match[1]}\" imports the entire module, preventing bundlers from removing unused code.`,\n recommendation: `Use named imports: import { specificFunction } from \"${match[1]}\"`,\n estimatedImpactMs: 20,\n filePath: file,\n line: i + 1,\n });\n }\n }\n\n // Check top-level heavy imports\n if (isTopLevel(line)) {\n for (const regex of [ESM_IMPORT, CJS_REQUIRE]) {\n regex.lastIndex = 0;\n while ((match = regex.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg && isHeavyPackage(pkg)) {\n const heavy = findHeavyPackage(pkg)!;\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Top-level import of heavy package \"${pkg}\"`,\n description: `\"${pkg}\" is imported at the top level in ${file}. This forces it to load during cold start even if not needed for every invocation.`,\n recommendation: `Consider lazy-loading: move the import inside the function that uses it. ${heavy.alternative}`,\n estimatedImpactMs: heavy.estimatedSavingsMs / 2,\n filePath: file,\n line: i + 1,\n });\n }\n }\n }\n }\n }\n }\n\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { filesScanned: files.length },\n };\n } catch (error) {\n console.warn('import-analysis analyzer warning:', error);\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nexport const awsSdkAnalyzer: Analyzer = {\n name: 'aws-sdk',\n description: 'Checks AWS SDK version usage and migration status',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...(pkgJson.dependencies ?? {}), ...(pkgJson.devDependencies ?? {}) };\n\n const hasV2 = 'aws-sdk' in allDeps;\n const v3Clients = Object.keys(allDeps).filter((d) => d.startsWith('@aws-sdk/client-'));\n const hasV3 = v3Clients.length > 0;\n\n if (hasV2 && !hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'critical',\n title: 'Using AWS SDK v2 (aws-sdk)',\n description: 'AWS SDK v2 is 65MB+ and loads all service clients. It adds 400ms+ to cold starts.',\n recommendation: 'Migrate to AWS SDK v3 (@aws-sdk/client-*). Only import the clients you need.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (hasV2 && hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Incomplete AWS SDK v2 to v3 migration',\n description: 'Both aws-sdk (v2) and @aws-sdk/client-* (v3) are present. This means v2 is still bundled alongside v3.',\n recommendation: 'Complete the migration to SDK v3 and remove the \"aws-sdk\" dependency.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (v3Clients.length > 5) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'info',\n title: `${v3Clients.length} AWS SDK v3 clients detected`,\n description: `This Lambda uses ${v3Clients.length} AWS SDK clients: ${v3Clients.join(', ')}. Each client adds to bundle size.`,\n recommendation: 'Verify all clients are necessary. Consider splitting into multiple Lambdas if responsibilities are too broad.',\n estimatedImpactMs: v3Clients.length * 5,\n });\n }\n\n // Check source files for unnecessary SSO client\n const sourceFiles = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: ['node_modules/**', 'dist/**', '**/*.d.ts'],\n absolute: false,\n });\n\n for (const file of sourceFiles) {\n const content = await fs.readFile(path.join(targetPath, file), 'utf-8');\n if (content.includes('@aws-sdk/client-sso')) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Unnecessary SSO client in Lambda',\n description: '@aws-sdk/client-sso is imported but Lambda functions use IAM roles, not SSO authentication.',\n recommendation: 'Remove the @aws-sdk/client-sso import. Lambda uses IAM execution roles for authentication.',\n estimatedImpactMs: 15,\n filePath: file,\n });\n break;\n }\n }\n\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { hasV2, hasV3, v3ClientCount: v3Clients.length },\n };\n } catch (error) {\n console.warn('aws-sdk analyzer warning:', error);\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nconst BUNDLER_PACKAGES = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel'];\nconst BUNDLER_CONFIGS = [\n 'webpack.config.*',\n 'rollup.config.*',\n 'tsup.config.*',\n 'esbuild.config.*',\n '.parcelrc',\n];\nconst BUNDLER_KEYWORDS = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel', 'bundle'];\n\nexport const bundlerDetectionAnalyzer: Analyzer = {\n name: 'bundler-detection',\n description: 'Detects whether a bundler is configured and checks ESM/bundler setup',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const devDeps = pkgJson.devDependencies ?? {};\n const deps = pkgJson.dependencies ?? {};\n const allDeps = { ...deps, ...devDeps };\n const scripts = pkgJson.scripts ?? {};\n\n // Check for bundler packages\n const detectedBundlers: string[] = [];\n for (const bundler of BUNDLER_PACKAGES) {\n if (bundler in allDeps) {\n detectedBundlers.push(bundler);\n }\n }\n\n // Check for config files\n const configFiles = await fg(BUNDLER_CONFIGS, {\n cwd: targetPath,\n dot: true,\n });\n\n // Check scripts for bundler keywords\n const bundlerScripts: string[] = [];\n for (const [name, script] of Object.entries(scripts)) {\n if (typeof script === 'string' && BUNDLER_KEYWORDS.some((kw) => script.includes(kw))) {\n bundlerScripts.push(name);\n }\n }\n\n // Check serverless.yml for bundler plugins\n let serverlessPlugin: string | null = null;\n try {\n const slsPath = path.join(targetPath, 'serverless.yml');\n const slsContent = await fs.readFile(slsPath, 'utf-8');\n if (slsContent.includes('serverless-esbuild')) serverlessPlugin = 'serverless-esbuild';\n else if (slsContent.includes('serverless-webpack')) serverlessPlugin = 'serverless-webpack';\n } catch {\n // serverless.yml not found, that's fine\n }\n\n // Check ESM\n const isESM = pkgJson.type === 'module';\n\n const hasBundler = detectedBundlers.length > 0 || configFiles.length > 0 || serverlessPlugin !== null;\n\n if (!hasBundler) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'critical',\n title: 'No bundler detected',\n description: 'No bundler (esbuild, webpack, rollup, etc.) was found in this project. Without a bundler, the entire node_modules directory is deployed, causing large bundle sizes and slow cold starts.',\n recommendation: 'Add esbuild (fastest) or webpack to bundle your Lambda function. This is typically the single biggest cold start improvement you can make.',\n estimatedImpactMs: 500,\n });\n } else {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: `Bundler detected: ${detectedBundlers.join(', ') || serverlessPlugin || 'config found'}`,\n description: `Found bundler setup: packages=[${detectedBundlers.join(', ')}], configs=[${configFiles.join(', ')}]${serverlessPlugin ? `, serverless plugin=${serverlessPlugin}` : ''}.`,\n recommendation: 'Ensure your bundler is configured for tree-shaking and minification.',\n estimatedImpactMs: 0,\n });\n }\n\n if (!isESM) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: 'Project is not using ESM',\n description: '\"type\": \"module\" is not set in package.json. ESM enables better tree-shaking with bundlers.',\n recommendation: 'Consider setting \"type\": \"module\" in package.json for better tree-shaking support.',\n estimatedImpactMs: 20,\n });\n }\n\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: {\n detectedBundlers,\n configFiles,\n bundlerScripts,\n serverlessPlugin,\n isESM,\n hasBundler,\n },\n };\n } catch (error) {\n console.warn('bundler-detection analyzer warning:', error);\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import chalk from 'chalk';\nimport type { DiagnosisReport, Diagnostic, DependencyInfo } from '../../types.js';\n\nconst SEVERITY_ICON: Record<string, string> = {\n critical: '🔴',\n warning: '⚠️',\n info: '💡',\n};\n\nconst SEVERITY_COLOR: Record<string, (s: string) => string> = {\n critical: chalk.red,\n warning: chalk.yellow,\n info: chalk.blue,\n};\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${bytes}B`;\n}\n\nexport function printReport(report: DiagnosisReport): void {\n console.log();\n console.log(chalk.bold.cyan('🩺 Lambda Doctor — Diagnosis Report'));\n console.log(chalk.gray(` Target: ${report.targetPath}`));\n console.log(chalk.gray(` Date: ${report.timestamp}`));\n console.log();\n\n // Bundle size breakdown\n const bundleSizeResult = report.results.find((r) => r.analyzer === 'bundle-size');\n if (bundleSizeResult?.metadata) {\n const { totalSizeBytes, topDependencies } = bundleSizeResult.metadata as {\n totalSizeBytes: number;\n topDependencies: DependencyInfo[];\n };\n if (totalSizeBytes > 0) {\n console.log(chalk.bold('📦 Bundle Size Breakdown'));\n console.log(chalk.gray(` Total: ${formatBytes(totalSizeBytes)}`));\n console.log();\n if (topDependencies && topDependencies.length > 0) {\n console.log(chalk.gray(' Top Dependencies:'));\n for (const dep of topDependencies) {\n const bar = '█'.repeat(Math.max(1, Math.round((dep.sizeBytes / totalSizeBytes) * 30)));\n console.log(` ${chalk.white(dep.name.padEnd(35))} ${formatBytes(dep.sizeBytes).padStart(10)} ${chalk.green(bar)}`);\n }\n console.log();\n }\n }\n }\n\n // Diagnostics sorted by severity\n const allDiagnostics = report.results.flatMap((r) => r.diagnostics);\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n const sorted = [...allDiagnostics].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity],\n );\n\n if (sorted.length === 0) {\n console.log(chalk.green.bold('✅ No issues found! Your Lambda looks healthy.'));\n console.log();\n return;\n }\n\n console.log(chalk.bold('🔍 Diagnostics'));\n console.log();\n\n for (const diag of sorted) {\n const icon = SEVERITY_ICON[diag.severity];\n const colorFn = SEVERITY_COLOR[diag.severity];\n const location = diag.filePath ? chalk.gray(` (${diag.filePath}${diag.line ? `:${diag.line}` : ''})`) : '';\n\n console.log(`${icon} ${colorFn(diag.severity.toUpperCase())} ${chalk.bold(diag.title)}${location}`);\n console.log(chalk.gray(` ${diag.description}`));\n console.log(chalk.green(` → ${diag.recommendation}`));\n if (diag.estimatedImpactMs > 0) {\n console.log(chalk.cyan(` ⏱ Est. improvement: ~${diag.estimatedImpactMs}ms`));\n }\n console.log();\n }\n\n // Footer summary\n const { summary } = report;\n console.log(chalk.bold('─'.repeat(60)));\n console.log(\n chalk.bold('Summary: ') +\n chalk.red(`${summary.critical} critical`) +\n chalk.gray(' | ') +\n chalk.yellow(`${summary.warnings} warnings`) +\n chalk.gray(' | ') +\n chalk.blue(`${summary.info} info`),\n );\n if (summary.estimatedTotalImpactMs > 0) {\n console.log(\n chalk.bold.green(`\\n🚀 Total estimated cold start improvement: ~${summary.estimatedTotalImpactMs}ms`),\n );\n }\n console.log();\n}\n"],"mappings":"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","names":["path","fs","path","path","fs","fg","fs","path","getPackageName","fg","path","fs","fs","fg","path","fs","fg","path","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../types.ts","../src/analyzers/bundle-size.ts","../src/analyzers/heavy-dependencies.ts","../known-heavy-packages.ts","../src/analyzers/import-analysis.ts","../src/analyzers/aws-sdk.ts","../src/analyzers/bundler-detection.ts","../src/reporters/console.ts"],"sourcesContent":["import path from 'path';\nimport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../types.js';\nimport { bundleSizeAnalyzer } from './analyzers/bundle-size.js';\nimport { heavyDependenciesAnalyzer } from './analyzers/heavy-dependencies.js';\nimport { importAnalysisAnalyzer } from './analyzers/import-analysis.js';\nimport { awsSdkAnalyzer } from './analyzers/aws-sdk.js';\nimport { bundlerDetectionAnalyzer } from './analyzers/bundler-detection.js';\n\nexport { printReport } from './reporters/console.js';\n\nconst ALL_ANALYZERS: Analyzer[] = [\n bundleSizeAnalyzer,\n heavyDependenciesAnalyzer,\n importAnalysisAnalyzer,\n awsSdkAnalyzer,\n bundlerDetectionAnalyzer,\n];\n\nexport async function analyze(config: AnalyzeConfig): Promise<DiagnosisReport> {\n const targetPath = path.resolve(config.targetPath);\n const start = performance.now();\n\n const excludePatterns = config.exclude ?? DEFAULT_EXCLUDE_PATTERNS;\n\n const analyzersToRun = config.analyzers\n ? ALL_ANALYZERS.filter((a) => config.analyzers!.includes(a.name))\n : ALL_ANALYZERS;\n\n const results = await Promise.all(\n analyzersToRun.map((a) => a.analyze(targetPath, excludePatterns)),\n );\n\n const allDiagnostics = results.flatMap((r) => r.diagnostics);\n const summary: ReportSummary = {\n totalIssues: allDiagnostics.length,\n critical: allDiagnostics.filter((d) => d.severity === 'critical').length,\n warnings: allDiagnostics.filter((d) => d.severity === 'warning').length,\n info: allDiagnostics.filter((d) => d.severity === 'info').length,\n estimatedTotalImpactMs: allDiagnostics.reduce((sum, d) => sum + d.estimatedImpactMs, 0),\n heavyDependencies: results.find((r) => r.analyzer === 'heavy-dependencies')?.metadata?.heavyCount as number ?? 0,\n bundleSizeBytes: results.find((r) => r.analyzer === 'bundle-size')?.metadata?.totalSizeBytes as number ?? undefined,\n };\n\n return {\n targetPath,\n timestamp: new Date().toISOString(),\n totalDurationMs: performance.now() - start,\n results,\n summary,\n };\n}\n\nexport type { AnalyzeConfig, DiagnosisReport, Analyzer, ReportSummary } from '../types.js';\nexport { DEFAULT_EXCLUDE_PATTERNS } from '../types.js';\n","// ============================================================\n// lambda-doctor core types\n// ============================================================\n\n/** Severity of a diagnostic finding */\nexport type Severity = 'critical' | 'warning' | 'info';\n\n/** Category of analysis */\nexport type AnalyzerName =\n | 'bundle-size'\n | 'heavy-dependencies'\n | 'import-analysis'\n | 'aws-sdk'\n | 'bundler-detection';\n\n/** A single diagnostic finding */\nexport interface Diagnostic {\n /** Which analyzer produced this */\n analyzer: AnalyzerName;\n /** Severity level */\n severity: Severity;\n /** Short human-readable title */\n title: string;\n /** Detailed description of the issue */\n description: string;\n /** Actionable fix recommendation */\n recommendation: string;\n /** Estimated cold start improvement in ms (0 if unknown) */\n estimatedImpactMs: number;\n /** File path related to this finding (optional) */\n filePath?: string;\n /** Line number (optional) */\n line?: number;\n}\n\n/** Summary of a dependency */\nexport interface DependencyInfo {\n /** Package name */\n name: string;\n /** Version string */\n version: string;\n /** Size on disk in bytes */\n sizeBytes: number;\n /** Whether it's a known heavy package */\n isHeavy: boolean;\n /** Suggested lighter alternative (if any) */\n alternative?: string;\n}\n\n/** Result from a single analyzer */\nexport interface AnalyzerResult {\n /** Analyzer name */\n analyzer: AnalyzerName;\n /** Time taken to run in ms */\n durationMs: number;\n /** Findings */\n diagnostics: Diagnostic[];\n /** Analyzer-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/** Full diagnosis report */\nexport interface DiagnosisReport {\n /** Path that was analyzed */\n targetPath: string;\n /** Timestamp */\n timestamp: string;\n /** Total analysis duration in ms */\n totalDurationMs: number;\n /** Results from each analyzer */\n results: AnalyzerResult[];\n /** Aggregated summary */\n summary: ReportSummary;\n}\n\n/** Aggregated summary across all analyzers */\nexport interface ReportSummary {\n /** Total number of diagnostics */\n totalIssues: number;\n /** Count by severity */\n critical: number;\n warnings: number;\n info: number;\n /** Total estimated cold start improvement in ms */\n estimatedTotalImpactMs: number;\n /** Total bundle size in bytes (if detected) */\n bundleSizeBytes?: number;\n /** Number of heavy dependencies found */\n heavyDependencies: number;\n}\n\n/** Configuration for the analyze command */\nexport interface AnalyzeConfig {\n /** Path to the Lambda project directory */\n targetPath: string;\n /** Which analyzers to run (default: all) */\n analyzers?: AnalyzerName[];\n /** Output format */\n format?: 'console' | 'json';\n /** Whether to show verbose output */\n verbose?: boolean;\n /** Glob patterns to exclude from file scanning */\n exclude?: string[];\n}\n\n/** Default glob patterns excluded from scanning */\nexport const DEFAULT_EXCLUDE_PATTERNS: string[] = [\n 'node_modules/**',\n 'dist/**',\n 'build/**',\n 'coverage/**',\n '**/*.d.ts',\n '**/__tests__/**',\n '**/*.test.*',\n '**/*.spec.*',\n '**/test/**',\n '**/tests/**',\n '**/cypress/**',\n '**/.serverless/**',\n '**/cdk.out/**',\n];\n\n/** Interface that all analyzers must implement */\nexport interface Analyzer {\n /** Unique name */\n name: AnalyzerName;\n /** Human-readable description */\n description: string;\n /** Run the analysis */\n analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult>;\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic, DependencyInfo } from '../../types.js';\n\nfunction getPackageName(filePath: string): string {\n // filePath is relative to node_modules, e.g. \"@aws-sdk/client-s3/dist/index.js\"\n const parts = filePath.split('/');\n if (parts[0].startsWith('@')) {\n return `${parts[0]}/${parts[1]}`;\n }\n return parts[0];\n}\n\nexport const bundleSizeAnalyzer: Analyzer = {\n name: 'bundle-size',\n description: 'Analyzes total node_modules size and identifies the largest dependencies',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n const nodeModulesPath = path.join(targetPath, 'node_modules');\n\n try {\n await fs.access(nodeModulesPath);\n } catch {\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n\n try {\n const files = await fg('**/*', {\n cwd: nodeModulesPath,\n stats: true,\n onlyFiles: true,\n dot: true,\n });\n\n const packageSizes = new Map<string, number>();\n\n for (const entry of files) {\n const pkgName = getPackageName(entry.path);\n const size = entry.stats?.size ?? 0;\n packageSizes.set(pkgName, (packageSizes.get(pkgName) ?? 0) + size);\n }\n\n const totalSizeBytes = [...packageSizes.values()].reduce((a, b) => a + b, 0);\n const sorted = [...packageSizes.entries()]\n .sort((a, b) => b[1] - a[1]);\n const top10 = sorted.slice(0, 10);\n\n const topDependencies: DependencyInfo[] = top10.map(([name, sizeBytes]) => ({\n name,\n version: '',\n sizeBytes,\n isHeavy: false,\n }));\n\n // Total bundle size diagnostics\n const totalMB = totalSizeBytes / (1024 * 1024);\n if (totalMB > 50) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: 'Bundle size is critically large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. AWS Lambda has a 250MB unzipped limit and large bundles severely impact cold start times.`,\n recommendation: 'Use a bundler (esbuild/webpack) to tree-shake and bundle only what you need. Remove unused dependencies.',\n estimatedImpactMs: Math.min(totalMB * 10, 2000),\n });\n } else if (totalMB > 10) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: 'Bundle size is large',\n description: `Total node_modules size is ${totalMB.toFixed(1)}MB. This adds unnecessary cold start latency.`,\n recommendation: 'Consider using a bundler to reduce the deployment package size.',\n estimatedImpactMs: Math.min(totalMB * 5, 500),\n });\n }\n\n // Individual dependency size diagnostics\n for (const [name, sizeBytes] of sorted) {\n const depMB = sizeBytes / (1024 * 1024);\n if (depMB > 5) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'critical',\n title: `Dependency \"${name}\" is very large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Look for a lighter alternative to \"${name}\" or ensure it's being tree-shaken.`,\n estimatedImpactMs: Math.min(depMB * 8, 500),\n });\n } else if (depMB > 1) {\n diagnostics.push({\n analyzer: 'bundle-size',\n severity: 'warning',\n title: `Dependency \"${name}\" is large (${depMB.toFixed(1)}MB)`,\n description: `The package \"${name}\" takes up ${depMB.toFixed(1)}MB on disk.`,\n recommendation: `Consider replacing \"${name}\" with a lighter alternative.`,\n estimatedImpactMs: Math.min(depMB * 5, 200),\n });\n }\n }\n\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { totalSizeBytes, topDependencies },\n };\n } catch (error) {\n console.warn('bundle-size analyzer warning:', error);\n return {\n analyzer: 'bundle-size',\n durationMs: performance.now() - start,\n diagnostics: [],\n metadata: { totalSizeBytes: 0, topDependencies: [] },\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { findHeavyPackage, HEAVY_PACKAGES } from '../../known-heavy-packages.js';\n\nconst DEV_ONLY_PACKAGES = ['typescript', 'ts-node', 'ts-jest', 'jest', 'mocha', 'eslint', 'prettier', 'tsup', 'webpack', 'rollup', 'esbuild'];\n\nexport const heavyDependenciesAnalyzer: Analyzer = {\n name: 'heavy-dependencies',\n description: 'Detects known heavy dependencies and dev tools in production',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const deps = pkgJson.dependencies ?? {};\n const devDeps = pkgJson.devDependencies ?? {};\n let heavyCount = 0;\n\n // Check production dependencies against heavy packages list\n for (const depName of Object.keys(deps)) {\n const heavy = findHeavyPackage(depName);\n if (heavy) {\n heavyCount++;\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'warning',\n title: `Heavy dependency: ${depName}`,\n description: heavy.reason,\n recommendation: heavy.alternative,\n estimatedImpactMs: heavy.estimatedSavingsMs,\n filePath: 'package.json',\n });\n }\n }\n\n // Check if dev-only tools are in production dependencies\n for (const depName of Object.keys(deps)) {\n if (DEV_ONLY_PACKAGES.includes(depName)) {\n diagnostics.push({\n analyzer: 'heavy-dependencies',\n severity: 'critical',\n title: `Dev tool \"${depName}\" in production dependencies`,\n description: `\"${depName}\" is a development tool that should not be in \"dependencies\". It adds unnecessary size and cold start time.`,\n recommendation: `Move \"${depName}\" from \"dependencies\" to \"devDependencies\".`,\n estimatedImpactMs: findHeavyPackage(depName)?.estimatedSavingsMs ?? 100,\n filePath: 'package.json',\n });\n }\n }\n\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { heavyCount, totalDependencies: Object.keys(deps).length },\n };\n } catch (error) {\n console.warn('heavy-dependencies analyzer warning:', error);\n return {\n analyzer: 'heavy-dependencies',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","// ============================================================\n// Database of known heavy npm packages and their alternatives\n// Used by heavy-dependencies and bundle-size analyzers\n// ============================================================\n\nexport interface HeavyPackage {\n /** Package name */\n name: string;\n /** Typical size on disk (bytes, approximate) */\n typicalSizeBytes: number;\n /** Why it's problematic for Lambda */\n reason: string;\n /** Suggested replacement */\n alternative: string;\n /** Estimated cold start savings if replaced (ms) */\n estimatedSavingsMs: number;\n}\n\n/**\n * Known heavy packages that hurt Lambda cold starts.\n * Sources:\n * - https://speedrun.nobackspacecrew.com/blog/2023/09/23/optimizing-lambda-coldstarts.html\n * - https://aws.amazon.com/blogs/compute/optimizing-node-js-dependencies-in-aws-lambda/\n * - Community benchmarks\n */\nexport const HEAVY_PACKAGES: HeavyPackage[] = [\n {\n name: 'aws-sdk',\n typicalSizeBytes: 65_000_000,\n reason: 'AWS SDK v2 is 65MB+ and loads all service clients. Lambda runtime includes it, but it\\'s slow.',\n alternative: 'Use @aws-sdk/client-* (v3) with selective imports. Only import clients you need.',\n estimatedSavingsMs: 400,\n },\n {\n name: 'moment',\n typicalSizeBytes: 4_800_000,\n reason: 'Moment.js is 4.8MB with locales. Not tree-shakeable.',\n alternative: 'Use dayjs (2KB) or date-fns with tree-shaking.',\n estimatedSavingsMs: 50,\n },\n {\n name: 'moment-timezone',\n typicalSizeBytes: 8_200_000,\n reason: 'Moment-timezone adds 8MB+ of timezone data on top of Moment.',\n alternative: 'Use dayjs/plugin/timezone or Intl.DateTimeFormat (built-in).',\n estimatedSavingsMs: 80,\n },\n {\n name: 'lodash',\n typicalSizeBytes: 1_400_000,\n reason: 'Full lodash is 1.4MB. Not tree-shakeable with CommonJS.',\n alternative: 'Use lodash-es (tree-shakeable) or individual packages like lodash.get.',\n estimatedSavingsMs: 30,\n },\n {\n name: 'axios',\n typicalSizeBytes: 450_000,\n reason: 'Axios is 450KB. Overkill for Lambda where you can use native fetch (Node 18+).',\n alternative: 'Use native fetch (Node 18+) or undici.',\n estimatedSavingsMs: 15,\n },\n {\n name: 'express',\n typicalSizeBytes: 550_000,\n reason: 'Express has 30+ dependencies. Heavy for a single Lambda function.',\n alternative: 'Use lambda-api (zero deps) or direct API Gateway event parsing.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'bluebird',\n typicalSizeBytes: 350_000,\n reason: 'Bluebird is unnecessary in Node 18+ which has native Promise with good performance.',\n alternative: 'Use native Promise (built-in).',\n estimatedSavingsMs: 10,\n },\n {\n name: 'uuid',\n typicalSizeBytes: 150_000,\n reason: 'UUID package is 150KB. Node 18+ has crypto.randomUUID() built-in.',\n alternative: 'Use crypto.randomUUID() (built-in Node 18+).',\n estimatedSavingsMs: 5,\n },\n {\n name: 'winston',\n typicalSizeBytes: 2_500_000,\n reason: 'Winston is 2.5MB with many transports. Too heavy for Lambda.',\n alternative: 'Use @aws-lambda-powertools/logger or pino.',\n estimatedSavingsMs: 40,\n },\n {\n name: 'joi',\n typicalSizeBytes: 950_000,\n reason: 'Joi is ~1MB. Heavy for Lambda validation.',\n alternative: 'Use zod (lighter, TypeScript-native) or ajv.',\n estimatedSavingsMs: 20,\n },\n {\n name: 'mongoose',\n typicalSizeBytes: 3_800_000,\n reason: 'Mongoose is 3.8MB. Extremely heavy for Lambda.',\n alternative: 'Use native MongoDB driver or Dynamoose for DynamoDB.',\n estimatedSavingsMs: 100,\n },\n {\n name: 'typescript',\n typicalSizeBytes: 65_000_000,\n reason: 'TypeScript compiler in production bundle is 65MB. Should only be a devDependency.',\n alternative: 'Move to devDependencies. Deploy compiled JavaScript only.',\n estimatedSavingsMs: 500,\n },\n {\n name: 'ts-node',\n typicalSizeBytes: 3_500_000,\n reason: 'ts-node adds 200-500ms cold start. Should not be in production.',\n alternative: 'Transpile to JavaScript before deployment.',\n estimatedSavingsMs: 350,\n },\n {\n name: '@nestjs/core',\n typicalSizeBytes: 5_200_000,\n reason: 'NestJS is a heavy framework (5MB+). Decorator metadata and DI container add cold start overhead.',\n alternative: 'Use lighter patterns for Lambda: plain handlers or lambda-api.',\n estimatedSavingsMs: 150,\n },\n {\n name: 'puppeteer',\n typicalSizeBytes: 300_000_000,\n reason: 'Puppeteer bundles Chromium (300MB+). Exceeds Lambda package limits.',\n alternative: 'Use @sparticuz/chromium with puppeteer-core for Lambda.',\n estimatedSavingsMs: 2000,\n },\n];\n\n/**\n * Lookup a package by name.\n */\nexport function findHeavyPackage(name: string): HeavyPackage | undefined {\n return HEAVY_PACKAGES.find((pkg) => pkg.name === name);\n}\n\n/**\n * Check if a package is known to be heavy.\n */\nexport function isHeavyPackage(name: string): boolean {\n return HEAVY_PACKAGES.some((pkg) => pkg.name === name);\n}\n","import fg from 'fast-glob';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../../types.js';\nimport { isHeavyPackage, findHeavyPackage } from '../../known-heavy-packages.js';\n\nconst ESM_IMPORT = /^import\\s+.*\\s+from\\s+['\"](.+)['\"]/gm;\nconst CJS_REQUIRE = /^(?:const|let|var)\\s+.*=\\s*require\\(['\"](.+)['\"]\\)/gm;\nconst WILDCARD_IMPORT = /^import\\s+\\*\\s+as\\s+\\w+\\s+from\\s+['\"](.+)['\"]/gm;\n\nfunction getPackageName(specifier: string): string | null {\n if (specifier.startsWith('.') || specifier.startsWith('/')) return null;\n const parts = specifier.split('/');\n if (parts[0].startsWith('@')) {\n return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : null;\n }\n return parts[0];\n}\n\nfunction isTopLevel(line: string): boolean {\n const indent = line.length - line.trimStart().length;\n return indent <= 1;\n}\n\nexport const importAnalysisAnalyzer: Analyzer = {\n name: 'import-analysis',\n description: 'Analyzes import patterns for tree-shaking issues and heavy top-level imports',\n\n async analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const files = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,\n absolute: false,\n });\n\n for (const file of files) {\n const filePath = path.join(targetPath, file);\n const content = await fs.readFile(filePath, 'utf-8');\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n // Check wildcard imports (tree-shaking issue)\n let match: RegExpExecArray | null;\n WILDCARD_IMPORT.lastIndex = 0;\n while ((match = WILDCARD_IMPORT.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg) {\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Wildcard import of \"${pkg}\" prevents tree-shaking`,\n description: `\"import * as ...\" from \"${match[1]}\" imports the entire module, preventing bundlers from removing unused code.`,\n recommendation: `Use named imports: import { specificFunction } from \"${match[1]}\"`,\n estimatedImpactMs: 20,\n filePath: file,\n line: i + 1,\n });\n }\n }\n\n // Check top-level heavy imports\n if (isTopLevel(line)) {\n for (const regex of [ESM_IMPORT, CJS_REQUIRE]) {\n regex.lastIndex = 0;\n while ((match = regex.exec(line)) !== null) {\n const pkg = getPackageName(match[1]);\n if (pkg && isHeavyPackage(pkg)) {\n const heavy = findHeavyPackage(pkg)!;\n diagnostics.push({\n analyzer: 'import-analysis',\n severity: 'warning',\n title: `Top-level import of heavy package \"${pkg}\"`,\n description: `\"${pkg}\" is imported at the top level in ${file}. This forces it to load during cold start even if not needed for every invocation.`,\n recommendation: `Consider lazy-loading: move the import inside the function that uses it. ${heavy.alternative}`,\n estimatedImpactMs: heavy.estimatedSavingsMs / 2,\n filePath: file,\n line: i + 1,\n });\n }\n }\n }\n }\n }\n }\n\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { filesScanned: files.length },\n };\n } catch (error) {\n console.warn('import-analysis analyzer warning:', error);\n return {\n analyzer: 'import-analysis',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../../types.js';\n\nexport const awsSdkAnalyzer: Analyzer = {\n name: 'aws-sdk',\n description: 'Checks AWS SDK version usage and migration status',\n\n async analyze(targetPath: string, exclude?: string[]): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const allDeps = { ...(pkgJson.dependencies ?? {}), ...(pkgJson.devDependencies ?? {}) };\n\n const hasV2 = 'aws-sdk' in allDeps;\n const v3Clients = Object.keys(allDeps).filter((d) => d.startsWith('@aws-sdk/client-'));\n const hasV3 = v3Clients.length > 0;\n\n if (hasV2 && !hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'critical',\n title: 'Using AWS SDK v2 (aws-sdk)',\n description: 'AWS SDK v2 is 65MB+ and loads all service clients. It adds 400ms+ to cold starts.',\n recommendation: 'Migrate to AWS SDK v3 (@aws-sdk/client-*). Only import the clients you need.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (hasV2 && hasV3) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Incomplete AWS SDK v2 to v3 migration',\n description: 'Both aws-sdk (v2) and @aws-sdk/client-* (v3) are present. This means v2 is still bundled alongside v3.',\n recommendation: 'Complete the migration to SDK v3 and remove the \"aws-sdk\" dependency.',\n estimatedImpactMs: 400,\n filePath: 'package.json',\n });\n }\n\n if (v3Clients.length > 5) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'info',\n title: `${v3Clients.length} AWS SDK v3 clients detected`,\n description: `This Lambda uses ${v3Clients.length} AWS SDK clients: ${v3Clients.join(', ')}. Each client adds to bundle size.`,\n recommendation: 'Verify all clients are necessary. Consider splitting into multiple Lambdas if responsibilities are too broad.',\n estimatedImpactMs: v3Clients.length * 5,\n });\n }\n\n // Check source files for unnecessary SSO client\n const sourceFiles = await fg(['**/*.ts', '**/*.js', '**/*.mjs'], {\n cwd: targetPath,\n ignore: exclude ?? DEFAULT_EXCLUDE_PATTERNS,\n absolute: false,\n });\n\n for (const file of sourceFiles) {\n const content = await fs.readFile(path.join(targetPath, file), 'utf-8');\n if (content.includes('@aws-sdk/client-sso')) {\n diagnostics.push({\n analyzer: 'aws-sdk',\n severity: 'warning',\n title: 'Unnecessary SSO client in Lambda',\n description: '@aws-sdk/client-sso is imported but Lambda functions use IAM roles, not SSO authentication.',\n recommendation: 'Remove the @aws-sdk/client-sso import. Lambda uses IAM execution roles for authentication.',\n estimatedImpactMs: 15,\n filePath: file,\n });\n break;\n }\n }\n\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: { hasV2, hasV3, v3ClientCount: v3Clients.length },\n };\n } catch (error) {\n console.warn('aws-sdk analyzer warning:', error);\n return {\n analyzer: 'aws-sdk',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import fs from 'fs/promises';\nimport fg from 'fast-glob';\nimport path from 'path';\nimport type { Analyzer, AnalyzerResult, Diagnostic } from '../../types.js';\n\nconst BUNDLER_PACKAGES = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel'];\nconst BUNDLER_CONFIGS = [\n 'webpack.config.*',\n 'rollup.config.*',\n 'tsup.config.*',\n 'esbuild.config.*',\n '.parcelrc',\n];\nconst BUNDLER_KEYWORDS = ['esbuild', 'webpack', 'rollup', 'tsup', 'parcel', 'bundle'];\n\nexport const bundlerDetectionAnalyzer: Analyzer = {\n name: 'bundler-detection',\n description: 'Detects whether a bundler is configured and checks ESM/bundler setup',\n\n async analyze(targetPath: string): Promise<AnalyzerResult> {\n const start = performance.now();\n const diagnostics: Diagnostic[] = [];\n\n try {\n const pkgJsonPath = path.join(targetPath, 'package.json');\n const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf-8'));\n const devDeps = pkgJson.devDependencies ?? {};\n const deps = pkgJson.dependencies ?? {};\n const allDeps = { ...deps, ...devDeps };\n const scripts = pkgJson.scripts ?? {};\n\n // Check for bundler packages\n const detectedBundlers: string[] = [];\n for (const bundler of BUNDLER_PACKAGES) {\n if (bundler in allDeps) {\n detectedBundlers.push(bundler);\n }\n }\n\n // Check for config files\n const configFiles = await fg(BUNDLER_CONFIGS, {\n cwd: targetPath,\n dot: true,\n });\n\n // Check scripts for bundler keywords\n const bundlerScripts: string[] = [];\n for (const [name, script] of Object.entries(scripts)) {\n if (typeof script === 'string' && BUNDLER_KEYWORDS.some((kw) => script.includes(kw))) {\n bundlerScripts.push(name);\n }\n }\n\n // Check serverless.yml for bundler plugins\n let serverlessPlugin: string | null = null;\n try {\n const slsPath = path.join(targetPath, 'serverless.yml');\n const slsContent = await fs.readFile(slsPath, 'utf-8');\n if (slsContent.includes('serverless-esbuild')) serverlessPlugin = 'serverless-esbuild';\n else if (slsContent.includes('serverless-webpack')) serverlessPlugin = 'serverless-webpack';\n } catch {\n // serverless.yml not found, that's fine\n }\n\n // Check ESM\n const isESM = pkgJson.type === 'module';\n\n const hasBundler = detectedBundlers.length > 0 || configFiles.length > 0 || serverlessPlugin !== null;\n\n if (!hasBundler) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'critical',\n title: 'No bundler detected',\n description: 'No bundler (esbuild, webpack, rollup, etc.) was found in this project. Without a bundler, the entire node_modules directory is deployed, causing large bundle sizes and slow cold starts.',\n recommendation: 'Add esbuild (fastest) or webpack to bundle your Lambda function. This is typically the single biggest cold start improvement you can make.',\n estimatedImpactMs: 500,\n });\n } else {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: `Bundler detected: ${detectedBundlers.join(', ') || serverlessPlugin || 'config found'}`,\n description: `Found bundler setup: packages=[${detectedBundlers.join(', ')}], configs=[${configFiles.join(', ')}]${serverlessPlugin ? `, serverless plugin=${serverlessPlugin}` : ''}.`,\n recommendation: 'Ensure your bundler is configured for tree-shaking and minification.',\n estimatedImpactMs: 0,\n });\n }\n\n if (!isESM) {\n diagnostics.push({\n analyzer: 'bundler-detection',\n severity: 'info',\n title: 'Project is not using ESM',\n description: '\"type\": \"module\" is not set in package.json. ESM enables better tree-shaking with bundlers.',\n recommendation: 'Consider setting \"type\": \"module\" in package.json for better tree-shaking support.',\n estimatedImpactMs: 20,\n });\n }\n\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics,\n metadata: {\n detectedBundlers,\n configFiles,\n bundlerScripts,\n serverlessPlugin,\n isESM,\n hasBundler,\n },\n };\n } catch (error) {\n console.warn('bundler-detection analyzer warning:', error);\n return {\n analyzer: 'bundler-detection',\n durationMs: performance.now() - start,\n diagnostics: [],\n };\n }\n },\n};\n","import chalk from 'chalk';\nimport type { DiagnosisReport, Diagnostic, DependencyInfo } from '../../types.js';\n\nconst SEVERITY_ICON: Record<string, string> = {\n critical: '🔴',\n warning: '⚠️',\n info: '💡',\n};\n\nconst SEVERITY_COLOR: Record<string, (s: string) => string> = {\n critical: chalk.red,\n warning: chalk.yellow,\n info: chalk.blue,\n};\n\nfunction formatBytes(bytes: number): string {\n if (bytes >= 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n if (bytes >= 1024) return `${(bytes / 1024).toFixed(1)}KB`;\n return `${bytes}B`;\n}\n\nexport function printReport(report: DiagnosisReport): void {\n console.log();\n console.log(chalk.bold.cyan('🩺 Lambda Doctor — Diagnosis Report'));\n console.log(chalk.gray(` Target: ${report.targetPath}`));\n console.log(chalk.gray(` Date: ${report.timestamp}`));\n console.log();\n\n // Bundle size breakdown\n const bundleSizeResult = report.results.find((r) => r.analyzer === 'bundle-size');\n if (bundleSizeResult?.metadata) {\n const { totalSizeBytes, topDependencies } = bundleSizeResult.metadata as {\n totalSizeBytes: number;\n topDependencies: DependencyInfo[];\n };\n if (totalSizeBytes > 0) {\n console.log(chalk.bold('📦 Bundle Size Breakdown'));\n console.log(chalk.gray(` Total: ${formatBytes(totalSizeBytes)}`));\n console.log();\n if (topDependencies && topDependencies.length > 0) {\n console.log(chalk.gray(' Top Dependencies:'));\n for (const dep of topDependencies) {\n const bar = '█'.repeat(Math.max(1, Math.round((dep.sizeBytes / totalSizeBytes) * 30)));\n console.log(` ${chalk.white(dep.name.padEnd(35))} ${formatBytes(dep.sizeBytes).padStart(10)} ${chalk.green(bar)}`);\n }\n console.log();\n }\n }\n }\n\n // Diagnostics sorted by severity\n const allDiagnostics = report.results.flatMap((r) => r.diagnostics);\n const severityOrder: Record<string, number> = { critical: 0, warning: 1, info: 2 };\n const sorted = [...allDiagnostics].sort(\n (a, b) => severityOrder[a.severity] - severityOrder[b.severity],\n );\n\n if (sorted.length === 0) {\n console.log(chalk.green.bold('✅ No issues found! Your Lambda looks healthy.'));\n console.log();\n return;\n }\n\n console.log(chalk.bold('🔍 Diagnostics'));\n console.log();\n\n for (const diag of sorted) {\n const icon = SEVERITY_ICON[diag.severity];\n const colorFn = SEVERITY_COLOR[diag.severity];\n const location = diag.filePath ? chalk.gray(` (${diag.filePath}${diag.line ? `:${diag.line}` : ''})`) : '';\n\n console.log(`${icon} ${colorFn(diag.severity.toUpperCase())} ${chalk.bold(diag.title)}${location}`);\n console.log(chalk.gray(` ${diag.description}`));\n console.log(chalk.green(` → ${diag.recommendation}`));\n if (diag.estimatedImpactMs > 0) {\n console.log(chalk.cyan(` ⏱ Est. improvement: ~${diag.estimatedImpactMs}ms`));\n }\n console.log();\n }\n\n // Footer summary\n const { summary } = report;\n console.log(chalk.bold('─'.repeat(60)));\n console.log(\n chalk.bold('Summary: ') +\n chalk.red(`${summary.critical} critical`) +\n chalk.gray(' | ') +\n chalk.yellow(`${summary.warnings} warnings`) +\n chalk.gray(' | ') +\n chalk.blue(`${summary.info} info`),\n );\n if (summary.estimatedTotalImpactMs > 0) {\n console.log(\n chalk.bold.green(`\\n🚀 Total estimated cold start improvement: ~${summary.estimatedTotalImpactMs}ms`),\n );\n }\n console.log();\n}\n"],"mappings":";AAAA,OAAOA,WAAU;;;AC0GV,IAAM,2BAAqC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACxHA,OAAO,QAAQ;AACf,OAAO,QAAQ;AACf,OAAO,UAAU;AAGjB,SAAS,eAAe,UAA0B;AAEhD,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,MAAI,MAAM,CAAC,EAAE,WAAW,GAAG,GAAG;AAC5B,WAAO,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;AAAA,EAChC;AACA,SAAO,MAAM,CAAC;AAChB;AAEO,IAAM,qBAA+B;AAAA,EAC1C,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,YAA6C;AACzD,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAA4B,CAAC;AACnC,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAE5D,QAAI;AACF,YAAM,GAAG,OAAO,eAAe;AAAA,IACjC,QAAQ;AACN,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,QACd,UAAU,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EAAE;AAAA,MACrD;AAAA,IACF;AAEA,QAAI;AACF,YAAM,QAAQ,MAAM,GAAG,QAAQ;AAAA,QAC7B,KAAK;AAAA,QACL,OAAO;AAAA,QACP,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AAED,YAAM,eAAe,oBAAI,IAAoB;AAE7C,iBAAW,SAAS,OAAO;AACzB,cAAM,UAAU,eAAe,MAAM,IAAI;AACzC,cAAM,OAAO,MAAM,OAAO,QAAQ;AAClC,qBAAa,IAAI,UAAU,aAAa,IAAI,OAAO,KAAK,KAAK,IAAI;AAAA,MACnE;AAEA,YAAM,iBAAiB,CAAC,GAAG,aAAa,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAC3E,YAAM,SAAS,CAAC,GAAG,aAAa,QAAQ,CAAC,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7B,YAAM,QAAQ,OAAO,MAAM,GAAG,EAAE;AAEhC,YAAM,kBAAoC,MAAM,IAAI,CAAC,CAAC,MAAM,SAAS,OAAO;AAAA,QAC1E;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,SAAS;AAAA,MACX,EAAE;AAGF,YAAM,UAAU,kBAAkB,OAAO;AACzC,UAAI,UAAU,IAAI;AAChB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,8BAA8B,QAAQ,QAAQ,CAAC,CAAC;AAAA,UAC7D,gBAAgB;AAAA,UAChB,mBAAmB,KAAK,IAAI,UAAU,IAAI,GAAI;AAAA,QAChD,CAAC;AAAA,MACH,WAAW,UAAU,IAAI;AACvB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa,8BAA8B,QAAQ,QAAQ,CAAC,CAAC;AAAA,UAC7D,gBAAgB;AAAA,UAChB,mBAAmB,KAAK,IAAI,UAAU,GAAG,GAAG;AAAA,QAC9C,CAAC;AAAA,MACH;AAGA,iBAAW,CAAC,MAAM,SAAS,KAAK,QAAQ;AACtC,cAAM,QAAQ,aAAa,OAAO;AAClC,YAAI,QAAQ,GAAG;AACb,sBAAY,KAAK;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO,eAAe,IAAI,oBAAoB,MAAM,QAAQ,CAAC,CAAC;AAAA,YAC9D,aAAa,gBAAgB,IAAI,cAAc,MAAM,QAAQ,CAAC,CAAC;AAAA,YAC/D,gBAAgB,sCAAsC,IAAI;AAAA,YAC1D,mBAAmB,KAAK,IAAI,QAAQ,GAAG,GAAG;AAAA,UAC5C,CAAC;AAAA,QACH,WAAW,QAAQ,GAAG;AACpB,sBAAY,KAAK;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO,eAAe,IAAI,eAAe,MAAM,QAAQ,CAAC,CAAC;AAAA,YACzD,aAAa,gBAAgB,IAAI,cAAc,MAAM,QAAQ,CAAC,CAAC;AAAA,YAC/D,gBAAgB,uBAAuB,IAAI;AAAA,YAC3C,mBAAmB,KAAK,IAAI,QAAQ,GAAG,GAAG;AAAA,UAC5C,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC;AAAA,QACA,UAAU,EAAE,gBAAgB,gBAAgB;AAAA,MAC9C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,iCAAiC,KAAK;AACnD,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,QACd,UAAU,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,EAAE;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AACF;;;AC5HA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACwBV,IAAM,iBAAiC;AAAA,EAC5C;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AACF;AAKO,SAAS,iBAAiB,MAAwC;AACvE,SAAO,eAAe,KAAK,CAAC,QAAQ,IAAI,SAAS,IAAI;AACvD;AAKO,SAAS,eAAe,MAAuB;AACpD,SAAO,eAAe,KAAK,CAAC,QAAQ,IAAI,SAAS,IAAI;AACvD;;;AD5IA,IAAM,oBAAoB,CAAC,cAAc,WAAW,WAAW,QAAQ,SAAS,UAAU,YAAY,QAAQ,WAAW,UAAU,SAAS;AAErI,IAAM,4BAAsC;AAAA,EACjD,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,YAA6C;AACzD,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAA4B,CAAC;AAEnC,QAAI;AACF,YAAM,cAAcC,MAAK,KAAK,YAAY,cAAc;AACxD,YAAM,UAAU,KAAK,MAAM,MAAMC,IAAG,SAAS,aAAa,OAAO,CAAC;AAClE,YAAM,OAAO,QAAQ,gBAAgB,CAAC;AACtC,YAAM,UAAU,QAAQ,mBAAmB,CAAC;AAC5C,UAAI,aAAa;AAGjB,iBAAW,WAAW,OAAO,KAAK,IAAI,GAAG;AACvC,cAAM,QAAQ,iBAAiB,OAAO;AACtC,YAAI,OAAO;AACT;AACA,sBAAY,KAAK;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO,qBAAqB,OAAO;AAAA,YACnC,aAAa,MAAM;AAAA,YACnB,gBAAgB,MAAM;AAAA,YACtB,mBAAmB,MAAM;AAAA,YACzB,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAGA,iBAAW,WAAW,OAAO,KAAK,IAAI,GAAG;AACvC,YAAI,kBAAkB,SAAS,OAAO,GAAG;AACvC,sBAAY,KAAK;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO,aAAa,OAAO;AAAA,YAC3B,aAAa,IAAI,OAAO;AAAA,YACxB,gBAAgB,SAAS,OAAO;AAAA,YAChC,mBAAmB,iBAAiB,OAAO,GAAG,sBAAsB;AAAA,YACpE,UAAU;AAAA,UACZ,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC;AAAA,QACA,UAAU,EAAE,YAAY,mBAAmB,OAAO,KAAK,IAAI,EAAE,OAAO;AAAA,MACtE;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,wCAAwC,KAAK;AAC1D,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;AErEA,OAAOC,SAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAKjB,IAAM,aAAa;AACnB,IAAM,cAAc;AACpB,IAAM,kBAAkB;AAExB,SAASC,gBAAe,WAAkC;AACxD,MAAI,UAAU,WAAW,GAAG,KAAK,UAAU,WAAW,GAAG,EAAG,QAAO;AACnE,QAAM,QAAQ,UAAU,MAAM,GAAG;AACjC,MAAI,MAAM,CAAC,EAAE,WAAW,GAAG,GAAG;AAC5B,WAAO,MAAM,UAAU,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,KAAK;AAAA,EACzD;AACA,SAAO,MAAM,CAAC;AAChB;AAEA,SAAS,WAAW,MAAuB;AACzC,QAAM,SAAS,KAAK,SAAS,KAAK,UAAU,EAAE;AAC9C,SAAO,UAAU;AACnB;AAEO,IAAM,yBAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,YAAoB,SAA6C;AAC7E,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAA4B,CAAC;AAEnC,QAAI;AACF,YAAM,QAAQ,MAAMC,IAAG,CAAC,WAAW,WAAW,UAAU,GAAG;AAAA,QACzD,KAAK;AAAA,QACL,QAAQ,WAAW;AAAA,QACnB,UAAU;AAAA,MACZ,CAAC;AAED,iBAAW,QAAQ,OAAO;AACxB,cAAM,WAAWC,MAAK,KAAK,YAAY,IAAI;AAC3C,cAAM,UAAU,MAAMC,IAAG,SAAS,UAAU,OAAO;AACnD,cAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,OAAO,MAAM,CAAC;AAGpB,cAAI;AACJ,0BAAgB,YAAY;AAC5B,kBAAQ,QAAQ,gBAAgB,KAAK,IAAI,OAAO,MAAM;AACpD,kBAAM,MAAMH,gBAAe,MAAM,CAAC,CAAC;AACnC,gBAAI,KAAK;AACP,0BAAY,KAAK;AAAA,gBACf,UAAU;AAAA,gBACV,UAAU;AAAA,gBACV,OAAO,uBAAuB,GAAG;AAAA,gBACjC,aAAa,2BAA2B,MAAM,CAAC,CAAC;AAAA,gBAChD,gBAAgB,wDAAwD,MAAM,CAAC,CAAC;AAAA,gBAChF,mBAAmB;AAAA,gBACnB,UAAU;AAAA,gBACV,MAAM,IAAI;AAAA,cACZ,CAAC;AAAA,YACH;AAAA,UACF;AAGA,cAAI,WAAW,IAAI,GAAG;AACpB,uBAAW,SAAS,CAAC,YAAY,WAAW,GAAG;AAC7C,oBAAM,YAAY;AAClB,sBAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,sBAAM,MAAMA,gBAAe,MAAM,CAAC,CAAC;AACnC,oBAAI,OAAO,eAAe,GAAG,GAAG;AAC9B,wBAAM,QAAQ,iBAAiB,GAAG;AAClC,8BAAY,KAAK;AAAA,oBACf,UAAU;AAAA,oBACV,UAAU;AAAA,oBACV,OAAO,sCAAsC,GAAG;AAAA,oBAChD,aAAa,IAAI,GAAG,qCAAqC,IAAI;AAAA,oBAC7D,gBAAgB,4EAA4E,MAAM,WAAW;AAAA,oBAC7G,mBAAmB,MAAM,qBAAqB;AAAA,oBAC9C,UAAU;AAAA,oBACV,MAAM,IAAI;AAAA,kBACZ,CAAC;AAAA,gBACH;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC;AAAA,QACA,UAAU,EAAE,cAAc,MAAM,OAAO;AAAA,MACzC;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,qCAAqC,KAAK;AACvD,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;AC3GA,OAAOI,SAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAIV,IAAM,iBAA2B;AAAA,EACtC,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,YAAoB,SAA6C;AAC7E,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAA4B,CAAC;AAEnC,QAAI;AACF,YAAM,cAAcC,MAAK,KAAK,YAAY,cAAc;AACxD,YAAM,UAAU,KAAK,MAAM,MAAMC,IAAG,SAAS,aAAa,OAAO,CAAC;AAClE,YAAM,UAAU,EAAE,GAAI,QAAQ,gBAAgB,CAAC,GAAI,GAAI,QAAQ,mBAAmB,CAAC,EAAG;AAEtF,YAAM,QAAQ,aAAa;AAC3B,YAAM,YAAY,OAAO,KAAK,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,kBAAkB,CAAC;AACrF,YAAM,QAAQ,UAAU,SAAS;AAEjC,UAAI,SAAS,CAAC,OAAO;AACnB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,UAAI,SAAS,OAAO;AAClB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,UACnB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAEA,UAAI,UAAU,SAAS,GAAG;AACxB,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO,GAAG,UAAU,MAAM;AAAA,UAC1B,aAAa,oBAAoB,UAAU,MAAM,qBAAqB,UAAU,KAAK,IAAI,CAAC;AAAA,UAC1F,gBAAgB;AAAA,UAChB,mBAAmB,UAAU,SAAS;AAAA,QACxC,CAAC;AAAA,MACH;AAGA,YAAM,cAAc,MAAMC,IAAG,CAAC,WAAW,WAAW,UAAU,GAAG;AAAA,QAC/D,KAAK;AAAA,QACL,QAAQ,WAAW;AAAA,QACnB,UAAU;AAAA,MACZ,CAAC;AAED,iBAAW,QAAQ,aAAa;AAC9B,cAAM,UAAU,MAAMD,IAAG,SAASD,MAAK,KAAK,YAAY,IAAI,GAAG,OAAO;AACtE,YAAI,QAAQ,SAAS,qBAAqB,GAAG;AAC3C,sBAAY,KAAK;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,OAAO;AAAA,YACP,aAAa;AAAA,YACb,gBAAgB;AAAA,YAChB,mBAAmB;AAAA,YACnB,UAAU;AAAA,UACZ,CAAC;AACD;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC;AAAA,QACA,UAAU,EAAE,OAAO,OAAO,eAAe,UAAU,OAAO;AAAA,MAC5D;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,6BAA6B,KAAK;AAC/C,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;AChGA,OAAOG,SAAQ;AACf,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,IAAM,mBAAmB,CAAC,WAAW,WAAW,UAAU,QAAQ,QAAQ;AAC1E,IAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,mBAAmB,CAAC,WAAW,WAAW,UAAU,QAAQ,UAAU,QAAQ;AAE7E,IAAM,2BAAqC;AAAA,EAChD,MAAM;AAAA,EACN,aAAa;AAAA,EAEb,MAAM,QAAQ,YAA6C;AACzD,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM,cAA4B,CAAC;AAEnC,QAAI;AACF,YAAM,cAAcA,MAAK,KAAK,YAAY,cAAc;AACxD,YAAM,UAAU,KAAK,MAAM,MAAMF,IAAG,SAAS,aAAa,OAAO,CAAC;AAClE,YAAM,UAAU,QAAQ,mBAAmB,CAAC;AAC5C,YAAM,OAAO,QAAQ,gBAAgB,CAAC;AACtC,YAAM,UAAU,EAAE,GAAG,MAAM,GAAG,QAAQ;AACtC,YAAM,UAAU,QAAQ,WAAW,CAAC;AAGpC,YAAM,mBAA6B,CAAC;AACpC,iBAAW,WAAW,kBAAkB;AACtC,YAAI,WAAW,SAAS;AACtB,2BAAiB,KAAK,OAAO;AAAA,QAC/B;AAAA,MACF;AAGA,YAAM,cAAc,MAAMC,IAAG,iBAAiB;AAAA,QAC5C,KAAK;AAAA,QACL,KAAK;AAAA,MACP,CAAC;AAGD,YAAM,iBAA2B,CAAC;AAClC,iBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACpD,YAAI,OAAO,WAAW,YAAY,iBAAiB,KAAK,CAAC,OAAO,OAAO,SAAS,EAAE,CAAC,GAAG;AACpF,yBAAe,KAAK,IAAI;AAAA,QAC1B;AAAA,MACF;AAGA,UAAI,mBAAkC;AACtC,UAAI;AACF,cAAM,UAAUC,MAAK,KAAK,YAAY,gBAAgB;AACtD,cAAM,aAAa,MAAMF,IAAG,SAAS,SAAS,OAAO;AACrD,YAAI,WAAW,SAAS,oBAAoB,EAAG,oBAAmB;AAAA,iBACzD,WAAW,SAAS,oBAAoB,EAAG,oBAAmB;AAAA,MACzE,QAAQ;AAAA,MAER;AAGA,YAAM,QAAQ,QAAQ,SAAS;AAE/B,YAAM,aAAa,iBAAiB,SAAS,KAAK,YAAY,SAAS,KAAK,qBAAqB;AAEjG,UAAI,CAAC,YAAY;AACf,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,QACrB,CAAC;AAAA,MACH,OAAO;AACL,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO,qBAAqB,iBAAiB,KAAK,IAAI,KAAK,oBAAoB,cAAc;AAAA,UAC7F,aAAa,kCAAkC,iBAAiB,KAAK,IAAI,CAAC,eAAe,YAAY,KAAK,IAAI,CAAC,IAAI,mBAAmB,uBAAuB,gBAAgB,KAAK,EAAE;AAAA,UACpL,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,QACrB,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,OAAO;AACV,oBAAY,KAAK;AAAA,UACf,UAAU;AAAA,UACV,UAAU;AAAA,UACV,OAAO;AAAA,UACP,aAAa;AAAA,UACb,gBAAgB;AAAA,UAChB,mBAAmB;AAAA,QACrB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC;AAAA,QACA,UAAU;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,uCAAuC,KAAK;AACzD,aAAO;AAAA,QACL,UAAU;AAAA,QACV,YAAY,YAAY,IAAI,IAAI;AAAA,QAChC,aAAa,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACF;;;AC1HA,OAAO,WAAW;AAGlB,IAAM,gBAAwC;AAAA,EAC5C,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AACR;AAEA,IAAM,iBAAwD;AAAA,EAC5D,UAAU,MAAM;AAAA,EAChB,SAAS,MAAM;AAAA,EACf,MAAM,MAAM;AACd;AAEA,SAAS,YAAY,OAAuB;AAC1C,MAAI,SAAS,OAAO,KAAM,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AACtE,MAAI,SAAS,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AACtD,SAAO,GAAG,KAAK;AACjB;AAEO,SAAS,YAAY,QAA+B;AACzD,UAAQ,IAAI;AACZ,UAAQ,IAAI,MAAM,KAAK,KAAK,iDAAqC,CAAC;AAClE,UAAQ,IAAI,MAAM,KAAK,cAAc,OAAO,UAAU,EAAE,CAAC;AACzD,UAAQ,IAAI,MAAM,KAAK,cAAc,OAAO,SAAS,EAAE,CAAC;AACxD,UAAQ,IAAI;AAGZ,QAAM,mBAAmB,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,aAAa;AAChF,MAAI,kBAAkB,UAAU;AAC9B,UAAM,EAAE,gBAAgB,gBAAgB,IAAI,iBAAiB;AAI7D,QAAI,iBAAiB,GAAG;AACtB,cAAQ,IAAI,MAAM,KAAK,iCAA0B,CAAC;AAClD,cAAQ,IAAI,MAAM,KAAK,aAAa,YAAY,cAAc,CAAC,EAAE,CAAC;AAClE,cAAQ,IAAI;AACZ,UAAI,mBAAmB,gBAAgB,SAAS,GAAG;AACjD,gBAAQ,IAAI,MAAM,KAAK,sBAAsB,CAAC;AAC9C,mBAAW,OAAO,iBAAiB;AACjC,gBAAM,MAAM,SAAI,OAAO,KAAK,IAAI,GAAG,KAAK,MAAO,IAAI,YAAY,iBAAkB,EAAE,CAAC,CAAC;AACrF,kBAAQ,IAAI,MAAM,MAAM,MAAM,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,YAAY,IAAI,SAAS,EAAE,SAAS,EAAE,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,EAAE;AAAA,QACtH;AACA,gBAAQ,IAAI;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAGA,QAAM,iBAAiB,OAAO,QAAQ,QAAQ,CAAC,MAAM,EAAE,WAAW;AAClE,QAAM,gBAAwC,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,EAAE;AACjF,QAAM,SAAS,CAAC,GAAG,cAAc,EAAE;AAAA,IACjC,CAAC,GAAG,MAAM,cAAc,EAAE,QAAQ,IAAI,cAAc,EAAE,QAAQ;AAAA,EAChE;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,YAAQ,IAAI,MAAM,MAAM,KAAK,oDAA+C,CAAC;AAC7E,YAAQ,IAAI;AACZ;AAAA,EACF;AAEA,UAAQ,IAAI,MAAM,KAAK,uBAAgB,CAAC;AACxC,UAAQ,IAAI;AAEZ,aAAW,QAAQ,QAAQ;AACzB,UAAM,OAAO,cAAc,KAAK,QAAQ;AACxC,UAAM,UAAU,eAAe,KAAK,QAAQ;AAC5C,UAAM,WAAW,KAAK,WAAW,MAAM,KAAK,KAAK,KAAK,QAAQ,GAAG,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,EAAE,GAAG,IAAI;AAExG,YAAQ,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,SAAS,YAAY,CAAC,CAAC,IAAI,MAAM,KAAK,KAAK,KAAK,CAAC,GAAG,QAAQ,EAAE;AAClG,YAAQ,IAAI,MAAM,KAAK,MAAM,KAAK,WAAW,EAAE,CAAC;AAChD,YAAQ,IAAI,MAAM,MAAM,aAAQ,KAAK,cAAc,EAAE,CAAC;AACtD,QAAI,KAAK,oBAAoB,GAAG;AAC9B,cAAQ,IAAI,MAAM,KAAK,iCAA4B,KAAK,iBAAiB,IAAI,CAAC;AAAA,IAChF;AACA,YAAQ,IAAI;AAAA,EACd;AAGA,QAAM,EAAE,QAAQ,IAAI;AACpB,UAAQ,IAAI,MAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AACtC,UAAQ;AAAA,IACN,MAAM,KAAK,WAAW,IACpB,MAAM,IAAI,GAAG,QAAQ,QAAQ,WAAW,IACxC,MAAM,KAAK,KAAK,IAChB,MAAM,OAAO,GAAG,QAAQ,QAAQ,WAAW,IAC3C,MAAM,KAAK,KAAK,IAChB,MAAM,KAAK,GAAG,QAAQ,IAAI,OAAO;AAAA,EACrC;AACA,MAAI,QAAQ,yBAAyB,GAAG;AACtC,YAAQ;AAAA,MACN,MAAM,KAAK,MAAM;AAAA,qDAAiD,QAAQ,sBAAsB,IAAI;AAAA,IACtG;AAAA,EACF;AACA,UAAQ,IAAI;AACd;;;ARtFA,IAAM,gBAA4B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,eAAsB,QAAQ,QAAiD;AAC7E,QAAM,aAAaG,MAAK,QAAQ,OAAO,UAAU;AACjD,QAAM,QAAQ,YAAY,IAAI;AAE9B,QAAM,kBAAkB,OAAO,WAAW;AAE1C,QAAM,iBAAiB,OAAO,YAC1B,cAAc,OAAO,CAAC,MAAM,OAAO,UAAW,SAAS,EAAE,IAAI,CAAC,IAC9D;AAEJ,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,eAAe,IAAI,CAAC,MAAM,EAAE,QAAQ,YAAY,eAAe,CAAC;AAAA,EAClE;AAEA,QAAM,iBAAiB,QAAQ,QAAQ,CAAC,MAAM,EAAE,WAAW;AAC3D,QAAM,UAAyB;AAAA,IAC7B,aAAa,eAAe;AAAA,IAC5B,UAAU,eAAe,OAAO,CAAC,MAAM,EAAE,aAAa,UAAU,EAAE;AAAA,IAClE,UAAU,eAAe,OAAO,CAAC,MAAM,EAAE,aAAa,SAAS,EAAE;AAAA,IACjE,MAAM,eAAe,OAAO,CAAC,MAAM,EAAE,aAAa,MAAM,EAAE;AAAA,IAC1D,wBAAwB,eAAe,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,mBAAmB,CAAC;AAAA,IACtF,mBAAmB,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,oBAAoB,GAAG,UAAU,cAAwB;AAAA,IAC/G,iBAAiB,QAAQ,KAAK,CAAC,MAAM,EAAE,aAAa,aAAa,GAAG,UAAU,kBAA4B;AAAA,EAC5G;AAEA,SAAO;AAAA,IACL;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,iBAAiB,YAAY,IAAI,IAAI;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AACF;","names":["path","fs","path","path","fs","fg","fs","path","getPackageName","fg","path","fs","fs","fg","path","path","fs","fg","fs","fg","path","path"]}
|
package/package.json
CHANGED