fork-version 4.1.9 → 5.0.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cli.d.ts +1 -1
  3. package/dist/cli.js +54 -193
  4. package/dist/commands/inspect.d.ts +9 -0
  5. package/dist/commands/inspect.js +41 -0
  6. package/dist/commands/main.d.ts +16 -0
  7. package/dist/commands/main.js +30 -0
  8. package/dist/commands/validate-config.d.ts +6 -0
  9. package/dist/commands/validate-config.js +11 -0
  10. package/dist/commit-parser/commit-parser.d.ts +114 -0
  11. package/dist/commit-parser/commit-parser.js +327 -0
  12. package/dist/commit-parser/filter-reverted-commits.d.ts +17 -0
  13. package/dist/commit-parser/filter-reverted-commits.js +34 -0
  14. package/dist/commit-parser/options.d.ts +74 -0
  15. package/dist/commit-parser/options.js +70 -0
  16. package/dist/commit-parser/parser-error.js +14 -0
  17. package/dist/commit-parser/types.d.ts +53 -0
  18. package/dist/config/changelog-preset-config.js +41 -0
  19. package/dist/config/cli-arguments.d.ts +109 -0
  20. package/dist/config/cli-arguments.js +141 -0
  21. package/dist/config/defaults.js +38 -0
  22. package/dist/config/define-config.d.ts +9 -0
  23. package/dist/config/define-config.js +9 -0
  24. package/dist/config/load-config.js +45 -0
  25. package/dist/config/merge-files.js +12 -0
  26. package/dist/config/schema.d.ts +50 -0
  27. package/dist/config/schema.js +61 -0
  28. package/dist/config/types.d.ts +279 -0
  29. package/dist/config/user-config.d.ts +6 -0
  30. package/dist/config/user-config.js +50 -0
  31. package/dist/detect-git-host/detect-git-host.js +35 -0
  32. package/dist/detect-git-host/host-azure-devops.js +28 -0
  33. package/dist/detect-git-host/host-bitbucket.js +28 -0
  34. package/dist/detect-git-host/host-github.js +32 -0
  35. package/dist/detect-git-host/host-gitlab.js +48 -0
  36. package/dist/files/arm-bicep.js +44 -0
  37. package/dist/files/file-manager.d.ts +47 -0
  38. package/dist/files/file-manager.js +65 -0
  39. package/dist/files/install-shield-ism.js +59 -0
  40. package/dist/files/json-package.js +68 -0
  41. package/dist/files/ms-build-project.js +59 -0
  42. package/dist/files/plain-text.js +35 -0
  43. package/dist/files/yaml-package.js +61 -0
  44. package/dist/index.d.ts +21 -646
  45. package/dist/index.js +19 -10
  46. package/dist/process/changelog.d.ts +7 -0
  47. package/dist/process/changelog.js +69 -0
  48. package/dist/process/commit.d.ts +9 -0
  49. package/dist/process/commit.js +22 -0
  50. package/dist/process/get-commits.d.ts +14 -0
  51. package/dist/process/get-commits.js +25 -0
  52. package/dist/process/get-current-version.d.ts +13 -0
  53. package/dist/process/get-current-version.js +35 -0
  54. package/dist/process/get-next-version.d.ts +21 -0
  55. package/dist/process/get-next-version.js +72 -0
  56. package/dist/process/tag.d.ts +8 -0
  57. package/dist/process/tag.js +15 -0
  58. package/dist/services/git.d.ts +141 -0
  59. package/dist/services/git.js +236 -0
  60. package/dist/services/logger.d.ts +18 -0
  61. package/dist/services/logger.js +35 -0
  62. package/dist/utils/clean-tag.js +21 -0
  63. package/dist/utils/escape-regex.js +17 -0
  64. package/dist/utils/file-state.js +19 -0
  65. package/dist/utils/format-commit-message.js +13 -0
  66. package/dist/utils/parse-regexp-string.js +31 -0
  67. package/dist/utils/release-type.js +47 -0
  68. package/dist/utils/trim-string-array.js +20 -0
  69. package/package.json +11 -29
  70. package/dist/chunk-KRGBUNRK.cjs +0 -2264
  71. package/dist/chunk-KRGBUNRK.cjs.map +0 -1
  72. package/dist/chunk-X4NB24VR.js +0 -2220
  73. package/dist/chunk-X4NB24VR.js.map +0 -1
  74. package/dist/cli.cjs +0 -205
  75. package/dist/cli.cjs.map +0 -1
  76. package/dist/cli.d.cts +0 -1
  77. package/dist/cli.js.map +0 -1
  78. package/dist/index.cjs +0 -80
  79. package/dist/index.cjs.map +0 -1
  80. package/dist/index.d.cts +0 -646
  81. package/dist/index.js.map +0 -1
