@bobfrankston/npmglobalize 1.0.80 → 1.0.81

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 (4) hide show
  1. package/cli.js +51 -75
  2. package/lib.d.ts +2 -0
  3. package/lib.js +28 -1
  4. package/package.json +1 -1
package/cli.js CHANGED
@@ -5,41 +5,10 @@
5
5
  import { globalize, globalizeWorkspace, readConfig, readPackageJson, writeConfig, writePackageJson } from './lib.js';
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
- import { fileURLToPath } from 'url';
9
8
  import { styleText } from 'util';
10
9
  import JSON5 from 'json5';
11
- // Check if JS files are up-to-date with TS files
12
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
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
- }
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 in ${__dirname}:`));
30
- outOfSync.forEach(f => {
31
- const tsPath = path.join(__dirname, f);
32
- const jsPath = path.join(__dirname, f.replace('.ts', '.js'));
33
- const tsMtime = fs.statSync(tsPath).mtime;
34
- const jsMtime = fs.statSync(jsPath).mtime;
35
- const fmt = (d) => d.toLocaleString();
36
- console.error(styleText('red', ` - ${tsPath}`));
37
- console.error(styleText('red', ` .ts: ${fmt(tsMtime)} .js: ${fmt(jsMtime)}`));
38
- });
39
- console.error('\n' + styleText('yellow', ' Please run: tsc'));
40
- console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
41
- process.exit(1);
42
- }
10
+ // npmglobalize install directory (for --version)
11
+ const __dirname = import.meta.dirname;
43
12
  function printHelp() {
44
13
  console.log(`
45
14
  npmglobalize - Transform file: dependencies to npm versions for publishing
@@ -68,6 +37,7 @@ Install Options:
68
37
  --install, -i Global install after publish (from registry)
69
38
  --link Global install via symlink (npm install -g .)
70
39
  --wsl Also install globally in WSL
40
+ --once Don't persist flags to .globalize.json5
71
41
 
72
42
  Mode Options:
73
43
  --files Keep file: paths after publish (default)
