@peiyanlu/release 0.0.15 → 0.0.16

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/dist/cli.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import path, { join, resolve } from "node:path";
2
2
  import { fileURLToPath, pathToFileURL } from "node:url";
3
- import { bumpPackageVersion, coloredChangeset, eol, execAsync, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLog, getPackageInfo, getPackageUrl, getPublishedVersion, getRemote, getStatus, gitAddAll, gitAddTracked, gitCommit, gitTagAnnotated, hasWriteAccess, isGitRepo, isOtpError, isPrerelease, isValid, isWorkingDirClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, pushBranch, pushTag, readJsonFile, registryArg, resolveChangelogRange, resolvePublishTag, runNpm } from "@peiyanlu/cli-utils";
3
+ import { bumpPackageVersion, canPublish, coloredStatus, eol, execAsync, getAuthenticatedUser, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLogSince, getPackageInfo, getPackageUrl, getPublishedVersion, getRemoteList, getRemoteNames, getShortStatus, gitAddAll, gitAddTracked, gitBranchCurrent, gitCommitMessage, gitPushBranch, gitPushTag, gitResetHardSync, gitTagAnnotated, gitTagDeleteSync, hasWriteAccess, isGitRepo, isOtpError, isPrerelease, isValidVersion, isWorkingTreeClean, parseGitHubRepo, parseVersion, pingRegistry, publishPackage, readJsonFile, resolveChangelogRange, resolvePublishTag } from "@peiyanlu/cli-utils";
4
4
  import { dim, green, red, rgb, underline, yellow } from "ansis";
5
5
  import { program } from "commander";
6
6
  import { createReadStream, createWriteStream, existsSync, readFileSync, statSync, writeFileSync } from "node:fs";
@@ -9,7 +9,6 @@ import { castArray, isFunction, isPlainObject, isUndefined, isZero } from "@peiy
9
9
  import { publint } from "publint";
10
10
  import { formatMessage } from "publint/utils";
11
11
  import { inc, neq } from "semver";
12
- import { spawnSync } from "node:child_process";
13
12
  import { inspect } from "node:util";
14
13
  import { ConventionalChangelog } from "conventional-changelog";
15
14
  import createPreset from "conventional-changelog-conventionalcommits";
@@ -19,7 +18,7 @@ import { Octokit } from "@octokit/rest";
19
18
  import { contentType } from "mime-types";
20
19
  import open from "open";
21
20
  import { glob } from "tinyglobby";
22
- //#region node_modules/.pnpm/tsdown@0.22.1_publint@0.3.21_typescript@6.0.3/node_modules/tsdown/esm-shims.js
21
+ //#region node_modules/.pnpm/tsdown@0.22.3_publint@0.3.21_typescript@6.0.3/node_modules/tsdown/esm-shims.js
23
22
  const getFilename = () => fileURLToPath(import.meta.url);
24
23
  const getDirname = () => path.dirname(getFilename());
25
24
  const __dirname = /* @__PURE__ */ getDirname();
