pubz 0.2.1 → 0.2.2

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 (2) hide show
  1. package/dist/cli.js +158 -94
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -2,6 +2,32 @@
2
2
  import { createRequire } from "node:module";
3
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
4
 
5
+ // src/colors.ts
6
+ var isColorSupported = process.env.FORCE_COLOR !== "0" && (process.env.FORCE_COLOR !== undefined || process.stdout.isTTY && process.env.TERM !== "dumb");
7
+ var fmt = (open, close) => {
8
+ if (!isColorSupported) {
9
+ return (str) => str;
10
+ }
11
+ return (str) => `\x1B[${open}m${str}\x1B[${close}m`;
12
+ };
13
+ var bold = fmt("1", "22");
14
+ var dim = fmt("2", "22");
15
+ var italic = fmt("3", "23");
16
+ var underline = fmt("4", "24");
17
+ var red = fmt("31", "39");
18
+ var green = fmt("32", "39");
19
+ var yellow = fmt("33", "39");
20
+ var blue = fmt("34", "39");
21
+ var magenta = fmt("35", "39");
22
+ var cyan = fmt("36", "39");
23
+ var white = fmt("37", "39");
24
+ var gray = fmt("90", "39");
25
+ var bgRed = fmt("41", "49");
26
+ var bgGreen = fmt("42", "49");
27
+ var bgYellow = fmt("43", "49");
28
+ var bgBlue = fmt("44", "49");
29
+ var muted = gray;
30
+
5
31
  // src/discovery.ts
6
32
  import { readFile, readdir as readdir2, stat as stat2 } from "node:fs/promises";
7
33
  import { join as join2, resolve } from "node:path";
