-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathchangelog.ts
85 lines (76 loc) · 1.97 KB
/
changelog.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import {
type ConventionalChangelogCommit as Commit,
parser,
toConventionalChangelogFormat,
} from "@conventional-commits/parser";
import { associateWith, mapNotNullish } from "@std/collections";
export type { Commit };
export type ChangeLog<
T extends string = string,
> = {
[K in T | "BREAKING CHANGE"]: ChangeLogRecord[];
};
export interface ChangeLogRecord {
scope: string | null;
text: string;
}
export interface ChangeLogOptions<
T extends string = string,
> {
types: T[];
scope?: string;
}
export function curateChangeLog<
T extends string = string,
>(
messages: string[],
options: ChangeLogOptions<T>,
): ChangeLog<T> {
const { scope, types } = options;
let commits = mapNotNullish(messages, tryParseCommit);
if (scope) {
commits = commits
.filter((it) => it.scope?.startsWith(scope))
.map((it): Commit => ({ ...it, scope: flatten(it.scope, scope) }));
}
return {
...associateWith(
types,
(type) =>
commits
.filter((it) => it.type === type)
.map((it): ChangeLogRecord => ({
scope: it.scope,
text: it.subject,
})),
),
"BREAKING CHANGE": commits
.flatMap(curateBreakingChange)
.map((it): ChangeLogRecord => ({ scope: null, text: it })),
} as ChangeLog<T>;
}
function flatten(scope: string | null, root?: string): string | null {
if (!scope) {
return null;
}
if (!root) {
return scope;
}
const sliced = scope.slice(root.length);
return sliced.length ? sliced : null;
}
export function tryParseCommit(message: string): Commit | undefined {
try {
return toConventionalChangelogFormat(parser(message));
} catch {
return undefined;
}
}
export function parseCommit(message: string): Commit {
return toConventionalChangelogFormat(parser(message));
}
export function curateBreakingChange(commit: Commit): string[] {
return commit.notes
.filter((note) => note.title === "BREAKING CHANGE")
.map((note) => note.text);
}