pubz 0.1.0 → 0.2.1

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/README.md +101 -0
  2. package/dist/cli.js +114 -9
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -14,4 +14,105 @@ bunx pubz
14
14
 
15
15
  ```bash
16
16
  bunx pubz
17
+ ```
18
+
19
+ ```bash
20
+ pubz - npm package publisher
21
+ =============================
22
+
23
+ Discovering packages...
24
+
25
+ Found 1 publishable package(s):
26
+
27
+ - pubz@0.1.0
28
+
29
+ Step 1: Version Management
30
+ --------------------------
31
+
32
+ Current version: 0.1.0
33
+
34
+ Bump version before publishing? [y/N] n
35
+ Select publish target:
36
+
37
+ > 1) Public npm registry (https://registry.npmjs.org)
38
+ 2) GitHub Packages (https://npm.pkg.github.com)
39
+
40
+ Enter choice [1-2] (default: 1): 1
41
+
42
+ Publishing to: https://registry.npmjs.org
43
+
44
+ Step 2: Building Packages
45
+ -------------------------
46
+
47
+ Running build...
48
+
49
+ $ bun build src/cli.ts --outdir dist --target node
50
+ Bundled 6 modules in 4ms
51
+
52
+ cli.js 20.0 KB (entry point)
53
+
54
+ Build completed successfully
55
+
56
+ Verifying builds...
57
+
58
+ pubz build verified
59
+
60
+ Step 3: Publishing to npm
61
+ -------------------------
62
+
63
+ About to publish the following packages:
64
+
65
+ pubz@0.1.0
66
+
67
+ Registry: https://registry.npmjs.org
68
+
69
+ Continue? [y/N] y
70
+
71
+ Publishing packages...
72
+
73
+ Publishing pubz@0.1.0...
74
+ bun publish v1.3.2 (b131639c)
75
+
76
+ packed 0.70KB package.json
77
+ packed 322B README.md
78
+ packed 20.0KB dist/cli.js
79
+
80
+ Total files: 3
81
+ Shasum: 0494617a65c8a92d8a2c43d115dea0f94919102f
82
+ Integrity: sha512-KLEM/H7EOadzz[...]c1up2JcHW9gcQ==
83
+ Unpacked size: 21.1KB
84
+ Packed size: 5.73KB
85
+ Tag: latest
86
+ Access: public
87
+ Registry: https://registry.npmjs.org
88
+
89
+ + pubz@0.1.0
90
+ pubz published successfully
91
+
92
+ ==================================
93
+ Publishing complete!
94
+
95
+ Published version: 0.1.0
96
+
97
+ Create a git tag for v0.1.0? [y/N] y
98
+
99
+ A .npmrc
100
+ M README.md
101
+ M package.json
102
+ M src/cli.ts
103
+ M src/publish.ts
104
+ M src/types.ts
105
+ Uncommitted changes detected. Committing...
106
+ error: pathspec 'release' did not match any file(s) known to git
107
+ error: pathspec 'v0.1.0' did not match any file(s) known to git
108
+ Changes committed
109
+ Tag v0.1.0 created
110
+ Push tag to origin? [y/N] y
111
+ fatal: 'origin' does not appear to be a git repository
112
+ fatal: Could not read from remote repository.
113
+
114
+ Please make sure you have the correct access rights
115
+ and the repository exists.
116
+
117
+ Done!
17
118
  ```
package/dist/cli.js CHANGED
@@ -191,6 +191,53 @@ async function select(message, options, defaultIndex = 0) {
191
191
  console.log(`Invalid choice. Using default: ${options[defaultIndex].label}`);
192
192
  return options[defaultIndex].value;
193
193
  }
194
+ async function multiSelect(message, options, allSelectedByDefault = true) {
195
+ const selected = new Set(allSelectedByDefault ? options.map((_, i) => i) : []);
196
+ const printOptions = () => {
197
+ console.log(message);
198
+ console.log("");
199
+ for (let i = 0;i < options.length; i++) {
200
+ const checkbox = selected.has(i) ? "[x]" : "[ ]";
201
+ console.log(` ${checkbox} ${i + 1}) ${options[i].label}`);
202
+ }
203
+ console.log("");
204
+ console.log('Enter number to toggle, "a" to select all, "n" to select none, or press Enter to confirm:');
205
+ };
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);
215
+ }
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);
232
+ }
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);
240
+ }
194
241
 
195
242
  // src/publish.ts
196
243
  import { spawn } from "node:child_process";
