pubz 0.5.2 → 0.7.0
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 +69 -113
- package/dist/cli.js +292 -257
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -179,118 +179,74 @@ jobs:
|
|
|
179
179
|
bunx pubz
|
|
180
180
|
```
|
|
181
181
|
|
|
182
|
+
<!-- demo-output-start -->
|
|
182
183
|
```
|
|
183
|
-
pubz
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Publishing to
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
npm notice name: pubz
|
|
251
|
-
npm notice version: 0.4.0
|
|
252
|
-
npm notice filename: pubz-0.4.0.tgz
|
|
253
|
-
npm notice package size: 12.0 kB
|
|
254
|
-
npm notice unpacked size: 49.1 kB
|
|
255
|
-
npm notice shasum: 3026a7936458dcaa84030a0ce2e206b9f74aa65d
|
|
256
|
-
npm notice integrity: sha512-6vKMOsC7sZa87[...]w8KNx1fD45u/A==
|
|
257
|
-
npm notice total files: 3
|
|
258
|
-
npm notice
|
|
259
|
-
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
|
|
260
|
-
Authenticate your account at:
|
|
261
|
-
https://www.npmjs.com/auth/cli/c47d9bee-2a1e-4adf-9aab-63d15acfade2
|
|
262
|
-
Press ENTER to open in the browser...
|
|
263
|
-
|
|
264
|
-
+ pubz@0.4.0
|
|
265
|
-
pubz published successfully
|
|
266
|
-
|
|
267
|
-
══════════════════════════════
|
|
268
|
-
Publishing complete!
|
|
269
|
-
|
|
270
|
-
Published version: 0.4.0
|
|
271
|
-
|
|
272
|
-
Changes since v0.2.12:
|
|
273
|
-
5553c95 Fix ENTER to open browser not working.
|
|
274
|
-
9aaddff Fix tag/push/release branch when using --yes.
|
|
275
|
-
0ce3ab8 Generate changlog and attach it to release page / print it out during publish.
|
|
276
|
-
5a29ca4 Merge branch 'main' of github.com:mm-zacharydavison/pubz
|
|
277
|
-
b4c47fc Clean up README.md formatting
|
|
278
|
-
2da403c Update README.md
|
|
279
|
-
88a4211 Update README with image and usage instructions
|
|
280
|
-
8a8148a Update README.md
|
|
281
|
-
2b45d21 Transform 'workspace:' definitions on publish, and restore them before any commit.
|
|
282
|
-
|
|
283
|
-
? Create a git tag for v0.4.0? [Y/n]
|
|
284
|
-
|
|
285
|
-
Tag v0.4.0 created
|
|
286
|
-
? Push tag to origin? [Y/n]
|
|
287
|
-
remote: This repository moved. Please use the new location:
|
|
288
|
-
remote: git@github.com:zdavison/pubz.git
|
|
289
|
-
To github.com:mm-zacharydavison/pubz.git
|
|
290
|
-
* [new tag] v0.4.0 -> v0.4.0
|
|
291
|
-
Tag v0.4.0 pushed to origin
|
|
292
|
-
? Create a GitHub release? [Y/n]
|
|
293
|
-
Release created: https://github.com/zdavison/pubz/releases/tag/v0.4.0
|
|
294
|
-
|
|
295
|
-
Done!
|
|
184
|
+
📦 pubz npm package publisher
|
|
185
|
+
|
|
186
|
+
┌─ Packages ─────────────────────────────────────────
|
|
187
|
+
• my-app@1.2.0
|
|
188
|
+
└────────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
┌─ 🔖 Version ───────────────────────────────────────
|
|
191
|
+
Bumping (minor): 1.2.0 → 1.3.0
|
|
192
|
+
Updating all packages...
|
|
193
|
+
chore: release v1.3.0
|
|
194
|
+
└────────────────────────────────────────────────────
|
|
195
|
+
|
|
196
|
+
┌─ 🏗️ Build ───────────────────────────────────────
|
|
197
|
+
Running bun run build...
|
|
198
|
+
|
|
199
|
+
$ bun build.js
|
|
200
|
+
Bundled 3 modules in 2ms
|
|
201
|
+
|
|
202
|
+
index.js 4.12 KB (entry point)
|
|
203
|
+
|
|
204
|
+
└────────────────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
Publishing to https://registry.npmjs.org:
|
|
207
|
+
|
|
208
|
+
• my-app@1.3.0
|
|
209
|
+
|
|
210
|
+
┌─ 🚀 Publish ───────────────────────────────────────
|
|
211
|
+
Preparing packages...
|
|
212
|
+
npm notice
|
|
213
|
+
npm notice Publishing to https://registry.npmjs.org
|
|
214
|
+
npm notice
|
|
215
|
+
└────────────────────────────────────────────────────
|
|
216
|
+
|
|
217
|
+
✅ Published v1.3.0!
|
|
218
|
+
|
|
219
|
+
┌─ 📋 Changelog ─────────────────────────────────────
|
|
220
|
+
Since v1.2.0
|
|
221
|
+
4e215fd docs: update README
|
|
222
|
+
5cbdd88 fix: fix edge case in parser
|
|
223
|
+
6142990 feat: add feature A
|
|
224
|
+
└────────────────────────────────────────────────────
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
┌─ ✨ AI Release Notes ───────────────────────────────
|
|
228
|
+
Generating...
|
|
229
|
+
|
|
230
|
+
### Features
|
|
231
|
+
|
|
232
|
+
- Added feature A.
|
|
233
|
+
|
|
234
|
+
### Bug Fixes
|
|
235
|
+
|
|
236
|
+
- Fixed an edge case in the parser.
|
|
237
|
+
|
|
238
|
+
### Documentation
|
|
239
|
+
|
|
240
|
+
- Updated README.
|
|
241
|
+
└────────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
┌─ 🏷️ Release ─────────────────────────────────────
|
|
244
|
+
Creating tag v1.3.0...
|
|
245
|
+
Pushing tag to origin...
|
|
246
|
+
* [new tag] v1.3.0 -> v1.3.0
|
|
247
|
+
Creating GitHub release...
|
|
248
|
+
└────────────────────────────────────────────────────
|
|
249
|
+
|
|
250
|
+
🎉 Done!
|
|
296
251
|
```
|
|
252
|
+
<!-- demo-output-end -->
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
4
4
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import { readFileSync } from "node:fs";
|
|
7
|
-
import { dirname, join as
|
|
7
|
+
import { dirname, join as join5 } from "node:path";
|
|
8
8
|
import { fileURLToPath } from "node:url";
|
|
9
9
|
|
|
10
10
|
// src/colors.ts
|
|
@@ -32,6 +32,18 @@ var bgGreen = fmt("42", "49");
|
|
|
32
32
|
var bgYellow = fmt("43", "49");
|
|
33
33
|
var bgBlue = fmt("44", "49");
|
|
34
34
|
var muted = gray;
|
|
35
|
+
var FRAME_WIDTH = 52;
|
|
36
|
+
function frameHeader(title) {
|
|
37
|
+
const inner = `─ ${title} `;
|
|
38
|
+
const padding = "─".repeat(Math.max(2, FRAME_WIDTH - inner.length));
|
|
39
|
+
console.log(dim(`┌${inner}${padding}`));
|
|
40
|
+
}
|
|
41
|
+
function frameFooter() {
|
|
42
|
+
console.log(dim(`└${"─".repeat(FRAME_WIDTH)}`));
|
|
43
|
+
}
|
|
44
|
+
function frameLine(text = "") {
|
|
45
|
+
console.log(" " + text);
|
|
46
|
+
}
|
|
35
47
|
|
|
36
48
|
// src/discovery.ts
|
|
37
49
|
import { readFile, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
@@ -386,6 +398,8 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
386
398
|
import { readFile as readFile2, stat as stat3 } from "node:fs/promises";
|
|
387
399
|
import { homedir as homedir2 } from "node:os";
|
|
388
400
|
import { join as join3 } from "node:path";
|
|
401
|
+
var DIM_ON = "\x1B[90m";
|
|
402
|
+
var DIM_OFF = "\x1B[39m";
|
|
389
403
|
function run(command, args, cwd) {
|
|
390
404
|
return new Promise((resolve2) => {
|
|
391
405
|
const proc = spawn2(command, args, {
|
|
@@ -395,11 +409,11 @@ function run(command, args, cwd) {
|
|
|
395
409
|
let output = "";
|
|
396
410
|
proc.stdout?.on("data", (data) => {
|
|
397
411
|
output += data.toString();
|
|
398
|
-
process.stdout.write(data);
|
|
412
|
+
process.stdout.write(DIM_ON + data.toString() + DIM_OFF);
|
|
399
413
|
});
|
|
400
414
|
proc.stderr?.on("data", (data) => {
|
|
401
415
|
output += data.toString();
|
|
402
|
-
process.stderr.write(data);
|
|
416
|
+
process.stderr.write(DIM_ON + data.toString() + DIM_OFF);
|
|
403
417
|
});
|
|
404
418
|
proc.on("close", (code) => {
|
|
405
419
|
resolve2({ code: code ?? 1, output });
|
|
@@ -419,17 +433,12 @@ function runInteractive(command, args, cwd) {
|
|
|
419
433
|
}
|
|
420
434
|
async function runBuild(cwd, dryRun) {
|
|
421
435
|
if (dryRun) {
|
|
422
|
-
console.log("[DRY RUN] Would run: bun run build");
|
|
423
436
|
return { success: true };
|
|
424
437
|
}
|
|
425
|
-
console.log("Running build...");
|
|
426
|
-
console.log("");
|
|
427
438
|
const result = await run("bun", ["run", "build"], cwd);
|
|
428
439
|
if (result.code !== 0) {
|
|
429
440
|
return { success: false, error: "Build failed" };
|
|
430
441
|
}
|
|
431
|
-
console.log("");
|
|
432
|
-
console.log("Build completed successfully");
|
|
433
442
|
return { success: true };
|
|
434
443
|
}
|
|
435
444
|
async function verifyBuild(pkg) {
|
|
@@ -472,10 +481,8 @@ function isOtpError(output) {
|
|
|
472
481
|
var NPM_COMMAND = process.env.PUBZ_NPM_COMMAND ?? "npm";
|
|
473
482
|
async function publishPackage(pkg, registry, context, dryRun) {
|
|
474
483
|
if (dryRun) {
|
|
475
|
-
console.log(` [DRY RUN] Would publish ${pkg.name}@${pkg.version} to ${registry}`);
|
|
476
484
|
return { success: true };
|
|
477
485
|
}
|
|
478
|
-
console.log(`Publishing ${pkg.name}@${pkg.version}...`);
|
|
479
486
|
const args = ["publish", "--registry", registry, "--access", "public"];
|
|
480
487
|
if (context.otp) {
|
|
481
488
|
args.push("--otp", context.otp);
|
|
@@ -500,7 +507,6 @@ async function publishPackage(pkg, registry, context, dryRun) {
|
|
|
500
507
|
}
|
|
501
508
|
return { success: false, error: `Failed to publish ${pkg.name}` };
|
|
502
509
|
}
|
|
503
|
-
console.log(` ${pkg.name} published successfully`);
|
|
504
510
|
return { success: true };
|
|
505
511
|
}
|
|
506
512
|
async function hasUncommittedChanges(cwd) {
|
|
@@ -516,29 +522,25 @@ async function hasUncommittedChanges(cwd) {
|
|
|
516
522
|
async function commitVersionBump(version, cwd, dryRun) {
|
|
517
523
|
const tagName = `v${version}`;
|
|
518
524
|
if (dryRun) {
|
|
519
|
-
console.log(`[DRY RUN] Would commit version bump for ${tagName}`);
|
|
520
525
|
return { success: true };
|
|
521
526
|
}
|
|
522
527
|
const statusResult = await run("git", ["status", "--porcelain"], cwd);
|
|
523
528
|
if (!statusResult.output.trim()) {
|
|
524
529
|
return { success: true };
|
|
525
530
|
}
|
|
526
|
-
console.log("Committing version bump...");
|
|
527
531
|
const addResult = await run("git", ["add", "-A"], cwd);
|
|
528
532
|
if (addResult.code !== 0) {
|
|
529
533
|
return { success: false, error: "Failed to stage changes" };
|
|
530
534
|
}
|
|
531
|
-
const commitResult = await run("git", ["commit", "-m", `chore: release ${tagName}`], cwd);
|
|
535
|
+
const commitResult = await run("git", ["commit", "-m", `chore: release ${tagName}`], cwd, { silent: true });
|
|
532
536
|
if (commitResult.code !== 0) {
|
|
533
537
|
return { success: false, error: "Failed to commit changes" };
|
|
534
538
|
}
|
|
535
|
-
console.log(" Changes committed");
|
|
536
539
|
return { success: true };
|
|
537
540
|
}
|
|
538
541
|
async function createGitTag(version, cwd, dryRun) {
|
|
539
542
|
const tagName = `v${version}`;
|
|
540
543
|
if (dryRun) {
|
|
541
|
-
console.log(`[DRY RUN] Would create git tag: ${tagName}`);
|
|
542
544
|
return { success: true };
|
|
543
545
|
}
|
|
544
546
|
const tagResult = await run("git", ["tag", tagName], cwd);
|
|
@@ -548,13 +550,11 @@ async function createGitTag(version, cwd, dryRun) {
|
|
|
548
550
|
error: `Failed to create tag ${tagName} (may already exist)`
|
|
549
551
|
};
|
|
550
552
|
}
|
|
551
|
-
console.log(` Tag ${tagName} created`);
|
|
552
553
|
return { success: true };
|
|
553
554
|
}
|
|
554
555
|
async function pushGitTag(version, cwd, dryRun) {
|
|
555
556
|
const tagName = `v${version}`;
|
|
556
557
|
if (dryRun) {
|
|
557
|
-
console.log(`[DRY RUN] Would push git tag: ${tagName}`);
|
|
558
558
|
return { success: true };
|
|
559
559
|
}
|
|
560
560
|
const branchResult = await run("git", ["push"], cwd);
|
|
@@ -565,12 +565,119 @@ async function pushGitTag(version, cwd, dryRun) {
|
|
|
565
565
|
if (result.code !== 0) {
|
|
566
566
|
return { success: false, error: `Failed to push tag ${tagName}` };
|
|
567
567
|
}
|
|
568
|
-
console.log(` Tag ${tagName} pushed to origin`);
|
|
569
568
|
return { success: true };
|
|
570
569
|
}
|
|
571
570
|
|
|
572
571
|
// src/changelog.ts
|
|
572
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
573
|
+
|
|
574
|
+
// src/claude.ts
|
|
573
575
|
import { spawn as spawn3 } from "node:child_process";
|
|
576
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
577
|
+
import { join as join4 } from "node:path";
|
|
578
|
+
async function resolveCredentials() {
|
|
579
|
+
const home = process.env.HOME ?? "";
|
|
580
|
+
if (!process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
581
|
+
try {
|
|
582
|
+
const tokenFile = join4(home, ".claude", "agent-oauth-token");
|
|
583
|
+
const token = (await readFile3(tokenFile, "utf-8")).trim();
|
|
584
|
+
if (token) {
|
|
585
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
586
|
+
}
|
|
587
|
+
} catch {}
|
|
588
|
+
}
|
|
589
|
+
if (!process.env.CLAUDE_CODE_OAUTH_TOKEN && process.platform === "darwin") {
|
|
590
|
+
try {
|
|
591
|
+
const token = await new Promise((resolve2) => {
|
|
592
|
+
const proc = spawn3("security", [
|
|
593
|
+
"find-generic-password",
|
|
594
|
+
"-s",
|
|
595
|
+
"Claude Code-credentials",
|
|
596
|
+
"-w"
|
|
597
|
+
], { stdio: ["ignore", "pipe", "pipe"] });
|
|
598
|
+
let stdout = "";
|
|
599
|
+
proc.stdout?.on("data", (d) => {
|
|
600
|
+
stdout += d.toString();
|
|
601
|
+
});
|
|
602
|
+
proc.on("close", (code) => {
|
|
603
|
+
if (code !== 0)
|
|
604
|
+
return resolve2(null);
|
|
605
|
+
try {
|
|
606
|
+
const creds = JSON.parse(stdout.trim());
|
|
607
|
+
const accessToken = creds?.claudeAiOauth?.accessToken;
|
|
608
|
+
resolve2(typeof accessToken === "string" && accessToken.length > 0 ? accessToken : null);
|
|
609
|
+
} catch {
|
|
610
|
+
resolve2(null);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
proc.on("error", () => resolve2(null));
|
|
614
|
+
});
|
|
615
|
+
if (token) {
|
|
616
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
617
|
+
}
|
|
618
|
+
} catch {}
|
|
619
|
+
}
|
|
620
|
+
if (!process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
621
|
+
try {
|
|
622
|
+
const raw = await readFile3(join4(home, ".claude.json"), "utf-8");
|
|
623
|
+
const creds = JSON.parse(raw);
|
|
624
|
+
const accessToken = creds?.claudeAiOauth?.accessToken;
|
|
625
|
+
if (typeof accessToken === "string" && accessToken.length > 0) {
|
|
626
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = accessToken;
|
|
627
|
+
}
|
|
628
|
+
} catch {}
|
|
629
|
+
}
|
|
630
|
+
if (process.env.CLAUDE_CODE_OAUTH_TOKEN) {
|
|
631
|
+
delete process.env.ANTHROPIC_API_KEY;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
async function isClaudeAvailable() {
|
|
635
|
+
return new Promise((resolve2) => {
|
|
636
|
+
const proc = spawn3("which", ["claude"], {
|
|
637
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
638
|
+
});
|
|
639
|
+
proc.on("close", (code) => resolve2(code === 0));
|
|
640
|
+
proc.on("error", () => resolve2(false));
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
async function runClaudePrompt(prompt2) {
|
|
644
|
+
await resolveCredentials();
|
|
645
|
+
return new Promise((resolve2) => {
|
|
646
|
+
const proc = spawn3("claude", ["-p", prompt2, "--no-session-persistence"], {
|
|
647
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
648
|
+
cwd: "/tmp"
|
|
649
|
+
});
|
|
650
|
+
let output = "";
|
|
651
|
+
let stderr = "";
|
|
652
|
+
proc.stdout?.on("data", (data) => {
|
|
653
|
+
output += data.toString();
|
|
654
|
+
});
|
|
655
|
+
proc.stderr?.on("data", (data) => {
|
|
656
|
+
stderr += data.toString();
|
|
657
|
+
});
|
|
658
|
+
proc.on("close", (code) => {
|
|
659
|
+
if (code === 0 && output.trim()) {
|
|
660
|
+
resolve2(output.trim());
|
|
661
|
+
} else {
|
|
662
|
+
debug(`claude CLI exited with code ${code}`);
|
|
663
|
+
if (stderr.trim()) {
|
|
664
|
+
debug(`claude stderr: ${stderr.trim()}`);
|
|
665
|
+
}
|
|
666
|
+
if (!output.trim() && code === 0) {
|
|
667
|
+
debug("claude CLI returned empty output");
|
|
668
|
+
}
|
|
669
|
+
resolve2(null);
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
proc.on("error", (err) => {
|
|
673
|
+
debug(`Failed to spawn claude CLI: ${err.message}`);
|
|
674
|
+
resolve2(null);
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// src/changelog.ts
|
|
680
|
+
var GH_COMMAND = process.env.PUBZ_GH_COMMAND ?? "gh";
|
|
574
681
|
function parseGitRemoteUrl(remoteUrl) {
|
|
575
682
|
const sshMatch = remoteUrl.match(/^git@([^:]+):(.+?)(?:\.git)?$/);
|
|
576
683
|
if (sshMatch) {
|
|
@@ -584,7 +691,7 @@ function parseGitRemoteUrl(remoteUrl) {
|
|
|
584
691
|
}
|
|
585
692
|
function runSilent(command, args, cwd) {
|
|
586
693
|
return new Promise((resolve2) => {
|
|
587
|
-
const proc =
|
|
694
|
+
const proc = spawn4(command, args, {
|
|
588
695
|
cwd,
|
|
589
696
|
stdio: ["ignore", "pipe", "pipe"]
|
|
590
697
|
});
|
|
@@ -667,10 +774,6 @@ async function generateChangelog(cwd) {
|
|
|
667
774
|
const markdown = formatChangelogMarkdown(commits, repoUrl);
|
|
668
775
|
return { commits, terminal, markdown, previousTag, repoUrl };
|
|
669
776
|
}
|
|
670
|
-
async function isClaudeAvailable() {
|
|
671
|
-
const result = await runSilent("which", ["claude"], process.cwd());
|
|
672
|
-
return result.code === 0;
|
|
673
|
-
}
|
|
674
777
|
async function generateAIReleaseNotes(commits, version) {
|
|
675
778
|
const filtered = commits.filter((c) => !isReleaseCommit(c.message));
|
|
676
779
|
if (filtered.length === 0)
|
|
@@ -683,37 +786,7 @@ Here are the commits included in this release:
|
|
|
683
786
|
${commitList}
|
|
684
787
|
|
|
685
788
|
Write concise, user-friendly release notes in markdown. Group related changes under headings if appropriate (e.g. Features, Bug Fixes, Improvements). Focus on what changed and why it matters to users — not implementation details. Do not include a title or version header. Output only the markdown body.`;
|
|
686
|
-
return
|
|
687
|
-
const proc = spawn3("claude", ["-p", prompt2], {
|
|
688
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
689
|
-
});
|
|
690
|
-
let output = "";
|
|
691
|
-
let stderr = "";
|
|
692
|
-
proc.stdout?.on("data", (data) => {
|
|
693
|
-
output += data.toString();
|
|
694
|
-
});
|
|
695
|
-
proc.stderr?.on("data", (data) => {
|
|
696
|
-
stderr += data.toString();
|
|
697
|
-
});
|
|
698
|
-
proc.on("close", (code) => {
|
|
699
|
-
if (code === 0 && output.trim()) {
|
|
700
|
-
resolve2(output.trim());
|
|
701
|
-
} else {
|
|
702
|
-
debug(`claude CLI exited with code ${code}`);
|
|
703
|
-
if (stderr.trim()) {
|
|
704
|
-
debug(`claude stderr: ${stderr.trim()}`);
|
|
705
|
-
}
|
|
706
|
-
if (!output.trim() && code === 0) {
|
|
707
|
-
debug("claude CLI returned empty output");
|
|
708
|
-
}
|
|
709
|
-
resolve2(null);
|
|
710
|
-
}
|
|
711
|
-
});
|
|
712
|
-
proc.on("error", (err) => {
|
|
713
|
-
debug(`Failed to spawn claude CLI: ${err.message}`);
|
|
714
|
-
resolve2(null);
|
|
715
|
-
});
|
|
716
|
-
});
|
|
789
|
+
return runClaudePrompt(prompt2);
|
|
717
790
|
}
|
|
718
791
|
async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
719
792
|
const tagName = `v${version}`;
|
|
@@ -721,7 +794,7 @@ async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
|
721
794
|
console.log(`[DRY RUN] Would create GitHub release for ${tagName}`);
|
|
722
795
|
return { success: true };
|
|
723
796
|
}
|
|
724
|
-
const result = await runSilent(
|
|
797
|
+
const result = await runSilent(GH_COMMAND, ["release", "create", tagName, "--title", tagName, "--notes", body], cwd);
|
|
725
798
|
if (result.code !== 0) {
|
|
726
799
|
return {
|
|
727
800
|
success: false,
|
|
@@ -733,12 +806,12 @@ async function createGitHubRelease(version, body, cwd, dryRun) {
|
|
|
733
806
|
}
|
|
734
807
|
|
|
735
808
|
// src/version.ts
|
|
736
|
-
import { readFile as
|
|
809
|
+
import { readFile as readFile4, writeFile } from "node:fs/promises";
|
|
737
810
|
async function transformWorkspaceProtocolForPublish(packages, newVersion, dryRun) {
|
|
738
811
|
const packageNames = new Set(packages.map((p) => p.name));
|
|
739
812
|
const transforms = [];
|
|
740
813
|
for (const pkg of packages) {
|
|
741
|
-
const content = await
|
|
814
|
+
const content = await readFile4(pkg.packageJsonPath, "utf-8");
|
|
742
815
|
const packageJson = JSON.parse(content);
|
|
743
816
|
let modified = false;
|
|
744
817
|
for (const depType of [
|
|
@@ -755,9 +828,7 @@ async function transformWorkspaceProtocolForPublish(packages, newVersion, dryRun
|
|
|
755
828
|
if (oldVersion.startsWith("workspace:")) {
|
|
756
829
|
const modifier = oldVersion.replace("workspace:", "");
|
|
757
830
|
const newVersionSpec = modifier === "*" || modifier === "" ? newVersion : `${modifier}${newVersion}`;
|
|
758
|
-
if (dryRun) {
|
|
759
|
-
console.log(` [DRY RUN] Would temporarily transform ${pkg.name} ${depType}.${depName}: ${oldVersion} -> ${newVersionSpec}`);
|
|
760
|
-
} else {
|
|
831
|
+
if (!dryRun) {
|
|
761
832
|
transforms.push({
|
|
762
833
|
packageJsonPath: pkg.packageJsonPath,
|
|
763
834
|
depType,
|
|
@@ -774,7 +845,6 @@ async function transformWorkspaceProtocolForPublish(packages, newVersion, dryRun
|
|
|
774
845
|
if (modified && !dryRun) {
|
|
775
846
|
await writeFile(pkg.packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
776
847
|
`);
|
|
777
|
-
console.log(` Transformed workspace references in ${pkg.name}`);
|
|
778
848
|
}
|
|
779
849
|
}
|
|
780
850
|
return transforms;
|
|
@@ -787,7 +857,7 @@ async function restoreWorkspaceProtocol(transforms) {
|
|
|
787
857
|
byPath.set(transform.packageJsonPath, existing);
|
|
788
858
|
}
|
|
789
859
|
for (const [packageJsonPath, pathTransforms] of byPath) {
|
|
790
|
-
const content = await
|
|
860
|
+
const content = await readFile4(packageJsonPath, "utf-8");
|
|
791
861
|
const packageJson = JSON.parse(content);
|
|
792
862
|
for (const transform of pathTransforms) {
|
|
793
863
|
const deps = packageJson[transform.depType];
|
|
@@ -798,9 +868,6 @@ async function restoreWorkspaceProtocol(transforms) {
|
|
|
798
868
|
await writeFile(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
799
869
|
`);
|
|
800
870
|
}
|
|
801
|
-
if (transforms.length > 0) {
|
|
802
|
-
console.log(` Restored workspace references in ${byPath.size} package(s)`);
|
|
803
|
-
}
|
|
804
871
|
}
|
|
805
872
|
function isValidVersion(version) {
|
|
806
873
|
return /^\d+\.\d+\.\d+(-.+)?$/.test(version);
|
|
@@ -823,21 +890,19 @@ function previewBump(version, type) {
|
|
|
823
890
|
return `${version} -> ${newVersion}`;
|
|
824
891
|
}
|
|
825
892
|
async function updatePackageVersion(pkg, newVersion, dryRun) {
|
|
826
|
-
const content = await
|
|
893
|
+
const content = await readFile4(pkg.packageJsonPath, "utf-8");
|
|
827
894
|
const packageJson = JSON.parse(content);
|
|
828
895
|
packageJson.version = newVersion;
|
|
829
896
|
if (dryRun) {
|
|
830
|
-
console.log(` [DRY RUN] Would update ${pkg.name}: ${pkg.version} -> ${newVersion}`);
|
|
831
897
|
return;
|
|
832
898
|
}
|
|
833
899
|
await writeFile(pkg.packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
834
900
|
`);
|
|
835
|
-
console.log(` Updated ${pkg.name}: ${pkg.version} -> ${newVersion}`);
|
|
836
901
|
}
|
|
837
902
|
async function updateLocalDependencyVersions(packages, newVersion, dryRun) {
|
|
838
903
|
const packageNames = new Set(packages.map((p) => p.name));
|
|
839
904
|
for (const pkg of packages) {
|
|
840
|
-
const content = await
|
|
905
|
+
const content = await readFile4(pkg.packageJsonPath, "utf-8");
|
|
841
906
|
const packageJson = JSON.parse(content);
|
|
842
907
|
let modified = false;
|
|
843
908
|
for (const depType of [
|
|
@@ -855,13 +920,9 @@ async function updateLocalDependencyVersions(packages, newVersion, dryRun) {
|
|
|
855
920
|
continue;
|
|
856
921
|
}
|
|
857
922
|
const newVersionSpec = oldVersion.startsWith("^") ? `^${newVersion}` : oldVersion.startsWith("~") ? `~${newVersion}` : newVersion;
|
|
858
|
-
if (deps[depName] !== newVersionSpec) {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
} else {
|
|
862
|
-
deps[depName] = newVersionSpec;
|
|
863
|
-
modified = true;
|
|
864
|
-
}
|
|
923
|
+
if (deps[depName] !== newVersionSpec && !dryRun) {
|
|
924
|
+
deps[depName] = newVersionSpec;
|
|
925
|
+
modified = true;
|
|
865
926
|
}
|
|
866
927
|
}
|
|
867
928
|
}
|
|
@@ -869,7 +930,6 @@ async function updateLocalDependencyVersions(packages, newVersion, dryRun) {
|
|
|
869
930
|
if (modified && !dryRun) {
|
|
870
931
|
await writeFile(pkg.packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
871
932
|
`);
|
|
872
|
-
console.log(` Updated local dependency versions in ${pkg.name}`);
|
|
873
933
|
}
|
|
874
934
|
}
|
|
875
935
|
}
|
|
@@ -881,13 +941,12 @@ var REGISTRIES = {
|
|
|
881
941
|
};
|
|
882
942
|
function getVersion() {
|
|
883
943
|
const __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
884
|
-
const pkgPath =
|
|
944
|
+
const pkgPath = join5(__dirname2, "..", "package.json");
|
|
885
945
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
886
946
|
return pkg.version;
|
|
887
947
|
}
|
|
888
948
|
function printUsage() {
|
|
889
|
-
console.log(`
|
|
890
|
-
pubz - Interactive npm package publisher
|
|
949
|
+
console.log(`pubz - Interactive npm package publisher
|
|
891
950
|
|
|
892
951
|
Usage: pubz [command] [options]
|
|
893
952
|
|
|
@@ -986,15 +1045,14 @@ async function main() {
|
|
|
986
1045
|
const skipAllPrompts = options.ci;
|
|
987
1046
|
const cwd = process.cwd();
|
|
988
1047
|
if (options.dryRun) {
|
|
989
|
-
console.log(yellow(bold("DRY RUN
|
|
1048
|
+
console.log(yellow(bold("⚠️ DRY RUN")) + dim(" — no actual changes will be made"));
|
|
990
1049
|
console.log("");
|
|
991
1050
|
}
|
|
992
|
-
console.log(bold("pubz") + dim("
|
|
993
|
-
console.log(dim("═".repeat(30)));
|
|
1051
|
+
console.log("\uD83D\uDCE6 " + bold("pubz") + dim(" npm package publisher"));
|
|
994
1052
|
console.log("");
|
|
995
1053
|
const uncommitted = await hasUncommittedChanges(cwd);
|
|
996
1054
|
if (uncommitted.hasChanges && !options.dryRun) {
|
|
997
|
-
console.
|
|
1055
|
+
console.error(red(bold("Error:")) + " You have uncommitted changes:");
|
|
998
1056
|
console.log("");
|
|
999
1057
|
for (const file of uncommitted.files.slice(0, 10)) {
|
|
1000
1058
|
console.log(` ${yellow(file)}`);
|
|
@@ -1007,8 +1065,6 @@ async function main() {
|
|
|
1007
1065
|
closePrompt();
|
|
1008
1066
|
process.exit(1);
|
|
1009
1067
|
}
|
|
1010
|
-
console.log(cyan("Discovering packages..."));
|
|
1011
|
-
console.log("");
|
|
1012
1068
|
let packages = await discoverPackages(cwd);
|
|
1013
1069
|
const publishablePackages = packages.filter((p) => !p.isPrivate);
|
|
1014
1070
|
if (publishablePackages.length === 0) {
|
|
@@ -1021,12 +1077,12 @@ async function main() {
|
|
|
1021
1077
|
process.exit(1);
|
|
1022
1078
|
}
|
|
1023
1079
|
packages = sortByDependencyOrder(publishablePackages);
|
|
1024
|
-
|
|
1025
|
-
console.log("");
|
|
1080
|
+
frameHeader("Packages");
|
|
1026
1081
|
for (const pkg of packages) {
|
|
1027
1082
|
const deps = pkg.localDependencies.length > 0 ? dim(` (depends on: ${pkg.localDependencies.join(", ")})`) : "";
|
|
1028
|
-
|
|
1083
|
+
frameLine(`${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(pkg.version)}${deps}`);
|
|
1029
1084
|
}
|
|
1085
|
+
frameFooter();
|
|
1030
1086
|
console.log("");
|
|
1031
1087
|
if (packages.length > 1 && !skipAllPrompts) {
|
|
1032
1088
|
const selectedPackages = await multiSelect("Select packages to publish:", packages.map((pkg) => ({
|
|
@@ -1042,18 +1098,14 @@ async function main() {
|
|
|
1042
1098
|
console.log("");
|
|
1043
1099
|
}
|
|
1044
1100
|
const currentVersion = packages[0].version;
|
|
1045
|
-
console.log(bold(cyan("Step 1:")) + " Version Management");
|
|
1046
|
-
console.log(dim("─".repeat(30)));
|
|
1047
|
-
console.log("");
|
|
1048
|
-
console.log(`Current version: ${yellow(currentVersion)}`);
|
|
1049
|
-
console.log("");
|
|
1050
1101
|
let newVersion = currentVersion;
|
|
1102
|
+
let didBump = false;
|
|
1051
1103
|
if (options.version) {
|
|
1052
1104
|
const bumpTypes = ["patch", "minor", "major"];
|
|
1053
1105
|
const isBumpType = bumpTypes.includes(options.version);
|
|
1054
1106
|
if (isBumpType) {
|
|
1055
1107
|
newVersion = bumpVersion(currentVersion, options.version);
|
|
1056
|
-
|
|
1108
|
+
didBump = true;
|
|
1057
1109
|
} else {
|
|
1058
1110
|
const cleaned = options.version.startsWith("v") ? options.version.slice(1) : options.version;
|
|
1059
1111
|
if (!isValidVersion(cleaned)) {
|
|
@@ -1062,45 +1114,18 @@ async function main() {
|
|
|
1062
1114
|
process.exit(1);
|
|
1063
1115
|
}
|
|
1064
1116
|
newVersion = cleaned;
|
|
1065
|
-
|
|
1066
|
-
}
|
|
1067
|
-
console.log("");
|
|
1068
|
-
console.log(`Updating version to ${green(newVersion)} in all packages...`);
|
|
1069
|
-
console.log("");
|
|
1070
|
-
for (const pkg of packages) {
|
|
1071
|
-
await updatePackageVersion(pkg, newVersion, options.dryRun);
|
|
1072
|
-
}
|
|
1073
|
-
await updateLocalDependencyVersions(packages, newVersion, options.dryRun);
|
|
1074
|
-
for (const pkg of packages) {
|
|
1075
|
-
pkg.version = newVersion;
|
|
1076
|
-
}
|
|
1077
|
-
const commitResult = await commitVersionBump(newVersion, cwd, options.dryRun);
|
|
1078
|
-
if (!commitResult.success) {
|
|
1079
|
-
console.error(red(bold("Failed to commit version bump:")) + ` ${commitResult.error}`);
|
|
1080
|
-
closePrompt();
|
|
1081
|
-
process.exit(1);
|
|
1117
|
+
didBump = true;
|
|
1082
1118
|
}
|
|
1083
|
-
console.log("");
|
|
1084
1119
|
} else if (!skipAllPrompts) {
|
|
1120
|
+
console.log(`Current version: ${yellow(currentVersion)}`);
|
|
1121
|
+
console.log("");
|
|
1085
1122
|
const shouldBump = skipConfirms || await confirm("Bump version before publishing?");
|
|
1086
1123
|
if (shouldBump) {
|
|
1087
1124
|
const bumpChoice = await select("Select version bump type:", [
|
|
1088
|
-
{
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
}
|
|
1092
|
-
{
|
|
1093
|
-
label: `minor (${previewBump(currentVersion, "minor")})`,
|
|
1094
|
-
value: "minor"
|
|
1095
|
-
},
|
|
1096
|
-
{
|
|
1097
|
-
label: `major (${previewBump(currentVersion, "major")})`,
|
|
1098
|
-
value: "major"
|
|
1099
|
-
},
|
|
1100
|
-
{
|
|
1101
|
-
label: "custom version",
|
|
1102
|
-
value: "custom"
|
|
1103
|
-
}
|
|
1125
|
+
{ label: `patch (${previewBump(currentVersion, "patch")})`, value: "patch" },
|
|
1126
|
+
{ label: `minor (${previewBump(currentVersion, "minor")})`, value: "minor" },
|
|
1127
|
+
{ label: `major (${previewBump(currentVersion, "major")})`, value: "major" },
|
|
1128
|
+
{ label: "custom version", value: "custom" }
|
|
1104
1129
|
]);
|
|
1105
1130
|
if (bumpChoice === "custom") {
|
|
1106
1131
|
let customVersion = "";
|
|
@@ -1117,24 +1142,34 @@ async function main() {
|
|
|
1117
1142
|
} else {
|
|
1118
1143
|
newVersion = bumpVersion(currentVersion, bumpChoice);
|
|
1119
1144
|
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
}
|
|
1130
|
-
const commitResult = await commitVersionBump(newVersion, cwd, options.dryRun);
|
|
1131
|
-
if (!commitResult.success) {
|
|
1132
|
-
console.error(red(bold("Failed to commit version bump:")) + ` ${commitResult.error}`);
|
|
1133
|
-
closePrompt();
|
|
1134
|
-
process.exit(1);
|
|
1135
|
-
}
|
|
1136
|
-
console.log("");
|
|
1145
|
+
didBump = true;
|
|
1146
|
+
}
|
|
1147
|
+
console.log("");
|
|
1148
|
+
}
|
|
1149
|
+
if (didBump) {
|
|
1150
|
+
frameHeader("\uD83D\uDD16 Version");
|
|
1151
|
+
if (options.version && ["patch", "minor", "major"].includes(options.version)) {
|
|
1152
|
+
frameLine(`Bumping (${options.version}): ${yellow(currentVersion)} → ${green(newVersion)}`);
|
|
1153
|
+
} else {
|
|
1154
|
+
frameLine(`${yellow(currentVersion)} → ${green(newVersion)}`);
|
|
1137
1155
|
}
|
|
1156
|
+
frameLine(dim("Updating all packages..."));
|
|
1157
|
+
for (const pkg of packages) {
|
|
1158
|
+
await updatePackageVersion(pkg, newVersion, options.dryRun);
|
|
1159
|
+
}
|
|
1160
|
+
await updateLocalDependencyVersions(packages, newVersion, options.dryRun);
|
|
1161
|
+
for (const pkg of packages) {
|
|
1162
|
+
pkg.version = newVersion;
|
|
1163
|
+
}
|
|
1164
|
+
const commitResult = await commitVersionBump(newVersion, cwd, options.dryRun);
|
|
1165
|
+
if (!commitResult.success) {
|
|
1166
|
+
frameFooter();
|
|
1167
|
+
console.error(red(bold("Failed to commit version bump:")) + ` ${commitResult.error}`);
|
|
1168
|
+
closePrompt();
|
|
1169
|
+
process.exit(1);
|
|
1170
|
+
}
|
|
1171
|
+
frameFooter();
|
|
1172
|
+
console.log("");
|
|
1138
1173
|
}
|
|
1139
1174
|
let registry = options.registry;
|
|
1140
1175
|
if (!registry && !skipAllPrompts) {
|
|
@@ -1148,62 +1183,31 @@ async function main() {
|
|
|
1148
1183
|
value: REGISTRIES.github
|
|
1149
1184
|
}
|
|
1150
1185
|
]);
|
|
1151
|
-
}
|
|
1152
|
-
registry = registry || REGISTRIES.npm;
|
|
1153
|
-
console.log("");
|
|
1154
|
-
console.log(`Publishing to: ${cyan(registry)}`);
|
|
1155
|
-
console.log("");
|
|
1156
|
-
if (!options.dryRun && !options.ci) {
|
|
1157
|
-
console.log(cyan("Verifying npm authentication..."));
|
|
1158
|
-
const authResult = await checkNpmAuth(registry);
|
|
1159
|
-
if (!authResult.authenticated) {
|
|
1160
|
-
console.log("");
|
|
1161
|
-
console.log(yellow("Not logged in to npm.") + " Starting login...");
|
|
1162
|
-
console.log("");
|
|
1163
|
-
pausePrompt();
|
|
1164
|
-
const loginResult = await npmLogin(registry);
|
|
1165
|
-
resetPrompt();
|
|
1166
|
-
if (!loginResult.success) {
|
|
1167
|
-
console.error(red(bold("Login failed:")) + ` ${loginResult.error}`);
|
|
1168
|
-
closePrompt();
|
|
1169
|
-
process.exit(1);
|
|
1170
|
-
}
|
|
1171
|
-
const verifyAuth = await checkNpmAuth(registry);
|
|
1172
|
-
if (!verifyAuth.authenticated) {
|
|
1173
|
-
console.error(red(bold("Error:")) + " Login did not complete successfully.");
|
|
1174
|
-
closePrompt();
|
|
1175
|
-
process.exit(1);
|
|
1176
|
-
}
|
|
1177
|
-
console.log("");
|
|
1178
|
-
console.log(green("Logged in as") + ` ${cyan(verifyAuth.username ?? "unknown")}`);
|
|
1179
|
-
} else {
|
|
1180
|
-
console.log(green("Authenticated as") + ` ${cyan(authResult.username ?? "unknown")}`);
|
|
1181
|
-
}
|
|
1182
1186
|
console.log("");
|
|
1183
1187
|
}
|
|
1188
|
+
registry = registry || REGISTRIES.npm;
|
|
1184
1189
|
if (!options.skipBuild) {
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1190
|
+
frameHeader("\uD83C\uDFD7️ Build");
|
|
1191
|
+
frameLine(dim("Running bun run build..."));
|
|
1192
|
+
frameLine();
|
|
1188
1193
|
const buildResult = await runBuild(cwd, options.dryRun);
|
|
1189
1194
|
if (!buildResult.success) {
|
|
1195
|
+
frameFooter();
|
|
1190
1196
|
console.error(red(bold("Build failed:")) + ` ${buildResult.error}`);
|
|
1191
1197
|
closePrompt();
|
|
1192
1198
|
process.exit(1);
|
|
1193
1199
|
}
|
|
1194
|
-
console.log("");
|
|
1195
|
-
console.log(cyan("Verifying builds..."));
|
|
1196
|
-
console.log("");
|
|
1197
1200
|
let allBuildsVerified = true;
|
|
1198
1201
|
for (const pkg of packages) {
|
|
1199
1202
|
const result = await verifyBuild(pkg);
|
|
1200
1203
|
if (result.success) {
|
|
1201
|
-
|
|
1204
|
+
frameLine(` ${green("✓")} ${pkg.name}`);
|
|
1202
1205
|
} else {
|
|
1203
|
-
|
|
1206
|
+
frameLine(` ${red("✗")} ${pkg.name}: ${result.error}`);
|
|
1204
1207
|
allBuildsVerified = false;
|
|
1205
1208
|
}
|
|
1206
1209
|
}
|
|
1210
|
+
frameFooter();
|
|
1207
1211
|
console.log("");
|
|
1208
1212
|
if (!allBuildsVerified) {
|
|
1209
1213
|
console.error(red("Build verification failed.") + muted(" Please fix the issues and try again."));
|
|
@@ -1211,21 +1215,16 @@ async function main() {
|
|
|
1211
1215
|
process.exit(1);
|
|
1212
1216
|
}
|
|
1213
1217
|
}
|
|
1214
|
-
console.log(bold(cyan("Step 3:")) + " Publishing to npm");
|
|
1215
|
-
console.log(dim("─".repeat(30)));
|
|
1216
|
-
console.log("");
|
|
1217
1218
|
if (options.dryRun) {
|
|
1218
|
-
console.log(yellow("[DRY RUN]") + ` Would publish
|
|
1219
|
+
console.log(yellow("[DRY RUN]") + ` Would publish to ${cyan(registry)}:`);
|
|
1219
1220
|
} else {
|
|
1220
|
-
console.log(
|
|
1221
|
+
console.log(`Publishing to ${cyan(registry)}:`);
|
|
1221
1222
|
}
|
|
1222
1223
|
console.log("");
|
|
1223
1224
|
for (const pkg of packages) {
|
|
1224
1225
|
console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
|
|
1225
1226
|
}
|
|
1226
1227
|
console.log("");
|
|
1227
|
-
console.log(`Registry: ${cyan(registry)}`);
|
|
1228
|
-
console.log("");
|
|
1229
1228
|
if (!options.dryRun && !skipConfirms) {
|
|
1230
1229
|
const shouldContinue = await confirm("Continue?");
|
|
1231
1230
|
if (!shouldContinue) {
|
|
@@ -1235,14 +1234,38 @@ async function main() {
|
|
|
1235
1234
|
}
|
|
1236
1235
|
console.log("");
|
|
1237
1236
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1237
|
+
frameHeader("\uD83D\uDE80 Publish");
|
|
1238
|
+
if (!options.dryRun && !options.ci) {
|
|
1239
|
+
frameLine(dim("Verifying authentication..."));
|
|
1240
|
+
const authResult = await checkNpmAuth(registry);
|
|
1241
|
+
if (!authResult.authenticated) {
|
|
1242
|
+
frameLine(yellow("Not authenticated.") + dim(" Starting login..."));
|
|
1243
|
+
frameLine();
|
|
1244
|
+
pausePrompt();
|
|
1245
|
+
const loginResult = await npmLogin(registry);
|
|
1246
|
+
resetPrompt();
|
|
1247
|
+
if (!loginResult.success) {
|
|
1248
|
+
frameFooter();
|
|
1249
|
+
console.error(red(bold("Login failed:")) + ` ${loginResult.error}`);
|
|
1250
|
+
closePrompt();
|
|
1251
|
+
process.exit(1);
|
|
1252
|
+
}
|
|
1253
|
+
const verifyAuth = await checkNpmAuth(registry);
|
|
1254
|
+
if (!verifyAuth.authenticated) {
|
|
1255
|
+
frameFooter();
|
|
1256
|
+
console.error(red(bold("Error:")) + " Login did not complete successfully.");
|
|
1257
|
+
closePrompt();
|
|
1258
|
+
process.exit(1);
|
|
1259
|
+
}
|
|
1260
|
+
frameLine(green("Logged in as") + ` ${cyan(verifyAuth.username ?? "unknown")}`);
|
|
1261
|
+
frameLine();
|
|
1262
|
+
} else {
|
|
1263
|
+
frameLine(dim(`Authenticated as ${cyan(authResult.username ?? "unknown")}`));
|
|
1264
|
+
frameLine();
|
|
1265
|
+
}
|
|
1243
1266
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1267
|
+
frameLine(dim("Preparing packages..."));
|
|
1268
|
+
const workspaceTransforms = await transformWorkspaceProtocolForPublish(packages, newVersion, options.dryRun);
|
|
1246
1269
|
const publishContext = {
|
|
1247
1270
|
otp: options.otp,
|
|
1248
1271
|
useBrowserAuth: !options.ci,
|
|
@@ -1254,6 +1277,11 @@ async function main() {
|
|
|
1254
1277
|
let failedError = "";
|
|
1255
1278
|
try {
|
|
1256
1279
|
for (const pkg of packages) {
|
|
1280
|
+
if (options.dryRun) {
|
|
1281
|
+
frameLine(` ${dim("[dry run]")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
|
|
1282
|
+
} else {
|
|
1283
|
+
frameLine(dim(` Publishing ${pkg.name}...`));
|
|
1284
|
+
}
|
|
1257
1285
|
const result = await publishPackage(pkg, registry, publishContext, options.dryRun);
|
|
1258
1286
|
if (!result.success) {
|
|
1259
1287
|
publishFailed = true;
|
|
@@ -1261,107 +1289,114 @@ async function main() {
|
|
|
1261
1289
|
failedError = result.error ?? "Unknown error";
|
|
1262
1290
|
break;
|
|
1263
1291
|
}
|
|
1292
|
+
if (!options.dryRun) {
|
|
1293
|
+
frameLine(` ${green("✓")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
|
|
1294
|
+
}
|
|
1264
1295
|
}
|
|
1265
1296
|
} finally {
|
|
1266
1297
|
if (workspaceTransforms.length > 0) {
|
|
1267
|
-
console.log("");
|
|
1268
1298
|
await restoreWorkspaceProtocol(workspaceTransforms);
|
|
1269
1299
|
}
|
|
1270
1300
|
}
|
|
1271
1301
|
if (publishFailed) {
|
|
1302
|
+
frameFooter();
|
|
1272
1303
|
console.error(red(bold("Failed to publish")) + ` ${cyan(failedPackageName)}: ${failedError}`);
|
|
1273
1304
|
console.log("");
|
|
1274
|
-
console.
|
|
1305
|
+
console.error(red("Stopping publish process."));
|
|
1275
1306
|
closePrompt();
|
|
1276
1307
|
process.exit(1);
|
|
1277
1308
|
}
|
|
1309
|
+
frameFooter();
|
|
1310
|
+
console.log("");
|
|
1278
1311
|
if (options.dryRun) {
|
|
1279
|
-
console.log("");
|
|
1280
1312
|
console.log(muted("Run without --dry-run to actually publish."));
|
|
1313
|
+
console.log("");
|
|
1281
1314
|
}
|
|
1282
|
-
console.log("");
|
|
1283
|
-
console.log(dim("═".repeat(30)));
|
|
1284
|
-
console.log(green(bold("Publishing complete!")));
|
|
1285
|
-
console.log("");
|
|
1286
|
-
console.log(`Published version: ${green(bold(newVersion))}`);
|
|
1315
|
+
console.log("✅ " + green(bold(`Published v${newVersion}!`)));
|
|
1287
1316
|
console.log("");
|
|
1288
1317
|
const changelog = await generateChangelog(cwd);
|
|
1289
1318
|
if (changelog.terminal) {
|
|
1290
|
-
|
|
1291
|
-
|
|
1319
|
+
frameHeader("\uD83D\uDCCB Changelog");
|
|
1320
|
+
frameLine(dim(`Since ${changelog.previousTag ?? "initial"}`));
|
|
1321
|
+
for (const line of changelog.terminal.split(`
|
|
1322
|
+
`)) {
|
|
1323
|
+
frameLine(line.trimStart());
|
|
1324
|
+
}
|
|
1325
|
+
frameFooter();
|
|
1292
1326
|
console.log("");
|
|
1293
1327
|
}
|
|
1294
1328
|
let releaseNotes = changelog.markdown;
|
|
1295
|
-
if (
|
|
1329
|
+
if (changelog.commits.length > 0) {
|
|
1296
1330
|
const claudeAvailable = await isClaudeAvailable();
|
|
1297
1331
|
if (claudeAvailable) {
|
|
1298
|
-
const useAI = await confirm("Generate release notes with AI (claude)?");
|
|
1332
|
+
const useAI = skipConfirms || await confirm("Generate release notes with AI (claude)?");
|
|
1299
1333
|
if (useAI) {
|
|
1300
|
-
console.log(
|
|
1334
|
+
console.log("");
|
|
1335
|
+
frameHeader("✨ AI Release Notes");
|
|
1336
|
+
frameLine(dim("Generating..."));
|
|
1301
1337
|
const aiNotes = await generateAIReleaseNotes(changelog.commits, newVersion);
|
|
1302
1338
|
if (aiNotes) {
|
|
1303
1339
|
releaseNotes = aiNotes;
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1340
|
+
frameLine();
|
|
1341
|
+
for (const line of aiNotes.split(`
|
|
1342
|
+
`)) {
|
|
1343
|
+
frameLine(line);
|
|
1344
|
+
}
|
|
1308
1345
|
} else {
|
|
1309
|
-
|
|
1346
|
+
frameLine(yellow("Generation failed, falling back to commit list.") + dim(" (run with --verbose for details)"));
|
|
1310
1347
|
}
|
|
1348
|
+
frameFooter();
|
|
1349
|
+
console.log("");
|
|
1311
1350
|
}
|
|
1312
1351
|
}
|
|
1313
1352
|
}
|
|
1314
1353
|
if (!options.dryRun) {
|
|
1354
|
+
let shouldTag;
|
|
1355
|
+
let shouldPush = false;
|
|
1356
|
+
let shouldRelease = false;
|
|
1315
1357
|
if (options.ci) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
console.log(cyan("Pushing tag to origin..."));
|
|
1320
|
-
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1321
|
-
if (releaseNotes) {
|
|
1322
|
-
console.log(cyan("Creating GitHub release..."));
|
|
1323
|
-
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1324
|
-
if (releaseResult.success && releaseResult.url) {
|
|
1325
|
-
console.log(` Release created: ${cyan(releaseResult.url)}`);
|
|
1326
|
-
} else if (!releaseResult.success) {
|
|
1327
|
-
console.error(yellow(releaseResult.error ?? "Failed to create GitHub release"));
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
} else {
|
|
1331
|
-
console.error(red(tagResult.error ?? "Failed to create git tag"));
|
|
1332
|
-
}
|
|
1333
|
-
console.log("");
|
|
1358
|
+
shouldTag = true;
|
|
1359
|
+
shouldPush = true;
|
|
1360
|
+
shouldRelease = !!releaseNotes;
|
|
1334
1361
|
} else {
|
|
1335
|
-
|
|
1362
|
+
shouldTag = skipConfirms || await confirm(`Create a git tag for ${cyan(`v${newVersion}`)}?`);
|
|
1336
1363
|
if (shouldTag) {
|
|
1364
|
+
shouldPush = skipConfirms || await confirm("Push tag to origin?");
|
|
1365
|
+
if (shouldPush && releaseNotes) {
|
|
1366
|
+
shouldRelease = skipConfirms || await confirm("Create a GitHub release?");
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
if (shouldTag)
|
|
1337
1370
|
console.log("");
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1371
|
+
}
|
|
1372
|
+
if (shouldTag) {
|
|
1373
|
+
frameHeader("\uD83C\uDFF7️ Release");
|
|
1374
|
+
frameLine(dim(`Creating tag v${newVersion}...`));
|
|
1375
|
+
const tagResult = await createGitTag(newVersion, cwd, options.dryRun);
|
|
1376
|
+
if (tagResult.success) {
|
|
1377
|
+
if (shouldPush) {
|
|
1378
|
+
frameLine(dim("Pushing tag to origin..."));
|
|
1379
|
+
await pushGitTag(newVersion, cwd, options.dryRun);
|
|
1380
|
+
if (releaseNotes && shouldRelease) {
|
|
1381
|
+
frameLine(dim("Creating GitHub release..."));
|
|
1382
|
+
const releaseResult = await createGitHubRelease(newVersion, releaseNotes, cwd, options.dryRun);
|
|
1383
|
+
if (releaseResult.success && releaseResult.url) {
|
|
1384
|
+
frameLine(` Release: ${cyan(releaseResult.url)}`);
|
|
1385
|
+
} else if (!releaseResult.success) {
|
|
1386
|
+
frameLine(yellow(releaseResult.error ?? "Failed to create GitHub release"));
|
|
1353
1387
|
}
|
|
1354
|
-
} else {
|
|
1355
|
-
console.log(`Tag created locally. Push manually with: ${dim(`git push origin v${newVersion}`)}`);
|
|
1356
1388
|
}
|
|
1357
1389
|
} else {
|
|
1358
|
-
|
|
1390
|
+
frameLine(`Push manually: ${dim(`git push origin v${newVersion}`)}`);
|
|
1359
1391
|
}
|
|
1360
|
-
|
|
1392
|
+
} else {
|
|
1393
|
+
frameLine(red(tagResult.error ?? "Failed to create git tag"));
|
|
1361
1394
|
}
|
|
1395
|
+
frameFooter();
|
|
1396
|
+
console.log("");
|
|
1362
1397
|
}
|
|
1363
1398
|
}
|
|
1364
|
-
console.log(green(bold("Done!")));
|
|
1399
|
+
console.log("\uD83C\uDF89 " + green(bold("Done!")));
|
|
1365
1400
|
closePrompt();
|
|
1366
1401
|
}
|
|
1367
1402
|
main().catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pubz",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Interactive CLI for publishing npm packages (single or monorepo)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build": "bun build src/cli.ts --outdir dist --target node",
|
|
14
14
|
"dev": "bun run src/cli.ts",
|
|
15
|
+
"demo": "bun .kadai/actions/gen-demo.ts",
|
|
15
16
|
"typecheck": "tsc --noEmit",
|
|
16
17
|
"lint": "bunx biome check src/",
|
|
17
18
|
"lint:fix": "bunx biome check --write src/"
|