@@ -45,11 +44,11 @@ const loadConfig = async (file) => {
45
44
  const resolveConfig = async (cwd) => {
46
45
  const configFile = findConfigFile(cwd);
47
46
  if (!configFile) return {
48
- configPath: "",
47
+ configFile: "",
49
48
  config: {}
50
49
  };
51
50
  return {
52
- configPath: configFile,
51
+ configFile,
53
52
  config: await loadConfig(configFile)
54
53
  };
55
54
  };
@@ -168,12 +167,12 @@ const gitCheck = async (ctx, config) => {
168
167
  ctx.noGitHub = true;
169
168
  return;
170
169
  }
171
- if (requireWorkDirClean && !await isWorkingDirClean()) throw new Error(MSG.ERROR.GIT_WORKDIR);
170
+ if (requireWorkDirClean && !await isWorkingTreeClean()) throw new Error(MSG.ERROR.GIT_WORKDIR);
172
171
  if (ignoreGithub) {
173
172
  ctx.noGitHub = true;
174
173
  return;
175
174
  }
176
- const { remoteName, remoteUrl } = await getRemote();
175
+ const { name: remoteName, url: remoteUrl } = (await getRemoteList())[0];
177
176
  if (!remoteUrl) if (requireRemote) throw new Error(MSG.ERROR.GIT_REMOTE(name));
178
177
  else {
179
178
  ctx.noGitHub = true;
@@ -194,18 +193,18 @@ const commitAndTag = async (ctx, config) => {
194
193
  const { git: { commit, tag, push, addUntrackedFiles, commitArgs, tagArgs, pushArgs } } = config;
195
194
  if (!commit) return;
196
195
  const args = dryRun ? ["--dry-run"] : [];
197
- addUntrackedFiles ? await gitAddAll() : await gitAddTracked(args);
198
- await gitCommit(commitMessage, [...commitArgs, ...args]);
196
+ addUntrackedFiles ? await gitAddAll(args) : await gitAddTracked(args);
197
+ await gitCommitMessage(commitMessage, [...commitArgs, ...args]);
199
198
  if (!dryRun) Object.assign(ctx.git, { isCommitted: true });
200
199
  if (tag) {
201
200
  await gitTagAnnotated(currentTag, tagMessage, [...tagArgs, ...args]);
202
201
  if (!dryRun) Object.assign(ctx.git, { isTagged: true });
203
202
  }
204
203
  if (push) {
205
- const remotes = await getAllRemotes();
204
+ const remotes = await getRemoteNames();
206
205
  for (const remoteName of remotes) {
207
- await pushTag(remoteName, currentTag, args);
208
- await pushBranch(remoteName, await getCurrentBranch(), [...pushArgs, ...args]);
206
+ await gitPushTag(remoteName, currentTag, args);
207
+ await gitPushBranch(remoteName, await gitBranchCurrent(), [...pushArgs, ...args]);
209
208
  }
210
209
  if (!dryRun) Object.assign(ctx.git, { isPushed: true });
211
210
  }
@@ -213,40 +212,8 @@ const commitAndTag = async (ctx, config) => {
213
212
  const gitRollback = (ctx) => {
214
213
  const { git: { currentTag, isCommitted, isTagged, isPushed } } = ctx;
215
214
  if (isPushed) return;
216
- spawnSync("git", ["restore", "."]);
217
- if (isTagged) spawnSync("git", [
218
- "tag",
219
- "--delete",
220
- currentTag
221
- ]);
222
- spawnSync("git", [
223
- "reset",
224
- "--hard",
225
- isCommitted ? "HEAD~1" : "HEAD"
226
- ]);
227
- };
228
- //#endregion
229
- //#region src/prompts.ts
230
- const abortTask = (msg) => {
231
- cancel(`${red("✕")} ${msg}`);
232
- process.exit(0);
233
- };
234
- const abortSinglePrompt = (value) => {
235
- if (isCancel(value)) abortTask(MSG.ABORT.CANCEL);
236
- };
237
- const abortGroupPrompt = (ctx) => {
238
- ctx && gitRollback(ctx);
239
- abortTask(MSG.ABORT.CANCEL);
240
- };
241
- const abortOnError = (err, ctx, exit = true) => {
242
- ctx && gitRollback(ctx);
243
- const msg = err.message.replace(/^\[(github|npm|git)]/, (a) => red(a));
244
- log.message(`\n${msg}\n`);
245
- exit && process.exit(1);
246
- };
247
- const taskEnd = (msg) => {
248
- outro(msg);
249
- process.exit(0);
215
+ if (isTagged) gitTagDeleteSync(currentTag);
216
+ gitResetHardSync(isCommitted ? 1 : 0);
250
217
  };
251
218
  //#endregion
252
219
  //#region src/utils.ts
@@ -301,6 +268,27 @@ const formatTemplate = async (ctx, config) => {
301
268
  });
302
269
  Object.assign(ctx.github, { releaseName });
303
270
  };
271
+ const abortTask = (msg) => {
272
+ cancel(`${red("✕")} ${msg}`);
273
+ process.exit(0);
274
+ };
275
+ const abortSinglePrompt = (value) => {
276
+ if (isCancel(value)) abortTask(MSG.ABORT.CANCEL);
277
+ };
278
+ const abortGroupPrompt = (ctx) => {
279
+ ctx && gitRollback(ctx);
280
+ abortTask(MSG.ABORT.CANCEL);
281
+ };
282
+ const abortOnError = (err, ctx, exit = true) => {
283
+ ctx && gitRollback(ctx);
284
+ const msg = err.message.replace(/^\[(github|npm|git)]/, (a) => red(a));
285
+ log.message(`\n${msg}\n`);
286
+ exit && process.exit(1);
287
+ };
288
+ const taskEnd = (msg) => {
289
+ outro(msg);
290
+ process.exit(0);
291
+ };
304
292
  //#endregion
305
293
  //#region src/version/prompts.ts
306
294
  const createVersionMap = (current) => ({
@@ -348,7 +336,7 @@ const runVersionPrompts = async (ctx, config) => {
348
336
  message: question(MSG.PROMPT.INPUT_VERSION, "version"),
349
337
  initialValue: current,
350
338
  validate: (val) => {
351
- if (!isValid(val)) return "Invalid version";
339
+ if (isUndefined(val) || !isValidVersion(val)) return "Invalid version";
352
340
  }
353
341
  });
354
342
  abortSinglePrompt(version);
@@ -591,8 +579,7 @@ const parsePreset = async () => {
591
579
  hidden: false
592
580
  })) });
593
581
  preset.writer ??= {};
