@bobfrankston/npmglobalize 1.0.122 → 1.0.124

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 (3) hide show
  1. package/lib.d.ts +2 -0
  2. package/lib.js +96 -83
  3. package/package.json +1 -1
package/lib.d.ts CHANGED
@@ -78,6 +78,8 @@ export interface GlobalizeOptions {
78
78
  local?: boolean;
79
79
  /** Freeze node_modules: replace symlinks/junctions with real copies for network share use */
80
80
  freeze?: boolean;
81
+ /** Internal: auto-initialize git repos without prompting (user chose "all") */
82
+ autoInit?: boolean;
81
83
  /** Internal: signals this call is from workspace orchestrator */
82
84
  _fromWorkspace?: boolean;
83
85
  /** Internal: signals this call is from CLI (version already printed) */
package/lib.js CHANGED
@@ -814,18 +814,6 @@ export function restoreDeps(pkg, verbose = false) {
814
814
  }
815
815
  }
816
816
  }
817
- // Remove bundledDependencies added for workspace hoisting
818
- if (pkg['.bundledDependencies']) {
819
- if (pkg['.bundledDependencies'].length === 0) {
820
- delete pkg.bundledDependencies;
821
- delete pkg.bundleDependencies;
822
- }
823
- else {
824
- pkg.bundledDependencies = pkg['.bundledDependencies'];
825
- }
826
- delete pkg['.bundledDependencies'];
827
- restored = true;
828
- }
829
817
  return restored;
830
818
  }
831
819
  /** Check if .dependencies exist (already transformed) */
@@ -2391,8 +2379,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2391
2379
  if (dryRun) {
2392
2380
  console.log(' [dry-run] Would initialize git repository');
2393
2381
  }
2394
- else if (!init) {
2395
- const choice = await promptChoice('No git repository found. What would you like to do?\n 1) Initialize git repository (default)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', '2', '3', '']);
2382
+ else if (!init && !options.autoInit) {
2383
+ const choice = await promptChoice('No git repository found. What would you like to do?\n 1) Initialize git repository (default)\n a) Initialize ALL (don\'t ask again for remaining deps)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', 'a', '2', '3', '']);
2396
2384
  if (choice === '2') {
2397
2385
  console.log(colors.dim('Switching to local-only mode...'));
2398
2386
  writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
@@ -2402,7 +2390,10 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2402
2390
  console.log('Aborted. Run with --init to initialize.');
2403
2391
  return false;
2404
2392
  }
2405
- // choice is '1' or '' (default)
2393
+ if (choice === 'a') {
2394
+ options.autoInit = true;
2395
+ }
2396
+ // choice is '1', 'a', or '' (default)
2406
2397
  const success = await initGit(cwd, gitVisibility, dryRun);
2407
2398
  if (!success)
2408
2399
  return false;
@@ -2417,8 +2408,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2417
2408
  }
2418
2409
  else if (!gitStatus.hasRemote) {
2419
2410
  // Git repo exists but no remote - need to create GitHub repo
2420
- if (!init) {
2421
- const choice = await promptChoice('No git remote configured. What would you like to do?\n 1) Create GitHub repository (default)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', '2', '3', '']);
2411
+ if (!init && !options.autoInit) {
2412
+ const choice = await promptChoice('No git remote configured. What would you like to do?\n 1) Create GitHub repository (default)\n a) Initialize ALL (don\'t ask again for remaining deps)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', 'a', '2', '3', '']);
2422
2413
  if (choice === '2') {
2423
2414
  console.log(colors.dim('Switching to local-only mode...'));
2424
2415
  writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
@@ -2428,6 +2419,9 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2428
2419
  console.log('Aborted. Run with --init to set up GitHub repository.');
2429
2420
  return false;
2430
2421
  }
2422
+ if (choice === 'a') {
2423
+ options.autoInit = true;
2424
+ }
2431
2425
  }
2432
2426
  const success = await initGit(cwd, gitVisibility, dryRun);
2433
2427
  if (!success)
@@ -2971,7 +2965,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2971
2965
  conform, // Propagate conform to dependencies
2972
2966
  publishDeps, // Propagate so transitive deps also get published
2973
2967
  forcePublish, // Propagate so transitive deps get force-published too
2974
- rebase // Propagate so behind-remote deps get rebased automatically
2968
+ rebase, // Propagate so behind-remote deps get rebased automatically
2969
+ autoInit: options.autoInit // Propagate "init all" choice
2975
2970
  });
