@bobfrankston/npmglobalize 1.0.88 → 1.0.89

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.
@@ -23,7 +23,9 @@
23
23
  "Bash(wsl ls:*)",
24
24
  "Bash(cmd.exe /c \"dir y:\\\\dev\\\\homecontrol\\\\utils\\\\addone /a /b\")",
25
25
  "Bash(cmd.exe /c \"dir /a /b y:\\\\dev\\\\homecontrol\\\\utils\\\\addone\")",
26
- "Bash(icacls:*)"
26
+ "Bash(icacls:*)",
27
+ "Bash(npm install:*)",
28
+ "Bash(echo:*)"
27
29
  ]
28
30
  }
29
31
  }
package/README.md CHANGED
@@ -224,78 +224,80 @@ Publishing requires being on a branch so commits and tags can be properly tracke
224
224
 
225
225
  ## Command Reference
226
226
 
227
- <!-- NOTE: Keep this in sync with the --help output in cli.ts printHelp().
227
+ <!-- NOTE: Keep this in sync with the -help output in cli.ts printHelp().
228
228
  The README expands on options with examples and context;
229
- cli.ts is the concise quick-reference. Update both when adding/changing flags. -->
229
+ cli.ts is the concise quick-reference. Update both when adding/changing flags.
230
+ Both -flag and --flag are accepted; single-dash is shown as primary. -->
230
231
 
231
232
  ### Release Options
232
233
  ```
233
- --patch Bump patch version (default)
234
- --minor Bump minor version
235
- --major Bump major version
236
- --nopublish, -np Just transform, don't publish
237
- --cleanup Restore file: dependencies from backup
238
- -m, --message <msg> Custom commit message (forces release even without changes)
234
+ -patch Bump patch version (default)
235
+ -minor Bump minor version
236
+ -major Bump major version
237
+ -nopublish, -np Just transform, don't publish (persisted to config)
238
+ -cleanup Restore file: dependencies from .dependencies backup
239
+ -m, -message <msg> Custom commit message (forces release even without changes)
239
240
  ```
240
241
 
241
242
  ### Dependency Options
242
243
  ```
243
- --update-deps, -ud Update package.json to latest versions (safe: minor/patch)
244
- --update-major Allow major version updates (breaking changes)
245
- --no-publish-deps, -npd Skip auto-publishing file: dependencies
246
- --force-publish Republish dependencies even if version exists
247
- --fix Run npm audit fix after transformation
248
- --no-fix Don't run npm audit
244
+ -update-deps, -ud Update package.json to latest versions (safe: minor/patch)
245
+ -update-major Allow major version updates (breaking changes)
246
+ -no-publish-deps, -npd Skip auto-publishing file: dependencies
247
+ -force-publish Republish dependencies even if version exists
248
+ -fix Run npm audit fix after transformation
249
+ -no-fix Don't run npm audit
249
250
  ```
250
251
 
251
252
  ### Install Options
252
253
  ```
253
- --install, -i Install globally after publish (from registry)
254
- --link Install globally via symlink (npm install -g .)
255
- --wsl Also install in WSL
256
- --once Don't persist flags to .globalize.json5
254
+ -install, -i Install globally after publish (from registry)
255
+ -link Install globally via symlink (npm install -g .)
256
+ -local Local install only — skip transform/publish, just npm install -g .
257
+ -wsl Also install in WSL
258
+ -once Don't persist flags to .globalize.json5
257
259
  ```
258
260
 
259
261
  ### Mode Options
260
262
  ```
261
- --files Keep file: paths after publish (default)
262
- --nofiles Keep npm versions permanently
263
+ -files Keep file: paths after publish (default)
264
+ -nofiles Keep npm versions permanently
263
265
  ```
264
266
 
265
267
  ### Git/npm Visibility
266
268
  ```
267
- --git private Make git repo private (default)
268
- --git public Make git repo public (requires confirmation)
269
- --npm private Mark npm package private (skip publish) (default)
270
- --npm public Publish to npm
269
+ -git private Make git repo private (default)
270
+ -git public Make git repo public (requires confirmation)
271
+ -npm private Mark npm package private (skip publish) (default)
272
+ -npm public Publish to npm
271
273
  ```
272
274
 
273
275
  ### Workspace Options
