@bobfrankston/npmglobalize 1.0.212 → 1.0.214

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/README.md CHANGED
@@ -298,10 +298,10 @@ reachable `repository.url` in `package.json`. If found, it offers two paths:
298
298
  ```
299
299
  How would you like to set up git?
300
300
  1) Adopt history from existing remote (recommended)
301
- 2) Initialize fresh git repository
302
- a) Adopt ALL (don't ask again for remaining deps)
303
- 3) Use local install only (skip git/publish)
304
- 4) Abort
301
+ 2) Adopt for ALL remaining deps (don't ask again)
302
+ 3) Initialize fresh git repository
303
+ 4) Use local install only (skip git/publish)
304
+ 5) Abort
305
305
  ```
306
306
 
307
307
  **Adopt** runs:
@@ -421,8 +421,8 @@ not what you meant to publish, so npmglobalize lists the conflicted files and st
421
421
  -link Install globally via symlink (npm install -g .)
422
422
  -local Local install only — skip transform/publish, just npm install -g .
423
423
  (persisted; a .commitmsg is still logged to npmchanges.md as "(local)")
424
- -nolocal Clear a persisted -local in .globalize.json5 — back to transform/publish
425
- (alias: -global)
424
+ -global Clear a persisted -local in .globalize.json5 — back to the normal
425
+ transform/publish flow (publishes to npm again)
426
426
  -wsl Also install in WSL
427
427
  -once Don't persist flags to .globalize.json5
428
428
  ```
@@ -773,7 +773,7 @@ npmglobalize -local # same as --local
773
773
  Some flags are **persisted** to `.globalize.json5` when set from the CLI:
774
774
  - `-install`, `-link`, `-wsl`, `-files`, `-fix` — install/build preferences
775
775
  - `-np` (noPublish) — once set, prevents accidental publishes
776
- - `-local` — remembers "this project is local-only" (clear with `-nolocal` / `-global`)
776
+ - `-local` — remembers "this project is local-only" (clear with `-global`)
777
777
  - `-git`/`-npm` visibility
778
778
 
779
779
  Other flags are **one-shot** (never persisted):
@@ -793,7 +793,7 @@ Skip all transform/publish logic and just run `npm install -g .` with `file:` de
793
793
  ```bash
794
794
  npmglobalize -local # Install globally from local directory
795
795
  npmglobalize -local -wsl # Also install in WSL
796
- npmglobalize -nolocal # Back to the normal transform/publish flow (alias: -global)
796
+ npmglobalize -global # Back to the normal transform/publish flow (publishes to npm)
797
797
  ```
798
798
 
799
799
  This is useful for:
@@ -802,7 +802,7 @@ This is useful for:
802
802
  - Projects with `file:` deps that should stay as-is
803
803
 
804
804
  `-local` is persisted to `.globalize.json5` (`"local": true`), so a bare
805
- `npmglobalize` keeps doing local installs until you run `-nolocal` (or edit the
805
+ `npmglobalize` keeps doing local installs until you run `-global` (or edit the
806
806
  file). Nothing is committed, bumped, or published, but a `.commitmsg` is still
807
807
  consumed: it is appended to `npmchanges.md` under a
808
808
  `## v<version> (local) — <YYYY-MM-DD>` header and deleted, so the notes are not
package/cli.js CHANGED
@@ -70,8 +70,8 @@ Install Options:
70
70
  -link Global install via symlink (npm install -g .)
71
71
  -local Local install only — skip transform/publish, just npm install -g .
72
72
  (persisted; a .commitmsg is still logged to npmchanges.md as "(local)")
73
- -nolocal Clear a persisted -local in .globalize.json5 — back to transform/publish
74
- (alias: -global)
73
+ -global Clear a persisted -local in .globalize.json5 — back to the normal
74
+ transform/publish flow (publishes to npm again)
75
75
  -wsl Also install globally in WSL
76
76
  -freeze Freeze node_modules (replace symlinks with real copies for network shares)
77
77
  -nofreeze Disable freeze
