pubz 0.7.0 → 0.7.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 (2) hide show
  1. package/dist/cli.js +193 -105
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3,8 +3,8 @@ import { createRequire } from "node:module";
3
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
4
 
5
5
  // src/cli.ts
6
- import { readFileSync } from "node:fs";
7
- import { dirname, join as join5 } from "node:path";
6
+ import { readFileSync as readFileSync2 } from "node:fs";
7
+ import { dirname, join as join6 } from "node:path";
8
8
  import { fileURLToPath } from "node:url";
9
9
 
10
10
  // src/colors.ts
@@ -805,6 +805,54 @@ async function createGitHubRelease(version, body, cwd, dryRun) {
805
805
  return { success: true, url };
806
806
  }
807
807
 
808
+ // src/config.ts
809
+ import { existsSync, readFileSync } from "node:fs";
810
+ import { join as join5 } from "node:path";
811
+ var CONFIG_FILENAME = ".pubz";
812
+ var VALID_KEYS = new Set(["skip-build", "skip-publish", "registry"]);
813
+ function loadConfig(cwd) {
814
+ const configPath = join5(cwd, CONFIG_FILENAME);
815
+ if (!existsSync(configPath)) {
816
+ debug(`No ${CONFIG_FILENAME} found at ${configPath}`);
817
+ return {};
818
+ }
819
+ const content = readFileSync(configPath, "utf-8");
820
+ const config = {};
821
+ for (const rawLine of content.split(`
822
+ `)) {
823
+ const line = rawLine.trim();
824
+ if (!line || line.startsWith("#"))
825
+ continue;
826
+ const eqIndex = line.indexOf("=");
827
+ let key;
828
+ let value;
829
+ if (eqIndex === -1) {
830
+ key = line;
831
+ } else {
832
+ key = line.slice(0, eqIndex).trim();
833
+ value = line.slice(eqIndex + 1).trim();
834
+ }
835
+ if (!VALID_KEYS.has(key)) {
836
+ debug(`Ignoring unknown config key: ${key}`);
837
+ continue;
838
+ }
839
+ if (key === "registry") {
840
+ config.registry = value ?? "";
841
+ } else {
842
+ const boolKey = key;
843
+ if (value === undefined || value === "true") {
844
+ config[boolKey] = true;
845
+ } else if (value === "false") {
846
+ config[boolKey] = false;
847
+ } else {
848
+ debug(`Invalid boolean value for ${key}: ${value}`);
849
+ }
850
+ }
851
+ }
852
+ debug(`Loaded ${CONFIG_FILENAME}: ${JSON.stringify(config)}`);
853
+ return config;
854
+ }
855
+
808
856
  // src/version.ts
809
857
  import { readFile as readFile4, writeFile } from "node:fs/promises";
