@soybeanjs/changelog 0.0.7 → 0.3.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.
package/dist/index.cjs CHANGED
@@ -1,567 +1 @@
1
- 'use strict';
2
-
3
- const cliProgress = require('cli-progress');
4
- const promises = require('fs/promises');
5
- const ofetch = require('ofetch');
6
- const dayjs = require('dayjs');
7
- const fs = require('fs');
8
- const convertGitmoji = require('convert-gitmoji');
9
-
10
- function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
-
12
- const dayjs__default = /*#__PURE__*/_interopDefaultCompat(dayjs);
13
-
14
- async function execCommand(cmd, args, options) {
15
- const { execa } = await import('execa');
16
- const res = await execa(cmd, args, options);
17
- return res?.stdout?.trim() || "";
18
- }
19
- function notNullish(v) {
20
- return v !== null && v !== void 0;
21
- }
22
- function partition(array, ...filters) {
23
- const result = new Array(filters.length + 1).fill(null).map(() => []);
24
- array.forEach((e, idx, arr) => {
25
- let i = 0;
26
- for (const filter of filters) {
27
- if (filter(e, idx, arr)) {
28
- result[i].push(e);
29
- return;
30
- }
31
- i += 1;
32
- }
33
- result[i].push(e);
34
- });
35
- return result;
36
- }
37
- function groupBy(items, key, groups = {}) {
38
- for (const item of items) {
39
- const v = item[key];
40
- groups[v] = groups[v] || [];
41
- groups[v].push(item);
42
- }
43
- return groups;
44
- }
45
- function capitalize(str) {
46
- return str.charAt(0).toUpperCase() + str.slice(1);
47
- }
48
- function join(array, glue = ", ", finalGlue = " and ") {
49
- if (!array || array.length === 0)
50
- return "";
51
- if (array.length === 1)
52
- return array[0];
53
- if (array.length === 2)
54
- return array.join(finalGlue);
55
- return `${array.slice(0, -1).join(glue)}${finalGlue}${array.slice(-1)}`;
56
- }
57
-
58
- const VERSION_REG = /v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
59
- const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g;
60
- const VERSION_WITH_RELEASE = /release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
61
-
62
- async function getTotalGitTags() {
63
- const tagStr = await execCommand("git", ["--no-pager", "tag", "-l", "--sort=creatordate"]);
64
- const tags = tagStr.split("\n");
65
- return tags;
66
- }
67
- async function getTagDateMap() {
68
- const tagDateStr = await execCommand("git", [
69
- "--no-pager",
70
- "log",
71
- "--tags",
72
- "--simplify-by-decoration",
73
- "--pretty=format:%ci %d"
74
- ]);
75
- const TAG_MARK = "tag: ";
76
- const map = /* @__PURE__ */ new Map();
77
- const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
78
- dates.forEach((item) => {
79
- const [dateStr, tagStr] = item.split(TAG_MARK);
80
- const date = dayjs__default(dateStr).format("YYYY-MM-DD");
81
- const tag = tagStr.match(VERSION_REG)?.[0];
82
- if (tag && date) {
83
- map.set(tag.trim(), date);
84
- }
85
- });
86
- return map;
87
- }
88
- function getFromToTags(tags) {
89
- const result = [];
90
- tags.forEach((tag, index) => {
91
- if (index < tags.length - 1) {
92
- result.push({ from: tag, to: tags[index + 1] });
93
- }
94
- });
95
- return result;
96
- }
97
- async function getLastGitTag(delta = 0) {
98
- const tags = await getTotalGitTags();
99
- return tags[tags.length + delta - 1];
100
- }
101
- async function getGitMainBranchName() {
102
- const main = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
103
- return main;
104
- }
105
- async function getCurrentGitBranch() {
106
- const tag = await execCommand("git", ["tag", "--points-at", "HEAD"]);
107
- const main = getGitMainBranchName();
108
- return tag || main;
109
- }
110
- async function getGitHubRepo() {
111
- const url = await execCommand("git", ["config", "--get", "remote.origin.url"]);
112
- const match = url.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);
113
- if (!match) {
114
- throw new Error(`Can not parse GitHub repo from url ${url}`);
115
- }
116
- return `${match[1]}/${match[2]}`;
117
- }
118
- function getFirstGitCommit() {
119
- return execCommand("git", ["rev-list", "--max-parents=0", "HEAD"]);
120
- }
121
- async function getGitDiff(from, to = "HEAD") {
122
- const rawGit = await execCommand("git", [
123
- "--no-pager",
124
- "log",
125
- `${from ? `${from}...` : ""}${to}`,
126
- '--pretty="----%n%s|%h|%an|%ae%n%b"',
127
- "--name-status"
128
- ]);
129
- const rwaGitLines = rawGit.split("----\n").splice(1);
130
- const gitCommits = rwaGitLines.map((line) => {
131
- const [firstLine, ...body] = line.split("\n");
132
- const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
133
- const gitCommit = {
134
- message,
135
- shortHash,
136
- author: { name: authorName, email: authorEmail },
137
- body: body.join("\n")
138
- };
139
- return gitCommit;
140
- });
141
- return gitCommits;
142
- }
143
- function parseGitCommit(commit) {
144
- const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
145
- const CoAuthoredByRegex = /co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim;
146
- const PullRequestRE = /\([a-z]*(#\d+)\s*\)/gm;
147
- const IssueRE = /(#\d+)/gm;
148
- const match = commit.message.match(ConventionalCommitRegex);
149
- if (!match?.groups) {
150
- return null;
151
- }
152
- const type = match.groups.type;
153
- const scope = match.groups.scope || "";
154
- const isBreaking = Boolean(match.groups.breaking);
155
- let description = match.groups.description;
156
- const references = [];
157
- for (const m of description.matchAll(PullRequestRE)) {
158
- references.push({ type: "pull-request", value: m[1] });
159
- }
160
- for (const m of description.matchAll(IssueRE)) {
161
- if (!references.some((i) => i.value === m[1])) {
162
- references.push({ type: "issue", value: m[1] });
163
- }
164
- }
165
- references.push({ value: commit.shortHash, type: "hash" });
166
- description = description.replace(PullRequestRE, "").trim();
167
- const authors = [commit.author];
168
- const matches = commit.body.matchAll(CoAuthoredByRegex);
169
- for (const $match of matches) {
170
- const { name = "", email = "" } = $match.groups || {};
171
- const author = {
172
- name: name.trim(),
173
- email: email.trim()
174
- };
175
- authors.push(author);
176
- }
177
- return {
178
- ...commit,
179
- authors,
180
- resolvedAuthors: [],
181
- description,
182
- type,
183
- scope,
184
- references,
185
- isBreaking
186
- };
187
- }
188
- async function getGitCommits(from, to = "HEAD") {
189
- const rwaGitCommits = await getGitDiff(from, to);
190
- const commits = rwaGitCommits.map((commit) => parseGitCommit(commit)).filter(notNullish);
191
- return commits;
192
- }
193
- function getHeaders(githubToken) {
194
- return {
195
- accept: "application/vnd.github.v3+json",
196
- authorization: `token ${githubToken}`
197
- };
198
- }
199
- async function getResolvedAuthorLogin(github, commitHashes, email) {
200
- let login = "";
201
- try {
202
- const data = await ofetch.ofetch(`https://ungh.cc/users/find/${email}`);
203
- login = data?.user?.username || "";
204
- } catch (e) {
205
- console.log("e: ", e);
206
- }
207
- if (login) {
208
- return login;
209
- }
210
- const { repo, token } = github;
211
- if (!token) {
212
- return login;
213
- }
214
- if (commitHashes.length) {
215
- try {
216
- const data = await ofetch.ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, {
217
- headers: getHeaders(token)
218
- });
219
- login = data?.author?.login || "";
220
- } catch (e) {
221
- console.log("e: ", e);
222
- }
223
- }
224
- if (login) {
225
- return login;
226
- }
227
- try {
228
- const data = await ofetch.ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, {
229
- headers: getHeaders(token)
230
- });
231
- login = data.items[0].login;
232
- } catch (e) {
233
- console.log("e: ", e);
234
- }
235
- return login;
236
- }
237
- async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins) {
238
- const resultCommits = [];
239
- const map = /* @__PURE__ */ new Map();
240
- for await (const commit of commits) {
241
- const resolvedAuthors = [];
242
- for await (const [index, author] of commit.authors.entries()) {
243
- const { email, name } = author;
244
- if (email && name) {
245
- const commitHashes = [];
246
- if (index === 0) {
247
- commitHashes.push(commit.shortHash);
248
- }
249
- const resolvedAuthor = {
250
- name,
251
- email,
252
- commits: commitHashes,
253
- login: ""
254
- };
255
- if (!resolvedLogins?.has(email)) {
256
- const login = await getResolvedAuthorLogin(github, commitHashes, email);
257
- resolvedAuthor.login = login;
258
- resolvedLogins?.set(email, login);
259
- } else {
260
- const login = resolvedLogins?.get(email) || "";
261
- resolvedAuthor.login = login;
262
- }
263
- resolvedAuthors.push(resolvedAuthor);
264
- if (!map.has(email)) {
265
- map.set(email, resolvedAuthor);
266
- }
267
- }
268
- }
269
- const resultCommit = { ...commit, resolvedAuthors };
270
- resultCommits.push(resultCommit);
271
- }
272
- return {
273
- commits: resultCommits,
274
- contributors: Array.from(map.values())
275
- };
276
- }
277
-
278
- function createDefaultOptions() {
279
- const cwd = process.cwd();
280
- const options = {
281
- cwd,
282
- types: {
283
- feat: "\u{1F680} Features",
284
- fix: "\u{1F41E} Bug Fixes",
285
- perf: "\u{1F525} Performance",
286
- refactor: "\u{1F485} Refactors",
287
- docs: "\u{1F4D6} Documentation",
288
- build: "\u{1F4E6} Build",
289
- types: "\u{1F30A} Types",
290
- chore: "\u{1F3E1} Chore",
291
- examples: "\u{1F3C0} Examples",
292
- test: "\u2705 Tests",
293
- style: "\u{1F3A8} Styles",
294
- ci: "\u{1F916} CI"
295
- },
296
- github: {
297
- repo: "",
298
- token: process.env.GITHUB_TOKEN || ""
299
- },
300
- from: "",
301
- to: "",
302
- tags: [],
303
- tagDateMap: /* @__PURE__ */ new Map(),
304
- capitalize: false,
305
- emoji: true,
306
- titles: {
307
- breakingChanges: "\u{1F6A8} Breaking Changes"
308
- },
309
- output: "CHANGELOG.md",
310
- regenerate: false,
311
- newVersion: ""
312
- };
313
- return options;
314
- }
315
- async function getVersionFromPkgJson(cwd) {
316
- let newVersion = "";
317
- try {
318
- const pkgJson = await promises.readFile(`${cwd}/package.json`, "utf-8");
319
- const pkg = JSON.parse(pkgJson);
320
- newVersion = pkg?.version || "";
321
- } catch {
322
- }
323
- return {
324
- newVersion
325
- };
326
- }
327
- async function createOptions(options) {
328
- var _a;
329
- const opts = createDefaultOptions();
330
- Object.assign(opts, options);
331
- const { newVersion } = await getVersionFromPkgJson(opts.cwd);
332
- (_a = opts.github).repo || (_a.repo = await getGitHubRepo());
333
- opts.newVersion || (opts.newVersion = `v${newVersion}`);
334
- opts.from || (opts.from = await getLastGitTag());
335
- opts.to || (opts.to = await getCurrentGitBranch());
336
- if (opts.to === opts.from) {
337
- const lastTag = await getLastGitTag(-1);
338
- const firstCommit = await getFirstGitCommit();
339
- opts.from = lastTag || firstCommit;
340
- }
341
- opts.tags = await getTotalGitTags();
342
- opts.tagDateMap = await getTagDateMap();
343
- return opts;
344
- }
345
-
346
- function formatReferences(references, githubRepo, type) {
347
- const refs = references.filter((i) => {
348
- if (type === "issues")
349
- return i.type === "issue" || i.type === "pull-request";
350
- return i.type === "hash";
351
- }).map((ref) => {
352
- if (!githubRepo)
353
- return ref.value;
354
- if (ref.type === "pull-request" || ref.type === "issue")
355
- return `https://github.com/${githubRepo}/issues/${ref.value.slice(1)}`;
356
- return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${githubRepo}/commit/${ref.value})`;
357
- });
358
- const referencesString = join(refs).trim();
359
- if (type === "issues")
360
- return referencesString && `in ${referencesString}`;
361
- return referencesString;
362
- }
363
- function formatLine(commit, options) {
364
- const prRefs = formatReferences(commit.references, options.github.repo, "issues");
365
- const hashRefs = formatReferences(commit.references, options.github.repo, "hash");
366
- let authors = join([...new Set(commit.resolvedAuthors.map((i) => i.login ? `@${i.login}` : `**${i.name}**`))]).trim();
367
- if (authors) {
368
- authors = `by ${authors}`;
369
- }
370
- let refs = [authors, prRefs, hashRefs].filter((i) => i?.trim()).join(" ");
371
- if (refs) {
372
- refs = `&nbsp;-&nbsp; ${refs}`;
373
- }
374
- const description = options.capitalize ? capitalize(commit.description) : commit.description;
375
- return [description, refs].filter((i) => i?.trim()).join(" ");
376
- }
377
- function formatTitle(name, options) {
378
- const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
379
- let formatName = name.trim();
380
- if (!options.emoji) {
381
- formatName = name.replace(emojisRE, "").trim();
382
- }
383
- return `### &nbsp;&nbsp;&nbsp;${formatName}`;
384
- }
385
- function formatSection(commits, sectionName, options) {
386
- if (!commits.length)
387
- return [];
388
- const lines = ["", formatTitle(sectionName, options), ""];
389
- const scopes = groupBy(commits, "scope");
390
- let useScopeGroup = true;
391
- if (!Object.entries(scopes).some(([k, v]) => k && v.length > 1)) {
392
- useScopeGroup = false;
393
- }
394
- Object.keys(scopes).sort().forEach((scope) => {
395
- let padding = "";
396
- let prefix = "";
397
- const scopeText = `**${scope}**`;
398
- if (scope && useScopeGroup) {
399
- lines.push(`- ${scopeText}:`);
400
- padding = " ";
401
- } else if (scope) {
402
- prefix = `${scopeText}: `;
403
- }
404
- lines.push(...scopes[scope].reverse().map((commit) => `${padding}- ${prefix}${formatLine(commit, options)}`));
405
- });
406
- return lines;
407
- }
408
- function getUserGithub(userName) {
409
- const githubUrl = `https://github.com/${userName}`;
410
- return githubUrl;
411
- }
412
- function getGitUserAvatar(userName) {
413
- const githubUrl = getUserGithub(userName);
414
- const avatarUrl = `${githubUrl}.png?size=48`;
415
- return avatarUrl;
416
- }
417
- function createContributorLine(contributors) {
418
- let loginLine = "";
419
- let unLoginLine = "";
420
- contributors.forEach((contributor, index) => {
421
- const { name, email, login } = contributor;
422
- if (!login) {
423
- let line = `[${name}](mailto:${email})`;
424
- if (index < contributors.length - 1) {
425
- line += ",&nbsp;";
426
- }
427
- unLoginLine += line;
428
- } else {
429
- const githubUrl = getUserGithub(login);
430
- const avatar = getGitUserAvatar(login);
431
- loginLine += `[![${login}](${avatar})](${githubUrl})&nbsp;&nbsp;`;
432
- }
433
- });
434
- return `${loginLine}
435
- ${unLoginLine}`;
436
- }
437
- function generateMarkdown(params) {
438
- const { options, showTitle, contributors } = params;
439
- const commits = params.commits.filter((commit) => commit.description.match(VERSION_WITH_RELEASE) === null);
440
- const lines = [];
441
- const isNewVersion = !VERSION_REG.test(options.to);
442
- const version = isNewVersion ? options.newVersion : options.to;
443
- const url = `https://github.com/${options.github.repo}/compare/${options.from}...${version}`;
444
- if (showTitle) {
445
- const date = isNewVersion ? dayjs__default().format("YY-MM-DD") : options.tagDateMap.get(options.to);
446
- let title = `## [${version}](${url})`;
447
- if (date) {
448
- title += ` (${date})`;
449
- }
450
- lines.push(title);
451
- }
452
- const [breaking, changes] = partition(commits, (c) => c.isBreaking);
453
- const group = groupBy(changes, "type");
454
- lines.push(...formatSection(breaking, options.titles.breakingChanges, options));
455
- for (const type of Object.keys(options.types)) {
456
- const items = group[type] || [];
457
- lines.push(...formatSection(items, options.types[type], options));
458
- }
459
- if (!lines.length) {
460
- lines.push("*No significant changes*");
461
- }
462
- if (!showTitle) {
463
- lines.push("", `##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${url})`);
464
- }
465
- if (showTitle) {
466
- lines.push("", "### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors", "");
467
- const contributorLine = createContributorLine(contributors);
468
- lines.push(contributorLine);
469
- }
470
- const md = convertGitmoji.convert(lines.join("\n").trim(), true);
471
- return md;
472
- }
473
- async function isVersionInMarkdown(version, mdPath) {
474
- let isIn = false;
475
- const md = await promises.readFile(mdPath, "utf8");
476
- if (md) {
477
- const matches = md.match(VERSION_REG_OF_MARKDOWN);
478
- if (matches?.length) {
479
- const versionInMarkdown = `## [${version}]`;
480
- isIn = matches.includes(versionInMarkdown);
481
- }
482
- }
483
- return isIn;
484
- }
485
- async function writeMarkdown(md, mdPath, regenerate = false) {
486
- let changelogMD;
487
- const changelogPrefix = "# Changelog";
488
- if (!regenerate && fs.existsSync(mdPath)) {
489
- changelogMD = await promises.readFile(mdPath, "utf8");
490
- if (!changelogMD.startsWith(changelogPrefix)) {
491
- changelogMD = `${changelogPrefix}
492
-
493
- ${changelogMD}`;
494
- }
495
- } else {
496
- changelogMD = `${changelogPrefix}
497
-
498
- `;
499
- }
500
- const lastEntry = changelogMD.match(/^###?\s+.*$/m);
501
- if (lastEntry) {
502
- changelogMD = `${changelogMD.slice(0, lastEntry.index) + md}
503
-
504
- ${changelogMD.slice(lastEntry.index)}`;
505
- } else {
506
- changelogMD += `
507
- ${md}
508
-
509
- `;
510
- }
511
- await promises.writeFile(mdPath, changelogMD);
512
- }
513
-
514
- async function getChangelogMarkdown(options) {
515
- const opts = await createOptions(options);
516
- const gitCommits = await getGitCommits(opts.from, opts.to);
517
- const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github);
518
- const markdown = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
519
- return markdown;
520
- }
521
- async function getTotalChangelogMarkdown(options, showProgress = true) {
522
- const opts = await createOptions(options);
523
- let bar = null;
524
- if (showProgress) {
525
- bar = new cliProgress.SingleBar(
526
- { format: "generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}" },
527
- cliProgress.Presets.shades_classic
528
- );
529
- }
530
- const tags = getFromToTags(opts.tags);
531
- if (tags.length === 0) {
532
- return getChangelogMarkdown(opts);
533
- }
534
- bar?.start(tags.length, 0);
535
- let markdown = "";
536
- const resolvedLogins = /* @__PURE__ */ new Map();
537
- for await (const [index, tag] of tags.entries()) {
538
- const { from, to } = tag;
539
- const gitCommits = await getGitCommits(from, to);
540
- const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github, resolvedLogins);
541
- const nextMd = generateMarkdown({ commits, options: { ...opts, from, to }, showTitle: true, contributors });
542
- markdown = `${nextMd}
543
-
544
- ${markdown}`;
545
- bar?.update(index + 1);
546
- }
547
- bar?.stop();
548
- return markdown;
549
- }
550
- async function generateChangelog(options) {
551
- const opts = await createOptions(options);
552
- const existContent = await isVersionInMarkdown(opts.to, opts.output);
553
- if (!opts.regenerate && existContent)
554
- return;
555
- const markdown = await getChangelogMarkdown(opts);
556
- await writeMarkdown(markdown, opts.output, opts.regenerate);
557
- }
558
- async function generateTotalChangelog(options, showProgress = true) {
559
- const opts = await createOptions(options);
560
- const markdown = await getTotalChangelogMarkdown(opts, showProgress);
561
- await writeMarkdown(markdown, opts.output, true);
562
- }
563
-
564
- exports.generateChangelog = generateChangelog;
565
- exports.generateTotalChangelog = generateTotalChangelog;
566
- exports.getChangelogMarkdown = getChangelogMarkdown;
567
- exports.getTotalChangelogMarkdown = getTotalChangelogMarkdown;
1
+ module.exports = require("/Users/soybean/Web/Projects/SoybeanJS/changelog/node_modules/.pnpm/jiti@1.19.3/node_modules/jiti/lib/index.js")(null, { interopDefault: true, esmResolve: true })("/Users/soybean/Web/Projects/SoybeanJS/changelog/src/index.ts")
package/dist/index.d.ts CHANGED
@@ -1,102 +1 @@
1
- /**
2
- * github config
3
- */
4
- interface GithubConfig {
5
- /**
6
- * the github repository name
7
- * @example soybeanjs/changelog
8
- */
9
- repo: string;
10
- /**
11
- * the github token
12
- */
13
- token: string;
14
- }
15
- interface ChangelogOption {
16
- /**
17
- * the directory of the project
18
- * @default process.cwd()
19
- */
20
- cwd: string;
21
- /**
22
- * the commit scope types
23
- */
24
- types: Record<string, string>;
25
- /**
26
- * github config
27
- */
28
- github: GithubConfig;
29
- /**
30
- * the commit hash or tag
31
- */
32
- from: string;
33
- /**
34
- * the commit hash or tag
35
- */
36
- to: string;
37
- /**
38
- * the whole commit tags
39
- */
40
- tags: string[];
41
- /**
42
- * the commit tag and date map
43
- */
44
- tagDateMap: Map<string, string>;
45
- /**
46
- * Whether to capitalize the first letter of the commit type
47
- */
48
- capitalize: boolean;
49
- /**
50
- * Use emojis in section titles
51
- * @default true
52
- */
53
- emoji: boolean;
54
- /**
55
- * the section titles
56
- */
57
- titles: {
58
- /**
59
- * the title of breaking changes section
60
- */
61
- breakingChanges: string;
62
- };
63
- /**
64
- * the output file path of the changelog
65
- */
66
- output: string;
67
- /**
68
- * Whether to regenerate the changelog if it already exists
69
- * @example the changelog already exists the content of v0.0.1, but you want to regenerate it
70
- */
71
- regenerate: boolean;
72
- /**
73
- * version from package.json, with prefix "v"
74
- * @description if the options "to" is not specified, the version will be used
75
- */
76
- newVersion: string;
77
- }
78
-
79
- /**
80
- * get the changelog markdown by two git tags
81
- * @param options the changelog options
82
- */
83
- declare function getChangelogMarkdown(options?: Partial<ChangelogOption>): Promise<string>;
84
- /**
85
- * get the changelog markdown by the total git tags
86
- * @param options the changelog options
87
- * @param showProgress whither show the progress bar
88
- */
89
- declare function getTotalChangelogMarkdown(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<string>;
90
- /**
91
- * generate the changelog markdown by two git tags
92
- * @param options the changelog options
93
- */
94
- declare function generateChangelog(options?: Partial<ChangelogOption>): Promise<void>;
95
- /**
96
- * generate the changelog markdown by the total git tags
97
- * @param options the changelog options
98
- * @param showProgress whither show the progress bar
99
- */
100
- declare function generateTotalChangelog(options?: Partial<ChangelogOption>, showProgress?: boolean): Promise<void>;
101
-
102
- export { ChangelogOption, generateChangelog, generateTotalChangelog, getChangelogMarkdown, getTotalChangelogMarkdown };
1
+ export * from "/Users/soybean/Web/Projects/SoybeanJS/changelog/src/index";
package/dist/index.mjs CHANGED
@@ -1,558 +1,9 @@
1
- import { SingleBar, Presets } from 'cli-progress';
2
- import { readFile, writeFile } from 'fs/promises';
3
- import { ofetch } from 'ofetch';
4
- import dayjs from 'dayjs';
5
- import { existsSync } from 'fs';
6
- import { convert } from 'convert-gitmoji';
1
+ import jiti from "file:///Users/soybean/Web/Projects/SoybeanJS/changelog/node_modules/.pnpm/jiti@1.19.3/node_modules/jiti/lib/index.js";
7
2
 
8
- async function execCommand(cmd, args, options) {
9
- const { execa } = await import('execa');
10
- const res = await execa(cmd, args, options);
11
- return res?.stdout?.trim() || "";
12
- }
13
- function notNullish(v) {
14
- return v !== null && v !== void 0;
15
- }
16
- function partition(array, ...filters) {
17
- const result = new Array(filters.length + 1).fill(null).map(() => []);
18
- array.forEach((e, idx, arr) => {
19
- let i = 0;
20
- for (const filter of filters) {
21
- if (filter(e, idx, arr)) {
22
- result[i].push(e);
23
- return;
24
- }
25
- i += 1;
26
- }
27
- result[i].push(e);
28
- });
29
- return result;
30
- }
31
- function groupBy(items, key, groups = {}) {
32
- for (const item of items) {
33
- const v = item[key];
34
- groups[v] = groups[v] || [];
35
- groups[v].push(item);
36
- }
37
- return groups;
38
- }
39
- function capitalize(str) {
40
- return str.charAt(0).toUpperCase() + str.slice(1);
41
- }
42
- function join(array, glue = ", ", finalGlue = " and ") {
43
- if (!array || array.length === 0)
44
- return "";
45
- if (array.length === 1)
46
- return array[0];
47
- if (array.length === 2)
48
- return array.join(finalGlue);
49
- return `${array.slice(0, -1).join(glue)}${finalGlue}${array.slice(-1)}`;
50
- }
3
+ /** @type {import("/Users/soybean/Web/Projects/SoybeanJS/changelog/src/index")} */
4
+ const _module = jiti(null, { interopDefault: true, esmResolve: true })("/Users/soybean/Web/Projects/SoybeanJS/changelog/src/index.ts");
51
5
 
52
- const VERSION_REG = /v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
53
- const VERSION_REG_OF_MARKDOWN = /## \[v\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?]/g;
54
- const VERSION_WITH_RELEASE = /release\sv\d+\.\d+\.\d+(-(beta|alpha)\.\d+)?/;
55
-
56
- async function getTotalGitTags() {
57
- const tagStr = await execCommand("git", ["--no-pager", "tag", "-l", "--sort=creatordate"]);
58
- const tags = tagStr.split("\n");
59
- return tags;
60
- }
61
- async function getTagDateMap() {
62
- const tagDateStr = await execCommand("git", [
63
- "--no-pager",
64
- "log",
65
- "--tags",
66
- "--simplify-by-decoration",
67
- "--pretty=format:%ci %d"
68
- ]);
69
- const TAG_MARK = "tag: ";
70
- const map = /* @__PURE__ */ new Map();
71
- const dates = tagDateStr.split("\n").filter((item) => item.includes(TAG_MARK));
72
- dates.forEach((item) => {
73
- const [dateStr, tagStr] = item.split(TAG_MARK);
74
- const date = dayjs(dateStr).format("YYYY-MM-DD");
75
- const tag = tagStr.match(VERSION_REG)?.[0];
76
- if (tag && date) {
77
- map.set(tag.trim(), date);
78
- }
79
- });
80
- return map;
81
- }
82
- function getFromToTags(tags) {
83
- const result = [];
84
- tags.forEach((tag, index) => {
85
- if (index < tags.length - 1) {
86
- result.push({ from: tag, to: tags[index + 1] });
87
- }
88
- });
89
- return result;
90
- }
91
- async function getLastGitTag(delta = 0) {
92
- const tags = await getTotalGitTags();
93
- return tags[tags.length + delta - 1];
94
- }
95
- async function getGitMainBranchName() {
96
- const main = await execCommand("git", ["rev-parse", "--abbrev-ref", "HEAD"]);
97
- return main;
98
- }
99
- async function getCurrentGitBranch() {
100
- const tag = await execCommand("git", ["tag", "--points-at", "HEAD"]);
101
- const main = getGitMainBranchName();
102
- return tag || main;
103
- }
104
- async function getGitHubRepo() {
105
- const url = await execCommand("git", ["config", "--get", "remote.origin.url"]);
106
- const match = url.match(/github\.com[/:]([\w\d._-]+?)\/([\w\d._-]+?)(\.git)?$/i);
107
- if (!match) {
108
- throw new Error(`Can not parse GitHub repo from url ${url}`);
109
- }
110
- return `${match[1]}/${match[2]}`;
111
- }
112
- function getFirstGitCommit() {
113
- return execCommand("git", ["rev-list", "--max-parents=0", "HEAD"]);
114
- }
115
- async function getGitDiff(from, to = "HEAD") {
116
- const rawGit = await execCommand("git", [
117
- "--no-pager",
118
- "log",
119
- `${from ? `${from}...` : ""}${to}`,
120
- '--pretty="----%n%s|%h|%an|%ae%n%b"',
121
- "--name-status"
122
- ]);
123
- const rwaGitLines = rawGit.split("----\n").splice(1);
124
- const gitCommits = rwaGitLines.map((line) => {
125
- const [firstLine, ...body] = line.split("\n");
126
- const [message, shortHash, authorName, authorEmail] = firstLine.split("|");
127
- const gitCommit = {
128
- message,
129
- shortHash,
130
- author: { name: authorName, email: authorEmail },
131
- body: body.join("\n")
132
- };
133
- return gitCommit;
134
- });
135
- return gitCommits;
136
- }
137
- function parseGitCommit(commit) {
138
- const ConventionalCommitRegex = /(?<type>[a-z]+)(\((?<scope>.+)\))?(?<breaking>!)?: (?<description>.+)/i;
139
- const CoAuthoredByRegex = /co-authored-by:\s*(?<name>.+)(<(?<email>.+)>)/gim;
140
- const PullRequestRE = /\([a-z]*(#\d+)\s*\)/gm;
141
- const IssueRE = /(#\d+)/gm;
142
- const match = commit.message.match(ConventionalCommitRegex);
143
- if (!match?.groups) {
144
- return null;
145
- }
146
- const type = match.groups.type;
147
- const scope = match.groups.scope || "";
148
- const isBreaking = Boolean(match.groups.breaking);
149
- let description = match.groups.description;
150
- const references = [];
151
- for (const m of description.matchAll(PullRequestRE)) {
152
- references.push({ type: "pull-request", value: m[1] });
153
- }
154
- for (const m of description.matchAll(IssueRE)) {
155
- if (!references.some((i) => i.value === m[1])) {
156
- references.push({ type: "issue", value: m[1] });
157
- }
158
- }
159
- references.push({ value: commit.shortHash, type: "hash" });
160
- description = description.replace(PullRequestRE, "").trim();
161
- const authors = [commit.author];
162
- const matches = commit.body.matchAll(CoAuthoredByRegex);
163
- for (const $match of matches) {
164
- const { name = "", email = "" } = $match.groups || {};
165
- const author = {
166
- name: name.trim(),
167
- email: email.trim()
168
- };
169
- authors.push(author);
170
- }
171
- return {
172
- ...commit,
173
- authors,
174
- resolvedAuthors: [],
175
- description,
176
- type,
177
- scope,
178
- references,
179
- isBreaking
180
- };
181
- }
182
- async function getGitCommits(from, to = "HEAD") {
183
- const rwaGitCommits = await getGitDiff(from, to);
184
- const commits = rwaGitCommits.map((commit) => parseGitCommit(commit)).filter(notNullish);
185
- return commits;
186
- }
187
- function getHeaders(githubToken) {
188
- return {
189
- accept: "application/vnd.github.v3+json",
190
- authorization: `token ${githubToken}`
191
- };
192
- }
193
- async function getResolvedAuthorLogin(github, commitHashes, email) {
194
- let login = "";
195
- try {
196
- const data = await ofetch(`https://ungh.cc/users/find/${email}`);
197
- login = data?.user?.username || "";
198
- } catch (e) {
199
- console.log("e: ", e);
200
- }
201
- if (login) {
202
- return login;
203
- }
204
- const { repo, token } = github;
205
- if (!token) {
206
- return login;
207
- }
208
- if (commitHashes.length) {
209
- try {
210
- const data = await ofetch(`https://api.github.com/repos/${repo}/commits/${commitHashes[0]}`, {
211
- headers: getHeaders(token)
212
- });
213
- login = data?.author?.login || "";
214
- } catch (e) {
215
- console.log("e: ", e);
216
- }
217
- }
218
- if (login) {
219
- return login;
220
- }
221
- try {
222
- const data = await ofetch(`https://api.github.com/search/users?q=${encodeURIComponent(email)}`, {
223
- headers: getHeaders(token)
224
- });
225
- login = data.items[0].login;
226
- } catch (e) {
227
- console.log("e: ", e);
228
- }
229
- return login;
230
- }
231
- async function getGitCommitsAndResolvedAuthors(commits, github, resolvedLogins) {
232
- const resultCommits = [];
233
- const map = /* @__PURE__ */ new Map();
234
- for await (const commit of commits) {
235
- const resolvedAuthors = [];
236
- for await (const [index, author] of commit.authors.entries()) {
237
- const { email, name } = author;
238
- if (email && name) {
239
- const commitHashes = [];
240
- if (index === 0) {
241
- commitHashes.push(commit.shortHash);
242
- }
243
- const resolvedAuthor = {
244
- name,
245
- email,
246
- commits: commitHashes,
247
- login: ""
248
- };
249
- if (!resolvedLogins?.has(email)) {
250
- const login = await getResolvedAuthorLogin(github, commitHashes, email);
251
- resolvedAuthor.login = login;
252
- resolvedLogins?.set(email, login);
253
- } else {
254
- const login = resolvedLogins?.get(email) || "";
255
- resolvedAuthor.login = login;
256
- }
257
- resolvedAuthors.push(resolvedAuthor);
258
- if (!map.has(email)) {
259
- map.set(email, resolvedAuthor);
260
- }
261
- }
262
- }
263
- const resultCommit = { ...commit, resolvedAuthors };
264
- resultCommits.push(resultCommit);
265
- }
266
- return {
267
- commits: resultCommits,
268
- contributors: Array.from(map.values())
269
- };
270
- }
271
-
272
- function createDefaultOptions() {
273
- const cwd = process.cwd();
274
- const options = {
275
- cwd,
276
- types: {
277
- feat: "\u{1F680} Features",
278
- fix: "\u{1F41E} Bug Fixes",
279
- perf: "\u{1F525} Performance",
280
- refactor: "\u{1F485} Refactors",
281
- docs: "\u{1F4D6} Documentation",
282
- build: "\u{1F4E6} Build",
283
- types: "\u{1F30A} Types",
284
- chore: "\u{1F3E1} Chore",
285
- examples: "\u{1F3C0} Examples",
286
- test: "\u2705 Tests",
287
- style: "\u{1F3A8} Styles",
288
- ci: "\u{1F916} CI"
289
- },
290
- github: {
291
- repo: "",
292
- token: process.env.GITHUB_TOKEN || ""
293
- },
294
- from: "",
295
- to: "",
296
- tags: [],
297
- tagDateMap: /* @__PURE__ */ new Map(),
298
- capitalize: false,
299
- emoji: true,
300
- titles: {
301
- breakingChanges: "\u{1F6A8} Breaking Changes"
302
- },
303
- output: "CHANGELOG.md",
304
- regenerate: false,
305
- newVersion: ""
306
- };
307
- return options;
308
- }
309
- async function getVersionFromPkgJson(cwd) {
310
- let newVersion = "";
311
- try {
312
- const pkgJson = await readFile(`${cwd}/package.json`, "utf-8");
313
- const pkg = JSON.parse(pkgJson);
314
- newVersion = pkg?.version || "";
315
- } catch {
316
- }
317
- return {
318
- newVersion
319
- };
320
- }
321
- async function createOptions(options) {
322
- var _a;
323
- const opts = createDefaultOptions();
324
- Object.assign(opts, options);
325
- const { newVersion } = await getVersionFromPkgJson(opts.cwd);
326
- (_a = opts.github).repo || (_a.repo = await getGitHubRepo());
327
- opts.newVersion || (opts.newVersion = `v${newVersion}`);
328
- opts.from || (opts.from = await getLastGitTag());
329
- opts.to || (opts.to = await getCurrentGitBranch());
330
- if (opts.to === opts.from) {
331
- const lastTag = await getLastGitTag(-1);
332
- const firstCommit = await getFirstGitCommit();
333
- opts.from = lastTag || firstCommit;
334
- }
335
- opts.tags = await getTotalGitTags();
336
- opts.tagDateMap = await getTagDateMap();
337
- return opts;
338
- }
339
-
340
- function formatReferences(references, githubRepo, type) {
341
- const refs = references.filter((i) => {
342
- if (type === "issues")
343
- return i.type === "issue" || i.type === "pull-request";
344
- return i.type === "hash";
345
- }).map((ref) => {
346
- if (!githubRepo)
347
- return ref.value;
348
- if (ref.type === "pull-request" || ref.type === "issue")
349
- return `https://github.com/${githubRepo}/issues/${ref.value.slice(1)}`;
350
- return `[<samp>(${ref.value.slice(0, 5)})</samp>](https://github.com/${githubRepo}/commit/${ref.value})`;
351
- });
352
- const referencesString = join(refs).trim();
353
- if (type === "issues")
354
- return referencesString && `in ${referencesString}`;
355
- return referencesString;
356
- }
357
- function formatLine(commit, options) {
358
- const prRefs = formatReferences(commit.references, options.github.repo, "issues");
359
- const hashRefs = formatReferences(commit.references, options.github.repo, "hash");
360
- let authors = join([...new Set(commit.resolvedAuthors.map((i) => i.login ? `@${i.login}` : `**${i.name}**`))]).trim();
361
- if (authors) {
362
- authors = `by ${authors}`;
363
- }
364
- let refs = [authors, prRefs, hashRefs].filter((i) => i?.trim()).join(" ");
365
- if (refs) {
366
- refs = `&nbsp;-&nbsp; ${refs}`;
367
- }
368
- const description = options.capitalize ? capitalize(commit.description) : commit.description;
369
- return [description, refs].filter((i) => i?.trim()).join(" ");
370
- }
371
- function formatTitle(name, options) {
372
- const emojisRE = /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g;
373
- let formatName = name.trim();
374
- if (!options.emoji) {
375
- formatName = name.replace(emojisRE, "").trim();
376
- }
377
- return `### &nbsp;&nbsp;&nbsp;${formatName}`;
378
- }
379
- function formatSection(commits, sectionName, options) {
380
- if (!commits.length)
381
- return [];
382
- const lines = ["", formatTitle(sectionName, options), ""];
383
- const scopes = groupBy(commits, "scope");
384
- let useScopeGroup = true;
385
- if (!Object.entries(scopes).some(([k, v]) => k && v.length > 1)) {
386
- useScopeGroup = false;
387
- }
388
- Object.keys(scopes).sort().forEach((scope) => {
389
- let padding = "";
390
- let prefix = "";
391
- const scopeText = `**${scope}**`;
392
- if (scope && useScopeGroup) {
393
- lines.push(`- ${scopeText}:`);
394
- padding = " ";
395
- } else if (scope) {
396
- prefix = `${scopeText}: `;
397
- }
398
- lines.push(...scopes[scope].reverse().map((commit) => `${padding}- ${prefix}${formatLine(commit, options)}`));
399
- });
400
- return lines;
401
- }
402
- function getUserGithub(userName) {
403
- const githubUrl = `https://github.com/${userName}`;
404
- return githubUrl;
405
- }
406
- function getGitUserAvatar(userName) {
407
- const githubUrl = getUserGithub(userName);
408
- const avatarUrl = `${githubUrl}.png?size=48`;
409
- return avatarUrl;
410
- }
411
- function createContributorLine(contributors) {
412
- let loginLine = "";
413
- let unLoginLine = "";
414
- contributors.forEach((contributor, index) => {
415
- const { name, email, login } = contributor;
416
- if (!login) {
417
- let line = `[${name}](mailto:${email})`;
418
- if (index < contributors.length - 1) {
419
- line += ",&nbsp;";
420
- }
421
- unLoginLine += line;
422
- } else {
423
- const githubUrl = getUserGithub(login);
424
- const avatar = getGitUserAvatar(login);
425
- loginLine += `[![${login}](${avatar})](${githubUrl})&nbsp;&nbsp;`;
426
- }
427
- });
428
- return `${loginLine}
429
- ${unLoginLine}`;
430
- }
431
- function generateMarkdown(params) {
432
- const { options, showTitle, contributors } = params;
433
- const commits = params.commits.filter((commit) => commit.description.match(VERSION_WITH_RELEASE) === null);
434
- const lines = [];
435
- const isNewVersion = !VERSION_REG.test(options.to);
436
- const version = isNewVersion ? options.newVersion : options.to;
437
- const url = `https://github.com/${options.github.repo}/compare/${options.from}...${version}`;
438
- if (showTitle) {
439
- const date = isNewVersion ? dayjs().format("YY-MM-DD") : options.tagDateMap.get(options.to);
440
- let title = `## [${version}](${url})`;
441
- if (date) {
442
- title += ` (${date})`;
443
- }
444
- lines.push(title);
445
- }
446
- const [breaking, changes] = partition(commits, (c) => c.isBreaking);
447
- const group = groupBy(changes, "type");
448
- lines.push(...formatSection(breaking, options.titles.breakingChanges, options));
449
- for (const type of Object.keys(options.types)) {
450
- const items = group[type] || [];
451
- lines.push(...formatSection(items, options.types[type], options));
452
- }
453
- if (!lines.length) {
454
- lines.push("*No significant changes*");
455
- }
456
- if (!showTitle) {
457
- lines.push("", `##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](${url})`);
458
- }
459
- if (showTitle) {
460
- lines.push("", "### &nbsp;&nbsp;&nbsp;\u2764\uFE0F Contributors", "");
461
- const contributorLine = createContributorLine(contributors);
462
- lines.push(contributorLine);
463
- }
464
- const md = convert(lines.join("\n").trim(), true);
465
- return md;
466
- }
467
- async function isVersionInMarkdown(version, mdPath) {
468
- let isIn = false;
469
- const md = await readFile(mdPath, "utf8");
470
- if (md) {
471
- const matches = md.match(VERSION_REG_OF_MARKDOWN);
472
- if (matches?.length) {
473
- const versionInMarkdown = `## [${version}]`;
474
- isIn = matches.includes(versionInMarkdown);
475
- }
476
- }
477
- return isIn;
478
- }
479
- async function writeMarkdown(md, mdPath, regenerate = false) {
480
- let changelogMD;
481
- const changelogPrefix = "# Changelog";
482
- if (!regenerate && existsSync(mdPath)) {
483
- changelogMD = await readFile(mdPath, "utf8");
484
- if (!changelogMD.startsWith(changelogPrefix)) {
485
- changelogMD = `${changelogPrefix}
486
-
487
- ${changelogMD}`;
488
- }
489
- } else {
490
- changelogMD = `${changelogPrefix}
491
-
492
- `;
493
- }
494
- const lastEntry = changelogMD.match(/^###?\s+.*$/m);
495
- if (lastEntry) {
496
- changelogMD = `${changelogMD.slice(0, lastEntry.index) + md}
497
-
498
- ${changelogMD.slice(lastEntry.index)}`;
499
- } else {
500
- changelogMD += `
501
- ${md}
502
-
503
- `;
504
- }
505
- await writeFile(mdPath, changelogMD);
506
- }
507
-
508
- async function getChangelogMarkdown(options) {
509
- const opts = await createOptions(options);
510
- const gitCommits = await getGitCommits(opts.from, opts.to);
511
- const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github);
512
- const markdown = generateMarkdown({ commits, options: opts, showTitle: true, contributors });
513
- return markdown;
514
- }
515
- async function getTotalChangelogMarkdown(options, showProgress = true) {
516
- const opts = await createOptions(options);
517
- let bar = null;
518
- if (showProgress) {
519
- bar = new SingleBar(
520
- { format: "generate total changelog: [{bar}] {percentage}% | ETA: {eta}s | {value}/{total}" },
521
- Presets.shades_classic
522
- );
523
- }
524
- const tags = getFromToTags(opts.tags);
525
- if (tags.length === 0) {
526
- return getChangelogMarkdown(opts);
527
- }
528
- bar?.start(tags.length, 0);
529
- let markdown = "";
530
- const resolvedLogins = /* @__PURE__ */ new Map();
531
- for await (const [index, tag] of tags.entries()) {
532
- const { from, to } = tag;
533
- const gitCommits = await getGitCommits(from, to);
534
- const { commits, contributors } = await getGitCommitsAndResolvedAuthors(gitCommits, opts.github, resolvedLogins);
535
- const nextMd = generateMarkdown({ commits, options: { ...opts, from, to }, showTitle: true, contributors });
536
- markdown = `${nextMd}
537
-
538
- ${markdown}`;
539
- bar?.update(index + 1);
540
- }
541
- bar?.stop();
542
- return markdown;
543
- }
544
- async function generateChangelog(options) {
545
- const opts = await createOptions(options);
546
- const existContent = await isVersionInMarkdown(opts.to, opts.output);
547
- if (!opts.regenerate && existContent)
548
- return;
549
- const markdown = await getChangelogMarkdown(opts);
550
- await writeMarkdown(markdown, opts.output, opts.regenerate);
551
- }
552
- async function generateTotalChangelog(options, showProgress = true) {
553
- const opts = await createOptions(options);
554
- const markdown = await getTotalChangelogMarkdown(opts, showProgress);
555
- await writeMarkdown(markdown, opts.output, true);
556
- }
557
-
558
- export { generateChangelog, generateTotalChangelog, getChangelogMarkdown, getTotalChangelogMarkdown };
6
+ export const getChangelogMarkdown = _module.getChangelogMarkdown;
7
+ export const getTotalChangelogMarkdown = _module.getTotalChangelogMarkdown;
8
+ export const generateChangelog = _module.generateChangelog;
9
+ export const generateTotalChangelog = _module.generateTotalChangelog;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soybeanjs/changelog",
3
- "version": "0.0.7",
3
+ "version": "0.3.1",
4
4
  "description": "generate changelog form git tags and commits for github",
5
5
  "author": {
6
6
  "name": "Soybean",
@@ -35,15 +35,15 @@
35
35
  "cli-progress": "3.12.0",
36
36
  "convert-gitmoji": "0.1.3",
37
37
  "dayjs": "1.11.9",
38
- "execa": "7.1.1",
39
- "ofetch": "1.1.1"
38
+ "execa": "8.0.1",
39
+ "ofetch": "1.2.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@soybeanjs/cli": "0.6.2",
42
+ "@soybeanjs/cli": "0.6.7",
43
43
  "@types/cli-progress": "3.11.0",
44
- "@types/node": "20.4.5",
45
- "eslint": "8.45.0",
46
- "eslint-config-soybeanjs": "0.5.3",
44
+ "@types/node": "20.5.2",
45
+ "eslint": "8.47.0",
46
+ "eslint-config-soybeanjs": "0.5.5",
47
47
  "simple-git-hooks": "2.9.0",
48
48
  "tsx": "3.12.7",
49
49
  "typescript": "5.1.6",
@@ -53,18 +53,17 @@
53
53
  "commit-msg": "pnpm soy git-commit-verify",
54
54
  "pre-commit": "pnpm typecheck && pnpm soy lint-staged"
55
55
  },
56
- "soybean": {
57
- "useSoybeanToken": true
58
- },
59
56
  "scripts": {
60
- "build": "pnpm typecheck && unbuild",
57
+ "build": "pnpm typecheck && unbuild && pnpm build-pkg",
58
+ "build-pkg": "pnpm -r --filter='./packages/*' run build",
59
+ "stub": "pnpm unbuild --stub",
61
60
  "lint": "eslint . --fix",
62
61
  "format": "soy prettier-write",
63
62
  "commit": "soy git-commit",
64
63
  "cleanup": "soy cleanup",
65
64
  "ncu": "soy ncu",
66
65
  "publish-pkg": "pnpm -r publish --access public",
67
- "typecheck": "tsc --noEmit",
66
+ "typecheck": "tsc --noEmit --skipLibCheck",
68
67
  "release": "soy release && pnpm build && pnpm publish-pkg"
69
68
  }
70
69
  }