@bobfrankston/npmglobalize 1.0.210 → 1.0.212

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/README.md +14 -1
  2. package/cli.js +12 -0
  3. package/lib.js +63 -48
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -257,6 +257,7 @@ Notes:
257
257
  - **Git/GitHub only.** npm publish does not consume git commit messages; `npmchanges.md` lives in the git repo and on GitHub but is excluded from the published npm tarball (the standard `*.md` rule keeps only `README.md`).
258
258
  - If both `-m` and `.commitmsg` are present, `-m` wins and `.commitmsg` is left alone (not consumed).
259
259
  - If publish fails, `.commitmsg` is preserved for the next attempt.
260
+ - Under `-local` (no publish) the file is still consumed — appended as `## v<version> (local) — <date>` and deleted, with no git commit. See [Local Install](#local-install--local).
260
261
  - `.commitmsg` is auto-added to `.npmignore` (security pattern) so it never leaks into the tarball.
261
262
 
262
263
  ### 🔧 Git Integration & Error Recovery
@@ -419,6 +420,9 @@ not what you meant to publish, so npmglobalize lists the conflicted files and st
419
420
  -install, -i Install globally after publish (from registry)
420
421
  -link Install globally via symlink (npm install -g .)
421
422
  -local Local install only — skip transform/publish, just npm install -g .
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)
422
426
  -wsl Also install in WSL
423
427
  -once Don't persist flags to .globalize.json5
424
428
  ```
@@ -769,7 +773,7 @@ npmglobalize -local # same as --local
769
773
  Some flags are **persisted** to `.globalize.json5` when set from the CLI:
770
774
  - `-install`, `-link`, `-wsl`, `-files`, `-fix` — install/build preferences
771
775
  - `-np` (noPublish) — once set, prevents accidental publishes
772
- - `-local` — remembers "this project is local-only"
776
+ - `-local` — remembers "this project is local-only" (clear with `-nolocal` / `-global`)
773
777
  - `-git`/`-npm` visibility
774
778
 
775
779
  Other flags are **one-shot** (never persisted):
@@ -789,6 +793,7 @@ Skip all transform/publish logic and just run `npm install -g .` with `file:` de
789
793
  ```bash
790
794
  npmglobalize -local # Install globally from local directory
791
795
  npmglobalize -local -wsl # Also install in WSL
796
+ npmglobalize -nolocal # Back to the normal transform/publish flow (alias: -global)
792
797
  ```
793
798
 
794
799
  This is useful for:
@@ -796,6 +801,14 @@ This is useful for:
796
801
  - Testing a CLI before publishing
797
802
  - Projects with `file:` deps that should stay as-is
798
803
 
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
806
+ file). Nothing is committed, bumped, or published, but a `.commitmsg` is still
807
+ consumed: it is appended to `npmchanges.md` under a
808
+ `## v<version> (local) — <YYYY-MM-DD>` header and deleted, so the notes are not
809
+ lost. Several local entries may share one version number — the date tells them
810
+ apart. No git commit is made for it; the next real publish carries it along.
811
+
799
812
  ### Private Packages
800
813
 
801
814
  Packages with `"private": true` in `package.json` skip the npm publish step. Dependencies are still transformed and restored — the publish is the only thing skipped.
package/cli.js CHANGED
@@ -69,6 +69,9 @@ Install Options:
69
69
  -install, -i Global install after publish (from registry)
70
70
  -link Global install via symlink (npm install -g .)
71
71
  -local Local install only — skip transform/publish, just npm install -g .
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)
72
75
  -wsl Also install globally in WSL
73
76
  -freeze Freeze node_modules (replace symlinks with real copies for network shares)
74
77
  -nofreeze Disable freeze
@@ -154,6 +157,7 @@ Examples:
154
157
  npmglobalize -link -wsl Release + link on Windows and WSL (symlink)
155
158
  npmglobalize -local Install locally with file: deps as-is (no publish)
156
159
  npmglobalize -local -wsl Local install on Windows and WSL
160
+ npmglobalize -nolocal Leave local-only mode; publish normally from now on
157
161
  npmglobalize -np Just transform, no publish (remembered in config)
158
162
  npmglobalize -cleanup Restore original dependencies
159
163
  npmglobalize -init Initialize git (adopt existing remote if any) + release