274
276
  ```
275
- -w, --workspace <pkg> Filter to specific package (repeatable)
276
- --no-workspace Disable workspace mode at a workspace root
277
- --continue-on-error Continue if a package fails in workspace mode
277
+ -w, -workspace <pkg> Filter to specific package (repeatable)
278
+ -no-workspace Disable workspace mode at a workspace root
279
+ -continue-on-error Continue if a package fails in workspace mode
278
280
  ```
279
281
 
280
282
  Workspace mode is auto-detected when run from a root with `"private": true` and a `workspaces` field.
281
283
 
282
284
  ### Other Options
283
285
  ```
284
- --init Initialize git/npm if needed (creates .gitignore, .npmignore,
286
+ -init Initialize git/npm if needed (creates .gitignore, .npmignore,
285
287
  .gitattributes, and configures git for LF line endings)
286
- --force Continue despite git errors
287
- --dry-run Preview what would happen
288
- --quiet Suppress npm warnings (default)
289
- --verbose Show detailed output
290
- --conform Update .gitignore/.npmignore/.gitattributes to best practices
288
+ -force Continue despite git errors
289
+ -dry-run Preview what would happen
290
+ -quiet Suppress npm warnings (default)
291
+ -verbose Show detailed output
292
+ -conform Update .gitignore/.npmignore/.gitattributes to best practices
291
293
  and configure git for LF line endings (fixes existing repos)
292
- --asis Skip ignore file checks (or set "asis": true in .globalize.json5)
293
- --fix-tags Automatically fix version/tag mismatches
294
- --rebase Automatically rebase if local is behind remote
295
- --show Show package.json dependency changes
296
- --package, -pkg Update package.json scripts to use npmglobalize (see below)
297
- -h, --help Show help
298
- -v, --version Show version
294
+ -asis Skip ignore file checks (or set "asis": true in .globalize.json5)
295
+ -fix-tags Automatically fix version/tag mismatches
296
+ -rebase Automatically rebase if local is behind remote
297
+ -show Show package.json dependency changes
298
+ -package, -pkg Update package.json scripts to use npmglobalize (see below)
299
+ -h, -help Show help
300
+ -v, -version Show version
299
301
  ```
300
302
 
301
303
  ## Using in package.json
@@ -391,6 +393,70 @@ npmglobalize --dry-run # See what would happen
391
393
  11. **Restores** file: references (if `--files`, default)
392
394
  12. **Runs audit** (shows security status)
393
395
 
396
+ ## Operational Details
397
+
398
+ ### The `.dependencies` Backup Mechanism
399
+
400
+ When `npmglobalize` transforms `file:` references to npm versions, it stores the originals in a `.dependencies` field (and `.devDependencies`, etc.) inside `package.json`. This is the central safety mechanism — it allows recovery from any failure during the publish cycle.
401
+
402
+ **How it works:**
403
+ - Before transforming, the original `file:` entries are copied to `.dependencies`
404
+ - After a successful publish, the originals are restored from `.dependencies` and the backup is removed
405
+ - If the process crashes, is interrupted, or exits early (e.g., private package, `--nopublish`), `.dependencies` remains in `package.json`
406
+ - On the **next run**, `transformDeps` detects `.dependencies`, restores the originals first, then re-transforms — so data is never lost
407
+
408
+ **Recovery commands:**
409
+ ```bash
410
+ npmglobalize -cleanup # Manually restore file: deps from .dependencies backup
411
+ ```
412
+
413
+ **Why not just restore immediately on error?** The `.dependencies` approach is deliberately persistent. If the tool crashes hard (killed process, power failure, npm timeout), there's no cleanup code to run. The backup in `package.json` survives because it was written before the risky operations began. The next run self-heals.
414
+
415
+ ### Flag Conventions
416
+
417
+ Both `-flag` and `--flag` are accepted. Single-dash is the primary convention:
418
+ ```bash
419
+ npmglobalize -patch # same as --patch
420
+ npmglobalize -np # same as --nopublish
421
+ npmglobalize -local # same as --local
422
+ ```
423
+
424
+ ### Persistent vs One-Shot Flags
425
+
426
+ Some flags are **persisted** to `.globalize.json5` when set from the CLI:
427
+ - `-install`, `-link`, `-wsl`, `-files`, `-fix` — install/build preferences
428
+ - `-np` (noPublish) — once set, prevents accidental publishes
429
+ - `-local` — remembers "this project is local-only"
430
+ - `-git`/`-npm` visibility
431
+
432
+ Other flags are **one-shot** (never persisted):
433
+ - `-cleanup`, `-init`, `-dry-run`, `-message` — situational actions
434
+ - `-update-deps`, `-update-major`, `-force-publish` — explicit per-run choices
435
+ - `-conform`, `-asis` — one-time fixes
436
+
437
+ Use `-once` to prevent any flag from persisting on that run:
438
+ ```bash
439
+ npmglobalize -np -once # No-publish this run only, don't remember it
440
+ ```
441
+
442
+ ### Local Install (`-local`)
443
+
444
+ 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:
445
+
446
+ ```bash
447
+ npmglobalize -local # Install globally from local directory
448
+ npmglobalize -local -wsl # Also install in WSL
449
+ ```
450
+
451
+ This is useful for:
452
+ - Development tools you don't publish
453
+ - Testing a CLI before publishing
454
+ - Projects with `file:` deps that should stay as-is
455
+
456
+ ### Private Packages
457
+
458
+ 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.
459
+
394
460
  ## Version Checking
