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 CHANGED
@@ -10,7 +10,7 @@ Static analysis CLI that scans your Node.js Lambda project and tells you exactly
10
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
11
11
  [![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue.svg)](https://www.typescriptlang.org/)
12
12
 
13
- [Quick Start](#quick-start) · [What It Checks](#what-it-checks) · [Example Output](#example-output) · [How It Works](#how-it-works)
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
- ## Example Output
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
- 🔴 CRITICAL Dev tool "typescript" in production dependencies
53
- → Move "typescript" from "dependencies" to "devDependencies".
54
- ⏱ Est. improvement: ~500ms
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
- 🔴 CRITICAL Using AWS SDK v2 (aws-sdk)
57
- Migrate to AWS SDK v3 (@aws-sdk/client-*). Only import the clients you need.
58
- ⏱ Est. improvement: ~400ms
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
- 🔴 CRITICAL No bundler detected
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 Heavy dependency: moment
65
- → Use dayjs (2KB) or date-fns with tree-shaking.
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
- Summary: 3 critical | 12 warnings | 1 info
73
- 🚀 Total estimated cold start improvement: ~2742.5ms
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((pkg) => pkg.name === name);
253
+ return HEAVY_PACKAGES.find((pkg2) => pkg2.name === name);
236
254
  }
237
255
  function isHeavyPackage(name) {
238
- return HEAVY_PACKAGES.some((pkg) => pkg.name === name);
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: ["node_modules/**", "dist/**", "**/*.d.ts"],
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 pkg = getPackageName2(match[1]);
341
- if (pkg) {
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 "${pkg}" prevents tree-shaking`,
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 pkg = getPackageName2(match[1]);
359
- if (pkg && isHeavyPackage(pkg)) {
360
- const heavy = findHeavyPackage(pkg);
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 "${pkg}"`,
365
- 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.`,
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: ["node_modules/**", "dist/**", "**/*.d.ts"],
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("0.1.0");
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: ["node_modules/**", "dist/**", "**/*.d.ts"],
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: ["node_modules/**", "dist/**", "**/*.d.ts"],
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":"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","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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lambda-doctor",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Diagnose and fix AWS Lambda cold start performance issues. Static analysis CLI tool.",
5
5
  "author": "Ozer Subasi (https://github.com/ozers)",
6
6
  "license": "MIT",