@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 +9 -12
- package/cli.js +10 -0
- package/lib.d.ts +2 -0
- package/lib.js +65 -0
- package/package.json +3 -1
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
|
|
422
|
+
### The `.dependencies` Backup (Internal/Transient)
|
|
423
423
|
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
**
|
|
433
|
-
|
|
434
|
-
|
|
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
|
|
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.
|
|
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",
|