395
461
 
396
462
  When publishing file: dependencies, checks if each version exists on npm:
@@ -408,34 +474,37 @@ npmglobalize
408
474
  npmglobalize y:\dev\myproject
409
475
 
410
476
  # Auto-fix tag conflicts and rebase
411
- npmglobalize --fix-tags --rebase
477
+ npmglobalize -fix-tags -rebase
412
478
 
413
479
  # Release with updates and security fixes
414
- npmglobalize --update-deps --fix
480
+ npmglobalize -update-deps -fix
415
481
 
416
482
  # Just update package.json, don't publish
417
- npmglobalize -np --update-deps
483
+ npmglobalize -np -update-deps
418
484
 
419
485
  # Force republish all dependencies
420
- npmglobalize --force-publish --update-major
486
+ npmglobalize -force-publish -update-major
421
487
 
422
488
  # Release + install on Windows and WSL (from registry)
423
- npmglobalize --install --wsl
489
+ npmglobalize -install -wsl
424
490
 
425
491
  # Release + link on Windows and WSL (symlink)
426
- npmglobalize --link --wsl
492
+ npmglobalize -link -wsl
493
+
494
+ # Install locally without publishing (file: deps stay as-is)
495
+ npmglobalize -local
427
496
 
428
497
  # Restore original file: references
429
- npmglobalize --cleanup
498
+ npmglobalize -cleanup
430
499
 
431
500
  # Initialize new git repo + release
432
- npmglobalize --init
501
+ npmglobalize -init
433
502
 
434
503
  # Migrate package.json scripts to use npmglobalize
435
- npmglobalize --package
504
+ npmglobalize -package
436
505
 
437
506
  # Preview what would happen
