@bobfrankston/npmglobalize 1.0.152 → 1.0.153
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 +5 -0
- package/lib.js +40 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -350,6 +350,11 @@ Workspace mode is auto-detected when run from a root with `"private": true` and
|
|
|
350
350
|
-asis Skip ignore file checks (or set "asis": true in .globalize.json5)
|
|
351
351
|
-fix-tags Automatically fix version/tag mismatches
|
|
352
352
|
-rebase Automatically rebase if local is behind remote
|
|
353
|
+
-clean-nested-modules, -clean-nested
|
|
354
|
+
Before npm pack, wipe node_modules/ inside each file: dep
|
|
355
|
+
target. Fixes arborist "Cannot read properties of null"
|
|
356
|
+
crashes caused by sibling file: deps with nested
|
|
357
|
+
node_modules. Suggested automatically when the error hits.
|
|
353
358
|
-show Show package.json dependency changes
|
|
354
359
|
-package, -pkg Update package.json scripts to use npmglobalize (see below)
|
|
355
360
|
-h, -help Show help
|
package/lib.js
CHANGED
|
@@ -1262,12 +1262,10 @@ function waitForNpmVersion(pkgName, version, maxWaitMs = 90000) {
|
|
|
1262
1262
|
process.stdout.write(' timed out\n');
|
|
1263
1263
|
return false;
|
|
1264
1264
|
}
|
|
1265
|
-
/** Delete `node_modules/` inside each `file:` dep target.
|
|
1266
|
-
* Works around arborist crashes during `npm pack` when sibling `file:` deps
|
|
1267
|
-
* have their own populated `node_modules/`. Returns the names of cleaned deps. */
|
|
1268
1265
|
function cleanNestedDepModules(pkg, cwd, verbose) {
|
|
1269
|
-
const
|
|
1266
|
+
const stashed = [];
|
|
1270
1267
|
const seen = new Set();
|
|
1268
|
+
const suffix = `.npmglobalize-stash-${process.pid}`;
|
|
1271
1269
|
for (const key of ['.dependencies', '.devDependencies', 'dependencies', 'devDependencies']) {
|
|
1272
1270
|
const deps = pkg?.[key];
|
|
1273
1271
|
if (!deps || typeof deps !== 'object')
|
|
@@ -1282,18 +1280,40 @@ function cleanNestedDepModules(pkg, cwd, verbose) {
|
|
|
1282
1280
|
if (!fs.existsSync(nm))
|
|
1283
1281
|
continue;
|
|
1284
1282
|
seen.add(name);
|
|
1283
|
+
const backup = nm + suffix;
|
|
1285
1284
|
try {
|
|
1286
|
-
fs.
|
|
1287
|
-
|
|
1285
|
+
if (fs.existsSync(backup))
|
|
1286
|
+
fs.rmSync(backup, { recursive: true, force: true });
|
|
1287
|
+
fs.renameSync(nm, backup);
|
|
1288
|
+
stashed.push({ name, nm, backup });
|
|
1288
1289
|
if (verbose)
|
|
1289
|
-
console.log(colors.dim(`
|
|
1290
|
+
console.log(colors.dim(` stashed ${nm} -> ${path.basename(backup)}`));
|
|
1290
1291
|
}
|
|
1291
1292
|
catch (e) {
|
|
1292
|
-
console.error(colors.yellow(` warning: could not
|
|
1293
|
+
console.error(colors.yellow(` warning: could not stash ${nm}: ${e.message}`));
|
|
1293
1294
|
}
|
|
1294
1295
|
}
|
|
1295
1296
|
}
|
|
1296
|
-
return
|
|
1297
|
+
return stashed;
|
|
1298
|
+
}
|
|
1299
|
+
/** Restore `node_modules/` previously moved aside by `cleanNestedDepModules`.
|
|
1300
|
+
* Safe to call multiple times; missing backups are skipped. */
|
|
1301
|
+
function restoreNestedDepModules(stashed, verbose) {
|
|
1302
|
+
for (const s of stashed) {
|
|
1303
|
+
try {
|
|
1304
|
+
if (!fs.existsSync(s.backup))
|
|
1305
|
+
continue;
|
|
1306
|
+
if (fs.existsSync(s.nm))
|
|
1307
|
+
fs.rmSync(s.nm, { recursive: true, force: true });
|
|
1308
|
+
fs.renameSync(s.backup, s.nm);
|
|
1309
|
+
if (verbose)
|
|
1310
|
+
console.log(colors.dim(` restored ${s.nm}`));
|
|
1311
|
+
}
|
|
1312
|
+
catch (e) {
|
|
1313
|
+
console.error(colors.yellow(` warning: could not restore ${s.nm}: ${e.message}`));
|
|
1314
|
+
console.error(colors.yellow(` backup remains at ${s.backup} — restore manually`));
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1297
1317
|
}
|
|
1298
1318
|
/** Run npm install -g with retries for registry propagation delay */
|
|
1299
1319
|
function installGlobalWithRetry(pkgSpec, cwd, maxRetries = 3) {
|
|
@@ -4270,11 +4290,14 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4270
4290
|
if (verbose) {
|
|
4271
4291
|
console.log(colors.green(`✓ Authenticated as ${authStatus.username}`));
|
|
4272
4292
|
}
|
|
4273
|
-
// Optionally
|
|
4293
|
+
// Optionally stash nested node_modules in file: dep targets before pack
|
|
4294
|
+
// (arborist crashes when sibling file: deps have populated node_modules).
|
|
4295
|
+
// Restored immediately after pack so symlinked file: deps stay runnable.
|
|
4296
|
+
let stashedDepModules = [];
|
|
4274
4297
|
if (options.cleanNestedModules) {
|
|
4275
|
-
|
|
4276
|
-
if (
|
|
4277
|
-
console.log(colors.yellow(` Cleaned node_modules in ${
|
|
4298
|
+
stashedDepModules = cleanNestedDepModules(pkg, cwd, verbose);
|
|
4299
|
+
if (stashedDepModules.length > 0) {
|
|
4300
|
+
console.log(colors.yellow(` Cleaned node_modules in ${stashedDepModules.length} file: dep target(s): ${stashedDepModules.map(s => s.name).join(', ')}`));
|
|
4278
4301
|
}
|
|
4279
4302
|
else if (verbose) {
|
|
4280
4303
|
console.log(colors.dim(' --clean-nested-modules: nothing to clean'));
|
|
@@ -4282,6 +4305,10 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4282
4305
|
}
|
|
4283
4306
|
// Create tarball first
|
|
4284
4307
|
const packResult = runCommand('npm', ['pack'], { cwd, silent: true });
|
|
4308
|
+
// Restore stashed node_modules now that pack is done — must happen
|
|
4309
|
+
// before any subsequent install -g symlinks to these dep targets.
|
|
4310
|
+
if (stashedDepModules.length > 0)
|
|
4311
|
+
restoreNestedDepModules(stashedDepModules, verbose);
|
|
4285
4312
|
if (!packResult.success) {
|
|
4286
4313
|
const d = diagnoseNpmPackFailure(cwd, packResult.output, packResult.stderr, pkg);
|
|
4287
4314
|
console.error(colors.red(`ERROR: ${d.summary}`));
|