@bobfrankston/npmglobalize 1.0.116 → 1.0.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -419,22 +419,19 @@ npmglobalize --dry-run # See what would happen
419
419
 
420
420
  ## Operational Details
421
421
 
422
- ### The `.dependencies` Backup Mechanism
422
+ ### The `.dependencies` Backup (Internal/Transient)
423
423
 
424
- 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.
424
+ **You should never see `.dependencies` in your `package.json` under normal operation.** It is a temporary internal backup that exists only during the brief publish cycle and is removed automatically when the cycle completes.
425
425
 
426
- **How it works:**
427
- - Before transforming, the original `file:` entries are copied to `.dependencies`
428
- - After a successful publish, the originals are restored from `.dependencies` and the backup is removed
429
- - If the process crashes, is interrupted, or exits early (e.g., private package, `--nopublish`), `.dependencies` remains in `package.json`
430
- - On the **next run**, `transformDeps` detects `.dependencies`, restores the originals first, then re-transforms — so data is never lost
426
+ During publishing, `npmglobalize` temporarily replaces `file:` references with npm version strings. The original `file:` entries are stashed in `.dependencies` (and `.devDependencies`, etc.) so they can be restored afterward. Once the publish succeeds and `file:` paths are restored, `.dependencies` is deleted. A normal run leaves no trace of it.
431
427
 
432
- **Recovery commands:**
433
- ```bash
434
- npmglobalize -cleanup # Manually restore file: deps from .dependencies backup
435
- ```
428
+ **If you see `.dependencies` in your `package.json`, something went wrong** — the tool crashed, was killed, or the publish failed partway through. It is not a feature to rely on or edit manually.
429
+
430
+ **Recovery:**
431
+ - **Re-run `npmglobalize`**: It detects leftover `.dependencies`, restores the originals, and continues normally. Self-healing is automatic.
432
+ - **Manual restore**: `npmglobalize -cleanup` restores file: deps and removes the `.dependencies` backup.
436
433
 
437
- **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.
434
+ **Why a persistent backup?** 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.
438
435
 
439
436
  ### Flag Conventions
440
437
 
package/cli.js CHANGED
@@ -42,6 +42,8 @@ Install Options:
42
42
  -wsl Also install globally in WSL
43
43
  -freeze Freeze node_modules (replace symlinks with real copies for network shares)
44
44
  -nofreeze Disable freeze
45
+ -importgen Run importgen to update import maps before publishing
46
+ -noimportgen Disable importgen
45
47
  -once Don't persist flags to .globalize.json5
46
48
 
47
49
  Mode Options:
