@node-cli/bundlecheck 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/trend.js CHANGED
@@ -54,27 +54,41 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
54
54
  const lines = [];
55
55
  // Color helper (respects boring flag)
56
56
  const blue = (text)=>boring ? text : kleur.blue(text);
57
- // Find min/max sizes for scaling (use min-max scaling to show differences)
58
- const gzipSizes = results.map((r)=>r.gzipSize);
59
- const rawSizes = results.map((r)=>r.rawSize);
60
- const minGzipSize = Math.min(...gzipSizes);
61
- const maxGzipSize = Math.max(...gzipSizes);
62
- const minRawSize = Math.min(...rawSizes);
63
- const maxRawSize = Math.max(...rawSizes);
64
- // Check if all formatted values are the same (to avoid misleading bar differences)
65
- const formattedGzipSizes = results.map((r)=>formatBytes(r.gzipSize));
66
- const formattedRawSizes = results.map((r)=>formatBytes(r.rawSize));
67
- const allGzipSame = new Set(formattedGzipSizes).size === 1;
68
- const allRawSame = new Set(formattedRawSizes).size === 1;
57
+ // Create maps from formatted string to representative value
58
+ // This ensures values that display the same get the same bar length
59
+ const gzipFormattedToValue = new Map();
60
+ const rawFormattedToValue = new Map();
61
+ for (const result of results){
62
+ const gzipFormatted = formatBytes(result.gzipSize);
63
+ const rawFormatted = formatBytes(result.rawSize);
64
+ // Use first occurrence as representative value for each formatted string
65
+ if (!gzipFormattedToValue.has(gzipFormatted)) {
66
+ gzipFormattedToValue.set(gzipFormatted, result.gzipSize);
67
+ }
68
+ if (!rawFormattedToValue.has(rawFormatted)) {
69
+ rawFormattedToValue.set(rawFormatted, result.rawSize);
70
+ }
71
+ }
72
+ // Get unique representative values for min/max calculation
73
+ const uniqueGzipValues = [
74
+ ...gzipFormattedToValue.values()
75
+ ];
76
+ const uniqueRawValues = [
77
+ ...rawFormattedToValue.values()
78
+ ];
79
+ const minGzipSize = Math.min(...uniqueGzipValues);
80
+ const maxGzipSize = Math.max(...uniqueGzipValues);
81
+ const minRawSize = Math.min(...uniqueRawValues);
82
+ const maxRawSize = Math.max(...uniqueRawValues);
69
83
  // Find max version length for alignment
70
84
  const maxVersionLen = Math.max(...results.map((r)=>r.version.length));
71
85
  // Bar width (characters)
72
86
  const barWidth = 30;
73
87
  const minBarWidth = 10; // Minimum bar length for smallest value
74
88
  // Helper to calculate bar length with min-max scaling
