@node-cli/bundlecheck 1.3.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 +202 -0
- package/dist/bundlecheck.js +23 -21
- package/dist/bundlecheck.js.map +1 -1
- package/dist/bundler.d.ts +10 -6
- package/dist/bundler.js +92 -84
- package/dist/bundler.js.map +1 -1
- package/dist/cache.d.ts +18 -15
- package/dist/cache.js +39 -35
- package/dist/cache.js.map +1 -1
- package/dist/defaults.d.ts +2 -2
- package/dist/defaults.js +10 -10
- package/dist/defaults.js.map +1 -1
- package/dist/index.d.ts +1 -7
- package/dist/index.js +229 -0
- package/dist/index.js.map +1 -0
- package/dist/trend.d.ts +14 -8
- package/dist/trend.js +39 -33
- 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 +4 -3
package/dist/bundler.js
CHANGED
|
@@ -8,12 +8,12 @@ import * as esbuild from "esbuild";
|
|
|
8
8
|
import { DEFAULT_EXTERNALS } from "./defaults.js";
|
|
9
9
|
const gzipAsync = promisify(zlib.gzip);
|
|
10
10
|
/**
|
|
11
|
-
* Escape special regex characters in a string
|
|
11
|
+
* Escape special regex characters in a string.
|
|
12
12
|
*/ function escapeRegExp(str) {
|
|
13
13
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Parse a package specifier to extract name, version, and subpath
|
|
16
|
+
* Parse a package specifier to extract name, version, and subpath.
|
|
17
17
|
* Handles:
|
|
18
18
|
* - @scope/package@1.0.0
|
|
19
19
|
* - @scope/package/subpath@1.0.0
|
|
@@ -24,17 +24,18 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
24
24
|
let version = "latest";
|
|
25
25
|
// Handle scoped packages (@scope/name...)
|
|
26
26
|
if (workingSpec.startsWith("@")) {
|
|
27
|
-
// Find the second @ which would separate version
|
|
27
|
+
// Find the second @ which would separate version.
|
|
28
28
|
const secondAtIndex = workingSpec.indexOf("@", 1);
|
|
29
29
|
if (secondAtIndex !== -1) {
|
|
30
30
|
version = workingSpec.substring(secondAtIndex + 1);
|
|
31
31
|
workingSpec = workingSpec.substring(0, secondAtIndex);
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Now workingSpec is like @scope/name or @scope/name/subpath Split by / and
|
|
35
|
+
* check if there are more than 2 parts.
|
|
36
|
+
*/ const parts = workingSpec.split("/");
|
|
36
37
|
if (parts.length > 2) {
|
|
37
|
-
// Has subpath: @scope/name/subpath/more
|
|
38
|
+
// Has subpath: @scope/name/subpath/more.
|
|
38
39
|
const name = `${parts[0]}/${parts[1]}`;
|
|
39
40
|
const subpath = parts.slice(2).join("/");
|
|
40
41
|
return {
|
|
@@ -43,19 +44,19 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
43
44
|
subpath
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
|
-
// No subpath: @scope/name
|
|
47
|
+
// No subpath: @scope/name.
|
|
47
48
|
return {
|
|
48
49
|
name: workingSpec,
|
|
49
50
|
version
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
|
-
// Handle non-scoped packages (name@version or name/subpath@version)
|
|
53
|
+
// Handle non-scoped packages (name@version or name/subpath@version).
|
|
53
54
|
const atIndex = workingSpec.indexOf("@");
|
|
54
55
|
if (atIndex !== -1) {
|
|
55
56
|
version = workingSpec.substring(atIndex + 1);
|
|
56
57
|
workingSpec = workingSpec.substring(0, atIndex);
|
|
57
58
|
}
|
|
58
|
-
// Check for subpath in non-scoped packages
|
|
59
|
+
// Check for subpath in non-scoped packages.
|
|
59
60
|
const slashIndex = workingSpec.indexOf("/");
|
|
60
61
|
if (slashIndex !== -1) {
|
|
61
62
|
const name = workingSpec.substring(0, slashIndex);
|
|
@@ -72,7 +73,7 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
/**
|
|
75
|
-
* Format bytes to human-readable string
|
|
76
|
+
* Format bytes to human-readable string.
|
|
76
77
|
*/ export function formatBytes(bytes) {
|
|
77
78
|
if (bytes === 0) {
|
|
78
79
|
return "0 B";
|
|
@@ -88,7 +89,7 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
88
89
|
return `${Number.parseFloat((bytes / k ** i).toFixed(2))} ${sizes[i]}`;
|
|
89
90
|
}
|
|
90
91
|
/**
|
|
91
|
-
* Create a temporary directory for bundling
|
|
92
|
+
* Create a temporary directory for bundling.
|
|
92
93
|
*/ function createTempDir() {
|
|
93
94
|
const tmpDir = path.join(os.tmpdir(), `bundlecheck-${Date.now()}`);
|
|
94
95
|
fs.mkdirSync(tmpDir, {
|
|
@@ -97,7 +98,7 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
97
98
|
return tmpDir;
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
100
|
-
* Clean up temporary directory
|
|
101
|
+
* Clean up temporary directory.
|
|
101
102
|
*/ function cleanupTempDir(tmpDir) {
|
|
102
103
|
try {
|
|
103
104
|
fs.rmSync(tmpDir, {
|
|
@@ -105,11 +106,11 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
105
106
|
force: true
|
|
106
107
|
});
|
|
107
108
|
} catch {
|
|
108
|
-
// Ignore cleanup errors
|
|
109
|
+
// Ignore cleanup errors.
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
|
-
* Check if pnpm is available
|
|
113
|
+
* Check if pnpm is available.
|
|
113
114
|
*/ function isPnpmAvailable() {
|
|
114
115
|
try {
|
|
115
116
|
execSync("pnpm --version", {
|
|
@@ -120,30 +121,30 @@ const gzipAsync = promisify(zlib.gzip);
|
|
|
120
121
|
return false;
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
|
-
// Cache the result of pnpm availability check
|
|
124
|
+
// Cache the result of pnpm availability check.
|
|
124
125
|
let usePnpm = null;
|
|
125
126
|
/**
|
|
126
|
-
* Validate and sanitize a registry URL to prevent command injection
|
|
127
|
+
* Validate and sanitize a registry URL to prevent command injection.
|
|
127
128
|
* @param registry - The registry URL to validate
|
|
128
129
|
* @returns The sanitized URL or undefined if invalid
|
|
129
130
|
* @throws Error if the URL is invalid or contains potentially malicious characters
|
|
130
131
|
*/ function validateRegistryUrl(registry) {
|
|
131
|
-
// Parse as URL to validate format
|
|
132
|
+
// Parse as URL to validate format.
|
|
132
133
|
let url;
|
|
133
134
|
try {
|
|
134
135
|
url = new URL(registry);
|
|
135
136
|
} catch {
|
|
136
137
|
throw new Error(`Invalid registry URL: ${registry}. Must be a valid URL (e.g., https://registry.example.com)`);
|
|
137
138
|
}
|
|
138
|
-
// Only allow http and https protocols
|
|
139
|
+
// Only allow http and https protocols.
|
|
139
140
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
140
141
|
throw new Error(`Invalid registry URL protocol: ${url.protocol}. Only http: and https: are allowed`);
|
|
141
142
|
}
|
|
142
|
-
// Return the sanitized URL (URL constructor normalizes it)
|
|
143
|
+
// Return the sanitized URL (URL constructor normalizes it).
|
|
143
144
|
return url.toString();
|
|
144
145
|
}
|
|
145
146
|
/**
|
|
146
|
-
* Get the install command (pnpm preferred, npm fallback)
|
|
147
|
+
* Get the install command (pnpm preferred, npm fallback).
|
|
147
148
|
* @param registry - Optional custom npm registry URL
|
|
148
149
|
*/ function getInstallCommand(registry) {
|
|
149
150
|
if (usePnpm === null) {
|
|
@@ -151,9 +152,9 @@ let usePnpm = null;
|
|
|
151
152
|
}
|
|
152
153
|
let registryArg = "";
|
|
153
154
|
if (registry) {
|
|
154
|
-
// Validate and sanitize the registry URL to prevent command injection
|
|
155
|
+
// Validate and sanitize the registry URL to prevent command injection.
|
|
155
156
|
const sanitizedRegistry = validateRegistryUrl(registry);
|
|
156
|
-
// Quote the URL to handle any special characters safely
|
|
157
|
+
// Quote the URL to handle any special characters safely.
|
|
157
158
|
registryArg = ` --registry "${sanitizedRegistry}"`;
|
|
158
159
|
}
|
|
159
160
|
if (usePnpm) {
|
|
@@ -162,19 +163,19 @@ let usePnpm = null;
|
|
|
162
163
|
return `npm install --legacy-peer-deps --ignore-scripts${registryArg}`;
|
|
163
164
|
}
|
|
164
165
|
/**
|
|
165
|
-
* Generate the entry file content based on package, subpath, and exports
|
|
166
|
+
* Generate the entry file content based on package, subpath, and exports.
|
|
166
167
|
*/ function generateEntryContent(options) {
|
|
167
168
|
const { packageName, subpath, exports, allSubpaths, exportToSubpath } = options;
|
|
168
|
-
// If we have exports mapped to different subpaths
|
|
169
|
+
// If we have exports mapped to different subpaths.
|
|
169
170
|
if (exportToSubpath && exportToSubpath.size > 0) {
|
|
170
|
-
// Group exports by subpath
|
|
171
|
+
// Group exports by subpath.
|
|
171
172
|
const subpathToExports = new Map();
|
|
172
173
|
for (const [exportName, sp] of exportToSubpath){
|
|
173
174
|
const existing = subpathToExports.get(sp) || [];
|
|
174
175
|
existing.push(exportName);
|
|
175
176
|
subpathToExports.set(sp, existing);
|
|
176
177
|
}
|
|
177
|
-
// Generate imports for each subpath
|
|
178
|
+
// Generate imports for each subpath.
|
|
178
179
|
const lines = [];
|
|
179
180
|
const allExportNames = [];
|
|
180
181
|
for (const [sp, exportNames] of subpathToExports){
|
|
@@ -186,43 +187,43 @@ let usePnpm = null;
|
|
|
186
187
|
lines.push(`export { ${allExportNames.join(", ")} };`);
|
|
187
188
|
return lines.join("\n") + "\n";
|
|
188
189
|
}
|
|
189
|
-
// If we have specific exports to import
|
|
190
|
+
// If we have specific exports to import.
|
|
190
191
|
if (exports && exports.length > 0) {
|
|
191
|
-
// Determine the import path
|
|
192
|
+
// Determine the import path.
|
|
192
193
|
const importPath = subpath ? `${packageName}/${subpath}` : packageName;
|
|
193
194
|
const importNames = exports.join(", ");
|
|
194
195
|
return `import { ${importNames} } from "${importPath}";\nexport { ${importNames} };\n`;
|
|
195
196
|
}
|
|
196
|
-
// If we have a specific subpath (but no specific exports)
|
|
197
|
+
// If we have a specific subpath (but no specific exports).
|
|
197
198
|
if (subpath) {
|
|
198
199
|
const importPath = `${packageName}/${subpath}`;
|
|
199
200
|
return `import * as pkg from "${importPath}";\nexport default pkg;\n`;
|
|
200
201
|
}
|
|
201
|
-
// If package has subpath exports only (no main entry), import all subpaths
|
|
202
|
+
// If package has subpath exports only (no main entry), import all subpaths.
|
|
202
203
|
if (allSubpaths && allSubpaths.length > 0) {
|
|
203
204
|
const imports = allSubpaths.map((sp, i)=>`import * as sub${i} from "${packageName}/${sp}";\nexport { sub${i} };`).join("\n");
|
|
204
205
|
return imports + "\n";
|
|
205
206
|
}
|
|
206
|
-
// Default: import everything from main entry
|
|
207
|
+
// Default: import everything from main entry.
|
|
207
208
|
return `import * as pkg from "${packageName}";\nexport default pkg;\n`;
|
|
208
209
|
}
|
|
209
210
|
/**
|
|
210
|
-
* Get externals list based on options
|
|
211
|
+
* Get externals list based on options.
|
|
211
212
|
*/ export function getExternals(packageName, externals, noExternal) {
|
|
212
213
|
if (noExternal) {
|
|
213
214
|
return [];
|
|
214
215
|
}
|
|
215
|
-
// Start with default externals (react, react-dom)
|
|
216
|
+
// Start with default externals (react, react-dom).
|
|
216
217
|
let result = [
|
|
217
218
|
...DEFAULT_EXTERNALS
|
|
218
219
|
];
|
|
219
|
-
// If checking react or react-dom themselves, don't mark them as external
|
|
220
|
+
// If checking react or react-dom themselves, don't mark them as external.
|
|
220
221
|
if (packageName === "react") {
|
|
221
222
|
result = result.filter((e)=>e !== "react");
|
|
222
223
|
} else if (packageName === "react-dom") {
|
|
223
224
|
result = result.filter((e)=>e !== "react-dom");
|
|
224
225
|
}
|
|
225
|
-
// Add any additional externals
|
|
226
|
+
// Add any additional externals.
|
|
226
227
|
if (externals && externals.length > 0) {
|
|
227
228
|
result = [
|
|
228
229
|
...new Set([
|
|
@@ -234,14 +235,15 @@ let usePnpm = null;
|
|
|
234
235
|
return result;
|
|
235
236
|
}
|
|
236
237
|
/**
|
|
237
|
-
* Get version, dependencies, peer dependencies, and exports from an installed
|
|
238
|
+
* Get version, dependencies, peer dependencies, and exports from an installed
|
|
239
|
+
* package.
|
|
238
240
|
*/ function getPackageInfo(tmpDir, packageName) {
|
|
239
241
|
try {
|
|
240
|
-
// Handle scoped packages - the package name in node_modules
|
|
242
|
+
// Handle scoped packages - the package name in node_modules.
|
|
241
243
|
const pkgJsonPath = path.join(tmpDir, "node_modules", packageName, "package.json");
|
|
242
244
|
if (fs.existsSync(pkgJsonPath)) {
|
|
243
245
|
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
|
|
244
|
-
// Check if package has a main entry point
|
|
246
|
+
// Check if package has a main entry point.
|
|
245
247
|
const hasMainEntry = Boolean(pkgJson.main || pkgJson.module || pkgJson.exports?.["."] || pkgJson.exports?.["./index"] || !pkgJson.exports && !pkgJson.main && !pkgJson.module);
|
|
246
248
|
return {
|
|
247
249
|
version: pkgJson.version || "unknown",
|
|
@@ -253,7 +255,7 @@ let usePnpm = null;
|
|
|
253
255
|
};
|
|
254
256
|
}
|
|
255
257
|
} catch {
|
|
256
|
-
// Ignore errors reading package info
|
|
258
|
+
// Ignore errors reading package info.
|
|
257
259
|
}
|
|
258
260
|
return {
|
|
259
261
|
version: "unknown",
|
|
@@ -265,19 +267,19 @@ let usePnpm = null;
|
|
|
265
267
|
};
|
|
266
268
|
}
|
|
267
269
|
/**
|
|
268
|
-
* Extract subpath export names from package exports field
|
|
269
|
-
*
|
|
270
|
+
* Extract subpath export names from package exports field Returns array of
|
|
271
|
+
* subpaths like ["header", "body", "datagrid"].
|
|
270
272
|
*/ function getSubpathExports(exports) {
|
|
271
273
|
if (!exports) {
|
|
272
274
|
return [];
|
|
273
275
|
}
|
|
274
276
|
const subpaths = [];
|
|
275
277
|
for (const key of Object.keys(exports)){
|
|
276
|
-
// Skip the main entry point and package.json
|
|
278
|
+
// Skip the main entry point and package.json.
|
|
277
279
|
if (key === "." || key === "./package.json") {
|
|
278
280
|
continue;
|
|
279
281
|
}
|
|
280
|
-
// Remove leading "./" to get subpath name
|
|
282
|
+
// Remove leading "./" to get subpath name.
|
|
281
283
|
if (key.startsWith("./")) {
|
|
282
284
|
subpaths.push(key.substring(2));
|
|
283
285
|
}
|
|
@@ -285,20 +287,20 @@ let usePnpm = null;
|
|
|
285
287
|
return subpaths;
|
|
286
288
|
}
|
|
287
289
|
/**
|
|
288
|
-
* Find which subpath(s) export the given component names
|
|
289
|
-
*
|
|
290
|
+
* Find which subpath(s) export the given component names Reads type definition
|
|
291
|
+
* files or JS files to find the exports.
|
|
290
292
|
*/ function findSubpathsForExports(tmpDir, packageName, exports, componentNames) {
|
|
291
293
|
const packageDir = path.join(tmpDir, "node_modules", packageName);
|
|
292
294
|
const exportToSubpath = new Map();
|
|
293
295
|
for (const [subpathKey, subpathValue] of Object.entries(exports)){
|
|
294
|
-
// Skip main entry and package.json
|
|
296
|
+
// Skip main entry and package.json.
|
|
295
297
|
if (subpathKey === "." || subpathKey === "./package.json") {
|
|
296
298
|
continue;
|
|
297
299
|
}
|
|
298
|
-
// Get the types or import path
|
|
300
|
+
// Get the types or import path.
|
|
299
301
|
let filePath;
|
|
300
302
|
if (typeof subpathValue === "object" && subpathValue !== null) {
|
|
301
|
-
// Prefer types file for more accurate export detection
|
|
303
|
+
// Prefer types file for more accurate export detection.
|
|
302
304
|
filePath = subpathValue.types || subpathValue.import;
|
|
303
305
|
} else if (typeof subpathValue === "string") {
|
|
304
306
|
filePath = subpathValue;
|
|
@@ -306,21 +308,21 @@ let usePnpm = null;
|
|
|
306
308
|
if (!filePath) {
|
|
307
309
|
continue;
|
|
308
310
|
}
|
|
309
|
-
// Resolve the file path
|
|
311
|
+
// Resolve the file path.
|
|
310
312
|
const fullPath = path.join(packageDir, filePath);
|
|
311
313
|
try {
|
|
312
314
|
if (fs.existsSync(fullPath)) {
|
|
313
315
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
314
316
|
const subpath = subpathKey.startsWith("./") ? subpathKey.substring(2) : subpathKey;
|
|
315
|
-
// Check each component name
|
|
317
|
+
// Check each component name.
|
|
316
318
|
for (const name of componentNames){
|
|
317
|
-
// Skip if already found
|
|
319
|
+
// Skip if already found.
|
|
318
320
|
if (exportToSubpath.has(name)) {
|
|
319
321
|
continue;
|
|
320
322
|
}
|
|
321
|
-
// Escape regex special characters in the name to prevent injection
|
|
323
|
+
// Escape regex special characters in the name to prevent injection.
|
|
322
324
|
const escapedName = escapeRegExp(name);
|
|
323
|
-
// Look for various export patterns
|
|
325
|
+
// Look for various export patterns.
|
|
324
326
|
const patterns = [
|
|
325
327
|
new RegExp(`export\\s*\\{[^}]*\\b${escapedName}\\b[^}]*\\}`, "m"),
|
|
326
328
|
new RegExp(`export\\s+declare\\s+(?:const|function|class)\\s+${escapedName}\\b`, "m"),
|
|
@@ -332,14 +334,14 @@ let usePnpm = null;
|
|
|
332
334
|
}
|
|
333
335
|
}
|
|
334
336
|
} catch {
|
|
335
|
-
// Ignore read errors, continue to next subpath
|
|
337
|
+
// Ignore read errors, continue to next subpath.
|
|
336
338
|
}
|
|
337
339
|
}
|
|
338
|
-
// Check if all exports were found
|
|
340
|
+
// Check if all exports were found.
|
|
339
341
|
if (exportToSubpath.size !== componentNames.length) {
|
|
340
342
|
return {}; // Not all exports found
|
|
341
343
|
}
|
|
342
|
-
// Check if all exports are from the same subpath
|
|
344
|
+
// Check if all exports are from the same subpath.
|
|
343
345
|
const subpaths = new Set(exportToSubpath.values());
|
|
344
346
|
if (subpaths.size === 1) {
|
|
345
347
|
return {
|
|
@@ -348,20 +350,20 @@ let usePnpm = null;
|
|
|
348
350
|
][0]
|
|
349
351
|
};
|
|
350
352
|
}
|
|
351
|
-
// Multiple subpaths needed
|
|
353
|
+
// Multiple subpaths needed.
|
|
352
354
|
return {
|
|
353
355
|
exportToSubpath
|
|
354
356
|
};
|
|
355
357
|
}
|
|
356
358
|
/**
|
|
357
|
-
* Check the bundle size of an npm package
|
|
359
|
+
* Check the bundle size of an npm package.
|
|
358
360
|
*/ export async function checkBundleSize(options) {
|
|
359
361
|
const { packageName: packageSpecifier, exports, additionalExternals, noExternal, gzipLevel = 5, registry, platform: explicitPlatform } = options;
|
|
360
|
-
// Parse the package specifier to extract name, version, and subpath
|
|
362
|
+
// Parse the package specifier to extract name, version, and subpath.
|
|
361
363
|
const { name: packageName, version: requestedVersion, subpath } = parsePackageSpecifier(packageSpecifier);
|
|
362
364
|
const tmpDir = createTempDir();
|
|
363
365
|
try {
|
|
364
|
-
// Create initial package.json
|
|
366
|
+
// Create initial package.json.
|
|
365
367
|
const packageJson = {
|
|
366
368
|
name: "bundlecheck-temp",
|
|
367
369
|
version: "1.0.0",
|
|
@@ -371,24 +373,28 @@ let usePnpm = null;
|
|
|
371
373
|
}
|
|
372
374
|
};
|
|
373
375
|
fs.writeFileSync(path.join(tmpDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
374
|
-
// Install the main package (try pnpm first, fallback to npm)
|
|
376
|
+
// Install the main package (try pnpm first, fallback to npm).
|
|
375
377
|
const installCmd = getInstallCommand(registry);
|
|
376
378
|
execSync(installCmd, {
|
|
377
379
|
cwd: tmpDir,
|
|
378
380
|
stdio: "pipe"
|
|
379
381
|
});
|
|
380
|
-
|
|
381
|
-
|
|
382
|
+
/**
|
|
383
|
+
* Get package info (version, dependencies, peer dependencies, exports,
|
|
384
|
+
* engines).
|
|
385
|
+
*/ const pkgInfo = getPackageInfo(tmpDir, packageName);
|
|
382
386
|
const peerDepKeys = Object.keys(pkgInfo.peerDependencies);
|
|
383
|
-
|
|
384
|
-
|
|
387
|
+
/**
|
|
388
|
+
* Determine platform: use explicit value if provided, otherwise auto-detect
|
|
389
|
+
* from engines.
|
|
390
|
+
*/ let platform = "browser";
|
|
385
391
|
if (explicitPlatform) {
|
|
386
392
|
platform = explicitPlatform;
|
|
387
393
|
} else if (pkgInfo.engines?.node && !pkgInfo.engines?.browser) {
|
|
388
|
-
// Package specifies node engine without browser - likely a Node.js package
|
|
394
|
+
// Package specifies node engine without browser - likely a Node.js package.
|
|
389
395
|
platform = "node";
|
|
390
396
|
}
|
|
391
|
-
// Collect all dependency names (prod + peer)
|
|
397
|
+
// Collect all dependency names (prod + peer).
|
|
392
398
|
const allDependencies = [
|
|
393
399
|
...new Set([
|
|
394
400
|
...Object.keys(pkgInfo.dependencies),
|
|
@@ -396,40 +402,42 @@ let usePnpm = null;
|
|
|
396
402
|
])
|
|
397
403
|
].sort();
|
|
398
404
|
if (peerDepKeys.length > 0) {
|
|
399
|
-
// Add peer dependencies to package.json
|
|
405
|
+
// Add peer dependencies to package.json.
|
|
400
406
|
for (const dep of peerDepKeys){
|
|
401
|
-
// Use the version range from peer dependencies
|
|
407
|
+
// Use the version range from peer dependencies.
|
|
402
408
|
packageJson.dependencies[dep] = pkgInfo.peerDependencies[dep];
|
|
403
409
|
}
|
|
404
|
-
// Update package.json and reinstall
|
|
410
|
+
// Update package.json and reinstall.
|
|
405
411
|
fs.writeFileSync(path.join(tmpDir, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
406
412
|
execSync(installCmd, {
|
|
407
413
|
cwd: tmpDir,
|
|
408
414
|
stdio: "pipe"
|
|
409
415
|
});
|
|
410
416
|
}
|
|
411
|
-
|
|
412
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Determine if we need to use all subpath exports or find the right
|
|
419
|
+
* subpath(s).
|
|
420
|
+
*/ let allSubpaths;
|
|
413
421
|
let resolvedSubpath = subpath;
|
|
414
422
|
let exportToSubpath;
|
|
415
423
|
if (!subpath && !pkgInfo.hasMainEntry && pkgInfo.exports) {
|
|
416
424
|
if (exports && exports.length > 0) {
|
|
417
|
-
// User specified exports but no subpath - try to find the right subpath(s)
|
|
425
|
+
// User specified exports but no subpath - try to find the right subpath(s).
|
|
418
426
|
const mapping = findSubpathsForExports(tmpDir, packageName, pkgInfo.exports, exports);
|
|
419
427
|
if (mapping.singleSubpath) {
|
|
420
|
-
// All exports from the same subpath
|
|
428
|
+
// All exports from the same subpath.
|
|
421
429
|
resolvedSubpath = mapping.singleSubpath;
|
|
422
430
|
} else if (mapping.exportToSubpath) {
|
|
423
|
-
// Exports from multiple subpaths
|
|
431
|
+
// Exports from multiple subpaths.
|
|
424
432
|
exportToSubpath = mapping.exportToSubpath;
|
|
425
433
|
}
|
|
426
434
|
}
|
|
427
|
-
// If still no subpath resolved and no mapping, bundle all subpaths
|
|
435
|
+
// If still no subpath resolved and no mapping, bundle all subpaths.
|
|
428
436
|
if (!resolvedSubpath && !exportToSubpath) {
|
|
429
437
|
allSubpaths = getSubpathExports(pkgInfo.exports);
|
|
430
438
|
}
|
|
431
439
|
}
|
|
432
|
-
// Create entry file with appropriate content
|
|
440
|
+
// Create entry file with appropriate content.
|
|
433
441
|
const entryContent = generateEntryContent({
|
|
434
442
|
packageName,
|
|
435
443
|
subpath: resolvedSubpath,
|
|
@@ -439,9 +447,9 @@ let usePnpm = null;
|
|
|
439
447
|
});
|
|
440
448
|
const entryFile = path.join(tmpDir, "entry.js");
|
|
441
449
|
fs.writeFileSync(entryFile, entryContent);
|
|
442
|
-
// Get externals
|
|
450
|
+
// Get externals.
|
|
443
451
|
const externals = getExternals(packageName, additionalExternals, noExternal);
|
|
444
|
-
// Bundle with esbuild
|
|
452
|
+
// Bundle with esbuild.
|
|
445
453
|
const result = await esbuild.build({
|
|
446
454
|
entryPoints: [
|
|
447
455
|
entryFile
|
|
@@ -456,10 +464,10 @@ let usePnpm = null;
|
|
|
456
464
|
external: externals,
|
|
457
465
|
metafile: true
|
|
458
466
|
});
|
|
459
|
-
// Get raw size
|
|
467
|
+
// Get raw size.
|
|
460
468
|
const bundleContent = result.outputFiles[0].contents;
|
|
461
469
|
const rawSize = bundleContent.length;
|
|
462
|
-
// Gzip the bundle (only for browser platform - not relevant for Node.js)
|
|
470
|
+
// Gzip the bundle (only for browser platform - not relevant for Node.js).
|
|
463
471
|
let gzipSize = null;
|
|
464
472
|
if (platform === "browser") {
|
|
465
473
|
const gzipped = await gzipAsync(Buffer.from(bundleContent), {
|
|
@@ -467,12 +475,12 @@ let usePnpm = null;
|
|
|
467
475
|
});
|
|
468
476
|
gzipSize = gzipped.length;
|
|
469
477
|
}
|
|
470
|
-
// Determine the display name
|
|
478
|
+
// Determine the display name.
|
|
471
479
|
let displayName = packageName;
|
|
472
480
|
if (resolvedSubpath) {
|
|
473
481
|
displayName = `${packageName}/${resolvedSubpath}`;
|
|
474
482
|
} else if (exportToSubpath && exportToSubpath.size > 0) {
|
|
475
|
-
// Multiple subpaths - show them all
|
|
483
|
+
// Multiple subpaths - show them all.
|
|
476
484
|
const uniqueSubpaths = [
|
|
477
485
|
...new Set(exportToSubpath.values())
|
|
478
486
|
].sort();
|