594
- preset.writer.headerPartial = `
595
- ## {{#if isPatch~}} <small> {{~/if~}}
582
+ preset.writer.headerPartial = `## {{#if isPatch~}} <small> {{~/if~}}
596
583
  {{#if @root.linkCompare~}}
597
584
  [{{version}}](
598
585
  {{~#if @root.repository~}}
@@ -616,8 +603,7 @@ const parsePreset = async () => {
616
603
  {{~/if}}
617
604
  {{~#if isPatch~}} </small> {{~/if}}
618
605
  `.trim() + eol();
619
- preset.writer.mainTemplate = `
620
- {{> header}}
606
+ preset.writer.mainTemplate = `{{> header}}
621
607
  {{#if noteGroups}}
622
608
  {{#each noteGroups}}
623
609
 
@@ -653,7 +639,7 @@ const getChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
653
639
  });
654
640
  let changelog = "";
655
641
  for await (const chunk of generator.write()) changelog += chunk;
656
- return changelog;
642
+ return changelog.trimEnd();
657
643
  };
658
644
  const generateChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
659
645
  const infile = join(getPkgDir(), "CHANGELOG.md");
@@ -932,18 +918,6 @@ const runNpmOptPrompts = async (ctx, config) => {
932
918
  };
933
919
  //#endregion
934
920
  //#region src/npm/publish.ts
935
- const canPublish = async (registry) => {
936
- const res = await runNpm([
937
- "publish",
938
- "--dry-run",
939
- "--no-git-checks",
940
- "--access",
941
- "public",
942
- ...registryArg(registry)
943
- ], { error: "throw" }).catch((err) => err);
944
- if (!(res instanceof Error)) return true;
945
- return [/previously published versions/i, /cannot publish over/i].some((reg) => reg.test(res.message));
946
- };
947
921
  const npmCheck = async (ctx, config) => {
948
922
  const { pkg: { name, current, publishConfig: { registry } } } = ctx;
949
923
  const { npm: { skipChecks } } = config;
@@ -1009,10 +983,10 @@ var Action = class {
1009
983
  const { otp, package: defPkg, ...others } = options;
1010
984
  const { showChangelog, showRelease, ci, dryRun } = Object.fromEntries(Object.entries(others).map(([k, v]) => [k, Boolean(v)]));
1011
985
  process.env["dryRun"] = String(dryRun);
1012
- const { configPath, config: local } = await resolveConfig(process.cwd());
986
+ const { configFile, config: local } = await resolveConfig(process.cwd());
1013
987
  const config = mergeConfig(createDefaultConfig(ci ? true : void 0), local);
1014
988
  info(MSG.INFO.TOOL(cName, cVersion));
1015
- info(MSG.INFO.CONFIG(configPath));
989
+ info(MSG.INFO.CONFIG(configFile));
1016
990
  console.log();
1017
991
  intro(prepare ? MSG.INTRO_PREPARE(dryRun) : MSG.INTRO(dryRun));
1018
992
  const { isMonorepo, packages, getPkgDir, ignoreNpm } = config;
@@ -1142,7 +1116,7 @@ var Action = class {
1142
1116
  from: "",
1143
1117
  to: "HEAD"
1144
1118
  } : await resolveChangelogRange(isIncrement, match);
1145
- const commits = await getLog(from, to, getPkgDir(selectedPkg));
1119
+ const commits = await getLogSince(from, to, getPkgDir(selectedPkg));
1146
1120
  const changelog = await getChangelog({
1147
1121
  getPkgDir: () => getPkgDir(selectedPkg),
1148
1122
  tagPrefix: tagPrefix?.(selectedPkg),
@@ -1150,7 +1124,7 @@ var Action = class {
1150
1124
  });
1151
1125
  Object.assign(ctx.github, { changelog });
1152
1126
  if (commits) {
1153
- msg("GIT", `Changelog(${from}...${to}):${eol(2)}` + changelog.trimEnd());
1127
+ msg("GIT", `Changelog(${from}...${to}):${eol(2)}` + changelog);
1154
1128
  msg("GIT", `Commits(${from}...${to}):${eol(2)}` + commits);
1155
1129
  if (showChangelog) taskEnd(MSG.LOG.SHOW_CHANGELOG);
1156
1130
  } else msg("GIT", MSG.LOG.CHANGELOG_EMPTY);
@@ -1172,8 +1146,8 @@ var Action = class {
1172
1146
  },
1173
1147
  enabled: isIncrement
1174
1148
  }]).catch((err) => abortOnError(err, ctx));
1175
- const changeset = await getStatus();
1176
- if (changeset) msg("GIT", `Changes:${eol(2)}` + coloredChangeset(changeset));
1149
+ const changeset = await getShortStatus();
1150
+ if (changeset) msg("GIT", `Changes:${eol(2)}` + coloredStatus(changeset));
1177
1151
  else msg("GIT", MSG.LOG.CHANGES_EMPTY);
1178
1152
  }
1179
1153
  async gitTask(ctx, config) {
@@ -1248,8 +1222,8 @@ program.command("init").description("Create a release configuration file").optio
1248
1222
  const isESM = type === "module";
1249
1223
  const isTS = existsSync(join(cwd, "tsconfig.json"));
1250
1224
  const infile = `release.config.${isESM ? "" : "m"}${isTS ? "ts" : "js"}`;
1251
- const configPath = join(cwd, infile);
1252
- if (existsSync(configPath) && !force) {
1225
+ const configFile = join(cwd, infile);
1226
+ if (existsSync(configFile) && !force) {
1253
1227
  console.error(`${red`Error:`} ${yellow(infile)} already exists.\nUse ${green`--force`} to overwrite.`);
1254
1228
  process.exit(1);
1255
1229
  }
@@ -1262,7 +1236,7 @@ program.command("init").description("Create a release configuration file").optio
1262
1236
  tagPrefix: (pkg) => \`\${ pkg }@\`,
1263
1237
  },
1264
1238
  }`;
1265
- writeFileSync(configPath, [`import { defineConfig } from '@peiyanlu/release'`, `export default defineConfig(${monorepo ? monoConfigToString() : "{}"})`].join(eol(2)), "utf-8");
1239
+ writeFileSync(configFile, [`import { defineConfig } from '@peiyanlu/release'`, `export default defineConfig(${monorepo ? monoConfigToString() : "{}"})`].join(eol(2)), "utf-8");
1266
1240
  console.log(`${green`✔`} ${infile} created successfully`);
1267
1241
  });
1268
1242
  program.parse(process.argv);
package/dist/index.mjs CHANGED
@@ -132,8 +132,7 @@ const parsePreset = async () => {
132
132
  hidden: false
133
133
  })) });
134
134
  preset.writer ??= {};
135
- preset.writer.headerPartial = `
136
- ## {{#if isPatch~}} <small> {{~/if~}}
135
+ preset.writer.headerPartial = `## {{#if isPatch~}} <small> {{~/if~}}
137
136
  {{#if @root.linkCompare~}}
138
137
  [{{version}}](
139
138
  {{~#if @root.repository~}}
@@ -157,8 +156,7 @@ const parsePreset = async () => {
157
156
  {{~/if}}
158
157
  {{~#if isPatch~}} </small> {{~/if}}
159
158
  `.trim() + eol();
160
- preset.writer.mainTemplate = `
161
- {{> header}}
159
+ preset.writer.mainTemplate = `{{> header}}
162
160
  {{#if noteGroups}}
163
161
  {{#each noteGroups}}
164
162
 
@@ -194,7 +192,7 @@ const getChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
194
192
  });
195
193
  let changelog = "";
196
194
  for await (const chunk of generator.write()) changelog += chunk;
197
- return changelog;
195
+ return changelog.trimEnd();
198
196
  };
199
197
  const generateChangelog = async ({ getPkgDir, tagPrefix, releaseCount = 1 }) => {
200
198
  const infile = join(getPkgDir(), "CHANGELOG.md");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peiyanlu/release",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Release project tool.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -30,16 +30,17 @@
30
30
  "@actions/github": "^9.1.1",
31
31
  "@clack/prompts": "^1.5.0",
32
32
  "@octokit/rest": "^22.0.1",
33
- "@peiyanlu/cli-utils": "^0.0.9",
33
+ "@peiyanlu/cli-utils": "^0.0.12",
34
34
  "@peiyanlu/ts-utils": "^0.0.7",
35
35
  "ansis": "^4.3.1",
36
36
  "commander": "^15.0.0",
37
- "conventional-changelog": "^7.2.0",
37
+ "conventional-changelog": "^7.2.1",
38
38
  "conventional-changelog-conventionalcommits": "^9.3.1",
39
+ "conventional-changelog-writer": "^8.3.0",
39
40
  "mime-types": "^3.0.2",
40
41
  "open": "^11.0.0",
41
42
  "publint": "^0.3.21",
42
- "semver": "^7.8.1",
43
+ "semver": "^7.8.5",
43
44
  "tinyglobby": "^0.2.17"
44
45
  },
45
46
  "devDependencies": {
@@ -47,9 +48,9 @@
47
48
  "@types/node": "^24.12.4",
48
49
  "@types/semver": "^7.7.1",
49
50
  "@vitest/coverage-v8": "^4.1.8",
50
- "tsdown": "^0.22.1",
51
+ "tsdown": "^0.22.3",
51
52
  "typescript": "^6.0.3",
52
- "vitest": "^4.1.8"
53
+ "vitest": "^4.1.9"
53
54
  },
54
55
  "author": {
55
56
  "name": "YanluPei",