@soybeanjs/cli 0.4.2 → 0.5.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/dist/index.cjs CHANGED
@@ -12,6 +12,7 @@ const promises = require('fs/promises');
12
12
  const EE = require('events');
13
13
  const Stream = require('stream');
14
14
  const stringdecoder = require('string_decoder');
15
+ const cliProgress = require('cli-progress');
15
16
  const ofetch = require('ofetch');
16
17
  const dayjs = require('dayjs');
17
18
  const convertGitmoji = require('convert-gitmoji');
@@ -37,10 +38,11 @@ const actualFS__namespace = /*#__PURE__*/_interopNamespaceCompat(actualFS);
37
38
  const EE__default = /*#__PURE__*/_interopDefaultCompat(EE);
38
39
  const Stream__default = /*#__PURE__*/_interopDefaultCompat(Stream);
39
40
  const stringdecoder__default = /*#__PURE__*/_interopDefaultCompat(stringdecoder);
41
+ const cliProgress__default = /*#__PURE__*/_interopDefaultCompat(cliProgress);
40
42
  const dayjs__default = /*#__PURE__*/_interopDefaultCompat(dayjs);
41
43
  const versionBumpp__default = /*#__PURE__*/_interopDefaultCompat(versionBumpp);
42
44
 
43
- const version = "0.4.2";
45
+ const version = "0.5.0";
44
46
 
45
47
  async function execCommand(cmd, args, options) {
46
48
  const { execa } = await import('execa');
@@ -7528,6 +7530,28 @@ async function getTotalGitTags() {
7528
7530
  const tags = tagStr.split("\n");
7529
7531
  return tags;
7530
7532
  }
7533
+ async function getTagDateMap() {
7534
+ const tagDateStr = await execCommand("git", [
7535
+ "--no-pager",
7536
+ "log",
7537
+ "--tags",
7538
+ "--simplify-by-decoration",
7539
+ "--pretty=format:%ci %d"
7540
+ ]);
7541
+ const TAG_MARK = "(tag: ";
7542
+ const map = /* @__PURE__ */ new Map();
7543
+ const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
7544
+ dates.forEach((item) => {
7545
+ const [dateStr, tagStr] = item.split(TAG_MARK);
7546
+ const date = dayjs__default(dateStr.trim()).format("YYYY-MM-DD");
7547
+ const VERSION_REG = /v\d+\.\d+\.\d+/;
7548
+ const tag = tagStr.match(VERSION_REG)?.[0];
7549
+ if (tag && date) {
7550
+ map.set(tag.trim(), date);
7551
+ }
7552
+ });
7553
+ return map;
7554
+ }
7531
7555
  function getFromToTags(tags) {
7532
7556
  const result = [];
7533
7557
  tags.forEach((tag, index) => {
@@ -7669,7 +7693,7 @@ async function getResolvedAuthorLogin(params) {
7669
7693
  }
7670
7694
  return login;
7671
7695
  }
7672
- async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7696
+ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken, resolvedLogins) {
7673
7697
  const resultCommits = [];
7674
7698
  const map = /* @__PURE__ */ new Map();
7675
7699
  for (const commit of commits) {
@@ -7687,14 +7711,18 @@ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7687
7711
  commits: commitHashes,
7688
7712
  login: ""
7689
7713
  };
7690
- if (!map.has(email)) {
7691
- resolvedAuthor.login = await getResolvedAuthorLogin({ github, githubToken, commitHashes, email });
7692
- map.set(author.email, resolvedAuthor);
7714
+ if (!resolvedLogins?.has(email)) {
7715
+ const login = await getResolvedAuthorLogin({ github, githubToken, commitHashes, email });
7716
+ resolvedAuthor.login = login;
7717
+ resolvedLogins?.set(email, login);
7693
7718
  } else {
7694
- const resolvedItem = map.get(author.email);
7695
- Object.assign(resolvedAuthor, resolvedItem);
7719
+ const login = resolvedLogins?.get(email) || "";
7720
+ resolvedAuthor.login = login;
7696
7721
  }
7697
7722
  resolvedAuthors.push(resolvedAuthor);
7723
+ if (!map.has(email)) {
7724
+ map.set(email, resolvedAuthor);
7725
+ }
7698
7726
  }
7699
7727
  }
7700
7728
  const resultCommit = { ...commit, resolvedAuthors };
@@ -7705,9 +7733,7 @@ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7705
7733
  contributors: Array.from(map.values())
7706
7734
  };
7707
7735
  }
