@bobfrankston/npmglobalize 1.0.47 → 1.0.49
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 +2 -2
- package/cli.js +3 -3
- package/lib.d.ts +3 -1
- package/lib.js +157 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -259,8 +259,8 @@ Publishing requires being on a branch so commits and tags can be properly tracke
|
|
|
259
259
|
```
|
|
260
260
|
--git private Make git repo private (default)
|
|
261
261
|
--git public Make git repo public
|
|
262
|
-
--npm private Mark package private (skip publish)
|
|
263
|
-
--npm public Publish to npm
|
|
262
|
+
--npm private Mark package private (skip publish) (default)
|
|
263
|
+
--npm public Publish to npm
|
|
264
264
|
```
|
|
265
265
|
|
|
266
266
|
### Other Options
|
package/cli.js
CHANGED
|
@@ -58,8 +58,8 @@ Mode Options:
|
|
|
58
58
|
Git/npm Visibility:
|
|
59
59
|
--git private Make git repo private (default)
|
|
60
60
|
--git public Make git repo public (requires confirmation)
|
|
61
|
-
--npm private Mark npm package private (skip publish)
|
|
62
|
-
--npm public Publish to npm
|
|
61
|
+
--npm private Mark npm package private (skip publish) (default)
|
|
62
|
+
--npm public Publish to npm
|
|
63
63
|
|
|
64
64
|
Other Options:
|
|
65
65
|
--init Initialize git/npm if needed
|
|
@@ -328,7 +328,7 @@ export async function main() {
|
|
|
328
328
|
const configOptions = readConfig(cwd);
|
|
329
329
|
const options = { ...configOptions, ...cliOptions };
|
|
330
330
|
try {
|
|
331
|
-
const success = await globalize(cwd, options);
|
|
331
|
+
const success = await globalize(cwd, options, configOptions);
|
|
332
332
|
process.exit(success ? 0 : 1);
|
|
333
333
|
}
|
|
334
334
|
catch (error) {
|
package/lib.d.ts
CHANGED
|
@@ -70,6 +70,8 @@ export declare function getLatestVersion(packageName: string): string | null;
|
|
|
70
70
|
export declare function checkVersionExists(packageName: string, version: string): boolean;
|
|
71
71
|
/** Check if a package exists on npm (any version) */
|
|
72
72
|
export declare function checkPackageExists(packageName: string): boolean;
|
|
73
|
+
/** Check npm package access level (public/restricted/null if not published) */
|
|
74
|
+
export declare function checkNpmAccess(packageName: string): 'public' | 'restricted' | null;
|
|
73
75
|
/** Update existing npm dependencies to latest versions */
|
|
74
76
|
export declare function updateNpmDeps(pkg: any, verbose?: boolean, allowMajor?: boolean): {
|
|
75
77
|
updated: boolean;
|
|
@@ -158,7 +160,7 @@ export declare function runNpmAudit(cwd: string, fix?: boolean, verbose?: boolea
|
|
|
158
160
|
};
|
|
159
161
|
/** Get the version of npmglobalize itself */
|
|
160
162
|
export declare function getToolVersion(): string;
|
|
161
|
-
export declare function globalize(cwd: string, options?: GlobalizeOptions): Promise<boolean>;
|
|
163
|
+
export declare function globalize(cwd: string, options?: GlobalizeOptions, configOptions?: Partial<GlobalizeOptions>): Promise<boolean>;
|
|
162
164
|
declare const _default: {
|
|
163
165
|
globalize: typeof globalize;
|
|
164
166
|
transformDeps: typeof transformDeps;
|
package/lib.js
CHANGED
|
@@ -8,12 +8,14 @@ import readline from 'readline';
|
|
|
8
8
|
import libversion from 'libnpmversion';
|
|
9
9
|
import JSON5 from 'json5';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
-
|
|
11
|
+
import { styleText } from 'util';
|
|
12
|
+
/** Color/style helpers using Node.js styleText (Node 24+) */
|
|
12
13
|
const colors = {
|
|
13
|
-
red: (text) =>
|
|
14
|
-
yellow: (text) =>
|
|
15
|
-
green: (text) =>
|
|
16
|
-
italic: (text) =>
|
|
14
|
+
red: (text) => styleText('red', text),
|
|
15
|
+
yellow: (text) => styleText('yellow', text),
|
|
16
|
+
green: (text) => styleText('green', text),
|
|
17
|
+
italic: (text) => styleText('italic', text),
|
|
18
|
+
dim: (text) => styleText('dim', text),
|
|
17
19
|
};
|
|
18
20
|
const DEP_KEYS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
19
21
|
/** Read and parse package.json from a directory */
|
|
@@ -100,7 +102,7 @@ export function writeConfig(dir, config, explicitKeys) {
|
|
|
100
102
|
else if (key === 'gitVisibility')
|
|
101
103
|
comment = ' // private (default) or public';
|
|
102
104
|
else if (key === 'npmVisibility')
|
|
103
|
-
comment = ' // private or public
|
|
105
|
+
comment = ' // private (default) or public';
|
|
104
106
|
else if (key === 'bump')
|
|
105
107
|
comment = ' // patch (default), minor, or major';
|
|
106
108
|
else if (key === 'fix')
|
|
@@ -183,6 +185,33 @@ export function checkPackageExists(packageName) {
|
|
|
183
185
|
return false;
|
|
184
186
|
}
|
|
185
187
|
}
|
|
188
|
+
/** Check npm package access level (public/restricted/null if not published) */
|
|
189
|
+
export function checkNpmAccess(packageName) {
|
|
190
|
+
try {
|
|
191
|
+
const result = spawnSync('npm', ['view', packageName, '--json'], {
|
|
192
|
+
encoding: 'utf-8',
|
|
193
|
+
stdio: 'pipe',
|
|
194
|
+
shell: true
|
|
195
|
+
});
|
|
196
|
+
if (result.status === 0 && result.stdout) {
|
|
197
|
+
const data = JSON.parse(result.stdout);
|
|
198
|
+
// npm view returns the latest version's info
|
|
199
|
+
// Scoped packages are 'restricted' by default, unscoped are 'public'
|
|
200
|
+
// The access field isn't always present, so we infer from scope
|
|
201
|
+
if (packageName.startsWith('@')) {
|
|
202
|
+
// Scoped package - check if it exists
|
|
203
|
+
return 'restricted'; // Scoped packages default to restricted
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
return 'public'; // Unscoped packages are always public
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return null; // Package doesn't exist on npm
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
186
215
|
/** Parse semver version string to major.minor.patch */
|
|
187
216
|
function parseSemver(version) {
|
|
188
217
|
const clean = version.replace(/^[^\d]*/, ''); // Remove ^, ~, etc.
|
|
@@ -1163,12 +1192,63 @@ export function getToolVersion() {
|
|
|
1163
1192
|
return 'unknown';
|
|
1164
1193
|
}
|
|
1165
1194
|
}
|
|
1166
|
-
export async function globalize(cwd, options = {}) {
|
|
1167
|
-
const { bump = 'patch', noPublish = false, cleanup = false, install = false, wsl = false, force = false, files = true, dryRun = false, quiet = true, verbose = false, init = false, gitVisibility = 'private', npmVisibility = '
|
|
1195
|
+
export async function globalize(cwd, options = {}, configOptions = {}) {
|
|
1196
|
+
const { bump = 'patch', noPublish = false, cleanup = false, install = 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
|
|
1168
1197
|
forcePublish = false, fix = false, fixTags = false, rebase = false, show = false } = options;
|
|
1169
1198
|
// Show tool version
|
|
1170
1199
|
const toolVersion = getToolVersion();
|
|
1171
1200
|
console.log(colors.italic(`npmglobalize v${toolVersion}`));
|
|
1201
|
+
// Show settings from .globalize.json5 if any
|
|
1202
|
+
if (Object.keys(configOptions).length > 0) {
|
|
1203
|
+
const settings = [];
|
|
1204
|
+
if (configOptions.install)
|
|
1205
|
+
settings.push('--install');
|
|
1206
|
+
if (configOptions.npmVisibility)
|
|
1207
|
+
settings.push(`--npm-visibility ${configOptions.npmVisibility}`);
|
|
1208
|
+
if (configOptions.gitVisibility)
|
|
1209
|
+
settings.push(`--git-visibility ${configOptions.gitVisibility}`);
|
|
1210
|
+
if (configOptions.conform)
|
|
1211
|
+
settings.push('--conform');
|
|
1212
|
+
if (configOptions.asis)
|
|
1213
|
+
settings.push('--asis');
|
|
1214
|
+
if (configOptions.updateDeps)
|
|
1215
|
+
settings.push('--update-deps');
|
|
1216
|
+
if (configOptions.updateMajor)
|
|
1217
|
+
settings.push('--update-major');
|
|
1218
|
+
if (configOptions.fix)
|
|
1219
|
+
settings.push('--fix');
|
|
1220
|
+
if (configOptions.fixTags)
|
|
1221
|
+
settings.push('--fix-tags');
|
|
1222
|
+
if (configOptions.rebase)
|
|
1223
|
+
settings.push('--rebase');
|
|
1224
|
+
if (configOptions.force)
|
|
1225
|
+
settings.push('--force');
|
|
1226
|
+
if (configOptions.verbose)
|
|
1227
|
+
settings.push('--verbose');
|
|
1228
|
+
if (configOptions.dryRun)
|
|
1229
|
+
settings.push('--dry-run');
|
|
1230
|
+
if (configOptions.bump)
|
|
1231
|
+
settings.push(`--bump ${configOptions.bump}`);
|
|
1232
|
+
if (configOptions.noPublish)
|
|
1233
|
+
settings.push('--no-publish');
|
|
1234
|
+
if (configOptions.cleanup)
|
|
1235
|
+
settings.push('--cleanup');
|
|
1236
|
+
if (configOptions.wsl)
|
|
1237
|
+
settings.push('--wsl');
|
|
1238
|
+
if (configOptions.files === false)
|
|
1239
|
+
settings.push('--no-files');
|
|
1240
|
+
if (configOptions.quiet === false)
|
|
1241
|
+
settings.push('--no-quiet');
|
|
1242
|
+
if (configOptions.publishDeps === false)
|
|
1243
|
+
settings.push('--no-publish-deps');
|
|
1244
|
+
if (configOptions.forcePublish)
|
|
1245
|
+
settings.push('--force-publish');
|
|
1246
|
+
if (configOptions.show)
|
|
1247
|
+
settings.push('--show');
|
|
1248
|
+
if (settings.length > 0) {
|
|
1249
|
+
console.log(colors.dim(`Settings from .globalize.json5: ${settings.join(', ')}`));
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1172
1252
|
console.log('');
|
|
1173
1253
|
// Check ignore files first (unless cleanup mode)
|
|
1174
1254
|
if (!cleanup && !asis) {
|
|
@@ -1431,28 +1511,66 @@ export async function globalize(cwd, options = {}) {
|
|
|
1431
1511
|
}
|
|
1432
1512
|
console.log(colors.yellow('Continuing with --force despite errors...'));
|
|
1433
1513
|
}
|
|
1434
|
-
// Check npm visibility
|
|
1514
|
+
// Check npm visibility and current publication status
|
|
1515
|
+
const currentAccess = checkNpmAccess(pkg.name);
|
|
1516
|
+
const isScoped = pkg.name.startsWith('@');
|
|
1435
1517
|
if (npmVisibility === 'private') {
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
pkg.
|
|
1518
|
+
// User explicitly wants private publication
|
|
1519
|
+
if (!isScoped) {
|
|
1520
|
+
console.error(colors.red(`ERROR: Private packages must be scoped (e.g., @bobfrankston/${pkg.name})`));
|
|
1521
|
+
return false;
|
|
1522
|
+
}
|
|
1523
|
+
if (currentAccess === 'public') {
|
|
1524
|
+
console.error(colors.red(`ERROR: Package '${pkg.name}' is currently PUBLIC on npm.`));
|
|
1525
|
+
console.error(colors.red(`Cannot change to private. Options:`));
|
|
1526
|
+
console.error(colors.yellow(` 1. Deprecate the public package: npm deprecate ${pkg.name} "moved to private"`));
|
|
1527
|
+
console.error(colors.yellow(` 2. Continue as public: npmglobalize --npm public`));
|
|
1528
|
+
console.error(colors.yellow(` 3. Use a different package name`));
|
|
1529
|
+
return false;
|
|
1530
|
+
}
|
|
1531
|
+
// Don't set "private": true in package.json - that blocks all publishing
|
|
1532
|
+
console.log(`Package '${pkg.name}' will publish as PRIVATE (restricted access).`);
|
|
1533
|
+
if (!currentAccess) {
|
|
1534
|
+
console.log(colors.dim(` First publish - requires paid npm account`));
|
|
1443
1535
|
}
|
|
1444
1536
|
}
|
|
1445
1537
|
else if (npmVisibility === 'public') {
|
|
1446
|
-
//
|
|
1538
|
+
// User explicitly wants public
|
|
1539
|
+
if (currentAccess === 'restricted') {
|
|
1540
|
+
console.error(colors.red(`ERROR: Package '${pkg.name}' is currently PRIVATE on npm.`));
|
|
1541
|
+
console.error(colors.red(`Cannot change to public. Options:`));
|
|
1542
|
+
console.error(colors.yellow(` 1. Unpublish and republish: npm unpublish ${pkg.name} --force`));
|
|
1543
|
+
console.error(colors.yellow(` 2. Continue as private: npmglobalize --npm private`));
|
|
1544
|
+
console.error(colors.yellow(` 3. Use a different package name`));
|
|
1545
|
+
return false;
|
|
1546
|
+
}
|
|
1447
1547
|
console.log(`Will publish '${pkg.name}' to PUBLIC npm registry.`);
|
|
1548
|
+
console.log(colors.yellow(` To use, run: npm install ${pkg.name}`));
|
|
1448
1549
|
}
|
|
1449
1550
|
else {
|
|
1450
|
-
// No explicit setting -
|
|
1451
|
-
if (
|
|
1452
|
-
console.log(`Package is
|
|
1551
|
+
// No explicit setting - preserve current state or use defaults
|
|
1552
|
+
if (currentAccess === 'public') {
|
|
1553
|
+
console.log(`Package '${pkg.name}' is PUBLIC on npm (will maintain status).`);
|
|
1554
|
+
}
|
|
1555
|
+
else if (currentAccess === 'restricted') {
|
|
1556
|
+
console.log(`Package '${pkg.name}' is PRIVATE on npm (will maintain status).`);
|
|
1557
|
+
}
|
|
1558
|
+
else if (pkg.private) {
|
|
1559
|
+
console.log(`Package '${pkg.name}' marked PRIVATE (package.json "private": true)`);
|
|
1560
|
+
console.log(colors.dim(` npm will reject publication - use for internal/local packages only`));
|
|
1453
1561
|
}
|
|
1454
1562
|
else {
|
|
1455
|
-
|
|
1563
|
+
// New package - default to private
|
|
1564
|
+
if (isScoped) {
|
|
1565
|
+
console.log(`Package '${pkg.name}' will publish as PRIVATE (default for new packages).`);
|
|
1566
|
+
console.log(colors.dim(` Use --npm public to make it public`));
|
|
1567
|
+
}
|
|
1568
|
+
else {
|
|
1569
|
+
console.log(colors.yellow(`WARNING: Package '${pkg.name}' is unscoped and will be PUBLIC.`));
|
|
1570
|
+
console.log(colors.yellow(` Unscoped packages cannot be private on npm.`));
|
|
1571
|
+
console.log(colors.yellow(` Consider using a scoped name: @bobfrankston/${pkg.name}`));
|
|
1572
|
+
console.log(colors.yellow(` Or use --npm public to confirm public publishing`));
|
|
1573
|
+
}
|
|
1456
1574
|
}
|
|
1457
1575
|
}
|
|
1458
1576
|
// Update existing npm dependencies if requested
|
|
@@ -1895,9 +2013,23 @@ export async function globalize(cwd, options = {}) {
|
|
|
1895
2013
|
}
|
|
1896
2014
|
// Publish the tarball
|
|
1897
2015
|
const npmArgs = ['publish', tarballName];
|
|
2016
|
+
// Determine access level
|
|
1898
2017
|
if (npmVisibility === 'public') {
|
|
2018
|
+
// Explicitly public
|
|
1899
2019
|
npmArgs.push('--access', 'public');
|
|
1900
2020
|
}
|
|
2021
|
+
else if (npmVisibility === 'private') {
|
|
2022
|
+
// Explicitly private - don't add flag, scoped packages are restricted by default
|
|
2023
|
+
// npmArgs.push('--access', 'restricted'); // Not needed, it's the default for scoped
|
|
2024
|
+
}
|
|
2025
|
+
else {
|
|
2026
|
+
// No explicit setting - check current npm state
|
|
2027
|
+
if (currentAccess === 'public') {
|
|
2028
|
+
// Maintain public status
|
|
2029
|
+
npmArgs.push('--access', 'public');
|
|
2030
|
+
}
|
|
2031
|
+
// If restricted or new, use defaults (scoped=restricted, unscoped=public)
|
|
2032
|
+
}
|
|
1901
2033
|
if (quiet) {
|
|
1902
2034
|
npmArgs.push('--quiet');
|
|
1903
2035
|
}
|
|
@@ -2027,7 +2159,10 @@ export async function globalize(cwd, options = {}) {
|
|
|
2027
2159
|
}
|
|
2028
2160
|
return false;
|
|
2029
2161
|
}
|
|
2030
|
-
|
|
2162
|
+
// Determine what was published
|
|
2163
|
+
const finalAccess = currentAccess || (isScoped ? 'restricted' : 'public');
|
|
2164
|
+
const accessLabel = finalAccess === 'restricted' ? 'PRIVATE' : 'PUBLIC';
|
|
2165
|
+
console.log(colors.green(`✓ Published to npm as ${accessLabel}`));
|
|
2031
2166
|
}
|
|
2032
2167
|
else {
|
|
2033
2168
|
console.log(` [dry-run] Would run: npm publish ${quiet ? '--quiet' : ''}`);
|