@bobfrankston/npmglobalize 1.0.121 → 1.0.123

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 +86 -46
  2. package/package.json +1 -1
package/lib.js CHANGED
@@ -2998,16 +2998,18 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2998
2998
  console.log(' No file: dependencies found.');
2999
2999
  }
3000
3000
  // Hoist workspace sub-package deps into root for publishing/global install.
3001
- // npm install -g only installs root-level dependencies, so sub-package deps
3002
- // like express must be present in the root package.json.
3003
- // These are added temporarily restoreDeps removes them via .dependencies backup.
3001
+ // npm install -g only installs root-level dependencies and doesn't process
3002
+ // the workspaces field, so:
3003
+ // 1. Third-party deps (express, ws, etc.) must be in root dependencies
3004
+ // 2. Sibling workspace packages must be in bundledDependencies so npm
3005
+ // includes them in the tarball's node_modules/
3006
+ // All changes are temporary — restoreDeps removes them via .dependencies backup.
3004
3007
  if (pkg.workspaces) {
3005
3008
  const wsPatterns = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces.packages || [];
3006
3009
  // Collect all workspace sub-package dirs
3007
3010
  const wsDirs = [];
3008
3011
  for (const pattern of wsPatterns) {
3009
3012
  if (pattern.includes('*')) {
3010
- // Glob pattern like "packages/*" — enumerate subdirectories
3011
3013
  const baseDir = path.resolve(cwd, pattern.replace(/\/?\*$/, ''));
3012
3014
  if (!fs.existsSync(baseDir))
3013
3015
  continue;
@@ -3017,14 +3019,13 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3017
3019
  }
3018
3020
  }
3019
3021
  else {
3020
- // Direct directory like "client"
3021
3022
  const dir = path.resolve(cwd, pattern);
3022
3023
  if (fs.existsSync(dir))
3023
3024
  wsDirs.push(dir);
3024
3025
  }
3025
3026
  }
3026
- // Collect all workspace package names (siblings to skip)
3027
- const wsNames = new Set();
3027
+ // Collect workspace package names and their relative paths
3028
+ const wsPackages = new Map(); // name -> relative dir
3028
3029
  for (const dir of wsDirs) {
3029
3030
  const pkgJsonPath = path.join(dir, 'package.json');
3030
3031
  if (!fs.existsSync(pkgJsonPath))
@@ -3032,11 +3033,11 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3032
3033
  try {
3033
3034
  const subPkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
3034
3035
  if (subPkg.name)
3035
- wsNames.add(subPkg.name);
3036
+ wsPackages.set(subPkg.name, path.relative(cwd, dir).replace(/\\/g, '/'));
3036
3037
  }
3037
3038
  catch { /* skip */ }
3038
3039
  }
3039
- // Find deps in sub-packages not present in root
3040
+ // Find third-party deps in sub-packages not present in root
3040
3041
  const rootDeps = { ...pkg.dependencies, ...pkg.devDependencies };
3041
3042
  const hoisted = [];
3042
3043
  for (const dir of wsDirs) {
@@ -3052,8 +3053,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3052
3053
  }
3053
3054
  const deps = subPkg.dependencies || {};
3054
3055
  for (const [dep, ver] of Object.entries(deps)) {
3055
- if (wsNames.has(dep))
3056
- continue; // sibling workspace — bundled
3056
+ if (wsPackages.has(dep))
3057
+ continue; // sibling workspace — handled via bundledDependencies
3057
3058
  if (dep in rootDeps)
3058
3059
  continue; // already in root
3059
3060
  if (hoisted.some(m => m.dep === dep))
@@ -3061,7 +3062,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3061
3062
  hoisted.push({ dep, version: ver, from: subPkg.name || path.basename(dir) });
3062
3063
  }
3063
3064
  }
3064
- if (hoisted.length > 0) {
3065
+ const needsUpdate = hoisted.length > 0 || wsPackages.size > 0;
3066
+ if (needsUpdate) {
3065
3067
  // Ensure .dependencies backup exists so restoreDeps will remove hoisted deps
3066
3068
  if (!pkg['.dependencies']) {
3067
3069
  pkg['.dependencies'] = { ...(pkg.dependencies || {}) };
@@ -3069,6 +3071,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3069
3071
  }
3070
3072
  if (!pkg.dependencies)
3071
3073
  pkg.dependencies = {};
3074
+ // Hoist third-party deps
3072
3075
  for (const m of hoisted) {
3073
3076
  let version = m.version;
3074
3077
  if (typeof version === 'string' && version.startsWith('file:')) {
@@ -3225,40 +3228,56 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3225
3228
  }
3226
3229
  }
3227
3230
  else if (install) {
3228
- // Quick check: does this version actually exist on npm?
3229
- const vCheck = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3230
- shell: process.platform === 'win32',
3231
- stdio: ['pipe', 'pipe', 'pipe'],
3232
- encoding: 'utf-8'
3233
- });
3234
- const vOnNpm = vCheck.status === 0 && vCheck.stdout?.trim() === pkgVersion;
3235
- if (vOnNpm) {
3236
- console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
3237
- const registryInstallResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3238
- if (registryInstallResult.success) {
3231
+ // Workspace packages must install from local npm install -g from
3232
+ // registry doesn't process workspaces, so sub-packages can't resolve
3233
+ // sibling imports. Local install handles workspace linking correctly.
3234
+ if (pkg.workspaces) {
3235
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from local (workspace)...`);
3236
+ const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3237
+ if (localResult.success) {
3239
3238
  console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3240
3239
  }
3241
3240
  else {
3242
3241
  console.error(colors.red(`✗ Global install failed`));
3243
- console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3242
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3244
3243
  }
3245
3244
  }
3246
3245
  else {
3247
- console.log(colors.yellow(`${pkgName}@${pkgVersion} not found on npm installing from local directory.`));
3248
- console.log(colors.dim(' Use -m "message" to publish this version to npm.'));
3249
- const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3250
- if (localResult.success) {
3251
- console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${pkgVersion}`));
3246
+ // Quick check: does this version actually exist on npm?
3247
+ const vCheck = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3248
+ shell: process.platform === 'win32',
3249
+ stdio: ['pipe', 'pipe', 'pipe'],
3250
+ encoding: 'utf-8'
3251
+ });
3252
+ const vOnNpm = vCheck.status === 0 && vCheck.stdout?.trim() === pkgVersion;
3253
+ if (vOnNpm) {
3254
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
3255
+ const registryInstallResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3256
+ if (registryInstallResult.success) {
3257
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3258
+ }
3259
+ else {
3260
+ console.error(colors.red(`✗ Global install failed`));
3261
+ console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3262
+ }
3252
3263
  }
