@bobfrankston/npmglobalize 1.0.53 → 1.0.61

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 CHANGED
@@ -10,19 +10,28 @@ import { styleText } from 'util';
10
10
  import JSON5 from 'json5';
11
11
  // Check if JS files are up-to-date with TS files
12
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
- const libTsPath = path.join(__dirname, 'lib.ts');
14
- const libJsPath = path.join(__dirname, 'lib.js');
15
- if (fs.existsSync(libTsPath) && fs.existsSync(libJsPath)) {
16
- const tsStat = fs.statSync(libTsPath);
17
- const jsStat = fs.statSync(libJsPath);
18
- if (jsStat.mtime < tsStat.mtime && !process.argv.includes('--force')) {
19
- console.error('\n' + styleText('red', '❌ Build check failed:'));
20
- console.error(styleText('red', ' lib.js is outdated (older than lib.ts)'));
21
- console.error('\n' + styleText('yellow', ' Please run: tsc'));
22
- console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
23
- process.exit(1);
13
+ // Check all .ts files in the directory
14
+ const tsFiles = ['lib.ts', 'cli.ts', 'index.ts'];
15
+ const outOfSync = [];
16
+ for (const tsFile of tsFiles) {
17
+ const tsPath = path.join(__dirname, tsFile);
18
+ const jsPath = path.join(__dirname, tsFile.replace('.ts', '.js'));
19
+ if (fs.existsSync(tsPath) && fs.existsSync(jsPath)) {
20
+ const tsStat = fs.statSync(tsPath);
21
+ const jsStat = fs.statSync(jsPath);
22
+ if (jsStat.mtime < tsStat.mtime) {
23
+ outOfSync.push(tsFile);
24
+ }
24
25
  }
25
26
  }
27
+ if (outOfSync.length > 0 && !process.argv.includes('--force')) {
28
+ console.error('\n' + styleText('red', '❌ Build check failed:'));
29
+ console.error(styleText('red', ` ${outOfSync.length} file(s) need compilation:`));
30
+ outOfSync.forEach(f => console.error(styleText('red', ` - ${f}`)));
31
+ console.error('\n' + styleText('yellow', ' Please run: tsc'));
32
+ console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
33
+ process.exit(1);
34
+ }
26
35
  function printHelp() {
27
36
  console.log(`
28
37
  npmglobalize - Transform file: dependencies to npm versions for publishing
package/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * npmglobalize - Main entry point
4
+ * Test comment 3
4
5
  */
5
6
  import './cli.js';
6
7
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * npmglobalize - Main entry point
4
+ * Test comment 3
4
5
  */
5
6
  import './cli.js';
6
7
  import { main } from './cli.js';
package/lib.d.ts CHANGED
@@ -119,7 +119,6 @@ export declare function fixVersionTagMismatch(cwd: string, pkg: any, verbose?: b
119
119
  export declare function runCommand(cmd: string, args: string[], options?: {
120
120
  silent?: boolean;
121
121
  cwd?: string;
122
- shell?: boolean;
123
122
  }): {
124
123
  success: boolean;
125
124
  output: string;
package/lib.js CHANGED
@@ -17,6 +17,10 @@ const colors = {
17
17
  italic: (text) => styleText('italic', text),
18
18
  dim: (text) => styleText('dim', text),
19
19
  };
20
+ /** Get npm command for current platform (npm.cmd on Windows, npm elsewhere) */
21
+ function getNpmCommand() {
22
+ return process.platform === 'win32' ? 'npm.cmd' : 'npm';
23
+ }
20
24
  const DEP_KEYS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
21
25
  /** Read and parse package.json from a directory */
22
26
  export function readPackageJson(dir) {
@@ -145,8 +149,7 @@ export function getLatestVersion(packageName) {
145
149
  try {
146
150
  const result = spawnSync('npm', ['view', packageName, 'version'], {
147
151
  encoding: 'utf-8',
148
- stdio: 'pipe',
149
- shell: true
152
+ stdio: 'pipe'
150
153
  });
151
154
  if (result.status === 0 && result.stdout) {
152
155
  return result.stdout.trim();
@@ -162,8 +165,7 @@ export function checkVersionExists(packageName, version) {
162
165
  try {
163
166
  const result = spawnSync('npm', ['view', `${packageName}@${version}`, 'version'], {
164
167
  encoding: 'utf-8',
165
- stdio: 'pipe',
166
- shell: true
168
+ stdio: 'pipe'
167
169
  });
168
170
  return result.status === 0 && result.stdout.trim() === version;
169
171
  }
@@ -176,8 +178,7 @@ export function checkPackageExists(packageName) {
176
178
  try {
177
179
  const result = spawnSync('npm', ['view', packageName, 'version'], {
178
180
  encoding: 'utf-8',
179
- stdio: 'pipe',
180
- shell: true
181
+ stdio: 'pipe'
181
182
  });
182
183
  return result.status === 0 && result.stdout.trim().length > 0;
183
184
  }
@@ -190,8 +191,7 @@ export function checkNpmAccess(packageName) {
190
191
  try {
191
192
  const result = spawnSync('npm', ['view', packageName, '--json'], {
192
193
  encoding: 'utf-8',
193
- stdio: 'pipe',
194
- shell: true
194
+ stdio: 'pipe'
195
195
  });
196
196
  if (result.status === 0 && result.stdout) {
197
197
  const data = JSON.parse(result.stdout);
@@ -526,13 +526,21 @@ export function fixVersionTagMismatch(cwd, pkg, verbose = false) {
526
526
  }
527
527
  /** Run a command and return success status */
528
528
  export function runCommand(cmd, args, options = {}) {
529
- const { silent = false, cwd, shell = false } = options;
529
+ const { silent = false, cwd } = options;
530
530
  try {
531
+ // Only use shell:true for npm commands which need it on Windows
532
+ // Git and other commands work fine without shell
533
+ const needsShell = cmd === 'npm' || cmd === 'npm.cmd';
534
+ // Debug: log the command being executed
535
+ if (!silent) {
536
+ console.log(colors.dim(`[DEBUG] Running: ${cmd} ${args.join(' ')}`));
537
+ }
531
538
  const result = spawnSync(cmd, args, {
532
539
  encoding: 'utf-8',
533
540
  stdio: silent ? 'pipe' : 'inherit',
534
541
  cwd,
535
- shell // Use shell when explicitly requested (e.g., for npm publish on Windows)
542
+ env: process.env, // Always inherit environment variables
543
+ shell: needsShell // Only use shell for npm commands
536
544
  });
537
545
  // For non-silent commands, we can't capture output when using 'inherit'
538
546
  // So we return empty string for output, but the user sees it in the terminal
@@ -740,11 +748,13 @@ export async function promptChoice(message, choices) {
740
748
  /** Check npm authentication status */
741
749
  function checkNpmAuth() {
742
750
  try {
743
- // Use shell:true on Windows for better compatibility
751
+ // Must use shell:true on Windows to find npm.cmd in PATH
752
+ // Must pass env: process.env to inherit NPM_TOKEN environment variable
744
753
  const result = spawnSync('npm', ['whoami'], {
745
754
  encoding: 'utf-8',
746
- shell: true,
747
- stdio: ['ignore', 'pipe', 'pipe']
755
+ stdio: ['ignore', 'pipe', 'pipe'],
756
+ env: process.env,
757
+ shell: true
748
758
  });
749
759
  if (result.status === 0 && result.stdout && result.stdout.trim()) {
750
760
  return { authenticated: true, username: result.stdout.trim() };
@@ -1108,7 +1118,7 @@ export function runNpmAudit(cwd, fix = false, verbose = false) {
1108
1118
  console.log(colors.yellow('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
1109
1119
  if (fix) {
1110
1120
  console.log('Running npm audit fix...');
1111
- const fixResult = runCommand('npm', ['audit', 'fix'], { cwd, silent: false, shell: true });
1121
+ const fixResult = runCommand('npm', ['audit', 'fix'], { cwd, silent: false });
1112
1122
  if (!fixResult.success) {
1113
1123
  console.log(colors.yellow('⚠ Some vulnerabilities could not be automatically fixed'));
1114
1124
  }
@@ -1120,8 +1130,7 @@ export function runNpmAudit(cwd, fix = false, verbose = false) {
1120
1130
  const auditResult = spawnSync('npm', ['audit', '--json'], {
1121
1131
  cwd,
1122
1132
  encoding: 'utf-8',
1123
- stdio: 'pipe',
1124
- shell: true
1133
+ stdio: 'pipe'
1125
1134
  });
1126
1135
  let hasVulnerabilities = false;
1127
1136
  let report = '';
@@ -1175,7 +1184,7 @@ export function runNpmAudit(cwd, fix = false, verbose = false) {
1175
1184
  catch (e) {
1176
1185
  // Fallback to text output if JSON parsing fails
1177
1186
  console.log('Running text audit...');
1178
- const textResult = runCommand('npm', ['audit'], { cwd, silent: false, shell: true });
1187
+ const textResult = runCommand('npm', ['audit'], { cwd, silent: false });
1179
1188
  report = 'Audit completed (see output above)';
1180
1189
  }
1181
1190
  }
@@ -1332,39 +1341,6 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
1332
1341
  }
1333
1342
  return true;
1334
1343
  }
1335
- // Check npm authentication early (unless dry-run or no-publish)
1336
- if (!dryRun && !noPublish) {
1337
- const authStatus = checkNpmAuth();
1338
- if (!authStatus.authenticated) {
1339
- console.error(colors.red('\n✗ npm authentication required'));
1340
- console.error('');
1341
- if (authStatus.error === 'token expired') {
1342
- console.error('Your npm access token has expired or been revoked.');
1343
- console.error('');
1344
- console.error('To fix this, run:');
1345
- console.error(colors.yellow(' npm logout'));
1346
- console.error(colors.yellow(' npm login'));
1347
- }
1348
- else if (authStatus.error === 'not logged in') {
1349
- console.error('You are not logged in to npm.');
1350
- console.error('');
1351
- console.error('To fix this, run:');
1352
- console.error(colors.yellow(' npm login'));
1353
- }
1354
- else {
1355
- console.error(`Authentication error: ${authStatus.error}`);
1356
- console.error('');
1357
- console.error('Try running:');
1358
- console.error(colors.yellow(' npm whoami'));
1359
- }
1360
- console.error('');
1361
- console.error('After logging in, try running this command again.');
1362
- return false;
1363
- }
1364
- if (verbose) {
1365
- console.log(colors.green(`✓ Authenticated as ${authStatus.username}`));
1366
- }
1367
- }
1368
1344
  // Check git status
1369
1345
  const gitStatus = getGitStatus(cwd);
1370
1346
  // Handle init mode
@@ -1396,7 +1372,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
1396
1372
  return false;
1397
1373
  }
1398
1374
  // Re-check git status after potential init
1399
- const currentGitStatus = getGitStatus(cwd);
1375
+ let currentGitStatus = getGitStatus(cwd);
1400
1376
  // Validate git state
1401
1377
  if (currentGitStatus.hasMergeConflict) {
1402
1378
  console.error(colors.red('ERROR: Merge conflict detected. Resolve before releasing.'));
@@ -1743,89 +1719,44 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
1743
1719
  console.log('Package is private - skipping npm publish.');
1744
1720
  return true;
1745
1721
  }
1722
+ // Re-check git status after all transformations and potential commits
1723
+ currentGitStatus = getGitStatus(cwd);
1746
1724
  // Check if there are changes to commit or a custom message
1747
1725
  if (!currentGitStatus.hasUncommitted && !message) {
1748
1726
  console.log('');
1749
1727
  console.log('No changes to commit and no custom message specified.');
1750
- // If install flag is set, verify/install even without publishing
1728
+ // If install flag is set, install from local directory
1751
1729
  if (install || wsl) {
1752
1730
  if (verbose) {
1753
1731
  console.log('');
1754
- console.log('Checking global installation...');
1732
+ console.log('Installing from local directory...');
1755
1733
  }
1756
1734
  const pkgName = pkg.name;
1757
1735
  if (install) {
1758
- const verifyResult = runCommand('npm', ['list', '-g', '--depth=0', pkgName], { cwd, silent: true });
1759
- if (verifyResult.success) {
1760
- console.log(colors.green(`✓ Already installed globally: ${pkgName}`));
1736
+ console.log(`Installing ${pkgName} globally from local directory...`);
1737
+ const localInstallResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false });
1738
+ if (localInstallResult.success) {
1739
+ const version = pkg.version;
1740
+ console.log(colors.green(`✓ Installed globally: ${pkgName}@${version}`));
1761
1741
  }
1762
1742
  else {
1763
- console.log(colors.yellow(`Package not installed globally. Installing latest version...`));
1764
- // First try installing from npm registry
1765
- const installResult = runCommand('npm', ['install', '-g', `${pkgName}@latest`], { cwd, silent: false });
1766
- if (installResult.success) {
1767
- const reVerify = runCommand('npm', ['list', '-g', '--depth=0', pkgName], { cwd, silent: true });
1768
- if (reVerify.success) {
1769
- const version = pkg.version;
1770
- console.log(colors.green(`✓ Installed and verified globally: ${pkgName}@${version}`));
1771
- }
1772
- else {
1773
- console.log(colors.yellow(`⚠ Install appeared successful but verification failed`));
1774
- }
1775
- }
1776
- else {
1777
- // If npm install fails, try installing from local directory
1778
- console.log(colors.yellow(`Could not install from npm. Trying local installation...`));
1779
- const localInstallResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, shell: true });
1780
- if (localInstallResult.success) {
1781
- const version = pkg.version;
1782
- console.log(colors.green(`✓ Installed globally from local: ${pkgName}@${version}`));
1783
- }
1784
- else {
1785
- console.error(colors.red(`✗ Global install failed`));
1786
- console.error(colors.yellow(' Try running manually: npm install -g .'));
1787
- }
1788
- }
1743
+ console.error(colors.red(`✗ Global install failed`));
1744
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
1789
1745
  }
1790
1746
  }
1791
1747
  if (wsl) {
1792
- const verifyResult = runCommand('wsl', ['npm', 'list', '-g', '--depth=0', pkgName], { cwd, silent: true });
1793
- if (verifyResult.success) {
1794
- console.log(colors.green(`✓ Already installed in WSL: ${pkgName}`));
1748
+ console.log(`Installing ${pkgName} in WSL from local directory...`);
1749
+ const wslInstallResult = runCommand('wsl', ['npm', 'install', '-g', '.'], { cwd, silent: false });
1750
+ if (wslInstallResult.success) {
1751
+ const version = pkg.version;
1752
+ console.log(colors.green(`✓ Installed in WSL: ${pkgName}@${version}`));
1795
1753
  }
1796
1754
  else {
1797
- console.log(colors.yellow(`Package not installed in WSL. Installing latest version...`));
1798
- // First try installing from npm registry
1799
- const wslInstallResult = runCommand('wsl', ['npm', 'install', '-g', `${pkgName}@latest`], { cwd, silent: false });
1800
- if (wslInstallResult.success) {
1801
- const reVerify = runCommand('wsl', ['npm', 'list', '-g', '--depth=0', pkgName], { cwd, silent: true });
1802
- if (reVerify.success) {
1803
- const version = pkg.version;
1804
- console.log(colors.green(`✓ Installed and verified in WSL: ${pkgName}@${version}`));
1805
- }
1806
- else {
1807
- console.log(colors.yellow(`⚠ WSL install appeared successful but verification failed`));
1808
- }
1809
- }
1810
- else {
1811
- // If npm install fails, try installing from local directory
1812
- console.log(colors.yellow(`Could not install from npm. Trying local installation in WSL...`));
1813
- const localWslInstallResult = runCommand('wsl', ['npm', 'install', '-g', '.'], { cwd, silent: false });
1814
- if (localWslInstallResult.success) {
1815
- const version = pkg.version;
1816
- console.log(colors.green(`✓ Installed in WSL from local: ${pkgName}@${version}`));
1817
- }
1818
- else {
1819
- console.error(colors.yellow('✗ WSL install failed (is npm installed in WSL?)'));
1820
- console.error(colors.yellow(' Try running manually: wsl npm install -g .'));
1821
- }
1822
- }
1755
+ console.error(colors.red(`✗ WSL install failed`));
1756
+ console.error(colors.yellow(' Try running manually in WSL: npm install -g .'));
1823
1757
  }
1824
1758
  }
1825
- console.log('');
1826
- return true;
1827
1759
  }
1828
- console.log('Nothing to release. Use -m "message" to force a release.');
1829
1760
  return true;
1830
1761
  }
1831
1762
  // Ensure node_modules is in .gitignore before any git operations
@@ -2018,18 +1949,50 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2018
1949
  // Publish
2019
1950
  console.log('Publishing to npm...');
2020
1951
  if (!dryRun) {
1952
+ // Check npm authentication right before publishing
1953
+ const authStatus = checkNpmAuth();
1954
+ if (!authStatus.authenticated) {
1955
+ console.error(colors.red('ERROR: npm authentication required'));
1956
+ console.error('');
1957
+ if (authStatus.error === 'token expired') {
1958
+ console.error('Your npm access token has expired or been revoked.');
1959
+ console.error('');
1960
+ console.error('To fix this, run:');
1961
+ console.error(colors.yellow(' npm logout'));
1962
+ console.error(colors.yellow(' npm login'));
1963
+ }
1964
+ else if (authStatus.error === 'not logged in') {
1965
+ console.error('You are not logged in to npm.');
1966
+ console.error('');
1967
+ console.error('To fix this, run:');
1968
+ console.error(colors.yellow(' npm login'));
1969
+ }
1970
+ else {
1971
+ console.error(`Authentication error: ${authStatus.error}`);
1972
+ console.error('');
1973
+ console.error('Try running:');
1974
+ console.error(colors.yellow(' npm whoami'));
1975
+ }
1976
+ console.error('');
1977
+ console.error('After logging in, try running this command again.');
1978
+ return false;
1979
+ }
1980
+ if (verbose) {
1981
+ console.log(colors.green(`✓ Authenticated as ${authStatus.username}`));
1982
+ }
2021
1983
  // Create tarball first
2022
- const packResult = runCommand('npm', ['pack'], { cwd, silent: true, shell: true });
1984
+ const packResult = runCommand('npm', ['pack'], { cwd, silent: true });
2023
1985
  if (!packResult.success) {
2024
1986
  console.error(colors.red('ERROR: Failed to create package tarball'));
2025
- if (packResult.stderr)
2026
- console.error(packResult.stderr);
1987
+ console.error(colors.yellow('Output:'), packResult.output);
1988
+ console.error(colors.yellow('Error:'), packResult.stderr);
2027
1989
  return false;
2028
1990
  }
2029
1991
  // Get the tarball filename from npm pack output
2030
1992
  const tarballName = packResult.output.trim().split('\n').pop()?.trim();
2031
1993
  if (!tarballName) {
2032
1994
  console.error(colors.red('ERROR: Could not determine tarball filename'));
1995
+ console.error(colors.yellow('npm pack output:'), packResult.output);
2033
1996
  return false;
2034
1997
  }
2035
1998
  const tarballPath = path.join(cwd, tarballName);
@@ -2068,7 +2031,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2068
2031
  console.log(colors.yellow(`⏱ Waiting ${retryDelay} seconds before retry (attempt ${attempt + 1}/${maxRetries})...`));
2069
2032
  await new Promise(resolve => setTimeout(resolve, retryDelay * 1000));
2070
2033
  }
2071
- publishResult = runCommand('npm', npmArgs, { cwd, silent: true, shell: true });
2034
+ publishResult = runCommand('npm', npmArgs, { cwd, silent: true });
2072
2035
  if (publishResult.success) {
2073
2036
  break; // Success!
2074
2037
  }
@@ -2213,7 +2176,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2213
2176
  console.log(`Installing globally: ${pkgName}@${pkgVersion}...`);
2214
2177
  if (!dryRun) {
2215
2178
  // Install from local directory (faster and works immediately after publish)
2216
- const installResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false, shell: true });
2179
+ const installResult = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false });
2217
2180
  if (installResult.success) {
2218
2181
  console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
2219
2182
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.53",
3
+ "version": "1.0.61",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/nul DELETED
File without changes