@@ -157,7 +157,7 @@ Examples:
157
157
  npmglobalize -link -wsl Release + link on Windows and WSL (symlink)
158
158
  npmglobalize -local Install locally with file: deps as-is (no publish)
159
159
  npmglobalize -local -wsl Local install on Windows and WSL
160
- npmglobalize -nolocal Leave local-only mode; publish normally from now on
160
+ npmglobalize -global Leave local-only mode; publish to npm from now on
161
161
  npmglobalize -np Just transform, no publish (remembered in config)
162
162
  npmglobalize -cleanup Restore original dependencies
163
163
  npmglobalize -init Initialize git (adopt existing remote if any) + release
@@ -233,7 +233,8 @@ function parseArgs(args) {
233
233
  // 2026-09-01 16:30 EDT — Claude Code (Opus 5), at Bob's direction. -local
234
234
  // persists to .globalize.json5 but had no counterpart, so leaving local-only
235
235
  // mode meant hand-editing the config. Same shape as -publish for -np.
236
- case '-nolocal':
236
+ // 2026-09-01 15:00 EDT — Bob: "-global makes more sense, -nolocal is confusing";
237
+ // -nolocal dropped, -global is the only spelling.
237
238
  case '-global':
238
239
  options.local = false;
239
240
  options.explicitKeys.add('local');
package/lib.d.ts CHANGED
@@ -589,8 +589,14 @@ export declare function validatePackageJson(pkg: any): string[];
589
589
  export declare function confirm(message: string, defaultYes?: boolean): Promise<boolean>;
590
590
  /** Prompt user for free text input */
591
591
  export declare function promptText(message: string, defaultValue?: string): Promise<string>;
592
- /** Prompt user for multiple choice */
593
- export declare function promptChoice(message: string, choices: string[]): Promise<string | null>;
592
+ /**
593
+ * Prompt user for multiple choice. Re-asks until the answer is one of `choices`.
594
+ *
595
+ * 2026-09-01 — Claude Code (Fable 5.1), at Bob's direction. Previously an unrecognized
596
+ * answer resolved null and every caller fell through to its default action, so a typo
597
+ * silently did something. Now it says what it didn't understand and asks again.
598
+ */
599
+ export declare function promptChoice(message: string, choices: string[]): Promise<string>;
594
600
  /** Initialize a local git repo by adopting history from an existing remote.
595
601
  * Preserves the working tree — local files appear as uncommitted changes
596
602
  * on top of the remote's HEAD. No force-push is required. */
package/lib.js CHANGED
@@ -445,7 +445,7 @@ export function writeConfig(dir, config, explicitKeys) {
445
445
  ['"gitVisibility": "private"', 'Git repo: private or public'],
446
446
  ['"npmVisibility": "private"', 'npm package: private or public'],
447
447
  ['"fix": false', 'true = auto-run npm audit fix'],
448
- ['"local": false', 'true = local install only (skip transform/publish); clear with -nolocal'],
448
+ ['"local": false', 'true = local install only (skip transform/publish); clear with -global'],
449
449
  ['"noPublish": false', 'true = transform but don\'t publish'],
450
450
  ['"freeze": false', 'true = freeze node_modules (replace symlinks with real copies)'],
451
451
  ['"usePaths": true', 'true = resolve file: deps from siblings; false = use latest npm version (standalone)'],
@@ -4995,23 +4995,46 @@ export async function promptText(message, defaultValue) {
4995
4995
  });
4996
4996
  });
4997
4997
  }