2976
2971
  if (!depSuccess) {
2977
2972
  console.error(colors.red(`Failed to publish ${name}`));
@@ -3009,13 +3004,12 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3009
3004
  else if (!alreadyTransformed && verbose) {
3010
3005
  console.log(' No file: dependencies found.');
3011
3006
  }
3012
- // Hoist workspace sub-package deps into root for publishing/global install.
3013
- // npm install -g only installs root-level dependencies and doesn't process
3014
- // the workspaces field, so:
3015
- // 1. Third-party deps (express, ws, etc.) must be in root dependencies
3016
- // 2. Sibling workspace packages must be in bundledDependencies so npm
3017
- // includes them in the tarball's node_modules/
3018
- // All changes are temporary — restoreDeps removes them via .dependencies backup.
3007
+ // Hoist workspace sub-package third-party deps into root for global install.
3008
+ // npm install -g from local handles workspace linking, but third-party deps
3009
+ // (express, ws, etc.) in sub-packages must also be in root dependencies
3010
+ // so they get installed. Workspace sibling refs are skipped npm install -g .
3011
+ // handles those via workspace linking.
3012
+ // Changes are temporary — restoreDeps removes them via .dependencies backup.
3019
3013
  if (pkg.workspaces) {
3020
3014
  const wsPatterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages || [];
3021
3015
  // Collect all workspace sub-package dirs
@@ -3036,8 +3030,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3036
3030
  wsDirs.push(dir);
3037
3031
  }
3038
3032
  }
3039
- // Collect workspace package names and their relative paths
3040
- const wsPackages = new Map(); // name -> relative dir
3033
+ // Collect workspace package names (to skip as siblings)
3034
+ const wsNames = new Set();
3041
3035
  for (const dir of wsDirs) {
3042
3036
  const pkgJsonPath = path.join(dir, 'package.json');
3043
3037
  if (!fs.existsSync(pkgJsonPath))
@@ -3045,7 +3039,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3045
3039
  try {
3046
3040
  const subPkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
3047
3041
  if (subPkg.name)
3048
- wsPackages.set(subPkg.name, path.relative(cwd, dir).replace(/\\/g, '/'));
3042
+ wsNames.add(subPkg.name);
3049
3043
  }
3050
3044
  catch { /* skip */ }
3051
3045
  }
@@ -3065,8 +3059,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3065
3059
  }
3066
3060
  const deps = subPkg.dependencies || {};
3067
3061
  for (const [dep, ver] of Object.entries(deps)) {
3068
- if (wsPackages.has(dep))
3069
- continue; // sibling workspace — handled via bundledDependencies
3062
+ if (wsNames.has(dep))
3063
+ continue; // sibling workspace — handled by npm install -g .
3070
3064
  if (dep in rootDeps)
3071
3065
  continue; // already in root
3072
3066
  if (hoisted.some(m => m.dep === dep))
@@ -3074,8 +3068,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3074
3068
  hoisted.push({ dep, version: ver, from: subPkg.name || path.basename(dir) });
3075
3069
  }
3076
3070
  }
3077
- const needsUpdate = hoisted.length > 0 || wsPackages.size > 0;
3078
- if (needsUpdate) {
3071
+ if (hoisted.length > 0) {
3079
3072
  // Ensure .dependencies backup exists so restoreDeps will remove hoisted deps
3080
3073
  if (!pkg['.dependencies']) {
3081
3074
  pkg['.dependencies'] = { ...(pkg.dependencies || {}) };
@@ -3083,7 +3076,6 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3083
3076
  }
3084
3077
  if (!pkg.dependencies)
3085
3078
  pkg.dependencies = {};
3086
- // Hoist third-party deps
3087
3079
  for (const m of hoisted) {
3088
3080
  let version = m.version;
3089
3081
  if (typeof version === 'string' && version.startsWith('file:')) {
@@ -3099,22 +3091,6 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3099
3091
  pkg.dependencies[m.dep] = version;
3100
3092
  console.log(colors.green(` + hoisted ${m.dep}: ${version} (from ${m.from})`));
3101
3093
  }
3102
- // Add workspace sibling packages to dependencies + bundledDependencies
3103
- // so npm includes them in the tarball's node_modules/
3104
- // Save original bundledDependencies for restore
3105
- const origBundled = pkg.bundledDependencies || pkg.bundleDependencies || [];
3106
- pkg['.bundledDependencies'] = [...origBundled];
3107
- const bundled = [...origBundled];
3108
- for (const [name, relDir] of wsPackages) {
3109
- if (!(name in pkg.dependencies)) {
3110
- pkg.dependencies[name] = 'file:./' + relDir;
3111
- }
3112
- if (!bundled.includes(name)) {
3113
- bundled.push(name);
3114
- }
3115
- console.log(colors.green(` + bundled workspace ${name} (./${relDir})`));
3116
- }
3117
- pkg.bundledDependencies = bundled;
3118
3094
  if (!dryRun) {
3119
3095
  writePackageJson(cwd, pkg);
3120
3096
  }
@@ -3256,40 +3232,56 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3256
3232
  }
3257
3233
  }
3258
3234
  else if (install) {
3259
- // Quick check: does this version actually exist on npm?
3260
- const vCheck = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3261
- shell: process.platform === 'win32',
3262
- stdio: ['pipe', 'pipe', 'pipe'],
3263
- encoding: 'utf-8'
3264
- });
3265
- const vOnNpm = vCheck.status === 0 && vCheck.stdout?.trim() === pkgVersion;
3266
- if (vOnNpm) {
3267
- console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
3268
- const registryInstallResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3269
- if (registryInstallResult.success) {
3235
+ // Workspace packages must install from local npm install -g from
3236
+ // registry doesn't process workspaces, so sub-packages can't resolve
3237
+ // sibling imports. Local install handles workspace linking correctly.
3238
+ if (pkg.workspaces) {
3239
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from local (workspace)...`);
3240
+ const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3241
+ if (localResult.success) {
3270
3242
  console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3271
3243
  }
3272
3244
  else {
3273
3245
  console.error(colors.red(`✗ Global install failed`));
3274
- console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3246
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3275
3247
  }
3276
3248
  }
3277
3249
  else {
3278
- console.log(colors.yellow(`${pkgName}@${pkgVersion} not found on npm installing from local directory.`));
3279
- console.log(colors.dim(' Use -m "message" to publish this version to npm.'));
3280
- const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3281
- if (localResult.success) {
3282
- console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${pkgVersion}`));
3250
+ // Quick check: does this version actually exist on npm?
3251
+ const vCheck = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3252
+ shell: process.platform === 'win32',
3253
+ stdio: ['pipe', 'pipe', 'pipe'],
3254
+ encoding: 'utf-8'
3255
+ });
3256
+ const vOnNpm = vCheck.status === 0 && vCheck.stdout?.trim() === pkgVersion;
3257
+ if (vOnNpm) {
3258
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
3259
+ const registryInstallResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3260
+ if (registryInstallResult.success) {
3261
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3262
+ }
3263
+ else {
3264
+ console.error(colors.red(`✗ Global install failed`));
3265
+ console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3266
+ }
3283
3267
  }
