@node-cli/bundlecheck 1.2.0 → 1.4.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 +287 -11
- package/dist/bundlecheck.js +82 -32
- package/dist/bundlecheck.js.map +1 -1
- package/dist/bundler.d.ts +17 -4
- package/dist/bundler.js +113 -91
- package/dist/bundler.js.map +1 -1
- package/dist/cache.d.ts +62 -0
- package/dist/cache.js +196 -0
- package/dist/cache.js.map +1 -0
- package/dist/defaults.d.ts +13 -0
- package/dist/defaults.js +65 -1
- package/dist/defaults.js.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.js +229 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +2 -0
- package/dist/parse.js +26 -1
- package/dist/parse.js.map +1 -1
- package/dist/trend.d.ts +17 -6
- package/dist/trend.js +95 -45
- package/dist/trend.js.map +1 -1
- package/dist/versions.d.ts +1 -1
- package/dist/versions.js +12 -10
- package/dist/versions.js.map +1 -1
- package/package.json +6 -3
package/dist/trend.js
CHANGED
|
@@ -1,27 +1,57 @@
|
|
|
1
1
|
import { Logger } from "@node-cli/logger";
|
|
2
2
|
import kleur from "kleur";
|
|
3
3
|
import { prerelease } from "semver";
|
|
4
|
-
import { checkBundleSize, formatBytes } from "./bundler.js";
|
|
4
|
+
import { checkBundleSize, formatBytes, getExternals, parsePackageSpecifier } from "./bundler.js";
|
|
5
|
+
import { getCachedResult, normalizeCacheKey, setCachedResult } from "./cache.js";
|
|
5
6
|
import { TREND_VERSION_COUNT } from "./defaults.js";
|
|
6
7
|
/**
|
|
7
|
-
* Select versions for trend analysis
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Select versions for trend analysis Returns the most recent stable versions
|
|
9
|
+
* (newest first) Filters out prerelease versions (canary, alpha, beta, rc,
|
|
10
|
+
* etc.)
|
|
10
11
|
*/ export function selectTrendVersions(allVersions, count = TREND_VERSION_COUNT) {
|
|
11
12
|
// Filter out prerelease versions (canary, alpha, beta, rc, etc.)
|
|
12
13
|
const stableVersions = allVersions.filter((v)=>!prerelease(v));
|
|
13
14
|
return stableVersions.slice(0, count);
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
|
-
* Analyze bundle size trend across multiple versions
|
|
17
|
+
* Analyze bundle size trend across multiple versions.
|
|
17
18
|
*/ export async function analyzeTrend(options) {
|
|
18
|
-
const { packageName, versions, exports, additionalExternals, noExternal, gzipLevel, boring, registry } = options;
|
|
19
|
+
const { packageName, versions, exports, additionalExternals, noExternal, gzipLevel, boring, registry, platform, force } = options;
|
|
19
20
|
const log = new Logger({
|
|
20
21
|
boring
|
|
21
22
|
});
|
|
22
23
|
const results = [];
|
|
24
|
+
// Parse base package name (without version).
|
|
25
|
+
const { name: baseName } = parsePackageSpecifier(packageName);
|
|
26
|
+
// Compute externals for cache key (same logic as bundler).
|
|
27
|
+
const externals = getExternals(baseName, additionalExternals, noExternal);
|
|
23
28
|
for (const version of versions){
|
|
24
29
|
const versionedPackage = `${packageName}@${version}`;
|
|
30
|
+
/**
|
|
31
|
+
* Build cache key for this version.
|
|
32
|
+
* NOTE: platform can be undefined (auto-detect), which is stored as "auto" in cache.
|
|
33
|
+
*/ const cacheKey = normalizeCacheKey({
|
|
34
|
+
packageName: baseName,
|
|
35
|
+
version,
|
|
36
|
+
exports,
|
|
37
|
+
platform,
|
|
38
|
+
gzipLevel: gzipLevel ?? 5,
|
|
39
|
+
externals,
|
|
40
|
+
noExternal: noExternal ?? false
|
|
41
|
+
});
|
|
42
|
+
// Check cache first (unless --force flag is set).
|
|
43
|
+
if (!force) {
|
|
44
|
+
const cached = getCachedResult(cacheKey);
|
|
45
|
+
if (cached) {
|
|
46
|
+
log.info(` Checking ${version}... (cached)`);
|
|
47
|
+
results.push({
|
|
48
|
+
version,
|
|
49
|
+
rawSize: cached.rawSize,
|
|
50
|
+
gzipSize: cached.gzipSize
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
25
55
|
log.info(` Checking ${version}...`);
|
|
26
56
|
try {
|
|
27
57
|
const result = await checkBundleSize({
|
|
@@ -30,22 +60,25 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
|
|
|
30
60
|
additionalExternals,
|
|
31
61
|
noExternal,
|
|
32
62
|
gzipLevel,
|
|
33
|
-
registry
|
|
63
|
+
registry,
|
|
64
|
+
platform
|
|
34
65
|
});
|
|
66
|
+
// Store result in cache.
|
|
67
|
+
setCachedResult(cacheKey, result);
|
|
35
68
|
results.push({
|
|
36
69
|
version,
|
|
37
70
|
rawSize: result.rawSize,
|
|
38
71
|
gzipSize: result.gzipSize
|
|
39
72
|
});
|
|
40
73
|
} catch {
|
|
41
|
-
// Skip versions that fail to analyze
|
|
74
|
+
// Skip versions that fail to analyze.
|
|
42
75
|
log.info(` Skipping ${version} (failed to analyze)`);
|
|
43
76
|
}
|
|
44
77
|
}
|
|
45
78
|
return results;
|
|
46
79
|
}
|
|
47
80
|
/**
|
|
48
|
-
* Render a bar graph showing bundle size trend
|
|
81
|
+
* Render a bar graph showing bundle size trend.
|
|
49
82
|
*/ export function renderTrendGraph(packageName, results, boring = false) {
|
|
50
83
|
if (results.length === 0) {
|
|
51
84
|
return [
|
|
@@ -53,90 +86,107 @@ import { TREND_VERSION_COUNT } from "./defaults.js";
|
|
|
53
86
|
];
|
|
54
87
|
}
|
|
55
88
|
const lines = [];
|
|
56
|
-
// Color helper (respects boring flag)
|
|
89
|
+
// Color helper (respects boring flag).
|
|
57
90
|
const blue = (text)=>boring ? text : kleur.blue(text);
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
91
|
+
// Check if gzip data is available (null for node platform).
|
|
92
|
+
const hasGzipData = results.some((r)=>r.gzipSize !== null);
|
|
93
|
+
/**
|
|
94
|
+
* Create maps from formatted string to representative value This ensures
|
|
95
|
+
* values that display the same get the same bar length.
|
|
96
|
+
*/ const gzipFormattedToValue = new Map();
|
|
61
97
|
const rawFormattedToValue = new Map();
|
|
62
98
|
for (const result of results){
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
99
|
+
if (hasGzipData && result.gzipSize !== null) {
|
|
100
|
+
const gzipFormatted = formatBytes(result.gzipSize);
|
|
101
|
+
// Use first occurrence as representative value for each formatted string.
|
|
102
|
+
if (!gzipFormattedToValue.has(gzipFormatted)) {
|
|
103
|
+
gzipFormattedToValue.set(gzipFormatted, result.gzipSize);
|
|
104
|
+
}
|
|
68
105
|
}
|
|
106
|
+
const rawFormatted = formatBytes(result.rawSize);
|
|
69
107
|
if (!rawFormattedToValue.has(rawFormatted)) {
|
|
70
108
|
rawFormattedToValue.set(rawFormatted, result.rawSize);
|
|
71
109
|
}
|
|
72
110
|
}
|
|
73
|
-
// Get unique representative values for min/max calculation
|
|
111
|
+
// Get unique representative values for min/max calculation.
|
|
74
112
|
const uniqueGzipValues = [
|
|
75
113
|
...gzipFormattedToValue.values()
|
|
76
114
|
];
|
|
77
115
|
const uniqueRawValues = [
|
|
78
116
|
...rawFormattedToValue.values()
|
|
79
117
|
];
|
|
80
|
-
const minGzipSize = Math.min(...uniqueGzipValues);
|
|
81
|
-
const maxGzipSize = Math.max(...uniqueGzipValues);
|
|
118
|
+
const minGzipSize = hasGzipData ? Math.min(...uniqueGzipValues) : 0;
|
|
119
|
+
const maxGzipSize = hasGzipData ? Math.max(...uniqueGzipValues) : 0;
|
|
82
120
|
const minRawSize = Math.min(...uniqueRawValues);
|
|
83
121
|
const maxRawSize = Math.max(...uniqueRawValues);
|
|
84
|
-
// Find max version length for alignment
|
|
122
|
+
// Find max version length for alignment.
|
|
85
123
|
const maxVersionLen = Math.max(...results.map((r)=>r.version.length));
|
|
86
|
-
// Bar width (characters)
|
|
124
|
+
// Bar width (characters).
|
|
87
125
|
const barWidth = 30;
|
|
88
126
|
const minBarWidth = 10; // Minimum bar length for smallest value
|
|
89
|
-
// Helper to calculate bar length with min-max scaling
|
|
127
|
+
// Helper to calculate bar length with min-max scaling.
|
|
90
128
|
const calcBarLength = (value, min, max)=>{
|
|
91
129
|
if (max === min) {
|
|
92
130
|
return barWidth; // All values are the same
|
|
93
131
|
}
|
|
94
|
-
// Scale from minBarWidth to barWidth based on position between min and max
|
|
132
|
+
// Scale from minBarWidth to barWidth based on position between min and max.
|
|
95
133
|
const ratio = (value - min) / (max - min);
|
|
96
134
|
return Math.round(minBarWidth + ratio * (barWidth - minBarWidth));
|
|
97
135
|
};
|
|
98
|
-
// Header
|
|
136
|
+
// Header.
|
|
99
137
|
lines.push("");
|
|
100
138
|
lines.push(`${blue("Bundle Size:")} ${packageName}`);
|
|
101
139
|
lines.push("─".repeat(60));
|
|
102
140
|
lines.push("");
|
|
103
|
-
// Gzip size bars
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
141
|
+
// Gzip size bars (only for browser platform).
|
|
142
|
+
if (hasGzipData) {
|
|
143
|
+
lines.push(blue("Gzip Size:"));
|
|
144
|
+
for (const result of results){
|
|
145
|
+
if (result.gzipSize === null) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const sizeStr = formatBytes(result.gzipSize);
|
|
149
|
+
/**
|
|
150
|
+
* Use representative value for this formatted string to ensure consistent
|
|
151
|
+
* bar length.
|
|
152
|
+
*/ const representativeValue = gzipFormattedToValue.get(sizeStr);
|
|
153
|
+
const barLength = calcBarLength(representativeValue, minGzipSize, maxGzipSize);
|
|
154
|
+
const bar = "▇".repeat(barLength);
|
|
155
|
+
const padding = " ".repeat(maxVersionLen - result.version.length);
|
|
156
|
+
lines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);
|
|
157
|
+
}
|
|
158
|
+
lines.push("");
|
|
113
159
|
}
|
|
114
|
-
|
|
115
|
-
// Raw size bars
|
|
160
|
+
// Raw size bars.
|
|
116
161
|
lines.push(blue("Raw Size:"));
|
|
117
162
|
for (const result of results){
|
|
118
163
|
const sizeStr = formatBytes(result.rawSize);
|
|
119
|
-
|
|
120
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Use representative value for this formatted string to ensure consistent bar
|
|
166
|
+
* length.
|
|
167
|
+
*/ const representativeValue = rawFormattedToValue.get(sizeStr);
|
|
121
168
|
const barLength = calcBarLength(representativeValue, minRawSize, maxRawSize);
|
|
122
169
|
const bar = "▇".repeat(barLength);
|
|
123
170
|
const padding = " ".repeat(maxVersionLen - result.version.length);
|
|
124
171
|
lines.push(` ${result.version}${padding} ${bar} ${sizeStr}`);
|
|
125
172
|
}
|
|
126
173
|
lines.push("");
|
|
127
|
-
// Summary
|
|
174
|
+
// Summary.
|
|
128
175
|
const oldestResult = results[results.length - 1];
|
|
129
176
|
const newestResult = results[0];
|
|
130
177
|
if (results.length > 1) {
|
|
131
|
-
const gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;
|
|
132
|
-
const gzipPercent = (gzipDiff / oldestResult.gzipSize * 100).toFixed(1);
|
|
133
178
|
const rawDiff = newestResult.rawSize - oldestResult.rawSize;
|
|
134
179
|
const rawPercent = (rawDiff / oldestResult.rawSize * 100).toFixed(1);
|
|
135
|
-
const gzipTrend = gzipDiff >= 0 ? `+${formatBytes(gzipDiff)}` : `-${formatBytes(Math.abs(gzipDiff))}`;
|
|
136
180
|
const rawTrend = rawDiff >= 0 ? `+${formatBytes(rawDiff)}` : `-${formatBytes(Math.abs(rawDiff))}`;
|
|
137
181
|
lines.push("─".repeat(60));
|
|
138
182
|
lines.push(`Change from ${oldestResult.version} to ${newestResult.version}:`);
|
|
139
|
-
|
|
183
|
+
// Gzip summary (only for browser platform).
|
|
184
|
+
if (hasGzipData && newestResult.gzipSize !== null && oldestResult.gzipSize !== null) {
|
|
185
|
+
const gzipDiff = newestResult.gzipSize - oldestResult.gzipSize;
|
|
186
|
+
const gzipPercent = (gzipDiff / oldestResult.gzipSize * 100).toFixed(1);
|
|
187
|
+
const gzipTrend = gzipDiff >= 0 ? `+${formatBytes(gzipDiff)}` : `-${formatBytes(Math.abs(gzipDiff))}`;
|
|
188
|
+
lines.push(` ${blue("Gzip:")} ${gzipTrend} (${gzipDiff >= 0 ? "+" : ""}${gzipPercent}%)`);
|
|
189
|
+
}
|
|
140
190
|
lines.push(` ${blue("Raw:")} ${rawTrend} (${rawDiff >= 0 ? "+" : ""}${rawPercent}%)`);
|
|
141
191
|
}
|
|
142
192
|
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\tregistry?: string;\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\tregistry,\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\tregistry,\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","registry","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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"}
|
|
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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"}
|
package/dist/versions.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ export type FetchVersionsOptions = {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function fetchPackageVersions(packageNameOrOptions: string | FetchVersionsOptions): Promise<NpmPackageInfo>;
|
|
10
10
|
/**
|
|
11
|
-
* Prompt user to select a version from available versions
|
|
11
|
+
* Prompt user to select a version from available versions.
|
|
12
12
|
*/
|
|
13
13
|
export declare function promptForVersion(packageName: string, versions: string[], tags: Record<string, string>): Promise<string>;
|
package/dist/versions.js
CHANGED
|
@@ -3,16 +3,16 @@ import { rsort } from "semver";
|
|
|
3
3
|
import { parsePackageSpecifier } from "./bundler.js";
|
|
4
4
|
import { DEFAULT_REGISTRY } from "./defaults.js";
|
|
5
5
|
export async function fetchPackageVersions(packageNameOrOptions) {
|
|
6
|
-
// Support both string (legacy) and options object
|
|
6
|
+
// Support both string (legacy) and options object.
|
|
7
7
|
const { packageName, registry } = typeof packageNameOrOptions === "string" ? {
|
|
8
8
|
packageName: packageNameOrOptions,
|
|
9
9
|
registry: undefined
|
|
10
10
|
} : packageNameOrOptions;
|
|
11
|
-
// Parse the package specifier to get just the name (without version)
|
|
11
|
+
// Parse the package specifier to get just the name (without version).
|
|
12
12
|
const { name } = parsePackageSpecifier(packageName);
|
|
13
|
-
// Use custom registry or default
|
|
13
|
+
// Use custom registry or default.
|
|
14
14
|
const registryUrl = registry || DEFAULT_REGISTRY;
|
|
15
|
-
// Ensure no trailing slash
|
|
15
|
+
// Ensure no trailing slash.
|
|
16
16
|
const baseUrl = registryUrl.replace(/\/$/, "");
|
|
17
17
|
const url = `${baseUrl}/${name}`;
|
|
18
18
|
const response = await fetch(url);
|
|
@@ -20,7 +20,7 @@ export async function fetchPackageVersions(packageNameOrOptions) {
|
|
|
20
20
|
throw new Error(`Failed to fetch package info: ${response.statusText}`);
|
|
21
21
|
}
|
|
22
22
|
const data = await response.json();
|
|
23
|
-
// Get all versions sorted by semver (newest first)
|
|
23
|
+
// Get all versions sorted by semver (newest first).
|
|
24
24
|
const versions = rsort(Object.keys(data.versions || {}));
|
|
25
25
|
// Get dist-tags (latest, next, beta, etc.)
|
|
26
26
|
const tags = data["dist-tags"] || {};
|
|
@@ -30,23 +30,25 @@ export async function fetchPackageVersions(packageNameOrOptions) {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Prompt user to select a version from available versions
|
|
33
|
+
* Prompt user to select a version from available versions.
|
|
34
34
|
*/ export async function promptForVersion(packageName, versions, tags) {
|
|
35
|
-
// Build choices with tags highlighted
|
|
35
|
+
// Build choices with tags highlighted.
|
|
36
36
|
const taggedVersions = new Set(Object.values(tags));
|
|
37
37
|
const tagByVersion = Object.fromEntries(Object.entries(tags).map(([tag, ver])=>[
|
|
38
38
|
ver,
|
|
39
39
|
tag
|
|
40
40
|
]));
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Limit to most recent 20 versions for usability, but include all tagged
|
|
43
|
+
* versions.
|
|
44
|
+
*/ const recentVersions = versions.slice(0, 20);
|
|
43
45
|
const displayVersions = [
|
|
44
46
|
...new Set([
|
|
45
47
|
...Object.values(tags),
|
|
46
48
|
...recentVersions
|
|
47
49
|
])
|
|
48
50
|
];
|
|
49
|
-
// Sort so tagged versions appear first, then by version order
|
|
51
|
+
// Sort so tagged versions appear first, then by version order.
|
|
50
52
|
displayVersions.sort((a, b)=>{
|
|
51
53
|
const aTagged = taggedVersions.has(a);
|
|
52
54
|
const bTagged = taggedVersions.has(b);
|
package/dist/versions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/versions.ts"],"sourcesContent":["import select from \"@inquirer/select\";\nimport { rsort } from \"semver\";\nimport { parsePackageSpecifier } from \"./bundler.js\";\nimport { DEFAULT_REGISTRY } from \"./defaults.js\";\n\nexport type NpmPackageInfo = {\n\tversions: string[];\n\ttags: Record<string, string>;\n};\n\n/**\n * Fetch available versions for an npm package from the registry
|
|
1
|
+
{"version":3,"sources":["../src/versions.ts"],"sourcesContent":["import select from \"@inquirer/select\";\nimport { rsort } from \"semver\";\nimport { parsePackageSpecifier } from \"./bundler.js\";\nimport { DEFAULT_REGISTRY } from \"./defaults.js\";\n\nexport type NpmPackageInfo = {\n\tversions: string[];\n\ttags: Record<string, string>;\n};\n\n/**\n * Fetch available versions for an npm package from the registry.\n */\ntype NpmRegistryResponse = {\n\tversions?: Record<string, unknown>;\n\t\"dist-tags\"?: Record<string, string>;\n};\n\nexport type FetchVersionsOptions = {\n\tpackageName: string;\n\tregistry?: string;\n};\n\nexport async function fetchPackageVersions(\n\tpackageNameOrOptions: string | FetchVersionsOptions,\n): Promise<NpmPackageInfo> {\n\t// Support both string (legacy) and options object.\n\tconst { packageName, registry } =\n\t\ttypeof packageNameOrOptions === \"string\"\n\t\t\t? { packageName: packageNameOrOptions, registry: undefined }\n\t\t\t: packageNameOrOptions;\n\n\t// Parse the package specifier to get just the name (without version).\n\tconst { name } = parsePackageSpecifier(packageName);\n\n\t// Use custom registry or default.\n\tconst registryUrl = registry || DEFAULT_REGISTRY;\n\t// Ensure no trailing slash.\n\tconst baseUrl = registryUrl.replace(/\\/$/, \"\");\n\tconst url = `${baseUrl}/${name}`;\n\tconst response = await fetch(url);\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch package info: ${response.statusText}`);\n\t}\n\n\tconst data = (await response.json()) as NpmRegistryResponse;\n\n\t// Get all versions sorted by semver (newest first).\n\tconst versions = rsort(Object.keys(data.versions || {}));\n\n\t// Get dist-tags (latest, next, beta, etc.)\n\tconst tags = data[\"dist-tags\"] || {};\n\n\treturn { versions, tags };\n}\n\n/**\n * Prompt user to select a version from available versions.\n */\nexport async function promptForVersion(\n\tpackageName: string,\n\tversions: string[],\n\ttags: Record<string, string>,\n): Promise<string> {\n\t// Build choices with tags highlighted.\n\tconst taggedVersions = new Set(Object.values(tags));\n\tconst tagByVersion = Object.fromEntries(\n\t\tObject.entries(tags).map(([tag, ver]) => [ver, tag]),\n\t);\n\n\t/**\n\t * Limit to most recent 20 versions for usability, but include all tagged\n\t * versions.\n\t */\n\tconst recentVersions = versions.slice(0, 20);\n\tconst displayVersions = [\n\t\t...new Set([...Object.values(tags), ...recentVersions]),\n\t];\n\n\t// Sort so tagged versions appear first, then by version order.\n\tdisplayVersions.sort((a, b) => {\n\t\tconst aTagged = taggedVersions.has(a);\n\t\tconst bTagged = taggedVersions.has(b);\n\t\tif (aTagged && !bTagged) {\n\t\t\treturn -1;\n\t\t}\n\t\tif (!aTagged && bTagged) {\n\t\t\treturn 1;\n\t\t}\n\t\treturn versions.indexOf(a) - versions.indexOf(b);\n\t});\n\n\tconst choices = displayVersions.map((ver) => {\n\t\tconst tag = tagByVersion[ver];\n\t\treturn {\n\t\t\tname: tag ? `${ver} (${tag})` : ver,\n\t\t\tvalue: ver,\n\t\t};\n\t});\n\n\tconst selectedVersion = await select({\n\t\tmessage: `Select a version for ${packageName}:`,\n\t\tchoices,\n\t\tpageSize: 15,\n\t});\n\n\treturn selectedVersion;\n}\n"],"names":["select","rsort","parsePackageSpecifier","DEFAULT_REGISTRY","fetchPackageVersions","packageNameOrOptions","packageName","registry","undefined","name","registryUrl","baseUrl","replace","url","response","fetch","ok","Error","statusText","data","json","versions","Object","keys","tags","promptForVersion","taggedVersions","Set","values","tagByVersion","fromEntries","entries","map","tag","ver","recentVersions","slice","displayVersions","sort","a","b","aTagged","has","bTagged","indexOf","choices","value","selectedVersion","message","pageSize"],"mappings":"AAAA,OAAOA,YAAY,mBAAmB;AACtC,SAASC,KAAK,QAAQ,SAAS;AAC/B,SAASC,qBAAqB,QAAQ,eAAe;AACrD,SAASC,gBAAgB,QAAQ,gBAAgB;AAoBjD,OAAO,eAAeC,qBACrBC,oBAAmD;IAEnD,mDAAmD;IACnD,MAAM,EAAEC,WAAW,EAAEC,QAAQ,EAAE,GAC9B,OAAOF,yBAAyB,WAC7B;QAAEC,aAAaD;QAAsBE,UAAUC;IAAU,IACzDH;IAEJ,sEAAsE;IACtE,MAAM,EAAEI,IAAI,EAAE,GAAGP,sBAAsBI;IAEvC,kCAAkC;IAClC,MAAMI,cAAcH,YAAYJ;IAChC,4BAA4B;IAC5B,MAAMQ,UAAUD,YAAYE,OAAO,CAAC,OAAO;IAC3C,MAAMC,MAAM,GAAGF,QAAQ,CAAC,EAAEF,MAAM;IAChC,MAAMK,WAAW,MAAMC,MAAMF;IAE7B,IAAI,CAACC,SAASE,EAAE,EAAE;QACjB,MAAM,IAAIC,MAAM,CAAC,8BAA8B,EAAEH,SAASI,UAAU,EAAE;IACvE;IAEA,MAAMC,OAAQ,MAAML,SAASM,IAAI;IAEjC,oDAAoD;IACpD,MAAMC,WAAWpB,MAAMqB,OAAOC,IAAI,CAACJ,KAAKE,QAAQ,IAAI,CAAC;IAErD,2CAA2C;IAC3C,MAAMG,OAAOL,IAAI,CAAC,YAAY,IAAI,CAAC;IAEnC,OAAO;QAAEE;QAAUG;IAAK;AACzB;AAEA;;CAEC,GACD,OAAO,eAAeC,iBACrBnB,WAAmB,EACnBe,QAAkB,EAClBG,IAA4B;IAE5B,uCAAuC;IACvC,MAAME,iBAAiB,IAAIC,IAAIL,OAAOM,MAAM,CAACJ;IAC7C,MAAMK,eAAeP,OAAOQ,WAAW,CACtCR,OAAOS,OAAO,CAACP,MAAMQ,GAAG,CAAC,CAAC,CAACC,KAAKC,IAAI,GAAK;YAACA;YAAKD;SAAI;IAGpD;;;EAGC,GACD,MAAME,iBAAiBd,SAASe,KAAK,CAAC,GAAG;IACzC,MAAMC,kBAAkB;WACpB,IAAIV,IAAI;eAAIL,OAAOM,MAAM,CAACJ;eAAUW;SAAe;KACtD;IAED,+DAA+D;IAC/DE,gBAAgBC,IAAI,CAAC,CAACC,GAAGC;QACxB,MAAMC,UAAUf,eAAegB,GAAG,CAACH;QACnC,MAAMI,UAAUjB,eAAegB,GAAG,CAACF;QACnC,IAAIC,WAAW,CAACE,SAAS;YACxB,OAAO,CAAC;QACT;QACA,IAAI,CAACF,WAAWE,SAAS;YACxB,OAAO;QACR;QACA,OAAOtB,SAASuB,OAAO,CAACL,KAAKlB,SAASuB,OAAO,CAACJ;IAC/C;IAEA,MAAMK,UAAUR,gBAAgBL,GAAG,CAAC,CAACE;QACpC,MAAMD,MAAMJ,YAAY,CAACK,IAAI;QAC7B,OAAO;YACNzB,MAAMwB,MAAM,GAAGC,IAAI,EAAE,EAAED,IAAI,CAAC,CAAC,GAAGC;YAChCY,OAAOZ;QACR;IACD;IAEA,MAAMa,kBAAkB,MAAM/C,OAAO;QACpCgD,SAAS,CAAC,qBAAqB,EAAE1C,YAAY,CAAC,CAAC;QAC/CuC;QACAI,UAAU;IACX;IAEA,OAAOF;AACR"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@node-cli/bundlecheck",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.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)",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
|
+
"main": "./dist/index.js",
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/
|
|
13
|
+
"import": "./dist/index.js"
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
"bin": "dist/bundlecheck.js",
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
"@inquirer/select": "5.0.4",
|
|
37
38
|
"@node-cli/logger": "1.3.4",
|
|
38
39
|
"@node-cli/parser": "2.4.5",
|
|
40
|
+
"better-sqlite3": "12.6.2",
|
|
39
41
|
"esbuild": "0.27.2",
|
|
40
42
|
"kleur": "4.1.5",
|
|
41
43
|
"semver": "7.7.3"
|
|
@@ -45,8 +47,9 @@
|
|
|
45
47
|
},
|
|
46
48
|
"devDependencies": {
|
|
47
49
|
"@node-cli/comments": "0.2.9",
|
|
50
|
+
"@types/better-sqlite3": "7.6.13",
|
|
48
51
|
"@vitest/coverage-v8": "4.0.18",
|
|
49
52
|
"vitest": "4.0.18"
|
|
50
53
|
},
|
|
51
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "e6ab3435a49c7cd2a0ef27bd692e3de658a29ef4"
|
|
52
55
|
}
|