@@ -297,6 +299,14 @@ function parseArgs(args) {
297
299
  case '-once':
298
300
  options.once = true;
299
301
  break;
302
+ case '-importgen':
303
+ options.importgen = true;
304
+ options.explicitKeys.add('importgen');
305
+ break;
306
+ case '-noimportgen':
307
+ options.importgen = false;
308
+ options.explicitKeys.add('importgen');
309
+ break;
300
310
  default:
301
311
  if (arg.startsWith('-')) {
302
312
  unrecognized.push(arg);
package/lib.d.ts CHANGED
@@ -72,6 +72,8 @@ export interface GlobalizeOptions {
72
72
  package?: boolean;
73
73
  /** Don't persist CLI flags to .globalize.json5 */
74
74
  once?: boolean;
75
+ /** Run importgen to update import maps before publishing */
76
+ importgen?: boolean;
75
77
  /** Local install only — skip transform/publish, just npm install -g . */
76
78
  local?: boolean;
77
79
  /** Freeze node_modules: replace symlinks/junctions with real copies for network share use */
package/lib.js CHANGED
@@ -14,6 +14,7 @@ import path from 'path';
14
14
  import { execSync, spawnSync } from 'child_process';
15
15
  import { readConfig as readUserConfig, writeConfig as writeUserConfig, configDir } from '@bobfrankston/userconfig';
16
16
  import { freezeDependencies } from '@bobfrankston/freezepak';
17
+ import { importgen as runImportgen } from '@bobfrankston/importgen';
17
18
  /** Wrapper for spawnSync that avoids DEP0190 (args + shell: true).
18
19
  * When shell is true, joins cmd+args into a single command string. */
19
20
  function spawnSafe(cmd, args, options = {}) {
@@ -2555,6 +2556,27 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
2555
2556
  console.log(' [dry-run] Would run: npm run build');
2556
2557
  }
2557
2558
  }
2559
+ // Run importgen if enabled (update import maps in HTML files)
2560
+ if (options.importgen) {
2561
+ try {
2562
+ if (!dryRun) {
2563
+ const igResult = runImportgen(cwd);
2564
+ console.log(colors.green('✓ importgen updated import maps'));
2565
+ if (verbose && igResult.depDirs.length > 0) {
2566
+ console.log(` ${igResult.depDirs.length} dependency dirs resolved`);
2567
+ }
2568
+ }
2569
+ else {
2570
+ console.log(' [dry-run] Would run: importgen');
2571
+ }
2572
+ }
2573
+ catch (error) {
2574
+ // importgen throws if no HTML file found — that's fine, just skip
2575
+ if (verbose) {
2576
+ console.log(colors.dim(` importgen skipped: ${error.message}`));
2577
+ }
2578
+ }
2579
+ }
2558
2580
  // Pre-flight check: fix version/tag mismatches silently
2559
2581
  if (!dryRun) {
2560
2582
  fixVersionTagMismatch(cwd, pkg, verbose);
@@ -3844,6 +3866,49 @@ export async function globalizeWorkspace(rootDir, options = {}, configOptions =
3844
3866
  console.log(`Packages (${packages.length}): ${packages.map(p => p.name).join(', ')}`);
3845
3867
  console.log(`Publish order: ${publishOrder.join(' → ')}`);
3846
3868
  console.log('');
3869
+ // Check that workspace packages' deps are hoisted to root (needed for global install)
3870
+ const rootPkg = readPackageJson(rootDir);
3871
+ if (rootPkg.bin) {
3872
+ const wsNames = new Set(packages.map(p => p.name));
3873
+ const rootDeps = { ...rootPkg.dependencies, ...rootPkg.devDependencies };
3874
+ const missing = [];
3875
+ for (const pkgInfo of packages) {
3876
+ const deps = pkgInfo.pkg.dependencies || {};
3877
+ for (const [dep, ver] of Object.entries(deps)) {
3878
+ if (wsNames.has(dep))
3879
+ continue; // sibling workspace package — bundled
3880
+ if (dep in rootDeps)
3881
+ continue; // already in root
3882
+ if (missing.some(m => m.dep === dep))
3883
+ continue; // already flagged
3884
+ missing.push({ dep, version: ver, from: pkgInfo.name });
3885
+ }
3886
+ }
3887
+ if (missing.length > 0) {
3888
+ console.log(colors.yellow('⚠ Workspace packages have dependencies not in root package.json:'));
3889
+ for (const m of missing) {
3890
+ console.log(colors.yellow(` ${m.dep} (${m.version}) — from ${m.from}`));
3891
+ }
3892
+ console.log(colors.dim(' Global install (npm install -g) only installs root deps.'));
3893
+ if (!options.dryRun) {
3894
+ const hoist = await confirm('Add missing deps to root package.json?', true);
3895
+ if (hoist) {
3896
+ if (!rootPkg.dependencies)
3897
+ rootPkg.dependencies = {};
3898
+ for (const m of missing) {
3899
+ rootPkg.dependencies[m.dep] = m.version;
3900
+ console.log(colors.green(` + ${m.dep}: ${m.version}`));
3901
+ }
3902
+ writePackageJson(rootDir, rootPkg);
3903
+ console.log(colors.green('✓ Hoisted workspace deps to root package.json'));
3904
+ }
3905
+ }
3906
+ else {
3907
+ console.log(colors.dim(' [dry-run] Would offer to hoist missing deps'));
3908
+ }
3909
+ console.log('');
3910
+ }
3911
+ }
3847
3912
  // Handle --cleanup: restore deps for all packages and return
3848
3913
  if (options.cleanup) {
3849
3914
  console.log('Restoring workspace dependencies...');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.116",
3
+ "version": "1.0.117",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -32,6 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@bobfrankston/freezepak": "^0.1.4",
35
+ "@bobfrankston/importgen": "^0.1.31",
35
36
  "@bobfrankston/userconfig": "^1.0.4",
36
37
  "@npmcli/package-json": "^7.0.4",
37
38
  "json5": "^2.2.3",
@@ -45,6 +46,7 @@
45
46
  },
46
47
  ".dependencies": {
47
48
  "@bobfrankston/freezepak": "file:../freezepak",
49
+ "@bobfrankston/importgen": "file:../importgen",
48
50
  "@bobfrankston/userconfig": "file:../userconfig",
49
51
  "@npmcli/package-json": "^7.0.4",
50
52
  "json5": "^2.2.3",