3253
3264
  else {
3254
- console.error(colors.red(`✗ Local install failed`));
3255
- console.error(colors.yellow(' Try running manually: npm install -g .'));
3265
+ console.log(colors.yellow(`${pkgName}@${pkgVersion} not found on npm — installing from local directory.`));
3266
+ console.log(colors.dim(' Use -m "message" to publish this version to npm.'));
3267
+ const localResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3268
+ if (localResult.success) {
3269
+ console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${pkgVersion}`));
3270
+ }
3271
+ else {
3272
+ console.error(colors.red(`✗ Local install failed`));
3273
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3274
+ }
3256
3275
  }
3257
3276
  }
3258
3277
  }
3259
3278
  if (wsl) {
3260
- // Check if version is on npm for registry-based WSL install
3261
- const useLocal = link || (() => {
3279
+ // Workspace packages must install from local (see above)
3280
+ const useLocal = link || !!pkg.workspaces || (() => {
3262
3281
  const vc = spawnSafe('npm', ['view', `${pkgName}@${pkgVersion}`, 'version'], {
3263
3282
  shell: process.platform === 'win32',
3264
3283
  stdio: ['pipe', 'pipe', 'pipe'],
@@ -3837,28 +3856,49 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3837
3856
  }
3838
3857
  }
3839
3858
  else if (install) {
3840
- console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
3841
- if (!dryRun) {
3842
- waitForNpmVersion(pkgName, pkgVersion);
3843
- const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3844
- if (installResult.success) {
3845
- globalInstallOk = true;
3846
- console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3859
+ if (updatedPkg.workspaces) {
3860
+ // Workspace packages: install from local for proper workspace linking
3861
+ console.log(`Installing ${pkgName}@${pkgVersion} globally from local (workspace)...`);
3862
+ if (!dryRun) {
3863
+ const installResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, showCommand: true });
3864
+ if (installResult.success) {
3865
+ globalInstallOk = true;
3866
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3867
+ }
3868
+ else {
3869
+ console.error(colors.red(`✗ Global install failed`));
3870
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
3871
+ }
3847
3872
  }
3848
3873
  else {
3849
- console.error(colors.red(`✗ Global install failed`));
3850
- console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3874
+ console.log(` [dry-run] Would run: npm install -g .`);
3851
3875
  }
3852
3876
  }
3853
3877
  else {
3854
- console.log(` [dry-run] Would run: npm install -g ${pkgName}@${pkgVersion}`);
3878
+ console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
3879
+ if (!dryRun) {
3880
+ waitForNpmVersion(pkgName, pkgVersion);
3881
+ const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
3882
+ if (installResult.success) {
3883
+ globalInstallOk = true;
3884
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
3885
+ }
3886
+ else {
3887
+ console.error(colors.red(`✗ Global install failed`));
3888
+ console.error(colors.yellow(` Try running manually: npm install -g ${pkgName}@${pkgVersion}`));
3889
+ }
3890
+ }
3891
+ else {
3892
+ console.log(` [dry-run] Would run: npm install -g ${pkgName}@${pkgVersion}`);
3893
+ }
3855
3894
  }
3856
3895
  }
3857
3896
  if (wsl) {
3858
- const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
3859
- if (!link && !install)
3897
+ const useLocalWsl = link || !!updatedPkg.workspaces;
3898
+ const wslArgs = useLocalWsl ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
3899
+ if (!useLocalWsl)
3860
3900
  waitForNpmVersion(pkgName, pkgVersion);
3861
- console.log(`Installing in WSL${link ? ' (link)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
3901
+ console.log(`Installing in WSL${useLocalWsl ? ' (local)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
3862
3902
  if (!dryRun) {
3863
3903
  const wslResult = runCommand('wsl', wslArgs, { cwd, silent: false, showCommand: true });
3864
3904
  if (wslResult.success) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.121",
3
+ "version": "1.0.123",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",