@bobfrankston/npmglobalize 1.0.14 → 1.0.19
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/lib.d.ts +1 -0
- package/lib.js +76 -58
- package/package.json +1 -1
package/lib.d.ts
CHANGED
package/lib.js
CHANGED
|
@@ -213,13 +213,13 @@ export function hasBackup(pkg) {
|
|
|
213
213
|
}
|
|
214
214
|
/** Run a command and return success status */
|
|
215
215
|
export function runCommand(cmd, args, options = {}) {
|
|
216
|
-
const { silent = false, cwd } = options;
|
|
216
|
+
const { silent = false, cwd, shell = false } = options;
|
|
217
217
|
try {
|
|
218
218
|
const result = spawnSync(cmd, args, {
|
|
219
219
|
encoding: 'utf-8',
|
|
220
220
|
stdio: silent ? 'pipe' : 'inherit',
|
|
221
221
|
cwd,
|
|
222
|
-
shell
|
|
222
|
+
shell // Use shell when explicitly requested (e.g., for npm publish on Windows)
|
|
223
223
|
});
|
|
224
224
|
// For non-silent commands, we can't capture output when using 'inherit'
|
|
225
225
|
// So we return empty string for output, but the user sees it in the terminal
|
|
@@ -993,69 +993,85 @@ export async function globalize(cwd, options = {}) {
|
|
|
993
993
|
}
|
|
994
994
|
// Publish
|
|
995
995
|
console.log('Publishing to npm...');
|
|
996
|
-
const npmArgs = ['publish'];
|
|
997
|
-
if (quiet) {
|
|
998
|
-
npmArgs.push('--quiet');
|
|
999
|
-
}
|
|
1000
996
|
if (!dryRun) {
|
|
1001
|
-
//
|
|
1002
|
-
const
|
|
1003
|
-
if (!
|
|
1004
|
-
console.error(colors.red('
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
997
|
+
// Create tarball first
|
|
998
|
+
const packResult = runCommand('npm', ['pack'], { cwd, silent: true, shell: true });
|
|
999
|
+
if (!packResult.success) {
|
|
1000
|
+
console.error(colors.red('ERROR: Failed to create package tarball'));
|
|
1001
|
+
if (packResult.stderr)
|
|
1002
|
+
console.error(packResult.stderr);
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
// Get the tarball filename from npm pack output
|
|
1006
|
+
const tarballName = packResult.output.trim().split('\n').pop()?.trim();
|
|
1007
|
+
if (!tarballName) {
|
|
1008
|
+
console.error(colors.red('ERROR: Could not determine tarball filename'));
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
const tarballPath = path.join(cwd, tarballName);
|
|
1012
|
+
if (verbose) {
|
|
1013
|
+
console.log(`Created tarball: ${tarballName}`);
|
|
1014
|
+
}
|
|
1015
|
+
// Publish the tarball
|
|
1016
|
+
const npmArgs = ['publish', tarballName];
|
|
1017
|
+
if (npmVisibility === 'public') {
|
|
1018
|
+
npmArgs.push('--access', 'public');
|
|
1019
|
+
}
|
|
1020
|
+
if (quiet) {
|
|
1021
|
+
npmArgs.push('--quiet');
|
|
1022
|
+
}
|
|
1023
|
+
// Retry logic for E409 conflicts (publishing too fast)
|
|
1024
|
+
const maxRetries = 12; // 12 attempts * 5 seconds = 60 seconds total
|
|
1025
|
+
const retryDelay = 5; // 5 seconds between attempts
|
|
1026
|
+
let publishResult;
|
|
1027
|
+
let attempt = 0;
|
|
1028
|
+
while (attempt < maxRetries) {
|
|
1029
|
+
if (attempt > 0) {
|
|
1030
|
+
console.log(colors.yellow(`⏱ Waiting ${retryDelay} seconds before retry (attempt ${attempt + 1}/${maxRetries})...`));
|
|
1031
|
+
await new Promise(resolve => setTimeout(resolve, retryDelay * 1000));
|
|
1029
1032
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1033
|
+
publishResult = runCommand('npm', npmArgs, { cwd, silent: true, shell: true });
|
|
1034
|
+
if (publishResult.success) {
|
|
1035
|
+
break; // Success!
|
|
1036
|
+
}
|
|
1037
|
+
// Check if it's an E409 error
|
|
1038
|
+
const output = (publishResult.output + '\n' + publishResult.stderr).toLowerCase();
|
|
1039
|
+
const isE409 = output.includes('e409') || output.includes('409 conflict');
|
|
1040
|
+
if (!isE409) {
|
|
1041
|
+
break; // Not an E409, don't retry
|
|
1042
|
+
}
|
|
1043
|
+
if (attempt === 0) {
|
|
1044
|
+
console.log(colors.yellow('⚠ npm is still processing the previous version, retrying...'));
|
|
1045
|
+
}
|
|
1046
|
+
attempt++;
|
|
1047
|
+
}
|
|
1048
|
+
// Clean up tarball
|
|
1049
|
+
try {
|
|
1050
|
+
fs.unlinkSync(tarballPath);
|
|
1051
|
+
if (verbose) {
|
|
1052
|
+
console.log(`Cleaned up tarball: ${tarballName}`);
|
|
1038
1053
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1054
|
+
}
|
|
1055
|
+
catch (e) {
|
|
1056
|
+
// Ignore cleanup errors
|
|
1057
|
+
}
|
|
1058
|
+
if (!publishResult.success) {
|
|
1059
|
+
console.error(colors.red('\nERROR: npm publish failed\n'));
|
|
1060
|
+
// Check for E409 conflict (publishing too fast)
|
|
1061
|
+
const output = (publishResult.output + '\n' + publishResult.stderr).toLowerCase();
|
|
1062
|
+
if (output.includes('e409') || output.includes('409 conflict')) {
|
|
1063
|
+
console.error(colors.yellow('⚠ Publishing too quickly'));
|
|
1041
1064
|
console.error('');
|
|
1042
|
-
console.error('
|
|
1043
|
-
console.error('
|
|
1065
|
+
console.error('npm is still processing the previous version after multiple retries.');
|
|
1066
|
+
console.error(colors.green('Solution: Wait a few more minutes and try again'));
|
|
1044
1067
|
console.error('');
|
|
1045
1068
|
}
|
|
1046
1069
|
else {
|
|
1047
|
-
// Show the actual error output
|
|
1048
|
-
if (publishResult.stderr) {
|
|
1049
|
-
console.error(publishResult.stderr);
|
|
1050
|
-
}
|
|
1051
|
-
if (publishResult.output) {
|
|
1052
|
-
console.error(publishResult.output);
|
|
1053
|
-
}
|
|
1054
|
-
console.error('');
|
|
1055
1070
|
console.error(colors.yellow('Common causes:'));
|
|
1056
1071
|
console.error(colors.yellow(' 1. Not logged in - run: npm login'));
|
|
1057
1072
|
console.error(colors.yellow(' 2. Version already published'));
|
|
1058
1073
|
console.error(colors.yellow(' 3. Authentication token expired'));
|
|
1074
|
+
console.error('');
|
|
1059
1075
|
}
|
|
1060
1076
|
if (transformed) {
|
|
1061
1077
|
console.log('Run --cleanup to restore file: dependencies');
|
|
@@ -1084,7 +1100,8 @@ export async function globalize(cwd, options = {}) {
|
|
|
1084
1100
|
if (install) {
|
|
1085
1101
|
console.log(`Installing globally: ${pkgName}@${pkgVersion}...`);
|
|
1086
1102
|
if (!dryRun) {
|
|
1087
|
-
|
|
1103
|
+
// Install from local directory (faster and works immediately after publish)
|
|
1104
|
+
const installResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, shell: true });
|
|
1088
1105
|
if (installResult.success) {
|
|
1089
1106
|
// Verify installation by checking if command exists
|
|
1090
1107
|
const verifyResult = runCommand('npm', ['list', '-g', '--depth=0', pkgName], { cwd, silent: true });
|
|
@@ -1097,17 +1114,18 @@ export async function globalize(cwd, options = {}) {
|
|
|
1097
1114
|
}
|
|
1098
1115
|
else {
|
|
1099
1116
|
console.error(colors.red(`✗ Global install failed`));
|
|
1100
|
-
console.error(colors.yellow(' Try running manually: npm install -g '
|
|
1117
|
+
console.error(colors.yellow(' Try running manually: npm install -g .'));
|
|
1101
1118
|
}
|
|
1102
1119
|
}
|
|
1103
1120
|
else {
|
|
1104
|
-
console.log(` [dry-run] Would run: npm install -g
|
|
1121
|
+
console.log(` [dry-run] Would run: npm install -g .`);
|
|
1105
1122
|
}
|
|
1106
1123
|
}
|
|
1107
1124
|
if (wsl) {
|
|
1108
1125
|
console.log(`Installing in WSL: ${pkgName}@${pkgVersion}...`);
|
|
1109
1126
|
if (!dryRun) {
|
|
1110
|
-
|
|
1127
|
+
// Install from local directory in WSL
|
|
1128
|
+
const wslResult = runCommand('wsl', ['npm', 'install', '-g', '.'], { cwd, silent: false });
|
|
1111
1129
|
if (wslResult.success) {
|
|
1112
1130
|
// Verify WSL installation
|
|
1113
1131
|
const verifyResult = runCommand('wsl', ['npm', 'list', '-g', '--depth=0', pkgName], { cwd, silent: true });
|