@peiyanlu/cli-utils 0.0.5 → 0.0.6

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/index.cjs CHANGED
@@ -414,7 +414,7 @@ const getAllRemotes = async () => {
414
414
  };
415
415
  /** 获取默认的远程地址 */
416
416
  const getDefaultRemote = async (branch) => {
417
- const targetBranch = branch ?? await getCurrentBranch();
417
+ const targetBranch = branch || await getCurrentBranch();
418
418
  return targetBranch ? await getRemoteForBranch(targetBranch) : void 0;
419
419
  };
420
420
  /** 获取默认远程地址之外的远程地址 */
@@ -432,29 +432,36 @@ const fetchAllBranch = (remoteName = "origin") => {
432
432
  ]);
433
433
  };
434
434
  /**
435
- * 获取本地所有 tag(不区分远程)
435
+ * 获取本地所有 tag
436
436
  * @returns {Promise<string[]>}
437
- * @defaults git tag
437
+ * @defaults git tag --list
438
438
  */
439
- const getTags = async () => {
440
- const tags = await runGit(["tag"]);
441
- return tags ? tags.split("\n").sort() : [];
439
+ const getLocalTags = async () => {
440
+ const tags = await runGit(["tag", "--list"]);
441
+ return tags ? tags.split("\n").filter(Boolean) : [];
442
+ };
443
+ /** 获取远程 tags */
444
+ const getSortedTags = async (match = "*", exclude = "*-beta.*", sort = "v:refname", count = 0) => {
445
+ const res = await runGit([
446
+ "for-each-ref",
447
+ "--format=%(refname:short)",
448
+ `--sort=-${sort}`,
449
+ `--exclude=${exclude}`,
450
+ `--count=${count}`,
451
+ `refs/tags/${match}`
452
+ ]);
453
+ return res ? res.split("\n").filter(Boolean) : [];
442
454
  };
443
455
  /**
444
456
  * 获取远程(或所有 refs)中的 tag
445
457
  * 使用 for-each-ref 以支持版本号排序
446
458
  * @param {string} match 默认 *
459
+ * @param {string} exclude 默认 beta
447
460
  * @returns {Promise<string[]>}
448
461
  * @defaults git for-each-ref --sort=-v:refname --format=%(refname:short) refs/tags/<match>
449
462
  */
450
- const getRemoteTags = async (match = "*") => {
451
- const tags = await runGit([
452
- "for-each-ref",
453
- "--sort=-v:refname",
454
- "--format=%(refname:short)",
455
- `refs/tags/${match}`
456
- ]);
457
- return tags ? tags.split("\n").sort() : [];
463
+ const getRemoteTags = async (match = "*", exclude = "*-beta.*") => {
464
+ return getSortedTags(match, exclude);
458
465
  };
459
466
  /**
460
467
  * 获取当前工作区状态(不包含未跟踪文件)
@@ -514,7 +521,7 @@ const getRemote = async () => {
514
521
  };
515
522
  };
516
523
  /**
517
- * 获取最新 tag(基于 git describe)
524
+ * 获取最新 tag
518
525
  *
519
526
  * 默认:
520
527
  * - 匹配所有 tag
@@ -522,73 +529,40 @@ const getRemote = async () => {
522
529
  * @param {string} match 默认 *
523
530
  * @param {string} exclude 默认 beta
524
531
  * @returns {Promise<string | undefined>}
525
- * @defaults git describe --tags --abbrev=0 --match=<match> --exclude=<exclude>
526
532
  */
527
533
  const getLatestTag = async (match = "*", exclude = "*-beta.*") => {
528
- return runGit([
529
- "describe",
530
- "--tags",
531
- "--abbrev=0",
532
- `--match=${match}`,
533
- `--exclude=${exclude}`
534
- ]);
535
- };
536
- /**
537
- * 从所有 refs 中获取最新 tag
538
- * 适用于 git describe 不可靠的场景(如 tag 不在当前分支)
539
- * @param {string} match
540
- * @returns {Promise<string | undefined>}
541
- * @defaults git -c versionsort.suffix=- for-each-ref --count=1 --sort=-v:refname --format=%(refname:short) refs/tags/<match>
542
- */
543
- const getLatestTagFromAllRefs = async (match = "*") => {
544
- return runGit([
545
- "-c",
546
- "versionsort.suffix=-",
547
- "for-each-ref",
548
- "--count=1",
549
- "--sort=-v:refname",
550
- "--format=%(refname:short)",
551
- `refs/tags/${match}`
552
- ]);
534
+ const [latestTag] = await getSortedTags(match, exclude, void 0, 1);
535
+ return latestTag;
553
536
  };
554
537
  /**
555
538
  * 获取上一个 tag
556
- * @param {string} current
557
- * @returns {Promise<string | undefined>}
558
- */
559
- const getPreviousTag = async (current) => {
560
- return runGit([
561
- "describe",
562
- "--tags",
563
- "--abbrev=0",
564
- `${await runGit([
565
- "rev-list",
566
- "--tags",
567
- current ?? "--skip=1",
568
- "--max-count=1"
569
- ])}^`
570
- ]);
571
- };
572
- /**
573
- * 将短 hash 解析为完整 hash
574
- * @param {string} short
539
+ *
540
+ * 默认:
541
+ * - 匹配所有 tag
542
+ * - 排除 beta 版本
543
+ * @param {string} latestTag
544
+ * @param {string} match 默认 *
545
+ * @param {string} exclude 默认 beta
575
546
  * @returns {Promise<string | undefined>}
576
547
  */
577
- const getFullHash = (short) => {
578
- return runGit(["rev-parse", short]);
548
+ const getPreviousTag = async (latestTag, match = "*", exclude = "*-beta.*") => {
549
+ const all = await getSortedTags(match, exclude, void 0, 2);
550
+ return all[all.findIndex((k) => latestTag === k) + 1];
579
551
  };
580
552
  /**
581
553
  * 计算 changelog 的 commit 范围
582
554
  * @param {boolean} isIncrement 是否为版本递增发布
583
- * @returns {Promise<{from: string, to: string} | {from: string, to: string} | {from: string, to: string}>}
555
+ * @param {string} match tag match
556
+ * @param {string} exclude tag exclude
557
+ * @returns {Promise<{from: string, to: string}>}
584
558
  */
585
- const resolveChangelogRange = async (isIncrement = true) => {
586
- const latestTag = await getLatestTag();
587
- const previousTag = await getPreviousTag(latestTag);
559
+ const resolveChangelogRange = async (isIncrement = true, match = "*", exclude = "*-beta.*") => {
560
+ const latestTag = await getLatestTag(match, exclude);
588
561
  if (!latestTag) return {
589
562
  from: "",
590
563
  to: "HEAD"
591
564
  };
565
+ const previousTag = await getPreviousTag(latestTag);
592
566
  if (!isIncrement && previousTag) return {
593
567
  from: previousTag,
594
568
  to: `${latestTag}^1`
@@ -599,6 +573,14 @@ const resolveChangelogRange = async (isIncrement = true) => {
599
573
  };
600
574
  };
601
575
  /**
576
+ * 将短 hash 解析为完整 hash
577
+ * @param {string} short
578
+ * @returns {Promise<string | undefined>}
579
+ */
580
+ const getFullHash = (short) => {
581
+ return runGit(["rev-parse", short]);
582
+ };
583
+ /**
602
584
  * 获取指定范围内的 commit 日志
603
585
  * @param {string} from
604
586
  * @param {string} to
@@ -634,7 +616,7 @@ const hasUpstreamBranch = async () => {
634
616
  /** 获取 push 所需的 upstream 参数 */
635
617
  const getUpstreamArgs = async (remoteName, branch) => {
636
618
  const hasUpstream = await hasUpstreamBranch();
637
- const target = branch ?? await getCurrentBranch();
619
+ const target = branch || await getCurrentBranch();
638
620
  if (!hasUpstream) return [
639
621
  "--set-upstream",
640
622
  remoteName,
@@ -1015,7 +997,7 @@ const getRegistry = async (pkgDir) => {
1015
997
  const getAccess = async (pkgDir) => {
1016
998
  const { name, publishConfig = {} } = readJsonFile((0, node_path.join)(pkgDir, "package.json"));
1017
999
  const { access } = publishConfig;
1018
- return access ?? (name.startsWith("@") ? "restricted" : "public");
1000
+ return access || (name.startsWith("@") ? "restricted" : "public");
1019
1001
  };
1020
1002
  /**
1021
1003
  * 检查与仓库的连接
@@ -1167,7 +1149,7 @@ exports.getGitRemoteUrl = getGitRemoteUrl;
1167
1149
  exports.getGithubReleaseUrl = getGithubReleaseUrl;
1168
1150
  exports.getGithubUrl = getGithubUrl;
1169
1151
  exports.getLatestTag = getLatestTag;
1170
- exports.getLatestTagFromAllRefs = getLatestTagFromAllRefs;
1152
+ exports.getLocalTags = getLocalTags;
1171
1153
  exports.getLog = getLog;
1172
1154
  exports.getOtherRemotes = getOtherRemotes;
1173
1155
  exports.getPackageInfo = getPackageInfo;
@@ -1178,8 +1160,8 @@ exports.getRegistry = getRegistry;
1178
1160
  exports.getRemote = getRemote;
1179
1161
  exports.getRemoteForBranch = getRemoteForBranch;
1180
1162
  exports.getRemoteTags = getRemoteTags;
1163
+ exports.getSortedTags = getSortedTags;
1181
1164
  exports.getStatus = getStatus;
1182
- exports.getTags = getTags;
1183
1165
  exports.getUpstreamArgs = getUpstreamArgs;
1184
1166
  exports.gitAddAll = gitAddAll;
1185
1167
  exports.gitAddTracked = gitAddTracked;
package/dist/index.d.cts CHANGED
@@ -155,19 +155,22 @@ declare const getOtherRemotes: (branch?: string) => Promise<string[]>;
155
155
  /** 提取所有分支 */
156
156
  declare const fetchAllBranch: (remoteName?: string) => Promise<string | undefined>;
157
157
  /**
158
- * 获取本地所有 tag(不区分远程)
158
+ * 获取本地所有 tag
159
159
  * @returns {Promise<string[]>}
160
- * @defaults git tag
160
+ * @defaults git tag --list
161
161
  */
162
- declare const getTags: () => Promise<string[]>;
162
+ declare const getLocalTags: () => Promise<string[]>;
163
+ /** 获取远程 tags */
164
+ declare const getSortedTags: (match?: string, exclude?: string, sort?: "v:refname" | "creatordate", count?: number) => Promise<string[]>;
163
165
  /**
164
166
  * 获取远程(或所有 refs)中的 tag
165
167
  * 使用 for-each-ref 以支持版本号排序
166
168
  * @param {string} match 默认 *
169
+ * @param {string} exclude 默认 beta
167
170
  * @returns {Promise<string[]>}
168
171
  * @defaults git for-each-ref --sort=-v:refname --format=%(refname:short) refs/tags/<match>
169
172
  */
170
- declare const getRemoteTags: (match?: string) => Promise<string[]>;
173
+ declare const getRemoteTags: (match?: string, exclude?: string) => Promise<string[]>;
171
174
  /**
172
175
  * 获取当前工作区状态(不包含未跟踪文件)
173
176
  * @returns {Promise<string | undefined>}
@@ -193,7 +196,7 @@ declare const getRemote: () => Promise<{
193
196
  remoteUrl: string | undefined;
194
197
  }>;
195
198
  /**
196
- * 获取最新 tag(基于 git describe)
199
+ * 获取最新 tag
197
200
  *
198
201
  * 默认:
199
202
  * - 匹配所有 tag
@@ -201,38 +204,37 @@ declare const getRemote: () => Promise<{
201
204
  * @param {string} match 默认 *
202
205
  * @param {string} exclude 默认 beta
203
206
  * @returns {Promise<string | undefined>}
204
- * @defaults git describe --tags --abbrev=0 --match=<match> --exclude=<exclude>
205
207
  */
206
208
  declare const getLatestTag: (match?: string, exclude?: string) => Promise<string | undefined>;
207
- /**
208
- * 从所有 refs 中获取最新 tag
209
- * 适用于 git describe 不可靠的场景(如 tag 不在当前分支)
210
- * @param {string} match
211
- * @returns {Promise<string | undefined>}
212
- * @defaults git -c versionsort.suffix=- for-each-ref --count=1 --sort=-v:refname --format=%(refname:short) refs/tags/<match>
213
- */
214
- declare const getLatestTagFromAllRefs: (match?: string) => Promise<string | undefined>;
215
209
  /**
216
210
  * 获取上一个 tag
217
- * @param {string} current
218
- * @returns {Promise<string | undefined>}
219
- */
220
- declare const getPreviousTag: (current?: string) => Promise<string | undefined>;
221
- /**
222
- * 将短 hash 解析为完整 hash
223
- * @param {string} short
211
+ *
212
+ * 默认:
213
+ * - 匹配所有 tag
214
+ * - 排除 beta 版本
215
+ * @param {string} latestTag
216
+ * @param {string} match 默认 *
217
+ * @param {string} exclude 默认 beta
224
218
  * @returns {Promise<string | undefined>}
225
219
  */
226
- declare const getFullHash: (short: string) => Promise<string | undefined>;
220
+ declare const getPreviousTag: (latestTag: string, match?: string, exclude?: string) => Promise<string | undefined>;
227
221
  /**
228
222
  * 计算 changelog 的 commit 范围
229
223
  * @param {boolean} isIncrement 是否为版本递增发布
230
- * @returns {Promise<{from: string, to: string} | {from: string, to: string} | {from: string, to: string}>}
224
+ * @param {string} match tag match
225
+ * @param {string} exclude tag exclude
226
+ * @returns {Promise<{from: string, to: string}>}
231
227
  */
232
- declare const resolveChangelogRange: (isIncrement?: boolean) => Promise<{
228
+ declare const resolveChangelogRange: (isIncrement?: boolean, match?: string, exclude?: string) => Promise<{
233
229
  from: string;
234
230
  to: string;
235
231
  }>;
232
+ /**
233
+ * 将短 hash 解析为完整 hash
234
+ * @param {string} short
235
+ * @returns {Promise<string | undefined>}
236
+ */
237
+ declare const getFullHash: (short: string) => Promise<string | undefined>;
236
238
  /**
237
239
  * 获取指定范围内的 commit 日志
238
240
  * @param {string} from
@@ -283,7 +285,7 @@ declare const pushTag: (remoteName: string, tag: string, args?: string[]) => Pro
283
285
  * @param {string[]} args
284
286
  * @returns {Promise<string | undefined>}
285
287
  */
286
- declare const pushBranch: (remoteName: string, branch: string, args?: string[]) => Promise<void>;
288
+ declare const pushBranch: (remoteName: string, branch?: string, args?: string[]) => Promise<void>;
287
289
  /**
288
290
  * 撤销【工作区】中某个文件的修改(未暂存的改动)
289
291
  * - 不影响暂存区
@@ -520,4 +522,4 @@ declare const publishPackage: (options?: {
520
522
  cwd?: string;
521
523
  }) => Promise<string | undefined>;
522
524
  //#endregion
523
- export { CliOptions, ConfirmResult, CopyOptions, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, ExecAsyncWithStringOptions, ExecResultOptions, ExecSyncWithStringOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncWithStringOptions, SpawnSyncWithStringOptions, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLatestTagFromAllRefs, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getStatus, getTags, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
525
+ export { CliOptions, ConfirmResult, CopyOptions, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, ExecAsyncWithStringOptions, ExecResultOptions, ExecSyncWithStringOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncWithStringOptions, SpawnSyncWithStringOptions, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLocalTags, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getSortedTags, getStatus, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
package/dist/index.d.mts CHANGED
@@ -155,19 +155,22 @@ declare const getOtherRemotes: (branch?: string) => Promise<string[]>;
155
155
  /** 提取所有分支 */
156
156
  declare const fetchAllBranch: (remoteName?: string) => Promise<string | undefined>;
157
157
  /**
158
- * 获取本地所有 tag(不区分远程)
158
+ * 获取本地所有 tag
159
159
  * @returns {Promise<string[]>}
160
- * @defaults git tag
160
+ * @defaults git tag --list
161
161
  */
162
- declare const getTags: () => Promise<string[]>;
162
+ declare const getLocalTags: () => Promise<string[]>;
163
+ /** 获取远程 tags */
164
+ declare const getSortedTags: (match?: string, exclude?: string, sort?: "v:refname" | "creatordate", count?: number) => Promise<string[]>;
163
165
  /**
164
166
  * 获取远程(或所有 refs)中的 tag
165
167
  * 使用 for-each-ref 以支持版本号排序
166
168
  * @param {string} match 默认 *
169
+ * @param {string} exclude 默认 beta
167
170
  * @returns {Promise<string[]>}
168
171
  * @defaults git for-each-ref --sort=-v:refname --format=%(refname:short) refs/tags/<match>
169
172
  */
170
- declare const getRemoteTags: (match?: string) => Promise<string[]>;
173
+ declare const getRemoteTags: (match?: string, exclude?: string) => Promise<string[]>;
171
174
  /**
172
175
  * 获取当前工作区状态(不包含未跟踪文件)
173
176
  * @returns {Promise<string | undefined>}
@@ -193,7 +196,7 @@ declare const getRemote: () => Promise<{
193
196
  remoteUrl: string | undefined;
194
197
  }>;
195
198
  /**
196
- * 获取最新 tag(基于 git describe)
199
+ * 获取最新 tag
197
200
  *
198
201
  * 默认:
199
202
  * - 匹配所有 tag
@@ -201,38 +204,37 @@ declare const getRemote: () => Promise<{
201
204
  * @param {string} match 默认 *
202
205
  * @param {string} exclude 默认 beta
203
206
  * @returns {Promise<string | undefined>}
204
- * @defaults git describe --tags --abbrev=0 --match=<match> --exclude=<exclude>
205
207
  */
206
208
  declare const getLatestTag: (match?: string, exclude?: string) => Promise<string | undefined>;
207
- /**
208
- * 从所有 refs 中获取最新 tag
209
- * 适用于 git describe 不可靠的场景(如 tag 不在当前分支)
210
- * @param {string} match
211
- * @returns {Promise<string | undefined>}
212
- * @defaults git -c versionsort.suffix=- for-each-ref --count=1 --sort=-v:refname --format=%(refname:short) refs/tags/<match>
213
- */
214
- declare const getLatestTagFromAllRefs: (match?: string) => Promise<string | undefined>;
215
209
  /**
216
210
  * 获取上一个 tag
217
- * @param {string} current
218
- * @returns {Promise<string | undefined>}
219
- */
220
- declare const getPreviousTag: (current?: string) => Promise<string | undefined>;
221
- /**
222
- * 将短 hash 解析为完整 hash
223
- * @param {string} short
211
+ *
212
+ * 默认:
213
+ * - 匹配所有 tag
214
+ * - 排除 beta 版本
215
+ * @param {string} latestTag
216
+ * @param {string} match 默认 *
217
+ * @param {string} exclude 默认 beta
224
218
  * @returns {Promise<string | undefined>}
225
219
  */
226
- declare const getFullHash: (short: string) => Promise<string | undefined>;
220
+ declare const getPreviousTag: (latestTag: string, match?: string, exclude?: string) => Promise<string | undefined>;
227
221
  /**
228
222
  * 计算 changelog 的 commit 范围
229
223
  * @param {boolean} isIncrement 是否为版本递增发布
230
- * @returns {Promise<{from: string, to: string} | {from: string, to: string} | {from: string, to: string}>}
224
+ * @param {string} match tag match
225
+ * @param {string} exclude tag exclude
226
+ * @returns {Promise<{from: string, to: string}>}
231
227
  */
232
- declare const resolveChangelogRange: (isIncrement?: boolean) => Promise<{
228
+ declare const resolveChangelogRange: (isIncrement?: boolean, match?: string, exclude?: string) => Promise<{
233
229
  from: string;
234
230
  to: string;
235
231
  }>;
232
+ /**
233
+ * 将短 hash 解析为完整 hash
234
+ * @param {string} short
235
+ * @returns {Promise<string | undefined>}
236
+ */
237
+ declare const getFullHash: (short: string) => Promise<string | undefined>;
236
238
  /**
237
239
  * 获取指定范围内的 commit 日志
238
240
  * @param {string} from
@@ -283,7 +285,7 @@ declare const pushTag: (remoteName: string, tag: string, args?: string[]) => Pro
283
285
  * @param {string[]} args
284
286
  * @returns {Promise<string | undefined>}
285
287
  */
286
- declare const pushBranch: (remoteName: string, branch: string, args?: string[]) => Promise<void>;
288
+ declare const pushBranch: (remoteName: string, branch?: string, args?: string[]) => Promise<void>;
287
289
  /**
288
290
  * 撤销【工作区】中某个文件的修改(未暂存的改动)
289
291
  * - 不影响暂存区
@@ -520,4 +522,4 @@ declare const publishPackage: (options?: {
520
522
  cwd?: string;
521
523
  }) => Promise<string | undefined>;
522
524
  //#endregion
523
- export { CliOptions, ConfirmResult, CopyOptions, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, ExecAsyncWithStringOptions, ExecResultOptions, ExecSyncWithStringOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncWithStringOptions, SpawnSyncWithStringOptions, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLatestTagFromAllRefs, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getStatus, getTags, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
525
+ export { CliOptions, ConfirmResult, CopyOptions, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, ExecAsyncWithStringOptions, ExecResultOptions, ExecSyncWithStringOptions, HttpLibrary, PkgInfo, PkgManager, SpawnAsyncWithStringOptions, SpawnSyncWithStringOptions, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLocalTags, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getSortedTags, getStatus, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
package/dist/index.mjs CHANGED
@@ -414,7 +414,7 @@ const getAllRemotes = async () => {
414
414
  };
415
415
  /** 获取默认的远程地址 */
416
416
  const getDefaultRemote = async (branch) => {
417
- const targetBranch = branch ?? await getCurrentBranch();
417
+ const targetBranch = branch || await getCurrentBranch();
418
418
  return targetBranch ? await getRemoteForBranch(targetBranch) : void 0;
419
419
  };
420
420
  /** 获取默认远程地址之外的远程地址 */
@@ -432,29 +432,36 @@ const fetchAllBranch = (remoteName = "origin") => {
432
432
  ]);
433
433
  };
434
434
  /**
435
- * 获取本地所有 tag(不区分远程)
435
+ * 获取本地所有 tag
436
436
  * @returns {Promise<string[]>}
437
- * @defaults git tag
437
+ * @defaults git tag --list
438
438
  */
439
- const getTags = async () => {
440
- const tags = await runGit(["tag"]);
441
- return tags ? tags.split("\n").sort() : [];
439
+ const getLocalTags = async () => {
440
+ const tags = await runGit(["tag", "--list"]);
441
+ return tags ? tags.split("\n").filter(Boolean) : [];
442
+ };
443
+ /** 获取远程 tags */
444
+ const getSortedTags = async (match = "*", exclude = "*-beta.*", sort = "v:refname", count = 0) => {
445
+ const res = await runGit([
446
+ "for-each-ref",
447
+ "--format=%(refname:short)",
448
+ `--sort=-${sort}`,
449
+ `--exclude=${exclude}`,
450
+ `--count=${count}`,
451
+ `refs/tags/${match}`
452
+ ]);
453
+ return res ? res.split("\n").filter(Boolean) : [];
442
454
  };
443
455
  /**
444
456
  * 获取远程(或所有 refs)中的 tag
445
457
  * 使用 for-each-ref 以支持版本号排序
446
458
  * @param {string} match 默认 *
459
+ * @param {string} exclude 默认 beta
447
460
  * @returns {Promise<string[]>}
448
461
  * @defaults git for-each-ref --sort=-v:refname --format=%(refname:short) refs/tags/<match>
449
462
  */
450
- const getRemoteTags = async (match = "*") => {
451
- const tags = await runGit([
452
- "for-each-ref",
453
- "--sort=-v:refname",
454
- "--format=%(refname:short)",
455
- `refs/tags/${match}`
456
- ]);
457
- return tags ? tags.split("\n").sort() : [];
463
+ const getRemoteTags = async (match = "*", exclude = "*-beta.*") => {
464
+ return getSortedTags(match, exclude);
458
465
  };
459
466
  /**
460
467
  * 获取当前工作区状态(不包含未跟踪文件)
@@ -514,7 +521,7 @@ const getRemote = async () => {
514
521
  };
515
522
  };
516
523
  /**
517
- * 获取最新 tag(基于 git describe)
524
+ * 获取最新 tag
518
525
  *
519
526
  * 默认:
520
527
  * - 匹配所有 tag
@@ -522,73 +529,40 @@ const getRemote = async () => {
522
529
  * @param {string} match 默认 *
523
530
  * @param {string} exclude 默认 beta
524
531
  * @returns {Promise<string | undefined>}
525
- * @defaults git describe --tags --abbrev=0 --match=<match> --exclude=<exclude>
526
532
  */
527
533
  const getLatestTag = async (match = "*", exclude = "*-beta.*") => {
528
- return runGit([
529
- "describe",
530
- "--tags",
531
- "--abbrev=0",
532
- `--match=${match}`,
533
- `--exclude=${exclude}`
534
- ]);
535
- };
536
- /**
537
- * 从所有 refs 中获取最新 tag
538
- * 适用于 git describe 不可靠的场景(如 tag 不在当前分支)
539
- * @param {string} match
540
- * @returns {Promise<string | undefined>}
541
- * @defaults git -c versionsort.suffix=- for-each-ref --count=1 --sort=-v:refname --format=%(refname:short) refs/tags/<match>
542
- */
543
- const getLatestTagFromAllRefs = async (match = "*") => {
544
- return runGit([
545
- "-c",
546
- "versionsort.suffix=-",
547
- "for-each-ref",
548
- "--count=1",
549
- "--sort=-v:refname",
550
- "--format=%(refname:short)",
551
- `refs/tags/${match}`
552
- ]);
534
+ const [latestTag] = await getSortedTags(match, exclude, void 0, 1);
535
+ return latestTag;
553
536
  };
554
537
  /**
555
538
  * 获取上一个 tag
556
- * @param {string} current
557
- * @returns {Promise<string | undefined>}
558
- */
559
- const getPreviousTag = async (current) => {
560
- return runGit([
561
- "describe",
562
- "--tags",
563
- "--abbrev=0",
564
- `${await runGit([
565
- "rev-list",
566
- "--tags",
567
- current ?? "--skip=1",
568
- "--max-count=1"
569
- ])}^`
570
- ]);
571
- };
572
- /**
573
- * 将短 hash 解析为完整 hash
574
- * @param {string} short
539
+ *
540
+ * 默认:
541
+ * - 匹配所有 tag
542
+ * - 排除 beta 版本
543
+ * @param {string} latestTag
544
+ * @param {string} match 默认 *
545
+ * @param {string} exclude 默认 beta
575
546
  * @returns {Promise<string | undefined>}
576
547
  */
577
- const getFullHash = (short) => {
578
- return runGit(["rev-parse", short]);
548
+ const getPreviousTag = async (latestTag, match = "*", exclude = "*-beta.*") => {
549
+ const all = await getSortedTags(match, exclude, void 0, 2);
550
+ return all[all.findIndex((k) => latestTag === k) + 1];
579
551
  };
580
552
  /**
581
553
  * 计算 changelog 的 commit 范围
582
554
  * @param {boolean} isIncrement 是否为版本递增发布
583
- * @returns {Promise<{from: string, to: string} | {from: string, to: string} | {from: string, to: string}>}
555
+ * @param {string} match tag match
556
+ * @param {string} exclude tag exclude
557
+ * @returns {Promise<{from: string, to: string}>}
584
558
  */
585
- const resolveChangelogRange = async (isIncrement = true) => {
586
- const latestTag = await getLatestTag();
587
- const previousTag = await getPreviousTag(latestTag);
559
+ const resolveChangelogRange = async (isIncrement = true, match = "*", exclude = "*-beta.*") => {
560
+ const latestTag = await getLatestTag(match, exclude);
588
561
  if (!latestTag) return {
589
562
  from: "",
590
563
  to: "HEAD"
591
564
  };
565
+ const previousTag = await getPreviousTag(latestTag);
592
566
  if (!isIncrement && previousTag) return {
593
567
  from: previousTag,
594
568
  to: `${latestTag}^1`
@@ -599,6 +573,14 @@ const resolveChangelogRange = async (isIncrement = true) => {
599
573
  };
600
574
  };
601
575
  /**
576
+ * 将短 hash 解析为完整 hash
577
+ * @param {string} short
578
+ * @returns {Promise<string | undefined>}
579
+ */
580
+ const getFullHash = (short) => {
581
+ return runGit(["rev-parse", short]);
582
+ };
583
+ /**
602
584
  * 获取指定范围内的 commit 日志
603
585
  * @param {string} from
604
586
  * @param {string} to
@@ -634,7 +616,7 @@ const hasUpstreamBranch = async () => {
634
616
  /** 获取 push 所需的 upstream 参数 */
635
617
  const getUpstreamArgs = async (remoteName, branch) => {
636
618
  const hasUpstream = await hasUpstreamBranch();
637
- const target = branch ?? await getCurrentBranch();
619
+ const target = branch || await getCurrentBranch();
638
620
  if (!hasUpstream) return [
639
621
  "--set-upstream",
640
622
  remoteName,
@@ -1015,7 +997,7 @@ const getRegistry = async (pkgDir) => {
1015
997
  const getAccess = async (pkgDir) => {
1016
998
  const { name, publishConfig = {} } = readJsonFile(join(pkgDir, "package.json"));
1017
999
  const { access } = publishConfig;
1018
- return access ?? (name.startsWith("@") ? "restricted" : "public");
1000
+ return access || (name.startsWith("@") ? "restricted" : "public");
1019
1001
  };
1020
1002
  /**
1021
1003
  * 检查与仓库的连接
@@ -1130,4 +1112,4 @@ const publishPackage = (options) => {
1130
1112
  };
1131
1113
 
1132
1114
  //#endregion
1133
- export { ConfirmResult, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, HttpLibrary, PkgManager, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLatestTagFromAllRefs, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getStatus, getTags, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
1115
+ export { ConfirmResult, DEFAULT_ACCESS, DEFAULT_REGISTRY, DEFAULT_TAG, HttpLibrary, PkgManager, YesOrNo, accessArg, bumpPackageVersion, checkVersion, coloredChangeset, copyDirAsync, countCommitsSinceLatestTag, deleteTag, deleteTagSync, discardAll, discardAllSync, discardFile, editFile, editJsonFile, emptyDir, eol, execAsync, execSyncWithString, fetchAllBranch, getAccess, getAllRemotes, getAuthenticatedUser, getCurrentBranch, getDefaultRemote, getDistTags, getFullHash, getGitConfig, getGitRemoteUrl, getGithubReleaseUrl, getGithubUrl, getLatestTag, getLocalTags, getLog, getOtherRemotes, getPackageInfo, getPackageUrl, getPreviousTag, getPublishedVersion, getRegistry, getRemote, getRemoteForBranch, getRemoteTags, getSortedTags, getStatus, getUpstreamArgs, gitAddAll, gitAddTracked, gitCommit, gitCommitAmend, gitTagAnnotated, gitTagLightweight, gitUndo, hasUpstreamBranch, hasWriteAccess, isEmpty, isGitRepo, isRemoteName, isTestFile, isValidPackageName, isWorkingDirClean, joinUrl, parseArgs, parseGitHubRepo, pingRegistry, pkgFromUserAgent, publishPackage, pushBranch, pushTag, readJsonFile, readSubDirs, registryArg, resetHard, resetHardSync, resetMixed, resetSoft, resolveChangelogRange, restoreAll, restoreAllSync, restoreFile, restoreFileFromCommit, restoreFromCommit, revertCommit, runCliForTest, runGit, runGitSync, runNode, runNodeSync, runNpm, runNpmSync, space, spawnAsync, spawnSyncWithString, stringifyArgs, tagArg, toValidPackageName, toValidProjectName, trimTemplate, unstageAll, unstageFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peiyanlu/cli-utils",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "Shared utils for building interactive Node.js CLI applications.",
5
5
  "license": "MIT",
6
6
  "type": "module",