438
- npmglobalize --dry-run --verbose
507
+ npmglobalize -dry-run -verbose
439
508
  ```
440
509
 
441
510
  ## Authentication
package/cli.js CHANGED
@@ -15,83 +15,88 @@ npmglobalize - Transform file: dependencies to npm versions for publishing
15
15
 
16
16
  Usage: npmglobalize [path] [options]
17
17
 
18
+ Note: Both -flag and --flag are accepted (e.g., -patch and --patch are the same).
19
+
18
20
  Arguments:
19
21
  path Path to the project directory (default: current directory)
20
22
 
21
23
  Release Options:
22
- --patch Bump patch version (default)
23
- --minor Bump minor version
24
- --major Bump major version
25
- --nopublish, -np Just transform, don't publish
26
- --cleanup Restore from .dependencies
27
- -m, --message <msg> Custom commit message (forces release even without changes)
24
+ -patch Bump patch version (default)
25
+ -minor Bump minor version
26
+ -major Bump major version
27
+ -nopublish, -np Just transform, don't publish (persisted to config)
28
+ -cleanup Restore from .dependencies
29
+ -m, -message <msg> Custom commit message (forces release even without changes)
28
30
 
29
31
  Dependency Options:
30
- --update-deps, -ud Update package.json to latest (minor/patch only, safe)
31
- --update-major Allow major version updates (breaking changes)
32
- --no-publish-deps, -npd Don't auto-publish file: dependencies (use with caution)
33
- --force-publish Republish dependencies even if version exists
34
- --fix Run npm audit fix after transformation
32
+ -update-deps, -ud Update package.json to latest (minor/patch only, safe)
33
+ -update-major Allow major version updates (breaking changes)
34
+ -no-publish-deps, -npd Don't auto-publish file: dependencies (use with caution)
35
+ -force-publish Republish dependencies even if version exists
36
+ -fix Run npm audit fix after transformation
35
37
 
36
38
  Install Options:
37
- --install, -i Global install after publish (from registry)
38
- --link Global install via symlink (npm install -g .)
39
- --wsl Also install globally in WSL
40
- --once Don't persist flags to .globalize.json5
39
+ -install, -i Global install after publish (from registry)
40
+ -link Global install via symlink (npm install -g .)
41
+ -local Local install only skip transform/publish, just npm install -g .
42
+ -wsl Also install globally in WSL
43
+ -once Don't persist flags to .globalize.json5
41
44
 
42
45
  Mode Options:
43
- --files Keep file: paths after publish (default)
44
- --nofiles Keep npm versions permanently
46
+ -files Keep file: paths after publish (default)
47
+ -nofiles Keep npm versions permanently
45
48
 
46
49
  Git/npm Visibility:
47
- --git private Make git repo private (default)
48
- --git public Make git repo public (requires confirmation)
49
- --npm private Mark npm package private (skip publish) (default)
50
- --npm public Publish to npm
50
+ -git private Make git repo private (default)
51
+ -git public Make git repo public (requires confirmation)
52
+ -npm private Mark npm package private (skip publish) (default)
53
+ -npm public Publish to npm
51
54
 
52
55
  Workspace Options:
53
- -w, --workspace <pkg> Filter to specific package (repeatable)
54
- --no-workspace Disable workspace mode at a workspace root
55
- --continue-on-error Continue if a package fails in workspace mode
56
+ -w, -workspace <pkg> Filter to specific package (repeatable)
57
+ -no-workspace Disable workspace mode at a workspace root
58
+ -continue-on-error Continue if a package fails in workspace mode
56
59
 
57
60
  Other Options:
58
- --init Initialize git/npm if needed
59
- --force Continue despite git errors
60
- --dry-run Preview what would happen
61
- --quiet Suppress npm warnings (default)
62
- --verbose Show detailed output
63
- --conform Update .gitignore/.npmignore to best practices
64
- --asis Skip ignore file checks (or set "asis": true in .globalize.json5)
65
- --rebase Automatically rebase if local is behind remote
66
- --show Show package.json dependency changes
67
- --package, -pkg Update package.json scripts to use npmglobalize
68
- -h, --help Show this help
69
- -v, --version Show version number
61
+ -init Initialize git/npm if needed
62
+ -force Continue despite git errors
63
+ -dry-run Preview what would happen
64
+ -quiet Suppress npm warnings (default)
65
+ -verbose Show detailed output
66
+ -conform Update .gitignore/.npmignore to best practices
67
+ -asis Skip ignore file checks (or set "asis": true in .globalize.json5)
68
+ -rebase Automatically rebase if local is behind remote
69
+ -show Show package.json dependency changes
70
+ -package, -pkg Update package.json scripts to use npmglobalize
71
+ -h, -help Show this help
72
+ -v, -version Show version number
70
73
 
71
74
  Examples:
72
75
  npmglobalize Transform + publish (auto-publishes file: deps)
73
76
  npmglobalize y:\\path\\to\\project Run on a different project directory
74
- npmglobalize --minor Release with minor version bump
75
- npmglobalize --fix-tags Fix version/tag mismatches before running
76
- npmglobalize --rebase Auto-rebase if behind remote
77
- npmglobalize --update-deps Safe updates (minor/patch only)
78
- npmglobalize --update-major Allow breaking changes (major updates)
77
+ npmglobalize -minor Release with minor version bump
78
+ npmglobalize -fix-tags Fix version/tag mismatches before running
79
+ npmglobalize -rebase Auto-rebase if behind remote
80
+ npmglobalize -update-deps Safe updates (minor/patch only)
81
+ npmglobalize -update-major Allow breaking changes (major updates)
79
82
  npmglobalize -npd Skip auto-publishing file: deps (use with caution)
80
- npmglobalize --force-publish Force republish all file: dependencies
81
- npmglobalize --fix Fix security vulnerabilities
82
- npmglobalize --install --wsl Release + install on Windows and WSL (from registry)
83
- npmglobalize --link --wsl Release + link on Windows and WSL (symlink)
84
- npmglobalize -np Just transform, no publish
85
- npmglobalize --cleanup Restore original dependencies
86
- npmglobalize --init Initialize new git repo + release
87
- npmglobalize --dry-run Preview what would happen
88
- npmglobalize --package Migrate scripts to use npmglobalize
83
+ npmglobalize -force-publish Force republish all file: dependencies
84
+ npmglobalize -fix Fix security vulnerabilities
85
+ npmglobalize -install -wsl Release + install on Windows and WSL (from registry)
86
+ npmglobalize -link -wsl Release + link on Windows and WSL (symlink)
87
+ npmglobalize -local Install locally with file: deps as-is (no publish)
88
+ npmglobalize -local -wsl Local install on Windows and WSL
89
+ npmglobalize -np Just transform, no publish (remembered in config)
90
+ npmglobalize -cleanup Restore original dependencies
91
+ npmglobalize -init Initialize new git repo + release
92
+ npmglobalize -dry-run Preview what would happen
93
+ npmglobalize -package Migrate scripts to use npmglobalize
89
94
 
90
95
  Workspace (auto-detected when run from a workspace root):
91
96
  npmglobalize Publish all workspace packages in dependency order
92
97
  npmglobalize -w msgcommon Publish only msgcommon
93
- npmglobalize --no-workspace Skip workspace detection, run single-package mode
94
- npmglobalize --continue-on-error Keep going if a package fails
98
+ npmglobalize -no-workspace Skip workspace detection, run single-package mode
99
+ npmglobalize -continue-on-error Keep going if a package fails
95
100
  `);