@@ -226,6 +230,14 @@ function parseArgs(args) {
226
230
  options.local = true;
227
231
  options.explicitKeys.add('local');
228
232
  break;
233
+ // 2026-09-01 16:30 EDT — Claude Code (Opus 5), at Bob's direction. -local
234
+ // persists to .globalize.json5 but had no counterpart, so leaving local-only
235
+ // mode meant hand-editing the config. Same shape as -publish for -np.
236
+ case '-nolocal':
237
+ case '-global':
238
+ options.local = false;
239
+ options.explicitKeys.add('local');
240
+ break;
229
241
  case '-install':
230
242
  case '-i':
231
243
  options.install = true;
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)'],
448
+ ['"local": false', 'true = local install only (skip transform/publish); clear with -nolocal'],
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)'],
@@ -6000,7 +6000,52 @@ export function getToolVersion() {
6000
6000
  return 'unknown';
6001
6001
  }
6002
6002
  }
6003
- /** Perform local-only install (npm install -g .) extracted for reuse from git-init prompts */
6003
+ // 2026-09-01 16:30 EDTClaude Code (Opus 5), at Bob's direction.
6004
+ // Under -local the run returned before any of the .commitmsg handling, so the
6005
+ // notes a local-only package accumulated in .commitmsg were never recorded
6006
+ // anywhere — they sat in the file, and the next edit overwrote them. A local
6007
+ // install is still a change worth a history line, so the same npmchanges.md
6008
+ // gets the entry, tagged "(local)" because nothing was published or bumped
6009
+ // (several local runs may legitimately share one version number). No git
6010
+ // activity: -local is the path taken when there is often no repo at all, and
6011
+ // when there is one the next real publish commits npmchanges.md with the rest.
6012
+ /** Consume .commitmsg for a -local run: append to npmchanges.md, delete the file. */
6013
+ function recordLocalChange(cwd, version, dryRun) {
6014
+ const commitMsgPath = path.join(cwd, '.commitmsg');
6015
+ if (!fs.existsSync(commitMsgPath))
6016
+ return;
6017
+ let content;
6018
+ try {
6019
+ content = fs.readFileSync(commitMsgPath, 'utf-8').trim();
6020
+ }
6021
+ catch (err) {
6022
+ console.error(colors.yellow(` Warning: could not read .commitmsg: ${err.message}`));
6023
+ return;
6024
+ }
6025
+ if (!content)
6026
+ return;
6027
+ if (dryRun) {
6028
+ console.log(` [dry-run] Would append .commitmsg to npmchanges.md as v${version} (local) and delete it`);
6029
+ return;
6030
+ }
6031
+ try {
6032
+ const npmChangesPath = path.join(cwd, 'npmchanges.md');
6033
+ const date = new Date().toISOString().slice(0, 10);
6034
+ const entry = `## v${version} (local) — ${date}\n\n${content}\n\n`;
6035
+ const existing = fs.existsSync(npmChangesPath)
6036
+ ? fs.readFileSync(npmChangesPath, 'utf-8')
6037
+ : '# npm Publish Changes\n\n';
6038
+ const sep = existing.endsWith('\n') ? '' : '\n';
6039
+ fs.writeFileSync(npmChangesPath, existing + sep + entry);
6040
+ fs.unlinkSync(commitMsgPath);
6041
+ console.log(colors.green(` ✓ Appended .commitmsg to npmchanges.md as v${version} (local) and removed .commitmsg`));
6042
+ }
6043
+ catch (err) {
6044
+ console.error(colors.yellow(` Warning: could not update npmchanges.md: ${err.message}`));
6045
+ }
6046
+ }
6047
+ /** Perform local-only install (npm install -g .) — the single -local path, reached
6048
+ * from the -local flag / config and from the git-init prompts' "local only" choice. */
6004
6049
  async function doLocalInstall(cwd, options) {
6005
6050
  const { dryRun = false, wsl = false } = options;
6006
6051
  const pkg = readPackageJson(cwd);
@@ -6008,6 +6053,9 @@ async function doLocalInstall(cwd, options) {
6008
6053
  const pkgVersion = pkg.version || '0.0.0';
6009
6054
  console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
6010
6055
  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)'));
6057
+ // Record before the bin check: a library's notes are history too.
6058
+ recordLocalChange(cwd, pkgVersion, dryRun);
6011
6059
  if (!pkg.bin) {
6012
6060
  console.log(colors.dim(` (library — skipping global install)`));
6013
6061
  return true;
@@ -6018,8 +6066,15 @@ async function doLocalInstall(cwd, options) {
6018
6066
  console.log(' [dry-run] Would run: wsl npm install -g .');
6019
6067
  return true;
6020
6068
  }
6021
- // 2026-09-01 10:55 EDT — Claude Code: see the note on the sibling local-install
6022
- // path captured, distilled output instead of raw npm chatter.
6069
+ // 2026-09-01 10:55 EDT — Claude Code (Opus 5), at Bob's direction. Was a
6070
+ // raw streamed `npm install -g .`, so the terminal got npm's chatter
6071
+ // verbatim — including `npm warn allow-scripts .npmrc allow-scripts
6072
+ // setting is being ignored because --allow-scripts was passed`, a
6073
+ // warning npmglobalize provokes on itself by passing that flag, and
6074
+ // which no reader can act on. installGlobalWithRetry captures the
6075
+ // output and prints only what matters (the added/changed/removed line,
6076
+ // or distilled errors plus a log file), which is what every other
6077
+ // install path here already does.
6023
6078
  const result = await installGlobalWithRetry('.', cwd, false, 1);
6024
6079
  if (result.success) {
6025
6080
  console.log(colors.green(`✓ Installed locally: ${pkgName}@${pkgVersion}`));
@@ -6120,51 +6175,11 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
6120
6175
  // -local is testing-only and must NOT mutate package.json — packages are meant to be installed
6121
6176
  // as published public packages by end users; the bin field is whatever the published shape is.
6122
6177
  // Library members (no bin) are silently skipped: nothing for global install to expose.
6178
+ // 2026-09-01 16:30 EDT — Claude Code (Opus 5): this was a verbatim copy of
6179
+ // doLocalInstall (the 10:55 output-capture note lives there now). One path,
6180
+ // so the .commitmsg recording added today lands in both entry points.
6123
6181
  if (local) {
6124
- const pkg = readPackageJson(cwd);
6125
- const pkgName = pkg.name || path.basename(cwd);
6126
- const pkgVersion = pkg.version || '0.0.0';
6127
- console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
6128
- console.log(colors.dim('Skipping transform/publish — installing with file: deps as-is'));
6129
- if (!pkg.bin) {
6130
- console.log(colors.dim(` (library — skipping global install)`));
6131
- return true;
6132
- }
6133
- if (dryRun) {
6134
- console.log(' [dry-run] Would run: npm install -g .');
6135
- if (wsl)
6136
- console.log(' [dry-run] Would run: wsl npm install -g .');
6137
- return true;
6138
- }
6139
- // 2026-09-01 10:55 EDT — Claude Code (Opus 5), at Bob's direction. Was a
6140
- // raw streamed `npm install -g .`, so the terminal got npm's chatter
6141
- // verbatim — including `npm warn allow-scripts .npmrc allow-scripts
6142
- // setting is being ignored because --allow-scripts was passed`, a
6143
- // warning npmglobalize provokes on itself by passing that flag, and
6144
- // which no reader can act on. installGlobalWithRetry captures the
6145
- // output and prints only what matters (the added/changed/removed line,
6146
- // or distilled errors plus a log file), which is what every other
6147
- // install path here already does.
6148
- const result = await installGlobalWithRetry('.', cwd, false, 1);
6149
- if (result.success) {
6150
- console.log(colors.green(`✓ Installed locally: ${pkgName}@${pkgVersion}`));
6151
- }
6152
- else {
6153
- console.error(colors.red(`✗ Local install failed`));
6154
- console.error(colors.yellow(' Try running manually: npm install -g .'));
6155
- return false;
6156
- }
6157
- if (wsl) {
6158
- console.log(`Installing ${pkgName} in WSL (local)...`);
6159
- const wslResult = await installInWsl(['npm', 'install', '-g', '.'], { cwd });
6160
- if (wslResult.success) {
6161
- console.log(colors.green(`✓ Installed in WSL: ${pkgName}@${pkgVersion}`));
6162
- }
6163
- else {
6164
- console.error(colors.yellow('✗ WSL install failed (is npm installed in WSL?)'));
6165
- }
6166
- }
6167
- return true;
6182
+ return doLocalInstall(cwd, options);
6168
6183
  }
6169
6184
  // Prescan the file: dep graph up front — surface all problems before
6170
6185
  // any transform/publish, so the user can fix them once and run clean.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.210",
3
+ "version": "1.0.212",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",