810
858
  async function transformWorkspaceProtocolForPublish(packages, newVersion, dryRun) {
@@ -941,8 +989,8 @@ var REGISTRIES = {
941
989
  };
942
990
  function getVersion() {
943
991
  const __dirname2 = dirname(fileURLToPath(import.meta.url));
944
- const pkgPath = join5(__dirname2, "..", "package.json");
945
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
992
+ const pkgPath = join6(__dirname2, "..", "package.json");
993
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
946
994
  return pkg.version;
947
995
  }
948
996
  function printUsage() {
@@ -958,6 +1006,7 @@ Options:
958
1006
  --registry <url> Specify npm registry URL (default: public npm)
959
1007
  --otp <code> One-time password for 2FA
960
1008
  --skip-build Skip the build step
1009
+ --skip-publish Skip npm publish (still does version bump, tag, and release)
961
1010
  --yes, -y Skip yes/no confirmation prompts (still asks for choices)
962
1011
  --ci CI mode: skip all prompts, auto-accept everything
963
1012
  --version <value> Version bump type (patch|minor|major) or explicit version (required with --ci)
@@ -968,8 +1017,18 @@ Examples:
968
1017
  pubz # Interactive publish
969
1018
  pubz --dry-run # Preview what would happen
970
1019
  pubz --registry https://npm.pkg.github.com # Publish to GitHub Packages
1020
+ pubz --skip-publish # Version bump, tag, release — no npm publish
971
1021
  pubz --ci --version patch # CI mode with patch bump
972
1022
  pubz --ci --version 1.2.3 # CI mode with explicit version
1023
+ pubz --ci --version patch --skip-publish # CI: bump, tag, release without npm publish
1024
+
1025
+ Config file:
1026
+ Place a .pubz file in your project root to set default options.
1027
+ CLI flags always override config values.
1028
+
1029
+ # .pubz
1030
+ skip-publish
1031
+ registry=https://npm.pkg.github.com
973
1032
  `);
974
1033
  }
975
1034
  function parseArgs(args) {
@@ -978,39 +1037,53 @@ function parseArgs(args) {
978
1037
  registry: "",
979
1038
  otp: "",
980
1039
  skipBuild: false,
1040
+ skipPublish: false,
981
1041
  skipConfirms: false,
982
1042
  ci: false,
983
1043
  version: "",
984
1044
  verbose: false,
985
1045
  help: false
986
1046
  };
1047
+ const cliExplicit = new Set;
987
1048
  for (let i = 0;i < args.length; i++) {
988
1049
  const arg = args[i];
989
1050
  switch (arg) {
990
1051
  case "--dry-run":
991
1052
  options.dryRun = true;
1053
+ cliExplicit.add("dryRun");
992
1054
  break;
993
1055
  case "--registry":
994
1056
  options.registry = args[++i] || "";
1057
+ cliExplicit.add("registry");
995
1058
  break;
996
1059
  case "--otp":
997
1060
  options.otp = args[++i] || "";
1061
+ cliExplicit.add("otp");
998
1062
  break;
999
1063
  case "--skip-build":
1000
1064
  options.skipBuild = true;
1065
+ cliExplicit.add("skipBuild");
1066
+ break;
1067
+ case "--skip-publish":
1068
+ options.skipPublish = true;
1069
+ cliExplicit.add("skipPublish");
1001
1070
  break;
1002
1071
  case "--yes":
1003
1072
  case "-y":
1004
1073
  options.skipConfirms = true;
1074
+ cliExplicit.add("skipConfirms");
1005
1075
  break;
1006
1076
  case "--ci":
1007
1077
  options.ci = true;
1078
+ cliExplicit.add("ci");
1008
1079
  break;
1009
1080
  case "--version":
1010
1081
  options.version = args[++i] || "";
1082
+ cliExplicit.add("version");
1011
1083
  break;
1012
1084
  case "--verbose":
1013
1085
  options.verbose = true;
1086
+ cliExplicit.add("verbose");
1014
1087
  break;
1015
1088
  case "-h":
1016
1089
  case "--help":
@@ -1018,19 +1091,30 @@ function parseArgs(args) {
1018
1091
  break;
1019
1092
  }
1020
1093
  }
1021
- return options;
1094
+ return { options, cliExplicit };
1022
1095
  }
1023
1096
  async function main() {
1024
1097
  if (process.argv[2] === "version") {
1025
1098
  console.log(getVersion());
1026
1099
  process.exit(0);
1027
1100
  }
1028
- const options = parseArgs(process.argv.slice(2));
1101
+ const { options, cliExplicit } = parseArgs(process.argv.slice(2));
1029
1102
  setVerbose(options.verbose);
1030
1103
  if (options.help) {
1031
1104
  printUsage();
1032
1105
  process.exit(0);
1033
1106
  }
1107
+ const cwd = process.cwd();
1108
+ const config = loadConfig(cwd);
1109
+ if (config["skip-build"] && !cliExplicit.has("skipBuild")) {
1110
+ options.skipBuild = config["skip-build"];
1111
+ }
1112
+ if (config["skip-publish"] && !cliExplicit.has("skipPublish")) {
1113
+ options.skipPublish = config["skip-publish"];
1114
+ }
1115
+ if (config.registry && !cliExplicit.has("registry")) {
1116
+ options.registry = config.registry;
1117
+ }
1034
1118
  if (options.ci && !options.version) {
1035
1119
  console.error(red(bold("Error:")) + " --ci requires --version to be specified");
1036
1120
  console.log("");
@@ -1043,7 +1127,6 @@ async function main() {
1043
1127
  }
1044
1128
  const skipConfirms = options.skipConfirms || options.ci;
1045
1129
  const skipAllPrompts = options.ci;
1046
- const cwd = process.cwd();
1047
1130
  if (options.dryRun) {
1048
1131
  console.log(yellow(bold("⚠️ DRY RUN")) + dim(" — no actual changes will be made"));
1049
1132
  console.log("");
@@ -1171,21 +1254,6 @@ async function main() {
1171
1254
  frameFooter();
1172
1255
  console.log("");
1173
1256
  }
1174
- let registry = options.registry;
1175
- if (!registry && !skipAllPrompts) {
1176
- registry = await select("Select publish target:", [
1177
- {
1178
- label: "Public npm registry (https://registry.npmjs.org)",
1179
- value: REGISTRIES.npm
1180
- },
1181
- {
1182
- label: "GitHub Packages (https://npm.pkg.github.com)",
1183
- value: REGISTRIES.github
1184
- }
1185
- ]);
1186
- console.log("");
1187
- }
1188
- registry = registry || REGISTRIES.npm;
1189
1257
  if (!options.skipBuild) {
1190
1258
  frameHeader("\uD83C\uDFD7️ Build");
1191
1259
  frameLine(dim("Running bun run build..."));
@@ -1215,104 +1283,124 @@ async function main() {
1215
1283
  process.exit(1);
1216
1284
  }
1217
1285
  }
1218
- if (options.dryRun) {
1219
- console.log(yellow("[DRY RUN]") + ` Would publish to ${cyan(registry)}:`);
1286
+ if (options.skipPublish) {
1287
+ console.log(yellow(bold("⏭️ Skipping npm publish")) + dim(" use without --skip-publish to publish to npm"));
1288
+ console.log("");
1220
1289
  } else {
1221
- console.log(`Publishing to ${cyan(registry)}:`);
1222
- }
1223
- console.log("");
1224
- for (const pkg of packages) {
1225
- console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1226
- }
1227
- console.log("");
1228
- if (!options.dryRun && !skipConfirms) {
1229
- const shouldContinue = await confirm("Continue?");
1230
- if (!shouldContinue) {
1231
- console.log(yellow("Publish cancelled."));
1232
- closePrompt();
1233
- process.exit(0);
1290
+ let registry = options.registry;
1291
+ if (!registry && !skipAllPrompts) {
1292
+ registry = await select("Select publish target:", [
1293
+ {
1294
+ label: "Public npm registry (https://registry.npmjs.org)",
1295
+ value: REGISTRIES.npm
1296
+ },
1297
+ {
1298
+ label: "GitHub Packages (https://npm.pkg.github.com)",
1299
+ value: REGISTRIES.github
1300
+ }
1301
+ ]);
1302
+ console.log("");
1303
+ }
1304
+ registry = registry || REGISTRIES.npm;
1305
+ if (options.dryRun) {
1306
+ console.log(yellow("[DRY RUN]") + ` Would publish to ${cyan(registry)}:`);
1307
+ } else {
1308
+ console.log(`Publishing to ${cyan(registry)}:`);
1234
1309
  }
1235
1310
  console.log("");
1236
- }
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.");
1311
+ for (const pkg of packages) {
1312
+ console.log(` ${dim("•")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1313
+ }
1314
+ console.log("");
1315
+ if (!options.dryRun && !skipConfirms) {
1316
+ const shouldContinue = await confirm("Continue?");
1317
+ if (!shouldContinue) {
1318
+ console.log(yellow("Publish cancelled."));
1257
1319
  closePrompt();
1258
- process.exit(1);
1320
+ process.exit(0);
1259
1321
  }
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();
1322
+ console.log("");
1265
1323
  }
1266
- }
1267
- frameLine(dim("Preparing packages..."));
1268
- const workspaceTransforms = await transformWorkspaceProtocolForPublish(packages, newVersion, options.dryRun);
1269
- const publishContext = {
1270
- otp: options.otp,
1271
- useBrowserAuth: !options.ci,
1272
- onInteractiveStart: pausePrompt,
1273
- onInteractiveComplete: resetPrompt
1274
- };
1275
- let publishFailed = false;
1276
- let failedPackageName = "";
1277
- let failedError = "";
1278
- try {
1279
- for (const pkg of packages) {
1280
- if (options.dryRun) {
1281
- frameLine(` ${dim("[dry run]")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1324
+ frameHeader("\uD83D\uDE80 Publish");
1325
+ if (!options.dryRun && !options.ci) {
1326
+ frameLine(dim("Verifying authentication..."));
1327
+ const authResult = await checkNpmAuth(registry);
1328
+ if (!authResult.authenticated) {
1329
+ frameLine(yellow("Not authenticated.") + dim(" Starting login..."));
1330
+ frameLine();
1331
+ pausePrompt();
1332
+ const loginResult = await npmLogin(registry);
1333
+ resetPrompt();
1334
+ if (!loginResult.success) {
1335
+ frameFooter();
1336
+ console.error(red(bold("Login failed:")) + ` ${loginResult.error}`);
1337
+ closePrompt();
1338
+ process.exit(1);
1339
+ }
1340
+ const verifyAuth = await checkNpmAuth(registry);
1341
+ if (!verifyAuth.authenticated) {
1342
+ frameFooter();
1343
+ console.error(red(bold("Error:")) + " Login did not complete successfully.");
1344
+ closePrompt();
1345
+ process.exit(1);
1346
+ }
1347
+ frameLine(green("Logged in as") + ` ${cyan(verifyAuth.username ?? "unknown")}`);
1348
+ frameLine();
1282
1349
  } else {
1283
- frameLine(dim(` Publishing ${pkg.name}...`));
1350
+ frameLine(dim(`Authenticated as ${cyan(authResult.username ?? "unknown")}`));
1351
+ frameLine();
1284
1352
  }
1285
- const result = await publishPackage(pkg, registry, publishContext, options.dryRun);
1286
- if (!result.success) {
1287
- publishFailed = true;
1288
- failedPackageName = pkg.name;
1289
- failedError = result.error ?? "Unknown error";
1290
- break;
1353
+ }
1354
+ frameLine(dim("Preparing packages..."));
1355
+ const workspaceTransforms = await transformWorkspaceProtocolForPublish(packages, newVersion, options.dryRun);
1356
+ const publishContext = {
1357
+ otp: options.otp,
1358
+ useBrowserAuth: !options.ci,
1359
+ onInteractiveStart: pausePrompt,
1360
+ onInteractiveComplete: resetPrompt
1361
+ };
1362
+ let publishFailed = false;
1363
+ let failedPackageName = "";
1364
+ let failedError = "";
1365
+ try {
1366
+ for (const pkg of packages) {
1367
+ if (options.dryRun) {
1368
+ frameLine(` ${dim("[dry run]")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1369
+ } else {
1370
+ frameLine(dim(` Publishing ${pkg.name}...`));
1371
+ }
1372
+ const result = await publishPackage(pkg, registry, publishContext, options.dryRun);
1373
+ if (!result.success) {
1374
+ publishFailed = true;
1375
+ failedPackageName = pkg.name;
1376
+ failedError = result.error ?? "Unknown error";
1377
+ break;
1378
+ }
1379
+ if (!options.dryRun) {
1380
+ frameLine(` ${green("✓")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1381
+ }
1291
1382
  }
1292
- if (!options.dryRun) {
1293
- frameLine(` ${green("✓")} ${cyan(pkg.name)}${dim("@")}${yellow(newVersion)}`);
1383
+ } finally {
1384
+ if (workspaceTransforms.length > 0) {
1385
+ await restoreWorkspaceProtocol(workspaceTransforms);
1294
1386
  }
1295
1387
  }
1296
- } finally {
1297
- if (workspaceTransforms.length > 0) {
1298
- await restoreWorkspaceProtocol(workspaceTransforms);
1388
+ if (publishFailed) {
1389
+ frameFooter();
1390
+ console.error(red(bold("Failed to publish")) + ` ${cyan(failedPackageName)}: ${failedError}`);
1391
+ console.log("");
1392
+ console.error(red("Stopping publish process."));
1393
+ closePrompt();
1394
+ process.exit(1);
1299
1395
  }
1300
- }
1301
- if (publishFailed) {
1302
1396
  frameFooter();
1303
- console.error(red(bold("Failed to publish")) + ` ${cyan(failedPackageName)}: ${failedError}`);
1304
- console.log("");
1305
- console.error(red("Stopping publish process."));
1306
- closePrompt();
1307
- process.exit(1);
1308
- }
1309
- frameFooter();
1310
- console.log("");
1311
- if (options.dryRun) {
1312
- console.log(muted("Run without --dry-run to actually publish."));
1313
1397
  console.log("");
1398
+ if (options.dryRun) {
1399
+ console.log(muted("Run without --dry-run to actually publish."));
1400
+ console.log("");
1401
+ }
1314
1402
  }
1315
- console.log("✅ " + green(bold(`Published v${newVersion}!`)));
1403
+ console.log("✅ " + green(bold(`Released v${newVersion}!`)));
1316
1404
  console.log("");
1317
1405
  const changelog = await generateChangelog(cwd);
1318
1406
  if (changelog.terminal) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pubz",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Interactive CLI for publishing npm packages (single or monorepo)",
5
5
  "type": "module",
6
6
  "bin": {