7708
- getTotalGitTags();
7709
7736
 
7710
- const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+\]/g;
7711
7737
  function formatReferences(references, github, type) {
7712
7738
  const refs = references.filter((i) => {
7713
7739
  if (type === "issues")
@@ -7773,22 +7799,37 @@ function getGitUserAvatar(userName) {
7773
7799
  const avatarUrl = `https://github.com/${userName}.png?size=48`;
7774
7800
  return avatarUrl;
7775
7801
  }
7776
- function createUserAvatar(userName) {
7777
- const el = `<a href="https://github.com/${userName}" data-hovercard-type="user" data-hovercard-url="/users/yanbowe/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self">
7778
- <img src="${getGitUserAvatar(
7779
- userName
7780
- )}" alt="@${userName}" size="32" height="32" width="32" data-view-component="true" class="avatar circle">
7781
- </a>`;
7782
- return el;
7802
+ function createContributorLine(contributors) {
7803
+ let loginLine = "";
7804
+ let unloginLine = "";
7805
+ contributors.forEach((contributor, index) => {
7806
+ const { name, email, login } = contributor;
7807
+ if (!login) {
7808
+ let line = `[${name}](mailto:${email})`;
7809
+ if (index < contributors.length - 1) {
7810
+ line += ", ";
7811
+ }
7812
+ unloginLine += line;
7813
+ } else {
7814
+ const avatar = getGitUserAvatar(login);
7815
+ loginLine += `![${login}](${avatar}) `;
7816
+ }
7817
+ });
7818
+ return `${loginLine}
7819
+ ${unloginLine}`;
7783
7820
  }
7784
7821
  function generateMarkdown(params) {
7822
+ const VERSION_REG = /v\d+\.\d+\.\d+/;
7785
7823
  const { commits, options, showTitle, contributors } = params;
7786
7824
  const lines = [];
7787
7825
  const url = `https://github.com/${options.github}/compare/${options.from}...${options.to}`;
7788
7826
  if (showTitle) {
7789
- const today = dayjs__default().format("YYYY-MM-DD");
7790
- const version = VERSION_REG_OF_MARKDOWN.test(options.to) ? options.to : options.newVersion;
7791
- const title = `## [${version}](${url})(${today})`;
7827
+ const version = VERSION_REG.test(options.to) ? options.to : options.newVersion;
7828
+ const date = options.tagDateMap.get(options.to);
7829
+ let title = `## [${version}](${url})`;
7830
+ if (date) {
7831
+ title += ` (${date})`;
7832
+ }
7792
7833
  lines.push(title);
7793
7834
  }
7794
7835
  const [breaking, changes] = partition(commits, (c) => c.isBreaking);
@@ -7806,7 +7847,7 @@ function generateMarkdown(params) {
7806
7847
  }
7807
7848
  if (showTitle) {
7808
7849
  lines.push("", "### \u2764\uFE0F Contributors", "");
7809
- const contributorLine = contributors.map((item) => createUserAvatar(item.login)).join(" ");
7850
+ const contributorLine = createContributorLine(contributors);
7810
7851
  lines.push(contributorLine);
7811
7852
  }
7812
7853
  const md = convertGitmoji.convert(lines.join("\n").trim(), true);
@@ -7814,6 +7855,7 @@ function generateMarkdown(params) {
7814
7855
  return markdown;
7815
7856
  }
7816
7857
  async function isVersionInMarkdown(version, mdPath) {
7858
+ const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+\]/g;
7817
7859
  let isIn = false;
7818
7860
  const md = await promises.readFile(mdPath, "utf8");
7819
7861
  if (md) {
@@ -7878,6 +7920,7 @@ function createDefaultOptions() {
7878
7920
  from: "",
7879
7921
  to: "",
7880
7922
  tags: [],
7923
+ tagDateMap: /* @__PURE__ */ new Map(),
7881
7924
  prerelease: false,
7882
7925
  capitalize: true,
7883
7926
  emoji: true,
@@ -7926,6 +7969,7 @@ async function initOptions() {
7926
7969
  options.from = lastTag || firstCommit;
7927
7970
  }
7928
7971
  options.tags = await getTotalGitTags();
7972
+ options.tagDateMap = await getTagDateMap();
7929
7973
  options.github = await getGitHubRepo();
7930
7974
  options.prerelease = isPrerelease(options.to);
7931
7975
  return options;
@@ -7942,21 +7986,27 @@ async function generateChangelogByTag(options) {
7942
7986
  }
7943
7987
  async function generateChangelogByTags(options) {
7944
7988
  const tags = getFromToTags(options.tags);
7989
+ const bar = new cliProgress__default.SingleBar({}, cliProgress__default.Presets.shades_classic);
7990
+ bar.start(tags.length, 0);
7945
7991
  let md = "";
7992
+ const resolvedLogins = /* @__PURE__ */ new Map();
7946
7993
  for (let i = 0; i < tags.length; i += 1) {
7947
7994
  const { from, to } = tags[i];
7948
7995
  const gitCommits = await getGitCommits(from, to, options.scopeMap);
7949
7996
  const { commits, contributors } = await getGitCommitsAndResolvedAuthors(
7950
7997
  gitCommits,
7951
7998
  options.github,
7952
- options.githubToken
7999
+ options.githubToken,
8000
+ resolvedLogins
7953
8001
  );
7954
8002
  const opts = { ...options, from, to };
7955
8003
  const nextMd = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
7956
8004
  md = `${nextMd}
7957
8005
 
7958
8006
  ${md}`;
8007
+ bar.update(i + 1);
7959
8008
  }
8009
+ bar.stop();
7960
8010
  return md;
7961
8011
  }
7962
8012
  async function generateChangelog(total = false) {
package/dist/index.mjs CHANGED
@@ -11,12 +11,13 @@ import { lstat, readdir as readdir$1, readlink, realpath, readFile, writeFile }
11
11
  import EE from 'events';
12
12
  import Stream from 'stream';
13
13
  import stringdecoder from 'string_decoder';
14
+ import cliProgress from 'cli-progress';
14
15
  import { ofetch } from 'ofetch';
15
16
  import dayjs from 'dayjs';
16
17
  import { convert } from 'convert-gitmoji';
17
18
  import versionBumpp from 'bumpp';
18
19
 
19
- const version = "0.4.2";
20
+ const version = "0.5.0";
20
21
 
21
22
  async function execCommand(cmd, args, options) {
22
23
  const { execa } = await import('execa');
@@ -7504,6 +7505,28 @@ async function getTotalGitTags() {
7504
7505
  const tags = tagStr.split("\n");
7505
7506
  return tags;
7506
7507
  }
7508
+ async function getTagDateMap() {
7509
+ const tagDateStr = await execCommand("git", [
7510
+ "--no-pager",
7511
+ "log",
7512
+ "--tags",
7513
+ "--simplify-by-decoration",
7514
+ "--pretty=format:%ci %d"
7515
+ ]);
7516
+ const TAG_MARK = "(tag: ";
7517
+ const map = /* @__PURE__ */ new Map();
7518
+ const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
7519
+ dates.forEach((item) => {
7520
+ const [dateStr, tagStr] = item.split(TAG_MARK);
7521
+ const date = dayjs(dateStr.trim()).format("YYYY-MM-DD");
7522
+ const VERSION_REG = /v\d+\.\d+\.\d+/;
7523
+ const tag = tagStr.match(VERSION_REG)?.[0];
7524
+ if (tag && date) {
7525
+ map.set(tag.trim(), date);
7526
+ }
7527
+ });
7528
+ return map;
7529
+ }
7507
7530
  function getFromToTags(tags) {
7508
7531
  const result = [];
7509
7532
  tags.forEach((tag, index) => {
@@ -7645,7 +7668,7 @@ async function getResolvedAuthorLogin(params) {
7645
7668
  }
7646
7669
  return login;
7647
7670
  }
7648
- async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7671
+ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken, resolvedLogins) {
7649
7672
  const resultCommits = [];
7650
7673
  const map = /* @__PURE__ */ new Map();
7651
7674
  for (const commit of commits) {
@@ -7663,14 +7686,18 @@ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7663
7686
  commits: commitHashes,
7664
7687
  login: ""
7665
7688
  };
7666
- if (!map.has(email)) {
7667
- resolvedAuthor.login = await getResolvedAuthorLogin({ github, githubToken, commitHashes, email });
7668
- map.set(author.email, resolvedAuthor);
7689
+ if (!resolvedLogins?.has(email)) {
7690
+ const login = await getResolvedAuthorLogin({ github, githubToken, commitHashes, email });
7691
+ resolvedAuthor.login = login;
7692
+ resolvedLogins?.set(email, login);
7669
7693
  } else {
7670
- const resolvedItem = map.get(author.email);
7671
- Object.assign(resolvedAuthor, resolvedItem);
7694
+ const login = resolvedLogins?.get(email) || "";
7695
+ resolvedAuthor.login = login;
7672
7696
  }
7673
7697
  resolvedAuthors.push(resolvedAuthor);
7698
+ if (!map.has(email)) {
7699
+ map.set(email, resolvedAuthor);
7700
+ }
7674
7701
  }
7675
7702
  }
7676
7703
  const resultCommit = { ...commit, resolvedAuthors };
@@ -7681,9 +7708,7 @@ async function getGitCommitsAndResolvedAuthors(commits, github, githubToken) {
7681
7708
  contributors: Array.from(map.values())
7682
7709
  };
7683
7710
  }
7684
- getTotalGitTags();
7685
7711
 
7686
- const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+\]/g;
7687
7712
  function formatReferences(references, github, type) {
7688
7713
  const refs = references.filter((i) => {
7689
7714
  if (type === "issues")
@@ -7749,22 +7774,37 @@ function getGitUserAvatar(userName) {
7749
7774
  const avatarUrl = `https://github.com/${userName}.png?size=48`;
7750
7775
  return avatarUrl;
7751
7776
  }
7752
- function createUserAvatar(userName) {
7753
- const el = `<a href="https://github.com/${userName}" data-hovercard-type="user" data-hovercard-url="/users/yanbowe/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self">
7754
- <img src="${getGitUserAvatar(
7755
- userName
7756
- )}" alt="@${userName}" size="32" height="32" width="32" data-view-component="true" class="avatar circle">
7757
- </a>`;
7758
- return el;
7777
+ function createContributorLine(contributors) {
7778
+ let loginLine = "";
7779
+ let unloginLine = "";
7780
+ contributors.forEach((contributor, index) => {
7781
+ const { name, email, login } = contributor;
7782
+ if (!login) {
7783
+ let line = `[${name}](mailto:${email})`;
7784
+ if (index < contributors.length - 1) {
7785
+ line += ", ";
7786
+ }
7787
+ unloginLine += line;
7788
+ } else {
7789
+ const avatar = getGitUserAvatar(login);
7790
+ loginLine += `![${login}](${avatar}) `;
7791
+ }
7792
+ });
7793
+ return `${loginLine}
7794
+ ${unloginLine}`;
7759
7795
  }
7760
7796
  function generateMarkdown(params) {
7797
+ const VERSION_REG = /v\d+\.\d+\.\d+/;
7761
7798
  const { commits, options, showTitle, contributors } = params;
7762
7799
  const lines = [];
7763
7800
  const url = `https://github.com/${options.github}/compare/${options.from}...${options.to}`;
7764
7801
  if (showTitle) {
7765
- const today = dayjs().format("YYYY-MM-DD");
7766
- const version = VERSION_REG_OF_MARKDOWN.test(options.to) ? options.to : options.newVersion;
7767
- const title = `## [${version}](${url})(${today})`;
7802
+ const version = VERSION_REG.test(options.to) ? options.to : options.newVersion;
7803
+ const date = options.tagDateMap.get(options.to);
7804
+ let title = `## [${version}](${url})`;
7805
+ if (date) {
7806
+ title += ` (${date})`;
7807
+ }
7768
7808
  lines.push(title);
7769
7809
  }
7770
7810
  const [breaking, changes] = partition(commits, (c) => c.isBreaking);
@@ -7782,7 +7822,7 @@ function generateMarkdown(params) {
7782
7822
  }
7783
7823
  if (showTitle) {
7784
7824
  lines.push("", "### \u2764\uFE0F Contributors", "");
7785
- const contributorLine = contributors.map((item) => createUserAvatar(item.login)).join(" ");
7825
+ const contributorLine = createContributorLine(contributors);
7786
7826
  lines.push(contributorLine);
7787
7827
  }
7788
7828
  const md = convert(lines.join("\n").trim(), true);
@@ -7790,6 +7830,7 @@ function generateMarkdown(params) {
7790
7830
  return markdown;
7791
7831
  }
7792
7832
  async function isVersionInMarkdown(version, mdPath) {
7833
+ const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+\]/g;
7793
7834
  let isIn = false;
7794
7835
  const md = await readFile(mdPath, "utf8");
7795
7836
  if (md) {
@@ -7854,6 +7895,7 @@ function createDefaultOptions() {
7854
7895
  from: "",
7855
7896
  to: "",
7856
7897
  tags: [],
7898
+ tagDateMap: /* @__PURE__ */ new Map(),
7857
7899
  prerelease: false,
7858
7900
  capitalize: true,
7859
7901
  emoji: true,
@@ -7902,6 +7944,7 @@ async function initOptions() {
7902
7944
  options.from = lastTag || firstCommit;
7903
7945
  }
7904
7946
  options.tags = await getTotalGitTags();
7947
+ options.tagDateMap = await getTagDateMap();
7905
7948
  options.github = await getGitHubRepo();
7906
7949
  options.prerelease = isPrerelease(options.to);
7907
7950
  return options;
@@ -7918,21 +7961,27 @@ async function generateChangelogByTag(options) {
7918
7961
  }
7919
7962
  async function generateChangelogByTags(options) {
7920
7963
  const tags = getFromToTags(options.tags);
7964
+ const bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
7965
+ bar.start(tags.length, 0);
7921
7966
  let md = "";
7967
+ const resolvedLogins = /* @__PURE__ */ new Map();
7922
7968
  for (let i = 0; i < tags.length; i += 1) {
7923
7969
  const { from, to } = tags[i];
7924
7970
  const gitCommits = await getGitCommits(from, to, options.scopeMap);
7925
7971
  const { commits, contributors } = await getGitCommitsAndResolvedAuthors(
7926
7972
  gitCommits,
7927
7973
  options.github,
7928
- options.githubToken
7974
+ options.githubToken,
7975
+ resolvedLogins
7929
7976
  );
7930
7977
  const opts = { ...options, from, to };
7931
7978
  const nextMd = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
7932
7979
  md = `${nextMd}
7933
7980
 
7934
7981
  ${md}`;
7982
+ bar.update(i + 1);
7935
7983
  }
7984
+ bar.stop();
7936
7985
  return md;
7937
7986
  }
7938
7987
  async function generateChangelog(total = false) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soybeanjs/cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "SoybeanJS's command line tools",
5
5
  "author": {
6
6
  "name": "Soybean",
@@ -34,6 +34,7 @@
34
34
  "dependencies": {
35
35
  "bumpp": "9.1.0",
36
36
  "cac": "6.7.14",
37
+ "cli-progress": "^3.12.0",
37
38
  "convert-gitmoji": "0.1.3",
38
39
  "dayjs": "1.11.8",
39
40
  "enquirer": "2.3.6",
@@ -47,10 +48,10 @@
47
48
  },
48
49
  "devDependencies": {
49
50
  "@soybeanjs/cli": "link:",
51
+ "@types/cli-progress": "^3.11.0",
50
52
  "@types/node": "20.2.5",
51
53
  "eslint": "8.41.0",
52
54
  "eslint-config-soybeanjs": "0.4.7",
53
- "githublogen": "link:../githublogen",
54
55
  "simple-git-hooks": "2.8.1",
55
56
  "tsx": "3.12.7",
56
57
  "typescript": "5.0.4",