@@ -164,23 +190,24 @@ function prompt(question) {
164
190
  function closePrompt() {
165
191
  rl.close();
166
192
  }
167
- async function confirm(message, defaultNo = true) {
168
- const hint = defaultNo ? "[y/N]" : "[Y/n]";
169
- const answer = await prompt(`${message} ${hint} `);
193
+ async function confirm(message, defaultYes = true) {
194
+ const hint = defaultYes ? `[${bold("Y")}/n]` : `[y/${bold("N")}]`;
195
+ const answer = await prompt(`${cyan("?")} ${message} ${hint} `);
170
196
  if (answer === "") {
171
- return !defaultNo;
197
+ return defaultYes;
172
198
  }
173
199
  return answer.toLowerCase() === "y";
174
200
  }
175
201
  async function select(message, options, defaultIndex = 0) {
176
- console.log(message);
202
+ console.log(`${cyan("?")} ${message}`);
177
203
  console.log("");
178
204
  for (let i = 0;i < options.length; i++) {
179
- const marker = i === defaultIndex ? ">" : " ";
180
- console.log(` ${marker} ${i + 1}) ${options[i].label}`);
205
+ const marker = i === defaultIndex ? cyan(">") : " ";
206
+ const num = dim(`${i + 1})`);
207
+ console.log(` ${marker} ${num} ${options[i].label}`);
181
208
  }
182
209
  console.log("");
183
- const answer = await prompt(`Enter choice [1-${options.length}] (default: ${defaultIndex + 1}): `);
210
+ const answer = await prompt(` Enter choice ${dim(`[1-${options.length}]`)} ${muted(`(default: ${defaultIndex + 1})`)}: `);
184
211
  if (answer === "") {
185
212
  return options[defaultIndex].value;
186
213
  }
@@ -188,55 +215,92 @@ async function select(message, options, defaultIndex = 0) {
188
215
  if (index >= 0 && index < options.length) {
189
216
  return options[index].value;
190
217
  }
191
- console.log(`Invalid choice. Using default: ${options[defaultIndex].label}`);
218
+ console.log(yellow(` Invalid choice. Using default: ${options[defaultIndex].label}`));
192
219
  return options[defaultIndex].value;
193
220
  }
194
221
  async function multiSelect(message, options, allSelectedByDefault = true) {
195
222
  const selected = new Set(allSelectedByDefault ? options.map((_, i) => i) : []);
196
- const printOptions = () => {
197
- console.log(message);
223
+ let cursor = 0;
224
+ const clearLines = (count) => {
225
+ for (let i = 0;i < count; i++) {
226
+ process.stdout.write("\x1B[A\x1B[2K");
227
+ }
228
+ };
229
+ const render = (initial = false) => {
230
+ if (!initial) {
231
+ clearLines(options.length + 3);
232
+ }
233
+ console.log(`${cyan("?")} ${message}`);
198
234
  console.log("");
199
235
  for (let i = 0;i < options.length; i++) {
200
- const checkbox = selected.has(i) ? "[x]" : "[ ]";
201
- console.log(` ${checkbox} ${i + 1}) ${options[i].label}`);
236
+ const isSelected = selected.has(i);
237
+ const isCursor = i === cursor;
238
+ const checkbox = isSelected ? green("[x]") : dim("[ ]");
239
+ const pointer = isCursor ? cyan(">") : " ";
240
+ const label = isCursor ? bold(options[i].label) : options[i].label;
241
+ console.log(` ${pointer} ${checkbox} ${label}`);
202
242
  }
203
243
  console.log("");
204
- console.log('Enter number to toggle, "a" to select all, "n" to select none, or press Enter to confirm:');
244
+ console.log(dim(" ↑/↓ navigate space toggle a all n none enter confirm"));
205
245
  };
206
- printOptions();
207
- while (true) {
208
- const answer = await prompt("> ");
209
- if (answer === "") {
210
- break;
211
- }
212
- if (answer.toLowerCase() === "a") {
213
- for (let i = 0;i < options.length; i++) {
214
- selected.add(i);
246
+ return new Promise((resolve2) => {
247
+ render(true);
248
+ rl.pause();
249
+ const stdin = process.stdin;
250
+ stdin.setRawMode(true);
251
+ stdin.resume();
252
+ const onKeypress = (key) => {
253
+ const str = key.toString();
254
+ if (str === "\x03") {
255
+ stdin.setRawMode(false);
256
+ stdin.removeListener("data", onKeypress);
257
+ rl.resume();
258
+ console.log("");
259
+ process.exit(0);
215
260
  }
216
- console.log("");
217
- printOptions();
218
- continue;
219
- }
220
- if (answer.toLowerCase() === "n") {
221
- selected.clear();
222
- console.log("");
223
- printOptions();
224
- continue;
225
- }
226
- const index = Number.parseInt(answer, 10) - 1;
227
- if (index >= 0 && index < options.length) {
228
- if (selected.has(index)) {
229
- selected.delete(index);
230
- } else {
231
- selected.add(index);
261
+ if (str === "\r" || str === `
262
+ `) {
263
+ stdin.setRawMode(false);
264
+ stdin.removeListener("data", onKeypress);
265
+ rl.resume();
266
+ console.log("");
267
+ resolve2(options.filter((_, i) => selected.has(i)).map((o) => o.value));
268
+ return;
232
269
  }
233
- console.log("");
234
- printOptions();
235
- } else {
236
- console.log("Invalid input. Try again.");
237
- }
238
- }
239
- return options.filter((_, i) => selected.has(i)).map((o) => o.value);
270
+ if (str === " ") {
271
+ if (selected.has(cursor)) {
272
+ selected.delete(cursor);
273
+ } else {
274
+ selected.add(cursor);
275
+ }
276
+ render();
277
+ return;
278
+ }
279
+ if (str === "\x1B[A" || str === "k") {
280
+ cursor = cursor > 0 ? cursor - 1 : options.length - 1;
281
+ render();
282
+ return;
283
+ }
284
+ if (str === "\x1B[B" || str === "j") {
285
+ cursor = cursor < options.length - 1 ? cursor + 1 : 0;
286
+ render();
287
+ return;
288
+ }
289
+ if (str === "a") {
290
+ for (let i = 0;i < options.length; i++) {
291
+ selected.add(i);
292
+ }
293
+ render();
294
+ return;
295
+ }
296
+ if (str === "n") {
297
+ selected.clear();
298
+ render();
299
+ return;
300
+ }
301
+ };
302
+ stdin.on("data", onKeypress);
303
+ });
240
304
  }
241
305
 
242
306
  // src/publish.ts
@@ -528,46 +592,46 @@ async function main() {
528
592
  }
529
593
  const cwd = process.cwd();
530
594
  if (options.dryRun) {
531
- console.log("DRY RUN MODE - No actual changes will be made");
595
+ console.log(yellow(bold("DRY RUN MODE")) + dim(" - No actual changes will be made"));
532
596
  console.log("");
533
597
  }
534
- console.log("pubz - npm package publisher");
535
- console.log("=============================");
598
+ console.log(bold("pubz") + dim(" - npm package publisher"));
599
+ console.log(dim("".repeat(30)));
536
600
  console.log("");
537
601
  const uncommitted = await hasUncommittedChanges(cwd);
538
602
  if (uncommitted.hasChanges && !options.dryRun) {
539
- console.log("Error: You have uncommitted changes:");
603
+ console.log(red(bold("Error:")) + " You have uncommitted changes:");
540
604
  console.log("");
541
605
  for (const file of uncommitted.files.slice(0, 10)) {
542
- console.log(` ${file}`);
606
+ console.log(` ${yellow(file)}`);
543
607
  }
544
608
  if (uncommitted.files.length > 10) {
545
- console.log(` ... and ${uncommitted.files.length - 10} more`);
609
+ console.log(dim(` ... and ${uncommitted.files.length - 10} more`));
546
610
  }
547
611
  console.log("");
548
- console.log("Please commit or stash your changes before publishing.");
612
+ console.log(muted("Please commit or stash your changes before publishing."));
549
613
  closePrompt();
550
614
  process.exit(1);
551
615
  }
552
- console.log("Discovering packages...");
616
+ console.log(cyan("Discovering packages..."));
553
617
  console.log("");
554
618
  let packages = await discoverPackages(cwd);
555
619
  const publishablePackages = packages.filter((p) => !p.isPrivate);
556
620
  if (publishablePackages.length === 0) {
557
- console.log("No publishable packages found.");
621
+ console.log(yellow("No publishable packages found."));
558
622
  console.log("");
559
- console.log("Make sure your packages:");
560
- console.log(' - Have a package.json with a "name" field');
561
- console.log(' - Do not have "private": true');
623
+ console.log(muted("Make sure your packages:"));
624
+ console.log(muted(' - Have a package.json with a "name" field'));
625
+ console.log(muted(' - Do not have "private": true'));
562
626
  console.log("");
563
627
  process.exit(1);
564
628
  }
565
629
  packages = sortByDependencyOrder(publishablePackages);
566
- console.log(`Found ${packages.length} publishable package(s):`);
630
+ console.log(`Found ${green(bold(String(packages.length)))} publishable package(s):`);
567
631
  console.log("");
568
632
  for (const pkg of packages) {
569
- const deps = pkg.localDependencies.length > 0 ? ` (depends on: ${pkg.localDependencies.join(", ")})` : "";
570
- console.log(` - ${pkg.name}@${pkg.version}${deps}`);
633
+ const deps = pkg.localDependencies.length > 0 ? dim(` (depends on: ${pkg.localDependencies.join(", ")})`) : "";
634
+ console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(pkg.version)}${deps}`);
571
635
  }
572
636
  console.log("");
573
637
  if (packages.length > 1 && !options.skipPrompts) {
@@ -576,7 +640,7 @@ async function main() {
576
640
  value: pkg
577
641
  })));
578
642
  if (selectedPackages.length === 0) {
579
- console.log("No packages selected. Exiting.");
643
+ console.log(yellow("No packages selected. Exiting."));
580
644
  closePrompt();
581
645
  process.exit(0);
582
646
  }
@@ -584,10 +648,10 @@ async function main() {
584
648
  console.log("");
585
649
  }
586
650
  const currentVersion = packages[0].version;
587
- console.log("Step 1: Version Management");
588
- console.log("--------------------------");
651
+ console.log(bold(cyan("Step 1:")) + " Version Management");
652
+ console.log(dim("".repeat(30)));
589
653
  console.log("");
590
- console.log(`Current version: ${currentVersion}`);
654
+ console.log(`Current version: ${yellow(currentVersion)}`);
591
655
  console.log("");
592
656
  let newVersion = currentVersion;
593
657
  if (!options.skipPrompts) {
@@ -609,7 +673,7 @@ async function main() {
609
673
  ]);
610
674
  newVersion = bumpVersion(currentVersion, bumpType);
611
675
  console.log("");
612
- console.log(`Updating version to ${newVersion} in all packages...`);
676
+ console.log(`Updating version to ${green(newVersion)} in all packages...`);
613
677
  console.log("");
614
678
  for (const pkg of packages) {
615
679
  await updatePackageVersion(pkg, newVersion, options.dryRun);
@@ -620,7 +684,7 @@ async function main() {
620
684
  }
621
685
  const commitResult = await commitVersionBump(newVersion, cwd, options.dryRun);
622
686
  if (!commitResult.success) {
623
- console.error(`Failed to commit version bump: ${commitResult.error}`);
687
+ console.error(red(bold("Failed to commit version bump:")) + ` ${commitResult.error}`);
624
688
  closePrompt();
625
689
  process.exit(1);
626
690
  }
@@ -642,88 +706,88 @@ async function main() {
642
706
  }
643
707
  registry = registry || REGISTRIES.npm;
644
708
  console.log("");
645
- console.log(`Publishing to: ${registry}`);
709
+ console.log(`Publishing to: ${cyan(registry)}`);
646
710
  console.log("");
647
711
  if (!options.skipBuild) {
648
- console.log("Step 2: Building Packages");
649
- console.log("-------------------------");
712
+ console.log(bold(cyan("Step 2:")) + " Building Packages");
713
+ console.log(dim("".repeat(30)));
650
714
  console.log("");
651
715
  const buildResult = await runBuild(cwd, options.dryRun);
652
716
  if (!buildResult.success) {
653
- console.error(`Build failed: ${buildResult.error}`);
717
+ console.error(red(bold("Build failed:")) + ` ${buildResult.error}`);
654
718
  closePrompt();
655
719
  process.exit(1);
656
720
  }
657
721
  console.log("");
658
- console.log("Verifying builds...");
722
+ console.log(cyan("Verifying builds..."));
659
723
  console.log("");
660
724
  let allBuildsVerified = true;
661
725
  for (const pkg of packages) {
662
726
  const result = await verifyBuild(pkg);
663
727
  if (result.success) {
664
- console.log(` ${pkg.name} build verified`);
728
+ console.log(` ${green("✓")} ${pkg.name} build verified`);
665
729
  } else {
666
- console.error(` ${pkg.name}: ${result.error}`);
730
+ console.error(` ${red("✗")} ${pkg.name}: ${result.error}`);
667
731
  allBuildsVerified = false;
668
732
  }
669
733
  }
670
734
  console.log("");
671
735
  if (!allBuildsVerified) {
672
- console.error("Build verification failed. Please fix the issues and try again.");
736
+ console.error(red("Build verification failed.") + muted(" Please fix the issues and try again."));
673
737
  closePrompt();
674
738
  process.exit(1);
675
739
  }
676
740
  }
677
- console.log("Step 3: Publishing to npm");
678
- console.log("-------------------------");
741
+ console.log(bold(cyan("Step 3:")) + " Publishing to npm");
742
+ console.log(dim("".repeat(30)));
679
743
  console.log("");
680
744
  if (options.dryRun) {
681
- console.log(`[DRY RUN] Would publish the following packages to ${registry}:`);
745
+ console.log(yellow("[DRY RUN]") + ` Would publish the following packages to ${cyan(registry)}:`);
682
746
  console.log("");
683
747
  for (const pkg of packages) {
684
- console.log(` ${pkg.name}@${newVersion}`);
748
+ console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
685
749
  }
686
750
  console.log("");
687
- console.log("Run without --dry-run to actually publish.");
751
+ console.log(muted("Run without --dry-run to actually publish."));
688
752
  } else {
689
753
  console.log("About to publish the following packages:");
690
754
  console.log("");
691
755
  for (const pkg of packages) {
692
- console.log(` ${pkg.name}@${newVersion}`);
756
+ console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
693
757
  }
694
758
  console.log("");
695
- console.log(`Registry: ${registry}`);
759
+ console.log(`Registry: ${cyan(registry)}`);
696
760
  console.log("");
697
761
  if (!options.skipPrompts) {
698
762
  const shouldContinue = await confirm("Continue?");
699
763
  if (!shouldContinue) {
700
- console.log("Publish cancelled.");
764
+ console.log(yellow("Publish cancelled."));
701
765
  closePrompt();
702
766
  process.exit(0);
703
767
  }
704
768
  }
705
769
  console.log("");
706
- console.log("Publishing packages...");
770
+ console.log(cyan("Publishing packages..."));
707
771
  console.log("");
708
772
  for (const pkg of packages) {
709
773
  const result = await publishPackage(pkg, registry, options.otp, options.dryRun);
710
774
  if (!result.success) {
711
- console.error(`Failed to publish ${pkg.name}: ${result.error}`);
775
+ console.error(red(bold("Failed to publish")) + ` ${cyan(pkg.name)}: ${result.error}`);
712
776
  console.log("");
713
- console.log("Stopping publish process.");
777
+ console.log(red("Stopping publish process."));
714
778
  closePrompt();
715
779
  process.exit(1);
716
780
  }
717
781
  }
718
782
  }
719
783
  console.log("");
720
- console.log("==================================");
721
- console.log("Publishing complete!");
784
+ console.log(dim("".repeat(30)));
785
+ console.log(green(bold("Publishing complete!")));
722
786
  console.log("");
723
- console.log(`Published version: ${newVersion}`);
787
+ console.log(`Published version: ${green(bold(newVersion))}`);
724
788
  console.log("");
725
789
  if (!options.dryRun && !options.skipPrompts) {
726
- const shouldTag = await confirm(`Create a git tag for v${newVersion}?`);
790
+ const shouldTag = await confirm(`Create a git tag for ${cyan(`v${newVersion}`)}?`);
727
791
  if (shouldTag) {
728
792
  console.log("");
729
793
  const tagResult = await createGitTag(newVersion, cwd, options.dryRun);
@@ -732,19 +796,19 @@ async function main() {
732
796
  if (shouldPush) {
733
797
  await pushGitTag(newVersion, cwd, options.dryRun);
734
798
  } else {
735
- console.log(`Tag created locally. Push manually with: git push origin v${newVersion}`);
799
+ console.log(`Tag created locally. Push manually with: ${dim(`git push origin v${newVersion}`)}`);
736
800
  }
737
801
  } else {
738
- console.error(tagResult.error);
802
+ console.error(red(tagResult.error ?? "Failed to create git tag"));
739
803
  }
740
804
  console.log("");
741
805
  }
742
806
  }
743
- console.log("Done!");
807
+ console.log(green(bold("Done!")));
744
808
  closePrompt();
745
809
  }
746
810
  main().catch((error) => {
747
- console.error("Error:", error.message);
811
+ console.error(red(bold("Error:")) + ` ${error.message}`);
748
812
  closePrompt();
749
813
  process.exit(1);
750
814
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pubz",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Interactive CLI for publishing npm packages (single or monorepo)",
5
5
  "type": "module",
6
6
  "bin": {