@@ -300,6 +270,9 @@ function parseArgs(args) {
300
270
  case '-pkg':
301
271
  options.package = true;
302
272
  break;
273
+ case '--once':
274
+ options.once = true;
275
+ break;
303
276
  default:
304
277
  if (arg.startsWith('-')) {
305
278
  unrecognized.push(arg);
@@ -329,52 +302,11 @@ export async function main() {
329
302
  process.exit(0);
330
303
  }
331
304
  if (cliOptions.version) {
332
- const __filename = fileURLToPath(import.meta.url);
333
- const __dirname = path.dirname(__filename);
334
305
  const pkgPath = path.join(__dirname, 'package.json');
335
306
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
336
307
  console.log(pkg.version);
337
308
  process.exit(0);
338
309
  }
339
- // Check if TypeScript files are compiled (unless --force or --help/--version)
340
- if (!cliOptions.force && !cliOptions.help && !cliOptions.version) {
341
- const __filename = fileURLToPath(import.meta.url);
342
- const __dirname = path.dirname(__filename);
343
- // Check for noEmit in tsconfig.json
344
- let noEmit = false;
345
- try {
346
- const tsconfigPath = path.join(__dirname, 'tsconfig.json');
347
- const content = fs.readFileSync(tsconfigPath, 'utf-8');
348
- const tsconfig = JSON5.parse(content);
349
- noEmit = tsconfig.compilerOptions?.noEmit === true;
350
- }
351
- catch (error) {
352
- // If we can't read tsconfig, assume we need to check
353
- }
354
- if (!noEmit) {
355
- // Check if this .js file is older than its .ts source
356
- const jsFile = __filename;
357
- const tsFile = jsFile.replace(/\.js$/, '.ts');
358
- if (fs.existsSync(tsFile)) {
359
- if (!fs.existsSync(jsFile)) {
360
- console.error('\n❌ Error: TypeScript files not compiled');
361
- console.error(`Missing: ${path.basename(jsFile)}`);
362
- console.error('\nPlease run: npm run build');
363
- console.error('Or use --force to skip this check\n');
364
- process.exit(1);
365
- }
366
- const tsStat = fs.statSync(tsFile);
367
- const jsStat = fs.statSync(jsFile);
368
- if (jsStat.mtime < tsStat.mtime) {
369
- console.error('\n❌ Error: TypeScript files not compiled');
370
- console.error(`${path.basename(jsFile)} is older than ${path.basename(tsFile)}`);
371
- console.error('\nPlease run: npm run build');
372
- console.error('Or use --force to skip this check\n');
373
- process.exit(1);
374
- }
375
- }
376
- }
377
- }
378
310
  if (cliOptions.error) {
379
311
  console.error(`Error: ${cliOptions.error}`);
380
312
  console.error('Run with --help for usage.');
@@ -393,6 +325,50 @@ export async function main() {
393
325
  process.exit(1);
394
326
  }
395
327
  }
328
+ // Check if TypeScript files in target project are compiled
329
+ if (!cliOptions.force) {
330
+ let noEmit = false;
331
+ try {
332
+ const tsconfigPath = path.join(cwd, 'tsconfig.json');
333
+ const content = fs.readFileSync(tsconfigPath, 'utf-8');
334
+ const tsconfig = JSON5.parse(content);
335
+ noEmit = tsconfig.compilerOptions?.noEmit === true;
336
+ }
337
+ catch (error) {
338
+ // No tsconfig or can't parse — skip check
339
+ noEmit = true;
340
+ }
341
+ if (!noEmit) {
342
+ const outOfSync = [];
343
+ const jsFiles = fs.readdirSync(cwd).filter(f => f.endsWith('.js') && !f.endsWith('.min.js'));
344
+ for (const jsFile of jsFiles) {
345
+ const tsFile = jsFile.replace(/\.js$/, '.ts');
346
+ const tsPath = path.join(cwd, tsFile);
347
+ const jsPath = path.join(cwd, jsFile);
348
+ if (fs.existsSync(tsPath)) {
349
+ const tsStat = fs.statSync(tsPath);
350
+ const jsStat = fs.statSync(jsPath);
351
+ if (jsStat.mtime < tsStat.mtime) {
352
+ outOfSync.push(tsFile);
353
+ }
354
+ }
355
+ }
356
+ if (outOfSync.length > 0) {
357
+ console.error('\n' + styleText('red', '❌ Build check failed:'));
358
+ console.error(styleText('red', ` ${outOfSync.length} file(s) need compilation in ${cwd}:`));
359
+ outOfSync.forEach(f => {
360
+ const tsPath = path.join(cwd, f);
361
+ const jsPath = path.join(cwd, f.replace('.ts', '.js'));
362
+ const fmt = (d) => d.toLocaleString();
363
+ console.error(styleText('red', ` - ${f}`));
364
+ console.error(styleText('red', ` .ts: ${fmt(fs.statSync(tsPath).mtime)} .js: ${fmt(fs.statSync(jsPath).mtime)}`));
365
+ });
366
+ console.error('\n' + styleText('yellow', ' Please run: tsc'));
367
+ console.error(styleText('yellow', ' Or use --force to skip this check') + '\n');
368
+ process.exit(1);
369
+ }
370
+ }
371
+ }
396
372
  // Handle --package: update scripts in target package.json
397
373
  if (cliOptions.package) {
398
374
  const pkg = readPackageJson(cwd);
@@ -419,7 +395,7 @@ export async function main() {
419
395
  const configOptions = readConfig(cwd);
420
396
  const options = { ...configOptions, ...cliOptions };
421
397
  // Persist explicitly set CLI flags to .globalize.json5
422
- if (cliOptions.explicitKeys.size > 0) {
398
+ if (cliOptions.explicitKeys.size > 0 && !cliOptions.once) {
423
399
  const persistable = { ...configOptions };
424
400
  for (const key of cliOptions.explicitKeys) {
425
401
  persistable[key] = options[key];
package/lib.d.ts CHANGED
@@ -69,6 +69,8 @@ export interface GlobalizeOptions {
69
69
  continueOnError?: boolean;
70
70
  /** Update package.json scripts to use npmglobalize */
71
71
  package?: boolean;
72
+ /** Don't persist CLI flags to .globalize.json5 */
73
+ once?: boolean;
72
74
  /** Internal: signals this call is from workspace orchestrator */
73
75
  _fromWorkspace?: boolean;
74
76
  }
package/lib.js CHANGED
@@ -110,7 +110,7 @@ export function writeConfig(dir, config, explicitKeys) {
110
110
  const existing = readConfig(dir);
111
111
  // Filter out temporary flags and default values (unless explicitly set)
112
112
  const filtered = {};
113
- const omitKeys = new Set(['noPublish', 'cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish']);
113
+ const omitKeys = new Set(['noPublish', 'cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish', 'once']);
114
114
  for (const [key, value] of Object.entries(config)) {
115
115
  if (omitKeys.has(key))
116
116
  continue;
@@ -719,6 +719,27 @@ export function fixVersionTagMismatch(cwd, pkg, verbose = false) {
719
719
  }
720
720
  return deletedAny;
721
721
  }
722
+ /** Wait for a package version to appear on the npm registry */
723
+ function waitForNpmVersion(pkgName, version, maxWaitMs = 60000) {
724
+ const interval = 3000;
725
+ const maxAttempts = Math.ceil(maxWaitMs / interval);
726
+ process.stdout.write(`Waiting for ${pkgName}@${version} on npm registry`);
727
+ for (let i = 0; i < maxAttempts; i++) {
728
+ const result = spawnSync('npm', ['view', `${pkgName}@${version}`, 'version'], {
729
+ shell: process.platform === 'win32',
730
+ stdio: ['pipe', 'pipe', 'pipe'],
731
+ encoding: 'utf-8'
732
+ });
733
+ if (result.status === 0 && result.stdout?.trim() === version) {
734
+ process.stdout.write(' ready\n');
735
+ return true;
736
+ }
737
+ process.stdout.write('.');
738
+ spawnSync(process.platform === 'win32' ? 'timeout' : 'sleep', process.platform === 'win32' ? ['/t', '3', '/nobreak'] : ['3'], { stdio: 'pipe', shell: process.platform === 'win32' });
739
+ }
740
+ process.stdout.write(' timed out\n');
741
+ return false;
742
+ }
722
743
  /** Run a command and return success status */
723
744
  export function runCommand(cmd, args, options = {}) {
724
745
  const { silent = false, cwd } = options;
@@ -2053,6 +2074,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2053
2074
  }
2054
2075
  }
2055
2076
  else if (install) {
2077
+ waitForNpmVersion(pkgName, pkgVersion);
2056
2078
  console.log(`Installing ${pkgName}@${pkgVersion} globally from registry...`);
2057
2079
  const registryInstallResult = runCommand('npm', ['install', '-g', `${pkgName}@${pkgVersion}`], { cwd, silent: false });
2058
2080
  if (registryInstallResult.success) {
@@ -2065,6 +2087,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2065
2087
  }
2066
2088
  if (wsl) {
2067
2089
  const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
2090
+ if (!link && !install)
2091
+ waitForNpmVersion(pkgName, pkgVersion);
2068
2092
  console.log(`Installing ${pkgName} in WSL${link ? ' (link)' : ' from registry'}...`);
2069
2093
  const wslInstallResult = runCommand('wsl', wslArgs, { cwd, silent: false });
2070
2094
  if (wslInstallResult.success) {
@@ -2510,6 +2534,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2510
2534
  else if (install) {
2511
2535
  console.log(`Installing globally from registry: ${pkgName}@${pkgVersion}...`);
2512
2536
  if (!dryRun) {
2537
+ waitForNpmVersion(pkgName, pkgVersion);
2513
2538
  const installResult = runCommand('npm', ['install', '-g', `${pkgName}@${pkgVersion}`], { cwd, silent: false });
2514
2539
  if (installResult.success) {
2515
2540
  console.log(colors.green(`✓ Installed globally: ${pkgName}@${pkgVersion}`));
@@ -2525,6 +2550,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2525
2550
  }
2526
2551
  if (wsl) {
2527
2552
  const wslArgs = link ? ['npm', 'install', '-g', '.'] : ['npm', 'install', '-g', `${pkgName}@${pkgVersion}`];
2553
+ if (!link && !install)
2554
+ waitForNpmVersion(pkgName, pkgVersion);
2528
2555
  console.log(`Installing in WSL${link ? ' (link)' : ' from registry'}: ${pkgName}@${pkgVersion}...`);
2529
2556
  if (!dryRun) {
2530
2557
  const wslResult = runCommand('wsl', wslArgs, { cwd, silent: false });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.80",
3
+ "version": "1.0.81",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",