@bobfrankston/npmglobalize 1.0.118 → 1.0.119

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.
Files changed (2) hide show
  1. package/lib.js +72 -50
  2. package/package.json +1 -1
package/lib.js CHANGED
@@ -1015,6 +1015,21 @@ export function runCommand(cmd, args, options = {}) {
1015
1015
  return { success: false, output: '', stderr: error.message };
1016
1016
  }
1017
1017
  }
1018
+ /** Run git commit silently and print a compact summary (no per-file create/delete mode lines). */
1019
+ function gitCommit(msg, cwd) {
1020
+ const result = runCommand('git', ['commit', '-m', msg], { cwd, silent: true });
1021
+ if (result.success) {
1022
+ // Print the summary lines, skip "create mode" / "delete mode" / "rename" noise
1023
+ const lines = result.output.split('\n');
1024
+ for (const line of lines) {
1025
+ const trimmed = line.trim();
1026
+ if (trimmed && !/^ *(create|delete|rename) mode /.test(trimmed)) {
1027
+ console.log(trimmed);
1028
+ }
1029
+ }
1030
+ }
1031
+ return result;
1032
+ }
1018
1033
  /** Extract GitHub repo identifier from repository field */
1019
1034
  function getGitHubRepo(pkg) {
1020
1035
  if (!pkg.repository)
@@ -3014,7 +3029,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3014
3029
  if (!dryRun) {
3015
3030
  writePackageJson(cwd, finalPkg);
3016
3031
  runCommand('git', ['add', 'package.json'], { cwd });
3017
- runCommand('git', ['commit', '-m', 'Restore file: dependencies'], { cwd });
3032
+ gitCommit('Restore file: dependencies', cwd);
3018
3033
  if (currentGitStatus.hasRemote) {
3019
3034
  pushWithProtection(cwd, verbose);
3020
3035
  }
@@ -3042,7 +3057,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3042
3057
  if (!dryRun) {
3043
3058
  writePackageJson(cwd, finalPkg);
3044
3059
  runCommand('git', ['add', 'package.json'], { cwd });
3045
- runCommand('git', ['commit', '-m', 'Restore file: dependencies'], { cwd });
3060
+ gitCommit('Restore file: dependencies', cwd);
3046
3061
  if (currentGitStatus.hasRemote) {
3047
3062
  pushWithProtection(cwd, verbose);
3048
3063
  }
@@ -3228,16 +3243,14 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3228
3243
  console.log(colors.yellow('Continuing with --force...'));
3229
3244
  }
3230
3245
  }
3231
- let commitResult = runCommand('git', ['commit', '-m', commitMsg], { cwd });
3246
+ let commitResult = gitCommit(commitMsg, cwd);
3232
3247
  if (!commitResult.success) {
3233
3248
  // Check for corrupted git index ("invalid object" / "Error building trees")
3234
- // Run silently to capture stderr for detection
3235
- const probe = runCommand('git', ['commit', '-m', commitMsg], { cwd, silent: true });
3236
- const errText = probe.stderr + probe.output;
3249
+ const errText = commitResult.stderr + commitResult.output;
3237
3250
  if (errText.includes('invalid object') || errText.includes('Error building trees')) {
3238
3251
  if (repairGitIndex(cwd)) {
3239
3252
  // Retry commit after repair
3240
- commitResult = runCommand('git', ['commit', '-m', commitMsg], { cwd });
3253
+ commitResult = gitCommit(commitMsg, cwd);
3241
3254
  }
3242
3255
  }
3243
3256
  if (!commitResult.success) {
@@ -3792,7 +3805,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3792
3805
  writePackageJson(cwd, finalPkg);
3793
3806
  // Commit the restore
3794
3807
  runCommand('git', ['add', 'package.json'], { cwd });
3795
- runCommand('git', ['commit', '-m', 'Restore file: dependencies'], { cwd });
3808
+ gitCommit('Restore file: dependencies', cwd);
3796
3809
  if (currentGitStatus.hasRemote) {
3797
3810
  pushWithProtection(cwd, verbose);
3798
3811
  }
@@ -3866,49 +3879,7 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
3866
3879
  console.log(`Packages (${packages.length}): ${packages.map(p => p.name).join(', ')}`);
3867
3880
  console.log(`Publish order: ${publishOrder.join(' → ')}`);
3868
3881
  console.log('');
3869
- // Check that workspace packages' deps are hoisted to root (needed for global install)
3870
3882
  const rootPkg = readPackageJson(rootDir);
3871
- if (rootPkg.bin) {
3872
- const wsNames = new Set(packages.map(p => p.name));
3873
- const rootDeps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
3874
- const missing = [];
3875
- for (const pkgInfo of packages) {
3876
- const deps = pkgInfo.pkg.dependencies || {};
3877
- for (const [dep, ver] of Object.entries(deps)) {
3878
- if (wsNames.has(dep))
3879
- continue; // sibling workspace package — bundled
3880
- if (dep in rootDeps)
3881
- continue; // already in root
3882
- if (missing.some(m => m.dep === dep))
3883
- continue; // already flagged
3884
- missing.push({ dep, version: ver, from: pkgInfo.name });
3885
- }
3886
- }
3887
- if (missing.length > 0) {
3888
- console.log(colors.yellow('⚠ Workspace packages have dependencies not in root package.json:'));
3889
- for (const m of missing) {
3890
- console.log(colors.yellow(` ${m.dep} (${m.version}) — from ${m.from}`));
3891
- }
3892
- console.log(colors.dim(' Global install (npm install -g) only installs root deps.'));
3893
- if (!options.dryRun) {
3894
- const hoist = await confirm('Add missing deps to root package.json?', true);
3895
- if (hoist) {
3896
- if (!rootPkg.dependencies)
3897
- rootPkg.dependencies = {};
3898
- for (const m of missing) {
3899
- rootPkg.dependencies[m.dep] = m.version;
3900
- console.log(colors.green(` + ${m.dep}: ${m.version}`));
3901
- }
3902
- writePackageJson(rootDir, rootPkg);
3903
- console.log(colors.green('✓ Hoisted workspace deps to root package.json'));
3904
- }
3905
- }
3906
- else {
3907
- console.log(colors.dim(' [dry-run] Would offer to hoist missing deps'));
3908
- }
3909
- console.log('');
3910
- }
3911
- }
3912
3883
  // Handle --cleanup: restore deps for all packages and return
3913
3884
  if (options.cleanup) {
3914
3885
  console.log('Restoring workspace dependencies...');
@@ -4062,6 +4033,46 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
4062
4033
  console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
4063
4034
  console.log(` Installing workspace root: ${colors.green(pkgName)}`);
4064
4035
  console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
4036
+ // Auto-hoist workspace sub-package deps to root for global install,
4037
+ // then restore original root deps afterward.
4038
+ const wsNames = new Set(packages.map(p => p.name));
4039
+ const rootDeps = { ...rootPkgFinal.dependencies, ...rootPkgFinal.devDependencies };
4040
+ const hoisted = [];
4041
+ for (const pkgInfo of packages) {
4042
+ const deps = pkgInfo.pkg.dependencies || {};
4043
+ for (const [dep, ver] of Object.entries(deps)) {
4044
+ if (wsNames.has(dep))
4045
+ continue; // sibling workspace — bundled
4046
+ if (dep in rootDeps)
4047
+ continue; // already in root
4048
+ if (hoisted.some(m => m.dep === dep))
4049
+ continue;
4050
+ hoisted.push({ dep, version: ver, from: pkgInfo.name });
4051
+ }
4052
+ }
4053
+ // Save original deps and add hoisted ones
4054
+ const savedDeps = rootPkgFinal.dependencies ? { ...rootPkgFinal.dependencies } : undefined;
4055
+ if (hoisted.length > 0 && !dryRun) {
4056
+ if (!rootPkgFinal.dependencies)
4057
+ rootPkgFinal.dependencies = {};
4058
+ for (const m of hoisted) {
4059
+ // Convert file: refs to npm versions (the sub-package was just published)
4060
+ let version = m.version;
4061
+ if (typeof version === 'string' && version.startsWith('file:')) {
4062
+ const depDir = path.resolve(rootDir, version.replace('file:', ''));
4063
+ try {
4064
+ const depPkg = readPackageJson(depDir);
4065
+ version = `^${depPkg.version}`;
4066
+ }
4067
+ catch {
4068
+ // keep original if we can't resolve
4069
+ }
4070
+ }
4071
+ rootPkgFinal.dependencies[m.dep] = version;
4072
+ console.log(colors.green(` + hoisted ${m.dep}: ${version} (from ${m.from})`));
4073
+ }
4074
+ writePackageJson(rootDir, rootPkgFinal);
4075
+ }
4065
4076
  if (link || install) {
4066
4077
  // Workspace root is private — always install from local directory
4067
4078
  console.log(`Installing ${pkgName}@${pkgVersion} globally from local directory...`);
@@ -4094,6 +4105,17 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
4094
4105
  console.log(` [dry-run] Would run: wsl npm install -g .`);
4095
4106
  }
4096
4107
  }
4108
+ // Restore original root deps after install
4109
+ if (hoisted.length > 0 && !dryRun) {
4110
+ if (savedDeps === undefined) {
4111
+ delete rootPkgFinal.dependencies;
4112
+ }
4113
+ else {
4114
+ rootPkgFinal.dependencies = savedDeps;
4115
+ }
4116
+ writePackageJson(rootDir, rootPkgFinal);
4117
+ console.log(colors.green('✓ Restored root package.json dependencies'));
4118
+ }
4097
4119
  console.log('');
4098
4120
  }
4099
4121
  return { success: allSuccess, packages: results, publishOrder };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.118",
3
+ "version": "1.0.119",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",