@@ -0,0 +1,327 @@
1
+ import { createParserOptions } from "./options.js";
2
+ import { ParserError } from "./parser-error.js";
3
+ //#region src/commit-parser/commit-parser.ts
4
+ var CommitParser = class {
5
+ #options;
6
+ #logger;
7
+ constructor(userOptions) {
8
+ this.#options = createParserOptions(userOptions);
9
+ this.setLogger = this.setLogger.bind(this);
10
+ this.createCommit = this.createCommit.bind(this);
11
+ this.parseRawCommit = this.parseRawCommit.bind(this);
12
+ this.parseSubject = this.parseSubject.bind(this);
13
+ this.parseMerge = this.parseMerge.bind(this);
14
+ this.parseRevert = this.parseRevert.bind(this);
15
+ this.parseMentions = this.parseMentions.bind(this);
16
+ this.parseReferenceParts = this.parseReferenceParts.bind(this);
17
+ this.parseReferences = this.parseReferences.bind(this);
18
+ this.parseNotes = this.parseNotes.bind(this);
19
+ this.parseRawLines = this.parseRawLines.bind(this);
20
+ this.parse = this.parse.bind(this);
21
+ }
22
+ setLogger(logger) {
23
+ this.#logger = logger;
24
+ return this;
25
+ }
26
+ createCommit() {
27
+ return {
28
+ raw: "",
29
+ subject: "",
30
+ body: "",
31
+ hash: "",
32
+ refNames: "",
33
+ date: "",
34
+ name: "",
35
+ email: "",
36
+ type: "",
37
+ scope: "",
38
+ breakingChange: "",
39
+ title: "",
40
+ merge: null,
41
+ revert: null,
42
+ notes: [],
43
+ mentions: [],
44
+ references: [],
45
+ tags: []
46
+ };
47
+ }
48
+ /**
49
+ * Parse the raw commit message into its expected parts
50
+ * - subject
51
+ * - body
52
+ * - hash
53
+ * - date
54
+ * - name
55
+ * - email
56
+ *
57
+ * @throws {ParserError}
58
+ */
59
+ parseRawCommit(rawCommit) {
60
+ const parsedCommit = this.createCommit();
61
+ const parts = rawCommit.split(/\r?\n/);
62
+ if (parts.length < 6) throw new ParserError("Commit doesn't contain enough parts", rawCommit);
63
+ const email = parts.pop();
64
+ const name = parts.pop();
65
+ const date = parts.pop();
66
+ const refNames = parts.pop();
67
+ const hash = parts.pop();
68
+ if (email) parsedCommit.email = email.trim();
69
+ if (name) parsedCommit.name = name.trim();
70
+ if (date) {
71
+ parsedCommit.date = date.trim();
72
+ if (Number.isNaN(Date.parse(parsedCommit.date))) throw new ParserError("Unable to parse commit date", rawCommit);
73
+ }
74
+ if (refNames) {
75
+ parsedCommit.refNames = refNames.trim();
76
+ const TAG_REGEX = /tag:\s*(?<tag>.+?)[,)]/gi;
77
+ let tagMatch = null;
78
+ while (tagMatch = TAG_REGEX.exec(refNames)) {
79
+ const { tag = "" } = tagMatch.groups ?? {};
80
+ if (tag) parsedCommit.tags.push(tag);
81
+ }
82
+ }
83
+ if (hash) parsedCommit.hash = hash.trim();
84
+ const subject = parts.shift()?.trimStart();
85
+ if (subject) {
86
+ parsedCommit.subject = subject;
87
+ parsedCommit.raw = subject;
88
+ }
89
+ parsedCommit.body = parts.filter((line) => {
90
+ if (this.#options.commentPattern) return !this.#options.commentPattern.test(line.trim());
91
+ return true;
92
+ }).join("\n").trim();
93
+ const raw = parts.join("\n").trim();
94
+ if (raw) parsedCommit.raw += "\n" + raw;
95
+ return parsedCommit;
96
+ }
97
+ /**
98
+ * Parse the commit subject into its expected parts
99
+ * - type
100
+ * - scope (optional)
101
+ * - breaking change (optional)
102
+ * - title
103
+ *
104
+ * @throws {ParserError}
105
+ */
106
+ parseSubject(commit) {
107
+ if (!this.#options.subjectPattern) return false;
108
+ const subjectMatch = this.#options.subjectPattern.exec(commit.subject);
109
+ if (subjectMatch?.groups) {
110
+ const { type = "", scope = "", breakingChange = "", title = "" } = subjectMatch.groups;
111
+ if (!type || !title) throw new ParserError("Unable to parse commit subject", commit);
112
+ commit.type = type;
113
+ commit.scope = scope;
114
+ if (breakingChange) commit.breakingChange = breakingChange;
115
+ commit.title = title;
116
+ return true;
117
+ }
118
+ return false;
119
+ }
120
+ /**
121
+ * Parse merge information from the commit subject
122
+ * @example
123
+ * ```txt
124
+ * "Merge pull request #123 from fork-version/feature"
125
+ * ```
126
+ */
127
+ parseMerge(commit) {
128
+ if (!this.#options.mergePattern) return false;
129
+ const mergeMatch = this.#options.mergePattern.exec(commit.subject);
130
+ if (mergeMatch?.groups) {
131
+ const { id = "", source = "" } = mergeMatch.groups;
132
+ commit.merge = {
133
+ id,
134
+ source
135
+ };
136
+ return true;
137
+ }
138
+ return false;
139
+ }
140
+ /**
141
+ * Parse revert information from the commit body
142
+ * @example
143
+ * ```txt
144
+ * "Revert "feat: initial commit"
145
+ *
146
+ * This reverts commit 4a79e9e546b4020d2882b7810dc549fa71960f4f."
147
+ * ```
148
+ */
149
+ parseRevert(commit) {
150
+ if (!this.#options.revertPattern) return false;
151
+ const revertMatch = this.#options.revertPattern.exec(commit.raw);
152
+ if (revertMatch?.groups) {
153
+ const { hash = "", subject = "" } = revertMatch.groups;
154
+ commit.revert = {
155
+ hash,
156
+ subject
157
+ };
158
+ return true;
159
+ }
160
+ return false;
161
+ }
162
+ /**
163
+ * Search for mentions from the commit line
164
+ * @example
165
+ * ```txt
166
+ * "@fork-version"
167
+ * ```
168
+ */
169
+ parseMentions(line, outMentions) {
170
+ if (!this.#options.mentionPattern) return false;
171
+ const mentionRegex = new RegExp(this.#options.mentionPattern, "g");
172
+ let foundMention = false;
173
+ let mentionMatch;
174
+ while (mentionMatch = mentionRegex.exec(line)) {
175
+ if (!mentionMatch) break;
176
+ const { username = "" } = mentionMatch.groups ?? {};
177
+ outMentions.add(username);
178
+ foundMention = true;
179
+ }
180
+ return foundMention;
181
+ }
182
+ /**
183
+ * Search for references from the commit line
184
+ * @example
185
+ * ```txt
186
+ * "#1234"
187
+ * "owner/repo#1234"
188
+ * ```
189
+ */
190
+ parseReferenceParts(referenceText, action) {
191
+ if (!this.#options.issuePattern) return void 0;
192
+ const references = [];
193
+ const issueRegex = new RegExp(this.#options.issuePattern, "gi");
194
+ let issueMatch;
195
+ while (issueMatch = issueRegex.exec(referenceText)) {
196
+ if (!issueMatch) break;
197
+ const { repository = "", prefix = "", issue = "" } = issueMatch.groups ?? {};
198
+ const reference = {
199
+ prefix,
200
+ issue,
201
+ action,
202
+ owner: null,
203
+ repository: null
204
+ };
205
+ if (repository) {
206
+ const slashIndex = repository.indexOf("/");
207
+ if (slashIndex !== -1) {
208
+ reference.owner = repository.slice(0, slashIndex);
209
+ reference.repository = repository.slice(slashIndex + 1);
210
+ } else reference.repository = repository;
211
+ }
212
+ references.push(reference);
213
+ }
214
+ if (references.length > 0) return references;
215
+ }
216
+ /**
217
+ * Search for actions and references from the commit line
218
+ * @example
219
+ * ```txt
220
+ * "Closes #1234"
221
+ * "fixes owner/repo#1234"
222
+ * ```
223
+ */
224
+ parseReferences(line, outReferences) {
225
+ if (!this.#options.referenceActionPattern || !this.#options.issuePattern) return false;
226
+ const referenceActionRegex = new RegExp(this.#options.referenceActionPattern, "gi").test(line) ? new RegExp(this.#options.referenceActionPattern, "gi") : /(?<reference>.*)/g;
227
+ let foundReference = false;
228
+ let referenceActionMatch;
229
+ while (referenceActionMatch = referenceActionRegex.exec(line)) {
230
+ if (!referenceActionMatch) break;
231
+ const { action = "", reference = "" } = referenceActionMatch.groups ?? {};
232
+ const parsedReferences = this.parseReferenceParts(reference, action || null);
233
+ if (!parsedReferences) break;
234
+ for (const ref of parsedReferences) if (!outReferences.some((r) => r.prefix === ref.prefix && r.issue === ref.issue)) outReferences.push(ref);
235
+ foundReference = true;
236
+ }
237
+ return foundReference;
238
+ }
239
+ /**
240
+ * Search for notes from the commit line
241
+ * @example
242
+ * ```txt
243
+ * "BREAKING CHANGE: this is a breaking change"
244
+ * ```
245
+ */
246
+ parseNotes(line, outNotes) {
247
+ if (!this.#options.notePattern) return false;
248
+ const noteMatch = new RegExp(this.#options.notePattern, "ig").exec(line);
249
+ if (noteMatch?.groups) {
250
+ const { title = "", text = "" } = noteMatch.groups;
251
+ outNotes.push({
252
+ title,
253
+ text
254
+ });
255
+ return true;
256
+ }
257
+ return false;
258
+ }
259
+ /**
260
+ * Parse the raw commit for mentions, references and notes
261
+ */
262
+ parseRawLines(commit) {
263
+ const mentions = /* @__PURE__ */ new Set();
264
+ const references = [];
265
+ const notes = [];
266
+ let lastNoteLine = -1;
267
+ const splitMessage = commit.raw.split("\n");
268
+ for (let index = 0; index < splitMessage.length; index++) {
269
+ const line = splitMessage[index];
270
+ const trimmedLine = line.trim();
271
+ if (this.#options.commentPattern?.test(trimmedLine)) continue;
272
+ this.parseMentions(trimmedLine, mentions);
273
+ if (this.parseReferences(trimmedLine, references)) {
274
+ lastNoteLine = -1;
275
+ continue;
276
+ }
277
+ if (this.parseNotes(trimmedLine, notes)) lastNoteLine = index;
278
+ else if (lastNoteLine !== -1) {
279
+ notes[notes.length - 1].text += `\n${line}`;
280
+ lastNoteLine = index;
281
+ }
282
+ }
283
+ if (mentions.size > 0) commit.mentions = Array.from(mentions);
284
+ if (references.length > 0) commit.references = references;
285
+ if (notes.length > 0) commit.notes = notes.map((note) => ({
286
+ ...note,
287
+ text: note.text.trim()
288
+ }));
289
+ }
290
+ /**
291
+ * Parse a commit log with the following format separated by new line characters:
292
+ * ```txt
293
+ * refactor: add test file
294
+ * Add a test file to the project
295
+ * 4ef2c86d393a9660aa9f753144256b1f200c16bd
296
+ * 2024-12-22T17:36:50Z
297
+ * Fork Version
298
+ * fork-version@example.com
299
+ * ```
300
+ *
301
+ * @example
302
+ * ```ts
303
+ * parse("refactor: add test file\nAdd a test file to the project\n4ef2c86d393a9660aa9f753144256b1f200c16bd\n2024-12-22T17:36:50Z\nFork Version\nfork-version@example.com");
304
+ * ```
305
+ *
306
+ * The expected input value can be generated by running the following command:
307
+ * ```sh
308
+ * git log --format="%s%n%b%n%H%n%cI%n%cN%n%cE%n"
309
+ * ```
310
+ * @see {@link https://git-scm.com/docs/pretty-formats|Git Pretty Format Documentation}
311
+ */
312
+ parse(rawCommit) {
313
+ try {
314
+ const commit = this.parseRawCommit(rawCommit);
315
+ this.parseSubject(commit);
316
+ this.parseMerge(commit);
317
+ this.parseRevert(commit);
318
+ this.parseRawLines(commit);
319
+ return commit;
320
+ } catch (error) {
321
+ if (this.#logger) this.#logger.debug("[Commit Parser] Failed to parse commit", { error });
322
+ return;
323
+ }
324
+ }
325
+ };
326
+ //#endregion
327
+ export { CommitParser };
@@ -0,0 +1,17 @@
1
+ import { Commit } from "./types.js";
2
+
3
+ //#region src/commit-parser/filter-reverted-commits.d.ts
4
+ /**
5
+ * Filter out revert commits and their corresponding reverted commits,
6
+ * this function expects the input to be sorted by date in descending order
7
+ * from the most recent to the oldest commit.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const commits: Commit[] = [...];
12
+ * const filteredCommits = filterRevertedCommits(commits);
13
+ * ```
14
+ */
15
+ declare function filterRevertedCommits(parsedCommits: Commit[]): Commit[];
16
+ //#endregion
17
+ export { filterRevertedCommits };
@@ -0,0 +1,34 @@
1
+ //#region src/commit-parser/filter-reverted-commits.ts
2
+ /**
3
+ * Filter out revert commits and their corresponding reverted commits,
4
+ * this function expects the input to be sorted by date in descending order
5
+ * from the most recent to the oldest commit.
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * const commits: Commit[] = [...];
10
+ * const filteredCommits = filterRevertedCommits(commits);
11
+ * ```
12
+ */
13
+ function filterRevertedCommits(parsedCommits) {
14
+ const revertedCommits = [];
15
+ for (const commit of parsedCommits) {
16
+ if (!commit.revert) continue;
17
+ if (revertedCommits.some((r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject)) continue;
18
+ revertedCommits.push(commit);
19
+ }
20
+ if (revertedCommits.length === 0) return parsedCommits;
21
+ const commitsWithoutReverts = [];
22
+ for (const commit of parsedCommits) {
23
+ if (commit.revert) continue;
24
+ const revertedIndex = revertedCommits.findIndex((r) => r.revert?.hash === commit.hash || r.revert?.subject === commit.subject);
25
+ if (revertedIndex !== -1) {
26
+ revertedCommits.splice(revertedIndex, 1);
27
+ continue;
28
+ }
29
+ commitsWithoutReverts.push(commit);
30
+ }
31
+ return commitsWithoutReverts;
32
+ }
33
+ //#endregion
34
+ export { filterRevertedCommits };
@@ -0,0 +1,74 @@
1
+ //#region src/commit-parser/options.d.ts
2
+ interface ParserOptions {
3
+ /**
4
+ * Pattern to match commit subjects
5
+ * - Expected capture groups: `type` `title`
6
+ * - Optional capture groups: `scope`, `breakingChange`
7
+ */
8
+ subjectPattern: RegExp | undefined;
9
+ /**
10
+ * Pattern to match merge commits
11
+ * - Expected capture groups: `id`, `source`
12
+ */
13
+ mergePattern: RegExp | undefined;
14
+ /**
15
+ * Pattern to match revert commits
16
+ * - Expected capture groups: `subject`, `hash`
17
+ */
18
+ revertPattern: RegExp | undefined;
19
+ /**
20
+ * Pattern to match commented out lines which will be trimmed
21
+ */
22
+ commentPattern: RegExp | undefined;
23
+ /**
24
+ * Pattern to match mentions
25
+ * - Expected capture groups: `username`
26
+ */
27
+ mentionPattern: RegExp | undefined;
28
+ /**
29
+ * List of action labels to match reference sections
30
+ * @default
31
+ * ["close", "closes", "closed", "fix", "fixes", "fixed", "resolve", "resolves", "resolved"]
32
+ */
33
+ referenceActions?: string[];
34
+ /**
35
+ * Pattern to match reference sections
36
+ * - Expected capture groups: `action`, `reference`
37
+ */
38
+ referenceActionPattern: RegExp | undefined;
39
+ /**
40
+ * List of issue prefixes to match issue ids
41
+ * @default
42
+ * ["#"]
43
+ */
44
+ issuePrefixes?: string[];
45
+ /**
46
+ * Pattern to match issue references
47
+ * - Expected capture groups: `repository`, `prefix`, `issue`
48
+ */
49
+ issuePattern: RegExp | undefined;
50
+ /**
51
+ * List of keywords to match note titles
52
+ * @default
53
+ * ["BREAKING CHANGE", "BREAKING-CHANGE"]
54
+ */
55
+ noteKeywords?: string[];
56
+ /**
57
+ * Pattern to match note sections
58
+ * - Expected capture groups: `title`
59
+ * - Optional capture groups: `text`
60
+ */
61
+ notePattern: RegExp | undefined;
62
+ }
63
+ /**
64
+ * Creates parser options by merging user-provided options with default values.
65
+ *
66
+ * Additionally, if a user provides a string for a property that expects a RegExp value,
67
+ * the function will attempt to parse it into a RegExp object.
68
+ *
69
+ * @param userOptions Optional user-provided options to override the defaults.
70
+ * @return A complete set of parser options with defaults applied and user overrides where specified.
71
+ */
72
+ declare function createParserOptions(userOptions?: Partial<ParserOptions>): ParserOptions;
73
+ //#endregion
74
+ export { ParserOptions, createParserOptions };
@@ -0,0 +1,70 @@
1
+ import { escapeRegex } from "../utils/escape-regex.js";
2
+ import { parseRegExpString } from "../utils/parse-regexp-string.js";
3
+ import { trimStringArray } from "../utils/trim-string-array.js";
4
+ //#region src/commit-parser/options.ts
5
+ /**
6
+ * Creates default parser options with predefined patterns and lists.
7
+ *
8
+ * The default expects the user is using Github as their hosting service.
9
+ *
10
+ * @param userOptions Optional user-provided options to override the defaults.
11
+ * @returns A complete set of parser options with defaults applied and user overrides where specified.
12
+ */
13
+ function createDefaultParserOptions(userOptions) {
14
+ const referenceActions = trimStringArray(userOptions?.referenceActions, escapeRegex) ?? [
15
+ "close",
16
+ "closes",
17
+ "closed",
18
+ "fix",
19
+ "fixes",
20
+ "fixed",
21
+ "resolve",
22
+ "resolves",
23
+ "resolved"
24
+ ];
25
+ const joinedReferenceActions = referenceActions.join("|");
26
+ const issuePrefixes = trimStringArray(userOptions?.issuePrefixes, escapeRegex) ?? ["#"];
27
+ const joinedIssuePrefixes = issuePrefixes.join("|");
28
+ const noteKeywords = trimStringArray(userOptions?.noteKeywords, escapeRegex) ?? ["BREAKING CHANGE", "BREAKING-CHANGE"];
29
+ const joinedNoteKeywords = noteKeywords.join("|");
30
+ return {
31
+ subjectPattern: /^(?<type>\w+)(?:\((?<scope>.*)\))?(?<breakingChange>!)?:\s+(?<title>.*)/i,
32
+ mergePattern: /^Merge pull request #(?<id>\d*) from (?<source>.*)/i,
33
+ revertPattern: /^[Rr]evert "(?<subject>.*)"(\s*This reverts commit (?<hash>[a-zA-Z0-9]*)\.)?/,
34
+ commentPattern: /^#(?!\d+\s)/,
35
+ mentionPattern: /(?<!\w)@(?<username>[\w-]+)/,
36
+ referenceActions,
37
+ referenceActionPattern: joinedReferenceActions ? new RegExp(`(?<action>${joinedReferenceActions})(?:\\s+(?<reference>.*?))(?=(?:${joinedReferenceActions})|$)`) : void 0,
38
+ issuePrefixes,
39
+ issuePattern: joinedIssuePrefixes ? new RegExp(`(?:.*?)??\\s*(?<repository>[\\w-\\.\\/]*?)??(?<prefix>${joinedIssuePrefixes})(?<issue>[\\w-]*\\d+)`) : void 0,
40
+ noteKeywords,
41
+ notePattern: joinedNoteKeywords ? new RegExp(`^(?<title>${joinedNoteKeywords}):(\\s*(?<text>.*))`) : void 0
42
+ };
43
+ }
44
+ /**
45
+ * Creates parser options by merging user-provided options with default values.
46
+ *
47
+ * Additionally, if a user provides a string for a property that expects a RegExp value,
48
+ * the function will attempt to parse it into a RegExp object.
49
+ *
50
+ * @param userOptions Optional user-provided options to override the defaults.
51
+ * @return A complete set of parser options with defaults applied and user overrides where specified.
52
+ */
53
+ function createParserOptions(userOptions) {
54
+ const initialOptions = createDefaultParserOptions(userOptions);
55
+ if (userOptions) for (const key of Object.keys(userOptions)) {
56
+ const userValue = userOptions[key];
57
+ if (!(key in initialOptions)) continue;
58
+ if (Array.isArray(initialOptions[key])) continue;
59
+ if (initialOptions[key] instanceof RegExp) {
60
+ if (userValue instanceof RegExp) initialOptions[key] = userValue;
61
+ else if (typeof userValue === "string") {
62
+ const parsed = parseRegExpString(userValue);
63
+ if (parsed) initialOptions[key] = parsed;
64
+ } else if (userValue == void 0) initialOptions[key] = void 0;
65
+ }
66
+ }
67
+ return initialOptions;
68
+ }
69
+ //#endregion
70
+ export { createParserOptions };
@@ -0,0 +1,14 @@
1
+ //#region src/commit-parser/parser-error.ts
2
+ /**
3
+ * Error thrown when commit parser encounters an error.
4
+ */
5
+ var ParserError = class extends Error {
6
+ detail;
7
+ constructor(message, detail) {
8
+ super(message);
9
+ this.name = "ParserError";
10
+ this.detail = detail;
11
+ }
12
+ };
13
+ //#endregion
14
+ export { ParserError };
@@ -0,0 +1,53 @@
1
+ //#region src/commit-parser/types.d.ts
2
+ interface CommitMerge {
3
+ id: string;
4
+ source: string;
5
+ }
6
+ interface CommitRevert {
7
+ hash: string;
8
+ subject: string;
9
+ }
10
+ interface CommitReference {
11
+ prefix: string;
12
+ issue: string;
13
+ action: string | null;
14
+ owner: string | null;
15
+ repository: string | null;
16
+ }
17
+ interface CommitNote {
18
+ title: string;
19
+ text: string;
20
+ }
21
+ interface Commit {
22
+ raw: string;
23
+ subject: string;
24
+ body: string;
25
+ hash: string;
26
+ refNames: string;
27
+ /**
28
+ * Committer date in ISO 8601 format
29
+ * @example
30
+ * "2024-12-22T17:36:50Z"
31
+ */
32
+ date: string;
33
+ /**
34
+ * Committer name (respects .mailmap)
35
+ */
36
+ name: string;
37
+ /**
38
+ * Committer email (respects .mailmap)
39
+ */
40
+ email: string;
41
+ type: string;
42
+ scope: string;
43
+ breakingChange: string;
44
+ title: string;
45
+ merge: CommitMerge | null;
46
+ revert: CommitRevert | null;
47
+ mentions: string[];
48
+ references: CommitReference[];
49
+ notes: CommitNote[];
50
+ tags: string[];
51
+ }
52
+ //#endregion
53
+ export { Commit, CommitMerge, CommitNote, CommitReference, CommitRevert };
@@ -0,0 +1,41 @@
1
+ import { ChangelogPresetConfigSchema, ChangelogPresetConfigTypeSchema } from "./schema.js";
2
+ import { z } from "zod";
3
+ import conventionalChangelogConfigSpec from "conventional-changelog-config-spec";
4
+ //#region src/config/changelog-preset-config.ts
5
+ function getChangelogPresetConfig(mergedConfig, cliArguments, detectedChangelogOptions) {
6
+ const preset = { name: "conventionalcommits" };
7
+ if (typeof conventionalChangelogConfigSpec.properties === "object") Object.entries(conventionalChangelogConfigSpec.properties).forEach(([key, value]) => {
8
+ if ("default" in value && value.default !== void 0) {
9
+ if (mergedConfig?.changelogAll && key === "types") {
10
+ const parsedTypes = z.array(ChangelogPresetConfigTypeSchema).safeParse(value.default);
11
+ if (parsedTypes.success) {
12
+ parsedTypes.data.forEach((type) => {
13
+ if (!type.section) {
14
+ delete type.hidden;
15
+ type.section = "Other Changes";
16
+ }
17
+ });
18
+ preset[key] = parsedTypes.data;
19
+ return;
20
+ }
21
+ }
22
+ preset[key] = value.default;
23
+ }
24
+ });
25
+ if (detectedChangelogOptions) Object.entries(detectedChangelogOptions).forEach(([key, value]) => {
26
+ if (value !== void 0) preset[key] = value;
27
+ });
28
+ if (mergedConfig?.changelogPresetConfig && typeof mergedConfig.changelogPresetConfig === "object") Object.entries(mergedConfig.changelogPresetConfig).forEach(([key, value]) => {
29
+ if (value !== void 0) preset[key] = value;
30
+ });
31
+ if (mergedConfig?.releaseMessageSuffix && !cliArguments?.releaseMessageSuffix) preset.releaseCommitMessageFormat = `${preset.releaseCommitMessageFormat} ${mergedConfig.releaseMessageSuffix}`;
32
+ if (cliArguments?.commitUrlFormat) preset.commitUrlFormat = cliArguments.commitUrlFormat;
33
+ if (cliArguments?.compareUrlFormat) preset.compareUrlFormat = cliArguments.compareUrlFormat;
34
+ if (cliArguments?.issueUrlFormat) preset.issueUrlFormat = cliArguments.issueUrlFormat;
35
+ if (cliArguments?.userUrlFormat) preset.userUrlFormat = cliArguments.userUrlFormat;
36
+ if (cliArguments?.releaseCommitMessageFormat) preset.releaseCommitMessageFormat = cliArguments.releaseCommitMessageFormat;
37
+ if (cliArguments?.releaseMessageSuffix) preset.releaseCommitMessageFormat = `${preset.releaseCommitMessageFormat} ${cliArguments.releaseMessageSuffix}`;
38
+ return ChangelogPresetConfigSchema.passthrough().parse(preset);
39
+ }
40
+ //#endregion
41
+ export { getChangelogPresetConfig };