@node-cli/bundlecheck 1.5.0 → 1.6.0
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 +44 -8
- package/dist/bundlecheck.js +7 -3
- package/dist/bundlecheck.js.map +1 -1
- package/dist/bundler.d.ts +4 -0
- package/dist/bundler.js +4 -4
- package/dist/bundler.js.map +1 -1
- package/dist/defaults.d.ts +18 -0
- package/dist/defaults.js +42 -1
- package/dist/defaults.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/parse.d.ts +1 -0
- package/dist/parse.js +16 -1
- package/dist/parse.js.map +1 -1
- package/dist/trend.d.ts +4 -0
- package/dist/trend.js +3 -2
- package/dist/trend.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -11,12 +11,12 @@ A CLI tool to check the bundle size of npm packages, similar to [bundlephobia.co
|
|
|
11
11
|
- Interactive version selection with `--versions` flag
|
|
12
12
|
- Bundle size trend analysis with `--trend` flag (bar graph across versions)
|
|
13
13
|
- Support for checking specific exports (tree-shaking)
|
|
14
|
-
- Smart externalization of React and React-DOM (
|
|
14
|
+
- Smart externalization of React and React-DOM (including subpaths like `jsx-runtime`)
|
|
15
15
|
- Raw and gzip sizes with configurable compression level
|
|
16
16
|
- **Platform support**: target `browser` (default) or `node` with smart auto-detection
|
|
17
17
|
- Custom npm registry support (for private registries)
|
|
18
18
|
- Fast bundling using esbuild (with pnpm support)
|
|
19
|
-
- **Local caching** for faster repeated lookups (SQLite-based, max
|
|
19
|
+
- **Local caching** for faster repeated lookups (SQLite-based, max 1000 entries)
|
|
20
20
|
- **Library API** for programmatic usage in Node.js applications
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
@@ -108,6 +108,7 @@ bundlecheck lodash "debounce,throttle"
|
|
|
108
108
|
| `--registry <url>` | `-r <url>` | Custom npm registry URL (default: registry.npmjs.org) |
|
|
109
109
|
| `--platform <name>` | `-p <name>` | Target platform: `auto` (default), `browser`, or `node` |
|
|
110
110
|
| `--force` | `-f` | Bypass cache and force re-fetch/re-calculation |
|
|
111
|
+
| `--target <target>` | `-T <target>` | esbuild target (e.g., "es2022", "es2020"). Default: "es2022" |
|
|
111
112
|
|
|
112
113
|
### Examples
|
|
113
114
|
|
|
@@ -151,6 +152,9 @@ bundlecheck express # auto-detects "node" from package.json engines
|
|
|
151
152
|
|
|
152
153
|
# Bypass cache and force re-fetch
|
|
153
154
|
bundlecheck lodash --force
|
|
155
|
+
|
|
156
|
+
# Use a specific esbuild target (default: es2022)
|
|
157
|
+
bundlecheck lodash --target es2020
|
|
154
158
|
```
|
|
155
159
|
|
|
156
160
|
## Programmatic Usage (Library API)
|
|
@@ -253,6 +257,7 @@ Get bundle size statistics for a single package.
|
|
|
253
257
|
| `registry` | `string` | `undefined`| Custom npm registry URL |
|
|
254
258
|
| `platform` | `"browser" \| "node" \| "auto"` | `"auto"` | Target platform |
|
|
255
259
|
| `force` | `boolean` | `false` | Bypass cache |
|
|
260
|
+
| `target` | `string` | `"es2022"` | esbuild target (e.g., "es2022", "es2020") |
|
|
256
261
|
|
|
257
262
|
**Returns:** `Promise<BundleStats>`
|
|
258
263
|
|
|
@@ -291,6 +296,7 @@ Get bundle size trend across multiple versions.
|
|
|
291
296
|
| `registry` | `string` | `undefined`| Custom npm registry URL |
|
|
292
297
|
| `platform` | `"browser" \| "node" \| "auto"` | `"auto"` | Target platform |
|
|
293
298
|
| `force` | `boolean` | `false` | Bypass cache |
|
|
299
|
+
| `target` | `string` | `"es2022"` | esbuild target (e.g., "es2022", "es2020") |
|
|
294
300
|
|
|
295
301
|
**Returns:** `Promise<BundleTrend>`
|
|
296
302
|
|
|
@@ -406,11 +412,13 @@ clearCache(); // Clears all cached results
|
|
|
406
412
|
## How It Works
|
|
407
413
|
|
|
408
414
|
1. Creates a temporary directory
|
|
409
|
-
2. Installs the specified npm package
|
|
415
|
+
2. Installs the specified npm package (and its peer dependencies)
|
|
410
416
|
3. Creates an entry file importing the package/exports
|
|
411
417
|
4. Bundles with esbuild (minified, tree-shaken)
|
|
412
|
-
5.
|
|
413
|
-
6.
|
|
418
|
+
5. If bundling fails due to unresolved React imports, automatically adds React to externals and retries
|
|
419
|
+
6. Reports raw and gzip sizes
|
|
420
|
+
7. Caches the result for faster future lookups
|
|
421
|
+
8. Cleans up temporary files
|
|
414
422
|
|
|
415
423
|
## Platform Support
|
|
416
424
|
|
|
@@ -437,9 +445,37 @@ bundlecheck fastify -p server # "server" is an alias for "node"
|
|
|
437
445
|
|
|
438
446
|
When a package declares `react` or `react-dom` in its `dependencies` or `peerDependencies`, they are automatically marked as external (not included in the bundle size). This matches how these packages would typically be used in a real application where React is provided by the host application.
|
|
439
447
|
|
|
440
|
-
|
|
448
|
+
### Subpath externalization
|
|
449
|
+
|
|
450
|
+
When `react` is externalized, the following subpaths are also automatically externalized:
|
|
451
|
+
|
|
452
|
+
- `react/jsx-runtime`
|
|
453
|
+
- `react/jsx-dev-runtime`
|
|
454
|
+
|
|
455
|
+
When `react-dom` is externalized:
|
|
456
|
+
|
|
457
|
+
- `react-dom/client`
|
|
458
|
+
- `react-dom/server`
|
|
459
|
+
|
|
460
|
+
This ensures that modern JSX transform imports and React 18+ APIs work correctly.
|
|
461
|
+
|
|
462
|
+
### Auto-detection for improperly packaged libraries
|
|
463
|
+
|
|
464
|
+
Some npm packages import from `react` without declaring it in their `peerDependencies`. Bundlecheck automatically detects this scenario: if the initial bundle fails due to unresolved React imports, it will automatically add `react` and/or `react-dom` to externals and retry.
|
|
441
465
|
|
|
442
|
-
|
|
466
|
+
This means commands like the following work out of the box, even when the package doesn't properly declare its peer dependencies:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
bundlecheck @versini/ui-button # Works even though react is not in peerDependencies
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Disabling externals
|
|
473
|
+
|
|
474
|
+
To include all dependencies (including React when present) in the bundle size calculation, use the `--no-external` flag:
|
|
475
|
+
|
|
476
|
+
```bash
|
|
477
|
+
bundlecheck react --no-external # Include React itself in the bundle
|
|
478
|
+
```
|
|
443
479
|
|
|
444
480
|
## Custom Registry
|
|
445
481
|
|
|
@@ -463,7 +499,7 @@ Bundle size results are cached locally to speed up repeated lookups. The cache i
|
|
|
463
499
|
### How it works
|
|
464
500
|
|
|
465
501
|
- Results are cached based on: package name, version, exports, platform, gzip level, and externals configuration
|
|
466
|
-
- The cache holds up to **
|
|
502
|
+
- The cache holds up to **1000 entries** (least recently used entries are evicted first)
|
|
467
503
|
- When you check a package, the CLI first looks for a cached result with matching parameters
|
|
468
504
|
|
|
469
505
|
### Smart version matching
|
package/dist/bundlecheck.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import kleur from "kleur";
|
|
4
4
|
import { checkBundleSize, formatBytes, getExternals, parsePackageSpecifier } from "./bundler.js";
|
|
5
5
|
import { getCachedResult, normalizeCacheKey, setCachedResult } from "./cache.js";
|
|
6
|
-
import { normalizePlatform, TREND_VERSION_COUNT } from "./defaults.js";
|
|
6
|
+
import { normalizePlatform, normalizeTarget, TREND_VERSION_COUNT } from "./defaults.js";
|
|
7
7
|
import { config } from "./parse.js";
|
|
8
8
|
import { analyzeTrend, renderTrendGraph, selectTrendVersions } from "./trend.js";
|
|
9
9
|
import { fetchPackageVersions, promptForVersion } from "./versions.js";
|
|
@@ -65,6 +65,8 @@ async function main() {
|
|
|
65
65
|
}
|
|
66
66
|
// Normalize platform from flag (handles aliases like "web" → "browser").
|
|
67
67
|
const platform = normalizePlatform(flags?.platform);
|
|
68
|
+
// Normalize target (e.g., lowercase).
|
|
69
|
+
const target = normalizeTarget(flags?.target);
|
|
68
70
|
/**
|
|
69
71
|
* If --trend flag is set, show bundle size trend across versions --trend alone
|
|
70
72
|
* uses default (5), --trend N uses N versions.
|
|
@@ -99,7 +101,8 @@ async function main() {
|
|
|
99
101
|
boring: flags?.boring,
|
|
100
102
|
registry: flags?.registry,
|
|
101
103
|
platform,
|
|
102
|
-
force: flags?.force
|
|
104
|
+
force: flags?.force,
|
|
105
|
+
target
|
|
103
106
|
});
|
|
104
107
|
if (results.length === 0) {
|
|
105
108
|
log.error("Failed to analyze any versions");
|
|
@@ -187,7 +190,8 @@ async function main() {
|
|
|
187
190
|
noExternal: flags?.noExternal,
|
|
188
191
|
gzipLevel: flags?.gzipLevel,
|
|
189
192
|
registry: flags?.registry,
|
|
190
|
-
platform
|
|
193
|
+
platform,
|
|
194
|
+
target
|
|
191
195
|
});
|
|
192
196
|
// Store result in cache.
|
|
193
197
|
setCachedResult(cacheKey, result);
|
package/dist/bundlecheck.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bundlecheck.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/* istanbul ignore file */\n\nimport { Logger } from \"@node-cli/logger\";\nimport kleur from \"kleur\";\nimport {\n\tcheckBundleSize,\n\tformatBytes,\n\tgetExternals,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport { normalizePlatform, TREND_VERSION_COUNT } from \"./defaults.js\";\nimport { config } from \"./parse.js\";\nimport {\n\tanalyzeTrend,\n\trenderTrendGraph,\n\tselectTrendVersions,\n} from \"./trend.js\";\nimport { fetchPackageVersions, promptForVersion } from \"./versions.js\";\n\nconst flags = config.flags;\nconst parameters = config.parameters;\n\n// Disable kleur colors when --boring flag is set.\nkleur.enabled = !flags?.boring;\n\nconst log = new Logger({\n\tboring: flags?.boring,\n});\n\n/**\n * Display bundle result in a formatted box.\n */\nfunction displayResult(\n\tresult: {\n\t\tpackageName: string;\n\t\tpackageVersion: string;\n\t\texports: string[];\n\t\trawSize: number;\n\t\tgzipSize: number | null;\n\t\tgzipLevel: number;\n\t\texternals: string[];\n\t\tdependencies: string[];\n\t\tplatform: \"browser\" | \"node\";\n\t\tnamedExportCount: number;\n\t},\n\tisAutoDetected: boolean,\n): void {\n\tconst blue = kleur.blue;\n\tconst green = kleur.green;\n\n\tconst platformLabel = result.platform === \"node\" ? \"node\" : \"browser\";\n\tconst platformNote = isAutoDetected ? \" (auto-detected)\" : \"\";\n\n\t// Format exports display.\n\tlet exportsDisplay: string;\n\tif (result.exports.length > 0) {\n\t\texportsDisplay = `{ ${result.exports.join(\", \")} }`;\n\t} else if (result.namedExportCount > 0) {\n\t\texportsDisplay = `${result.namedExportCount} named exports (entire package)`;\n\t} else {\n\t\texportsDisplay = \"* (entire package)\";\n\t}\n\n\tlog.printBox(\n\t\t[\n\t\t\t`${blue(\"Package:\")} ${result.packageName} (${blue(\"version:\")} ${result.packageVersion})`,\n\t\t\t`${blue(\"Exports:\")} ${exportsDisplay}`,\n\t\t\t\"\",\n\t\t\t`${blue(\"Raw size:\")} ${formatBytes(result.rawSize)}`,\n\t\t\tresult.gzipSize !== null\n\t\t\t\t? `${blue(\"Gzip size:\")} ${formatBytes(result.gzipSize)} (level ${result.gzipLevel})`\n\t\t\t\t: `${blue(\"Gzip size:\")} N/A (not applicable for node platform)`,\n\t\t\t\"\",\n\t\t\tresult.externals.length > 0\n\t\t\t\t? `${blue(\"Externals:\")} ${result.externals.join(\", \")}`\n\t\t\t\t: `${blue(\"Externals:\")} ${green(\"none\")}`,\n\t\t\tresult.dependencies.length > 0\n\t\t\t\t? `${blue(\"Dependencies:\")} ${result.dependencies.join(\", \")}`\n\t\t\t\t: `${blue(\"Dependencies:\")} ${green(\"none\")}`,\n\t\t\t`${blue(\"Platform:\")} ${platformLabel}${platformNote}`,\n\t\t],\n\t\t{\n\t\t\tborderStyle: \"round\",\n\t\t\talign: \"left\",\n\t\t},\n\t);\n}\n\nasync function main() {\n\tlet packageName = parameters?.[\"0\"];\n\n\tif (!packageName) {\n\t\tlog.error(\"Package name is required\");\n\t\tconfig.showHelp?.();\n\t\tprocess.exit(1);\n\t}\n\n\t// Parse additional externals if provided (comma-separated).\n\tlet additionalExternals: string[] | undefined;\n\tif (flags?.external) {\n\t\tadditionalExternals = flags.external\n\t\t\t.split(\",\")\n\t\t\t.map((e) => e.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\t// Parse exports if provided (comma-separated).\n\tlet exports: string[] | undefined;\n\tconst exportsArg = parameters?.[\"1\"];\n\tif (exportsArg) {\n\t\texports = exportsArg\n\t\t\t.split(\",\")\n\t\t\t.map((e) => e.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\t// Normalize platform from flag (handles aliases like \"web\" → \"browser\").\n\tconst platform = normalizePlatform(flags?.platform);\n\n\t/**\n\t * If --trend flag is set, show bundle size trend across versions --trend alone\n\t * uses default (5), --trend N uses N versions.\n\t */\n\tconst trendValue = flags?.trend;\n\tif (trendValue !== undefined) {\n\t\tconst parsedCount = Number.parseInt(trendValue, 10);\n\t\tconst versionCount =\n\t\t\t!Number.isNaN(parsedCount) && parsedCount > 0\n\t\t\t\t? parsedCount\n\t\t\t\t: TREND_VERSION_COUNT;\n\n\t\ttry {\n\t\t\tconst { name, subpath } = parsePackageSpecifier(packageName);\n\t\t\t// Construct the full package path including subpath if present.\n\t\t\tconst fullPackagePath = subpath ? `${name}/${subpath}` : name;\n\n\t\t\tlog.info(`\\nFetching available versions for ${name}...`);\n\n\t\t\tconst { versions } = await fetchPackageVersions({\n\t\t\t\tpackageName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\n\t\t\tif (versions.length === 0) {\n\t\t\t\tlog.error(\"No versions found for this package\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Select versions for trend.\n\t\t\tconst trendVersions = selectTrendVersions(versions, versionCount);\n\n\t\t\tlog.info(\n\t\t\t\t`Analyzing ${trendVersions.length} versions: ${trendVersions.join(\", \")}`,\n\t\t\t);\n\t\t\tlog.info(\"\");\n\n\t\t\tconst results = await analyzeTrend({\n\t\t\t\tpackageName: fullPackagePath,\n\t\t\t\tversions: trendVersions,\n\t\t\t\texports,\n\t\t\t\tadditionalExternals,\n\t\t\t\tnoExternal: flags?.noExternal,\n\t\t\t\tgzipLevel: flags?.gzipLevel,\n\t\t\t\tboring: flags?.boring,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t\tplatform,\n\t\t\t\tforce: flags?.force,\n\t\t\t});\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tlog.error(\"Failed to analyze any versions\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Render and display the trend graph.\n\t\t\tconst graphLines = renderTrendGraph(\n\t\t\t\tfullPackagePath,\n\t\t\t\tresults,\n\t\t\t\tflags?.boring,\n\t\t\t);\n\t\t\tfor (const line of graphLines) {\n\t\t\t\tlog.log(line);\n\t\t\t}\n\n\t\t\tprocess.exit(0);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tlog.error(`Failed to analyze trend: ${errorMessage}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t// If --versions flag is set, fetch and prompt for version selection.\n\tif (flags?.versions) {\n\t\ttry {\n\t\t\tconst { name, subpath } = parsePackageSpecifier(packageName);\n\t\t\tlog.info(`\\nFetching available versions for ${name}...`);\n\n\t\t\tconst { versions, tags } = await fetchPackageVersions({\n\t\t\t\tpackageName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\n\t\t\tif (versions.length === 0) {\n\t\t\t\tlog.error(\"No versions found for this package\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst selectedVersion = await promptForVersion(name, versions, tags);\n\t\t\t// Rebuild specifier preserving any subpath.\n\t\t\tpackageName = subpath\n\t\t\t\t? `${name}/${subpath}@${selectedVersion}`\n\t\t\t\t: `${name}@${selectedVersion}`;\n\t\t\tlog.info(`\\nSelected: ${packageName}`);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tlog.error(`Failed to fetch versions: ${errorMessage}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tlog.info(`\\nAnalyzing bundle size for: ${packageName}`);\n\tif (exports && exports.length > 0) {\n\t\tlog.info(`Exports: { ${exports.join(\", \")} }`);\n\t}\n\n\ttry {\n\t\t// Parse package specifier to get name and version.\n\t\tconst { name: baseName, version: requestedVersion } =\n\t\t\tparsePackageSpecifier(packageName);\n\n\t\t// Resolve \"latest\" to actual version for cache key.\n\t\tlet resolvedVersion = requestedVersion;\n\t\tif (requestedVersion === \"latest\") {\n\t\t\tconst { tags } = await fetchPackageVersions({\n\t\t\t\tpackageName: baseName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\t\t\tresolvedVersion = tags.latest || requestedVersion;\n\t\t}\n\n\t\t// Compute externals for cache key (same logic as bundler).\n\t\tconst externals = getExternals(\n\t\t\tbaseName,\n\t\t\tadditionalExternals,\n\t\t\tflags?.noExternal,\n\t\t);\n\n\t\t/**\n\t\t * Build cache key.\n\t\t * NOTE: platform can be undefined (auto-detect), which is stored as \"auto\" in cache.\n\t\t */\n\t\tconst cacheKey = normalizeCacheKey({\n\t\t\tpackageName: baseName,\n\t\t\tversion: resolvedVersion,\n\t\t\texports,\n\t\t\tplatform,\n\t\t\tgzipLevel: flags?.gzipLevel ?? 5,\n\t\t\texternals,\n\t\t\tnoExternal: flags?.noExternal ?? false,\n\t\t});\n\n\t\t// Check cache (unless --force flag is set).\n\t\tif (!flags?.force) {\n\t\t\tconst cached = getCachedResult(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tlog.info(\"NOTE: Using cached results\\n\");\n\t\t\t\tdisplayResult(cached, platform === undefined);\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t}\n\n\t\tlog.info(\"Please wait, installing and bundling...\\n\");\n\n\t\tconst result = await checkBundleSize({\n\t\t\tpackageName,\n\t\t\texports,\n\t\t\tadditionalExternals,\n\t\t\tnoExternal: flags?.noExternal,\n\t\t\tgzipLevel: flags?.gzipLevel,\n\t\t\tregistry: flags?.registry,\n\t\t\tplatform,\n\t\t});\n\n\t\t// Store result in cache.\n\t\tsetCachedResult(cacheKey, result);\n\n\t\tdisplayResult(result, platform === undefined);\n\n\t\tprocess.exit(0);\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tlog.error(`Failed to analyze bundle size: ${errorMessage}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nmain();\n"],"names":["Logger","kleur","checkBundleSize","formatBytes","getExternals","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","normalizePlatform","TREND_VERSION_COUNT","config","analyzeTrend","renderTrendGraph","selectTrendVersions","fetchPackageVersions","promptForVersion","flags","parameters","enabled","boring","log","displayResult","result","isAutoDetected","blue","green","platformLabel","platform","platformNote","exportsDisplay","exports","length","join","namedExportCount","printBox","packageName","packageVersion","rawSize","gzipSize","gzipLevel","externals","dependencies","borderStyle","align","main","error","showHelp","process","exit","additionalExternals","external","split","map","e","trim","filter","Boolean","exportsArg","trendValue","trend","undefined","parsedCount","Number","parseInt","versionCount","isNaN","name","subpath","fullPackagePath","info","versions","registry","trendVersions","results","noExternal","force","graphLines","line","errorMessage","Error","message","String","tags","selectedVersion","baseName","version","requestedVersion","resolvedVersion","latest","cacheKey","cached"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/bundlecheck.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/* istanbul ignore file */\n\nimport { Logger } from \"@node-cli/logger\";\nimport kleur from \"kleur\";\nimport {\n\tcheckBundleSize,\n\tformatBytes,\n\tgetExternals,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport {\n\tnormalizePlatform,\n\tnormalizeTarget,\n\tTREND_VERSION_COUNT,\n} from \"./defaults.js\";\nimport { config } from \"./parse.js\";\nimport {\n\tanalyzeTrend,\n\trenderTrendGraph,\n\tselectTrendVersions,\n} from \"./trend.js\";\nimport { fetchPackageVersions, promptForVersion } from \"./versions.js\";\n\nconst flags = config.flags;\nconst parameters = config.parameters;\n\n// Disable kleur colors when --boring flag is set.\nkleur.enabled = !flags?.boring;\n\nconst log = new Logger({\n\tboring: flags?.boring,\n});\n\n/**\n * Display bundle result in a formatted box.\n */\nfunction displayResult(\n\tresult: {\n\t\tpackageName: string;\n\t\tpackageVersion: string;\n\t\texports: string[];\n\t\trawSize: number;\n\t\tgzipSize: number | null;\n\t\tgzipLevel: number;\n\t\texternals: string[];\n\t\tdependencies: string[];\n\t\tplatform: \"browser\" | \"node\";\n\t\tnamedExportCount: number;\n\t},\n\tisAutoDetected: boolean,\n): void {\n\tconst blue = kleur.blue;\n\tconst green = kleur.green;\n\n\tconst platformLabel = result.platform === \"node\" ? \"node\" : \"browser\";\n\tconst platformNote = isAutoDetected ? \" (auto-detected)\" : \"\";\n\n\t// Format exports display.\n\tlet exportsDisplay: string;\n\tif (result.exports.length > 0) {\n\t\texportsDisplay = `{ ${result.exports.join(\", \")} }`;\n\t} else if (result.namedExportCount > 0) {\n\t\texportsDisplay = `${result.namedExportCount} named exports (entire package)`;\n\t} else {\n\t\texportsDisplay = \"* (entire package)\";\n\t}\n\n\tlog.printBox(\n\t\t[\n\t\t\t`${blue(\"Package:\")} ${result.packageName} (${blue(\"version:\")} ${result.packageVersion})`,\n\t\t\t`${blue(\"Exports:\")} ${exportsDisplay}`,\n\t\t\t\"\",\n\t\t\t`${blue(\"Raw size:\")} ${formatBytes(result.rawSize)}`,\n\t\t\tresult.gzipSize !== null\n\t\t\t\t? `${blue(\"Gzip size:\")} ${formatBytes(result.gzipSize)} (level ${result.gzipLevel})`\n\t\t\t\t: `${blue(\"Gzip size:\")} N/A (not applicable for node platform)`,\n\t\t\t\"\",\n\t\t\tresult.externals.length > 0\n\t\t\t\t? `${blue(\"Externals:\")} ${result.externals.join(\", \")}`\n\t\t\t\t: `${blue(\"Externals:\")} ${green(\"none\")}`,\n\t\t\tresult.dependencies.length > 0\n\t\t\t\t? `${blue(\"Dependencies:\")} ${result.dependencies.join(\", \")}`\n\t\t\t\t: `${blue(\"Dependencies:\")} ${green(\"none\")}`,\n\t\t\t`${blue(\"Platform:\")} ${platformLabel}${platformNote}`,\n\t\t],\n\t\t{\n\t\t\tborderStyle: \"round\",\n\t\t\talign: \"left\",\n\t\t},\n\t);\n}\n\nasync function main() {\n\tlet packageName = parameters?.[\"0\"];\n\n\tif (!packageName) {\n\t\tlog.error(\"Package name is required\");\n\t\tconfig.showHelp?.();\n\t\tprocess.exit(1);\n\t}\n\n\t// Parse additional externals if provided (comma-separated).\n\tlet additionalExternals: string[] | undefined;\n\tif (flags?.external) {\n\t\tadditionalExternals = flags.external\n\t\t\t.split(\",\")\n\t\t\t.map((e) => e.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\t// Parse exports if provided (comma-separated).\n\tlet exports: string[] | undefined;\n\tconst exportsArg = parameters?.[\"1\"];\n\tif (exportsArg) {\n\t\texports = exportsArg\n\t\t\t.split(\",\")\n\t\t\t.map((e) => e.trim())\n\t\t\t.filter(Boolean);\n\t}\n\n\t// Normalize platform from flag (handles aliases like \"web\" → \"browser\").\n\tconst platform = normalizePlatform(flags?.platform);\n\n\t// Normalize target (e.g., lowercase).\n\tconst target = normalizeTarget(flags?.target);\n\n\t/**\n\t * If --trend flag is set, show bundle size trend across versions --trend alone\n\t * uses default (5), --trend N uses N versions.\n\t */\n\tconst trendValue = flags?.trend;\n\tif (trendValue !== undefined) {\n\t\tconst parsedCount = Number.parseInt(trendValue, 10);\n\t\tconst versionCount =\n\t\t\t!Number.isNaN(parsedCount) && parsedCount > 0\n\t\t\t\t? parsedCount\n\t\t\t\t: TREND_VERSION_COUNT;\n\n\t\ttry {\n\t\t\tconst { name, subpath } = parsePackageSpecifier(packageName);\n\t\t\t// Construct the full package path including subpath if present.\n\t\t\tconst fullPackagePath = subpath ? `${name}/${subpath}` : name;\n\n\t\t\tlog.info(`\\nFetching available versions for ${name}...`);\n\n\t\t\tconst { versions } = await fetchPackageVersions({\n\t\t\t\tpackageName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\n\t\t\tif (versions.length === 0) {\n\t\t\t\tlog.error(\"No versions found for this package\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Select versions for trend.\n\t\t\tconst trendVersions = selectTrendVersions(versions, versionCount);\n\n\t\t\tlog.info(\n\t\t\t\t`Analyzing ${trendVersions.length} versions: ${trendVersions.join(\", \")}`,\n\t\t\t);\n\t\t\tlog.info(\"\");\n\n\t\t\tconst results = await analyzeTrend({\n\t\t\t\tpackageName: fullPackagePath,\n\t\t\t\tversions: trendVersions,\n\t\t\t\texports,\n\t\t\t\tadditionalExternals,\n\t\t\t\tnoExternal: flags?.noExternal,\n\t\t\t\tgzipLevel: flags?.gzipLevel,\n\t\t\t\tboring: flags?.boring,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t\tplatform,\n\t\t\t\tforce: flags?.force,\n\t\t\t\ttarget,\n\t\t\t});\n\n\t\t\tif (results.length === 0) {\n\t\t\t\tlog.error(\"Failed to analyze any versions\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\t// Render and display the trend graph.\n\t\t\tconst graphLines = renderTrendGraph(\n\t\t\t\tfullPackagePath,\n\t\t\t\tresults,\n\t\t\t\tflags?.boring,\n\t\t\t);\n\t\t\tfor (const line of graphLines) {\n\t\t\t\tlog.log(line);\n\t\t\t}\n\n\t\t\tprocess.exit(0);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tlog.error(`Failed to analyze trend: ${errorMessage}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\t// If --versions flag is set, fetch and prompt for version selection.\n\tif (flags?.versions) {\n\t\ttry {\n\t\t\tconst { name, subpath } = parsePackageSpecifier(packageName);\n\t\t\tlog.info(`\\nFetching available versions for ${name}...`);\n\n\t\t\tconst { versions, tags } = await fetchPackageVersions({\n\t\t\t\tpackageName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\n\t\t\tif (versions.length === 0) {\n\t\t\t\tlog.error(\"No versions found for this package\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tconst selectedVersion = await promptForVersion(name, versions, tags);\n\t\t\t// Rebuild specifier preserving any subpath.\n\t\t\tpackageName = subpath\n\t\t\t\t? `${name}/${subpath}@${selectedVersion}`\n\t\t\t\t: `${name}@${selectedVersion}`;\n\t\t\tlog.info(`\\nSelected: ${packageName}`);\n\t\t} catch (error) {\n\t\t\tconst errorMessage =\n\t\t\t\terror instanceof Error ? error.message : String(error);\n\t\t\tlog.error(`Failed to fetch versions: ${errorMessage}`);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tlog.info(`\\nAnalyzing bundle size for: ${packageName}`);\n\tif (exports && exports.length > 0) {\n\t\tlog.info(`Exports: { ${exports.join(\", \")} }`);\n\t}\n\n\ttry {\n\t\t// Parse package specifier to get name and version.\n\t\tconst { name: baseName, version: requestedVersion } =\n\t\t\tparsePackageSpecifier(packageName);\n\n\t\t// Resolve \"latest\" to actual version for cache key.\n\t\tlet resolvedVersion = requestedVersion;\n\t\tif (requestedVersion === \"latest\") {\n\t\t\tconst { tags } = await fetchPackageVersions({\n\t\t\t\tpackageName: baseName,\n\t\t\t\tregistry: flags?.registry,\n\t\t\t});\n\t\t\tresolvedVersion = tags.latest || requestedVersion;\n\t\t}\n\n\t\t// Compute externals for cache key (same logic as bundler).\n\t\tconst externals = getExternals(\n\t\t\tbaseName,\n\t\t\tadditionalExternals,\n\t\t\tflags?.noExternal,\n\t\t);\n\n\t\t/**\n\t\t * Build cache key.\n\t\t * NOTE: platform can be undefined (auto-detect), which is stored as \"auto\" in cache.\n\t\t */\n\t\tconst cacheKey = normalizeCacheKey({\n\t\t\tpackageName: baseName,\n\t\t\tversion: resolvedVersion,\n\t\t\texports,\n\t\t\tplatform,\n\t\t\tgzipLevel: flags?.gzipLevel ?? 5,\n\t\t\texternals,\n\t\t\tnoExternal: flags?.noExternal ?? false,\n\t\t});\n\n\t\t// Check cache (unless --force flag is set).\n\t\tif (!flags?.force) {\n\t\t\tconst cached = getCachedResult(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tlog.info(\"NOTE: Using cached results\\n\");\n\t\t\t\tdisplayResult(cached, platform === undefined);\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t}\n\n\t\tlog.info(\"Please wait, installing and bundling...\\n\");\n\n\t\tconst result = await checkBundleSize({\n\t\t\tpackageName,\n\t\t\texports,\n\t\t\tadditionalExternals,\n\t\t\tnoExternal: flags?.noExternal,\n\t\t\tgzipLevel: flags?.gzipLevel,\n\t\t\tregistry: flags?.registry,\n\t\t\tplatform,\n\t\t\ttarget,\n\t\t});\n\n\t\t// Store result in cache.\n\t\tsetCachedResult(cacheKey, result);\n\n\t\tdisplayResult(result, platform === undefined);\n\n\t\tprocess.exit(0);\n\t} catch (error) {\n\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\tlog.error(`Failed to analyze bundle size: ${errorMessage}`);\n\t\tprocess.exit(1);\n\t}\n}\n\nmain();\n"],"names":["Logger","kleur","checkBundleSize","formatBytes","getExternals","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","normalizePlatform","normalizeTarget","TREND_VERSION_COUNT","config","analyzeTrend","renderTrendGraph","selectTrendVersions","fetchPackageVersions","promptForVersion","flags","parameters","enabled","boring","log","displayResult","result","isAutoDetected","blue","green","platformLabel","platform","platformNote","exportsDisplay","exports","length","join","namedExportCount","printBox","packageName","packageVersion","rawSize","gzipSize","gzipLevel","externals","dependencies","borderStyle","align","main","error","showHelp","process","exit","additionalExternals","external","split","map","e","trim","filter","Boolean","exportsArg","target","trendValue","trend","undefined","parsedCount","Number","parseInt","versionCount","isNaN","name","subpath","fullPackagePath","info","versions","registry","trendVersions","results","noExternal","force","graphLines","line","errorMessage","Error","message","String","tags","selectedVersion","baseName","version","requestedVersion","resolvedVersion","latest","cacheKey","cached"],"mappings":"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"}
|
package/dist/bundler.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type BundleOptions = {
|
|
|
23
23
|
* Target platform. If undefined, auto-detects from package.json engines.
|
|
24
24
|
*/
|
|
25
25
|
platform?: "browser" | "node";
|
|
26
|
+
/**
|
|
27
|
+
* esbuild target (e.g., "es2022", "es2020"). Defaults to "es2022".
|
|
28
|
+
*/
|
|
29
|
+
target?: string;
|
|
26
30
|
};
|
|
27
31
|
export type BundleResult = {
|
|
28
32
|
packageName: string;
|
package/dist/bundler.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { promisify } from "node:util";
|
|
6
6
|
import zlib from "node:zlib";
|
|
7
7
|
import * as esbuild from "esbuild";
|
|
8
|
-
import { DEFAULT_EXTERNALS, EXTERNAL_SUBPATHS } from "./defaults.js";
|
|
8
|
+
import { DEFAULT_EXTERNALS, DEFAULT_TARGET, EXTERNAL_SUBPATHS } from "./defaults.js";
|
|
9
9
|
import { getNamedExports } from "./exports.js";
|
|
10
10
|
const gzipAsync = promisify(zlib.gzip);
|
|
11
11
|
/**
|
|
@@ -446,7 +446,7 @@ let usePnpm = null;
|
|
|
446
446
|
/**
|
|
447
447
|
* Check the bundle size of an npm package.
|
|
448
448
|
*/ export async function checkBundleSize(options) {
|
|
449
|
-
const { packageName: packageSpecifier, exports, additionalExternals, noExternal, gzipLevel = 5, registry, platform: explicitPlatform } = options;
|
|
449
|
+
const { packageName: packageSpecifier, exports, additionalExternals, noExternal, gzipLevel = 5, registry, platform: explicitPlatform, target = DEFAULT_TARGET } = options;
|
|
450
450
|
// Parse the package specifier to extract name, version, and subpath.
|
|
451
451
|
const { name: packageName, version: requestedVersion, subpath } = parsePackageSpecifier(packageSpecifier);
|
|
452
452
|
const tmpDir = createTempDir();
|
|
@@ -559,7 +559,7 @@ let usePnpm = null;
|
|
|
559
559
|
write: false,
|
|
560
560
|
format: "esm",
|
|
561
561
|
platform,
|
|
562
|
-
target
|
|
562
|
+
target,
|
|
563
563
|
minify: true,
|
|
564
564
|
treeShaking: true,
|
|
565
565
|
external: esbuildExternals,
|
|
@@ -595,7 +595,7 @@ let usePnpm = null;
|
|
|
595
595
|
write: false,
|
|
596
596
|
format: "esm",
|
|
597
597
|
platform,
|
|
598
|
-
target
|
|
598
|
+
target,
|
|
599
599
|
minify: true,
|
|
600
600
|
treeShaking: true,
|
|
601
601
|
external: esbuildExternals,
|
package/dist/bundler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/bundler.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport zlib from \"node:zlib\";\nimport * as esbuild from \"esbuild\";\nimport { DEFAULT_EXTERNALS, EXTERNAL_SUBPATHS } from \"./defaults.js\";\nimport { getNamedExports } from \"./exports.js\";\n\nconst gzipAsync = promisify(zlib.gzip);\n\n/**\n * Escape special regex characters in a string.\n */\nfunction escapeRegExp(str: string): string {\n\treturn str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport type ParsedPackage = {\n\tname: string;\n\tversion: string;\n\tsubpath?: string;\n};\n\n/**\n * Parse a package specifier to extract name, version, and subpath.\n * Handles:\n * - @scope/package@1.0.0\n * - @scope/package/subpath@1.0.0\n * - @scope/package/subpath\n * - package/subpath@1.0.0\n */\nexport function parsePackageSpecifier(specifier: string): ParsedPackage {\n\tlet workingSpec = specifier;\n\tlet version = \"latest\";\n\n\t// Handle scoped packages (@scope/name...)\n\tif (workingSpec.startsWith(\"@\")) {\n\t\t// Find the second @ which would separate version.\n\t\tconst secondAtIndex = workingSpec.indexOf(\"@\", 1);\n\t\tif (secondAtIndex !== -1) {\n\t\t\tversion = workingSpec.substring(secondAtIndex + 1);\n\t\t\tworkingSpec = workingSpec.substring(0, secondAtIndex);\n\t\t}\n\n\t\t/**\n\t\t * Now workingSpec is like @scope/name or @scope/name/subpath Split by / and\n\t\t * check if there are more than 2 parts.\n\t\t */\n\t\tconst parts = workingSpec.split(\"/\");\n\t\tif (parts.length > 2) {\n\t\t\t// Has subpath: @scope/name/subpath/more.\n\t\t\tconst name = `${parts[0]}/${parts[1]}`;\n\t\t\tconst subpath = parts.slice(2).join(\"/\");\n\t\t\treturn { name, version, subpath };\n\t\t}\n\t\t// No subpath: @scope/name.\n\t\treturn { name: workingSpec, version };\n\t}\n\n\t// Handle non-scoped packages (name@version or name/subpath@version).\n\tconst atIndex = workingSpec.indexOf(\"@\");\n\tif (atIndex !== -1) {\n\t\tversion = workingSpec.substring(atIndex + 1);\n\t\tworkingSpec = workingSpec.substring(0, atIndex);\n\t}\n\n\t// Check for subpath in non-scoped packages.\n\tconst slashIndex = workingSpec.indexOf(\"/\");\n\tif (slashIndex !== -1) {\n\t\tconst name = workingSpec.substring(0, slashIndex);\n\t\tconst subpath = workingSpec.substring(slashIndex + 1);\n\t\treturn { name, version, subpath };\n\t}\n\n\treturn { name: workingSpec, version };\n}\n\nexport type BundleOptions = {\n\tpackageName: string;\n\texports?: string[];\n\tadditionalExternals?: string[];\n\tnoExternal?: boolean;\n\tgzipLevel?: number;\n\tregistry?: string;\n\t/**\n\t * Target platform. If undefined, auto-detects from package.json engines.\n\t */\n\tplatform?: \"browser\" | \"node\";\n};\n\nexport type BundleResult = {\n\tpackageName: string;\n\tpackageVersion: string;\n\texports: string[];\n\trawSize: number;\n\t/**\n\t * Gzip size in bytes, or null for node platform (gzip not applicable).\n\t */\n\tgzipSize: number | null;\n\tgzipLevel: number;\n\texternals: string[];\n\tdependencies: string[];\n\tplatform: \"browser\" | \"node\";\n\t/**\n\t * Total number of named exports in the package (when analyzing entire\n\t * package).\n\t */\n\tnamedExportCount: number;\n};\n\n/**\n * Format bytes to human-readable string.\n */\nexport function formatBytes(bytes: number): string {\n\tif (bytes === 0) {\n\t\treturn \"0 B\";\n\t}\n\tconst k = 1024;\n\tconst sizes = [\"B\", \"kB\", \"MB\", \"GB\"];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\treturn `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;\n}\n\n/**\n * Create a temporary directory for bundling.\n */\nfunction createTempDir(): string {\n\tconst tmpDir = path.join(os.tmpdir(), `bundlecheck-${Date.now()}`);\n\tfs.mkdirSync(tmpDir, { recursive: true });\n\treturn tmpDir;\n}\n\n/**\n * Clean up temporary directory.\n */\nfunction cleanupTempDir(tmpDir: string): void {\n\ttry {\n\t\tfs.rmSync(tmpDir, { recursive: true, force: true });\n\t} catch {\n\t\t// Ignore cleanup errors.\n\t}\n}\n\n/**\n * Check if pnpm is available.\n */\nfunction isPnpmAvailable(): boolean {\n\ttry {\n\t\texecSync(\"pnpm --version\", { stdio: \"pipe\" });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// Cache the result of pnpm availability check.\nlet usePnpm: boolean | null = null;\n\n/**\n * Validate and sanitize a registry URL to prevent command injection.\n * @param registry - The registry URL to validate\n * @returns The sanitized URL or undefined if invalid\n * @throws Error if the URL is invalid or contains potentially malicious characters\n */\nfunction validateRegistryUrl(registry: string): string {\n\t// Parse as URL to validate format.\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(registry);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Invalid registry URL: ${registry}. Must be a valid URL (e.g., https://registry.example.com)`,\n\t\t);\n\t}\n\n\t// Only allow http and https protocols.\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\n\t\t\t`Invalid registry URL protocol: ${url.protocol}. Only http: and https: are allowed`,\n\t\t);\n\t}\n\n\t// Return the sanitized URL (URL constructor normalizes it).\n\treturn url.toString();\n}\n\n/**\n * Get the install command (pnpm preferred, npm fallback).\n * @param registry - Optional custom npm registry URL\n */\nfunction getInstallCommand(registry?: string): string {\n\tif (usePnpm === null) {\n\t\tusePnpm = isPnpmAvailable();\n\t}\n\n\tlet registryArg = \"\";\n\tif (registry) {\n\t\t// Validate and sanitize the registry URL to prevent command injection.\n\t\tconst sanitizedRegistry = validateRegistryUrl(registry);\n\t\t// Quote the URL to handle any special characters safely.\n\t\tregistryArg = ` --registry \"${sanitizedRegistry}\"`;\n\t}\n\n\tif (usePnpm) {\n\t\treturn `pnpm install --ignore-scripts --no-frozen-lockfile${registryArg}`;\n\t}\n\treturn `npm install --legacy-peer-deps --ignore-scripts${registryArg}`;\n}\n\nexport type EntryContentOptions = {\n\tpackageName: string;\n\tsubpath?: string;\n\texports?: string[];\n\tallSubpaths?: string[];\n\texportToSubpath?: Map<string, string>;\n};\n\n/**\n * Generate the entry file content based on package, subpath, and exports.\n */\nfunction generateEntryContent(options: EntryContentOptions): string {\n\tconst { packageName, subpath, exports, allSubpaths, exportToSubpath } =\n\t\toptions;\n\n\t// If we have exports mapped to different subpaths.\n\tif (exportToSubpath && exportToSubpath.size > 0) {\n\t\t// Group exports by subpath.\n\t\tconst subpathToExports = new Map<string, string[]>();\n\t\tfor (const [exportName, sp] of exportToSubpath) {\n\t\t\tconst existing = subpathToExports.get(sp) || [];\n\t\t\texisting.push(exportName);\n\t\t\tsubpathToExports.set(sp, existing);\n\t\t}\n\n\t\t// Generate imports for each subpath.\n\t\tconst lines: string[] = [];\n\t\tconst allExportNames: string[] = [];\n\n\t\tfor (const [sp, exportNames] of subpathToExports) {\n\t\t\tconst importPath = `${packageName}/${sp}`;\n\t\t\tconst names = exportNames.join(\", \");\n\t\t\tlines.push(`import { ${names} } from \"${importPath}\";`);\n\t\t\tallExportNames.push(...exportNames);\n\t\t}\n\n\t\tlines.push(`export { ${allExportNames.join(\", \")} };`);\n\t\treturn lines.join(\"\\n\") + \"\\n\";\n\t}\n\n\t// If we have specific exports to import.\n\tif (exports && exports.length > 0) {\n\t\t// Determine the import path.\n\t\tconst importPath = subpath ? `${packageName}/${subpath}` : packageName;\n\t\tconst importNames = exports.join(\", \");\n\t\treturn `import { ${importNames} } from \"${importPath}\";\\nexport { ${importNames} };\\n`;\n\t}\n\n\t// If we have a specific subpath (but no specific exports).\n\tif (subpath) {\n\t\tconst importPath = `${packageName}/${subpath}`;\n\t\treturn `import * as pkg from \"${importPath}\";\\nexport default pkg;\\n`;\n\t}\n\n\t// If package has subpath exports only (no main entry), import all subpaths.\n\tif (allSubpaths && allSubpaths.length > 0) {\n\t\tconst imports = allSubpaths\n\t\t\t.map(\n\t\t\t\t(sp, i) =>\n\t\t\t\t\t`import * as sub${i} from \"${packageName}/${sp}\";\\nexport { sub${i} };`,\n\t\t\t)\n\t\t\t.join(\"\\n\");\n\t\treturn imports + \"\\n\";\n\t}\n\n\t// Default: import everything from main entry.\n\treturn `import * as pkg from \"${packageName}\";\\nexport default pkg;\\n`;\n}\n\n/**\n * Check if an error is an esbuild BuildFailure. BuildFailure has an `errors`\n * array with structured error objects.\n */\nfunction isEsbuildBuildFailure(\n\terror: unknown,\n): error is { errors: Array<{ text: string; location?: unknown }> } {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"errors\" in error &&\n\t\tArray.isArray((error as { errors: unknown }).errors)\n\t);\n}\n\n/**\n * Extract unresolved module paths from an esbuild BuildFailure error. Returns\n * an object indicating which react-related modules failed to resolve.\n *\n * Uses esbuild's structured error objects (errors array) for reliable parsing.\n * Falls back to string matching if the error format is unexpected.\n *\n * Tested against esbuild 0.27.x error format.\n *\n */\nfunction parseUnresolvedModules(error: unknown): {\n\thasUnresolvedReact: boolean;\n\thasUnresolvedReactDom: boolean;\n} {\n\tconst result = { hasUnresolvedReact: false, hasUnresolvedReactDom: false };\n\n\t/**\n\t * Pattern to extract module path from \"Could not resolve X\" errors. Matches:\n\t * Could not resolve \"module-name\" or Could not resolve 'module-name'.\n\t */\n\tconst resolveErrorPattern = /Could not resolve [\"']([^\"']+)[\"']/;\n\n\tif (isEsbuildBuildFailure(error)) {\n\t\t// Use structured error objects from esbuild BuildFailure.\n\t\tfor (const err of error.errors) {\n\t\t\tconst match = resolveErrorPattern.exec(err.text);\n\t\t\tif (match) {\n\t\t\t\tconst modulePath = match[1];\n\t\t\t\t// Check if it's a react or react-dom import (including subpaths).\n\t\t\t\tif (modulePath === \"react\" || modulePath.startsWith(\"react/\")) {\n\t\t\t\t\tresult.hasUnresolvedReact = true;\n\t\t\t\t}\n\t\t\t\tif (modulePath === \"react-dom\" || modulePath.startsWith(\"react-dom/\")) {\n\t\t\t\t\tresult.hasUnresolvedReactDom = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Fallback: parse error message string (less reliable).\n\t\tconst errorMessage = String(error);\n\t\tconst matches = errorMessage.matchAll(\n\t\t\t/Could not resolve [\"']([^\"']+)[\"']/g,\n\t\t);\n\t\tfor (const match of matches) {\n\t\t\tconst modulePath = match[1];\n\t\t\tif (modulePath === \"react\" || modulePath.startsWith(\"react/\")) {\n\t\t\t\tresult.hasUnresolvedReact = true;\n\t\t\t}\n\t\t\tif (modulePath === \"react-dom\" || modulePath.startsWith(\"react-dom/\")) {\n\t\t\t\tresult.hasUnresolvedReactDom = true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Get externals list based on options and package dependencies. react and\n * react-dom are only marked as external if they are declared in the package's\n * dependencies or peerDependencies.\n *\n * Returns the base package names (e.g., [\"react\", \"react-dom\"]) for display\n * purposes.\n *\n */\nexport function getExternals(\n\tpackageName: string,\n\texternals?: string[],\n\tnoExternal?: boolean,\n\tpackageDependencies?: string[],\n): string[] {\n\tif (noExternal) {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Start with empty result - we'll only add react/react-dom if they're in\n\t * package deps.\n\t */\n\tlet result: string[] = [];\n\n\t/**\n\t * Only include react/react-dom if they're in the package's dependencies or\n\t * peerDependencies.\n\t */\n\tif (packageDependencies && packageDependencies.length > 0) {\n\t\tfor (const dep of DEFAULT_EXTERNALS) {\n\t\t\t// Don't mark as external if we're checking the package itself.\n\t\t\tif (dep === packageName) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (packageDependencies.includes(dep)) {\n\t\t\t\tresult.push(dep);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add any additional externals.\n\tif (externals && externals.length > 0) {\n\t\tresult = [...new Set([...result, ...externals])];\n\t}\n\n\treturn result;\n}\n\n/**\n * Expand externals to include subpaths for esbuild. For example, \"react\"\n * expands to [\"react\", \"react/jsx-runtime\", \"react/jsx-dev-runtime\"]. This is\n * needed because esbuild doesn't automatically externalize subpaths.\n */\nexport function expandExternalsForEsbuild(externals: string[]): string[] {\n\tconst expanded: string[] = [];\n\n\tfor (const ext of externals) {\n\t\texpanded.push(ext);\n\t\t// Add subpaths if this is a known package with subpath exports.\n\t\tconst subpaths = EXTERNAL_SUBPATHS[ext];\n\t\tif (subpaths) {\n\t\t\texpanded.push(...subpaths);\n\t\t}\n\t}\n\n\treturn [...new Set(expanded)];\n}\n\nexport type PackageExports = Record<\n\tstring,\n\tstring | { import?: string; types?: string }\n>;\n\nexport type PackageInfo = {\n\tversion: string;\n\tdependencies: Record<string, string>;\n\tpeerDependencies: Record<string, string>;\n\texports: PackageExports | null;\n\thasMainEntry: boolean;\n\tengines: Record<string, string> | null;\n};\n\n/**\n * Get version, dependencies, peer dependencies, and exports from an installed\n * package.\n */\nfunction getPackageInfo(tmpDir: string, packageName: string): PackageInfo {\n\ttry {\n\t\t// Handle scoped packages - the package name in node_modules.\n\t\tconst pkgJsonPath = path.join(\n\t\t\ttmpDir,\n\t\t\t\"node_modules\",\n\t\t\tpackageName,\n\t\t\t\"package.json\",\n\t\t);\n\t\tif (fs.existsSync(pkgJsonPath)) {\n\t\t\tconst pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf-8\"));\n\n\t\t\t// Check if package has a main entry point.\n\t\t\tconst hasMainEntry = Boolean(\n\t\t\t\tpkgJson.main ||\n\t\t\t\t\tpkgJson.module ||\n\t\t\t\t\tpkgJson.exports?.[\".\"] ||\n\t\t\t\t\tpkgJson.exports?.[\"./index\"] ||\n\t\t\t\t\t(!pkgJson.exports && !pkgJson.main && !pkgJson.module),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tversion: pkgJson.version || \"unknown\",\n\t\t\t\tdependencies: pkgJson.dependencies || {},\n\t\t\t\tpeerDependencies: pkgJson.peerDependencies || {},\n\t\t\t\texports: pkgJson.exports || null,\n\t\t\t\thasMainEntry,\n\t\t\t\tengines: pkgJson.engines || null,\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// Ignore errors reading package info.\n\t}\n\treturn {\n\t\tversion: \"unknown\",\n\t\tdependencies: {},\n\t\tpeerDependencies: {},\n\t\texports: null,\n\t\thasMainEntry: true,\n\t\tengines: null,\n\t};\n}\n\n/**\n * Extract subpath export names from package exports field Returns array of\n * subpaths like [\"header\", \"body\", \"datagrid\"].\n */\nfunction getSubpathExports(exports: PackageExports | null): string[] {\n\tif (!exports) {\n\t\treturn [];\n\t}\n\n\tconst subpaths: string[] = [];\n\tfor (const key of Object.keys(exports)) {\n\t\t// Skip the main entry point and package.json.\n\t\tif (key === \".\" || key === \"./package.json\") {\n\t\t\tcontinue;\n\t\t}\n\t\t// Remove leading \"./\" to get subpath name.\n\t\tif (key.startsWith(\"./\")) {\n\t\t\tsubpaths.push(key.substring(2));\n\t\t}\n\t}\n\treturn subpaths;\n}\n\n/**\n * Result of finding subpaths for exports.\n */\ntype SubpathMapping = {\n\t// Single subpath if all exports are from the same subpath.\n\tsingleSubpath?: string;\n\t// Map of export name to subpath for multiple subpaths.\n\texportToSubpath?: Map<string, string>;\n};\n\n/**\n * Find which subpath(s) export the given component names Reads type definition\n * files or JS files to find the exports.\n */\nfunction findSubpathsForExports(\n\ttmpDir: string,\n\tpackageName: string,\n\texports: PackageExports,\n\tcomponentNames: string[],\n): SubpathMapping {\n\tconst packageDir = path.join(tmpDir, \"node_modules\", packageName);\n\tconst exportToSubpath = new Map<string, string>();\n\n\tfor (const [subpathKey, subpathValue] of Object.entries(exports)) {\n\t\t// Skip main entry and package.json.\n\t\tif (subpathKey === \".\" || subpathKey === \"./package.json\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Get the types or import path.\n\t\tlet filePath: string | undefined;\n\t\tif (typeof subpathValue === \"object\" && subpathValue !== null) {\n\t\t\t// Prefer types file for more accurate export detection.\n\t\t\tfilePath = subpathValue.types || subpathValue.import;\n\t\t} else if (typeof subpathValue === \"string\") {\n\t\t\tfilePath = subpathValue;\n\t\t}\n\n\t\tif (!filePath) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Resolve the file path.\n\t\tconst fullPath = path.join(packageDir, filePath);\n\n\t\ttry {\n\t\t\tif (fs.existsSync(fullPath)) {\n\t\t\t\tconst content = fs.readFileSync(fullPath, \"utf-8\");\n\t\t\t\tconst subpath = subpathKey.startsWith(\"./\")\n\t\t\t\t\t? subpathKey.substring(2)\n\t\t\t\t\t: subpathKey;\n\n\t\t\t\t// Check each component name.\n\t\t\t\tfor (const name of componentNames) {\n\t\t\t\t\t// Skip if already found.\n\t\t\t\t\tif (exportToSubpath.has(name)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Escape regex special characters in the name to prevent injection.\n\t\t\t\t\tconst escapedName = escapeRegExp(name);\n\n\t\t\t\t\t// Look for various export patterns.\n\t\t\t\t\tconst patterns = [\n\t\t\t\t\t\tnew RegExp(`export\\\\s*\\\\{[^}]*\\\\b${escapedName}\\\\b[^}]*\\\\}`, \"m\"),\n\t\t\t\t\t\tnew RegExp(\n\t\t\t\t\t\t\t`export\\\\s+declare\\\\s+(?:const|function|class)\\\\s+${escapedName}\\\\b`,\n\t\t\t\t\t\t\t\"m\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew RegExp(\n\t\t\t\t\t\t\t`export\\\\s+(?:const|function|class)\\\\s+${escapedName}\\\\b`,\n\t\t\t\t\t\t\t\"m\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\n\t\t\t\t\tif (patterns.some((pattern) => pattern.test(content))) {\n\t\t\t\t\t\texportToSubpath.set(name, subpath);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors, continue to next subpath.\n\t\t}\n\t}\n\n\t// Check if all exports were found.\n\tif (exportToSubpath.size !== componentNames.length) {\n\t\treturn {}; // Not all exports found\n\t}\n\n\t// Check if all exports are from the same subpath.\n\tconst subpaths = new Set(exportToSubpath.values());\n\tif (subpaths.size === 1) {\n\t\treturn { singleSubpath: [...subpaths][0] };\n\t}\n\n\t// Multiple subpaths needed.\n\treturn { exportToSubpath };\n}\n\n/**\n * Check the bundle size of an npm package.\n */\nexport async function checkBundleSize(\n\toptions: BundleOptions,\n): Promise<BundleResult> {\n\tconst {\n\t\tpackageName: packageSpecifier,\n\t\texports,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel = 5,\n\t\tregistry,\n\t\tplatform: explicitPlatform,\n\t} = options;\n\n\t// Parse the package specifier to extract name, version, and subpath.\n\tconst {\n\t\tname: packageName,\n\t\tversion: requestedVersion,\n\t\tsubpath,\n\t} = parsePackageSpecifier(packageSpecifier);\n\n\tconst tmpDir = createTempDir();\n\n\ttry {\n\t\t// Create initial package.json.\n\t\tconst packageJson: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\ttype: string;\n\t\t\tdependencies: Record<string, string>;\n\t\t} = {\n\t\t\tname: \"bundlecheck-temp\",\n\t\t\tversion: \"1.0.0\",\n\t\t\ttype: \"module\",\n\t\t\tdependencies: {\n\t\t\t\t[packageName]: requestedVersion,\n\t\t\t},\n\t\t};\n\n\t\tfs.writeFileSync(\n\t\t\tpath.join(tmpDir, \"package.json\"),\n\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t);\n\n\t\t// Install the main package (try pnpm first, fallback to npm).\n\t\tconst installCmd = getInstallCommand(registry);\n\t\texecSync(installCmd, {\n\t\t\tcwd: tmpDir,\n\t\t\tstdio: \"pipe\",\n\t\t});\n\n\t\t/**\n\t\t * Get package info (version, dependencies, peer dependencies, exports,\n\t\t * engines).\n\t\t */\n\t\tconst pkgInfo = getPackageInfo(tmpDir, packageName);\n\t\tconst peerDepKeys = Object.keys(pkgInfo.peerDependencies);\n\n\t\t/**\n\t\t * Determine platform: use explicit value if provided, otherwise auto-detect\n\t\t * from engines.\n\t\t */\n\t\tlet platform: \"browser\" | \"node\" = \"browser\";\n\t\tif (explicitPlatform) {\n\t\t\tplatform = explicitPlatform;\n\t\t} else if (pkgInfo.engines?.node && !pkgInfo.engines?.browser) {\n\t\t\t// Package specifies node engine without browser - likely a Node.js package.\n\t\t\tplatform = \"node\";\n\t\t}\n\n\t\t// Collect all dependency names (prod + peer).\n\t\tconst allDependencies = [\n\t\t\t...new Set([...Object.keys(pkgInfo.dependencies), ...peerDepKeys]),\n\t\t].sort();\n\n\t\tif (peerDepKeys.length > 0) {\n\t\t\t// Add peer dependencies to package.json.\n\t\t\tfor (const dep of peerDepKeys) {\n\t\t\t\t// Use the version range from peer dependencies.\n\t\t\t\tpackageJson.dependencies[dep] = pkgInfo.peerDependencies[dep];\n\t\t\t}\n\n\t\t\t// Update package.json and reinstall.\n\t\t\tfs.writeFileSync(\n\t\t\t\tpath.join(tmpDir, \"package.json\"),\n\t\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t\t);\n\n\t\t\texecSync(installCmd, {\n\t\t\t\tcwd: tmpDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Determine if we need to use all subpath exports or find the right\n\t\t * subpath(s).\n\t\t */\n\t\tlet allSubpaths: string[] | undefined;\n\t\tlet resolvedSubpath = subpath;\n\t\tlet exportToSubpath: Map<string, string> | undefined;\n\n\t\tif (!subpath && !pkgInfo.hasMainEntry && pkgInfo.exports) {\n\t\t\tif (exports && exports.length > 0) {\n\t\t\t\t// User specified exports but no subpath - try to find the right subpath(s).\n\t\t\t\tconst mapping = findSubpathsForExports(\n\t\t\t\t\ttmpDir,\n\t\t\t\t\tpackageName,\n\t\t\t\t\tpkgInfo.exports,\n\t\t\t\t\texports,\n\t\t\t\t);\n\n\t\t\t\tif (mapping.singleSubpath) {\n\t\t\t\t\t// All exports from the same subpath.\n\t\t\t\t\tresolvedSubpath = mapping.singleSubpath;\n\t\t\t\t} else if (mapping.exportToSubpath) {\n\t\t\t\t\t// Exports from multiple subpaths.\n\t\t\t\t\texportToSubpath = mapping.exportToSubpath;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If still no subpath resolved and no mapping, bundle all subpaths.\n\t\t\tif (!resolvedSubpath && !exportToSubpath) {\n\t\t\t\tallSubpaths = getSubpathExports(pkgInfo.exports);\n\t\t\t}\n\t\t}\n\n\t\t// Create entry file with appropriate content.\n\t\tconst entryContent = generateEntryContent({\n\t\t\tpackageName,\n\t\t\tsubpath: resolvedSubpath,\n\t\t\texports,\n\t\t\tallSubpaths,\n\t\t\texportToSubpath,\n\t\t});\n\t\tconst entryFile = path.join(tmpDir, \"entry.js\");\n\t\tfs.writeFileSync(entryFile, entryContent);\n\n\t\t/**\n\t\t * Get externals based on package dependencies. Only include react/react-dom\n\t\t * if they're in the package's dependencies or peerDependencies.\n\t\t */\n\t\tlet externals = getExternals(\n\t\t\tpackageName,\n\t\t\tadditionalExternals,\n\t\t\tnoExternal,\n\t\t\tallDependencies,\n\t\t);\n\n\t\t/**\n\t\t * Expand externals to include subpaths for esbuild.\n\t\t * e.g., \"react\" -> [\"react\", \"react/jsx-runtime\", \"react/jsx-dev-runtime\"]\n\t\t */\n\t\tlet esbuildExternals = expandExternalsForEsbuild(externals);\n\n\t\t/**\n\t\t * Bundle with esbuild. We use a two-phase approach:\n\t\t * 1. First attempt with logLevel: \"silent\" to suppress errors\n\t\t * 2. If it fails due to unresolved react imports, auto-add react to externals and retry\n\t\t * This handles packages that don't properly declare react as a peer\n\t\t * dependency.\n\t\t */\n\t\tlet result: esbuild.BuildResult<{ write: false; metafile: true }>;\n\t\ttry {\n\t\t\tresult = await esbuild.build({\n\t\t\t\tentryPoints: [entryFile],\n\t\t\t\tbundle: true,\n\t\t\t\twrite: false,\n\t\t\t\tformat: \"esm\",\n\t\t\t\tplatform,\n\t\t\t\ttarget: \"es2020\",\n\t\t\t\tminify: true,\n\t\t\t\ttreeShaking: true,\n\t\t\t\texternal: esbuildExternals,\n\t\t\t\tmetafile: true,\n\t\t\t\tlogLevel: \"silent\", // Suppress errors on first attempt (will retry if needed)\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t/**\n\t\t\t * Parse unresolved module errors using esbuild's structured error format.\n\t\t\t * This handles packages that don't properly declare react as a peer\n\t\t\t * dependency.\n\t\t\t */\n\t\t\tconst { hasUnresolvedReact, hasUnresolvedReactDom } =\n\t\t\t\tparseUnresolvedModules(error);\n\n\t\t\tif (!noExternal && (hasUnresolvedReact || hasUnresolvedReactDom)) {\n\t\t\t\t// Auto-add react and/or react-dom to externals and retry.\n\t\t\t\tconst autoExternals: string[] = [];\n\t\t\t\tif (hasUnresolvedReact && !externals.includes(\"react\")) {\n\t\t\t\t\tautoExternals.push(\"react\");\n\t\t\t\t}\n\t\t\t\tif (hasUnresolvedReactDom && !externals.includes(\"react-dom\")) {\n\t\t\t\t\tautoExternals.push(\"react-dom\");\n\t\t\t\t}\n\n\t\t\t\tif (autoExternals.length > 0) {\n\t\t\t\t\texternals = [...externals, ...autoExternals];\n\t\t\t\t\tesbuildExternals = expandExternalsForEsbuild(externals);\n\n\t\t\t\t\tresult = await esbuild.build({\n\t\t\t\t\t\tentryPoints: [entryFile],\n\t\t\t\t\t\tbundle: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\t\tplatform,\n\t\t\t\t\t\ttarget: \"es2020\",\n\t\t\t\t\t\tminify: true,\n\t\t\t\t\t\ttreeShaking: true,\n\t\t\t\t\t\texternal: esbuildExternals,\n\t\t\t\t\t\tmetafile: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\t// Get raw size.\n\t\tconst bundleContent = result.outputFiles[0].contents;\n\t\tconst rawSize = bundleContent.length;\n\n\t\t// Gzip the bundle (only for browser platform - not relevant for Node.js).\n\t\tlet gzipSize: number | null = null;\n\t\tif (platform === \"browser\") {\n\t\t\tconst gzipped = await gzipAsync(Buffer.from(bundleContent), {\n\t\t\t\tlevel: gzipLevel,\n\t\t\t});\n\t\t\tgzipSize = gzipped.length;\n\t\t}\n\n\t\t// Determine the display name.\n\t\tlet displayName = packageName;\n\t\tif (resolvedSubpath) {\n\t\t\tdisplayName = `${packageName}/${resolvedSubpath}`;\n\t\t} else if (exportToSubpath && exportToSubpath.size > 0) {\n\t\t\t// Multiple subpaths - show them all.\n\t\t\tconst uniqueSubpaths = [...new Set(exportToSubpath.values())].sort();\n\t\t\tdisplayName = `${packageName}/{${uniqueSubpaths.join(\", \")}}`;\n\t\t}\n\n\t\t/**\n\t\t * Get named export count from the package's type definitions. Use\n\t\t * runtimeCount to exclude type-only exports (types, interfaces).\n\t\t */\n\t\tconst { runtimeCount: namedExportCount } = getNamedExports(\n\t\t\ttmpDir,\n\t\t\tpackageName,\n\t\t);\n\n\t\treturn {\n\t\t\tpackageName: displayName,\n\t\t\tpackageVersion: pkgInfo.version,\n\t\t\texports: exports || [],\n\t\t\trawSize,\n\t\t\tgzipSize,\n\t\t\tgzipLevel,\n\t\t\texternals,\n\t\t\tdependencies: allDependencies,\n\t\t\tplatform,\n\t\t\tnamedExportCount,\n\t\t};\n\t} finally {\n\t\tcleanupTempDir(tmpDir);\n\t}\n}\n"],"names":["execSync","fs","os","path","promisify","zlib","esbuild","DEFAULT_EXTERNALS","EXTERNAL_SUBPATHS","getNamedExports","gzipAsync","gzip","escapeRegExp","str","replace","parsePackageSpecifier","specifier","workingSpec","version","startsWith","secondAtIndex","indexOf","substring","parts","split","length","name","subpath","slice","join","atIndex","slashIndex","formatBytes","bytes","k","sizes","i","Math","floor","log","Number","parseFloat","toFixed","createTempDir","tmpDir","tmpdir","Date","now","mkdirSync","recursive","cleanupTempDir","rmSync","force","isPnpmAvailable","stdio","usePnpm","validateRegistryUrl","registry","url","URL","Error","protocol","toString","getInstallCommand","registryArg","sanitizedRegistry","generateEntryContent","options","packageName","exports","allSubpaths","exportToSubpath","size","subpathToExports","Map","exportName","sp","existing","get","push","set","lines","allExportNames","exportNames","importPath","names","importNames","imports","map","isEsbuildBuildFailure","error","Array","isArray","errors","parseUnresolvedModules","result","hasUnresolvedReact","hasUnresolvedReactDom","resolveErrorPattern","err","match","exec","text","modulePath","errorMessage","String","matches","matchAll","getExternals","externals","noExternal","packageDependencies","dep","includes","Set","expandExternalsForEsbuild","expanded","ext","subpaths","getPackageInfo","pkgJsonPath","existsSync","pkgJson","JSON","parse","readFileSync","hasMainEntry","Boolean","main","module","dependencies","peerDependencies","engines","getSubpathExports","key","Object","keys","findSubpathsForExports","componentNames","packageDir","subpathKey","subpathValue","entries","filePath","types","import","fullPath","content","has","escapedName","patterns","RegExp","some","pattern","test","values","singleSubpath","checkBundleSize","packageSpecifier","additionalExternals","gzipLevel","platform","explicitPlatform","requestedVersion","packageJson","type","writeFileSync","stringify","installCmd","cwd","pkgInfo","peerDepKeys","node","browser","allDependencies","sort","resolvedSubpath","mapping","entryContent","entryFile","esbuildExternals","build","entryPoints","bundle","write","format","target","minify","treeShaking","external","metafile","logLevel","autoExternals","bundleContent","outputFiles","contents","rawSize","gzipSize","gzipped","Buffer","from","level","displayName","uniqueSubpaths","runtimeCount","namedExportCount","packageVersion"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/bundler.ts"],"sourcesContent":["import { execSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport zlib from \"node:zlib\";\nimport * as esbuild from \"esbuild\";\nimport {\n\tDEFAULT_EXTERNALS,\n\tDEFAULT_TARGET,\n\tEXTERNAL_SUBPATHS,\n} from \"./defaults.js\";\nimport { getNamedExports } from \"./exports.js\";\n\nconst gzipAsync = promisify(zlib.gzip);\n\n/**\n * Escape special regex characters in a string.\n */\nfunction escapeRegExp(str: string): string {\n\treturn str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport type ParsedPackage = {\n\tname: string;\n\tversion: string;\n\tsubpath?: string;\n};\n\n/**\n * Parse a package specifier to extract name, version, and subpath.\n * Handles:\n * - @scope/package@1.0.0\n * - @scope/package/subpath@1.0.0\n * - @scope/package/subpath\n * - package/subpath@1.0.0\n */\nexport function parsePackageSpecifier(specifier: string): ParsedPackage {\n\tlet workingSpec = specifier;\n\tlet version = \"latest\";\n\n\t// Handle scoped packages (@scope/name...)\n\tif (workingSpec.startsWith(\"@\")) {\n\t\t// Find the second @ which would separate version.\n\t\tconst secondAtIndex = workingSpec.indexOf(\"@\", 1);\n\t\tif (secondAtIndex !== -1) {\n\t\t\tversion = workingSpec.substring(secondAtIndex + 1);\n\t\t\tworkingSpec = workingSpec.substring(0, secondAtIndex);\n\t\t}\n\n\t\t/**\n\t\t * Now workingSpec is like @scope/name or @scope/name/subpath Split by / and\n\t\t * check if there are more than 2 parts.\n\t\t */\n\t\tconst parts = workingSpec.split(\"/\");\n\t\tif (parts.length > 2) {\n\t\t\t// Has subpath: @scope/name/subpath/more.\n\t\t\tconst name = `${parts[0]}/${parts[1]}`;\n\t\t\tconst subpath = parts.slice(2).join(\"/\");\n\t\t\treturn { name, version, subpath };\n\t\t}\n\t\t// No subpath: @scope/name.\n\t\treturn { name: workingSpec, version };\n\t}\n\n\t// Handle non-scoped packages (name@version or name/subpath@version).\n\tconst atIndex = workingSpec.indexOf(\"@\");\n\tif (atIndex !== -1) {\n\t\tversion = workingSpec.substring(atIndex + 1);\n\t\tworkingSpec = workingSpec.substring(0, atIndex);\n\t}\n\n\t// Check for subpath in non-scoped packages.\n\tconst slashIndex = workingSpec.indexOf(\"/\");\n\tif (slashIndex !== -1) {\n\t\tconst name = workingSpec.substring(0, slashIndex);\n\t\tconst subpath = workingSpec.substring(slashIndex + 1);\n\t\treturn { name, version, subpath };\n\t}\n\n\treturn { name: workingSpec, version };\n}\n\nexport type BundleOptions = {\n\tpackageName: string;\n\texports?: string[];\n\tadditionalExternals?: string[];\n\tnoExternal?: boolean;\n\tgzipLevel?: number;\n\tregistry?: string;\n\t/**\n\t * Target platform. If undefined, auto-detects from package.json engines.\n\t */\n\tplatform?: \"browser\" | \"node\";\n\t/**\n\t * esbuild target (e.g., \"es2022\", \"es2020\"). Defaults to \"es2022\".\n\t */\n\ttarget?: string;\n};\n\nexport type BundleResult = {\n\tpackageName: string;\n\tpackageVersion: string;\n\texports: string[];\n\trawSize: number;\n\t/**\n\t * Gzip size in bytes, or null for node platform (gzip not applicable).\n\t */\n\tgzipSize: number | null;\n\tgzipLevel: number;\n\texternals: string[];\n\tdependencies: string[];\n\tplatform: \"browser\" | \"node\";\n\t/**\n\t * Total number of named exports in the package (when analyzing entire\n\t * package).\n\t */\n\tnamedExportCount: number;\n};\n\n/**\n * Format bytes to human-readable string.\n */\nexport function formatBytes(bytes: number): string {\n\tif (bytes === 0) {\n\t\treturn \"0 B\";\n\t}\n\tconst k = 1024;\n\tconst sizes = [\"B\", \"kB\", \"MB\", \"GB\"];\n\tconst i = Math.floor(Math.log(bytes) / Math.log(k));\n\treturn `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;\n}\n\n/**\n * Create a temporary directory for bundling.\n */\nfunction createTempDir(): string {\n\tconst tmpDir = path.join(os.tmpdir(), `bundlecheck-${Date.now()}`);\n\tfs.mkdirSync(tmpDir, { recursive: true });\n\treturn tmpDir;\n}\n\n/**\n * Clean up temporary directory.\n */\nfunction cleanupTempDir(tmpDir: string): void {\n\ttry {\n\t\tfs.rmSync(tmpDir, { recursive: true, force: true });\n\t} catch {\n\t\t// Ignore cleanup errors.\n\t}\n}\n\n/**\n * Check if pnpm is available.\n */\nfunction isPnpmAvailable(): boolean {\n\ttry {\n\t\texecSync(\"pnpm --version\", { stdio: \"pipe\" });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n// Cache the result of pnpm availability check.\nlet usePnpm: boolean | null = null;\n\n/**\n * Validate and sanitize a registry URL to prevent command injection.\n * @param registry - The registry URL to validate\n * @returns The sanitized URL or undefined if invalid\n * @throws Error if the URL is invalid or contains potentially malicious characters\n */\nfunction validateRegistryUrl(registry: string): string {\n\t// Parse as URL to validate format.\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(registry);\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Invalid registry URL: ${registry}. Must be a valid URL (e.g., https://registry.example.com)`,\n\t\t);\n\t}\n\n\t// Only allow http and https protocols.\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\n\t\t\t`Invalid registry URL protocol: ${url.protocol}. Only http: and https: are allowed`,\n\t\t);\n\t}\n\n\t// Return the sanitized URL (URL constructor normalizes it).\n\treturn url.toString();\n}\n\n/**\n * Get the install command (pnpm preferred, npm fallback).\n * @param registry - Optional custom npm registry URL\n */\nfunction getInstallCommand(registry?: string): string {\n\tif (usePnpm === null) {\n\t\tusePnpm = isPnpmAvailable();\n\t}\n\n\tlet registryArg = \"\";\n\tif (registry) {\n\t\t// Validate and sanitize the registry URL to prevent command injection.\n\t\tconst sanitizedRegistry = validateRegistryUrl(registry);\n\t\t// Quote the URL to handle any special characters safely.\n\t\tregistryArg = ` --registry \"${sanitizedRegistry}\"`;\n\t}\n\n\tif (usePnpm) {\n\t\treturn `pnpm install --ignore-scripts --no-frozen-lockfile${registryArg}`;\n\t}\n\treturn `npm install --legacy-peer-deps --ignore-scripts${registryArg}`;\n}\n\nexport type EntryContentOptions = {\n\tpackageName: string;\n\tsubpath?: string;\n\texports?: string[];\n\tallSubpaths?: string[];\n\texportToSubpath?: Map<string, string>;\n};\n\n/**\n * Generate the entry file content based on package, subpath, and exports.\n */\nfunction generateEntryContent(options: EntryContentOptions): string {\n\tconst { packageName, subpath, exports, allSubpaths, exportToSubpath } =\n\t\toptions;\n\n\t// If we have exports mapped to different subpaths.\n\tif (exportToSubpath && exportToSubpath.size > 0) {\n\t\t// Group exports by subpath.\n\t\tconst subpathToExports = new Map<string, string[]>();\n\t\tfor (const [exportName, sp] of exportToSubpath) {\n\t\t\tconst existing = subpathToExports.get(sp) || [];\n\t\t\texisting.push(exportName);\n\t\t\tsubpathToExports.set(sp, existing);\n\t\t}\n\n\t\t// Generate imports for each subpath.\n\t\tconst lines: string[] = [];\n\t\tconst allExportNames: string[] = [];\n\n\t\tfor (const [sp, exportNames] of subpathToExports) {\n\t\t\tconst importPath = `${packageName}/${sp}`;\n\t\t\tconst names = exportNames.join(\", \");\n\t\t\tlines.push(`import { ${names} } from \"${importPath}\";`);\n\t\t\tallExportNames.push(...exportNames);\n\t\t}\n\n\t\tlines.push(`export { ${allExportNames.join(\", \")} };`);\n\t\treturn lines.join(\"\\n\") + \"\\n\";\n\t}\n\n\t// If we have specific exports to import.\n\tif (exports && exports.length > 0) {\n\t\t// Determine the import path.\n\t\tconst importPath = subpath ? `${packageName}/${subpath}` : packageName;\n\t\tconst importNames = exports.join(\", \");\n\t\treturn `import { ${importNames} } from \"${importPath}\";\\nexport { ${importNames} };\\n`;\n\t}\n\n\t// If we have a specific subpath (but no specific exports).\n\tif (subpath) {\n\t\tconst importPath = `${packageName}/${subpath}`;\n\t\treturn `import * as pkg from \"${importPath}\";\\nexport default pkg;\\n`;\n\t}\n\n\t// If package has subpath exports only (no main entry), import all subpaths.\n\tif (allSubpaths && allSubpaths.length > 0) {\n\t\tconst imports = allSubpaths\n\t\t\t.map(\n\t\t\t\t(sp, i) =>\n\t\t\t\t\t`import * as sub${i} from \"${packageName}/${sp}\";\\nexport { sub${i} };`,\n\t\t\t)\n\t\t\t.join(\"\\n\");\n\t\treturn imports + \"\\n\";\n\t}\n\n\t// Default: import everything from main entry.\n\treturn `import * as pkg from \"${packageName}\";\\nexport default pkg;\\n`;\n}\n\n/**\n * Check if an error is an esbuild BuildFailure. BuildFailure has an `errors`\n * array with structured error objects.\n */\nfunction isEsbuildBuildFailure(\n\terror: unknown,\n): error is { errors: Array<{ text: string; location?: unknown }> } {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t\"errors\" in error &&\n\t\tArray.isArray((error as { errors: unknown }).errors)\n\t);\n}\n\n/**\n * Extract unresolved module paths from an esbuild BuildFailure error. Returns\n * an object indicating which react-related modules failed to resolve.\n *\n * Uses esbuild's structured error objects (errors array) for reliable parsing.\n * Falls back to string matching if the error format is unexpected.\n *\n * Tested against esbuild 0.27.x error format.\n *\n */\nfunction parseUnresolvedModules(error: unknown): {\n\thasUnresolvedReact: boolean;\n\thasUnresolvedReactDom: boolean;\n} {\n\tconst result = { hasUnresolvedReact: false, hasUnresolvedReactDom: false };\n\n\t/**\n\t * Pattern to extract module path from \"Could not resolve X\" errors. Matches:\n\t * Could not resolve \"module-name\" or Could not resolve 'module-name'.\n\t */\n\tconst resolveErrorPattern = /Could not resolve [\"']([^\"']+)[\"']/;\n\n\tif (isEsbuildBuildFailure(error)) {\n\t\t// Use structured error objects from esbuild BuildFailure.\n\t\tfor (const err of error.errors) {\n\t\t\tconst match = resolveErrorPattern.exec(err.text);\n\t\t\tif (match) {\n\t\t\t\tconst modulePath = match[1];\n\t\t\t\t// Check if it's a react or react-dom import (including subpaths).\n\t\t\t\tif (modulePath === \"react\" || modulePath.startsWith(\"react/\")) {\n\t\t\t\t\tresult.hasUnresolvedReact = true;\n\t\t\t\t}\n\t\t\t\tif (modulePath === \"react-dom\" || modulePath.startsWith(\"react-dom/\")) {\n\t\t\t\t\tresult.hasUnresolvedReactDom = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\t// Fallback: parse error message string (less reliable).\n\t\tconst errorMessage = String(error);\n\t\tconst matches = errorMessage.matchAll(\n\t\t\t/Could not resolve [\"']([^\"']+)[\"']/g,\n\t\t);\n\t\tfor (const match of matches) {\n\t\t\tconst modulePath = match[1];\n\t\t\tif (modulePath === \"react\" || modulePath.startsWith(\"react/\")) {\n\t\t\t\tresult.hasUnresolvedReact = true;\n\t\t\t}\n\t\t\tif (modulePath === \"react-dom\" || modulePath.startsWith(\"react-dom/\")) {\n\t\t\t\tresult.hasUnresolvedReactDom = true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result;\n}\n\n/**\n * Get externals list based on options and package dependencies. react and\n * react-dom are only marked as external if they are declared in the package's\n * dependencies or peerDependencies.\n *\n * Returns the base package names (e.g., [\"react\", \"react-dom\"]) for display\n * purposes.\n *\n */\nexport function getExternals(\n\tpackageName: string,\n\texternals?: string[],\n\tnoExternal?: boolean,\n\tpackageDependencies?: string[],\n): string[] {\n\tif (noExternal) {\n\t\treturn [];\n\t}\n\n\t/**\n\t * Start with empty result - we'll only add react/react-dom if they're in\n\t * package deps.\n\t */\n\tlet result: string[] = [];\n\n\t/**\n\t * Only include react/react-dom if they're in the package's dependencies or\n\t * peerDependencies.\n\t */\n\tif (packageDependencies && packageDependencies.length > 0) {\n\t\tfor (const dep of DEFAULT_EXTERNALS) {\n\t\t\t// Don't mark as external if we're checking the package itself.\n\t\t\tif (dep === packageName) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (packageDependencies.includes(dep)) {\n\t\t\t\tresult.push(dep);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add any additional externals.\n\tif (externals && externals.length > 0) {\n\t\tresult = [...new Set([...result, ...externals])];\n\t}\n\n\treturn result;\n}\n\n/**\n * Expand externals to include subpaths for esbuild. For example, \"react\"\n * expands to [\"react\", \"react/jsx-runtime\", \"react/jsx-dev-runtime\"]. This is\n * needed because esbuild doesn't automatically externalize subpaths.\n */\nexport function expandExternalsForEsbuild(externals: string[]): string[] {\n\tconst expanded: string[] = [];\n\n\tfor (const ext of externals) {\n\t\texpanded.push(ext);\n\t\t// Add subpaths if this is a known package with subpath exports.\n\t\tconst subpaths = EXTERNAL_SUBPATHS[ext];\n\t\tif (subpaths) {\n\t\t\texpanded.push(...subpaths);\n\t\t}\n\t}\n\n\treturn [...new Set(expanded)];\n}\n\nexport type PackageExports = Record<\n\tstring,\n\tstring | { import?: string; types?: string }\n>;\n\nexport type PackageInfo = {\n\tversion: string;\n\tdependencies: Record<string, string>;\n\tpeerDependencies: Record<string, string>;\n\texports: PackageExports | null;\n\thasMainEntry: boolean;\n\tengines: Record<string, string> | null;\n};\n\n/**\n * Get version, dependencies, peer dependencies, and exports from an installed\n * package.\n */\nfunction getPackageInfo(tmpDir: string, packageName: string): PackageInfo {\n\ttry {\n\t\t// Handle scoped packages - the package name in node_modules.\n\t\tconst pkgJsonPath = path.join(\n\t\t\ttmpDir,\n\t\t\t\"node_modules\",\n\t\t\tpackageName,\n\t\t\t\"package.json\",\n\t\t);\n\t\tif (fs.existsSync(pkgJsonPath)) {\n\t\t\tconst pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, \"utf-8\"));\n\n\t\t\t// Check if package has a main entry point.\n\t\t\tconst hasMainEntry = Boolean(\n\t\t\t\tpkgJson.main ||\n\t\t\t\t\tpkgJson.module ||\n\t\t\t\t\tpkgJson.exports?.[\".\"] ||\n\t\t\t\t\tpkgJson.exports?.[\"./index\"] ||\n\t\t\t\t\t(!pkgJson.exports && !pkgJson.main && !pkgJson.module),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tversion: pkgJson.version || \"unknown\",\n\t\t\t\tdependencies: pkgJson.dependencies || {},\n\t\t\t\tpeerDependencies: pkgJson.peerDependencies || {},\n\t\t\t\texports: pkgJson.exports || null,\n\t\t\t\thasMainEntry,\n\t\t\t\tengines: pkgJson.engines || null,\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// Ignore errors reading package info.\n\t}\n\treturn {\n\t\tversion: \"unknown\",\n\t\tdependencies: {},\n\t\tpeerDependencies: {},\n\t\texports: null,\n\t\thasMainEntry: true,\n\t\tengines: null,\n\t};\n}\n\n/**\n * Extract subpath export names from package exports field Returns array of\n * subpaths like [\"header\", \"body\", \"datagrid\"].\n */\nfunction getSubpathExports(exports: PackageExports | null): string[] {\n\tif (!exports) {\n\t\treturn [];\n\t}\n\n\tconst subpaths: string[] = [];\n\tfor (const key of Object.keys(exports)) {\n\t\t// Skip the main entry point and package.json.\n\t\tif (key === \".\" || key === \"./package.json\") {\n\t\t\tcontinue;\n\t\t}\n\t\t// Remove leading \"./\" to get subpath name.\n\t\tif (key.startsWith(\"./\")) {\n\t\t\tsubpaths.push(key.substring(2));\n\t\t}\n\t}\n\treturn subpaths;\n}\n\n/**\n * Result of finding subpaths for exports.\n */\ntype SubpathMapping = {\n\t// Single subpath if all exports are from the same subpath.\n\tsingleSubpath?: string;\n\t// Map of export name to subpath for multiple subpaths.\n\texportToSubpath?: Map<string, string>;\n};\n\n/**\n * Find which subpath(s) export the given component names Reads type definition\n * files or JS files to find the exports.\n */\nfunction findSubpathsForExports(\n\ttmpDir: string,\n\tpackageName: string,\n\texports: PackageExports,\n\tcomponentNames: string[],\n): SubpathMapping {\n\tconst packageDir = path.join(tmpDir, \"node_modules\", packageName);\n\tconst exportToSubpath = new Map<string, string>();\n\n\tfor (const [subpathKey, subpathValue] of Object.entries(exports)) {\n\t\t// Skip main entry and package.json.\n\t\tif (subpathKey === \".\" || subpathKey === \"./package.json\") {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Get the types or import path.\n\t\tlet filePath: string | undefined;\n\t\tif (typeof subpathValue === \"object\" && subpathValue !== null) {\n\t\t\t// Prefer types file for more accurate export detection.\n\t\t\tfilePath = subpathValue.types || subpathValue.import;\n\t\t} else if (typeof subpathValue === \"string\") {\n\t\t\tfilePath = subpathValue;\n\t\t}\n\n\t\tif (!filePath) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Resolve the file path.\n\t\tconst fullPath = path.join(packageDir, filePath);\n\n\t\ttry {\n\t\t\tif (fs.existsSync(fullPath)) {\n\t\t\t\tconst content = fs.readFileSync(fullPath, \"utf-8\");\n\t\t\t\tconst subpath = subpathKey.startsWith(\"./\")\n\t\t\t\t\t? subpathKey.substring(2)\n\t\t\t\t\t: subpathKey;\n\n\t\t\t\t// Check each component name.\n\t\t\t\tfor (const name of componentNames) {\n\t\t\t\t\t// Skip if already found.\n\t\t\t\t\tif (exportToSubpath.has(name)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Escape regex special characters in the name to prevent injection.\n\t\t\t\t\tconst escapedName = escapeRegExp(name);\n\n\t\t\t\t\t// Look for various export patterns.\n\t\t\t\t\tconst patterns = [\n\t\t\t\t\t\tnew RegExp(`export\\\\s*\\\\{[^}]*\\\\b${escapedName}\\\\b[^}]*\\\\}`, \"m\"),\n\t\t\t\t\t\tnew RegExp(\n\t\t\t\t\t\t\t`export\\\\s+declare\\\\s+(?:const|function|class)\\\\s+${escapedName}\\\\b`,\n\t\t\t\t\t\t\t\"m\",\n\t\t\t\t\t\t),\n\t\t\t\t\t\tnew RegExp(\n\t\t\t\t\t\t\t`export\\\\s+(?:const|function|class)\\\\s+${escapedName}\\\\b`,\n\t\t\t\t\t\t\t\"m\",\n\t\t\t\t\t\t),\n\t\t\t\t\t];\n\n\t\t\t\t\tif (patterns.some((pattern) => pattern.test(content))) {\n\t\t\t\t\t\texportToSubpath.set(name, subpath);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore read errors, continue to next subpath.\n\t\t}\n\t}\n\n\t// Check if all exports were found.\n\tif (exportToSubpath.size !== componentNames.length) {\n\t\treturn {}; // Not all exports found\n\t}\n\n\t// Check if all exports are from the same subpath.\n\tconst subpaths = new Set(exportToSubpath.values());\n\tif (subpaths.size === 1) {\n\t\treturn { singleSubpath: [...subpaths][0] };\n\t}\n\n\t// Multiple subpaths needed.\n\treturn { exportToSubpath };\n}\n\n/**\n * Check the bundle size of an npm package.\n */\nexport async function checkBundleSize(\n\toptions: BundleOptions,\n): Promise<BundleResult> {\n\tconst {\n\t\tpackageName: packageSpecifier,\n\t\texports,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel = 5,\n\t\tregistry,\n\t\tplatform: explicitPlatform,\n\t\ttarget = DEFAULT_TARGET,\n\t} = options;\n\n\t// Parse the package specifier to extract name, version, and subpath.\n\tconst {\n\t\tname: packageName,\n\t\tversion: requestedVersion,\n\t\tsubpath,\n\t} = parsePackageSpecifier(packageSpecifier);\n\n\tconst tmpDir = createTempDir();\n\n\ttry {\n\t\t// Create initial package.json.\n\t\tconst packageJson: {\n\t\t\tname: string;\n\t\t\tversion: string;\n\t\t\ttype: string;\n\t\t\tdependencies: Record<string, string>;\n\t\t} = {\n\t\t\tname: \"bundlecheck-temp\",\n\t\t\tversion: \"1.0.0\",\n\t\t\ttype: \"module\",\n\t\t\tdependencies: {\n\t\t\t\t[packageName]: requestedVersion,\n\t\t\t},\n\t\t};\n\n\t\tfs.writeFileSync(\n\t\t\tpath.join(tmpDir, \"package.json\"),\n\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t);\n\n\t\t// Install the main package (try pnpm first, fallback to npm).\n\t\tconst installCmd = getInstallCommand(registry);\n\t\texecSync(installCmd, {\n\t\t\tcwd: tmpDir,\n\t\t\tstdio: \"pipe\",\n\t\t});\n\n\t\t/**\n\t\t * Get package info (version, dependencies, peer dependencies, exports,\n\t\t * engines).\n\t\t */\n\t\tconst pkgInfo = getPackageInfo(tmpDir, packageName);\n\t\tconst peerDepKeys = Object.keys(pkgInfo.peerDependencies);\n\n\t\t/**\n\t\t * Determine platform: use explicit value if provided, otherwise auto-detect\n\t\t * from engines.\n\t\t */\n\t\tlet platform: \"browser\" | \"node\" = \"browser\";\n\t\tif (explicitPlatform) {\n\t\t\tplatform = explicitPlatform;\n\t\t} else if (pkgInfo.engines?.node && !pkgInfo.engines?.browser) {\n\t\t\t// Package specifies node engine without browser - likely a Node.js package.\n\t\t\tplatform = \"node\";\n\t\t}\n\n\t\t// Collect all dependency names (prod + peer).\n\t\tconst allDependencies = [\n\t\t\t...new Set([...Object.keys(pkgInfo.dependencies), ...peerDepKeys]),\n\t\t].sort();\n\n\t\tif (peerDepKeys.length > 0) {\n\t\t\t// Add peer dependencies to package.json.\n\t\t\tfor (const dep of peerDepKeys) {\n\t\t\t\t// Use the version range from peer dependencies.\n\t\t\t\tpackageJson.dependencies[dep] = pkgInfo.peerDependencies[dep];\n\t\t\t}\n\n\t\t\t// Update package.json and reinstall.\n\t\t\tfs.writeFileSync(\n\t\t\t\tpath.join(tmpDir, \"package.json\"),\n\t\t\t\tJSON.stringify(packageJson, null, 2),\n\t\t\t);\n\n\t\t\texecSync(installCmd, {\n\t\t\t\tcwd: tmpDir,\n\t\t\t\tstdio: \"pipe\",\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * Determine if we need to use all subpath exports or find the right\n\t\t * subpath(s).\n\t\t */\n\t\tlet allSubpaths: string[] | undefined;\n\t\tlet resolvedSubpath = subpath;\n\t\tlet exportToSubpath: Map<string, string> | undefined;\n\n\t\tif (!subpath && !pkgInfo.hasMainEntry && pkgInfo.exports) {\n\t\t\tif (exports && exports.length > 0) {\n\t\t\t\t// User specified exports but no subpath - try to find the right subpath(s).\n\t\t\t\tconst mapping = findSubpathsForExports(\n\t\t\t\t\ttmpDir,\n\t\t\t\t\tpackageName,\n\t\t\t\t\tpkgInfo.exports,\n\t\t\t\t\texports,\n\t\t\t\t);\n\n\t\t\t\tif (mapping.singleSubpath) {\n\t\t\t\t\t// All exports from the same subpath.\n\t\t\t\t\tresolvedSubpath = mapping.singleSubpath;\n\t\t\t\t} else if (mapping.exportToSubpath) {\n\t\t\t\t\t// Exports from multiple subpaths.\n\t\t\t\t\texportToSubpath = mapping.exportToSubpath;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If still no subpath resolved and no mapping, bundle all subpaths.\n\t\t\tif (!resolvedSubpath && !exportToSubpath) {\n\t\t\t\tallSubpaths = getSubpathExports(pkgInfo.exports);\n\t\t\t}\n\t\t}\n\n\t\t// Create entry file with appropriate content.\n\t\tconst entryContent = generateEntryContent({\n\t\t\tpackageName,\n\t\t\tsubpath: resolvedSubpath,\n\t\t\texports,\n\t\t\tallSubpaths,\n\t\t\texportToSubpath,\n\t\t});\n\t\tconst entryFile = path.join(tmpDir, \"entry.js\");\n\t\tfs.writeFileSync(entryFile, entryContent);\n\n\t\t/**\n\t\t * Get externals based on package dependencies. Only include react/react-dom\n\t\t * if they're in the package's dependencies or peerDependencies.\n\t\t */\n\t\tlet externals = getExternals(\n\t\t\tpackageName,\n\t\t\tadditionalExternals,\n\t\t\tnoExternal,\n\t\t\tallDependencies,\n\t\t);\n\n\t\t/**\n\t\t * Expand externals to include subpaths for esbuild.\n\t\t * e.g., \"react\" -> [\"react\", \"react/jsx-runtime\", \"react/jsx-dev-runtime\"]\n\t\t */\n\t\tlet esbuildExternals = expandExternalsForEsbuild(externals);\n\n\t\t/**\n\t\t * Bundle with esbuild. We use a two-phase approach:\n\t\t * 1. First attempt with logLevel: \"silent\" to suppress errors\n\t\t * 2. If it fails due to unresolved react imports, auto-add react to externals and retry\n\t\t * This handles packages that don't properly declare react as a peer\n\t\t * dependency.\n\t\t */\n\t\tlet result: esbuild.BuildResult<{ write: false; metafile: true }>;\n\t\ttry {\n\t\t\tresult = await esbuild.build({\n\t\t\t\tentryPoints: [entryFile],\n\t\t\t\tbundle: true,\n\t\t\t\twrite: false,\n\t\t\t\tformat: \"esm\",\n\t\t\t\tplatform,\n\t\t\t\ttarget,\n\t\t\t\tminify: true,\n\t\t\t\ttreeShaking: true,\n\t\t\t\texternal: esbuildExternals,\n\t\t\t\tmetafile: true,\n\t\t\t\tlogLevel: \"silent\", // Suppress errors on first attempt (will retry if needed)\n\t\t\t});\n\t\t} catch (error) {\n\t\t\t/**\n\t\t\t * Parse unresolved module errors using esbuild's structured error format.\n\t\t\t * This handles packages that don't properly declare react as a peer\n\t\t\t * dependency.\n\t\t\t */\n\t\t\tconst { hasUnresolvedReact, hasUnresolvedReactDom } =\n\t\t\t\tparseUnresolvedModules(error);\n\n\t\t\tif (!noExternal && (hasUnresolvedReact || hasUnresolvedReactDom)) {\n\t\t\t\t// Auto-add react and/or react-dom to externals and retry.\n\t\t\t\tconst autoExternals: string[] = [];\n\t\t\t\tif (hasUnresolvedReact && !externals.includes(\"react\")) {\n\t\t\t\t\tautoExternals.push(\"react\");\n\t\t\t\t}\n\t\t\t\tif (hasUnresolvedReactDom && !externals.includes(\"react-dom\")) {\n\t\t\t\t\tautoExternals.push(\"react-dom\");\n\t\t\t\t}\n\n\t\t\t\tif (autoExternals.length > 0) {\n\t\t\t\t\texternals = [...externals, ...autoExternals];\n\t\t\t\t\tesbuildExternals = expandExternalsForEsbuild(externals);\n\n\t\t\t\t\tresult = await esbuild.build({\n\t\t\t\t\t\tentryPoints: [entryFile],\n\t\t\t\t\t\tbundle: true,\n\t\t\t\t\t\twrite: false,\n\t\t\t\t\t\tformat: \"esm\",\n\t\t\t\t\t\tplatform,\n\t\t\t\t\t\ttarget,\n\t\t\t\t\t\tminify: true,\n\t\t\t\t\t\ttreeShaking: true,\n\t\t\t\t\t\texternal: esbuildExternals,\n\t\t\t\t\t\tmetafile: true,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\t// Get raw size.\n\t\tconst bundleContent = result.outputFiles[0].contents;\n\t\tconst rawSize = bundleContent.length;\n\n\t\t// Gzip the bundle (only for browser platform - not relevant for Node.js).\n\t\tlet gzipSize: number | null = null;\n\t\tif (platform === \"browser\") {\n\t\t\tconst gzipped = await gzipAsync(Buffer.from(bundleContent), {\n\t\t\t\tlevel: gzipLevel,\n\t\t\t});\n\t\t\tgzipSize = gzipped.length;\n\t\t}\n\n\t\t// Determine the display name.\n\t\tlet displayName = packageName;\n\t\tif (resolvedSubpath) {\n\t\t\tdisplayName = `${packageName}/${resolvedSubpath}`;\n\t\t} else if (exportToSubpath && exportToSubpath.size > 0) {\n\t\t\t// Multiple subpaths - show them all.\n\t\t\tconst uniqueSubpaths = [...new Set(exportToSubpath.values())].sort();\n\t\t\tdisplayName = `${packageName}/{${uniqueSubpaths.join(\", \")}}`;\n\t\t}\n\n\t\t/**\n\t\t * Get named export count from the package's type definitions. Use\n\t\t * runtimeCount to exclude type-only exports (types, interfaces).\n\t\t */\n\t\tconst { runtimeCount: namedExportCount } = getNamedExports(\n\t\t\ttmpDir,\n\t\t\tpackageName,\n\t\t);\n\n\t\treturn {\n\t\t\tpackageName: displayName,\n\t\t\tpackageVersion: pkgInfo.version,\n\t\t\texports: exports || [],\n\t\t\trawSize,\n\t\t\tgzipSize,\n\t\t\tgzipLevel,\n\t\t\texternals,\n\t\t\tdependencies: allDependencies,\n\t\t\tplatform,\n\t\t\tnamedExportCount,\n\t\t};\n\t} finally {\n\t\tcleanupTempDir(tmpDir);\n\t}\n}\n"],"names":["execSync","fs","os","path","promisify","zlib","esbuild","DEFAULT_EXTERNALS","DEFAULT_TARGET","EXTERNAL_SUBPATHS","getNamedExports","gzipAsync","gzip","escapeRegExp","str","replace","parsePackageSpecifier","specifier","workingSpec","version","startsWith","secondAtIndex","indexOf","substring","parts","split","length","name","subpath","slice","join","atIndex","slashIndex","formatBytes","bytes","k","sizes","i","Math","floor","log","Number","parseFloat","toFixed","createTempDir","tmpDir","tmpdir","Date","now","mkdirSync","recursive","cleanupTempDir","rmSync","force","isPnpmAvailable","stdio","usePnpm","validateRegistryUrl","registry","url","URL","Error","protocol","toString","getInstallCommand","registryArg","sanitizedRegistry","generateEntryContent","options","packageName","exports","allSubpaths","exportToSubpath","size","subpathToExports","Map","exportName","sp","existing","get","push","set","lines","allExportNames","exportNames","importPath","names","importNames","imports","map","isEsbuildBuildFailure","error","Array","isArray","errors","parseUnresolvedModules","result","hasUnresolvedReact","hasUnresolvedReactDom","resolveErrorPattern","err","match","exec","text","modulePath","errorMessage","String","matches","matchAll","getExternals","externals","noExternal","packageDependencies","dep","includes","Set","expandExternalsForEsbuild","expanded","ext","subpaths","getPackageInfo","pkgJsonPath","existsSync","pkgJson","JSON","parse","readFileSync","hasMainEntry","Boolean","main","module","dependencies","peerDependencies","engines","getSubpathExports","key","Object","keys","findSubpathsForExports","componentNames","packageDir","subpathKey","subpathValue","entries","filePath","types","import","fullPath","content","has","escapedName","patterns","RegExp","some","pattern","test","values","singleSubpath","checkBundleSize","packageSpecifier","additionalExternals","gzipLevel","platform","explicitPlatform","target","requestedVersion","packageJson","type","writeFileSync","stringify","installCmd","cwd","pkgInfo","peerDepKeys","node","browser","allDependencies","sort","resolvedSubpath","mapping","entryContent","entryFile","esbuildExternals","build","entryPoints","bundle","write","format","minify","treeShaking","external","metafile","logLevel","autoExternals","bundleContent","outputFiles","contents","rawSize","gzipSize","gzipped","Buffer","from","level","displayName","uniqueSubpaths","runtimeCount","namedExportCount","packageVersion"],"mappings":"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"}
|
package/dist/defaults.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare const defaultFlags: {
|
|
|
7
7
|
registry: string;
|
|
8
8
|
platform: string;
|
|
9
9
|
force: boolean;
|
|
10
|
+
target: string;
|
|
10
11
|
};
|
|
11
12
|
/**
|
|
12
13
|
* Normalize platform aliases to canonical esbuild platform values.
|
|
@@ -20,6 +21,23 @@ export declare function normalizePlatform(platform: string | undefined): "browse
|
|
|
20
21
|
*/
|
|
21
22
|
export declare function isValidPlatform(platform: string | undefined): boolean;
|
|
22
23
|
export declare const TREND_VERSION_COUNT = 5;
|
|
24
|
+
/**
|
|
25
|
+
* Default esbuild target for bundling.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_TARGET = "es2022";
|
|
28
|
+
/**
|
|
29
|
+
* Valid esbuild target values.
|
|
30
|
+
* Includes ECMAScript versions (es2015-es2024, esnext) and browser/runtime targets.
|
|
31
|
+
*/
|
|
32
|
+
export declare const VALID_TARGETS: string[];
|
|
33
|
+
/**
|
|
34
|
+
* Check if a target value is valid.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isValidTarget(target: string | undefined): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Normalize target to lowercase.
|
|
39
|
+
*/
|
|
40
|
+
export declare function normalizeTarget(target: string | undefined): string;
|
|
23
41
|
/**
|
|
24
42
|
* Base packages to auto-detect for externalization. These are checked against
|
|
25
43
|
* the package's dependencies/peerDependencies.
|
package/dist/defaults.js
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
versions: false,
|
|
7
7
|
registry: "",
|
|
8
8
|
platform: "auto",
|
|
9
|
-
force: false
|
|
9
|
+
force: false,
|
|
10
|
+
target: "es2022"
|
|
10
11
|
};
|
|
11
12
|
/**
|
|
12
13
|
* Normalize platform aliases to canonical esbuild platform values.
|
|
@@ -71,6 +72,46 @@
|
|
|
71
72
|
return validValues.includes(normalized);
|
|
72
73
|
}
|
|
73
74
|
export const TREND_VERSION_COUNT = 5;
|
|
75
|
+
/**
|
|
76
|
+
* Default esbuild target for bundling.
|
|
77
|
+
*/ export const DEFAULT_TARGET = "es2022";
|
|
78
|
+
/**
|
|
79
|
+
* Valid esbuild target values.
|
|
80
|
+
* Includes ECMAScript versions (es2015-es2024, esnext) and browser/runtime targets.
|
|
81
|
+
*/ export const VALID_TARGETS = [
|
|
82
|
+
"es2015",
|
|
83
|
+
"es2016",
|
|
84
|
+
"es2017",
|
|
85
|
+
"es2018",
|
|
86
|
+
"es2019",
|
|
87
|
+
"es2020",
|
|
88
|
+
"es2021",
|
|
89
|
+
"es2022",
|
|
90
|
+
"es2023",
|
|
91
|
+
"es2024",
|
|
92
|
+
"esnext"
|
|
93
|
+
];
|
|
94
|
+
/**
|
|
95
|
+
* Check if a target value is valid.
|
|
96
|
+
*/ export function isValidTarget(target) {
|
|
97
|
+
if (target === undefined) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
const normalized = target.toLowerCase().trim();
|
|
101
|
+
// Empty string after trim is invalid.
|
|
102
|
+
if (normalized === "") {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
return VALID_TARGETS.includes(normalized);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Normalize target to lowercase.
|
|
109
|
+
*/ export function normalizeTarget(target) {
|
|
110
|
+
if (!target) {
|
|
111
|
+
return DEFAULT_TARGET;
|
|
112
|
+
}
|
|
113
|
+
return target.toLowerCase().trim();
|
|
114
|
+
}
|
|
74
115
|
/**
|
|
75
116
|
* Base packages to auto-detect for externalization. These are checked against
|
|
76
117
|
* the package's dependencies/peerDependencies.
|
package/dist/defaults.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/defaults.ts"],"sourcesContent":["/* istanbul ignore file */\n\nexport const defaultFlags = {\n\tboring: false,\n\tgzipLevel: 5,\n\texternal: \"\",\n\tnoExternal: false,\n\tversions: false,\n\tregistry: \"\",\n\tplatform: \"auto\",\n\tforce: false,\n};\n\n/**\n * Normalize platform aliases to canonical esbuild platform values.\n * - \"auto\" → undefined (triggers auto-detection based on package engines)\n * - Browser aliases: \"browser\", \"web\", \"desktop\", \"client\" → \"browser\"\n * - Node aliases: \"node\", \"server\", \"nodejs\", \"backend\" → \"node\"\n */\nexport function normalizePlatform(\n\tplatform: string | undefined,\n): \"browser\" | \"node\" | undefined {\n\tif (!platform) {\n\t\treturn undefined;\n\t}\n\n\tconst normalized = platform.toLowerCase().trim();\n\n\t// Auto-detect from package.json engines.\n\tif (normalized === \"auto\") {\n\t\treturn undefined;\n\t}\n\n\t// Node aliases.\n\tif ([\"node\", \"server\", \"nodejs\", \"backend\"].includes(normalized)) {\n\t\treturn \"node\";\n\t}\n\n\t// Browser aliases.\n\tif ([\"browser\", \"web\", \"desktop\", \"client\"].includes(normalized)) {\n\t\treturn \"browser\";\n\t}\n\n\t// Invalid value - will be caught by validation.\n\treturn normalized as \"browser\" | \"node\";\n}\n\n/**\n * Check if a platform value is valid (either canonical or alias).\n */\nexport function isValidPlatform(platform: string | undefined): boolean {\n\tif (platform === undefined) {\n\t\treturn true;\n\t}\n\n\tconst normalized = platform.toLowerCase().trim();\n\n\t// Empty string after trim is invalid.\n\tif (normalized === \"\") {\n\t\treturn false;\n\t}\n\tconst validValues = [\n\t\t// Auto-detect.\n\t\t\"auto\",\n\t\t// Browser.\n\t\t\"browser\",\n\t\t\"web\",\n\t\t\"desktop\",\n\t\t\"client\",\n\t\t// Node.\n\t\t\"node\",\n\t\t\"server\",\n\t\t\"nodejs\",\n\t\t\"backend\",\n\t];\n\n\treturn validValues.includes(normalized);\n}\n\nexport const TREND_VERSION_COUNT = 5;\n\n/**\n * Base packages to auto-detect for externalization. These are checked against\n * the package's dependencies/peerDependencies.\n */\nexport const DEFAULT_EXTERNALS = [\"react\", \"react-dom\"];\n\n/**\n * Subpath externals to add when a base package is detected. When \"react\" is in\n * dependencies, we also need to externalize \"react/jsx-runtime\" etc. because\n * esbuild doesn't automatically externalize subpaths.\n */\nexport const EXTERNAL_SUBPATHS: Record<string, string[]> = {\n\treact: [\"react/jsx-runtime\", \"react/jsx-dev-runtime\"],\n\t\"react-dom\": [\"react-dom/client\", \"react-dom/server\"],\n};\n\nexport const DEFAULT_REGISTRY = \"https://registry.npmjs.org\";\n"],"names":["defaultFlags","boring","gzipLevel","external","noExternal","versions","registry","platform","force","normalizePlatform","undefined","normalized","toLowerCase","trim","includes","isValidPlatform","validValues","TREND_VERSION_COUNT","DEFAULT_EXTERNALS","EXTERNAL_SUBPATHS","react","DEFAULT_REGISTRY"],"mappings":"AAAA,wBAAwB,GAExB,OAAO,MAAMA,eAAe;IAC3BC,QAAQ;IACRC,WAAW;IACXC,UAAU;IACVC,YAAY;IACZC,UAAU;IACVC,UAAU;IACVC,UAAU;IACVC,OAAO;
|
|
1
|
+
{"version":3,"sources":["../src/defaults.ts"],"sourcesContent":["/* istanbul ignore file */\n\nexport const defaultFlags = {\n\tboring: false,\n\tgzipLevel: 5,\n\texternal: \"\",\n\tnoExternal: false,\n\tversions: false,\n\tregistry: \"\",\n\tplatform: \"auto\",\n\tforce: false,\n\ttarget: \"es2022\",\n};\n\n/**\n * Normalize platform aliases to canonical esbuild platform values.\n * - \"auto\" → undefined (triggers auto-detection based on package engines)\n * - Browser aliases: \"browser\", \"web\", \"desktop\", \"client\" → \"browser\"\n * - Node aliases: \"node\", \"server\", \"nodejs\", \"backend\" → \"node\"\n */\nexport function normalizePlatform(\n\tplatform: string | undefined,\n): \"browser\" | \"node\" | undefined {\n\tif (!platform) {\n\t\treturn undefined;\n\t}\n\n\tconst normalized = platform.toLowerCase().trim();\n\n\t// Auto-detect from package.json engines.\n\tif (normalized === \"auto\") {\n\t\treturn undefined;\n\t}\n\n\t// Node aliases.\n\tif ([\"node\", \"server\", \"nodejs\", \"backend\"].includes(normalized)) {\n\t\treturn \"node\";\n\t}\n\n\t// Browser aliases.\n\tif ([\"browser\", \"web\", \"desktop\", \"client\"].includes(normalized)) {\n\t\treturn \"browser\";\n\t}\n\n\t// Invalid value - will be caught by validation.\n\treturn normalized as \"browser\" | \"node\";\n}\n\n/**\n * Check if a platform value is valid (either canonical or alias).\n */\nexport function isValidPlatform(platform: string | undefined): boolean {\n\tif (platform === undefined) {\n\t\treturn true;\n\t}\n\n\tconst normalized = platform.toLowerCase().trim();\n\n\t// Empty string after trim is invalid.\n\tif (normalized === \"\") {\n\t\treturn false;\n\t}\n\tconst validValues = [\n\t\t// Auto-detect.\n\t\t\"auto\",\n\t\t// Browser.\n\t\t\"browser\",\n\t\t\"web\",\n\t\t\"desktop\",\n\t\t\"client\",\n\t\t// Node.\n\t\t\"node\",\n\t\t\"server\",\n\t\t\"nodejs\",\n\t\t\"backend\",\n\t];\n\n\treturn validValues.includes(normalized);\n}\n\nexport const TREND_VERSION_COUNT = 5;\n\n/**\n * Default esbuild target for bundling.\n */\nexport const DEFAULT_TARGET = \"es2022\";\n\n/**\n * Valid esbuild target values.\n * Includes ECMAScript versions (es2015-es2024, esnext) and browser/runtime targets.\n */\nexport const VALID_TARGETS = [\n\t\"es2015\",\n\t\"es2016\",\n\t\"es2017\",\n\t\"es2018\",\n\t\"es2019\",\n\t\"es2020\",\n\t\"es2021\",\n\t\"es2022\",\n\t\"es2023\",\n\t\"es2024\",\n\t\"esnext\",\n];\n\n/**\n * Check if a target value is valid.\n */\nexport function isValidTarget(target: string | undefined): boolean {\n\tif (target === undefined) {\n\t\treturn true;\n\t}\n\n\tconst normalized = target.toLowerCase().trim();\n\n\t// Empty string after trim is invalid.\n\tif (normalized === \"\") {\n\t\treturn false;\n\t}\n\n\treturn VALID_TARGETS.includes(normalized);\n}\n\n/**\n * Normalize target to lowercase.\n */\nexport function normalizeTarget(target: string | undefined): string {\n\tif (!target) {\n\t\treturn DEFAULT_TARGET;\n\t}\n\treturn target.toLowerCase().trim();\n}\n\n/**\n * Base packages to auto-detect for externalization. These are checked against\n * the package's dependencies/peerDependencies.\n */\nexport const DEFAULT_EXTERNALS = [\"react\", \"react-dom\"];\n\n/**\n * Subpath externals to add when a base package is detected. When \"react\" is in\n * dependencies, we also need to externalize \"react/jsx-runtime\" etc. because\n * esbuild doesn't automatically externalize subpaths.\n */\nexport const EXTERNAL_SUBPATHS: Record<string, string[]> = {\n\treact: [\"react/jsx-runtime\", \"react/jsx-dev-runtime\"],\n\t\"react-dom\": [\"react-dom/client\", \"react-dom/server\"],\n};\n\nexport const DEFAULT_REGISTRY = \"https://registry.npmjs.org\";\n"],"names":["defaultFlags","boring","gzipLevel","external","noExternal","versions","registry","platform","force","target","normalizePlatform","undefined","normalized","toLowerCase","trim","includes","isValidPlatform","validValues","TREND_VERSION_COUNT","DEFAULT_TARGET","VALID_TARGETS","isValidTarget","normalizeTarget","DEFAULT_EXTERNALS","EXTERNAL_SUBPATHS","react","DEFAULT_REGISTRY"],"mappings":"AAAA,wBAAwB,GAExB,OAAO,MAAMA,eAAe;IAC3BC,QAAQ;IACRC,WAAW;IACXC,UAAU;IACVC,YAAY;IACZC,UAAU;IACVC,UAAU;IACVC,UAAU;IACVC,OAAO;IACPC,QAAQ;AACT,EAAE;AAEF;;;;;CAKC,GACD,OAAO,SAASC,kBACfH,QAA4B;IAE5B,IAAI,CAACA,UAAU;QACd,OAAOI;IACR;IAEA,MAAMC,aAAaL,SAASM,WAAW,GAAGC,IAAI;IAE9C,yCAAyC;IACzC,IAAIF,eAAe,QAAQ;QAC1B,OAAOD;IACR;IAEA,gBAAgB;IAChB,IAAI;QAAC;QAAQ;QAAU;QAAU;KAAU,CAACI,QAAQ,CAACH,aAAa;QACjE,OAAO;IACR;IAEA,mBAAmB;IACnB,IAAI;QAAC;QAAW;QAAO;QAAW;KAAS,CAACG,QAAQ,CAACH,aAAa;QACjE,OAAO;IACR;IAEA,gDAAgD;IAChD,OAAOA;AACR;AAEA;;CAEC,GACD,OAAO,SAASI,gBAAgBT,QAA4B;IAC3D,IAAIA,aAAaI,WAAW;QAC3B,OAAO;IACR;IAEA,MAAMC,aAAaL,SAASM,WAAW,GAAGC,IAAI;IAE9C,sCAAsC;IACtC,IAAIF,eAAe,IAAI;QACtB,OAAO;IACR;IACA,MAAMK,cAAc;QACnB,eAAe;QACf;QACA,WAAW;QACX;QACA;QACA;QACA;QACA,QAAQ;QACR;QACA;QACA;QACA;KACA;IAED,OAAOA,YAAYF,QAAQ,CAACH;AAC7B;AAEA,OAAO,MAAMM,sBAAsB,EAAE;AAErC;;CAEC,GACD,OAAO,MAAMC,iBAAiB,SAAS;AAEvC;;;CAGC,GACD,OAAO,MAAMC,gBAAgB;IAC5B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACA,CAAC;AAEF;;CAEC,GACD,OAAO,SAASC,cAAcZ,MAA0B;IACvD,IAAIA,WAAWE,WAAW;QACzB,OAAO;IACR;IAEA,MAAMC,aAAaH,OAAOI,WAAW,GAAGC,IAAI;IAE5C,sCAAsC;IACtC,IAAIF,eAAe,IAAI;QACtB,OAAO;IACR;IAEA,OAAOQ,cAAcL,QAAQ,CAACH;AAC/B;AAEA;;CAEC,GACD,OAAO,SAASU,gBAAgBb,MAA0B;IACzD,IAAI,CAACA,QAAQ;QACZ,OAAOU;IACR;IACA,OAAOV,OAAOI,WAAW,GAAGC,IAAI;AACjC;AAEA;;;CAGC,GACD,OAAO,MAAMS,oBAAoB;IAAC;IAAS;CAAY,CAAC;AAExD;;;;CAIC,GACD,OAAO,MAAMC,oBAA8C;IAC1DC,OAAO;QAAC;QAAqB;KAAwB;IACrD,aAAa;QAAC;QAAoB;KAAmB;AACtD,EAAE;AAEF,OAAO,MAAMC,mBAAmB,6BAA6B"}
|
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,10 @@ export type GetBundleStatsOptions = {
|
|
|
47
47
|
* Bypass cache and force re-analysis.
|
|
48
48
|
*/
|
|
49
49
|
force?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* esbuild target (e.g., "es2022", "es2020"). Defaults to "es2022".
|
|
52
|
+
*/
|
|
53
|
+
target?: string;
|
|
50
54
|
};
|
|
51
55
|
/**
|
|
52
56
|
* Result from getBundleStats.
|
|
@@ -147,6 +151,10 @@ export type GetBundleTrendOptions = {
|
|
|
147
151
|
* Bypass cache and force re-analysis.
|
|
148
152
|
*/
|
|
149
153
|
force?: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* esbuild target (e.g., "es2022", "es2020"). Defaults to "es2022".
|
|
156
|
+
*/
|
|
157
|
+
target?: string;
|
|
150
158
|
};
|
|
151
159
|
/**
|
|
152
160
|
* Single version result in trend analysis.
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
*/ import { checkBundleSize, formatBytes, parsePackageSpecifier } from "./bundler.js";
|
|
7
7
|
import { getCachedResult, normalizeCacheKey, setCachedResult } from "./cache.js";
|
|
8
|
-
import { normalizePlatform, TREND_VERSION_COUNT } from "./defaults.js";
|
|
8
|
+
import { normalizePlatform, normalizeTarget, TREND_VERSION_COUNT } from "./defaults.js";
|
|
9
9
|
import { analyzeTrend, selectTrendVersions } from "./trend.js";
|
|
10
10
|
import { fetchPackageVersions as fetchVersions } from "./versions.js";
|
|
11
11
|
/**
|
|
@@ -28,9 +28,11 @@ import { fetchPackageVersions as fetchVersions } from "./versions.js";
|
|
|
28
28
|
* ```
|
|
29
29
|
*
|
|
30
30
|
*/ export async function getBundleStats(options) {
|
|
31
|
-
const { package: packageName, exports: exportsList, external: additionalExternals, noExternal, gzipLevel = 5, registry, platform: platformOption = "auto", force = false } = options;
|
|
31
|
+
const { package: packageName, exports: exportsList, external: additionalExternals, noExternal, gzipLevel = 5, registry, platform: platformOption = "auto", force = false, target: targetOption } = options;
|
|
32
32
|
// Normalize platform.
|
|
33
33
|
const platform = normalizePlatform(platformOption === "auto" ? undefined : platformOption);
|
|
34
|
+
// Normalize target.
|
|
35
|
+
const target = normalizeTarget(targetOption);
|
|
34
36
|
// Parse package specifier.
|
|
35
37
|
const { name: baseName, version: requestedVersion } = parsePackageSpecifier(packageName);
|
|
36
38
|
// Resolve "latest" to actual version for cache key.
|
|
@@ -71,7 +73,8 @@ import { fetchPackageVersions as fetchVersions } from "./versions.js";
|
|
|
71
73
|
noExternal,
|
|
72
74
|
gzipLevel,
|
|
73
75
|
registry,
|
|
74
|
-
platform
|
|
76
|
+
platform,
|
|
77
|
+
target
|
|
75
78
|
});
|
|
76
79
|
// Store in cache.
|
|
77
80
|
setCachedResult(cacheKey, result);
|
|
@@ -93,9 +96,11 @@ import { fetchPackageVersions as fetchVersions } from "./versions.js";
|
|
|
93
96
|
* ```
|
|
94
97
|
*
|
|
95
98
|
*/ export async function getBundleTrend(options) {
|
|
96
|
-
const { package: packageName, versionCount = TREND_VERSION_COUNT, exports: exportsList, external: additionalExternals, noExternal, gzipLevel, registry, platform: platformOption = "auto", force = false } = options;
|
|
99
|
+
const { package: packageName, versionCount = TREND_VERSION_COUNT, exports: exportsList, external: additionalExternals, noExternal, gzipLevel, registry, platform: platformOption = "auto", force = false, target: targetOption } = options;
|
|
97
100
|
// Normalize platform.
|
|
98
101
|
const platform = normalizePlatform(platformOption === "auto" ? undefined : platformOption);
|
|
102
|
+
// Normalize target.
|
|
103
|
+
const target = normalizeTarget(targetOption);
|
|
99
104
|
// Parse package name (ignore version if provided).
|
|
100
105
|
const { name: baseName, subpath } = parsePackageSpecifier(packageName);
|
|
101
106
|
const fullPackagePath = subpath ? `${baseName}/${subpath}` : baseName;
|
|
@@ -120,7 +125,8 @@ import { fetchPackageVersions as fetchVersions } from "./versions.js";
|
|
|
120
125
|
boring: true,
|
|
121
126
|
registry,
|
|
122
127
|
platform,
|
|
123
|
-
force
|
|
128
|
+
force,
|
|
129
|
+
target
|
|
124
130
|
});
|
|
125
131
|
if (results.length === 0) {
|
|
126
132
|
throw new Error(`Failed to analyze any versions for package: ${baseName}`);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @node-cli/bundlecheck - Library API\n *\n * Programmatic interface for analyzing npm package bundle sizes.\n *\n */\n\nimport {\n\ttype BundleResult,\n\tcheckBundleSize,\n\tformatBytes,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport { normalizePlatform, TREND_VERSION_COUNT } from \"./defaults.js\";\nimport type { NamedExport } from \"./exports.js\";\nimport { analyzeTrend, selectTrendVersions } from \"./trend.js\";\nimport { fetchPackageVersions as fetchVersions } from \"./versions.js\";\n\n/**\n * =============================================================================\n * Types\n * =============================================================================\n */\n\n/**\n * Options for getting bundle stats of a single package.\n */\nexport type GetBundleStatsOptions = {\n\t/**\n\t * Package name with optional version (e.g., \"@mantine/core\" or\n\t * \"@mantine/core@7.0.0\").\n\t */\n\tpackage: string;\n\t/**\n\t * Specific exports to measure (e.g., [\"Button\", \"Input\"]).\n\t */\n\texports?: string[];\n\t/**\n\t * Additional packages to mark as external (not bundled).\n\t */\n\texternal?: string[];\n\t/**\n\t * Bundle everything including dependencies that would normally be external.\n\t */\n\tnoExternal?: boolean;\n\t/**\n\t * Gzip compression level (1-9, default 5).\n\t */\n\tgzipLevel?: number;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n\t/**\n\t * Target platform: \"browser\", \"node\", or \"auto\" (default: \"auto\" - auto-detect\n\t * from package.json).\n\t */\n\tplatform?: \"browser\" | \"node\" | \"auto\";\n\t/**\n\t * Bypass cache and force re-analysis.\n\t */\n\tforce?: boolean;\n};\n\n/**\n * Result from getBundleStats.\n */\nexport type BundleStats = {\n\t/**\n\t * Display name of the package (may include subpath).\n\t */\n\tpackageName: string;\n\t/**\n\t * Resolved package version.\n\t */\n\tpackageVersion: string;\n\t/**\n\t * Exports that were analyzed.\n\t */\n\texports: string[];\n\t/**\n\t * Raw (minified) bundle size in bytes.\n\t */\n\trawSize: number;\n\t/**\n\t * Gzipped bundle size in bytes (null for node platform).\n\t */\n\tgzipSize: number | null;\n\t/**\n\t * Gzip compression level used.\n\t */\n\tgzipLevel: number;\n\t/**\n\t * Packages marked as external (not included in bundle).\n\t */\n\texternals: string[];\n\t/**\n\t * Package dependencies.\n\t */\n\tdependencies: string[];\n\t/**\n\t * Target platform used for bundling.\n\t */\n\tplatform: \"browser\" | \"node\";\n\t/**\n\t * Human-readable raw size (e.g., \"45.2 kB\").\n\t */\n\trawSizeFormatted: string;\n\t/**\n\t * Human-readable gzip size (e.g., \"12.3 kB\") or null.\n\t */\n\tgzipSizeFormatted: string | null;\n\t/**\n\t * Whether the result was retrieved from cache.\n\t */\n\tfromCache: boolean;\n\t/**\n\t * Total number of named exports in the package (when analyzing entire\n\t * package).\n\t */\n\tnamedExportCount: number;\n};\n\n/**\n * Options for getting bundle size trend across versions.\n */\nexport type GetBundleTrendOptions = {\n\t/**\n\t * Package name (e.g., \"@mantine/core\") - version is ignored if provided.\n\t */\n\tpackage: string;\n\t/**\n\t * Number of versions to analyze (default 5).\n\t */\n\tversionCount?: number;\n\t/**\n\t * Specific exports to measure (e.g., [\"Button\", \"Input\"]).\n\t */\n\texports?: string[];\n\t/**\n\t * Additional packages to mark as external (not bundled).\n\t */\n\texternal?: string[];\n\t/**\n\t * Bundle everything including dependencies that would normally be external.\n\t */\n\tnoExternal?: boolean;\n\t/**\n\t * Gzip compression level (1-9, default 5).\n\t */\n\tgzipLevel?: number;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n\t/**\n\t * Target platform: \"browser\", \"node\", or \"auto\" (default: \"auto\" - auto-detect\n\t * from package.json).\n\t */\n\tplatform?: \"browser\" | \"node\" | \"auto\";\n\t/**\n\t * Bypass cache and force re-analysis.\n\t */\n\tforce?: boolean;\n};\n\n/**\n * Single version result in trend analysis.\n */\nexport type TrendVersionResult = {\n\t/**\n\t * Package version.\n\t */\n\tversion: string;\n\t/**\n\t * Raw (minified) bundle size in bytes.\n\t */\n\trawSize: number;\n\t/**\n\t * Gzipped bundle size in bytes (null for node platform).\n\t */\n\tgzipSize: number | null;\n\t/**\n\t * Human-readable raw size (e.g., \"45.2 kB\").\n\t */\n\trawSizeFormatted: string;\n\t/**\n\t * Human-readable gzip size (e.g., \"12.3 kB\") or null.\n\t */\n\tgzipSizeFormatted: string | null;\n};\n\n/**\n * Size change information between oldest and newest versions.\n */\nexport type TrendChange = {\n\t/**\n\t * Oldest version analyzed.\n\t */\n\tfromVersion: string;\n\t/**\n\t * Newest version analyzed.\n\t */\n\ttoVersion: string;\n\t/**\n\t * Raw size difference in bytes (positive = increase, negative = decrease).\n\t */\n\trawDiff: number;\n\t/**\n\t * Raw size percentage change (null if oldest size was 0).\n\t */\n\trawPercent: number | null;\n\t/**\n\t * Human-readable raw size change (e.g., \"+5.2 kB\" or \"-1.3 kB\").\n\t */\n\trawDiffFormatted: string;\n\t/**\n\t * Gzip size difference in bytes (null if not applicable).\n\t */\n\tgzipDiff: number | null;\n\t/**\n\t * Gzip size percentage change (null if not applicable or oldest size was 0).\n\t */\n\tgzipPercent: number | null;\n\t/**\n\t * Human-readable gzip size change (e.g., \"+1.5 kB\" or \"-0.8 kB\") or null.\n\t */\n\tgzipDiffFormatted: string | null;\n};\n\n/**\n * Result from getBundleTrend.\n */\nexport type BundleTrend = {\n\t/**\n\t * Package name.\n\t */\n\tpackageName: string;\n\t/**\n\t * Results for each version analyzed (newest first).\n\t */\n\tversions: TrendVersionResult[];\n\t/**\n\t * Size change between oldest and newest versions (null if only one version).\n\t */\n\tchange: TrendChange | null;\n};\n\n/**\n * Options for fetching package versions.\n */\nexport type GetPackageVersionsOptions = {\n\t/**\n\t * Package name (e.g., \"@mantine/core\").\n\t */\n\tpackage: string;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n};\n\n/**\n * Result from getPackageVersions.\n */\nexport type PackageVersions = {\n\t/**\n\t * All available versions (sorted newest first).\n\t */\n\tversions: string[];\n\t/**\n\t * Distribution tags (e.g., { latest: \"7.0.0\", next: \"8.0.0-beta.1\" }).\n\t */\n\ttags: Record<string, string>;\n};\n\n/**\n * =============================================================================\n * Library Functions\n * =============================================================================\n */\n\n/**\n * Get bundle size statistics for an npm package.\n *\n * @example\n * ```js\n * import { getBundleStats } from \"@node-cli/bundlecheck\";\n *\n * const stats = await getBundleStats({\n * package: \"@mantine/core@7.0.0\",\n * exports: [\"Button\", \"Input\"],\n * });\n *\n * console.log(stats.gzipSizeFormatted); // \"12.3 kB\"\n * ```\n *\n */\nexport async function getBundleStats(\n\toptions: GetBundleStatsOptions,\n): Promise<BundleStats> {\n\tconst {\n\t\tpackage: packageName,\n\t\texports: exportsList,\n\t\texternal: additionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel = 5,\n\t\tregistry,\n\t\tplatform: platformOption = \"auto\",\n\t\tforce = false,\n\t} = options;\n\n\t// Normalize platform.\n\tconst platform = normalizePlatform(\n\t\tplatformOption === \"auto\" ? undefined : platformOption,\n\t);\n\n\t// Parse package specifier.\n\tconst { name: baseName, version: requestedVersion } =\n\t\tparsePackageSpecifier(packageName);\n\n\t// Resolve \"latest\" to actual version for cache key.\n\tlet resolvedVersion = requestedVersion;\n\tif (requestedVersion === \"latest\") {\n\t\tconst { tags } = await fetchVersions({\n\t\t\tpackageName: baseName,\n\t\t\tregistry,\n\t\t});\n\t\tresolvedVersion = tags.latest || requestedVersion;\n\t}\n\n\t/**\n\t * Build cache key.\n\t * NOTE: We use additionalExternals here, not computed externals, because the default externals (react, react-dom) are determined at bundle time based on the package's dependencies.\n\t * The cache key captures the user's intent (additionalExternals + noExternal\n\t * flag), and the actual externals are stored in the cached result.\n\t */\n\tconst cacheKey = normalizeCacheKey({\n\t\tpackageName: baseName,\n\t\tversion: resolvedVersion,\n\t\texports: exportsList,\n\t\tplatform,\n\t\tgzipLevel,\n\t\texternals: additionalExternals || [],\n\t\tnoExternal: noExternal ?? false,\n\t});\n\n\t// Check cache (unless force is set).\n\tif (!force) {\n\t\tconst cached = getCachedResult(cacheKey);\n\t\tif (cached) {\n\t\t\treturn formatBundleStats(cached, true);\n\t\t}\n\t}\n\n\t// Perform the analysis.\n\tconst result = await checkBundleSize({\n\t\tpackageName,\n\t\texports: exportsList,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tregistry,\n\t\tplatform,\n\t});\n\n\t// Store in cache.\n\tsetCachedResult(cacheKey, result);\n\n\treturn formatBundleStats(result, false);\n}\n\n/**\n * Get bundle size trend across multiple versions of a package.\n *\n * @example\n * ```js\n * import { getBundleTrend } from \"@node-cli/bundlecheck\";\n *\n * const trend = await getBundleTrend({\n * package: \"@mantine/core\",\n * versionCount: 5,\n * });\n *\n * console.log(trend.change?.rawDiffFormatted); // \"+5.2 kB\"\n * ```\n *\n */\nexport async function getBundleTrend(\n\toptions: GetBundleTrendOptions,\n): Promise<BundleTrend> {\n\tconst {\n\t\tpackage: packageName,\n\t\tversionCount = TREND_VERSION_COUNT,\n\t\texports: exportsList,\n\t\texternal: additionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tregistry,\n\t\tplatform: platformOption = \"auto\",\n\t\tforce = false,\n\t} = options;\n\n\t// Normalize platform.\n\tconst platform = normalizePlatform(\n\t\tplatformOption === \"auto\" ? undefined : platformOption,\n\t);\n\n\t// Parse package name (ignore version if provided).\n\tconst { name: baseName, subpath } = parsePackageSpecifier(packageName);\n\tconst fullPackagePath = subpath ? `${baseName}/${subpath}` : baseName;\n\n\t// Fetch available versions.\n\tconst { versions } = await fetchVersions({\n\t\tpackageName: baseName,\n\t\tregistry,\n\t});\n\n\tif (versions.length === 0) {\n\t\tthrow new Error(`No versions found for package: ${baseName}`);\n\t}\n\n\t// Select versions for trend.\n\tconst trendVersions = selectTrendVersions(versions, versionCount);\n\n\t// Analyze all versions (silently - no console output).\n\tconst results = await analyzeTrend({\n\t\tpackageName: fullPackagePath,\n\t\tversions: trendVersions,\n\t\texports: exportsList,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tboring: true, // Suppress logging\n\t\tregistry,\n\t\tplatform,\n\t\tforce,\n\t});\n\n\tif (results.length === 0) {\n\t\tthrow new Error(`Failed to analyze any versions for package: ${baseName}`);\n\t}\n\n\t// Format results.\n\tconst formattedVersions: TrendVersionResult[] = results.map((r) => ({\n\t\tversion: r.version,\n\t\trawSize: r.rawSize,\n\t\tgzipSize: r.gzipSize,\n\t\trawSizeFormatted: formatBytes(r.rawSize),\n\t\tgzipSizeFormatted: r.gzipSize !== null ? formatBytes(r.gzipSize) : null,\n\t}));\n\n\t// Calculate change between oldest and newest.\n\tlet change: TrendChange | null = null;\n\tif (results.length > 1) {\n\t\tconst newest = results[0];\n\t\tconst oldest = results[results.length - 1];\n\n\t\tconst rawDiff = newest.rawSize - oldest.rawSize;\n\t\t// Handle division by zero: if oldest size is 0, percent is null.\n\t\tconst rawPercent =\n\t\t\toldest.rawSize === 0 ? null : (rawDiff / oldest.rawSize) * 100;\n\n\t\tlet gzipDiff: number | null = null;\n\t\tlet gzipPercent: number | null = null;\n\t\tlet gzipDiffFormatted: string | null = null;\n\n\t\tif (newest.gzipSize !== null && oldest.gzipSize !== null) {\n\t\t\tgzipDiff = newest.gzipSize - oldest.gzipSize;\n\t\t\t// Handle division by zero: if oldest size is 0, percent is null.\n\t\t\tgzipPercent =\n\t\t\t\toldest.gzipSize === 0 ? null : (gzipDiff / oldest.gzipSize) * 100;\n\t\t\tgzipDiffFormatted =\n\t\t\t\tgzipDiff >= 0\n\t\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\n\t\t}\n\n\t\tchange = {\n\t\t\tfromVersion: oldest.version,\n\t\t\ttoVersion: newest.version,\n\t\t\trawDiff,\n\t\t\trawPercent:\n\t\t\t\trawPercent !== null ? Number.parseFloat(rawPercent.toFixed(1)) : null,\n\t\t\trawDiffFormatted:\n\t\t\t\trawDiff >= 0\n\t\t\t\t\t? `+${formatBytes(rawDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(rawDiff))}`,\n\t\t\tgzipDiff,\n\t\t\tgzipPercent:\n\t\t\t\tgzipPercent !== null ? Number.parseFloat(gzipPercent.toFixed(1)) : null,\n\t\t\tgzipDiffFormatted,\n\t\t};\n\t}\n\n\treturn {\n\t\tpackageName: fullPackagePath,\n\t\tversions: formattedVersions,\n\t\tchange,\n\t};\n}\n\n/**\n * Get available versions for an npm package.\n *\n * @example\n * ```js\n * import { getPackageVersions } from \"@node-cli/bundlecheck\";\n *\n * const { versions, tags } = await getPackageVersions({\n * package: \"@mantine/core\",\n * });\n *\n * console.log(tags.latest); // \"7.0.0\"\n * ```\n *\n */\nexport async function getPackageVersions(\n\toptions: GetPackageVersionsOptions,\n): Promise<PackageVersions> {\n\tconst { package: packageName, registry } = options;\n\n\tconst result = await fetchVersions({\n\t\tpackageName,\n\t\tregistry,\n\t});\n\n\treturn {\n\t\tversions: result.versions,\n\t\ttags: result.tags,\n\t};\n}\n\n/**\n * Options for getting package exports.\n */\nexport type GetPackageExportsOptions = {\n\t/**\n\t * Package name with optional version (e.g., \"@mantine/core\" or\n\t * \"@mantine/core@7.0.0\").\n\t */\n\tpackage: string;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n};\n\n/**\n * A named export from a package.\n */\nexport type PackageExport = {\n\t/**\n\t * The export name (e.g., \"Button\", \"useState\").\n\t */\n\tname: string;\n\t/**\n\t * The type of export.\n\t */\n\tkind:\n\t\t| \"function\"\n\t\t| \"class\"\n\t\t| \"const\"\n\t\t| \"type\"\n\t\t| \"interface\"\n\t\t| \"enum\"\n\t\t| \"unknown\";\n};\n\n/**\n * Result from getPackageExports.\n */\nexport type PackageExports = {\n\t/**\n\t * Package name.\n\t */\n\tpackageName: string;\n\t/**\n\t * Resolved package version.\n\t */\n\tpackageVersion: string;\n\t/**\n\t * Array of all named exports found in the package (including types).\n\t */\n\texports: PackageExport[];\n\t/**\n\t * Total count of all named exports (including types).\n\t */\n\tcount: number;\n\t/**\n\t * Array of runtime exports only (excluding types and interfaces). These are\n\t * the exports that can actually be imported at runtime.\n\t */\n\truntimeExports: PackageExport[];\n\t/**\n\t * Count of runtime exports only (functions, classes, const, enums).\n\t */\n\truntimeCount: number;\n};\n\n/**\n * Get the named exports of an npm package by analyzing its type definitions.\n *\n * @example\n * ```js\n * import { getPackageExports } from \"@node-cli/bundlecheck\";\n *\n * const { exports, count } = await getPackageExports({\n * package: \"@mantine/core@7.0.0\",\n * });\n *\n * console.log(`Found ${count} exports`);\n * console.log(exports.map(e => e.name)); // [\"Accordion\", \"ActionIcon\", \"Alert\", ...]\n * ```\n *\n */\nexport async function getPackageExports(\n\toptions: GetPackageExportsOptions,\n): Promise<PackageExports> {\n\tconst { package: packageName, registry } = options;\n\n\t/**\n\t * Import the install utilities from bundler (we'll use a minimal bundle\n\t * check).\n\t */\n\tconst { name: baseName, version: requestedVersion } =\n\t\tparsePackageSpecifier(packageName);\n\n\t// Resolve \"latest\" to actual version.\n\tlet resolvedVersion = requestedVersion;\n\tif (requestedVersion === \"latest\") {\n\t\tconst { tags } = await fetchVersions({\n\t\t\tpackageName: baseName,\n\t\t\tregistry,\n\t\t});\n\t\tresolvedVersion = tags.latest || requestedVersion;\n\t}\n\n\t/**\n\t * Use a minimal bundle check to install the package and get exports We'll\n\t * leverage the existing infrastructure.\n\t */\n\tconst { installPackage } = await import(\"./exports-installer.js\");\n\n\tconst { version, exports, runtimeExports } = await installPackage({\n\t\tpackageName: baseName,\n\t\tversion: resolvedVersion,\n\t\tregistry,\n\t});\n\n\treturn {\n\t\tpackageName: baseName,\n\t\tpackageVersion: version,\n\t\texports: exports.map((e: NamedExport) => ({\n\t\t\tname: e.name,\n\t\t\tkind: e.kind,\n\t\t})),\n\t\tcount: exports.length,\n\t\truntimeExports: runtimeExports.map((e: NamedExport) => ({\n\t\t\tname: e.name,\n\t\t\tkind: e.kind,\n\t\t})),\n\t\truntimeCount: runtimeExports.length,\n\t};\n}\n\n/**\n * =============================================================================\n * Re-exports for advanced usage\n * =============================================================================\n */\n\n/**\n * - Format bytes to human-readable string (e.g., 1024 → \"1 kB\").\n * - Parse a package specifier (e.g., \"@scope/name@1.0.0\" → { name, version,\n * subpath }).\n */\nexport { formatBytes, parsePackageSpecifier } from \"./bundler.js\";\n/**\n * - Clear the bundle cache.\n * - Get the number of cached entries.\n */\nexport { clearCache, getCacheCount } from \"./cache.js\";\n\n/**\n * =============================================================================\n * Internal Helpers\n * =============================================================================\n */\n\n/**\n * Format a BundleResult into a BundleStats object.\n */\nfunction formatBundleStats(\n\tresult: BundleResult,\n\tfromCache: boolean,\n): BundleStats {\n\treturn {\n\t\tpackageName: result.packageName,\n\t\tpackageVersion: result.packageVersion,\n\t\texports: result.exports,\n\t\trawSize: result.rawSize,\n\t\tgzipSize: result.gzipSize,\n\t\tgzipLevel: result.gzipLevel,\n\t\texternals: result.externals,\n\t\tdependencies: result.dependencies,\n\t\tplatform: result.platform,\n\t\trawSizeFormatted: formatBytes(result.rawSize),\n\t\tgzipSizeFormatted:\n\t\t\tresult.gzipSize !== null ? formatBytes(result.gzipSize) : null,\n\t\tfromCache,\n\t\tnamedExportCount: result.namedExportCount,\n\t};\n}\n"],"names":["checkBundleSize","formatBytes","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","normalizePlatform","TREND_VERSION_COUNT","analyzeTrend","selectTrendVersions","fetchPackageVersions","fetchVersions","getBundleStats","options","package","packageName","exports","exportsList","external","additionalExternals","noExternal","gzipLevel","registry","platform","platformOption","force","undefined","name","baseName","version","requestedVersion","resolvedVersion","tags","latest","cacheKey","externals","cached","formatBundleStats","result","getBundleTrend","versionCount","subpath","fullPackagePath","versions","length","Error","trendVersions","results","boring","formattedVersions","map","r","rawSize","gzipSize","rawSizeFormatted","gzipSizeFormatted","change","newest","oldest","rawDiff","rawPercent","gzipDiff","gzipPercent","gzipDiffFormatted","Math","abs","fromVersion","toVersion","Number","parseFloat","toFixed","rawDiffFormatted","getPackageVersions","getPackageExports","installPackage","runtimeExports","packageVersion","e","kind","count","runtimeCount","clearCache","getCacheCount","fromCache","dependencies","namedExportCount"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @node-cli/bundlecheck - Library API\n *\n * Programmatic interface for analyzing npm package bundle sizes.\n *\n */\n\nimport {\n\ttype BundleResult,\n\tcheckBundleSize,\n\tformatBytes,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport {\n\tnormalizePlatform,\n\tnormalizeTarget,\n\tTREND_VERSION_COUNT,\n} from \"./defaults.js\";\nimport type { NamedExport } from \"./exports.js\";\nimport { analyzeTrend, selectTrendVersions } from \"./trend.js\";\nimport { fetchPackageVersions as fetchVersions } from \"./versions.js\";\n\n/**\n * =============================================================================\n * Types\n * =============================================================================\n */\n\n/**\n * Options for getting bundle stats of a single package.\n */\nexport type GetBundleStatsOptions = {\n\t/**\n\t * Package name with optional version (e.g., \"@mantine/core\" or\n\t * \"@mantine/core@7.0.0\").\n\t */\n\tpackage: string;\n\t/**\n\t * Specific exports to measure (e.g., [\"Button\", \"Input\"]).\n\t */\n\texports?: string[];\n\t/**\n\t * Additional packages to mark as external (not bundled).\n\t */\n\texternal?: string[];\n\t/**\n\t * Bundle everything including dependencies that would normally be external.\n\t */\n\tnoExternal?: boolean;\n\t/**\n\t * Gzip compression level (1-9, default 5).\n\t */\n\tgzipLevel?: number;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n\t/**\n\t * Target platform: \"browser\", \"node\", or \"auto\" (default: \"auto\" - auto-detect\n\t * from package.json).\n\t */\n\tplatform?: \"browser\" | \"node\" | \"auto\";\n\t/**\n\t * Bypass cache and force re-analysis.\n\t */\n\tforce?: boolean;\n\t/**\n\t * esbuild target (e.g., \"es2022\", \"es2020\"). Defaults to \"es2022\".\n\t */\n\ttarget?: string;\n};\n\n/**\n * Result from getBundleStats.\n */\nexport type BundleStats = {\n\t/**\n\t * Display name of the package (may include subpath).\n\t */\n\tpackageName: string;\n\t/**\n\t * Resolved package version.\n\t */\n\tpackageVersion: string;\n\t/**\n\t * Exports that were analyzed.\n\t */\n\texports: string[];\n\t/**\n\t * Raw (minified) bundle size in bytes.\n\t */\n\trawSize: number;\n\t/**\n\t * Gzipped bundle size in bytes (null for node platform).\n\t */\n\tgzipSize: number | null;\n\t/**\n\t * Gzip compression level used.\n\t */\n\tgzipLevel: number;\n\t/**\n\t * Packages marked as external (not included in bundle).\n\t */\n\texternals: string[];\n\t/**\n\t * Package dependencies.\n\t */\n\tdependencies: string[];\n\t/**\n\t * Target platform used for bundling.\n\t */\n\tplatform: \"browser\" | \"node\";\n\t/**\n\t * Human-readable raw size (e.g., \"45.2 kB\").\n\t */\n\trawSizeFormatted: string;\n\t/**\n\t * Human-readable gzip size (e.g., \"12.3 kB\") or null.\n\t */\n\tgzipSizeFormatted: string | null;\n\t/**\n\t * Whether the result was retrieved from cache.\n\t */\n\tfromCache: boolean;\n\t/**\n\t * Total number of named exports in the package (when analyzing entire\n\t * package).\n\t */\n\tnamedExportCount: number;\n};\n\n/**\n * Options for getting bundle size trend across versions.\n */\nexport type GetBundleTrendOptions = {\n\t/**\n\t * Package name (e.g., \"@mantine/core\") - version is ignored if provided.\n\t */\n\tpackage: string;\n\t/**\n\t * Number of versions to analyze (default 5).\n\t */\n\tversionCount?: number;\n\t/**\n\t * Specific exports to measure (e.g., [\"Button\", \"Input\"]).\n\t */\n\texports?: string[];\n\t/**\n\t * Additional packages to mark as external (not bundled).\n\t */\n\texternal?: string[];\n\t/**\n\t * Bundle everything including dependencies that would normally be external.\n\t */\n\tnoExternal?: boolean;\n\t/**\n\t * Gzip compression level (1-9, default 5).\n\t */\n\tgzipLevel?: number;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n\t/**\n\t * Target platform: \"browser\", \"node\", or \"auto\" (default: \"auto\" - auto-detect\n\t * from package.json).\n\t */\n\tplatform?: \"browser\" | \"node\" | \"auto\";\n\t/**\n\t * Bypass cache and force re-analysis.\n\t */\n\tforce?: boolean;\n\t/**\n\t * esbuild target (e.g., \"es2022\", \"es2020\"). Defaults to \"es2022\".\n\t */\n\ttarget?: string;\n};\n\n/**\n * Single version result in trend analysis.\n */\nexport type TrendVersionResult = {\n\t/**\n\t * Package version.\n\t */\n\tversion: string;\n\t/**\n\t * Raw (minified) bundle size in bytes.\n\t */\n\trawSize: number;\n\t/**\n\t * Gzipped bundle size in bytes (null for node platform).\n\t */\n\tgzipSize: number | null;\n\t/**\n\t * Human-readable raw size (e.g., \"45.2 kB\").\n\t */\n\trawSizeFormatted: string;\n\t/**\n\t * Human-readable gzip size (e.g., \"12.3 kB\") or null.\n\t */\n\tgzipSizeFormatted: string | null;\n};\n\n/**\n * Size change information between oldest and newest versions.\n */\nexport type TrendChange = {\n\t/**\n\t * Oldest version analyzed.\n\t */\n\tfromVersion: string;\n\t/**\n\t * Newest version analyzed.\n\t */\n\ttoVersion: string;\n\t/**\n\t * Raw size difference in bytes (positive = increase, negative = decrease).\n\t */\n\trawDiff: number;\n\t/**\n\t * Raw size percentage change (null if oldest size was 0).\n\t */\n\trawPercent: number | null;\n\t/**\n\t * Human-readable raw size change (e.g., \"+5.2 kB\" or \"-1.3 kB\").\n\t */\n\trawDiffFormatted: string;\n\t/**\n\t * Gzip size difference in bytes (null if not applicable).\n\t */\n\tgzipDiff: number | null;\n\t/**\n\t * Gzip size percentage change (null if not applicable or oldest size was 0).\n\t */\n\tgzipPercent: number | null;\n\t/**\n\t * Human-readable gzip size change (e.g., \"+1.5 kB\" or \"-0.8 kB\") or null.\n\t */\n\tgzipDiffFormatted: string | null;\n};\n\n/**\n * Result from getBundleTrend.\n */\nexport type BundleTrend = {\n\t/**\n\t * Package name.\n\t */\n\tpackageName: string;\n\t/**\n\t * Results for each version analyzed (newest first).\n\t */\n\tversions: TrendVersionResult[];\n\t/**\n\t * Size change between oldest and newest versions (null if only one version).\n\t */\n\tchange: TrendChange | null;\n};\n\n/**\n * Options for fetching package versions.\n */\nexport type GetPackageVersionsOptions = {\n\t/**\n\t * Package name (e.g., \"@mantine/core\").\n\t */\n\tpackage: string;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n};\n\n/**\n * Result from getPackageVersions.\n */\nexport type PackageVersions = {\n\t/**\n\t * All available versions (sorted newest first).\n\t */\n\tversions: string[];\n\t/**\n\t * Distribution tags (e.g., { latest: \"7.0.0\", next: \"8.0.0-beta.1\" }).\n\t */\n\ttags: Record<string, string>;\n};\n\n/**\n * =============================================================================\n * Library Functions\n * =============================================================================\n */\n\n/**\n * Get bundle size statistics for an npm package.\n *\n * @example\n * ```js\n * import { getBundleStats } from \"@node-cli/bundlecheck\";\n *\n * const stats = await getBundleStats({\n * package: \"@mantine/core@7.0.0\",\n * exports: [\"Button\", \"Input\"],\n * });\n *\n * console.log(stats.gzipSizeFormatted); // \"12.3 kB\"\n * ```\n *\n */\nexport async function getBundleStats(\n\toptions: GetBundleStatsOptions,\n): Promise<BundleStats> {\n\tconst {\n\t\tpackage: packageName,\n\t\texports: exportsList,\n\t\texternal: additionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel = 5,\n\t\tregistry,\n\t\tplatform: platformOption = \"auto\",\n\t\tforce = false,\n\t\ttarget: targetOption,\n\t} = options;\n\n\t// Normalize platform.\n\tconst platform = normalizePlatform(\n\t\tplatformOption === \"auto\" ? undefined : platformOption,\n\t);\n\n\t// Normalize target.\n\tconst target = normalizeTarget(targetOption);\n\n\t// Parse package specifier.\n\tconst { name: baseName, version: requestedVersion } =\n\t\tparsePackageSpecifier(packageName);\n\n\t// Resolve \"latest\" to actual version for cache key.\n\tlet resolvedVersion = requestedVersion;\n\tif (requestedVersion === \"latest\") {\n\t\tconst { tags } = await fetchVersions({\n\t\t\tpackageName: baseName,\n\t\t\tregistry,\n\t\t});\n\t\tresolvedVersion = tags.latest || requestedVersion;\n\t}\n\n\t/**\n\t * Build cache key.\n\t * NOTE: We use additionalExternals here, not computed externals, because the default externals (react, react-dom) are determined at bundle time based on the package's dependencies.\n\t * The cache key captures the user's intent (additionalExternals + noExternal\n\t * flag), and the actual externals are stored in the cached result.\n\t */\n\tconst cacheKey = normalizeCacheKey({\n\t\tpackageName: baseName,\n\t\tversion: resolvedVersion,\n\t\texports: exportsList,\n\t\tplatform,\n\t\tgzipLevel,\n\t\texternals: additionalExternals || [],\n\t\tnoExternal: noExternal ?? false,\n\t});\n\n\t// Check cache (unless force is set).\n\tif (!force) {\n\t\tconst cached = getCachedResult(cacheKey);\n\t\tif (cached) {\n\t\t\treturn formatBundleStats(cached, true);\n\t\t}\n\t}\n\n\t// Perform the analysis.\n\tconst result = await checkBundleSize({\n\t\tpackageName,\n\t\texports: exportsList,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tregistry,\n\t\tplatform,\n\t\ttarget,\n\t});\n\n\t// Store in cache.\n\tsetCachedResult(cacheKey, result);\n\n\treturn formatBundleStats(result, false);\n}\n\n/**\n * Get bundle size trend across multiple versions of a package.\n *\n * @example\n * ```js\n * import { getBundleTrend } from \"@node-cli/bundlecheck\";\n *\n * const trend = await getBundleTrend({\n * package: \"@mantine/core\",\n * versionCount: 5,\n * });\n *\n * console.log(trend.change?.rawDiffFormatted); // \"+5.2 kB\"\n * ```\n *\n */\nexport async function getBundleTrend(\n\toptions: GetBundleTrendOptions,\n): Promise<BundleTrend> {\n\tconst {\n\t\tpackage: packageName,\n\t\tversionCount = TREND_VERSION_COUNT,\n\t\texports: exportsList,\n\t\texternal: additionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tregistry,\n\t\tplatform: platformOption = \"auto\",\n\t\tforce = false,\n\t\ttarget: targetOption,\n\t} = options;\n\n\t// Normalize platform.\n\tconst platform = normalizePlatform(\n\t\tplatformOption === \"auto\" ? undefined : platformOption,\n\t);\n\n\t// Normalize target.\n\tconst target = normalizeTarget(targetOption);\n\n\t// Parse package name (ignore version if provided).\n\tconst { name: baseName, subpath } = parsePackageSpecifier(packageName);\n\tconst fullPackagePath = subpath ? `${baseName}/${subpath}` : baseName;\n\n\t// Fetch available versions.\n\tconst { versions } = await fetchVersions({\n\t\tpackageName: baseName,\n\t\tregistry,\n\t});\n\n\tif (versions.length === 0) {\n\t\tthrow new Error(`No versions found for package: ${baseName}`);\n\t}\n\n\t// Select versions for trend.\n\tconst trendVersions = selectTrendVersions(versions, versionCount);\n\n\t// Analyze all versions (silently - no console output).\n\tconst results = await analyzeTrend({\n\t\tpackageName: fullPackagePath,\n\t\tversions: trendVersions,\n\t\texports: exportsList,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tboring: true, // Suppress logging\n\t\tregistry,\n\t\tplatform,\n\t\tforce,\n\t\ttarget,\n\t});\n\n\tif (results.length === 0) {\n\t\tthrow new Error(`Failed to analyze any versions for package: ${baseName}`);\n\t}\n\n\t// Format results.\n\tconst formattedVersions: TrendVersionResult[] = results.map((r) => ({\n\t\tversion: r.version,\n\t\trawSize: r.rawSize,\n\t\tgzipSize: r.gzipSize,\n\t\trawSizeFormatted: formatBytes(r.rawSize),\n\t\tgzipSizeFormatted: r.gzipSize !== null ? formatBytes(r.gzipSize) : null,\n\t}));\n\n\t// Calculate change between oldest and newest.\n\tlet change: TrendChange | null = null;\n\tif (results.length > 1) {\n\t\tconst newest = results[0];\n\t\tconst oldest = results[results.length - 1];\n\n\t\tconst rawDiff = newest.rawSize - oldest.rawSize;\n\t\t// Handle division by zero: if oldest size is 0, percent is null.\n\t\tconst rawPercent =\n\t\t\toldest.rawSize === 0 ? null : (rawDiff / oldest.rawSize) * 100;\n\n\t\tlet gzipDiff: number | null = null;\n\t\tlet gzipPercent: number | null = null;\n\t\tlet gzipDiffFormatted: string | null = null;\n\n\t\tif (newest.gzipSize !== null && oldest.gzipSize !== null) {\n\t\t\tgzipDiff = newest.gzipSize - oldest.gzipSize;\n\t\t\t// Handle division by zero: if oldest size is 0, percent is null.\n\t\t\tgzipPercent =\n\t\t\t\toldest.gzipSize === 0 ? null : (gzipDiff / oldest.gzipSize) * 100;\n\t\t\tgzipDiffFormatted =\n\t\t\t\tgzipDiff >= 0\n\t\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\n\t\t}\n\n\t\tchange = {\n\t\t\tfromVersion: oldest.version,\n\t\t\ttoVersion: newest.version,\n\t\t\trawDiff,\n\t\t\trawPercent:\n\t\t\t\trawPercent !== null ? Number.parseFloat(rawPercent.toFixed(1)) : null,\n\t\t\trawDiffFormatted:\n\t\t\t\trawDiff >= 0\n\t\t\t\t\t? `+${formatBytes(rawDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(rawDiff))}`,\n\t\t\tgzipDiff,\n\t\t\tgzipPercent:\n\t\t\t\tgzipPercent !== null ? Number.parseFloat(gzipPercent.toFixed(1)) : null,\n\t\t\tgzipDiffFormatted,\n\t\t};\n\t}\n\n\treturn {\n\t\tpackageName: fullPackagePath,\n\t\tversions: formattedVersions,\n\t\tchange,\n\t};\n}\n\n/**\n * Get available versions for an npm package.\n *\n * @example\n * ```js\n * import { getPackageVersions } from \"@node-cli/bundlecheck\";\n *\n * const { versions, tags } = await getPackageVersions({\n * package: \"@mantine/core\",\n * });\n *\n * console.log(tags.latest); // \"7.0.0\"\n * ```\n *\n */\nexport async function getPackageVersions(\n\toptions: GetPackageVersionsOptions,\n): Promise<PackageVersions> {\n\tconst { package: packageName, registry } = options;\n\n\tconst result = await fetchVersions({\n\t\tpackageName,\n\t\tregistry,\n\t});\n\n\treturn {\n\t\tversions: result.versions,\n\t\ttags: result.tags,\n\t};\n}\n\n/**\n * Options for getting package exports.\n */\nexport type GetPackageExportsOptions = {\n\t/**\n\t * Package name with optional version (e.g., \"@mantine/core\" or\n\t * \"@mantine/core@7.0.0\").\n\t */\n\tpackage: string;\n\t/**\n\t * Custom npm registry URL.\n\t */\n\tregistry?: string;\n};\n\n/**\n * A named export from a package.\n */\nexport type PackageExport = {\n\t/**\n\t * The export name (e.g., \"Button\", \"useState\").\n\t */\n\tname: string;\n\t/**\n\t * The type of export.\n\t */\n\tkind:\n\t\t| \"function\"\n\t\t| \"class\"\n\t\t| \"const\"\n\t\t| \"type\"\n\t\t| \"interface\"\n\t\t| \"enum\"\n\t\t| \"unknown\";\n};\n\n/**\n * Result from getPackageExports.\n */\nexport type PackageExports = {\n\t/**\n\t * Package name.\n\t */\n\tpackageName: string;\n\t/**\n\t * Resolved package version.\n\t */\n\tpackageVersion: string;\n\t/**\n\t * Array of all named exports found in the package (including types).\n\t */\n\texports: PackageExport[];\n\t/**\n\t * Total count of all named exports (including types).\n\t */\n\tcount: number;\n\t/**\n\t * Array of runtime exports only (excluding types and interfaces). These are\n\t * the exports that can actually be imported at runtime.\n\t */\n\truntimeExports: PackageExport[];\n\t/**\n\t * Count of runtime exports only (functions, classes, const, enums).\n\t */\n\truntimeCount: number;\n};\n\n/**\n * Get the named exports of an npm package by analyzing its type definitions.\n *\n * @example\n * ```js\n * import { getPackageExports } from \"@node-cli/bundlecheck\";\n *\n * const { exports, count } = await getPackageExports({\n * package: \"@mantine/core@7.0.0\",\n * });\n *\n * console.log(`Found ${count} exports`);\n * console.log(exports.map(e => e.name)); // [\"Accordion\", \"ActionIcon\", \"Alert\", ...]\n * ```\n *\n */\nexport async function getPackageExports(\n\toptions: GetPackageExportsOptions,\n): Promise<PackageExports> {\n\tconst { package: packageName, registry } = options;\n\n\t/**\n\t * Import the install utilities from bundler (we'll use a minimal bundle\n\t * check).\n\t */\n\tconst { name: baseName, version: requestedVersion } =\n\t\tparsePackageSpecifier(packageName);\n\n\t// Resolve \"latest\" to actual version.\n\tlet resolvedVersion = requestedVersion;\n\tif (requestedVersion === \"latest\") {\n\t\tconst { tags } = await fetchVersions({\n\t\t\tpackageName: baseName,\n\t\t\tregistry,\n\t\t});\n\t\tresolvedVersion = tags.latest || requestedVersion;\n\t}\n\n\t/**\n\t * Use a minimal bundle check to install the package and get exports We'll\n\t * leverage the existing infrastructure.\n\t */\n\tconst { installPackage } = await import(\"./exports-installer.js\");\n\n\tconst { version, exports, runtimeExports } = await installPackage({\n\t\tpackageName: baseName,\n\t\tversion: resolvedVersion,\n\t\tregistry,\n\t});\n\n\treturn {\n\t\tpackageName: baseName,\n\t\tpackageVersion: version,\n\t\texports: exports.map((e: NamedExport) => ({\n\t\t\tname: e.name,\n\t\t\tkind: e.kind,\n\t\t})),\n\t\tcount: exports.length,\n\t\truntimeExports: runtimeExports.map((e: NamedExport) => ({\n\t\t\tname: e.name,\n\t\t\tkind: e.kind,\n\t\t})),\n\t\truntimeCount: runtimeExports.length,\n\t};\n}\n\n/**\n * =============================================================================\n * Re-exports for advanced usage\n * =============================================================================\n */\n\n/**\n * - Format bytes to human-readable string (e.g., 1024 → \"1 kB\").\n * - Parse a package specifier (e.g., \"@scope/name@1.0.0\" → { name, version,\n * subpath }).\n */\nexport { formatBytes, parsePackageSpecifier } from \"./bundler.js\";\n/**\n * - Clear the bundle cache.\n * - Get the number of cached entries.\n */\nexport { clearCache, getCacheCount } from \"./cache.js\";\n\n/**\n * =============================================================================\n * Internal Helpers\n * =============================================================================\n */\n\n/**\n * Format a BundleResult into a BundleStats object.\n */\nfunction formatBundleStats(\n\tresult: BundleResult,\n\tfromCache: boolean,\n): BundleStats {\n\treturn {\n\t\tpackageName: result.packageName,\n\t\tpackageVersion: result.packageVersion,\n\t\texports: result.exports,\n\t\trawSize: result.rawSize,\n\t\tgzipSize: result.gzipSize,\n\t\tgzipLevel: result.gzipLevel,\n\t\texternals: result.externals,\n\t\tdependencies: result.dependencies,\n\t\tplatform: result.platform,\n\t\trawSizeFormatted: formatBytes(result.rawSize),\n\t\tgzipSizeFormatted:\n\t\t\tresult.gzipSize !== null ? formatBytes(result.gzipSize) : null,\n\t\tfromCache,\n\t\tnamedExportCount: result.namedExportCount,\n\t};\n}\n"],"names":["checkBundleSize","formatBytes","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","normalizePlatform","normalizeTarget","TREND_VERSION_COUNT","analyzeTrend","selectTrendVersions","fetchPackageVersions","fetchVersions","getBundleStats","options","package","packageName","exports","exportsList","external","additionalExternals","noExternal","gzipLevel","registry","platform","platformOption","force","target","targetOption","undefined","name","baseName","version","requestedVersion","resolvedVersion","tags","latest","cacheKey","externals","cached","formatBundleStats","result","getBundleTrend","versionCount","subpath","fullPackagePath","versions","length","Error","trendVersions","results","boring","formattedVersions","map","r","rawSize","gzipSize","rawSizeFormatted","gzipSizeFormatted","change","newest","oldest","rawDiff","rawPercent","gzipDiff","gzipPercent","gzipDiffFormatted","Math","abs","fromVersion","toVersion","Number","parseFloat","toFixed","rawDiffFormatted","getPackageVersions","getPackageExports","installPackage","runtimeExports","packageVersion","e","kind","count","runtimeCount","clearCache","getCacheCount","fromCache","dependencies","namedExportCount"],"mappings":"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"}
|
package/dist/parse.d.ts
CHANGED
package/dist/parse.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* istanbul ignore file */ import { parser } from "@node-cli/parser";
|
|
2
|
-
import { defaultFlags, isValidPlatform } from "./defaults.js";
|
|
2
|
+
import { defaultFlags, isValidPlatform, isValidTarget } from "./defaults.js";
|
|
3
3
|
export const config = parser({
|
|
4
4
|
meta: import.meta,
|
|
5
5
|
examples: [
|
|
@@ -54,6 +54,10 @@ export const config = parser({
|
|
|
54
54
|
{
|
|
55
55
|
command: "bundlecheck lodash --force",
|
|
56
56
|
comment: "## Bypass cache and force re-fetch/re-calculation"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
command: "bundlecheck lodash --target es2020",
|
|
60
|
+
comment: "## Use a specific esbuild target (default: es2022)"
|
|
57
61
|
}
|
|
58
62
|
],
|
|
59
63
|
flags: {
|
|
@@ -119,6 +123,12 @@ export const config = parser({
|
|
|
119
123
|
default: defaultFlags.force,
|
|
120
124
|
description: "Bypass cache and force re-fetch/re-calculation",
|
|
121
125
|
type: "boolean"
|
|
126
|
+
},
|
|
127
|
+
target: {
|
|
128
|
+
shortFlag: "T",
|
|
129
|
+
default: defaultFlags.target,
|
|
130
|
+
description: 'esbuild target for bundling (e.g., "es2022", "es2020"). Default: "es2022"',
|
|
131
|
+
type: "string"
|
|
122
132
|
}
|
|
123
133
|
},
|
|
124
134
|
parameters: {
|
|
@@ -144,6 +154,11 @@ export const config = parser({
|
|
|
144
154
|
exit: 1,
|
|
145
155
|
message: ()=>'Error: Invalid platform. Use "browser" (or web, desktop, client) or "node" (or server, nodejs, backend)',
|
|
146
156
|
test: (flags)=>!isValidPlatform(flags.platform)
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
exit: 1,
|
|
160
|
+
message: ()=>'Error: Invalid target. Use an ECMAScript version (e.g., "es2022", "es2020", "esnext")',
|
|
161
|
+
test: (flags)=>!isValidTarget(flags.target)
|
|
147
162
|
}
|
|
148
163
|
],
|
|
149
164
|
usage: true,
|
package/dist/parse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["/* istanbul ignore file */\nimport { parser } from \"@node-cli/parser\";\nimport { defaultFlags, isValidPlatform } from \"./defaults.js\";\n\nexport type Flags = {\n\tboring?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tversions?: boolean;\n\ttrend?: string;\n\tgzipLevel?: number;\n\texternal?: string;\n\tnoExternal?: boolean;\n\tregistry?: string;\n\tplatform?: string;\n\tforce?: boolean;\n};\n\nexport type Parameters = {\n\t[\"0\"]?: string; // package name\n\t[\"1\"]?: string; // exports (comma-separated)\n};\n\nexport type Configuration = {\n\tflags?: Flags;\n\tparameters?: Parameters;\n\tusage?: boolean;\n\tshowHelp?: () => void;\n};\n\nexport const config: Configuration = parser({\n\tmeta: import.meta,\n\texamples: [\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash\",\n\t\t\tcomment: \"## Check the bundle size of the entire lodash package\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash@4.17.0\",\n\t\t\tcomment: \"## Check a specific version of a package\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck @mantine/core\",\n\t\t\tcomment: \"## Check the bundle size of the entire @mantine/core package\",\n\t\t},\n\t\t{\n\t\t\tcommand: 'bundlecheck @mantine/core \"ScrollArea,Button\"',\n\t\t\tcomment:\n\t\t\t\t\"## Check the bundle size of specific exports from @mantine/core\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck react --no-external\",\n\t\t\tcomment:\n\t\t\t\t\"## Check the bundle size of react itself (not marked as external)\",\n\t\t},\n\t\t{\n\t\t\tcommand: 'bundlecheck some-pkg --external \"vue,svelte\"',\n\t\t\tcomment: \"## Add vue and svelte as additional external dependencies\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --gzip-level 6\",\n\t\t\tcomment: \"## Use a different gzip compression level (1-9)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --versions\",\n\t\t\tcomment: \"## Choose from available versions interactively\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --trend\",\n\t\t\tcomment: \"## Show bundle size trend (default: 5 versions)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --trend 3\",\n\t\t\tcomment: \"## Show bundle size trend for 3 versions\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --registry https://registry.example.com\",\n\t\t\tcomment: \"## Use a custom npm registry\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck express --platform node\",\n\t\t\tcomment:\n\t\t\t\t\"## Check bundle size for Node.js platform (aliases: server, nodejs, backend)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --force\",\n\t\t\tcomment: \"## Bypass cache and force re-fetch/re-calculation\",\n\t\t},\n\t],\n\tflags: {\n\t\tgzipLevel: {\n\t\t\tshortFlag: \"g\",\n\t\t\tdefault: defaultFlags.gzipLevel,\n\t\t\tdescription: \"Gzip compression level (1-9, default: 5)\",\n\t\t\ttype: \"number\",\n\t\t},\n\t\texternal: {\n\t\t\tshortFlag: \"e\",\n\t\t\tdefault: defaultFlags.external,\n\t\t\tdescription:\n\t\t\t\t\"Comma-separated additional externals (react, react-dom auto-external when in package deps)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tnoExternal: {\n\t\t\tshortFlag: \"n\",\n\t\t\tdefault: defaultFlags.noExternal,\n\t\t\tdescription:\n\t\t\t\t\"Do not mark any packages as external (useful for checking react/react-dom themselves)\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tboring: {\n\t\t\tshortFlag: \"b\",\n\t\t\tdefault: defaultFlags.boring,\n\t\t\tdescription: \"Do not use color output\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\thelp: {\n\t\t\tshortFlag: \"h\",\n\t\t\tdescription: \"Display help instructions\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversion: {\n\t\t\tshortFlag: \"v\",\n\t\t\tdescription: \"Output the current version\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversions: {\n\t\t\tshortFlag: \"V\",\n\t\t\tdefault: defaultFlags.versions,\n\t\t\tdescription: \"Choose from available package versions interactively\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\ttrend: {\n\t\t\tshortFlag: \"t\",\n\t\t\tdescription: \"Show bundle size trend for N recent versions (default: 5)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tregistry: {\n\t\t\tshortFlag: \"r\",\n\t\t\tdefault: defaultFlags.registry,\n\t\t\tdescription:\n\t\t\t\t\"Custom npm registry URL (default: https://registry.npmjs.org)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tplatform: {\n\t\t\tshortFlag: \"p\",\n\t\t\tdefault: defaultFlags.platform,\n\t\t\tdescription:\n\t\t\t\t'Target platform: \"auto\" (default, detects from engines), \"browser\" or \"node\"',\n\t\t\ttype: \"string\",\n\t\t},\n\t\tforce: {\n\t\t\tshortFlag: \"f\",\n\t\t\tdefault: defaultFlags.force,\n\t\t\tdescription: \"Bypass cache and force re-fetch/re-calculation\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t},\n\tparameters: {\n\t\tpackage: {\n\t\t\tdescription: \"The npm package to check (e.g., lodash, @mantine/core)\",\n\t\t},\n\t\texports: {\n\t\t\tdescription:\n\t\t\t\t'Comma-separated list of exports to check (e.g., \"ScrollArea,Button\")',\n\t\t},\n\t},\n\trestrictions: [\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () => \"Error: Package name is required\",\n\t\t\ttest: (flags, parameters) => !parameters?.[\"0\"],\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () => \"Error: Gzip level must be between 1 and 9\",\n\t\t\ttest: (flags) =>\n\t\t\t\tflags.gzipLevel !== undefined &&\n\t\t\t\t(flags.gzipLevel < 1 || flags.gzipLevel > 9),\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () =>\n\t\t\t\t'Error: Invalid platform. Use \"browser\" (or web, desktop, client) or \"node\" (or server, nodejs, backend)',\n\t\t\ttest: (flags) => !isValidPlatform(flags.platform),\n\t\t},\n\t],\n\tusage: true,\n\tdefaultFlags,\n});\n"],"names":["parser","defaultFlags","isValidPlatform","config","meta","examples","command","comment","flags","gzipLevel","shortFlag","default","description","type","external","noExternal","boring","help","version","versions","trend","registry","platform","force","parameters","package","exports","restrictions","exit","message","test","undefined","usage"],"mappings":"AAAA,wBAAwB,GACxB,SAASA,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,YAAY,EAAEC,eAAe,QAAQ,gBAAgB;
|
|
1
|
+
{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["/* istanbul ignore file */\nimport { parser } from \"@node-cli/parser\";\nimport { defaultFlags, isValidPlatform, isValidTarget } from \"./defaults.js\";\n\nexport type Flags = {\n\tboring?: boolean;\n\thelp?: boolean;\n\tversion?: boolean;\n\tversions?: boolean;\n\ttrend?: string;\n\tgzipLevel?: number;\n\texternal?: string;\n\tnoExternal?: boolean;\n\tregistry?: string;\n\tplatform?: string;\n\tforce?: boolean;\n\ttarget?: string;\n};\n\nexport type Parameters = {\n\t[\"0\"]?: string; // package name\n\t[\"1\"]?: string; // exports (comma-separated)\n};\n\nexport type Configuration = {\n\tflags?: Flags;\n\tparameters?: Parameters;\n\tusage?: boolean;\n\tshowHelp?: () => void;\n};\n\nexport const config: Configuration = parser({\n\tmeta: import.meta,\n\texamples: [\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash\",\n\t\t\tcomment: \"## Check the bundle size of the entire lodash package\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash@4.17.0\",\n\t\t\tcomment: \"## Check a specific version of a package\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck @mantine/core\",\n\t\t\tcomment: \"## Check the bundle size of the entire @mantine/core package\",\n\t\t},\n\t\t{\n\t\t\tcommand: 'bundlecheck @mantine/core \"ScrollArea,Button\"',\n\t\t\tcomment:\n\t\t\t\t\"## Check the bundle size of specific exports from @mantine/core\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck react --no-external\",\n\t\t\tcomment:\n\t\t\t\t\"## Check the bundle size of react itself (not marked as external)\",\n\t\t},\n\t\t{\n\t\t\tcommand: 'bundlecheck some-pkg --external \"vue,svelte\"',\n\t\t\tcomment: \"## Add vue and svelte as additional external dependencies\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --gzip-level 6\",\n\t\t\tcomment: \"## Use a different gzip compression level (1-9)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --versions\",\n\t\t\tcomment: \"## Choose from available versions interactively\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --trend\",\n\t\t\tcomment: \"## Show bundle size trend (default: 5 versions)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --trend 3\",\n\t\t\tcomment: \"## Show bundle size trend for 3 versions\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --registry https://registry.example.com\",\n\t\t\tcomment: \"## Use a custom npm registry\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck express --platform node\",\n\t\t\tcomment:\n\t\t\t\t\"## Check bundle size for Node.js platform (aliases: server, nodejs, backend)\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --force\",\n\t\t\tcomment: \"## Bypass cache and force re-fetch/re-calculation\",\n\t\t},\n\t\t{\n\t\t\tcommand: \"bundlecheck lodash --target es2020\",\n\t\t\tcomment: \"## Use a specific esbuild target (default: es2022)\",\n\t\t},\n\t],\n\tflags: {\n\t\tgzipLevel: {\n\t\t\tshortFlag: \"g\",\n\t\t\tdefault: defaultFlags.gzipLevel,\n\t\t\tdescription: \"Gzip compression level (1-9, default: 5)\",\n\t\t\ttype: \"number\",\n\t\t},\n\t\texternal: {\n\t\t\tshortFlag: \"e\",\n\t\t\tdefault: defaultFlags.external,\n\t\t\tdescription:\n\t\t\t\t\"Comma-separated additional externals (react, react-dom auto-external when in package deps)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tnoExternal: {\n\t\t\tshortFlag: \"n\",\n\t\t\tdefault: defaultFlags.noExternal,\n\t\t\tdescription:\n\t\t\t\t\"Do not mark any packages as external (useful for checking react/react-dom themselves)\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tboring: {\n\t\t\tshortFlag: \"b\",\n\t\t\tdefault: defaultFlags.boring,\n\t\t\tdescription: \"Do not use color output\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\thelp: {\n\t\t\tshortFlag: \"h\",\n\t\t\tdescription: \"Display help instructions\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversion: {\n\t\t\tshortFlag: \"v\",\n\t\t\tdescription: \"Output the current version\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\tversions: {\n\t\t\tshortFlag: \"V\",\n\t\t\tdefault: defaultFlags.versions,\n\t\t\tdescription: \"Choose from available package versions interactively\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\ttrend: {\n\t\t\tshortFlag: \"t\",\n\t\t\tdescription: \"Show bundle size trend for N recent versions (default: 5)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tregistry: {\n\t\t\tshortFlag: \"r\",\n\t\t\tdefault: defaultFlags.registry,\n\t\t\tdescription:\n\t\t\t\t\"Custom npm registry URL (default: https://registry.npmjs.org)\",\n\t\t\ttype: \"string\",\n\t\t},\n\t\tplatform: {\n\t\t\tshortFlag: \"p\",\n\t\t\tdefault: defaultFlags.platform,\n\t\t\tdescription:\n\t\t\t\t'Target platform: \"auto\" (default, detects from engines), \"browser\" or \"node\"',\n\t\t\ttype: \"string\",\n\t\t},\n\t\tforce: {\n\t\t\tshortFlag: \"f\",\n\t\t\tdefault: defaultFlags.force,\n\t\t\tdescription: \"Bypass cache and force re-fetch/re-calculation\",\n\t\t\ttype: \"boolean\",\n\t\t},\n\t\ttarget: {\n\t\t\tshortFlag: \"T\",\n\t\t\tdefault: defaultFlags.target,\n\t\t\tdescription:\n\t\t\t\t'esbuild target for bundling (e.g., \"es2022\", \"es2020\"). Default: \"es2022\"',\n\t\t\ttype: \"string\",\n\t\t},\n\t},\n\tparameters: {\n\t\tpackage: {\n\t\t\tdescription: \"The npm package to check (e.g., lodash, @mantine/core)\",\n\t\t},\n\t\texports: {\n\t\t\tdescription:\n\t\t\t\t'Comma-separated list of exports to check (e.g., \"ScrollArea,Button\")',\n\t\t},\n\t},\n\trestrictions: [\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () => \"Error: Package name is required\",\n\t\t\ttest: (flags, parameters) => !parameters?.[\"0\"],\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () => \"Error: Gzip level must be between 1 and 9\",\n\t\t\ttest: (flags) =>\n\t\t\t\tflags.gzipLevel !== undefined &&\n\t\t\t\t(flags.gzipLevel < 1 || flags.gzipLevel > 9),\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () =>\n\t\t\t\t'Error: Invalid platform. Use \"browser\" (or web, desktop, client) or \"node\" (or server, nodejs, backend)',\n\t\t\ttest: (flags) => !isValidPlatform(flags.platform),\n\t\t},\n\t\t{\n\t\t\texit: 1,\n\t\t\tmessage: () =>\n\t\t\t\t'Error: Invalid target. Use an ECMAScript version (e.g., \"es2022\", \"es2020\", \"esnext\")',\n\t\t\ttest: (flags) => !isValidTarget(flags.target),\n\t\t},\n\t],\n\tusage: true,\n\tdefaultFlags,\n});\n"],"names":["parser","defaultFlags","isValidPlatform","isValidTarget","config","meta","examples","command","comment","flags","gzipLevel","shortFlag","default","description","type","external","noExternal","boring","help","version","versions","trend","registry","platform","force","target","parameters","package","exports","restrictions","exit","message","test","undefined","usage"],"mappings":"AAAA,wBAAwB,GACxB,SAASA,MAAM,QAAQ,mBAAmB;AAC1C,SAASC,YAAY,EAAEC,eAAe,EAAEC,aAAa,QAAQ,gBAAgB;AA6B7E,OAAO,MAAMC,SAAwBJ,OAAO;IAC3CK,MAAM;IACNC,UAAU;QACT;YACCC,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SACC;QACF;QACA;YACCD,SAAS;YACTC,SACC;QACF;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SACC;QACF;QACA;YACCD,SAAS;YACTC,SAAS;QACV;QACA;YACCD,SAAS;YACTC,SAAS;QACV;KACA;IACDC,OAAO;QACNC,WAAW;YACVC,WAAW;YACXC,SAASX,aAAaS,SAAS;YAC/BG,aAAa;YACbC,MAAM;QACP;QACAC,UAAU;YACTJ,WAAW;YACXC,SAASX,aAAac,QAAQ;YAC9BF,aACC;YACDC,MAAM;QACP;QACAE,YAAY;YACXL,WAAW;YACXC,SAASX,aAAae,UAAU;YAChCH,aACC;YACDC,MAAM;QACP;QACAG,QAAQ;YACPN,WAAW;YACXC,SAASX,aAAagB,MAAM;YAC5BJ,aAAa;YACbC,MAAM;QACP;QACAI,MAAM;YACLP,WAAW;YACXE,aAAa;YACbC,MAAM;QACP;QACAK,SAAS;YACRR,WAAW;YACXE,aAAa;YACbC,MAAM;QACP;QACAM,UAAU;YACTT,WAAW;YACXC,SAASX,aAAamB,QAAQ;YAC9BP,aAAa;YACbC,MAAM;QACP;QACAO,OAAO;YACNV,WAAW;YACXE,aAAa;YACbC,MAAM;QACP;QACAQ,UAAU;YACTX,WAAW;YACXC,SAASX,aAAaqB,QAAQ;YAC9BT,aACC;YACDC,MAAM;QACP;QACAS,UAAU;YACTZ,WAAW;YACXC,SAASX,aAAasB,QAAQ;YAC9BV,aACC;YACDC,MAAM;QACP;QACAU,OAAO;YACNb,WAAW;YACXC,SAASX,aAAauB,KAAK;YAC3BX,aAAa;YACbC,MAAM;QACP;QACAW,QAAQ;YACPd,WAAW;YACXC,SAASX,aAAawB,MAAM;YAC5BZ,aACC;YACDC,MAAM;QACP;IACD;IACAY,YAAY;QACXC,SAAS;YACRd,aAAa;QACd;QACAe,SAAS;YACRf,aACC;QACF;IACD;IACAgB,cAAc;QACb;YACCC,MAAM;YACNC,SAAS,IAAM;YACfC,MAAM,CAACvB,OAAOiB,aAAe,CAACA,YAAY,CAAC,IAAI;QAChD;QACA;YACCI,MAAM;YACNC,SAAS,IAAM;YACfC,MAAM,CAACvB,QACNA,MAAMC,SAAS,KAAKuB,aACnBxB,CAAAA,MAAMC,SAAS,GAAG,KAAKD,MAAMC,SAAS,GAAG,CAAA;QAC5C;QACA;YACCoB,MAAM;YACNC,SAAS,IACR;YACDC,MAAM,CAACvB,QAAU,CAACP,gBAAgBO,MAAMc,QAAQ;QACjD;QACA;YACCO,MAAM;YACNC,SAAS,IACR;YACDC,MAAM,CAACvB,QAAU,CAACN,cAAcM,MAAMgB,MAAM;QAC7C;KACA;IACDS,OAAO;IACPjC;AACD,GAAG"}
|
package/dist/trend.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export type TrendOptions = {
|
|
|
23
23
|
* Bypass cache and force re-fetch/re-calculation.
|
|
24
24
|
*/
|
|
25
25
|
force?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* esbuild target (e.g., "es2022", "es2020"). Defaults to "es2022".
|
|
28
|
+
*/
|
|
29
|
+
target?: string;
|
|
26
30
|
};
|
|
27
31
|
/**
|
|
28
32
|
* Select versions for trend analysis Returns the most recent stable versions
|
package/dist/trend.js
CHANGED
|
@@ -16,7 +16,7 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
|
|
|
16
16
|
/**
|
|
17
17
|
* Analyze bundle size trend across multiple versions.
|
|
18
18
|
*/ export async function analyzeTrend(options) {
|
|
19
|
-
const { packageName, versions, exports, additionalExternals, noExternal, gzipLevel, boring, registry, platform, force } = options;
|
|
19
|
+
const { packageName, versions, exports, additionalExternals, noExternal, gzipLevel, boring, registry, platform, force, target } = options;
|
|
20
20
|
const log = new Logger({
|
|
21
21
|
boring
|
|
22
22
|
});
|
|
@@ -61,7 +61,8 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
|
|
|
61
61
|
noExternal,
|
|
62
62
|
gzipLevel,
|
|
63
63
|
registry,
|
|
64
|
-
platform
|
|
64
|
+
platform,
|
|
65
|
+
target
|
|
65
66
|
});
|
|
66
67
|
// Store result in cache.
|
|
67
68
|
setCachedResult(cacheKey, result);
|
package/dist/trend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/trend.ts"],"sourcesContent":["import { Logger } from \"@node-cli/logger\";\nimport kleur from \"kleur\";\nimport { prerelease } from \"semver\";\nimport {\n\tcheckBundleSize,\n\tformatBytes,\n\tgetExternals,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport { TREND_VERSION_COUNT } from \"./defaults.js\";\n\nexport type TrendResult = {\n\tversion: string;\n\trawSize: number;\n\t/**\n\t * Gzip size in bytes, or null for node platform.\n\t */\n\tgzipSize: number | null;\n};\n\nexport type TrendOptions = {\n\tpackageName: string;\n\tversions: string[];\n\texports?: string[];\n\tadditionalExternals?: string[];\n\tnoExternal?: boolean;\n\tgzipLevel?: number;\n\tboring?: boolean;\n\tregistry?: string;\n\t/**\n\t * Target platform. If undefined, auto-detects from package.json engines.\n\t */\n\tplatform?: \"browser\" | \"node\";\n\t/**\n\t * Bypass cache and force re-fetch/re-calculation.\n\t */\n\tforce?: boolean;\n};\n\n/**\n * Select versions for trend analysis Returns the most recent stable versions\n * (newest first) Filters out prerelease versions (canary, alpha, beta, rc,\n * etc.)\n */\nexport function selectTrendVersions(\n\tallVersions: string[],\n\tcount: number = TREND_VERSION_COUNT,\n): string[] {\n\t// Filter out prerelease versions (canary, alpha, beta, rc, etc.)\n\tconst stableVersions = allVersions.filter((v) => !prerelease(v));\n\treturn stableVersions.slice(0, count);\n}\n\n/**\n * Analyze bundle size trend across multiple versions.\n */\nexport async function analyzeTrend(\n\toptions: TrendOptions,\n): Promise<TrendResult[]> {\n\tconst {\n\t\tpackageName,\n\t\tversions,\n\t\texports,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tboring,\n\t\tregistry,\n\t\tplatform,\n\t\tforce,\n\t} = options;\n\n\tconst log = new Logger({ boring });\n\tconst results: TrendResult[] = [];\n\n\t// Parse base package name (without version).\n\tconst { name: baseName } = parsePackageSpecifier(packageName);\n\n\t// Compute externals for cache key (same logic as bundler).\n\tconst externals = getExternals(baseName, additionalExternals, noExternal);\n\n\tfor (const version of versions) {\n\t\tconst versionedPackage = `${packageName}@${version}`;\n\n\t\t/**\n\t\t * Build cache key for this version.\n\t\t * NOTE: platform can be undefined (auto-detect), which is stored as \"auto\" in cache.\n\t\t */\n\t\tconst cacheKey = normalizeCacheKey({\n\t\t\tpackageName: baseName,\n\t\t\tversion,\n\t\t\texports,\n\t\t\tplatform,\n\t\t\tgzipLevel: gzipLevel ?? 5,\n\t\t\texternals,\n\t\t\tnoExternal: noExternal ?? false,\n\t\t});\n\n\t\t// Check cache first (unless --force flag is set).\n\t\tif (!force) {\n\t\t\tconst cached = getCachedResult(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tlog.info(` Checking ${version}... (cached)`);\n\t\t\t\tresults.push({\n\t\t\t\t\tversion,\n\t\t\t\t\trawSize: cached.rawSize,\n\t\t\t\t\tgzipSize: cached.gzipSize,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tlog.info(` Checking ${version}...`);\n\n\t\ttry {\n\t\t\tconst result = await checkBundleSize({\n\t\t\t\tpackageName: versionedPackage,\n\t\t\t\texports,\n\t\t\t\tadditionalExternals,\n\t\t\t\tnoExternal,\n\t\t\t\tgzipLevel,\n\t\t\t\tregistry,\n\t\t\t\tplatform,\n\t\t\t});\n\n\t\t\t// Store result in cache.\n\t\t\tsetCachedResult(cacheKey, result);\n\n\t\t\tresults.push({\n\t\t\t\tversion,\n\t\t\t\trawSize: result.rawSize,\n\t\t\t\tgzipSize: result.gzipSize,\n\t\t\t});\n\t\t} catch {\n\t\t\t// Skip versions that fail to analyze.\n\t\t\tlog.info(` Skipping ${version} (failed to analyze)`);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Render a bar graph showing bundle size trend.\n */\nexport function renderTrendGraph(\n\tpackageName: string,\n\tresults: TrendResult[],\n\tboring: boolean = false,\n): string[] {\n\tif (results.length === 0) {\n\t\treturn [\"No data to display\"];\n\t}\n\n\tconst lines: string[] = [];\n\n\t// Color helper (respects boring flag).\n\tconst blue = (text: string) => (boring ? text : kleur.blue(text));\n\n\t// Check if gzip data is available (null for node platform).\n\tconst hasGzipData = results.some((r) => r.gzipSize !== null);\n\n\t/**\n\t * Create maps from formatted string to representative value This ensures\n\t * values that display the same get the same bar length.\n\t */\n\tconst gzipFormattedToValue = new Map<string, number>();\n\tconst rawFormattedToValue = new Map<string, number>();\n\n\tfor (const result of results) {\n\t\tif (hasGzipData && result.gzipSize !== null) {\n\t\t\tconst gzipFormatted = formatBytes(result.gzipSize);\n\t\t\t// Use first occurrence as representative value for each formatted string.\n\t\t\tif (!gzipFormattedToValue.has(gzipFormatted)) {\n\t\t\t\tgzipFormattedToValue.set(gzipFormatted, result.gzipSize);\n\t\t\t}\n\t\t}\n\t\tconst rawFormatted = formatBytes(result.rawSize);\n\t\tif (!rawFormattedToValue.has(rawFormatted)) {\n\t\t\trawFormattedToValue.set(rawFormatted, result.rawSize);\n\t\t}\n\t}\n\n\t// Get unique representative values for min/max calculation.\n\tconst uniqueGzipValues = [...gzipFormattedToValue.values()];\n\tconst uniqueRawValues = [...rawFormattedToValue.values()];\n\n\tconst minGzipSize = hasGzipData ? Math.min(...uniqueGzipValues) : 0;\n\tconst maxGzipSize = hasGzipData ? Math.max(...uniqueGzipValues) : 0;\n\tconst minRawSize = Math.min(...uniqueRawValues);\n\tconst maxRawSize = Math.max(...uniqueRawValues);\n\n\t// Find max version length for alignment.\n\tconst maxVersionLen = Math.max(...results.map((r) => r.version.length));\n\n\t// Bar width (characters).\n\tconst barWidth = 30;\n\tconst minBarWidth = 10; // Minimum bar length for smallest value\n\n\t// Helper to calculate bar length with min-max scaling.\n\tconst calcBarLength = (value: number, min: number, max: number): number => {\n\t\tif (max === min) {\n\t\t\treturn barWidth; // All values are the same\n\t\t}\n\t\t// Scale from minBarWidth to barWidth based on position between min and max.\n\t\tconst ratio = (value - min) / (max - min);\n\t\treturn Math.round(minBarWidth + ratio * (barWidth - minBarWidth));\n\t};\n\n\t// Header.\n\tlines.push(\"\");\n\tlines.push(`${blue(\"Bundle Size:\")} ${packageName}`);\n\tlines.push(\"─\".repeat(60));\n\tlines.push(\"\");\n\n\t// Gzip size bars (only for browser platform).\n\tif (hasGzipData) {\n\t\tlines.push(blue(\"Gzip Size:\"));\n\t\tfor (const result of results) {\n\t\t\tif (result.gzipSize === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst sizeStr = formatBytes(result.gzipSize);\n\t\t\t/**\n\t\t\t * Use representative value for this formatted string to ensure consistent\n\t\t\t * bar length.\n\t\t\t */\n\t\t\tconst representativeValue = gzipFormattedToValue.get(sizeStr) as number;\n\t\t\tconst barLength = calcBarLength(\n\t\t\t\trepresentativeValue,\n\t\t\t\tminGzipSize,\n\t\t\t\tmaxGzipSize,\n\t\t\t);\n\t\t\tconst bar = \"▇\".repeat(barLength);\n\t\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\t\tlines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);\n\t\t}\n\n\t\tlines.push(\"\");\n\t}\n\n\t// Raw size bars.\n\tlines.push(blue(\"Raw Size:\"));\n\tfor (const result of results) {\n\t\tconst sizeStr = formatBytes(result.rawSize);\n\t\t/**\n\t\t * Use representative value for this formatted string to ensure consistent bar\n\t\t * length.\n\t\t */\n\t\tconst representativeValue = rawFormattedToValue.get(sizeStr) as number;\n\t\tconst barLength = calcBarLength(\n\t\t\trepresentativeValue,\n\t\t\tminRawSize,\n\t\t\tmaxRawSize,\n\t\t);\n\t\tconst bar = \"▇\".repeat(barLength);\n\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\tlines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);\n\t}\n\n\tlines.push(\"\");\n\n\t// Summary.\n\tconst oldestResult = results[results.length - 1];\n\tconst newestResult = results[0];\n\n\tif (results.length > 1) {\n\t\tconst rawDiff = newestResult.rawSize - oldestResult.rawSize;\n\t\tconst rawPercent = ((rawDiff / oldestResult.rawSize) * 100).toFixed(1);\n\t\tconst rawTrend =\n\t\t\trawDiff >= 0\n\t\t\t\t? `+${formatBytes(rawDiff)}`\n\t\t\t\t: `-${formatBytes(Math.abs(rawDiff))}`;\n\n\t\tlines.push(\"─\".repeat(60));\n\t\tlines.push(\n\t\t\t`Change from ${oldestResult.version} to ${newestResult.version}:`,\n\t\t);\n\n\t\t// Gzip summary (only for browser platform).\n\t\tif (\n\t\t\thasGzipData &&\n\t\t\tnewestResult.gzipSize !== null &&\n\t\t\toldestResult.gzipSize !== null\n\t\t) {\n\t\t\tconst gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;\n\t\t\tconst gzipPercent = ((gzipDiff / oldestResult.gzipSize) * 100).toFixed(1);\n\t\t\tconst gzipTrend =\n\t\t\t\tgzipDiff >= 0\n\t\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\n\t\t\tlines.push(\n\t\t\t\t` ${blue(\"Gzip:\")} ${gzipTrend} (${gzipDiff >= 0 ? \"+\" : \"\"}${gzipPercent}%)`,\n\t\t\t);\n\t\t}\n\n\t\tlines.push(\n\t\t\t` ${blue(\"Raw:\")} ${rawTrend} (${rawDiff >= 0 ? \"+\" : \"\"}${rawPercent}%)`,\n\t\t);\n\t}\n\n\tlines.push(\"\");\n\n\treturn lines;\n}\n"],"names":["Logger","kleur","prerelease","checkBundleSize","formatBytes","getExternals","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","TREND_VERSION_COUNT","selectTrendVersions","allVersions","count","stableVersions","filter","v","slice","analyzeTrend","options","packageName","versions","exports","additionalExternals","noExternal","gzipLevel","boring","registry","platform","force","log","results","name","baseName","externals","version","versionedPackage","cacheKey","cached","info","push","rawSize","gzipSize","result","renderTrendGraph","length","lines","blue","text","hasGzipData","some","r","gzipFormattedToValue","Map","rawFormattedToValue","gzipFormatted","has","set","rawFormatted","uniqueGzipValues","values","uniqueRawValues","minGzipSize","Math","min","maxGzipSize","max","minRawSize","maxRawSize","maxVersionLen","map","barWidth","minBarWidth","calcBarLength","value","ratio","round","repeat","sizeStr","representativeValue","get","barLength","bar","padding","oldestResult","newestResult","rawDiff","rawPercent","toFixed","rawTrend","abs","gzipDiff","gzipPercent","gzipTrend"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/trend.ts"],"sourcesContent":["import { Logger } from \"@node-cli/logger\";\nimport kleur from \"kleur\";\nimport { prerelease } from \"semver\";\nimport {\n\tcheckBundleSize,\n\tformatBytes,\n\tgetExternals,\n\tparsePackageSpecifier,\n} from \"./bundler.js\";\nimport {\n\tgetCachedResult,\n\tnormalizeCacheKey,\n\tsetCachedResult,\n} from \"./cache.js\";\nimport { TREND_VERSION_COUNT } from \"./defaults.js\";\n\nexport type TrendResult = {\n\tversion: string;\n\trawSize: number;\n\t/**\n\t * Gzip size in bytes, or null for node platform.\n\t */\n\tgzipSize: number | null;\n};\n\nexport type TrendOptions = {\n\tpackageName: string;\n\tversions: string[];\n\texports?: string[];\n\tadditionalExternals?: string[];\n\tnoExternal?: boolean;\n\tgzipLevel?: number;\n\tboring?: boolean;\n\tregistry?: string;\n\t/**\n\t * Target platform. If undefined, auto-detects from package.json engines.\n\t */\n\tplatform?: \"browser\" | \"node\";\n\t/**\n\t * Bypass cache and force re-fetch/re-calculation.\n\t */\n\tforce?: boolean;\n\t/**\n\t * esbuild target (e.g., \"es2022\", \"es2020\"). Defaults to \"es2022\".\n\t */\n\ttarget?: string;\n};\n\n/**\n * Select versions for trend analysis Returns the most recent stable versions\n * (newest first) Filters out prerelease versions (canary, alpha, beta, rc,\n * etc.)\n */\nexport function selectTrendVersions(\n\tallVersions: string[],\n\tcount: number = TREND_VERSION_COUNT,\n): string[] {\n\t// Filter out prerelease versions (canary, alpha, beta, rc, etc.)\n\tconst stableVersions = allVersions.filter((v) => !prerelease(v));\n\treturn stableVersions.slice(0, count);\n}\n\n/**\n * Analyze bundle size trend across multiple versions.\n */\nexport async function analyzeTrend(\n\toptions: TrendOptions,\n): Promise<TrendResult[]> {\n\tconst {\n\t\tpackageName,\n\t\tversions,\n\t\texports,\n\t\tadditionalExternals,\n\t\tnoExternal,\n\t\tgzipLevel,\n\t\tboring,\n\t\tregistry,\n\t\tplatform,\n\t\tforce,\n\t\ttarget,\n\t} = options;\n\n\tconst log = new Logger({ boring });\n\tconst results: TrendResult[] = [];\n\n\t// Parse base package name (without version).\n\tconst { name: baseName } = parsePackageSpecifier(packageName);\n\n\t// Compute externals for cache key (same logic as bundler).\n\tconst externals = getExternals(baseName, additionalExternals, noExternal);\n\n\tfor (const version of versions) {\n\t\tconst versionedPackage = `${packageName}@${version}`;\n\n\t\t/**\n\t\t * Build cache key for this version.\n\t\t * NOTE: platform can be undefined (auto-detect), which is stored as \"auto\" in cache.\n\t\t */\n\t\tconst cacheKey = normalizeCacheKey({\n\t\t\tpackageName: baseName,\n\t\t\tversion,\n\t\t\texports,\n\t\t\tplatform,\n\t\t\tgzipLevel: gzipLevel ?? 5,\n\t\t\texternals,\n\t\t\tnoExternal: noExternal ?? false,\n\t\t});\n\n\t\t// Check cache first (unless --force flag is set).\n\t\tif (!force) {\n\t\t\tconst cached = getCachedResult(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\tlog.info(` Checking ${version}... (cached)`);\n\t\t\t\tresults.push({\n\t\t\t\t\tversion,\n\t\t\t\t\trawSize: cached.rawSize,\n\t\t\t\t\tgzipSize: cached.gzipSize,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tlog.info(` Checking ${version}...`);\n\n\t\ttry {\n\t\t\tconst result = await checkBundleSize({\n\t\t\t\tpackageName: versionedPackage,\n\t\t\t\texports,\n\t\t\t\tadditionalExternals,\n\t\t\t\tnoExternal,\n\t\t\t\tgzipLevel,\n\t\t\t\tregistry,\n\t\t\t\tplatform,\n\t\t\t\ttarget,\n\t\t\t});\n\n\t\t\t// Store result in cache.\n\t\t\tsetCachedResult(cacheKey, result);\n\n\t\t\tresults.push({\n\t\t\t\tversion,\n\t\t\t\trawSize: result.rawSize,\n\t\t\t\tgzipSize: result.gzipSize,\n\t\t\t});\n\t\t} catch {\n\t\t\t// Skip versions that fail to analyze.\n\t\t\tlog.info(` Skipping ${version} (failed to analyze)`);\n\t\t}\n\t}\n\n\treturn results;\n}\n\n/**\n * Render a bar graph showing bundle size trend.\n */\nexport function renderTrendGraph(\n\tpackageName: string,\n\tresults: TrendResult[],\n\tboring: boolean = false,\n): string[] {\n\tif (results.length === 0) {\n\t\treturn [\"No data to display\"];\n\t}\n\n\tconst lines: string[] = [];\n\n\t// Color helper (respects boring flag).\n\tconst blue = (text: string) => (boring ? text : kleur.blue(text));\n\n\t// Check if gzip data is available (null for node platform).\n\tconst hasGzipData = results.some((r) => r.gzipSize !== null);\n\n\t/**\n\t * Create maps from formatted string to representative value This ensures\n\t * values that display the same get the same bar length.\n\t */\n\tconst gzipFormattedToValue = new Map<string, number>();\n\tconst rawFormattedToValue = new Map<string, number>();\n\n\tfor (const result of results) {\n\t\tif (hasGzipData && result.gzipSize !== null) {\n\t\t\tconst gzipFormatted = formatBytes(result.gzipSize);\n\t\t\t// Use first occurrence as representative value for each formatted string.\n\t\t\tif (!gzipFormattedToValue.has(gzipFormatted)) {\n\t\t\t\tgzipFormattedToValue.set(gzipFormatted, result.gzipSize);\n\t\t\t}\n\t\t}\n\t\tconst rawFormatted = formatBytes(result.rawSize);\n\t\tif (!rawFormattedToValue.has(rawFormatted)) {\n\t\t\trawFormattedToValue.set(rawFormatted, result.rawSize);\n\t\t}\n\t}\n\n\t// Get unique representative values for min/max calculation.\n\tconst uniqueGzipValues = [...gzipFormattedToValue.values()];\n\tconst uniqueRawValues = [...rawFormattedToValue.values()];\n\n\tconst minGzipSize = hasGzipData ? Math.min(...uniqueGzipValues) : 0;\n\tconst maxGzipSize = hasGzipData ? Math.max(...uniqueGzipValues) : 0;\n\tconst minRawSize = Math.min(...uniqueRawValues);\n\tconst maxRawSize = Math.max(...uniqueRawValues);\n\n\t// Find max version length for alignment.\n\tconst maxVersionLen = Math.max(...results.map((r) => r.version.length));\n\n\t// Bar width (characters).\n\tconst barWidth = 30;\n\tconst minBarWidth = 10; // Minimum bar length for smallest value\n\n\t// Helper to calculate bar length with min-max scaling.\n\tconst calcBarLength = (value: number, min: number, max: number): number => {\n\t\tif (max === min) {\n\t\t\treturn barWidth; // All values are the same\n\t\t}\n\t\t// Scale from minBarWidth to barWidth based on position between min and max.\n\t\tconst ratio = (value - min) / (max - min);\n\t\treturn Math.round(minBarWidth + ratio * (barWidth - minBarWidth));\n\t};\n\n\t// Header.\n\tlines.push(\"\");\n\tlines.push(`${blue(\"Bundle Size:\")} ${packageName}`);\n\tlines.push(\"─\".repeat(60));\n\tlines.push(\"\");\n\n\t// Gzip size bars (only for browser platform).\n\tif (hasGzipData) {\n\t\tlines.push(blue(\"Gzip Size:\"));\n\t\tfor (const result of results) {\n\t\t\tif (result.gzipSize === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst sizeStr = formatBytes(result.gzipSize);\n\t\t\t/**\n\t\t\t * Use representative value for this formatted string to ensure consistent\n\t\t\t * bar length.\n\t\t\t */\n\t\t\tconst representativeValue = gzipFormattedToValue.get(sizeStr) as number;\n\t\t\tconst barLength = calcBarLength(\n\t\t\t\trepresentativeValue,\n\t\t\t\tminGzipSize,\n\t\t\t\tmaxGzipSize,\n\t\t\t);\n\t\t\tconst bar = \"▇\".repeat(barLength);\n\t\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\t\tlines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);\n\t\t}\n\n\t\tlines.push(\"\");\n\t}\n\n\t// Raw size bars.\n\tlines.push(blue(\"Raw Size:\"));\n\tfor (const result of results) {\n\t\tconst sizeStr = formatBytes(result.rawSize);\n\t\t/**\n\t\t * Use representative value for this formatted string to ensure consistent bar\n\t\t * length.\n\t\t */\n\t\tconst representativeValue = rawFormattedToValue.get(sizeStr) as number;\n\t\tconst barLength = calcBarLength(\n\t\t\trepresentativeValue,\n\t\t\tminRawSize,\n\t\t\tmaxRawSize,\n\t\t);\n\t\tconst bar = \"▇\".repeat(barLength);\n\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\tlines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);\n\t}\n\n\tlines.push(\"\");\n\n\t// Summary.\n\tconst oldestResult = results[results.length - 1];\n\tconst newestResult = results[0];\n\n\tif (results.length > 1) {\n\t\tconst rawDiff = newestResult.rawSize - oldestResult.rawSize;\n\t\tconst rawPercent = ((rawDiff / oldestResult.rawSize) * 100).toFixed(1);\n\t\tconst rawTrend =\n\t\t\trawDiff >= 0\n\t\t\t\t? `+${formatBytes(rawDiff)}`\n\t\t\t\t: `-${formatBytes(Math.abs(rawDiff))}`;\n\n\t\tlines.push(\"─\".repeat(60));\n\t\tlines.push(\n\t\t\t`Change from ${oldestResult.version} to ${newestResult.version}:`,\n\t\t);\n\n\t\t// Gzip summary (only for browser platform).\n\t\tif (\n\t\t\thasGzipData &&\n\t\t\tnewestResult.gzipSize !== null &&\n\t\t\toldestResult.gzipSize !== null\n\t\t) {\n\t\t\tconst gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;\n\t\t\tconst gzipPercent = ((gzipDiff / oldestResult.gzipSize) * 100).toFixed(1);\n\t\t\tconst gzipTrend =\n\t\t\t\tgzipDiff >= 0\n\t\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\n\t\t\tlines.push(\n\t\t\t\t` ${blue(\"Gzip:\")} ${gzipTrend} (${gzipDiff >= 0 ? \"+\" : \"\"}${gzipPercent}%)`,\n\t\t\t);\n\t\t}\n\n\t\tlines.push(\n\t\t\t` ${blue(\"Raw:\")} ${rawTrend} (${rawDiff >= 0 ? \"+\" : \"\"}${rawPercent}%)`,\n\t\t);\n\t}\n\n\tlines.push(\"\");\n\n\treturn lines;\n}\n"],"names":["Logger","kleur","prerelease","checkBundleSize","formatBytes","getExternals","parsePackageSpecifier","getCachedResult","normalizeCacheKey","setCachedResult","TREND_VERSION_COUNT","selectTrendVersions","allVersions","count","stableVersions","filter","v","slice","analyzeTrend","options","packageName","versions","exports","additionalExternals","noExternal","gzipLevel","boring","registry","platform","force","target","log","results","name","baseName","externals","version","versionedPackage","cacheKey","cached","info","push","rawSize","gzipSize","result","renderTrendGraph","length","lines","blue","text","hasGzipData","some","r","gzipFormattedToValue","Map","rawFormattedToValue","gzipFormatted","has","set","rawFormatted","uniqueGzipValues","values","uniqueRawValues","minGzipSize","Math","min","maxGzipSize","max","minRawSize","maxRawSize","maxVersionLen","map","barWidth","minBarWidth","calcBarLength","value","ratio","round","repeat","sizeStr","representativeValue","get","barLength","bar","padding","oldestResult","newestResult","rawDiff","rawPercent","toFixed","rawTrend","abs","gzipDiff","gzipPercent","gzipTrend"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-cli/bundlecheck",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"description": "CLI tool to check the bundle size of npm packages (like bundlephobia)",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"@vitest/coverage-v8": "4.0.18",
|
|
51
51
|
"vitest": "4.0.18"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "bb80931807dd01d5b115de9c867d9cea178573ff"
|
|
54
54
|
}
|