@bobfrankston/npmglobalize 1.0.222 → 1.0.224

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 (5) hide show
  1. package/README.md +23 -3
  2. package/cli.js +8 -7
  3. package/lib.d.ts +15 -2
  4. package/lib.js +101 -29
  5. package/package.json +3 -3
package/README.md CHANGED
@@ -200,6 +200,24 @@ node_modules check:
200
200
  **name-only** (`--no-allow-scripts-pin`): a version pin would re-open the
201
201
  question on every bump. Without a terminal (piped stdin) nothing is asked;
202
202
  the pending packages are listed with the command to approve them.
203
+ - **Each answer is remembered for every project.** A decision about `sharp`'s
204
+ install script is about sharp, not about the project that asked first, so
205
+ `y`/`n`/`a` answers are stored once per user in your userconfig `npm.json5` (the file `@bobfrankston/userconfig` names as `configPath`; the prompt prints its location):
206
+
207
+ ```json5
208
+ allowScripts: {
209
+ sharp: true,
210
+ koffi: true,
211
+ 'some-pkg': false,
212
+ },
213
+ ```
214
+
215
+ The next project that meets a remembered package gets its `package.json`
216
+ entry written silently (`· install-script decisions applied from …npm.json5:
217
+ sharp allowed`). A project's own `allowScripts` entry wins over the
218
+ remembered one, so a per-project exception is just an edit to that
219
+ `package.json`. Edit or delete an entry in `npm.json5` to change your mind
220
+ everywhere.
203
221
  - The field is written by npm itself, so a linked dep gets the key npm wants
204
222
  for it — the `file:` spec, e.g. `"file:../../../../projects/com/com-wrapper": true`
205
223
  (relative to the link's parent directory, not the project).
@@ -207,8 +225,8 @@ node_modules check:
207
225
  The **global** install then allowlists your own packages — it just built and
208
226
  published them from your source, so they're trusted — plus whatever the
209
227
  project's `allowScripts` approved (a `file:` key is mapped to that dep's
210
- published name) and your user `.npmrc` `allow-scripts` list, minus anything
211
- the project denied. Third-party packages you never approved stay gated:
228
+ published name), your remembered `npm.json5` approvals, and your user `.npmrc`
229
+ `allow-scripts` list, minus anything denied. Third-party packages you never approved stay gated:
212
230
 