4998
- /** Prompt user for multiple choice */
4999
- export async function promptChoice(message, choices) {
4998
+ /**
4999
+ * Prompt user for multiple choice. Re-asks until the answer is one of `choices`.
5000
+ *
5001
+ * 2026-09-01 — Claude Code (Fable 5.1), at Bob's direction. Previously an unrecognized
5002
+ * answer resolved null and every caller fell through to its default action, so a typo
5003
+ * silently did something. Now it says what it didn't understand and asks again.
5004
+ */
5005
+ export function promptChoice(message, choices) {
5000
5006
  const rl = readline.createInterface({
5001
5007
  input: process.stdin,
5002
5008
  output: process.stdout
5003
5009
  });
5010
+ const shown = choices.filter(c => c !== '').join(', ');
5011
+ // A 'line' listener rather than repeated rl.question(): when stdin is piped, several
5012
+ // lines can arrive in one chunk and a line landing between two question() calls is
5013
+ // dropped. The listener sees every line.
5004
5014
  return new Promise((resolve) => {
5005
- rl.question(`${message} `, (answer) => {
5015
+ let done = false;
5016
+ const finish = (value) => {
5017
+ done = true;
5006
5018
  rl.close();
5019
+ resolve(value);
5020
+ };
5021
+ rl.setPrompt(`${message} `);
5022
+ rl.prompt();
5023
+ rl.on('line', (answer) => {
5024
+ if (done)
5025
+ return;
5007
5026
  const a = answer.trim().toLowerCase();
5008
- if (choices.includes(a)) {
5009
- resolve(a);
5010
- }
5011
- else {
5012
- resolve(null);
5013
- }
5027
+ if (choices.includes(a))
5028
+ return finish(a);
5029
+ console.log(colors.yellow(`Unrecognized choice "${a}" — expected one of: ${shown}`));
5030
+ rl.prompt();
5014
5031
  });
5032
+ // EOF with no valid answer: behave as "just pressed Enter" ('' is the default where
5033
+ // a default exists; callers without one treat '' as abort).
5034
+ rl.on('close', () => { if (!done) {
5035
+ done = true;
5036
+ resolve('');
5037
+ } });
5015
5038
  });
5016
5039
  }
5017
5040
  /** Check npm authentication status */
@@ -6053,7 +6076,7 @@ async function doLocalInstall(cwd, options) {
6053
6076
  const pkgVersion = pkg.version || '0.0.0';
6054
6077
  console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
6055
6078
  console.log(colors.dim('Skipping transform/publish — installing with file: deps as-is'));
6056
- console.log(colors.dim(' (switch back to the publish flow with -nolocal)'));
6079
+ console.log(colors.dim(' (switch back to the publish flow with -global)'));
6057
6080
  // Record before the bin check: a library's notes are history too.
6058
6081
  recordLocalChange(cwd, pkgVersion, dryRun);
6059
6082
  if (!pkg.bin) {
@@ -6393,51 +6416,60 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6393
6416
  justInitialized = true;
6394
6417
  }
6395
6418
  else if (!init && !options.autoInit && !publishDepsYes) {
6419
+ // 2026-09-01 — Claude Code (Fable 5.1), at Bob's direction. These menus were
6420
+ // numbered "1 a 2 3": the "ALL" option was lettered and sat between 1 and 2, so
6421
+ // a reader who wanted the second line typed 2 and got something else. Bob:
6422
+ // "I type 2 when I mean a because that's what humans do." Options are now
6423
+ // numbered in display order; the ALL variant is 2, directly under the single.
6396
6424
  let choice;
6397
6425
  if (adoptable) {
6398
6426
  choice = await promptChoice('How would you like to set up git?\n'
6399
6427
  + ' 1) Adopt history from existing remote (recommended)\n'
6400
- + ' a) Adopt ALL (don\'t ask again for remaining deps)\n'
6401
- + ' 2) Initialize fresh git repository\n'
6402
- + ' 3) Use local install only (skip git/publish)\n'
6403
- + ' 4) Abort\nChoice:', ['1', 'a', '2', '3', '4', '']);
6404
- if (choice === '3') {
6428
+ + ' 2) Adopt for ALL remaining deps (don\'t ask again)\n'
6429
+ + ' 3) Initialize fresh git repository\n'
6430
+ + ' 4) Use local install only (skip git/publish)\n'
6431
+ + ' 5) Abort\nChoice [1]:', ['1', '2', '3', '4', '5', '']);
6432
+ if (choice === '4') {
6405
6433
  console.log(colors.dim('Switching to local-only mode...'));
6406
6434
  writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
6407
6435
  return doLocalInstall(cwd, options);
6408
6436
  }
6409
- if (choice === '4') {
6437
+ if (choice === '5') {
6410
6438
  console.log('Aborted. Run with --init to initialize.');
6411
6439
  return false;
6412
6440
  }
6413
- if (choice === 'a')
6441
+ if (choice === '2')
6414
6442
  options.autoInit = true;
6415
- if (choice === '2') {
6443
+ if (choice === '3') {
6416
6444
  const success = await initGit(cwd, gitVisibility, dryRun, allowTs);
6417
6445
  if (!success)
6418
6446
  return false;
6419
6447
  }
6420
6448
  else {
6421
- // '1', 'a', '' default → adopt
6449
+ // '1', '2', '' default → adopt
6422
6450
  const success = await adoptExistingRemote(cwd, adoptable.url, adoptable.defaultBranch, dryRun);
6423
6451
  if (!success)
6424
6452
  return false;
6425
6453
  }
6426
6454
  }
6427
6455
  else {
6428
- choice = await promptChoice('No git repository found. What would you like to do?\n 1) Initialize git repository (default)\n a) Initialize ALL (don\'t ask again for remaining deps)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', 'a', '2', '3', '']);
6429
- if (choice === '2') {
6456
+ choice = await promptChoice('No git repository found. What would you like to do?\n'
6457
+ + ' 1) Initialize git repository\n'
6458
+ + ' 2) Initialize for ALL remaining deps (don\'t ask again)\n'
6459
+ + ' 3) Use local install only (skip git/publish)\n'
6460
+ + ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
6461
+ if (choice === '3') {
6430
6462
  console.log(colors.dim('Switching to local-only mode...'));
6431
6463
  writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
6432
6464
  return doLocalInstall(cwd, options);
6433
6465
  }
6434
- if (choice === '3') {
6466
+ if (choice === '4') {
6435
6467
  console.log('Aborted. Run with --init to initialize.');
6436
6468
  return false;
6437
6469
  }
6438
- if (choice === 'a')
6470
+ if (choice === '2')
6439
6471
  options.autoInit = true;
6440
- // choice is '1', 'a', or '' (default)
6472
+ // choice is '1', '2', or '' (default) → init
6441
6473
  const success = await initGit(cwd, gitVisibility, dryRun, allowTs);
6442
6474
  if (!success)
6443
6475
  return false;
@@ -6463,17 +6495,22 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6463
6495
  else if (!gitStatus.hasRemote) {
6464
6496
  // Git repo exists but no remote - need to create GitHub repo
6465
6497
  if (!init && !options.autoInit && !publishDepsYes) {
6466
- const choice = await promptChoice('No git remote configured. What would you like to do?\n 1) Create GitHub repository (default)\n a) Initialize ALL (don\'t ask again for remaining deps)\n 2) Use local install only (skip git/publish)\n 3) Abort\nChoice:', ['1', 'a', '2', '3', '']);
6467
- if (choice === '2') {
6498
+ // 2026-09-01 Claude Code (Fable 5.1): renumbered from "1 a 2 3" (see note above).
6499
+ const choice = await promptChoice('No git remote configured. What would you like to do?\n'
6500
+ + ' 1) Create GitHub repository\n'
6501
+ + ' 2) Create for ALL remaining deps (don\'t ask again)\n'
6502
+ + ' 3) Use local install only (skip git/publish)\n'
6503
+ + ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
6504
+ if (choice === '3') {
6468
6505
  console.log(colors.dim('Switching to local-only mode...'));
6469
6506
  writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
6470
6507
  return doLocalInstall(cwd, options);
6471
6508
  }
6472
- if (choice === '3') {
6509
+ if (choice === '4') {
6473
6510
  console.log('Aborted. Run with --init to set up GitHub repository.');
6474
6511
  return false;
6475
6512
  }
6476
- if (choice === 'a') {
6513
+ if (choice === '2') {
6477
6514
  options.autoInit = true;
6478
6515
  }
6479
6516
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.212",
3
+ "version": "1.0.214",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",