3284
3268
  else {
3285
- console.error(colors.red(`✗ Local install failed`));
3286
- console.error(colors.yellow(' Try running manually: npm install -g .'));
3269
+ console.log(colors.yellow(`${pkgName}@${pkgVersion} not found on npm — installing from local directory.`));
3270
+ console.log(colors.dim(' Use -m "message" to publish this version to npm.'));
3271
+ const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3272
+ if (localResult.success) {
3273
+ console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${pkgVersion}`));
3274
+ }
3275
+ else {
3276
+ console.error(colors.red(`✗ Local install failed`));
3277
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3278
+ }
3287
3279
  }
3288
3280
  }
3289
3281
  }
3290
3282
  if (wsl) {
3291
- // Check if version is on npm for registry-based WSL install
3292
- const useLocal = link || (() => {
3283
+ // Workspace packages must install from local (see above)
3284
+ const useLocal = link || !!pkg.workspaces || (() => {
3293
3285
  const vc = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3294
3286
  shell: process.platform === 'win32',
3295
3287
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -3868,28 +3860,49 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3868
3860
  }
3869
3861
  }
3870
3862
  else if (install) {
3871
- console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
3872
- if (!dryRun) {
3873
- waitForNpmVersion(pkgName, pkgVersion);
3874
- const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3875
- if (installResult.success) {
3876
- globalInstallOk = true;
3877
- console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3863
+ if (updatedPkg.workspaces) {
3864
+ // Workspace packages: install from local for proper workspace linking
3865
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from local (workspace)...`);
3866
+ if (!dryRun) {
3867
+ const installResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3868
+ if (installResult.success) {
3869
+ globalInstallOk = true;
3870
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3871
+ }
3872
+ else {
3873
+ console.error(colors.red(`✗ Global install failed`));
3874
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3875
+ }
3878
3876
  }
3879
3877
  else {
3880
- console.error(colors.red(`✗ Global install failed`));
3881
- console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3878
+ console.log(` [dry-run] Would run: npm install -g .`);
3882
3879
  }
3883
3880
  }
3884
3881
  else {
3885
- console.log(` [dry-run] Would run: npm install -g ${pkgName}@${pkgVersion}`);
3882
+ console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
3883
+ if (!dryRun) {
3884
+ waitForNpmVersion(pkgName, pkgVersion);
3885
+ const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3886
+ if (installResult.success) {
3887
+ globalInstallOk = true;
3888
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3889
+ }
3890
+ else {
3891
+ console.error(colors.red(`✗ Global install failed`));
3892
+ console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3893
+ }
3894
+ }
3895
+ else {
3896
+ console.log(` [dry-run] Would run: npm install -g ${pkgName}@${pkgVersion}`);
3897
+ }
3886
3898
  }
3887
3899
  }
3888
3900
  if (wsl) {
3889
- const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
3890
- if (!link && !install)
3901
+ const useLocalWsl = link || !!updatedPkg.workspaces;
3902
+ const wslArgs = useLocalWsl ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
3903
+ if (!useLocalWsl)
3891
3904
  waitForNpmVersion(pkgName, pkgVersion);
3892
- console.log(`Installing in WSL${link ? ' (link)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
3905
+ console.log(`Installing in WSL${useLocalWsl ? ' (local)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
3893
3906
  if (!dryRun) {
3894
3907
  const wslResult = runCommand('wsl', wslArgs, { cwd, silent: false, showCommand: true });
3895
3908
  if (wslResult.success) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.122",
3
+ "version": "1.0.124",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",