@bobfrankston/npmglobalize 1.0.221 → 1.0.223
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 +24 -12
- package/cli.js +25 -12
- package/lib.d.ts +5 -2
- package/lib.js +75 -23
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -304,7 +304,7 @@ Notes:
|
|
|
304
304
|
- **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`).
|
|
305
305
|
- If both `-m` and `.commitmsg` are present, `-m` wins and `.commitmsg` is left alone (not consumed).
|
|
306
306
|
- If publish fails, `.commitmsg` is preserved for the next attempt.
|
|
307
|
-
- 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).
|
|
307
|
+
- Under `-local-install` (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-install).
|
|
308
308
|
- `.commitmsg` is auto-added to `.npmignore` (security pattern) so it never leaks into the tarball.
|
|
309
309
|
|
|
310
310
|
### 🔧 Git Integration & Error Recovery
|
|
@@ -467,9 +467,11 @@ not what you meant to publish, so npmglobalize lists the conflicted files and st
|
|
|
467
467
|
```
|
|
468
468
|
-install, -i Install globally after publish (from registry)
|
|
469
469
|
-link Install globally via symlink (npm install -g .)
|
|
470
|
-
-local
|
|
471
|
-
|
|
472
|
-
|
|
470
|
+
-local-install Install from the local directory only — skip transform/publish, just
|
|
471
|
+
npm install -g . with file: deps as-is (also -localinstall; -local is
|
|
472
|
+
the deprecated old spelling). Persisted; a .commitmsg is still logged
|
|
473
|
+
to npmchanges.md as "(local)"
|
|
474
|
+
-global Clear a persisted -local-install in .globalize.json5 — back to the normal
|
|
473
475
|
transform/publish flow (publishes to npm again)
|
|
474
476
|
-wsl Also install in WSL
|
|
475
477
|
-once Don't persist flags to .globalize.json5
|
|
@@ -772,6 +774,10 @@ Cycle-safe via a shared visited set; each project is built at most once per run.
|
|
|
772
774
|
|
|
773
775
|
This complements the existing publish cascade (which ensures version refs are correct) by closing the build-freshness gap that `npm install` alone left open.
|
|
774
776
|
|
|
777
|
+
#### `bin` shebang
|
|
778
|
+
|
|
779
|
+
Every file named in `package.json` `bin` must start with `#!/usr/bin/env node`. npm's Windows `.cmd` shim doesn't care, but the symlink npm creates on Linux, WSL and macOS execs the file directly, and without the shebang `sh` tries to run it and fails with a syntax error. Before each project is built, `npmglobalize` checks each `bin` file and adds the line if it is missing — in the `.ts` source when there is one (tsc carries it through to the emitted `.js`, and the touched source makes the freshness check rebuild), otherwise in the `.js` itself. A leading BOM, which would also defeat the shebang, is removed at the same time. A `bin` entry whose file does not exist yet is reported as a warning.
|
|
780
|
+
|
|
775
781
|
#### Import maps (`importgen`) as a build step
|
|
776
782
|
|
|
777
783
|
Browser projects that use [`importgen`](https://www.npmjs.com/package/@bobfrankston/importgen) have historically regenerated their import map from `.vscode/tasks.json`, which only runs when VS Code opens the folder — so a command-line or CI build could publish a stale map. `npmglobalize` treats the import map as a build product and moves the step into the package's own `build` script, where every build path picks it up.
|
|
@@ -838,7 +844,7 @@ Both `-flag` and `--flag` are accepted. Single-dash is the primary convention:
|
|
|
838
844
|
```bash
|
|
839
845
|
npmglobalize -patch # same as --patch
|
|
840
846
|
npmglobalize -np # same as --nopublish
|
|
841
|
-
npmglobalize -local
|
|
847
|
+
npmglobalize -local-install # same as --local-install
|
|
842
848
|
```
|
|
843
849
|
|
|
844
850
|
### Persistent vs One-Shot Flags
|
|
@@ -846,7 +852,7 @@ npmglobalize -local # same as --local
|
|
|
846
852
|
Some flags are **persisted** to `.globalize.json5` when set from the CLI:
|
|
847
853
|
- `-install`, `-link`, `-wsl`, `-files`, `-fix` — install/build preferences
|
|
848
854
|
- `-np` (noPublish) — once set, prevents accidental publishes
|
|
849
|
-
- `-local` — remembers "this project is local-only" (clear with `-global`)
|
|
855
|
+
- `-local-install` — remembers "this project is local-only" (clear with `-global`)
|
|
850
856
|
- `-git`/`-npm` visibility
|
|
851
857
|
|
|
852
858
|
Other flags are **one-shot** (never persisted):
|
|
@@ -859,14 +865,14 @@ Use `-once` to prevent any flag from persisting on that run:
|
|
|
859
865
|
npmglobalize -np -once # No-publish this run only, don't remember it
|
|
860
866
|
```
|
|
861
867
|
|
|
862
|
-
### Local Install (`-local`)
|
|
868
|
+
### Local Install (`-local-install`)
|
|
863
869
|
|
|
864
870
|
Skip all transform/publish logic and just run `npm install -g .` with `file:` deps as-is. Use this when you want to install a CLI tool locally for your own use without publishing anything:
|
|
865
871
|
|
|
866
872
|
```bash
|
|
867
|
-
npmglobalize -local
|
|
868
|
-
npmglobalize -local -wsl
|
|
869
|
-
npmglobalize -global
|
|
873
|
+
npmglobalize -local-install # Install globally from the local directory
|
|
874
|
+
npmglobalize -local-install -wsl # Also install in WSL
|
|
875
|
+
npmglobalize -global # Back to the normal transform/publish flow (publishes to npm)
|
|
870
876
|
```
|
|
871
877
|
|
|
872
878
|
This is useful for:
|
|
@@ -874,7 +880,13 @@ This is useful for:
|
|
|
874
880
|
- Testing a CLI before publishing
|
|
875
881
|
- Projects with `file:` deps that should stay as-is
|
|
876
882
|
|
|
877
|
-
`-
|
|
883
|
+
`-localinstall` is accepted as well. The old spelling `-local` still works but prints a
|
|
884
|
+
deprecation note; it was renamed (2026-09-07) because "local" read as "local mode" rather
|
|
885
|
+
than "install from the local directory".
|
|
886
|
+
|
|
887
|
+
`-local-install` is persisted to `.globalize.json5` (`"localInstall": true`; the older
|
|
888
|
+
`"local"` key is still read and is rewritten to the new name the next time the file is
|
|
889
|
+
saved), so a bare
|
|
878
890
|
`npmglobalize` keeps doing local installs until you run `-global` (or edit the
|
|
879
891
|
file). Nothing is committed, bumped, or published, but a `.commitmsg` is still
|
|
880
892
|
consumed: it is appended to `npmchanges.md` under a
|
|
@@ -921,7 +933,7 @@ npmglobalize -install -wsl
|
|
|
921
933
|
npmglobalize -link -wsl
|
|
922
934
|
|
|
923
935
|
# Install locally without publishing (file: deps stay as-is)
|
|
924
|
-
npmglobalize -local
|
|
936
|
+
npmglobalize -local-install
|
|
925
937
|
|
|
926
938
|
# Restore original file: references
|
|
927
939
|
npmglobalize -cleanup
|
package/cli.js
CHANGED
|
@@ -70,9 +70,11 @@ Dependency Options:
|
|
|
70
70
|
Install Options:
|
|
71
71
|
-install, -i Global install after publish (from registry)
|
|
72
72
|
-link Global install via symlink (npm install -g .)
|
|
73
|
-
-local
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
-local-install Install from the local directory only — skip transform/publish, just
|
|
74
|
+
npm install -g . with file: deps as-is (also -localinstall; -local is
|
|
75
|
+
the deprecated old spelling). Persisted; a .commitmsg is still logged
|
|
76
|
+
to npmchanges.md as "(local)"
|
|
77
|
+
-global Clear a persisted -local-install in .globalize.json5 — back to the normal
|
|
76
78
|
transform/publish flow (publishes to npm again)
|
|
77
79
|
-wsl Also install globally in WSL
|
|
78
80
|
-freeze Freeze node_modules (replace symlinks with real copies for network shares)
|
|
@@ -157,8 +159,8 @@ Examples:
|
|
|
157
159
|
npmglobalize -fix Fix security vulnerabilities
|
|
158
160
|
npmglobalize -install -wsl Release + install on Windows and WSL (from registry)
|
|
159
161
|
npmglobalize -link -wsl Release + link on Windows and WSL (symlink)
|
|
160
|
-
npmglobalize -local
|
|
161
|
-
npmglobalize -local -wsl
|
|
162
|
+
npmglobalize -local-install Install from the local directory, file: deps as-is (no publish)
|
|
163
|
+
npmglobalize -local-install -wsl Local install on Windows and WSL
|
|
162
164
|
npmglobalize -global Leave local-only mode; publish to npm from now on
|
|
163
165
|
npmglobalize -np Just transform, no publish (remembered in config)
|
|
164
166
|
npmglobalize -cleanup Restore original dependencies
|
|
@@ -228,18 +230,29 @@ function parseArgs(args) {
|
|
|
228
230
|
case '-cleanup':
|
|
229
231
|
options.cleanup = true;
|
|
230
232
|
break;
|
|
233
|
+
// 2026-09-07 — Claude Code (Fable 5.1), at Bob's direction: "-local is
|
|
234
|
+
// confusing" — it read like "local mode" / "local deps" rather than "install
|
|
235
|
+
// from the local directory". Renamed to -local-install (-localinstall also
|
|
236
|
+
// accepted). -local still works but says so, so muscle memory isn't broken
|
|
237
|
+
// and the old spelling is phased out rather than silently kept alive.
|
|
238
|
+
// The .globalize.json5 key was renamed "local" → "localInstall" the same day;
|
|
239
|
+
// readConfig accepts the old name and the next persist rewrites it.
|
|
231
240
|
case '-local':
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
241
|
+
console.log(colors.yellow('! -local is deprecated — use -local-install (or -localinstall). Same meaning: npm install -g . from the local directory, no publish.'));
|
|
242
|
+
// falls through
|
|
243
|
+
case '-local-install':
|
|
244
|
+
case '-localinstall':
|
|
245
|
+
options.localInstall = true;
|
|
246
|
+
options.explicitKeys.add('localInstall');
|
|
247
|
+
break;
|
|
248
|
+
// 2026-09-01 16:30 EDT — Claude Code (Opus 5), at Bob's direction. -local-install
|
|
236
249
|
// persists to .globalize.json5 but had no counterpart, so leaving local-only
|
|
237
250
|
// mode meant hand-editing the config. Same shape as -publish for -np.
|
|
238
251
|
// 2026-09-01 15:00 EDT — Bob: "-global makes more sense, -nolocal is confusing";
|
|
239
252
|
// -nolocal dropped, -global is the only spelling.
|
|
240
253
|
case '-global':
|
|
241
|
-
options.
|
|
242
|
-
options.explicitKeys.add('
|
|
254
|
+
options.localInstall = false;
|
|
255
|
+
options.explicitKeys.add('localInstall');
|
|
243
256
|
break;
|
|
244
257
|
case '-install':
|
|
245
258
|
case '-i':
|
|
@@ -651,7 +664,7 @@ export async function main() {
|
|
|
651
664
|
console.log(`Updated ${path.join(cwd, 'package.json')} scripts:`);
|
|
652
665
|
changes.forEach(c => console.log(` ${c}`));
|
|
653
666
|
// If no other flags need processing, exit; otherwise fall through
|
|
654
|
-
if (!cliOptions.install && !cliOptions.link && !cliOptions.
|
|
667
|
+
if (!cliOptions.install && !cliOptions.link && !cliOptions.localInstall) {
|
|
655
668
|
process.exit(0);
|
|
656
669
|
}
|
|
657
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
|
-
|
|
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 */
|
|
@@ -456,6 +457,8 @@ export declare function ensureBuildScript(cwd: string): Promise<{
|
|
|
456
457
|
* was skipped because there was nothing to build / the user declined the
|
|
457
458
|
* build-script prompt / output already up to date). Pass `forceBuild` to
|
|
458
459
|
* skip the freshness check. */
|
|
460
|
+
/** Every `bin` entry gets a `#!/usr/bin/env node` first line, added to the source if missing. */
|
|
461
|
+
export declare function ensureBinShebang(cwd: string): void;
|
|
459
462
|
export declare function buildProject(cwd: string, opts?: {
|
|
460
463
|
verbose?: boolean;
|
|
461
464
|
force?: boolean;
|
package/lib.js
CHANGED
|
@@ -312,7 +312,18 @@ export function readConfig(dir) {
|
|
|
312
312
|
}
|
|
313
313
|
try {
|
|
314
314
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
315
|
-
|
|
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
|
-
|
|
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
|
-
['"
|
|
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)'],
|
|
@@ -3536,7 +3547,48 @@ export async function ensureBuildScript(cwd) {
|
|
|
3536
3547
|
* was skipped because there was nothing to build / the user declined the
|
|
3537
3548
|
* build-script prompt / output already up to date). Pass `forceBuild` to
|
|
3538
3549
|
* skip the freshness check. */
|
|
3550
|
+
// 2026-09-07 — Claude Code (Fable 5.1), at Bob's direction: "When a program is
|
|
3551
|
+
// installed, at least locally, it needs a shebang for node. Make sure the main
|
|
3552
|
+
// program has a shebang." npm's Windows .cmd shim doesn't care, but the symlink
|
|
3553
|
+
// npm creates on Linux/WSL/macOS execs the file directly, so a bin entry
|
|
3554
|
+
// without `#!/usr/bin/env node` fails there with "syntax error" from sh. The
|
|
3555
|
+
// shebang belongs in the SOURCE (.ts): tsc carries it through to the emitted
|
|
3556
|
+
// .js, and editing the .ts bumps its mtime so the freshness check rebuilds.
|
|
3557
|
+
// Runs ahead of the build for that reason, and for every package in the
|
|
3558
|
+
// cascade, since a file: dep can be a CLI too.
|
|
3559
|
+
/** Every `bin` entry gets a `#!/usr/bin/env node` first line, added to the source if missing. */
|
|
3560
|
+
export function ensureBinShebang(cwd) {
|
|
3561
|
+
let pkg;
|
|
3562
|
+
try {
|
|
3563
|
+
pkg = readPackageJson(cwd);
|
|
3564
|
+
}
|
|
3565
|
+
catch {
|
|
3566
|
+
return;
|
|
3567
|
+
} // no package.json: nothing to check, the build reports that
|
|
3568
|
+
if (!pkg?.bin)
|
|
3569
|
+
return;
|
|
3570
|
+
const targets = typeof pkg.bin === 'string' ? [pkg.bin]
|
|
3571
|
+
: (typeof pkg.bin === 'object' ? Object.values(pkg.bin).filter((v) => typeof v === 'string') : []);
|
|
3572
|
+
for (const rel of targets) {
|
|
3573
|
+
const emitted = path.join(cwd, rel);
|
|
3574
|
+
// Prefer the TypeScript source the bin file is emitted from.
|
|
3575
|
+
const tsSibling = emitted.replace(/\.(m|c)?js$/i, '.$1ts');
|
|
3576
|
+
const file = tsSibling !== emitted && fs.existsSync(tsSibling) ? tsSibling : emitted;
|
|
3577
|
+
if (!fs.existsSync(file)) {
|
|
3578
|
+
console.log(colors.yellow(`! bin "${rel}" in ${pkg.name}: file not found (needs a #!/usr/bin/env node shebang once it exists)`));
|
|
3579
|
+
continue;
|
|
3580
|
+
}
|
|
3581
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
3582
|
+
const body = raw.startsWith('') ? raw.slice(1) : raw; // a BOM ahead of #! defeats the shebang
|
|
3583
|
+
if (body.startsWith('#!'))
|
|
3584
|
+
continue;
|
|
3585
|
+
fs.writeFileSync(file, `#!/usr/bin/env node
|
|
3586
|
+
${body}`, 'utf-8');
|
|
3587
|
+
console.log(colors.green(`+ Added #!/usr/bin/env node to ${path.relative(cwd, file)} (bin "${rel}")`));
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3539
3590
|
export async function buildProject(cwd, opts = {}) {
|
|
3591
|
+
ensureBinShebang(cwd);
|
|
3540
3592
|
// Fix removed-in-TS7 tsconfig settings up front rather than waiting for a
|
|
3541
3593
|
// build to fail on them. A deprecated `moduleResolution` is only a *hard*
|
|
3542
3594
|
// error under the tsc that flags it (TS6+, and the editor's bundled
|
|
@@ -6529,15 +6581,15 @@ export function getToolVersion() {
|
|
|
6529
6581
|
}
|
|
6530
6582
|
}
|
|
6531
6583
|
// 2026-09-01 16:30 EDT — Claude Code (Opus 5), at Bob's direction.
|
|
6532
|
-
// Under -local the run returned before any of the .commitmsg handling, so the
|
|
6584
|
+
// Under -local-install the run returned before any of the .commitmsg handling, so the
|
|
6533
6585
|
// notes a local-only package accumulated in .commitmsg were never recorded
|
|
6534
6586
|
// anywhere — they sat in the file, and the next edit overwrote them. A local
|
|
6535
6587
|
// install is still a change worth a history line, so the same npmchanges.md
|
|
6536
6588
|
// gets the entry, tagged "(local)" because nothing was published or bumped
|
|
6537
6589
|
// (several local runs may legitimately share one version number). No git
|
|
6538
|
-
// activity: -local is the path taken when there is often no repo at all, and
|
|
6590
|
+
// activity: -local-install is the path taken when there is often no repo at all, and
|
|
6539
6591
|
// when there is one the next real publish commits npmchanges.md with the rest.
|
|
6540
|
-
/** Consume .commitmsg for a -local run: append to npmchanges.md, delete the file. */
|
|
6592
|
+
/** Consume .commitmsg for a -local-install run: append to npmchanges.md, delete the file. */
|
|
6541
6593
|
function recordLocalChange(cwd, version, dryRun) {
|
|
6542
6594
|
const commitMsgPath = path.join(cwd, '.commitmsg');
|
|
6543
6595
|
if (!fs.existsSync(commitMsgPath))
|
|
@@ -6572,8 +6624,8 @@ function recordLocalChange(cwd, version, dryRun) {
|
|
|
6572
6624
|
console.error(colors.yellow(` Warning: could not update npmchanges.md: ${err.message}`));
|
|
6573
6625
|
}
|
|
6574
6626
|
}
|
|
6575
|
-
/** Perform local-only install (npm install -g .) — the single -local path, reached
|
|
6576
|
-
* from the -local flag / config and from the git-init prompts' "local only" choice. */
|
|
6627
|
+
/** Perform local-only install (npm install -g .) — the single -local-install path, reached
|
|
6628
|
+
* from the -local-install flag / config and from the git-init prompts' "local only" choice. */
|
|
6577
6629
|
async function doLocalInstall(cwd, options) {
|
|
6578
6630
|
const { dryRun = false, wsl = false } = options;
|
|
6579
6631
|
const pkg = readPackageJson(cwd);
|
|
@@ -6628,7 +6680,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
6628
6680
|
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
|
|
6629
6681
|
publishDepsYes = false, // -pd: auto-yes to dep-cascade prompts (private only)
|
|
6630
6682
|
publicDeps = false, // -public-deps: cascade public visibility to all deps
|
|
6631
|
-
noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false,
|
|
6683
|
+
noPrescan = false, forcePublish = false, fix = true, fixTags = false, rebase = false, show = false, localInstall = false, freeze = false, usePaths = true, allowTs, adopt = false, importCheck = false } = options;
|
|
6632
6684
|
// 2026-09-06 — Claude Code (Fable 5.1), at Bob's direction: a directory marked
|
|
6633
6685
|
// `.stale` is retired. Refuse to build, publish or install it — and because the
|
|
6634
6686
|
// dep cascade reaches deps through this same function, refuse to cascade into
|
|
@@ -6692,8 +6744,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
6692
6744
|
settings.push('--force-publish');
|
|
6693
6745
|
if (configOptions.show)
|
|
6694
6746
|
settings.push('--show');
|
|
6695
|
-
if (configOptions.
|
|
6696
|
-
settings.push('-local');
|
|
6747
|
+
if (configOptions.localInstall)
|
|
6748
|
+
settings.push('-local-install');
|
|
6697
6749
|
if (configOptions.freeze)
|
|
6698
6750
|
settings.push('-freeze');
|
|
6699
6751
|
if (configOptions.usePaths === false)
|
|
@@ -6710,14 +6762,14 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
6710
6762
|
}
|
|
6711
6763
|
}
|
|
6712
6764
|
console.log('');
|
|
6713
|
-
// -local: skip all transform/publish, just install from local directory with file: deps intact.
|
|
6714
|
-
// -local is testing-only and must NOT mutate package.json — packages are meant to be installed
|
|
6765
|
+
// -local-install: skip all transform/publish, just install from local directory with file: deps intact.
|
|
6766
|
+
// -local-install is testing-only and must NOT mutate package.json — packages are meant to be installed
|
|
6715
6767
|
// as published public packages by end users; the bin field is whatever the published shape is.
|
|
6716
6768
|
// Library members (no bin) are silently skipped: nothing for global install to expose.
|
|
6717
6769
|
// 2026-09-01 16:30 EDT — Claude Code (Opus 5): this was a verbatim copy of
|
|
6718
6770
|
// doLocalInstall (the 10:55 output-capture note lives there now). One path,
|
|
6719
6771
|
// so the .commitmsg recording added today lands in both entry points.
|
|
6720
|
-
if (
|
|
6772
|
+
if (localInstall) {
|
|
6721
6773
|
return doLocalInstall(cwd, options);
|
|
6722
6774
|
}
|
|
6723
6775
|
// Prescan the file: dep graph up front — surface all problems before
|
|
@@ -6947,7 +6999,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
6947
6999
|
+ ' 5) Abort\nChoice [1]:', ['1', '2', '3', '4', '5', '']);
|
|
6948
7000
|
if (choice === '4') {
|
|
6949
7001
|
console.log(colors.dim('Switching to local-only mode...'));
|
|
6950
|
-
writeConfig(cwd, { ...configOptions,
|
|
7002
|
+
writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
|
|
6951
7003
|
return doLocalInstall(cwd, options);
|
|
6952
7004
|
}
|
|
6953
7005
|
if (choice === '5') {
|
|
@@ -6976,7 +7028,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
6976
7028
|
+ ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
|
|
6977
7029
|
if (choice === '3') {
|
|
6978
7030
|
console.log(colors.dim('Switching to local-only mode...'));
|
|
6979
|
-
writeConfig(cwd, { ...configOptions,
|
|
7031
|
+
writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
|
|
6980
7032
|
return doLocalInstall(cwd, options);
|
|
6981
7033
|
}
|
|
6982
7034
|
if (choice === '4') {
|
|
@@ -7019,7 +7071,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
7019
7071
|
+ ' 4) Abort\nChoice [1]:', ['1', '2', '3', '4', '']);
|
|
7020
7072
|
if (choice === '3') {
|
|
7021
7073
|
console.log(colors.dim('Switching to local-only mode...'));
|
|
7022
|
-
writeConfig(cwd, { ...configOptions,
|
|
7074
|
+
writeConfig(cwd, { ...configOptions, localInstall: true }, new Set(['localInstall']));
|
|
7023
7075
|
return doLocalInstall(cwd, options);
|
|
7024
7076
|
}
|
|
7025
7077
|
if (choice === '4') {
|
|
@@ -7834,8 +7886,8 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
7834
7886
|
surprises.push(`usePaths=false${fromConfig('usePaths')} — file: deps resolved from npm, not siblings`);
|
|
7835
7887
|
if (configOptions.freeze || freeze)
|
|
7836
7888
|
surprises.push(`freeze=true${fromConfig('freeze')}`);
|
|
7837
|
-
if (configOptions.
|
|
7838
|
-
surprises.push(`
|
|
7889
|
+
if (configOptions.localInstall || localInstall)
|
|
7890
|
+
surprises.push(`localInstall=true${fromConfig('localInstall')}`);
|
|
7839
7891
|
if (configOptions.files === false || files === false)
|
|
7840
7892
|
surprises.push(`files=false${fromConfig('files')} — npm versions left in package.json`);
|
|
7841
7893
|
if (configOptions.allowTs === true || allowTs === true)
|
|
@@ -9017,15 +9069,15 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
|
|
|
9017
9069
|
console.log(`Packages (${packages.length}): ${packages.map(p => p.name).join(', ')}`);
|
|
9018
9070
|
console.log(`Publish order: ${publishOrder.join(' → ')}`);
|
|
9019
9071
|
console.log('');
|
|
9020
|
-
// Warn if -local / -install are present at the workspace root: those are
|
|
9072
|
+
// Warn if -local-install / -install are present at the workspace root: those are
|
|
9021
9073
|
// component-level concerns. In workspace mode they only act on members
|
|
9022
9074
|
// that have a `bin` field; libraries are silently skipped. Telling the
|
|
9023
9075
|
// user up front avoids the surprise of "I asked for install but most
|
|
9024
9076
|
// packages didn't install."
|
|
9025
9077
|
const installSources = [];
|
|
9026
|
-
if (options.
|
|
9027
|
-
const src = configOptions.
|
|
9028
|
-
installSources.push(`-local (${src})`);
|
|
9078
|
+
if (options.localInstall || configOptions.localInstall) {
|
|
9079
|
+
const src = configOptions.localInstall && !options.localInstall ? '.globalize.json5' : 'CLI';
|
|
9080
|
+
installSources.push(`-local-install (${src})`);
|
|
9029
9081
|
}
|
|
9030
9082
|
if (options.install || configOptions.install) {
|
|
9031
9083
|
const src = configOptions.install && !options.install ? '.globalize.json5' : 'CLI';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/npmglobalize",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.223",
|
|
4
4
|
"description": "Transform file: dependencies to npm versions for publishing",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@bobfrankston/freezepak": "^0.1.9",
|
|
35
|
-
"@bobfrankston/importgen": "^0.1.
|
|
36
|
-
"@bobfrankston/themecolors": "^0.1.
|
|
35
|
+
"@bobfrankston/importgen": "^0.1.43",
|
|
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",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
".transformedSnapshot": {
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@bobfrankston/freezepak": "^0.1.9",
|
|
63
|
-
"@bobfrankston/importgen": "^0.1.
|
|
64
|
-
"@bobfrankston/themecolors": "^0.1.
|
|
63
|
+
"@bobfrankston/importgen": "^0.1.43",
|
|
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",
|