96
101
  }
97
102
  function parseArgs(args) {
@@ -105,150 +110,157 @@ function parseArgs(args) {
105
110
  const positional = [];
106
111
  for (let i = 0; i < args.length; i++) {
107
112
  const arg = args[i];
108
- switch (arg) {
109
- case '--help':
113
+ // Normalize --flag to -flag (backward compatible: --patch → -patch)
114
+ const norm = arg.replace(/^--/, '-');
115
+ switch (norm) {
116
+ case '-help':
110
117
  case '-h':
111
118
  options.help = true;
112
119
  break;
113
- case '--version':
120
+ case '-version':
114
121
  case '-v':
115
122
  options.version = true;
116
123
  break;
117
- case '--patch':
124
+ case '-patch':
118
125
  options.bump = 'patch';
119
126
  break;
120
- case '--minor':
127
+ case '-minor':
121
128
  options.bump = 'minor';
122
129
  break;
123
- case '--major':
130
+ case '-major':
124
131
  options.bump = 'major';
125
132
  break;
126
- case '--nopublish':
133
+ case '-nopublish':
127
134
  case '-np':
128
- case '--apply': // Keep for backward compatibility
135
+ case '-apply': // Keep for backward compatibility
129
136
  options.noPublish = true;
137
+ options.explicitKeys.add('noPublish');
130
138
  break;
131
- case '--cleanup':
139
+ case '-cleanup':
132
140
  options.cleanup = true;
133
141
  break;
134
- case '--install':
142
+ case '-local':
143
+ options.local = true;
144
+ options.explicitKeys.add('local');
145
+ break;
146
+ case '-install':
135
147
  case '-i':
136
148
  options.install = true;
137
149
  options.explicitKeys.add('install');
138
150
  break;
139
- case '--noinstall':
151
+ case '-noinstall':
140
152
  case '-ni':
141
153
  options.install = false;
142
154
  options.explicitKeys.add('install');
143
155
  break;
144
- case '--link':
156
+ case '-link':
145
157
  options.link = true;
146
158
  options.explicitKeys.add('link');
147
159
  break;
148
- case '--wsl':
160
+ case '-wsl':
149
161
  options.wsl = true;
150
162
  options.explicitKeys.add('wsl');
151
163
  break;
152
- case '--nowsl':
164
+ case '-nowsl':
153
165
  options.wsl = false;
154
166
  options.explicitKeys.add('wsl');
155
167
  break;
156
- case '--force':
168
+ case '-force':
157
169
  options.force = true;
158
170
  break;
159
- case '--files':
171
+ case '-files':
160
172
  options.files = true;
161
173
  options.explicitKeys.add('files');
162
174
  break;
163
- case '--nofiles':
175
+ case '-nofiles':
164
176
  options.files = false;
165
177
  options.explicitKeys.add('files');
166
178
  break;
167
- case '--dry-run':
179
+ case '-dry-run':
168
180
  options.dryRun = true;
169
181
  break;
170
- case '--quiet':
182
+ case '-quiet':
171
183
  options.quiet = true;
172
184
  break;
173
- case '--verbose':
185
+ case '-verbose':
174
186
  options.verbose = true;
175
187
  options.quiet = false;
176
188
  break;
177
- case '--init':
189
+ case '-init':
178
190
  options.init = true;
179
191
  break;
180
- case '--git':
192
+ case '-git':
181
193
  i++;
182
194
  if (args[i] === 'private' || args[i] === 'public') {
183
195
  options.gitVisibility = args[i];
184
196
  options.explicitKeys.add('gitVisibility');
185
197
  }
186
198
  else {
187
- options.error = `--git requires 'private' or 'public', got: ${args[i]}`;
199
+ options.error = `-git requires 'private' or 'public', got: ${args[i]}`;
188
200
  }
189
201
  break;
190
- case '--npm':
202
+ case '-npm':
191
203
  i++;
192
204
  if (args[i] === 'private' || args[i] === 'public') {
193
205
  options.npmVisibility = args[i];
194
206
  options.explicitKeys.add('npmVisibility');
195
207
  }
196
208
  else {
197
- options.error = `--npm requires 'private' or 'public', got: ${args[i]}`;
209
+ options.error = `-npm requires 'private' or 'public', got: ${args[i]}`;
198
210
  }
199
211
  break;
200
- case '--message':
212
+ case '-message':
201
213
  case '-m':
202
214
  i++;
203
215
  if (args[i]) {
204
216
  options.message = args[i];
205
217
  }
206
218
  else {
207
- options.error = '-m/--message requires a commit message';
219
+ options.error = '-m requires a commit message';
208
220
  }
209
221
  break;
210
- case '--conform':
222
+ case '-conform':
211
223
  options.conform = true;
212
224
  break;
213
- case '--asis':
225
+ case '-asis':
214
226
  options.asis = true;
215
227
  break;
216
- case '--fix-tags':
228
+ case '-fix-tags':
217
229
  options.fixTags = true;
218
230
  break;
219
- case '--rebase':
231
+ case '-rebase':
220
232
  options.rebase = true;
221
233
  break;
222
- case '--show':
234
+ case '-show':
223
235
  options.show = true;
224
236
  break;
225
- case '--update-deps':
237
+ case '-update-deps':
226
238
  case '-ud':
227
239
  options.updateDeps = true;
228
240
  break;
229
- case '--update-major':
241
+ case '-update-major':
230
242
  options.updateMajor = true;
231
- options.updateDeps = true; // Implies --update-deps
243
+ options.updateDeps = true; // Implies -update-deps
232
244
  break;
233
- case '--publish-deps':
245
+ case '-publish-deps':
234
246
  options.publishDeps = true; // Explicitly enable (though it's default)
235
247
  break;
236
- case '--no-publish-deps':
248
+ case '-no-publish-deps':
237
249
  case '-npd':
238
250
  options.publishDeps = false; // Disable auto-publishing
239
251
  break;
240
- case '--force-publish':
252
+ case '-force-publish':
241
253
  options.forcePublish = true;
242
254
  break;
243
- case '--fix':
255
+ case '-fix':
244
256
  options.fix = true;
245
257
  options.explicitKeys.add('fix');
246
258
  break;
247
- case '--no-fix':
259
+ case '-no-fix':
248
260
  options.fix = false;
249
261
  options.explicitKeys.add('fix');
250
262
  break;
251
- case '--workspace':
263
+ case '-workspace':
252
264
  case '-w':
253
265
  i++;
254
266
  if (args[i]) {
@@ -257,20 +269,20 @@ function parseArgs(args) {
257
269
  options.workspaceFilter.push(args[i]);
258
270
  }
259
271
  else {
260
- options.error = '-w/--workspace requires a package name';
272
+ options.error = '-w requires a package name';
261
273
  }
262
274
  break;
263
- case '--no-workspace':
275
+ case '-no-workspace':
264
276
  options.noWorkspace = true;
265
277
  break;
266
- case '--continue-on-error':
278
+ case '-continue-on-error':
267
279
  options.continueOnError = true;
268
280
  break;
269
- case '--package':
281
+ case '-package':
270
282
  case '-pkg':
271
283
  options.package = true;
272
284
  break;
273
- case '--once':
285
+ case '-once':
274
286
  options.once = true;
275
287
  break;
276
288
  default:
@@ -311,7 +323,7 @@ export async function main() {
311
323
  }
312
324
  if (cliOptions.error) {
313
325
  console.error(`Error: ${cliOptions.error}`);
314
- console.error('Run with --help for usage.');
326
+ console.error('Run with -help for usage.');
315
327
  process.exit(1);
316
328
  }
317
329
  let cwd = process.cwd();
package/lib.d.ts CHANGED
@@ -71,6 +71,8 @@ export interface GlobalizeOptions {
71
71
  package?: boolean;
72
72
  /** Don't persist CLI flags to .globalize.json5 */
73
73
  once?: boolean;
74
+ /** Local install only — skip transform/publish, just npm install -g . */
75
+ local?: boolean;
74
76
  /** Internal: signals this call is from workspace orchestrator */
75
77
  _fromWorkspace?: boolean;
76
78
  /** Internal: signals this call is from CLI (version already printed) */
package/lib.js CHANGED
@@ -111,7 +111,7 @@ export function writeConfig(dir, config, explicitKeys) {
111
111
  const existing = readConfig(dir);
112
112
  // Filter out temporary flags and default values (unless explicitly set)
113
113
  const filtered = {};
114
- const omitKeys = new Set(['noPublish', 'cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish', 'once']);
114
+ const omitKeys = new Set(['cleanup', 'init', 'dryRun', 'message', 'conform', 'asis', 'help', 'error', 'updateDeps', 'updateMajor', 'publishDeps', 'forcePublish', 'once']);
115
115
  for (const [key, value] of Object.entries(config)) {
116
116
  if (omitKeys.has(key))
117
117
  continue;
@@ -160,6 +160,10 @@ export function writeConfig(dir, config, explicitKeys) {
160
160
  comment = ' // patch (default), minor, or major';
161
161
  else if (key === 'fix')
162
162
  comment = ' // Auto-run npm audit fix';
163
+ else if (key === 'local')
164
+ comment = ' // Local install only (skip transform/publish)';
165
+ else if (key === 'noPublish')
166
+ comment = ' // Transform but don\'t publish';
163
167
  lines.push(` "${key}": ${jsonValue}${comma}${comment}`);
164
168
  });
165
169
  lines.push('');
@@ -177,6 +181,8 @@ export function writeConfig(dir, config, explicitKeys) {
177
181
  lines.push(' // "gitVisibility": "private" // Git repo: private or public');
178
182
  lines.push(' // "npmVisibility": "private" // npm package: private or public');
179
183
  lines.push(' // "fix": false // Auto-run npm audit fix');
184
+ lines.push(' // "local": false // Local install only (skip transform/publish)');
185
+ lines.push(' // "noPublish": false // Transform but don\'t publish');
180
186
  lines.push('}');
181
187
  fs.writeFileSync(configPath, lines.join('\n') + '\n');
182
188
  }
@@ -1471,7 +1477,7 @@ export function getToolVersion() {
1471
1477
  }
1472
1478
  export async function globalize(cwd, options = {}, configOptions = {}) {
1473
1479
  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
1474
- forcePublish = false, fix = false, fixTags = false, rebase = false, show = false } = options;
1480
+ forcePublish = false, fix = false, fixTags = false, rebase = false, show = false, local = false } = options;
1475
1481
  // Show tool version only for recursive dep calls (CLI already prints it at startup)
1476
1482
  const toolVersion = getToolVersion();
1477
1483
  if (!options._fromWorkspace && !options._fromCli) {
@@ -1526,11 +1532,51 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
1526
1532
  settings.push('--force-publish');
1527
1533
  if (configOptions.show)
1528
1534
  settings.push('--show');
1535
+ if (configOptions.local)
1536
+ settings.push('-local');
1529
1537
  if (settings.length > 0) {
1530
1538
  console.log(colors.dim(`Settings from .globalize.json5: ${settings.join(', ')}`));
1531
1539
  }
1532
1540
  }
1533
1541
  console.log('');
1542
+ // -local: skip all transform/publish, just install from local directory with file: deps intact
1543
+ if (local) {
1544
+ const pkg = readPackageJson(cwd);
1545
+ const pkgName = pkg.name || path.basename(cwd);
1546
+ const pkgVersion = pkg.version || '0.0.0';
1547
+ console.log(colors.blue(`Local install: ${pkgName}@${pkgVersion}`));
1548
+ console.log(colors.dim('Skipping transform/publish — installing with file: deps as-is'));
1549
+ if (!pkg.bin) {
1550
+ console.log(colors.yellow('Note: No bin field — this is a library, not a CLI tool.'));
1551
+ console.log(colors.yellow('Running npm install -g . anyway (creates global link)...'));
1552
+ }
1553
+ if (dryRun) {
1554
+ console.log(' [dry-run] Would run: npm install -g .');
1555
+ if (wsl)
1556
+ console.log(' [dry-run] Would run: wsl npm install -g .');
1557
+ return true;
1558
+ }
1559
+ const result = runCommand('npm', ['install', '-g', '.'], { cwd, silent: false });
1560
+ if (result.success) {
1561
+ console.log(colors.green(`✓ Installed locally: ${pkgName}@${pkgVersion}`));
1562
+ }
1563
+ else {
1564
+ console.error(colors.red(`✗ Local install failed`));
1565
+ console.error(colors.yellow(' Try running manually: npm install -g .'));
1566
+ return false;
1567
+ }
1568
+ if (wsl) {
1569
+ console.log(`Installing ${pkgName} in WSL (local)...`);
1570
+ const wslResult = runCommand('wsl', ['npm', 'install', '-g', '.'], { cwd, silent: false });
1571
+ if (wslResult.success) {
1572
+ console.log(colors.green(`✓ Installed in WSL: ${pkgName}@${pkgVersion}`));
1573
+ }
1574
+ else {
1575
+ console.error(colors.yellow('✗ WSL install failed (is npm installed in WSL?)'));
1576
+ }
1577
+ }
1578
+ return true;
1579
+ }
1534
1580
  // Check ignore files first (unless cleanup mode)
1535
1581
  if (!cleanup && !asis) {
1536
1582
  const checkResult = checkIgnoreFiles(cwd, { conform, asis, verbose });
@@ -2088,11 +2134,37 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2088
2134
  }
2089
2135
  if (noPublish) {
2090
2136
  console.log('Transform complete (--nopublish mode).');
2137
+ if (files && transformResult.transformed) {
2138
+ console.log('Restoring file: dependencies...');
2139
+ const finalPkg = readPackageJson(cwd);
2140
+ restoreDeps(finalPkg, verbose);
2141
+ if (!dryRun) {
2142
+ writePackageJson(cwd, finalPkg);
2143
+ runCommand('git', ['add', 'package.json'], { cwd });
2144
+ runCommand('git', ['commit', '-m', 'Restore file: dependencies'], { cwd });
2145
+ if (currentGitStatus.hasRemote) {
2146
+ runCommand('git', ['push'], { cwd });
2147
+ }
2148
+ }
2149
+ }
2091
2150
  return true;
2092
2151
  }
2093
2152
  // Skip if private
2094
2153
  if (pkg.private) {
2095
2154
  console.log('Package is private - skipping npm publish.');
2155
+ if (files && transformResult.transformed) {
2156
+ console.log('Restoring file: dependencies...');
2157
+ const finalPkg = readPackageJson(cwd);
2158
+ restoreDeps(finalPkg, verbose);
2159
+ if (!dryRun) {
2160
+ writePackageJson(cwd, finalPkg);
2161
+ runCommand('git', ['add', 'package.json'], { cwd });
2162
+ runCommand('git', ['commit', '-m', 'Restore file: dependencies'], { cwd });
2163
+ if (currentGitStatus.hasRemote) {
2164
+ runCommand('git', ['push'], { cwd });
2165
+ }
2166
+ }
2167
+ }
2096
2168
  return true;
2097
2169
  }
2098
2170
  // Re-check git status after all transformations and potential commits
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.88",
3
+ "version": "1.0.89",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",