@@ -200,8 +247,7 @@ function run(command, args, cwd) {
200
247
  return new Promise((resolve2) => {
201
248
  const proc = spawn(command, args, {
202
249
  cwd,
203
- stdio: ["inherit", "pipe", "pipe"],
204
- shell: true
250
+ stdio: ["inherit", "pipe", "pipe"]
205
251
  });
206
252
  let output = "";
207
253
  proc.stdout?.on("data", (data) => {
@@ -283,18 +329,43 @@ async function publishPackage(pkg, registry, otp, dryRun) {
283
329
  console.log(` ${pkg.name} published successfully`);
284
330
  return { success: true };
285
331
  }
286
- async function createGitTag(version, cwd, dryRun) {
332
+ async function hasUncommittedChanges(cwd) {
333
+ const result = await run("git", ["status", "--porcelain"], cwd);
334
+ const output = result.output.trim();
335
+ if (!output) {
336
+ return { hasChanges: false, files: [] };
337
+ }
338
+ const files = output.split(`
339
+ `).map((line) => line.slice(3));
340
+ return { hasChanges: true, files };
341
+ }
342
+ async function commitVersionBump(version, cwd, dryRun) {
287
343
  const tagName = `v${version}`;
288
344
  if (dryRun) {
289
- console.log(`[DRY RUN] Would create git tag: ${tagName}`);
345
+ console.log(`[DRY RUN] Would commit version bump for ${tagName}`);
290
346
  return { success: true };
291
347
  }
292
348
  const statusResult = await run("git", ["status", "--porcelain"], cwd);
293
- if (statusResult.output.trim()) {
294
- console.log("Uncommitted changes detected. Committing...");
295
- await run("git", ["add", "-A"], cwd);
296
- await run("git", ["commit", "-m", `chore: release ${tagName}`], cwd);
297
- console.log(" Changes committed");
349
+ if (!statusResult.output.trim()) {
350
+ return { success: true };
351
+ }
352
+ console.log("Committing version bump...");
353
+ const addResult = await run("git", ["add", "-A"], cwd);
354
+ if (addResult.code !== 0) {
355
+ return { success: false, error: "Failed to stage changes" };
356
+ }
357
+ const commitResult = await run("git", ["commit", "-m", `chore: release ${tagName}`], cwd);
358
+ if (commitResult.code !== 0) {
359
+ return { success: false, error: "Failed to commit changes" };
360
+ }
361
+ console.log(" Changes committed");
362
+ return { success: true };
363
+ }
364
+ async function createGitTag(version, cwd, dryRun) {
365
+ const tagName = `v${version}`;
366
+ if (dryRun) {
367
+ console.log(`[DRY RUN] Would create git tag: ${tagName}`);
368
+ return { success: true };
298
369
  }
299
370
  const tagResult = await run("git", ["tag", tagName], cwd);
300
371
  if (tagResult.code !== 0) {
@@ -463,6 +534,21 @@ async function main() {
463
534
  console.log("pubz - npm package publisher");
464
535
  console.log("=============================");
465
536
  console.log("");
537
+ const uncommitted = await hasUncommittedChanges(cwd);
538
+ if (uncommitted.hasChanges && !options.dryRun) {
539
+ console.log("Error: You have uncommitted changes:");
540
+ console.log("");
541
+ for (const file of uncommitted.files.slice(0, 10)) {
542
+ console.log(` ${file}`);
543
+ }
544
+ if (uncommitted.files.length > 10) {
545
+ console.log(` ... and ${uncommitted.files.length - 10} more`);
546
+ }
547
+ console.log("");
548
+ console.log("Please commit or stash your changes before publishing.");
549
+ closePrompt();
550
+ process.exit(1);
551
+ }
466
552
  console.log("Discovering packages...");
467
553
  console.log("");
468
554
  let packages = await discoverPackages(cwd);
@@ -484,6 +570,19 @@ async function main() {
484
570
  console.log(` - ${pkg.name}@${pkg.version}${deps}`);
485
571
  }
486
572
  console.log("");
573
+ if (packages.length > 1 && !options.skipPrompts) {
574
+ const selectedPackages = await multiSelect("Select packages to publish:", packages.map((pkg) => ({
575
+ label: `${pkg.name}@${pkg.version}`,
576
+ value: pkg
577
+ })));
578
+ if (selectedPackages.length === 0) {
579
+ console.log("No packages selected. Exiting.");
580
+ closePrompt();
581
+ process.exit(0);
582
+ }
583
+ packages = sortByDependencyOrder(selectedPackages);
584
+ console.log("");
585
+ }
487
586
  const currentVersion = packages[0].version;
488
587
  console.log("Step 1: Version Management");
489
588
  console.log("--------------------------");
@@ -519,6 +618,12 @@ async function main() {
519
618
  for (const pkg of packages) {
520
619
  pkg.version = newVersion;
521
620
  }
621
+ const commitResult = await commitVersionBump(newVersion, cwd, options.dryRun);
622
+ if (!commitResult.success) {
623
+ console.error(`Failed to commit version bump: ${commitResult.error}`);
624
+ closePrompt();
625
+ process.exit(1);
626
+ }
522
627
  console.log("");
523
628
  }
524
629
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pubz",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Interactive CLI for publishing npm packages (single or monorepo)",
5
5
  "type": "module",
6
6
  "bin": {