@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 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 (default)
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 (default)
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
- /** ANSI color codes */
11
+ import { styleText } from 'util';
12
+ /** Color/style helpers using Node.js styleText (Node 24+) */
12
13
  const colors = {
13
- red: (text) => `\x1b[31m${text}\x1b[0m`,
14
- yellow: (text) => `\x1b[33m${text}\x1b[0m`,
15
- green: (text) => `\x1b[32m${text}\x1b[0m`,
16
- italic: (text) => `\x1b[3m${text}\x1b[0m`,
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 (default)';
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 = 'public', message, conform = false, asis = false, updateDeps = false, updateMajor = false, publishDeps = true, // Default to publishing deps for safety
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 - explicit confirmation
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
- if (!pkg.private) {
1437
- const ok = await confirm('Mark npm package PRIVATE - will not publish to npm. Continue?', false);
1438
- if (!ok) {
1439
- console.log('Aborted.');
1440
- return false;
1441
- }
1442
- pkg.private = true;
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
- // Explicit public - inform user
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 - check current state
1451
- if (pkg.private) {
1452
- console.log(`Package is marked PRIVATE - will not publish to npm.`);
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
- console.log(`Will publish '${pkg.name}' to PUBLIC npm registry.`);
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
- console.log(colors.green('✓ Published to npm'));
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' : ''}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.47",
3
+ "version": "1.0.49",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",