@ucdjs/release-scripts 0.1.0-beta.46 → 0.1.0-beta.48

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/index.mjs +131 -63
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8,8 +8,8 @@ import farver from "farver";
8
8
  import mri from "mri";
9
9
  import { exec } from "tinyexec";
10
10
  import { dedent } from "@luxass/utils";
11
+ import semver, { compare, gt } from "semver";
11
12
  import prompts from "prompts";
12
- import { compare, gt } from "semver";
13
13
 
14
14
  //#region src/operations/changelog-format.ts
15
15
  function formatCommitLine({ commit, owner, repo, authors }) {
@@ -1003,42 +1003,38 @@ function parseChangelog(content) {
1003
1003
  //#endregion
1004
1004
  //#region src/operations/semver.ts
1005
1005
  function isValidSemver(version) {
1006
- return /^\d+\.\d+\.\d+(?:[-+].+)?$/.test(version);
1006
+ return semver.valid(version) != null;
1007
1007
  }
1008
1008
  function getNextVersion(currentVersion, bump) {
1009
1009
  if (bump === "none") return currentVersion;
1010
1010
  if (!isValidSemver(currentVersion)) throw new Error(`Cannot bump version for invalid semver: ${currentVersion}`);
1011
- const match = currentVersion.match(/^(\d+)\.(\d+)\.(\d+)(.*)$/);
1012
- if (!match) throw new Error(`Invalid semver version: ${currentVersion}`);
1013
- const [, major, minor, patch] = match;
1014
- let newMajor = Number.parseInt(major, 10);
1015
- let newMinor = Number.parseInt(minor, 10);
1016
- let newPatch = Number.parseInt(patch, 10);
1017
- switch (bump) {
1018
- case "major":
1019
- newMajor += 1;
1020
- newMinor = 0;
1021
- newPatch = 0;
1022
- break;
1023
- case "minor":
1024
- newMinor += 1;
1025
- newPatch = 0;
1026
- break;
1027
- case "patch":
1028
- newPatch += 1;
1029
- break;
1030
- }
1031
- return `${newMajor}.${newMinor}.${newPatch}`;
1011
+ const next = semver.inc(currentVersion, bump);
1012
+ if (!next) throw new Error(`Failed to bump version ${currentVersion} with bump ${bump}`);
1013
+ return next;
1032
1014
  }
1033
1015
  function calculateBumpType(oldVersion, newVersion) {
1034
1016
  if (!isValidSemver(oldVersion) || !isValidSemver(newVersion)) throw new Error(`Cannot calculate bump type for invalid semver: ${oldVersion} or ${newVersion}`);
1035
- const oldParts = oldVersion.split(".").map(Number);
1036
- const newParts = newVersion.split(".").map(Number);
1037
- if (newParts[0] > oldParts[0]) return "major";
1038
- if (newParts[1] > oldParts[1]) return "minor";
1039
- if (newParts[2] > oldParts[2]) return "patch";
1017
+ const diff = semver.diff(oldVersion, newVersion);
1018
+ if (!diff) return "none";
1019
+ if (diff === "major" || diff === "premajor") return "major";
1020
+ if (diff === "minor" || diff === "preminor") return "minor";
1021
+ if (diff === "patch" || diff === "prepatch" || diff === "prerelease") return "patch";
1022
+ if (semver.gt(newVersion, oldVersion)) return "patch";
1040
1023
  return "none";
1041
1024
  }
1025
+ function getPrereleaseIdentifier(version) {
1026
+ const parsed = semver.parse(version);
1027
+ if (!parsed || parsed.prerelease.length === 0) return;
1028
+ const identifier = parsed.prerelease[0];
1029
+ return typeof identifier === "string" ? identifier : void 0;
1030
+ }
1031
+ function getNextPrereleaseVersion(currentVersion, mode, identifier) {
1032
+ if (!isValidSemver(currentVersion)) throw new Error(`Cannot bump prerelease for invalid semver: ${currentVersion}`);
1033
+ const releaseType = mode === "next" ? "prerelease" : mode;
1034
+ const next = identifier ? semver.inc(currentVersion, releaseType, identifier) : semver.inc(currentVersion, releaseType);
1035
+ if (!next) throw new Error(`Failed to compute prerelease version for ${currentVersion}`);
1036
+ return next;
1037
+ }
1042
1038
 
1043
1039
  //#endregion
1044
1040
  //#region src/core/prompts.ts
@@ -1062,41 +1058,101 @@ async function selectPackagePrompt(packages) {
1062
1058
  async function selectVersionPrompt(workspaceRoot, pkg, currentVersion, suggestedVersion, options) {
1063
1059
  const defaultChoice = options?.defaultChoice ?? "auto";
1064
1060
  const suggestedSuffix = options?.suggestedHint ? farver.dim(` (${options.suggestedHint})`) : "";
1065
- const initial = defaultChoice === "skip" ? 0 : defaultChoice === "suggested" ? 4 : defaultChoice === "as-is" ? 5 : suggestedVersion === currentVersion ? 0 : 4;
1061
+ const prereleaseIdentifier = getPrereleaseIdentifier(currentVersion);
1062
+ const nextDefaultPrerelease = getNextPrereleaseVersion(currentVersion, "next", prereleaseIdentifier === "alpha" || prereleaseIdentifier === "beta" ? prereleaseIdentifier : "beta");
1063
+ const nextBeta = getNextPrereleaseVersion(currentVersion, "next", "beta");
1064
+ const nextAlpha = getNextPrereleaseVersion(currentVersion, "next", "alpha");
1065
+ const prePatchBeta = getNextPrereleaseVersion(currentVersion, "prepatch", "beta");
1066
+ const preMinorBeta = getNextPrereleaseVersion(currentVersion, "preminor", "beta");
1067
+ const preMajorBeta = getNextPrereleaseVersion(currentVersion, "premajor", "beta");
1068
+ const prePatchAlpha = getNextPrereleaseVersion(currentVersion, "prepatch", "alpha");
1069
+ const preMinorAlpha = getNextPrereleaseVersion(currentVersion, "preminor", "alpha");
1070
+ const preMajorAlpha = getNextPrereleaseVersion(currentVersion, "premajor", "alpha");
1071
+ const choices = [
1072
+ {
1073
+ value: "skip",
1074
+ title: `skip ${farver.dim("(no change)")}`
1075
+ },
1076
+ {
1077
+ value: "suggested",
1078
+ title: `suggested ${farver.bold(suggestedVersion)}${suggestedSuffix}`
1079
+ },
1080
+ {
1081
+ value: "as-is",
1082
+ title: `as-is ${farver.dim("(keep current version)")}`
1083
+ },
1084
+ {
1085
+ value: "major",
1086
+ title: `major ${farver.bold(getNextVersion(pkg.version, "major"))}`
1087
+ },
1088
+ {
1089
+ value: "minor",
1090
+ title: `minor ${farver.bold(getNextVersion(pkg.version, "minor"))}`
1091
+ },
1092
+ {
1093
+ value: "patch",
1094
+ title: `patch ${farver.bold(getNextVersion(pkg.version, "patch"))}`
1095
+ },
1096
+ {
1097
+ value: "next",
1098
+ title: `next ${farver.bold(nextDefaultPrerelease)}`
1099
+ },
1100
+ {
1101
+ value: "prepatch-beta",
1102
+ title: `pre-patch (beta) ${farver.bold(prePatchBeta)}`
1103
+ },
1104
+ {
1105
+ value: "preminor-beta",
1106
+ title: `pre-minor (beta) ${farver.bold(preMinorBeta)}`
1107
+ },
1108
+ {
1109
+ value: "premajor-beta",
1110
+ title: `pre-major (beta) ${farver.bold(preMajorBeta)}`
1111
+ },
1112
+ {
1113
+ value: "prepatch-alpha",
1114
+ title: `pre-patch (alpha) ${farver.bold(prePatchAlpha)}`
1115
+ },
1116
+ {
1117
+ value: "preminor-alpha",
1118
+ title: `pre-minor (alpha) ${farver.bold(preMinorAlpha)}`
1119
+ },
1120
+ {
1121
+ value: "premajor-alpha",
1122
+ title: `pre-major (alpha) ${farver.bold(preMajorAlpha)}`
1123
+ },
1124
+ {
1125
+ value: "next-beta",
1126
+ title: `next beta ${farver.bold(nextBeta)}`
1127
+ },
1128
+ {
1129
+ value: "next-alpha",
1130
+ title: `next alpha ${farver.bold(nextAlpha)}`
1131
+ },
1132
+ {
1133
+ value: "custom",
1134
+ title: "custom"
1135
+ }
1136
+ ];
1137
+ const initialValue = defaultChoice === "auto" ? suggestedVersion === currentVersion ? "skip" : "suggested" : defaultChoice;
1138
+ const initial = Math.max(0, choices.findIndex((choice) => choice.value === initialValue));
1139
+ const prereleaseVersionByChoice = {
1140
+ "next": nextDefaultPrerelease,
1141
+ "next-beta": nextBeta,
1142
+ "next-alpha": nextAlpha,
1143
+ "prepatch-beta": prePatchBeta,
1144
+ "preminor-beta": preMinorBeta,
1145
+ "premajor-beta": preMajorBeta,
1146
+ "prepatch-alpha": prePatchAlpha,
1147
+ "preminor-alpha": preMinorAlpha,
1148
+ "premajor-alpha": preMajorAlpha
1149
+ };
1066
1150
  const answers = await prompts([{
1067
1151
  type: "autocomplete",
1068
1152
  name: "version",
1069
1153
  message: `${pkg.name}: ${farver.green(pkg.version)}`,
1070
- choices: [
1071
- {
1072
- value: "skip",
1073
- title: `skip ${farver.dim("(no change)")}`
1074
- },
1075
- {
1076
- value: "major",
1077
- title: `major ${farver.bold(getNextVersion(pkg.version, "major"))}`
1078
- },
1079
- {
1080
- value: "minor",
1081
- title: `minor ${farver.bold(getNextVersion(pkg.version, "minor"))}`
1082
- },
1083
- {
1084
- value: "patch",
1085
- title: `patch ${farver.bold(getNextVersion(pkg.version, "patch"))}`
1086
- },
1087
- {
1088
- value: "suggested",
1089
- title: `suggested ${farver.bold(suggestedVersion)}${suggestedSuffix}`
1090
- },
1091
- {
1092
- value: "as-is",
1093
- title: `as-is ${farver.dim("(keep current version)")}`
1094
- },
1095
- {
1096
- value: "custom",
1097
- title: "custom"
1098
- }
1099
- ],
1154
+ choices,
1155
+ limit: choices.length,
1100
1156
  initial
1101
1157
  }, {
1102
1158
  type: (prev) => prev === "custom" ? "text" : null,
@@ -1115,7 +1171,9 @@ async function selectVersionPrompt(workspaceRoot, pkg, currentVersion, suggested
1115
1171
  if (!answers.custom) return null;
1116
1172
  return answers.custom;
1117
1173
  } else if (answers.version === "as-is") return currentVersion;
1118
- else return getNextVersion(pkg.version, answers.version);
1174
+ const prereleaseVersion = prereleaseVersionByChoice[answers.version];
1175
+ if (prereleaseVersion) return prereleaseVersion;
1176
+ return getNextVersion(pkg.version, answers.version);
1119
1177
  }
1120
1178
 
1121
1179
  //#endregion
@@ -2114,11 +2172,12 @@ async function buildPackage(packageName, workspaceRoot, options) {
2114
2172
  * Publish a package to NPM
2115
2173
  * Uses pnpm to handle workspace protocol and catalog: resolution automatically
2116
2174
  * @param packageName - The package name to publish
2175
+ * @param version - The package version to publish
2117
2176
  * @param workspaceRoot - Path to the workspace root
2118
2177
  * @param options - Normalized release scripts options
2119
2178
  * @returns Result indicating success or failure
2120
2179
  */
2121
- async function publishPackage(packageName, workspaceRoot, options) {
2180
+ async function publishPackage(packageName, version, workspaceRoot, options) {
2122
2181
  const args = [
2123
2182
  "--filter",
2124
2183
  packageName,
@@ -2128,7 +2187,16 @@ async function publishPackage(packageName, workspaceRoot, options) {
2128
2187
  "--no-git-checks"
2129
2188
  ];
2130
2189
  if (options.npm.otp) args.push("--otp", options.npm.otp);
2131
- if (process.env.NPM_CONFIG_TAG) args.push("--tag", process.env.NPM_CONFIG_TAG);
2190
+ const explicitTag = process.env.NPM_CONFIG_TAG;
2191
+ const prereleaseTag = (() => {
2192
+ const prerelease = semver.prerelease(version);
2193
+ if (!prerelease || prerelease.length === 0) return;
2194
+ const identifier = prerelease[0];
2195
+ if (identifier === "alpha" || identifier === "beta") return identifier;
2196
+ return "next";
2197
+ })();
2198
+ const publishTag = explicitTag || prereleaseTag;
2199
+ if (publishTag) args.push("--tag", publishTag);
2132
2200
  const env = { ...process.env };
2133
2201
  if (options.npm.provenance) env.NPM_CONFIG_PROVENANCE = "true";
2134
2202
  try {
@@ -2192,7 +2260,7 @@ async function publishWorkflow(options) {
2192
2260
  }
2193
2261
  }
2194
2262
  logger.step(`Publishing ${farver.cyan(`${packageName}@${version}`)} to NPM...`);
2195
- const publishResult = await publishPackage(packageName, options.workspaceRoot, options);
2263
+ const publishResult = await publishPackage(packageName, version, options.workspaceRoot, options);
2196
2264
  if (!publishResult.ok) {
2197
2265
  logger.error(`Failed to publish: ${publishResult.error.message}`);
2198
2266
  status.failed.push(packageName);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ucdjs/release-scripts",
3
- "version": "0.1.0-beta.46",
3
+ "version": "0.1.0-beta.48",
4
4
  "description": "@ucdjs release scripts",
5
5
  "type": "module",
6
6
  "license": "MIT",