@bobfrankston/npmglobalize 1.0.148 → 1.0.149

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.
Files changed (3) hide show
  1. package/lib.d.ts +7 -5
  2. package/lib.js +56 -26
  3. package/package.json +1 -1
package/lib.d.ts CHANGED
@@ -188,13 +188,15 @@ export declare function buildDependencyGraph(packages: Array<{
188
188
  /** Topological sort with cycle detection. Returns package names in dependency order. */
189
189
  export declare function topologicalSort(graph: Map<string, Set<string>>): string[];
190
190
  /** Transform file: dependencies to npm versions */
191
+ export type UnpublishedDep = {
192
+ name: string;
193
+ version: string;
194
+ path: string;
195
+ reason: 'new' | 'update';
196
+ };
191
197
  export declare function transformDeps(pkg: any, baseDir: string, verbose?: boolean, forcePublish?: boolean): {
192
198
  transformed: boolean;
193
- unpublished: Array<{
194
- name: string;
195
- version: string;
196
- path: string;
197
- }>;
199
+ unpublished: UnpublishedDep[];
198
200
  };
199
201
  /** A problem discovered by the prescan. */
200
202
  export interface PrescanIssue {
package/lib.js CHANGED
@@ -863,7 +863,6 @@ function hasLocalChanges(packageName, version, targetPath, verbose) {
863
863
  return false;
864
864
  }
865
865
  }
866
- /** Transform file: dependencies to npm versions */
867
866
  export function transformDeps(pkg, baseDir, verbose = false, forcePublish = false) {
868
867
  let transformed = false;
869
868
  const unpublished = [];
@@ -894,7 +893,7 @@ export function transformDeps(pkg, baseDir, verbose = false, forcePublish = fals
894
893
  // Check if this version exists on npm (or if force publish)
895
894
  const versionExists = forcePublish ? false : checkVersionExists(name, targetVersion);
896
895
  if (!versionExists) {
897
- unpublished.push({ name, version: targetVersion, path: targetPath });
896
+ unpublished.push({ name, version: targetVersion, path: targetPath, reason: forcePublish ? 'update' : 'new' });
898
897
  if (forcePublish) {
899
898
  console.log(colors.yellow(` ⟳ ${name}@${targetVersion} will be republished (--force-publish)`));
900
899
  }
@@ -908,15 +907,15 @@ export function transformDeps(pkg, baseDir, verbose = false, forcePublish = fals
908
907
  }
909
908
  // Check transitive file: deps — if any are unpublished, this dep needs republishing
910
909
  if (hasUnpublishedTransitiveDeps(name, targetPkg, targetPath, verbose)) {
911
- unpublished.push({ name, version: targetVersion, path: targetPath });
910
+ unpublished.push({ name, version: targetVersion, path: targetPath, reason: 'update' });
912
911
  console.log(colors.yellow(` ⟳ ${name}@${targetVersion} has unpublished transitive deps — will republish`));
913
912
  }
914
913
  else if (hasLocalChanges(name, targetVersion, targetPath, verbose)) {
915
- unpublished.push({ name, version: targetVersion, path: targetPath });
914
+ unpublished.push({ name, version: targetVersion, path: targetPath, reason: 'update' });
916
915
  console.log(colors.yellow(` ⟳ ${name}@${targetVersion} has local changes not on npm — will republish`));
917
916
  }
918
917
  else if (checkIgnoreFiles(targetPath, { verbose }).securityChanges.length > 0) {
919
- unpublished.push({ name, version: targetVersion, path: targetPath });
918
+ unpublished.push({ name, version: targetVersion, path: targetPath, reason: 'update' });
920
919
  console.log(colors.yellow(` ⟳ ${name}@${targetVersion} has missing ignore patterns — will republish`));
921
920
  }
922
921
  }
@@ -2349,6 +2348,13 @@ export async function initGit(cwd, visibility, dryRun) {
2349
2348
  if (staged.status !== 0) {
2350
2349
  runCommandOrThrow('git', ['commit', '-m', 'Initial commit'], { cwd });
2351
2350
  }
2351
+ // Guarantee HEAD exists — `gh repo create --push` refuses an empty repo.
2352
+ // Can happen if the working tree had nothing to stage (everything ignored, etc.).
2353
+ const hasHead = spawnSafe('git', ['rev-parse', '--verify', 'HEAD'], { cwd, stdio: 'pipe' });
2354
+ if (hasHead.status !== 0) {
2355
+ console.log(colors.yellow(' No commits yet — creating an empty initial commit so --push can proceed.'));
2356
+ runCommandOrThrow('git', ['commit', '--allow-empty', '-m', 'Initial commit'], { cwd });
2357
+ }
2352
2358
  // Create GitHub repo (or link to existing one)
2353
2359
  const visFlag = visibility === 'private' ? '--private' : '--public';
2354
2360
  const createResult = runCommand('gh', ['repo', 'create', repoName, visFlag, '--source=.', '--push'], { cwd, silent: true });
@@ -3337,21 +3343,59 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3337
3343
  }
3338
3344
  console.log('');
3339
3345
  }
3340
- // Check if target packages need to be published
3346
+ // Publish/update dependencies.
3347
+ // - reason='update': already on npm but stale (local changes, broken transitive, missing ignore) — auto-publish always
3348
+ // - reason='new' : version not on npm yet — auto-publish if --publish-deps, else prompt
3341
3349
  if (transformResult.unpublished.length > 0 && !noPublish) {
3350
+ const updateDepsList = transformResult.unpublished.filter(d => d.reason === 'update');
3351
+ const newDepsList = transformResult.unpublished.filter(d => d.reason === 'new');
3342
3352
  console.log('');
3343
- console.log(colors.yellow('Dependencies to publish:'));
3344
- for (const { name, version, path } of transformResult.unpublished) {
3345
- console.log(colors.yellow(` ${name}@${version} (${path})`));
3353
+ if (updateDepsList.length > 0) {
3354
+ console.log(colors.yellow('Dependencies to update (already on npm, auto-republishing):'));
3355
+ for (const { name, version, path } of updateDepsList) {
3356
+ console.log(colors.yellow(` ${name}@${version} (${path})`));
3357
+ }
3358
+ }
3359
+ if (newDepsList.length > 0) {
3360
+ console.log(colors.yellow('New dependencies to publish:'));
3361
+ for (const { name, version, path } of newDepsList) {
3362
+ console.log(colors.yellow(` ${name}@${version} (${path})`));
3363
+ }
3346
3364
  }
3347
3365
  console.log('');
3348
3366
  console.log('Dependency tree (✓ = on npm, ✗ = needs publishing):');
3349
3367
  printDepTree(cwd);
3350
3368
  console.log('');
3351
- if (publishDeps) {
3369
+ // Decide which deps to publish now.
3370
+ // Updates always run. New deps run if --publish-deps; otherwise prompt.
3371
+ let depsToPublish = [...updateDepsList];
3372
+ let proceedWithNew = newDepsList.length === 0 || publishDeps;
3373
+ if (newDepsList.length > 0 && !publishDeps) {
3374
+ console.log(colors.yellow('Options for NEW dependencies:'));
3375
+ console.log(colors.yellow(' 1. Publish them manually first'));
3376
+ console.log(colors.yellow(' 2. Use --publish-deps (-pd) to publish them automatically'));
3377
+ console.log(colors.yellow(' 3. Use -npd (--no-publish-deps) to skip dependency publishing'));
3378
+ console.log(colors.dim(' (--force controls error-continuation only; it does not imply consent to publish new deps)'));
3379
+ console.log('');
3380
+ if (publishDepsYes) {
3381
+ proceedWithNew = true;
3382
+ }
3383
+ else {
3384
+ proceedWithNew = await confirm('Publish new dependencies now?', false);
3385
+ if (!proceedWithNew) {
3386
+ const newList = newDepsList.map(d => `${d.name}@${d.version}`).join(', ');
3387
+ recordBuildIssue(pkg.name || cwd, 'error', `Declined publishing new deps (${newList}). Rerun with -pd to auto-publish, or publish them manually first.`);
3388
+ return false;
3389
+ }
3390
+ }
3391
+ }
3392
+ if (proceedWithNew) {
3393
+ depsToPublish.push(...newDepsList);
3394
+ }
3395
+ if (depsToPublish.length > 0) {
3352
3396
  const action = forcePublish ? 'Publishing/updating' : 'Publishing';
3353
- console.log(`${action} file: dependencies first (--publish-deps)...`);
3354
- for (const { name, version, path } of transformResult.unpublished) {
3397
+ console.log(`${action} file: dependencies first...`);
3398
+ for (const { name, version, path } of depsToPublish) {
3355
3399
  console.log('');
3356
3400
  console.log(colors.yellow(`━━━ Publishing ${name}@${version} ━━━`));
3357
3401
  if (!dryRun) {
@@ -3393,20 +3437,6 @@ export async function globalize(cwd, options = {}, configOptions = {}) {
3393
3437
  console.log('');
3394
3438
  console.log(colors.green('✓ All dependencies published'));
3395
3439
  }
3396
- else {
3397
- console.log(colors.yellow('Options:'));
3398
- console.log(colors.yellow(' 1. Publish them manually first'));
3399
- console.log(colors.yellow(' 2. Use --publish-deps to publish them automatically'));
3400
- console.log(colors.yellow(' 3. Use --force to continue anyway (NOT RECOMMENDED)'));
3401
- console.log(colors.yellow(' 4. Use -npd (--no-publish-deps) to skip dependency publishing'));
3402
- console.log('');
3403
- if (!force && !publishDepsYes) {
3404
- const shouldContinue = await confirm('Continue with unpublished dependencies?', false);
3405
- if (!shouldContinue) {
3406
- return false;
3407
- }
3408
- }
3409
- }
3410
3440
  }
3411
3441
  if (!dryRun) {
3412
3442
  writePackageJson(cwd, pkg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/npmglobalize",
3
- "version": "1.0.148",
3
+ "version": "1.0.149",
4
4
  "description": "Transform file: dependencies to npm versions for publishing",
5
5
  "main": "index.js",
6
6
  "type": "module",