@bobfrankston/npmglobalize 1.0.166 → 1.0.168
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/cli.js +5 -0
- package/lib/git.d.ts +12 -4
- package/lib/git.js +29 -11
- package/lib.js +125 -62
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -24,6 +24,7 @@ Release Options:
|
|
|
24
24
|
-minor Bump minor version
|
|
25
25
|
-major Bump major version
|
|
26
26
|
-nopublish, -np Just transform, don't publish (persisted to config)
|
|
27
|
+
-publish Clear a persisted -nopublish in .globalize.json5
|
|
27
28
|
-cleanup Restore from .dependencies
|
|
28
29
|
-m, -message <msg> Custom commit message (forces release even without changes)
|
|
29
30
|
If -m not given and a .commitmsg file exists in cwd, its
|
|
@@ -158,6 +159,10 @@ function parseArgs(args) {
|
|
|
158
159
|
options.noPublish = true;
|
|
159
160
|
options.explicitKeys.add('noPublish');
|
|
160
161
|
break;
|
|
162
|
+
case '-publish':
|
|
163
|
+
options.noPublish = false;
|
|
164
|
+
options.explicitKeys.add('noPublish');
|
|
165
|
+
break;
|
|
161
166
|
case '-cleanup':
|
|
162
167
|
options.cleanup = true;
|
|
163
168
|
break;
|
package/lib/git.d.ts
CHANGED
|
@@ -51,10 +51,18 @@ export declare function parseVersionTag(tag: string): number[] | null;
|
|
|
51
51
|
export declare function compareVersions(a: number[], b: number[]): number;
|
|
52
52
|
/** Fix version/tag mismatches */
|
|
53
53
|
export declare function fixVersionTagMismatch(cwd: string, pkg: any, verbose?: boolean): boolean;
|
|
54
|
-
/** Wait for a package version to appear on the npm registry
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
/** Wait for a package version to appear on the npm registry.
|
|
55
|
+
* First-time publishes (brand-new package name) take much longer to
|
|
56
|
+
* propagate than version bumps — npm has no cached metadata to update,
|
|
57
|
+
* so the registry/CDN can take several minutes before the package is
|
|
58
|
+
* resolvable. We wait longer and re-probe `npm view` for the version
|
|
59
|
+
* string until it shows up (or we hit the cap). */
|
|
60
|
+
export declare function waitForNpmVersion(pkgName: string, version: string, isNewPackage?: boolean, maxWaitMs?: number): boolean;
|
|
61
|
+
/** Run npm install -g with retries for registry propagation delay.
|
|
62
|
+
* Brand-new packages (first-time publish) take much longer to become
|
|
63
|
+
* installable than version bumps, so we use longer waits and more
|
|
64
|
+
* attempts when `isNewPackage` is true. */
|
|
65
|
+
export declare function installGlobalWithRetry(pkgSpec: string, cwd: string, isNewPackage?: boolean, maxRetries?: number): {
|
|
58
66
|
success: boolean;
|
|
59
67
|
output: string;
|
|
60
68
|
stderr: string;
|
package/lib/git.js
CHANGED
|
@@ -469,11 +469,24 @@ export function fixVersionTagMismatch(cwd, pkg, verbose = false) {
|
|
|
469
469
|
return deletedAny;
|
|
470
470
|
}
|
|
471
471
|
// ── Group 5: npm install helpers (private) ──────────────────────────
|
|
472
|
-
/**
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
472
|
+
/** Reliable synchronous sleep — works regardless of stdio/TTY state.
|
|
473
|
+
* (Windows `timeout /t` exits immediately when stdio is piped, which broke
|
|
474
|
+
* the previous spawn-based sleep.) */
|
|
475
|
+
function sleepSync(ms) {
|
|
476
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
477
|
+
}
|
|
478
|
+
/** Wait for a package version to appear on the npm registry.
|
|
479
|
+
* First-time publishes (brand-new package name) take much longer to
|
|
480
|
+
* propagate than version bumps — npm has no cached metadata to update,
|
|
481
|
+
* so the registry/CDN can take several minutes before the package is
|
|
482
|
+
* resolvable. We wait longer and re-probe `npm view` for the version
|
|
483
|
+
* string until it shows up (or we hit the cap). */
|
|
484
|
+
export function waitForNpmVersion(pkgName, version, isNewPackage = false, maxWaitMs) {
|
|
485
|
+
const effectiveMaxWait = maxWaitMs ?? (isNewPackage ? 600000 : 180000);
|
|
486
|
+
const interval = isNewPackage ? 5000 : 3000;
|
|
487
|
+
const maxAttempts = Math.ceil(effectiveMaxWait / interval);
|
|
488
|
+
const suffix = isNewPackage ? ' (new package, may take several minutes)' : '';
|
|
489
|
+
process.stdout.write(`Waiting for ${pkgName}@${version} on npm registry${suffix}`);
|
|
477
490
|
for (let i = 0; i < maxAttempts; i++) {
|
|
478
491
|
const result = spawnSafe('npm', ['view', `${pkgName}@${version}`, 'version'], {
|
|
479
492
|
shell: process.platform === 'win32',
|
|
@@ -485,17 +498,22 @@ export function waitForNpmVersion(pkgName, version, maxWaitMs = 90000) {
|
|
|
485
498
|
return true;
|
|
486
499
|
}
|
|
487
500
|
process.stdout.write('.');
|
|
488
|
-
|
|
501
|
+
sleepSync(interval);
|
|
489
502
|
}
|
|
490
503
|
process.stdout.write(' timed out\n');
|
|
491
504
|
return false;
|
|
492
505
|
}
|
|
493
|
-
/** Run npm install -g with retries for registry propagation delay
|
|
494
|
-
|
|
506
|
+
/** Run npm install -g with retries for registry propagation delay.
|
|
507
|
+
* Brand-new packages (first-time publish) take much longer to become
|
|
508
|
+
* installable than version bumps, so we use longer waits and more
|
|
509
|
+
* attempts when `isNewPackage` is true. */
|
|
510
|
+
export function installGlobalWithRetry(pkgSpec, cwd, isNewPackage = false, maxRetries) {
|
|
511
|
+
const retries = maxRetries ?? (isNewPackage ? 6 : 3);
|
|
512
|
+
const delaySec = isNewPackage ? 30 : 10;
|
|
495
513
|
let result = runCommand('npm', ['install', '-g', pkgSpec], { cwd, silent: false, showCommand: true });
|
|
496
|
-
for (let attempt = 1; attempt <
|
|
497
|
-
console.log(colors.yellow(` Retrying install (attempt ${attempt + 1}/${
|
|
498
|
-
|
|
514
|
+
for (let attempt = 1; attempt < retries && !result.success; attempt++) {
|
|
515
|
+
console.log(colors.yellow(` Retrying install (attempt ${attempt + 1}/${retries}) in ${delaySec} seconds...`));
|
|
516
|
+
sleepSync(delaySec * 1000);
|
|
499
517
|
result = runCommand('npm', ['install', '-g', pkgSpec], { cwd, silent: false, showCommand: true });
|
|
500
518
|
}
|
|
501
519
|
return result;
|
package/lib.js
CHANGED
|
@@ -1365,11 +1365,24 @@ export function fixVersionTagMismatch(cwd, pkg, verbose = false) {
|
|
|
1365
1365
|
}
|
|
1366
1366
|
return deletedAny;
|
|
1367
1367
|
}
|
|
1368
|
-
/**
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1368
|
+
/** Reliable synchronous sleep — works regardless of stdio/TTY state.
|
|
1369
|
+
* (Windows `timeout /t` exits immediately when stdio is piped, which broke
|
|
1370
|
+
* the previous spawn-based sleep.) */
|
|
1371
|
+
function sleepSync(ms) {
|
|
1372
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
1373
|
+
}
|
|
1374
|
+
/** Wait for a package version to appear on the npm registry.
|
|
1375
|
+
* First-time publishes (brand-new package name) take much longer to
|
|
1376
|
+
* propagate than version bumps — npm has no cached metadata to update,
|
|
1377
|
+
* so the registry/CDN can take several minutes before the package is
|
|
1378
|
+
* resolvable. We wait longer and re-probe `npm view` for the version
|
|
1379
|
+
* string until it shows up (or we hit the cap). */
|
|
1380
|
+
function waitForNpmVersion(pkgName, version, isNewPackage = false, maxWaitMs) {
|
|
1381
|
+
const effectiveMaxWait = maxWaitMs ?? (isNewPackage ? 600000 : 180000);
|
|
1382
|
+
const interval = isNewPackage ? 5000 : 3000;
|
|
1383
|
+
const maxAttempts = Math.ceil(effectiveMaxWait / interval);
|
|
1384
|
+
const suffix = isNewPackage ? ' (new package, may take several minutes)' : '';
|
|
1385
|
+
process.stdout.write(`${timestamp()} Waiting for ${pkgName}@${version} on npm registry${suffix}`);
|
|
1373
1386
|
for (let i = 0; i < maxAttempts; i++) {
|
|
1374
1387
|
const result = spawnSafe('npm', ['view', `${pkgName}@${version}`, 'version'], {
|
|
1375
1388
|
shell: process.platform === 'win32',
|
|
@@ -1381,7 +1394,7 @@ function waitForNpmVersion(pkgName, version, maxWaitMs = 90000) {
|
|
|
1381
1394
|
return true;
|
|
1382
1395
|
}
|
|
1383
1396
|
process.stdout.write('.');
|
|
1384
|
-
|
|
1397
|
+
sleepSync(interval);
|
|
1385
1398
|
}
|
|
1386
1399
|
process.stdout.write(' timed out\n');
|
|
1387
1400
|
return false;
|
|
@@ -1687,12 +1700,17 @@ export function ensureWorkspaceDepModules(rootDir, members, verbose = false) {
|
|
|
1687
1700
|
console.error(colors.dim(r.stderr.split('\n').slice(0, 5).join('\n')));
|
|
1688
1701
|
}
|
|
1689
1702
|
}
|
|
1690
|
-
/** Run npm install -g with retries for registry propagation delay
|
|
1691
|
-
|
|
1703
|
+
/** Run npm install -g with retries for registry propagation delay.
|
|
1704
|
+
* Brand-new packages (first-time publish) take much longer to become
|
|
1705
|
+
* installable than version bumps, so we use longer waits and more
|
|
1706
|
+
* attempts when `isNewPackage` is true. */
|
|
1707
|
+
function installGlobalWithRetry(pkgSpec, cwd, isNewPackage = false, maxRetries) {
|
|
1708
|
+
const retries = maxRetries ?? (isNewPackage ? 6 : 3);
|
|
1709
|
+
const delaySec = isNewPackage ? 30 : 10;
|
|
1692
1710
|
let result = runCommand('npm', ['install', '-g', pkgSpec], { cwd, silent: false, showCommand: true });
|
|
1693
|
-
for (let attempt = 1; attempt <
|
|
1694
|
-
console.log(colors.yellow(` Retrying install (attempt ${attempt + 1}/${
|
|
1695
|
-
|
|
1711
|
+
for (let attempt = 1; attempt < retries && !result.success; attempt++) {
|
|
1712
|
+
console.log(colors.yellow(` Retrying install (attempt ${attempt + 1}/${retries}) in ${delaySec} seconds...`));
|
|
1713
|
+
sleepSync(delaySec * 1000);
|
|
1696
1714
|
result = runCommand('npm', ['install', '-g', pkgSpec], { cwd, silent: false, showCommand: true });
|
|
1697
1715
|
}
|
|
1698
1716
|
return result;
|
|
@@ -3039,25 +3057,6 @@ export function getToolVersion() {
|
|
|
3039
3057
|
return 'unknown';
|
|
3040
3058
|
}
|
|
3041
3059
|
}
|
|
3042
|
-
/** Offer to add a bin field if missing — returns true if bin was added, false to skip/abort */
|
|
3043
|
-
async function offerAddBin(cwd, pkg) {
|
|
3044
|
-
if (pkg.bin)
|
|
3045
|
-
return true;
|
|
3046
|
-
// Determine likely entry point
|
|
3047
|
-
const mainFile = pkg.main || 'index.js';
|
|
3048
|
-
const cmdName = (pkg.name || path.basename(cwd)).replace(/^@[^/]+\//, '');
|
|
3049
|
-
console.log(colors.yellow('No bin field — this is a library, not a CLI tool.'));
|
|
3050
|
-
console.log(colors.yellow('Libraries should not be installed globally. Use npm install <name> in projects instead.'));
|
|
3051
|
-
const choice = await promptChoice(`Add bin field to make it a CLI tool?\n 1) Yes, use "${cmdName}" → "${mainFile}"\n 2) Skip global install (default)\nChoice:`, ['1', '2', '']);
|
|
3052
|
-
if (choice === '1') {
|
|
3053
|
-
pkg.bin = { [cmdName]: mainFile };
|
|
3054
|
-
writePackageJson(cwd, pkg);
|
|
3055
|
-
console.log(colors.green(`✓ Added bin: { "${cmdName}": "${mainFile}" }`));
|
|
3056
|
-
return true;
|
|
3057
|
-
}
|
|
3058
|
-
// choice is '2' or '' (default) — skip
|
|
3059
|
-
return false;
|
|
3060
|
-
}
|
|
3061
3060
|
/** Perform local-only install (npm install -g .) — extracted for reuse from git-init prompts */
|
|
3062
3061
|
async function doLocalInstall(cwd, options) {
|
|
3063
3062
|
const { dryRun = false, wsl = false } = options;
|
|
@@ -3067,12 +3066,8 @@ async function doLocalInstall(cwd, options) {
|
|
|
3067
3066
|
console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
|
|
3068
3067
|
console.log(colors.dim('Skipping transform/publish — installing with file: deps as-is'));
|
|
3069
3068
|
if (!pkg.bin) {
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
console.log(colors.yellow('Skipping global install — library packages should not be installed globally.'));
|
|
3073
|
-
console.log(colors.yellow(`To use in projects: npm install ${pkgName}`));
|
|
3074
|
-
return true;
|
|
3075
|
-
}
|
|
3069
|
+
console.log(colors.dim(` (library — skipping global install)`));
|
|
3070
|
+
return true;
|
|
3076
3071
|
}
|
|
3077
3072
|
if (dryRun) {
|
|
3078
3073
|
console.log(' [dry-run] Would run: npm install -g .');
|
|
@@ -3143,8 +3138,6 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3143
3138
|
settings.push('--dry-run');
|
|
3144
3139
|
if (configOptions.bump)
|
|
3145
3140
|
settings.push(`--bump ${configOptions.bump}`);
|
|
3146
|
-
if (configOptions.noPublish)
|
|
3147
|
-
settings.push('--no-publish');
|
|
3148
3141
|
if (configOptions.cleanup)
|
|
3149
3142
|
settings.push('--cleanup');
|
|
3150
3143
|
if (configOptions.wsl)
|
|
@@ -3172,9 +3165,15 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3172
3165
|
if (settings.length > 0) {
|
|
3173
3166
|
console.log(colors.dim(`Settings from .globalize.json5: ${settings.join(', ')}`));
|
|
3174
3167
|
}
|
|
3168
|
+
if (configOptions.noPublish) {
|
|
3169
|
+
console.log(colors.yellow(`! noPublish=true in .globalize.json5 — transform only, no npm publish (clear with -publish)`));
|
|
3170
|
+
}
|
|
3175
3171
|
}
|
|
3176
3172
|
console.log('');
|
|
3177
|
-
// -local: skip all transform/publish, just install from local directory with file: deps intact
|
|
3173
|
+
// -local: skip all transform/publish, just install from local directory with file: deps intact.
|
|
3174
|
+
// -local is testing-only and must NOT mutate package.json — packages are meant to be installed
|
|
3175
|
+
// as published public packages by end users; the bin field is whatever the published shape is.
|
|
3176
|
+
// Library members (no bin) are silently skipped: nothing for global install to expose.
|
|
3178
3177
|
if (local) {
|
|
3179
3178
|
const pkg = readPackageJson(cwd);
|
|
3180
3179
|
const pkgName = pkg.name || path.basename(cwd);
|
|
@@ -3182,12 +3181,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3182
3181
|
console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
|
|
3183
3182
|
console.log(colors.dim('Skipping transform/publish — installing with file: deps as-is'));
|
|
3184
3183
|
if (!pkg.bin) {
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
console.log(colors.yellow('Skipping global install — library packages should not be installed globally.'));
|
|
3188
|
-
console.log(colors.yellow(`To use in projects: npm install ${pkgName}`));
|
|
3189
|
-
return true;
|
|
3190
|
-
}
|
|
3184
|
+
console.log(colors.dim(` (library — skipping global install)`));
|
|
3185
|
+
return true;
|
|
3191
3186
|
}
|
|
3192
3187
|
if (dryRun) {
|
|
3193
3188
|
console.log(' [dry-run] Would run: npm install -g .');
|
|
@@ -3526,10 +3521,14 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3526
3521
|
}
|
|
3527
3522
|
// Read package.json
|
|
3528
3523
|
const pkg = readPackageJson(cwd);
|
|
3524
|
+
// Ensure node_modules are present in this dir and every transitive file: dep
|
|
3525
|
+
// before doing anything else. Independent of build script presence — a dep
|
|
3526
|
+
// with new declared deps still needs its own `npm install` even if it has
|
|
3527
|
+
// no build step. CLI entrypoint already ran this, so skip when _fromCli.
|
|
3528
|
+
if (!options._fromCli && !dryRun)
|
|
3529
|
+
ensureFileDepModules(cwd, verbose);
|
|
3529
3530
|
// Run build step if package.json has a build script (skip if CLI already built)
|
|
3530
3531
|
if (pkg.scripts?.build && !options._fromCli) {
|
|
3531
|
-
if (!dryRun)
|
|
3532
|
-
ensureFileDepModules(cwd, verbose);
|
|
3533
3532
|
console.log(`${timestamp()} Running build...`);
|
|
3534
3533
|
if (!dryRun) {
|
|
3535
3534
|
// For workspace roots whose build invokes `--workspaces`, npm uses
|
|
@@ -3628,6 +3627,10 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
3628
3627
|
}
|
|
3629
3628
|
// Check npm visibility and current publication status
|
|
3630
3629
|
let currentAccess = checkNpmAccess(pkg.name);
|
|
3630
|
+
// Track whether this name is brand-new on npm so post-publish waits use
|
|
3631
|
+
// longer timeouts — first-time publishes propagate slowly through the
|
|
3632
|
+
// registry/CDN even after `npm publish` reports success.
|
|
3633
|
+
const wasNewPackage = !currentAccess;
|
|
3631
3634
|
let isScoped = pkg.name.startsWith('@');
|
|
3632
3635
|
// Check if public intent was explicitly declared anywhere:
|
|
3633
3636
|
// CLI (--npm public), config file (.globalize.json5), or package.json publishConfig
|
|
@@ -4147,6 +4150,36 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4147
4150
|
}
|
|
4148
4151
|
}
|
|
4149
4152
|
}
|
|
4153
|
+
// Highlighted summary so noPublish (and other surprises) don't slip past unnoticed
|
|
4154
|
+
const finalPkg2 = readPackageJson(cwd);
|
|
4155
|
+
const surprises = [];
|
|
4156
|
+
const fromConfig = (k) => k in configOptions ? ' (from .globalize.json5)' : '';
|
|
4157
|
+
surprises.push(`noPublish=true${fromConfig('noPublish')} — nothing was published; clear with -publish`);
|
|
4158
|
+
if (configOptions.forcePublish || forcePublish)
|
|
4159
|
+
surprises.push(`forcePublish=true${fromConfig('forcePublish')}`);
|
|
4160
|
+
if (configOptions.publishDeps === false || publishDeps === false)
|
|
4161
|
+
surprises.push(`publishDeps=false${fromConfig('publishDeps')} — file: deps NOT republished`);
|
|
4162
|
+
if (configOptions.usePaths === false || usePaths === false)
|
|
4163
|
+
surprises.push(`usePaths=false${fromConfig('usePaths')} — file: deps resolved from npm, not siblings`);
|
|
4164
|
+
if (configOptions.freeze || freeze)
|
|
4165
|
+
surprises.push(`freeze=true${fromConfig('freeze')}`);
|
|
4166
|
+
if (configOptions.local || local)
|
|
4167
|
+
surprises.push(`local=true${fromConfig('local')}`);
|
|
4168
|
+
if (configOptions.files === false || files === false)
|
|
4169
|
+
surprises.push(`files=false${fromConfig('files')} — npm versions left in package.json`);
|
|
4170
|
+
if (configOptions.allowTs === true || allowTs === true)
|
|
4171
|
+
surprises.push(`allowTs=true${fromConfig('allowTs')} — .ts source kept in tarball`);
|
|
4172
|
+
console.log('');
|
|
4173
|
+
console.log(colors.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
4174
|
+
console.log(colors.yellow('! Transform Summary (NO PUBLISH)'));
|
|
4175
|
+
console.log(colors.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
4176
|
+
console.log(` Package: ${colors.green(finalPkg2.name)}`);
|
|
4177
|
+
console.log(` Version: ${colors.green('v' + finalPkg2.version)}`);
|
|
4178
|
+
console.log(` Published: ${colors.red('✗')}`);
|
|
4179
|
+
for (const s of surprises)
|
|
4180
|
+
console.log(` ${colors.yellow('!')} ${s}`);
|
|
4181
|
+
console.log(colors.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
4182
|
+
console.log('');
|
|
4150
4183
|
return true;
|
|
4151
4184
|
}
|
|
4152
4185
|
// Skip if private
|
|
@@ -4244,11 +4277,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
4244
4277
|
const pkgName = pkg.name;
|
|
4245
4278
|
const pkgVersion = pkg.version;
|
|
4246
4279
|
if (!pkg.bin && (install || link || wsl)) {
|
|
4247
|
-
|
|
4248
|
-
if (!proceed) {
|
|
4249
|
-
console.log(colors.yellow('Skipping global install — library packages should not be installed globally.'));
|
|
4250
|
-
console.log(colors.yellow(`To use in projects: npm install ${pkgName}`));
|
|
4251
|
-
}
|
|
4280
|
+
console.log(colors.dim(` ${pkgName}: library — skipping global install`));
|
|
4252
4281
|
}
|
|
4253
4282
|
if (pkg.bin && (install || link || wsl)) {
|
|
4254
4283
|
if (link) {
|
|
@@ -5044,11 +5073,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
5044
5073
|
let globalInstallOk = false;
|
|
5045
5074
|
let wslInstallOk = false;
|
|
5046
5075
|
if (!updatedPkg.bin && (install || link || wsl)) {
|
|
5047
|
-
|
|
5048
|
-
if (!proceed) {
|
|
5049
|
-
console.log(colors.yellow('Skipping global install — library packages should not be installed globally.'));
|
|
5050
|
-
console.log(colors.yellow(`To use in projects: npm install ${pkgName}`));
|
|
5051
|
-
}
|
|
5076
|
+
console.log(colors.dim(` ${pkgName}: library — skipping global install`));
|
|
5052
5077
|
}
|
|
5053
5078
|
if (updatedPkg.bin && (install || link || wsl)) {
|
|
5054
5079
|
if (link) {
|
|
@@ -5092,8 +5117,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
5092
5117
|
else {
|
|
5093
5118
|
console.log(`${timestamp()} Installing globally from registry: ${pkgName}@${pkgVersion}...`);
|
|
5094
5119
|
if (!dryRun) {
|
|
5095
|
-
waitForNpmVersion(pkgName, pkgVersion);
|
|
5096
|
-
const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd);
|
|
5120
|
+
waitForNpmVersion(pkgName, pkgVersion, wasNewPackage);
|
|
5121
|
+
const installResult = installGlobalWithRetry(`${pkgName}@${pkgVersion}`, cwd, wasNewPackage);
|
|
5097
5122
|
if (installResult.success) {
|
|
5098
5123
|
globalInstallOk = true;
|
|
5099
5124
|
console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
|
|
@@ -5122,7 +5147,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
5122
5147
|
const useLocalWsl = link || !!updatedPkg.workspaces;
|
|
5123
5148
|
const wslArgs = useLocalWsl ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
|
|
5124
5149
|
if (!useLocalWsl)
|
|
5125
|
-
waitForNpmVersion(pkgName, pkgVersion);
|
|
5150
|
+
waitForNpmVersion(pkgName, pkgVersion, wasNewPackage);
|
|
5126
5151
|
console.log(`Installing in WSL${useLocalWsl ? ' (local)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
|
|
5127
5152
|
if (!dryRun) {
|
|
5128
5153
|
const wslResult = installInWsl(wslArgs, { cwd });
|
|
@@ -5208,6 +5233,23 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
5208
5233
|
if (files && transformResult.transformed) {
|
|
5209
5234
|
console.log(` Restored file: deps: ${colors.green('✓')}`);
|
|
5210
5235
|
}
|
|
5236
|
+
// Surface non-default settings the user may have forgotten about
|
|
5237
|
+
{
|
|
5238
|
+
const surprises = [];
|
|
5239
|
+
const fromConfig = (k) => k in configOptions ? ' (from .globalize.json5)' : '';
|
|
5240
|
+
if (configOptions.forcePublish || forcePublish)
|
|
5241
|
+
surprises.push(`forcePublish=true${fromConfig('forcePublish')}`);
|
|
5242
|
+
if (configOptions.publishDeps === false || publishDeps === false)
|
|
5243
|
+
surprises.push(`publishDeps=false${fromConfig('publishDeps')} — file: deps NOT republished`);
|
|
5244
|
+
if (configOptions.usePaths === false || usePaths === false)
|
|
5245
|
+
surprises.push(`usePaths=false${fromConfig('usePaths')} — file: deps resolved from npm, not siblings`);
|
|
5246
|
+
if (configOptions.files === false || files === false)
|
|
5247
|
+
surprises.push(`files=false${fromConfig('files')} — npm versions left in package.json`);
|
|
5248
|
+
if (configOptions.allowTs === true || allowTs === true)
|
|
5249
|
+
surprises.push(`allowTs=true${fromConfig('allowTs')} — .ts source kept in tarball`);
|
|
5250
|
+
for (const s of surprises)
|
|
5251
|
+
console.log(` ${colors.yellow('!')} ${s}`);
|
|
5252
|
+
}
|
|
5211
5253
|
console.log(colors.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
5212
5254
|
console.log('');
|
|
5213
5255
|
// Only show "To use run" message if package provides commands (has bin field)
|
|
@@ -5237,6 +5279,26 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
|
|
|
5237
5279
|
console.log(`Packages (${packages.length}): ${packages.map(p => p.name).join(', ')}`);
|
|
5238
5280
|
console.log(`Publish order: ${publishOrder.join(' → ')}`);
|
|
5239
5281
|
console.log('');
|
|
5282
|
+
// Warn if -local / -install are present at the workspace root: those are
|
|
5283
|
+
// component-level concerns. In workspace mode they only act on members
|
|
5284
|
+
// that have a `bin` field; libraries are silently skipped. Telling the
|
|
5285
|
+
// user up front avoids the surprise of "I asked for install but most
|
|
5286
|
+
// packages didn't install."
|
|
5287
|
+
const installSources = [];
|
|
5288
|
+
if (options.local || configOptions.local) {
|
|
5289
|
+
const src = configOptions.local && !options.local ? '.globalize.json5' : 'CLI';
|
|
5290
|
+
installSources.push(`-local (${src})`);
|
|
5291
|
+
}
|
|
5292
|
+
if (options.install || configOptions.install) {
|
|
5293
|
+
const src = configOptions.install && !options.install ? '.globalize.json5' : 'CLI';
|
|
5294
|
+
installSources.push(`-install (${src})`);
|
|
5295
|
+
}
|
|
5296
|
+
if (installSources.length > 0) {
|
|
5297
|
+
console.log(colors.yellow(`! ${installSources.join(', ')} at workspace root — these are component-level flags.`));
|
|
5298
|
+
console.log(colors.yellow(` Only members with a \`bin\` field will install globally; libraries are skipped.`));
|
|
5299
|
+
console.log(colors.yellow(` For per-component control, run npmglobalize inside the component directory.`));
|
|
5300
|
+
console.log('');
|
|
5301
|
+
}
|
|
5240
5302
|
const rootPkg = readPackageJson(rootDir);
|
|
5241
5303
|
// Handle --cleanup: restore deps for all packages and return
|
|
5242
5304
|
if (options.cleanup) {
|
|
@@ -5380,13 +5442,14 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
|
|
|
5380
5442
|
}
|
|
5381
5443
|
}
|
|
5382
5444
|
}
|
|
5445
|
+
const relPath = path.relative(rootDir, pkgInfo.dir).split(path.sep).join('/') || '.';
|
|
5383
5446
|
if (reason) {
|
|
5384
5447
|
flaggedForWork.add(pkgName);
|
|
5385
|
-
console.log(` ${colors.yellow('⟳')} ${pkgName} — ${reason}`);
|
|
5448
|
+
console.log(` ${colors.yellow('⟳')} ${pkgName} — ${reason} ${colors.dim(relPath)}`);
|
|
5386
5449
|
}
|
|
5387
5450
|
else {
|
|
5388
5451
|
skipReasons.set(pkgName, 'clean, published, build fresh');
|
|
5389
|
-
console.log(` ${colors.green('✓')} ${pkgName} — skip (clean, published, build fresh)`);
|
|
5452
|
+
console.log(` ${colors.green('✓')} ${pkgName} — skip (clean, published, build fresh) ${colors.dim(relPath)}`);
|
|
5390
5453
|
}
|
|
5391
5454
|
}
|
|
5392
5455
|
console.log('');
|