75
- const calcBarLength = (value, min, max, allSame)=>{
76
- if (max === min || allSame) {
77
- return barWidth; // All values are effectively the same
89
+ const calcBarLength = (value, min, max)=>{
90
+ if (max === min) {
91
+ return barWidth; // All values are the same
78
92
  }
79
93
  // Scale from minBarWidth to barWidth based on position between min and max
80
94
  const ratio = (value - min) / (max - min);
@@ -88,20 +102,24 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
88
102
  // Gzip size bars
89
103
  lines.push(blue("Gzip Size:"));
90
104
  for (const result of results){
91
- const barLength = calcBarLength(result.gzipSize, minGzipSize, maxGzipSize, allGzipSame);
105
+ const sizeStr = formatBytes(result.gzipSize);
106
+ // Use representative value for this formatted string to ensure consistent bar length
107
+ const representativeValue = gzipFormattedToValue.get(sizeStr);
108
+ const barLength = calcBarLength(representativeValue, minGzipSize, maxGzipSize);
92
109
  const bar = "▇".repeat(barLength);
93
110
  const padding = " ".repeat(maxVersionLen - result.version.length);
94
- const sizeStr = formatBytes(result.gzipSize);
95
111
  lines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);
96
112
  }
97
113
  lines.push("");
98
114
  // Raw size bars
99
115
  lines.push(blue("Raw Size:"));
100
116
  for (const result of results){
101
- const barLength = calcBarLength(result.rawSize, minRawSize, maxRawSize, allRawSame);
117
+ const sizeStr = formatBytes(result.rawSize);
118
+ // Use representative value for this formatted string to ensure consistent bar length
119
+ const representativeValue = rawFormattedToValue.get(sizeStr);
120
+ const barLength = calcBarLength(representativeValue, minRawSize, maxRawSize);
102
121
  const bar = "▇".repeat(barLength);
103
122
  const padding = " ".repeat(maxVersionLen - result.version.length);
104
- const sizeStr = formatBytes(result.rawSize);
105
123
  lines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);
106
124
  }
107
125
  lines.push("");
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 { checkBundleSize, formatBytes } from \"./bundler.js\";\nimport { TREND_VERSION_COUNT } from \"./defaults.js\";\n\nexport type TrendResult = {\n\tversion: string;\n\trawSize: number;\n\tgzipSize: number;\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};\n\n/**\n * Select versions for trend analysis\n * Returns the most recent stable versions (newest first)\n * Filters out prerelease versions (canary, alpha, beta, rc, 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} = options;\n\n\tconst log = new Logger({ boring });\n\tconst results: TrendResult[] = [];\n\n\tfor (const version of versions) {\n\t\tconst versionedPackage = `${packageName}@${version}`;\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});\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// Find min/max sizes for scaling (use min-max scaling to show differences)\n\tconst gzipSizes = results.map((r) => r.gzipSize);\n\tconst rawSizes = results.map((r) => r.rawSize);\n\n\tconst minGzipSize = Math.min(...gzipSizes);\n\tconst maxGzipSize = Math.max(...gzipSizes);\n\tconst minRawSize = Math.min(...rawSizes);\n\tconst maxRawSize = Math.max(...rawSizes);\n\n\t// Check if all formatted values are the same (to avoid misleading bar differences)\n\tconst formattedGzipSizes = results.map((r) => formatBytes(r.gzipSize));\n\tconst formattedRawSizes = results.map((r) => formatBytes(r.rawSize));\n\tconst allGzipSame = new Set(formattedGzipSizes).size === 1;\n\tconst allRawSame = new Set(formattedRawSizes).size === 1;\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 = (\n\t\tvalue: number,\n\t\tmin: number,\n\t\tmax: number,\n\t\tallSame: boolean,\n\t): number => {\n\t\tif (max === min || allSame) {\n\t\t\treturn barWidth; // All values are effectively 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\n\tlines.push(blue(\"Gzip Size:\"));\n\tfor (const result of results) {\n\t\tconst barLength = calcBarLength(\n\t\t\tresult.gzipSize,\n\t\t\tminGzipSize,\n\t\t\tmaxGzipSize,\n\t\t\tallGzipSame,\n\t\t);\n\t\tconst bar = \"▇\".repeat(barLength);\n\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\tconst sizeStr = formatBytes(result.gzipSize);\n\t\tlines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);\n\t}\n\n\tlines.push(\"\");\n\n\t// Raw size bars\n\tlines.push(blue(\"Raw Size:\"));\n\tfor (const result of results) {\n\t\tconst barLength = calcBarLength(\n\t\t\tresult.rawSize,\n\t\t\tminRawSize,\n\t\t\tmaxRawSize,\n\t\t\tallRawSame,\n\t\t);\n\t\tconst bar = \"▇\".repeat(barLength);\n\t\tconst padding = \" \".repeat(maxVersionLen - result.version.length);\n\t\tconst sizeStr = formatBytes(result.rawSize);\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 gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;\n\t\tconst gzipPercent = ((gzipDiff / oldestResult.gzipSize) * 100).toFixed(1);\n\t\tconst rawDiff = newestResult.rawSize - oldestResult.rawSize;\n\t\tconst rawPercent = ((rawDiff / oldestResult.rawSize) * 100).toFixed(1);\n\n\t\tconst gzipTrend =\n\t\t\tgzipDiff >= 0\n\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\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\t\tlines.push(\n\t\t\t` ${blue(\"Gzip:\")} ${gzipTrend} (${gzipDiff >= 0 ? \"+\" : \"\"}${gzipPercent}%)`,\n\t\t);\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","TREND_VERSION_COUNT","selectTrendVersions","allVersions","count","stableVersions","filter","v","slice","analyzeTrend","options","packageName","versions","exports","additionalExternals","noExternal","gzipLevel","boring","log","results","version","versionedPackage","info","result","push","rawSize","gzipSize","renderTrendGraph","length","lines","blue","text","gzipSizes","map","r","rawSizes","minGzipSize","Math","min","maxGzipSize","max","minRawSize","maxRawSize","formattedGzipSizes","formattedRawSizes","allGzipSame","Set","size","allRawSame","maxVersionLen","barWidth","minBarWidth","calcBarLength","value","allSame","ratio","round","repeat","barLength","bar","padding","sizeStr","oldestResult","newestResult","gzipDiff","gzipPercent","toFixed","rawDiff","rawPercent","gzipTrend","abs","rawTrend"],"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 { checkBundleSize, formatBytes } from \"./bundler.js\";\nimport { TREND_VERSION_COUNT } from \"./defaults.js\";\n\nexport type TrendResult = {\n\tversion: string;\n\trawSize: number;\n\tgzipSize: number;\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};\n\n/**\n * Select versions for trend analysis\n * Returns the most recent stable versions (newest first)\n * Filters out prerelease versions (canary, alpha, beta, rc, 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} = options;\n\n\tconst log = new Logger({ boring });\n\tconst results: TrendResult[] = [];\n\n\tfor (const version of versions) {\n\t\tconst versionedPackage = `${packageName}@${version}`;\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});\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// Create maps from formatted string to representative value\n\t// This ensures values that display the same get the same bar length\n\tconst gzipFormattedToValue = new Map<string, number>();\n\tconst rawFormattedToValue = new Map<string, number>();\n\n\tfor (const result of results) {\n\t\tconst gzipFormatted = formatBytes(result.gzipSize);\n\t\tconst rawFormatted = formatBytes(result.rawSize);\n\t\t// Use first occurrence as representative value for each formatted string\n\t\tif (!gzipFormattedToValue.has(gzipFormatted)) {\n\t\t\tgzipFormattedToValue.set(gzipFormatted, result.gzipSize);\n\t\t}\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 = Math.min(...uniqueGzipValues);\n\tconst maxGzipSize = Math.max(...uniqueGzipValues);\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\n\tlines.push(blue(\"Gzip Size:\"));\n\tfor (const result of results) {\n\t\tconst sizeStr = formatBytes(result.gzipSize);\n\t\t// Use representative value for this formatted string to ensure consistent bar length\n\t\tconst representativeValue = gzipFormattedToValue.get(sizeStr) as number;\n\t\tconst barLength = calcBarLength(\n\t\t\trepresentativeValue,\n\t\t\tminGzipSize,\n\t\t\tmaxGzipSize,\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// 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// Use representative value for this formatted string to ensure consistent bar length\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 gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;\n\t\tconst gzipPercent = ((gzipDiff / oldestResult.gzipSize) * 100).toFixed(1);\n\t\tconst rawDiff = newestResult.rawSize - oldestResult.rawSize;\n\t\tconst rawPercent = ((rawDiff / oldestResult.rawSize) * 100).toFixed(1);\n\n\t\tconst gzipTrend =\n\t\t\tgzipDiff >= 0\n\t\t\t\t? `+${formatBytes(gzipDiff)}`\n\t\t\t\t: `-${formatBytes(Math.abs(gzipDiff))}`;\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\t\tlines.push(\n\t\t\t` ${blue(\"Gzip:\")} ${gzipTrend} (${gzipDiff >= 0 ? \"+\" : \"\"}${gzipPercent}%)`,\n\t\t);\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","TREND_VERSION_COUNT","selectTrendVersions","allVersions","count","stableVersions","filter","v","slice","analyzeTrend","options","packageName","versions","exports","additionalExternals","noExternal","gzipLevel","boring","log","results","version","versionedPackage","info","result","push","rawSize","gzipSize","renderTrendGraph","length","lines","blue","text","gzipFormattedToValue","Map","rawFormattedToValue","gzipFormatted","rawFormatted","has","set","uniqueGzipValues","values","uniqueRawValues","minGzipSize","Math","min","maxGzipSize","max","minRawSize","maxRawSize","maxVersionLen","map","r","barWidth","minBarWidth","calcBarLength","value","ratio","round","repeat","sizeStr","representativeValue","get","barLength","bar","padding","oldestResult","newestResult","gzipDiff","gzipPercent","toFixed","rawDiff","rawPercent","gzipTrend","abs","rawTrend"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-cli/bundlecheck",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "license": "MIT",
5
5
  "author": "Arno Versini",
6
6
  "description": "CLI tool to check the bundle size of npm packages (like bundlephobia)",
@@ -48,5 +48,5 @@
48
48
  "@vitest/coverage-v8": "4.0.18",
49
49
  "vitest": "4.0.18"
50
50
  },
51
- "gitHead": "290c95d11163e5beace97376acc91ecbf1eecfce"
51
+ "gitHead": "9a5656abbda863cba86bdf6e3fb2f6d959515a54"
52
52
  }