213
231
  ```
214
232
  > npm install -g @bobfrankston/winpos@2.0.51 --allow-scripts @bobfrankston/winpos,@bobfrankston/msger,@bobfrankston/msgcommon,sharp
@@ -884,7 +902,9 @@ This is useful for:
884
902
  deprecation note; it was renamed (2026-09-07) because "local" read as "local mode" rather
885
903
  than "install from the local directory".
886
904
 
887
- `-local-install` is persisted to `.globalize.json5` (`"local": true`), so a bare
905
+ `-local-install` is persisted to `.globalize.json5` (`"localInstall": true`; the older
906
+ `"local"` key is still read and is rewritten to the new name the next time the file is
907
+ saved), so a bare
888
908
  `npmglobalize` keeps doing local installs until you run `-global` (or edit the
889
909
  file). Nothing is committed, bumped, or published, but a `.commitmsg` is still
890
910
  consumed: it is appended to `npmchanges.md` under a
package/cli.js CHANGED
@@ -235,14 +235,15 @@ function parseArgs(args) {
235
235
  // from the local directory". Renamed to -local-install (-localinstall also
236
236
  // accepted). -local still works but says so, so muscle memory isn't broken
237
237
  // and the old spelling is phased out rather than silently kept alive.
238
- // The .globalize.json5 key stays "local" so existing configs keep working.
238
+ // The .globalize.json5 key was renamed "local" "localInstall" the same day;
239
+ // readConfig accepts the old name and the next persist rewrites it.
239
240
  case '-local':
240
- console.log(colors.yellow('! -local is deprecated — use -local-install (same meaning: npm install -g . from the local directory, no publish)'));
241
+ console.log(colors.yellow('! -local is deprecated — use -local-install (or -localinstall). Same meaning: npm install -g . from the local directory, no publish.'));
241
242
  // falls through
242
243
  case '-local-install':
243
244
  case '-localinstall':
244
- options.local = true;
245
- options.explicitKeys.add('local');
245
+ options.localInstall = true;
246
+ options.explicitKeys.add('localInstall');
246
247
  break;
247
248
  // 2026-09-01 16:30 EDT — Claude Code (Opus 5), at Bob's direction. -local-install
248
249
  // persists to .globalize.json5 but had no counterpart, so leaving local-only
@@ -250,8 +251,8 @@ function parseArgs(args) {
250
251
  // 2026-09-01 15:00 EDT — Bob: "-global makes more sense, -nolocal is confusing";
251
252
  // -nolocal dropped, -global is the only spelling.
252
253
  case '-global':
253
- options.local = false;
254
- options.explicitKeys.add('local');
254
+ options.localInstall = false;
255
+ options.explicitKeys.add('localInstall');
255
256
  break;
256
257
  case '-install':
257
258
  case '-i':
@@ -663,7 +664,7 @@ export async function main() {
663
664
  console.log(`Updated ${path.join(cwd, 'package.json')} scripts:`);
664
665
  changes.forEach(c => console.log(` ${c}`));
665
666
  // If no other flags need processing, exit; otherwise fall through
666
- if (!cliOptions.install && !cliOptions.link && !cliOptions.local) {
667
+ if (!cliOptions.install && !cliOptions.link && !cliOptions.localInstall) {
667
668
  process.exit(0);
668
669
  }
669
670
  }
package/lib.d.ts CHANGED
@@ -132,8 +132,9 @@ export interface GlobalizeOptions {
132
132
  * are absent. Currently declarative (recorded in config and displayed);
133
133
  * the actual conversion path is TODO. */
134
134
  usePaths?: boolean;
135
- /** Local install only — skip transform/publish, just npm install -g . */
136
- local?: boolean;
135
+ /** Local install only (-local-install) — skip transform/publish, just npm install -g .
136
+ * Config key renamed from "local" 2026-09-07; readConfig still accepts the old name. */
137
+ localInstall?: boolean;
137
138
  /** Build every file: dep even when outputs look up to date (skips the freshness check) */
138
139
  forceBuild?: boolean;
139
140
  /** Freeze node_modules: replace symlinks/junctions with real copies for network share use */
@@ -570,6 +571,18 @@ export declare function projectAllowScripts(dir: string): {
570
571
  allowed: string[];
571
572
  denied: string[];
572
573
  };
574
+ /** The user's remembered install-script decisions, by package name.
575
+ * `true` = approve, `false` = deny. Read from npm.json5 via userconfig. */
576
+ export declare function globalAllowScripts(): Record<string, boolean>;
577
+ /** Merge new decisions into the remembered set and persist it. */
578
+ export declare function rememberAllowScripts(decisions: Record<string, boolean>): void;
579
+ /** Project policy layered over the remembered user policy: a name the
580
+ * project decided keeps the project's answer; every other remembered
581
+ * name contributes its own. */
582
+ export declare function effectiveAllowScripts(dir: string): {
583
+ allowed: string[];
584
+ denied: string[];
585
+ };
573
586
  /** Bring the project's package.json `allowScripts` up to date with what is
574
587
  * installed, so `npm install` stops warning and — once npm starts enforcing
575
588
  * the policy — keeps running the scripts this project depends on.
package/lib.js CHANGED
@@ -14,7 +14,7 @@ import os from 'os';
14
14
  import path from 'path';
15
15
  import { execSync, spawn, spawnSync } from 'child_process';
16
16
  import { builtinModules } from 'module';
17
- import { readConfig as readUserConfig, writeConfig as writeUserConfig, configDir } from '@bobfrankston/userconfig';
17
+ import { readConfig as readUserConfig, writeConfig as writeUserConfig, configDir, configPath as userConfigPath } from '@bobfrankston/userconfig';
18
18
  import { freezeDependencies } from '@bobfrankston/freezepak';
19
19
  import { importgen as runImportgen } from '@bobfrankston/importgen';
20
20
  /** Wrapper for spawnSync that avoids DEP0190 (args + shell: true).
@@ -312,7 +312,18 @@ export function readConfig(dir) {
312
312
  }
313
313
  try {
314
314
  const content = fs.readFileSync(configPath, 'utf-8');
315
- return JSON5.parse(content);
315
+ const config = JSON5.parse(content);
316
+ // 2026-09-07 — Claude Code (Fable 5.1), at Bob's direction: the "local" key
317
+ // was renamed "localInstall" along with the -local → -local-install flag.
318
+ // Old files keep working: the value is carried over here, and since
319
+ // writeConfig reads the existing config through this same function, the
320
+ // next persist writes the new name and drops the old one.
321
+ if ('local' in config && !('localInstall' in config)) {
322
+ config.localInstall = config.local;
323
+ console.log(colors.dim(` (.globalize.json5: "local" is now "localInstall" — rewritten on the next persist)`));
324
+ }
325
+ delete config.local;
326
+ return config;
316
327
  }
317
328
  catch (error) {
318
329
  console.warn(`Warning: Could not parse .globalize.json5 config: ${error.message}`);
@@ -332,7 +343,7 @@ const BOOL_COMMENTS = {
332
343
  quiet: { on: 'Suppress npm warnings', off: 'Show npm warnings' },
333
344
  verbose: { on: 'Show detailed output', off: 'Normal output detail' },
334
345
  fix: { on: 'Auto-run npm audit fix (default)', off: 'Do NOT run npm audit fix (audit report still runs)' },
335
- local: { on: 'Local install only via -local-install (skip transform/publish)', off: 'Normal transform/publish flow' },
346
+ localInstall: { on: 'Local install only via -local-install (skip transform/publish)', off: 'Normal transform/publish flow' },
336
347
  noPublish: { on: 'Transform but don\'t publish', off: 'Publish normally' },
337
348
  freeze: { on: 'Freeze node_modules (replace symlinks with real copies)', off: 'Leave node_modules symlinks as-is' },
338
349
  usePaths: { on: 'Resolve file: deps from sibling checkouts', off: 'Resolve file: deps from npm, not siblings (standalone package)' },
@@ -444,7 +455,7 @@ export function writeConfig(dir, config, explicitKeys) {
444
455
  ['"gitVisibility": "private"', 'Git repo: private or public'],
445
456
  ['"npmVisibility": "private"', 'npm package: private or public'],
446
457
  ['"fix": true', 'true = auto-run npm audit fix (never --force); false = report only'],
447
- ['"local": false', 'true = install from the local directory only, set by -local-install (skip transform/publish); clear with -global'],
458
+ ['"localInstall": false', 'true = install from the local directory only, set by -local-install (skip transform/publish); clear with -global'],
448
459
  ['"noPublish": false', 'true = transform but don\'t publish'],
449
460
  ['"freeze": false', 'true = freeze node_modules (replace symlinks with real copies)'],
450
461
  ['"usePaths": true', 'true = resolve file: deps from siblings; false = use latest npm version (standalone)'],
@@ -4361,18 +4372,55 @@ function npmrcAllowScripts() {
4361
4372
  return [];
4362
4373
  return r.output.split(/[,\s]+/).map(s => s.trim()).filter(Boolean);
4363
4374
  }
4375
+ // 2026-09-07 — Claude Code (Fable 5.1), at Bob's direction ("why not save the
4376
+ // accept scripts globally rather than asking me each time"). A yes/no about a
4377
+ // third-party package's install scripts is a decision about that PACKAGE, not
4378
+ // about the project that happened to ask first — sharp is sharp in whts and in
4379
+ // label-core. So every answer is remembered once, per user, in npm.json5
4380
+ // (`allowScripts: { sharp: true, "evil-pkg": false }`), and a project that
4381
+ // meets a remembered package gets its package.json field written without a
4382
+ // question. package.json stays the record npm itself reads; npm.json5 is the
4383
+ // memory that pre-answers it.
4384
+ /** The user's remembered install-script decisions, by package name.
4385
+ * `true` = approve, `false` = deny. Read from npm.json5 via userconfig. */
4386
+ export function globalAllowScripts() {
4387
+ const policy = readUserNpmConfig().allowScripts;
4388
+ return policy && typeof policy === 'object' ? { ...policy } : {};
4389
+ }
4390
+ /** Merge new decisions into the remembered set and persist it. */
4391
+ export function rememberAllowScripts(decisions) {
4392
+ if (!Object.keys(decisions).length)
4393
+ return;
4394
+ writeUserNpmConfig({ allowScripts: { ...globalAllowScripts(), ...decisions } });
4395
+ }
4364
4396
  /** npm args allowing install scripts on a GLOBAL install: our own packages,
4365
- * whatever the project's package.json `allowScripts` approves, and the
4366
- * user's .npmrc list — minus anything the project denies. Empty when npm
4367
- * predates the policy (it runs the scripts anyway) or nothing is allowed. */
4397
+ * whatever the project's package.json `allowScripts` approves, the user's
4398
+ * remembered approvals (npm.json5), and the user's .npmrc list — minus
4399
+ * anything denied. A project's explicit decision wins over the remembered
4400
+ * one. Empty when npm predates the policy (it runs the scripts anyway) or
4401
+ * nothing is allowed. */
4368
4402
  function allowScriptsArgs(dir) {
4369
4403
  if (!npmSupportsAllowScripts())
4370
4404
  return [];
4371
- const project = projectAllowScripts(dir);
4372
- const names = [...new Set([...ownScopePackages(dir), ...project.allowed, ...npmrcAllowScripts()])]
4373
- .filter(n => !project.denied.includes(n));
4405
+ const { allowed, denied } = effectiveAllowScripts(dir);
4406
+ const names = [...new Set([...ownScopePackages(dir), ...allowed, ...npmrcAllowScripts()])]
4407
+ .filter(n => !denied.includes(n));
4374
4408
  return names.length ? ['--allow-scripts', names.join(',')] : [];
4375
4409
  }
4410
+ /** Project policy layered over the remembered user policy: a name the
4411
+ * project decided keeps the project's answer; every other remembered
4412
+ * name contributes its own. */
4413
+ export function effectiveAllowScripts(dir) {
4414
+ const project = projectAllowScripts(dir);
4415
+ const allowed = new Set(project.allowed);
4416
+ const denied = new Set(project.denied);
4417
+ for (const [name, ok] of Object.entries(globalAllowScripts())) {
4418
+ if (allowed.has(name) || denied.has(name))
4419
+ continue;
4420
+ (ok ? allowed : denied).add(name);
4421
+ }
4422
+ return { allowed: [...allowed], denied: [...denied] };
4423
+ }
4376
4424
  /** Parse the text listing of `npm approve-scripts --allow-scripts-pending`:
4377
4425
  * one indented `name@version (event: cmd; event: cmd)` line per node,
4378
4426
  * the same package repeated when several versions are installed. */
@@ -4424,16 +4472,23 @@ export async function ensureAllowScripts(dir, opts = {}) {
4424
4472
  if (!pending.length)
4425
4473
  return;
4426
4474
  const trusted = new Set([...ownScopePackages(dir), ...localDepDisplayNames(dir)]);
4427
- const auto = pending.filter(p => trusted.has(p.name));
4428
- const ask = pending.filter(p => !trusted.has(p.name));
4429
4475
  const label = (p) => p.versions.length ? `${p.name}@${p.versions.join('|')}` : p.name;
4476
+ const auto = pending.filter(p => trusted.has(p.name));
4477
+ // 2026-09-07 — Claude Code (Fable 5.1), at Bob's direction: a package already
4478
+ // decided in npm.json5 is applied here without asking; only never-seen
4479
+ // third-party packages reach the prompt, and their answers are remembered.
4480
+ const remembered = globalAllowScripts();
4481
+ const rememberedYes = pending.filter(p => !trusted.has(p.name) && remembered[p.name] === true);
4482
+ const rememberedNo = pending.filter(p => !trusted.has(p.name) && remembered[p.name] === false);
4483
+ const ask = pending.filter(p => !trusted.has(p.name) && !(p.name in remembered));
4430
4484
  if (opts.dryRun) {
4431
- console.log(colors.dim(` [dry-run] allowScripts in ${pkgName}: would approve ${auto.map(label).join(', ') || '(none)'}; would ask about ${ask.map(label).join(', ') || '(none)'}`));
4485
+ console.log(colors.dim(` [dry-run] allowScripts in ${pkgName}: would approve ${[...auto, ...rememberedYes].map(label).join(', ') || '(none)'}; would deny ${rememberedNo.map(label).join(', ') || '(none)'}; would ask about ${ask.map(label).join(', ') || '(none)'}`));
4432
4486
  return;
4433
4487
  }
4434
- const approve = auto.map(p => p.name);
4435
- const deny = [];
4488
+ const approve = [...auto, ...rememberedYes].map(p => p.name);
4489
+ const deny = rememberedNo.map(p => p.name);
4436
4490
  const skipped = [];
4491
+ const decisions = {};
4437
4492
  if (ask.length) {
4438
4493
  if (!process.stdin.isTTY) {
4439
4494
  console.log(colors.yellow(` ⚠ ${ask.length} third-party package(s) in ${pkgName} have install scripts not yet covered by allowScripts (no terminal to ask): ${ask.map(label).join(', ')}`));
@@ -4441,40 +4496,56 @@ export async function ensureAllowScripts(dir, opts = {}) {
4441
4496
  skipped.push(...ask.map(label));
4442
4497
  }
4443
4498
  else {
4444
- console.log(colors.cyan(`npm gates install scripts for ${ask.length} third-party package(s) in ${pkgName}. Approvals are recorded in package.json "allowScripts" (name-only) and honored on the global install too.`));
4499
+ console.log(colors.cyan(`npm gates install scripts for ${ask.length} third-party package(s) in ${pkgName}. Each answer is recorded in package.json "allowScripts" (name-only), honored on the global install, and remembered for every project in ${userConfigPath}.`));
4445
4500
  let allRemaining = false;
4446
4501
  for (const p of ask) {
4447
4502
  const prebuilt = PREBUILT_SCRIPT_RUNNERS.test(p.scripts) ? ' — prebuilt-binary fetcher, the package ships binaries' : '';
4448
4503
  if (allRemaining) {
4449
4504
  approve.push(p.name);
4505
+ decisions[p.name] = true;
4450
4506
  continue;
4451
4507
  }
4452
4508
  const answer = await promptChoice(` Allow install scripts for ${label(p)} (${p.scripts})${prebuilt}? [y]es / [n]o, deny / [a]ll remaining / [s]kip for now:`, ['y', 'n', 'a', 's']);
4453
4509
  switch (answer) {
4454
4510
  case 'y':
4455
4511
  approve.push(p.name);
4512
+ decisions[p.name] = true;
4456
4513
  break;
4457
4514
  case 'a':
4458
4515
  approve.push(p.name);
4516
+ decisions[p.name] = true;
4459
4517
  allRemaining = true;
4460
4518
  break;
4461
4519
  case 'n':
4462
4520
  deny.push(p.name);
4521
+ decisions[p.name] = false;
4463
4522
  break;
4464
4523
  default:
4465
4524
  skipped.push(label(p));
4466
4525
  break; // 's', or EOF ('' from promptChoice)
4467
4526
  }
4468
4527
  }
4528
+ try {
4529
+ rememberAllowScripts(decisions);
4530
+ }
4531
+ catch (error) {
4532
+ // Not swallowed: the project's package.json still gets the answer below;
4533
+ // only the cross-project memory is lost, and the user is told so.
4534
+ console.log(colors.yellow(` ⚠ could not remember install-script decisions in ${userConfigPath}: ${error.message}`));
4535
+ }
4469
4536
  }
4470
4537
  }
4538
+ if (rememberedYes.length || rememberedNo.length) {
4539
+ console.log(colors.dim(` · install-script decisions applied from ${userConfigPath}: ${[...rememberedYes.map(p => `${p.name} allowed`), ...rememberedNo.map(p => `${p.name} denied`)].join(', ')}`));
4540
+ }
4471
4541
  // `npm approve-scripts <name>` matches installed nodes by the same display
4472
4542
  // name the pending listing used, and writes the right key for each kind
4473
4543
  // (registry name, or the file: path for a linked dep).
4474
4544
  if (approve.length) {
4475
4545
  const r = await runCommandAsync('npm', ['approve-scripts', '--no-allow-scripts-pin', ...approve], { cwd: dir, silent: true });
4546
+ const autoNote = [auto.length ? `${auto.length} own/local` : '', rememberedYes.length ? `${rememberedYes.length} remembered` : ''].filter(Boolean).join(', ');
4476
4547
  if (r.success)
4477
- console.log(colors.green(` ✓ allowScripts: approved ${approve.join(', ')}${auto.length ? ` (${auto.length} own/local approved automatically)` : ''}`));
4548
+ console.log(colors.green(` ✓ allowScripts: approved ${approve.join(', ')}${autoNote ? ` (${autoNote} approved automatically)` : ''}`));
4478
4549
  else
4479
4550
  console.log(colors.red(` ✗ npm approve-scripts failed: ${(r.stderr || r.output).trim().split('\n').find(l => /npm error/.test(l)) ?? 'see output'}`));
4480
4551
  }
@@ -4888,8 +4959,9 @@ export async function installInWsl(wslArgs, opts = {}) {
4888
4959
  // list is left out — WSL's npm has its own .npmrc. Probed against WSL's
4889
4960
  // npm, which is a separate install from the Windows one.
4890
4961
  if (opts.cwd && wslArgs.includes('install') && await wslNpmSupportsAllowScripts()) {
4891
- const project = projectAllowScripts(opts.cwd);
4892
- const names = [...new Set([...ownScopePackages(opts.cwd), ...project.allowed])].filter(n => !project.denied.includes(n));
4962
+ // 2026-09-07 Claude Code (Fable 5.1): remembered npm.json5 decisions apply in WSL too.
4963
+ const policy = effectiveAllowScripts(opts.cwd);
4964
+ const names = [...new Set([...ownScopePackages(opts.cwd), ...policy.allowed])].filter(n => !policy.denied.includes(n));
4893
4965
  if (names.length)
4894
4966
  wslArgs = [...wslArgs, '--allow-scripts', names.join(',')];
4895
4967
  }
@@ -6669,7 +6741,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6669
6741
  const { bump = 'patch', noPublish = false, cleanup = false, install = false, link = false, wsl = false, force = false, files = true, dryRun = false, quiet = true, verbose = false, init = false, gitVisibility = 'private', npmVisibility = 'private', message, conform = false, asis = false, updateDeps = false, updateMajor = false, publishDeps = true, // Default to publishing deps for safety
6670
6742
  publishDepsYes = false, // -pd: auto-yes to dep-cascade prompts (private only)
6671
6743
  publicDeps = false, // -public-deps: cascade public visibility to all deps
6672
- noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false, local = false, freeze = false, usePaths = true, allowTs, adopt = false, importCheck = false } = options;
6744
+ noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false, localInstall = false, freeze = false, usePaths = true, allowTs, adopt = false, importCheck = false } = options;
6673
6745
  // 2026-09-06 — Claude Code (Fable 5.1), at Bob's direction: a directory marked
6674
6746
  // `.stale` is retired. Refuse to build, publish or install it — and because the
6675
6747
  // dep cascade reaches deps through this same function, refuse to cascade into
@@ -6733,7 +6805,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6733
6805
  settings.push('--force-publish');
6734
6806
  if (configOptions.show)
6735
6807
  settings.push('--show');
6736
- if (configOptions.local)
6808
+ if (configOptions.localInstall)
6737
6809
  settings.push('-local-install');
6738
6810
  if (configOptions.freeze)
6739
6811
  settings.push('-freeze');
@@ -6758,7 +6830,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6758
6830
  // 2026-09-01 16:30 EDT — Claude Code (Opus 5): this was a verbatim copy of
6759
6831
  // doLocalInstall (the 10:55 output-capture note lives there now). One path,
6760
6832
  // so the .commitmsg recording added today lands in both entry points.
6761
- if (local) {
6833
+ if (localInstall) {
6762
6834
  return doLocalInstall(cwd, options);
6763
6835
  }
6764
6836
  // Prescan the file: dep graph up front — surface all problems before
@@ -6988,7 +7060,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6988
7060
  + ' 5) Abort\nChoice [1]:', ['1', '2', '3', '4', '5', '']);
6989
7061
  if (choice === '4') {
6990
7062
  console.log(colors.dim('Switching to local-only mode...'));
6991
- writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
7063
+ writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
6992
7064
  return doLocalInstall(cwd, options);
6993
7065
  }
6994
7066
  if (choice === '5') {
@@ -7017,7 +7089,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
7017
7089
  + ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
7018
7090
  if (choice === '3') {
7019
7091
  console.log(colors.dim('Switching to local-only mode...'));
7020
- writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
7092
+ writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
7021
7093
  return doLocalInstall(cwd, options);
7022
7094
  }
7023
7095
  if (choice === '4') {
@@ -7060,7 +7132,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
7060
7132
  + ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
7061
7133
  if (choice === '3') {
7062
7134
  console.log(colors.dim('Switching to local-only mode...'));
7063
- writeConfig(cwd, { ...configOptions, local: true }, new Set(['local']));
7135
+ writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
7064
7136
  return doLocalInstall(cwd, options);
7065
7137
  }
7066
7138
  if (choice === '4') {
@@ -7875,8 +7947,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
7875
7947
  surprises.push(`usePaths=false${fromConfig('usePaths')} — file: deps resolved from npm, not siblings`);
7876
7948
  if (configOptions.freeze || freeze)
7877
7949
  surprises.push(`freeze=true${fromConfig('freeze')}`);
7878
- if (configOptions.local || local)
7879
- surprises.push(`local=true${fromConfig('local')}`);
7950
+ if (configOptions.localInstall || localInstall)
7951
+ surprises.push(`localInstall=true${fromConfig('localInstall')}`);
7880
7952
  if (configOptions.files === false || files === false)
7881
7953
  surprises.push(`files=false${fromConfig('files')} — npm versions left in package.json`);
7882
7954
  if (configOptions.allowTs === true || allowTs === true)
@@ -9064,8 +9136,8 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
9064
9136
  // user up front avoids the surprise of "I asked for install but most
9065
9137
  // packages didn't install."
9066
9138
  const installSources = [];
9067
- if (options.local || configOptions.local) {
9068
- const src = configOptions.local && !options.local ? '.globalize.json5' : 'CLI';
9139
+ if (options.localInstall || configOptions.localInstall) {
9140
+ const src = configOptions.localInstall && !options.localInstall ? '.globalize.json5' : 'CLI';
9069
9141
  installSources.push(`-local-install (${src})`);
9070
9142
  }
9071
9143
  if (options.install || configOptions.install) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.222",
3
+ "version": "1.0.224",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@bobfrankston/freezepak": "^0.1.9",
35
35
  "@bobfrankston/importgen": "^0.1.43",
36
- "@bobfrankston/themecolors": "^0.1.9",
36
+ "@bobfrankston/themecolors": "^0.1.10",
37
37
  "@bobfrankston/userconfig": "^1.0.11",
38
38
  "@npmcli/package-json": "^7.0.4",
39
39
  "json5": "^2.2.3",
@@ -61,7 +61,7 @@
61
61
  "dependencies": {
62
62
  "@bobfrankston/freezepak": "^0.1.9",
63
63
  "@bobfrankston/importgen": "^0.1.43",
64
- "@bobfrankston/themecolors": "^0.1.9",
64
+ "@bobfrankston/themecolors": "^0.1.10",
65
65
  "@bobfrankston/userconfig": "^1.0.11",
66
66
  "@npmcli/package-json": "^7.0.4",
67
67
  "json5": "^2.2.3",