@bobfrankston/npmglobalize 1.0.233 → 1.0.235
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 +3 -1
- package/lib.js +27 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ Errors abort (unless `--force`); warnings prompt to continue.
|
|
|
94
94
|
|
|
95
95
|
An unscoped dependency with private intent is reported differently: it is not a question. npmglobalize never renames a dependency to add a scope (the name is what every consumer imports by, and changing it is the dep owner's own project), so the dep cannot reach npm and neither can the package that depends on it. The first run says so in full, names the dep and its path, records it under `unscopedDepsNoted` in the consumer's `.globalize.json5`, and stops. Later runs print one line per dep and stop. Nothing is asked, because no answer could change the outcome. Fix it in the dep: scope the name in its own `package.json`, or set `npmVisibility: "public"` or `noprefix: true` in its `.globalize.json5`; the note clears itself on the next run. If the cascade reaches such a dep anyway (`-no-prescan`), it stops there with the same message. The same holds when you run npmglobalize *in* an unscoped package: it used to ask "Add scope to package name?", and now it warns and assumes no, since a rename changes what every consumer imports. Publishing an unscoped package PUBLIC on purpose takes an explicit `-npm public` or `noprefix: true`. (2026-09-14)
|
|
96
96
|
|
|
97
|
-
**Own-scope packages installed from npm instead of linked.** When a package in the `file:` graph depends on one of its own-scope packages by version range (`"@bobfrankston/miscassists": "^1.0.61"`) rather than `file:`, npm puts a registry copy in that package's `node_modules` instead of a link to the local source. The consumer is usually nested under other `file:` deps, where neither the `+` list nor the dependency tree shows it, so the prescan lists every such edge on every run: consumer → dep and range, the `package.json` that holds the range, and — when the same dep is linked as `file:` elsewhere in the graph — the directory of its local source (that package then exists twice). Nothing is asked and the run continues; a range can be deliberate. A package with `"files": false` in its `.globalize.json5` keeps npm refs on purpose and is not listed. npmglobalize does not rewrite the range: change it to a `file:` path in the named `package.json`, then run `npmglobalize` in that package. (2026-09-21)
|
|
97
|
+
**Own-scope packages installed from npm instead of linked.** When a package in the `file:` graph depends on one of its own-scope packages by version range (`"@bobfrankston/miscassists": "^1.0.61"`) rather than `file:`, npm puts a registry copy in that package's `node_modules` instead of a link to the local source. The consumer is usually nested under other `file:` deps, where neither the `+` list nor the dependency tree shows it, so the prescan lists every such edge on every run: consumer → dep and range, the `package.json` that holds the range, and — when the same dep is linked as `file:` elsewhere in the graph — the directory of its local source (that package then exists twice). Each finding is repeated as one line in the end-of-run **Issues Summary**, because the prescan block has scrolled away by the time a cascade finishes. Nothing is asked and the run continues; a range can be deliberate. A package with `"files": false` in its `.globalize.json5` keeps npm refs on purpose and is not listed. npmglobalize does not rewrite the range: change it to a `file:` path in the named `package.json`, then run `npmglobalize` in that package. (2026-09-21)
|
|
98
98
|
|
|
99
99
|
Skip the prescan with `-no-prescan` / `-nps`.
|
|
100
100
|
|
|
@@ -527,6 +527,8 @@ not what you meant to publish, so npmglobalize lists the conflicted files and st
|
|
|
527
527
|
Example: -npm public,ts
|
|
528
528
|
```
|
|
529
529
|
|
|
530
|
+
Flipping an already-published package between private and public runs `npm access set`. Since Aug 2026 that fails with a bare 403 when the token in `.npmrc` is a bypass-2FA granular token (npm no longer lets such tokens change package access, and offers no OTP prompt). npmglobalize recognizes that case, says so, and points at the package's Access page on npmjs.com (`https://www.npmjs.com/package/<name>/access`, browser sign-in with 2FA); set the status there and rerun. The finding is repeated in the Issues Summary. Publishing itself is unaffected until the Jan 2027 phase of the same deprecation. (2026-09-23)
|
|
531
|
+
|
|
530
532
|
`ts` is already the default on git (source is tracked). Pass `-npm ts` to ship
|
|
531
533
|
the same files to npm — useful for debugging installed packages or "source on
|
|
532
534
|
demand" packages. `noEmit` projects automatically ship `.ts` files (they *are*
|
package/lib.js
CHANGED
|
@@ -1088,7 +1088,7 @@ export async function cascadePublicVisibility(cwd, opts = {}) {
|
|
|
1088
1088
|
console.log(colors.green(` ✓ Flipped ${targetName} to PUBLIC on npm`));
|
|
1089
1089
|
}
|
|
1090
1090
|
else {
|
|
1091
|
-
blockers.push({ name: targetName, reason:
|
|
1091
|
+
blockers.push({ name: targetName, reason: explainAccessChangeFailure(targetName, 'public', r) });
|
|
1092
1092
|
}
|
|
1093
1093
|
}
|
|
1094
1094
|
else {
|
|
@@ -2123,6 +2123,12 @@ export function reportRegistryRefs(registryRefs, fileTargets) {
|
|
|
2123
2123
|
if (localSource) {
|
|
2124
2124
|
console.log(colors.dim(` local source, linked as file: elsewhere in this graph: ${localSource}`));
|
|
2125
2125
|
}
|
|
2126
|
+
// 2026-09-21 — Claude Code (Fable 5.1), at Bob's direction ("it should summarize the
|
|
2127
|
+
// findings at the end"). The block above prints before the cascade and scrolls away, so
|
|
2128
|
+
// each finding also goes into the Issues Summary cli.ts prints on every exit path. One
|
|
2129
|
+
// self-contained line: it has to make sense with the prescan output long gone.
|
|
2130
|
+
recordBuildIssue(ref.consumer, 'warning', `${ref.package} ${ref.range} is installed from npm, not file: — ${path.join(ref.path, 'package.json')}`
|
|
2131
|
+
+ (localSource ? ` (local source: ${localSource})` : ''));
|
|
2126
2132
|
}
|
|
2127
2133
|
console.log(colors.dim(` To link one, set it to a file: path in the package.json named above, then run npmglobalize in that package.`));
|
|
2128
2134
|
console.log('');
|
|
@@ -6101,6 +6107,24 @@ function checkNpmAuth() {
|
|
|
6101
6107
|
return { authenticated: false, error: error.message };
|
|
6102
6108
|
}
|
|
6103
6109
|
}
|
|
6110
|
+
/** Explain a failed `npm access set status=...` and say what will actually work.
|
|
6111
|
+
* 2026-09-23 01:10 EDT — Claude Code (Fable 5.1), at Bob's direction. Since early Aug
|
|
6112
|
+
* 2026 a granular token that bypasses 2FA no longer covers package-access changes
|
|
6113
|
+
* (https://gh.io/npm-gat-bypass2fa-deprecation): the registry answers the access POST
|
|
6114
|
+
* with a bare 403 and npm never offers an OTP prompt. The old message here said "Try
|
|
6115
|
+
* manually: npm access set ..." — the same command with the same token, which fails
|
|
6116
|
+
* the same way. The path that works is the package's Access page on npmjs.com, signed
|
|
6117
|
+
* in with 2FA. Recorded as a build issue too, so it survives to the Issues Summary. */
|
|
6118
|
+
function explainAccessChangeFailure(name, status, result) {
|
|
6119
|
+
const text = `${result.stderr}\n${result.output}`;
|
|
6120
|
+
const tokenBlocked = /\bE?403\b/.test(text) && /\/access\b/.test(text);
|
|
6121
|
+
const page = `https://www.npmjs.com/package/${name}/access`;
|
|
6122
|
+
const message = tokenBlocked
|
|
6123
|
+
? `Cannot change ${name} to ${status} with the npm token in .npmrc (403 on the access endpoint): since Aug 2026 bypass-2FA tokens no longer cover access changes. Set Package Status on ${page} (browser, 2FA), then rerun.`
|
|
6124
|
+
: `Failed to change ${name} to ${status}. Try manually: npm access set status=${status} ${name} (or on ${page}).`;
|
|
6125
|
+
recordBuildIssue(name, 'error', message);
|
|
6126
|
+
return message;
|
|
6127
|
+
}
|
|
6104
6128
|
/** Get authentication setup instructions */
|
|
6105
6129
|
function getAuthInstructions() {
|
|
6106
6130
|
const npmrcPath = path.join(process.env.USERPROFILE || process.env.HOME || '~', '.npmrc');
|
|
@@ -7975,7 +7999,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
7975
7999
|
currentAccess = 'restricted';
|
|
7976
8000
|
}
|
|
7977
8001
|
else {
|
|
7978
|
-
console.error(colors.red(
|
|
8002
|
+
console.error(colors.red(explainAccessChangeFailure(pkg.name, 'restricted', accessResult)));
|
|
7979
8003
|
if (!force)
|
|
7980
8004
|
return false;
|
|
7981
8005
|
}
|
|
@@ -7998,7 +8022,7 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
|
7998
8022
|
currentAccess = 'public';
|
|
7999
8023
|
}
|
|
8000
8024
|
else {
|
|
8001
|
-
console.error(colors.red(
|
|
8025
|
+
console.error(colors.red(explainAccessChangeFailure(pkg.name, 'public', accessResult)));
|
|
8002
8026
|
if (!force)
|
|
8003
8027
|
return false;
|
|
8004
8028
|
}
|