@aneuhold/core-ts-lib 2.2.9 → 2.2.11

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 (89) hide show
  1. package/lib/index.d.ts +5 -3
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.js +3 -2
  4. package/lib/index.js.map +1 -1
  5. package/lib/index.ts +5 -2
  6. package/lib/services/ChangelogService/ChangelogFileService.d.ts +42 -0
  7. package/lib/services/ChangelogService/ChangelogFileService.d.ts.map +1 -0
  8. package/lib/services/ChangelogService/ChangelogFileService.js +65 -0
  9. package/lib/services/ChangelogService/ChangelogFileService.js.map +1 -0
  10. package/lib/services/ChangelogService/ChangelogFileService.ts +68 -0
  11. package/lib/services/ChangelogService/ChangelogGenerator.d.ts +58 -0
  12. package/lib/services/ChangelogService/ChangelogGenerator.d.ts.map +1 -0
  13. package/lib/services/ChangelogService/ChangelogGenerator.js +145 -0
  14. package/lib/services/ChangelogService/ChangelogGenerator.js.map +1 -0
  15. package/lib/services/ChangelogService/ChangelogGenerator.ts +188 -0
  16. package/lib/services/ChangelogService/ChangelogParser.d.ts +21 -0
  17. package/lib/services/ChangelogService/ChangelogParser.d.ts.map +1 -0
  18. package/lib/services/ChangelogService/ChangelogParser.js +76 -0
  19. package/lib/services/ChangelogService/ChangelogParser.js.map +1 -0
  20. package/lib/services/ChangelogService/ChangelogParser.ts +94 -0
  21. package/lib/services/ChangelogService/ChangelogService.d.ts +54 -0
  22. package/lib/services/ChangelogService/ChangelogService.d.ts.map +1 -0
  23. package/lib/services/ChangelogService/ChangelogService.js +201 -0
  24. package/lib/services/ChangelogService/ChangelogService.js.map +1 -0
  25. package/lib/services/ChangelogService/ChangelogService.ts +293 -0
  26. package/lib/services/ChangelogService/ChangelogValidator.d.ts +15 -0
  27. package/lib/services/ChangelogService/ChangelogValidator.d.ts.map +1 -0
  28. package/lib/services/ChangelogService/ChangelogValidator.js +44 -0
  29. package/lib/services/ChangelogService/ChangelogValidator.js.map +1 -0
  30. package/lib/services/ChangelogService/ChangelogValidator.ts +55 -0
  31. package/lib/services/ChangelogService/GitTagService.d.ts +29 -0
  32. package/lib/services/ChangelogService/GitTagService.d.ts.map +1 -0
  33. package/lib/services/ChangelogService/GitTagService.js +57 -0
  34. package/lib/services/ChangelogService/GitTagService.js.map +1 -0
  35. package/lib/services/ChangelogService/GitTagService.ts +60 -0
  36. package/lib/services/ChangelogService/RepositoryInfoService.d.ts +14 -0
  37. package/lib/services/ChangelogService/RepositoryInfoService.d.ts.map +1 -0
  38. package/lib/services/ChangelogService/RepositoryInfoService.js +55 -0
  39. package/lib/services/ChangelogService/RepositoryInfoService.js.map +1 -0
  40. package/lib/services/ChangelogService/RepositoryInfoService.ts +64 -0
  41. package/lib/services/ChangelogService/index.d.ts +2 -0
  42. package/lib/services/ChangelogService/index.d.ts.map +1 -0
  43. package/lib/services/ChangelogService/index.js +2 -0
  44. package/lib/services/ChangelogService/index.js.map +1 -0
  45. package/lib/services/ChangelogService/index.ts +1 -0
  46. package/lib/services/ChangelogService/types.d.ts +27 -0
  47. package/lib/services/ChangelogService/types.d.ts.map +1 -0
  48. package/lib/services/ChangelogService/types.js +3 -0
  49. package/lib/services/ChangelogService/types.js.map +1 -0
  50. package/lib/services/ChangelogService/types.ts +30 -0
  51. package/lib/services/DependencyService.d.ts +2 -9
  52. package/lib/services/DependencyService.d.ts.map +1 -1
  53. package/lib/services/DependencyService.js +2 -11
  54. package/lib/services/DependencyService.js.map +1 -1
  55. package/lib/services/DependencyService.ts +2 -11
  56. package/lib/services/PackageService/JsrPackageService.d.ts +81 -0
  57. package/lib/services/PackageService/JsrPackageService.d.ts.map +1 -0
  58. package/lib/services/{PackageService.js → PackageService/JsrPackageService.js} +70 -312
  59. package/lib/services/PackageService/JsrPackageService.js.map +1 -0
  60. package/lib/services/{PackageService.ts → PackageService/JsrPackageService.ts} +79 -372
  61. package/lib/services/PackageService/NpmPackageService.d.ts +45 -0
  62. package/lib/services/PackageService/NpmPackageService.d.ts.map +1 -0
  63. package/lib/services/PackageService/NpmPackageService.js +146 -0
  64. package/lib/services/PackageService/NpmPackageService.js.map +1 -0
  65. package/lib/services/PackageService/NpmPackageService.ts +178 -0
  66. package/lib/services/PackageService/PackageService.d.ts +77 -0
  67. package/lib/services/PackageService/PackageService.d.ts.map +1 -0
  68. package/lib/services/PackageService/PackageService.js +96 -0
  69. package/lib/services/PackageService/PackageService.js.map +1 -0
  70. package/lib/services/PackageService/PackageService.ts +108 -0
  71. package/lib/services/PackageService/PackageServiceUtils.d.ts +69 -0
  72. package/lib/services/PackageService/PackageServiceUtils.d.ts.map +1 -0
  73. package/lib/services/PackageService/PackageServiceUtils.js +185 -0
  74. package/lib/services/PackageService/PackageServiceUtils.js.map +1 -0
  75. package/lib/services/PackageService/PackageServiceUtils.ts +239 -0
  76. package/lib/services/StringService.d.ts +12 -0
  77. package/lib/services/StringService.d.ts.map +1 -1
  78. package/lib/services/StringService.js +56 -0
  79. package/lib/services/StringService.js.map +1 -1
  80. package/lib/services/StringService.ts +72 -0
  81. package/lib/types/VersionType.d.ts +9 -0
  82. package/lib/types/VersionType.d.ts.map +1 -0
  83. package/lib/types/VersionType.js +10 -0
  84. package/lib/types/VersionType.js.map +1 -0
  85. package/lib/types/VersionType.ts +8 -0
  86. package/package.json +7 -6
  87. package/lib/services/PackageService.d.ts +0 -159
  88. package/lib/services/PackageService.d.ts.map +0 -1
  89. package/lib/services/PackageService.js.map +0 -1
@@ -0,0 +1,293 @@
1
+ import ErrorUtils from '../../utils/ErrorUtils.js';
2
+ import { DR } from '../DependencyRegistry.js';
3
+ import ChangelogFileService from './ChangelogFileService.js';
4
+ import ChangelogGenerator from './ChangelogGenerator.js';
5
+ import ChangelogParser from './ChangelogParser.js';
6
+ import ChangelogValidator from './ChangelogValidator.js';
7
+ import GitTagService from './GitTagService.js';
8
+ import RepositoryInfoService from './RepositoryInfoService.js';
9
+ import { CHANGELOG_FILENAME, type ChangelogVersionEntry } from './types.js';
10
+
11
+ /**
12
+ * A service for managing and validating changelog files in packages.
13
+ *
14
+ * This service handles the creation, validation, and maintenance of CHANGELOG.md
15
+ * files following the Keep a Changelog format.
16
+ */
17
+ export default class ChangelogService {
18
+ /**
19
+ * Validates that a changelog exists and contains a valid entry for the specified version.
20
+ *
21
+ * @param version The version to validate in the changelog
22
+ * @param packagePath Optional path to the package directory (defaults to current working directory)
23
+ * @throws Error if validation fails
24
+ */
25
+ static async validateChangelogForVersion(version: string, packagePath?: string): Promise<void> {
26
+ const workingDir = packagePath || process.cwd();
27
+
28
+ DR.logger.info(`Validating changelog for version ${version}...`);
29
+
30
+ const changelogExists = await ChangelogFileService.changelogExists(packagePath);
31
+ if (!changelogExists) {
32
+ throw new Error(
33
+ `No ${CHANGELOG_FILENAME} file found in ${workingDir}. ` +
34
+ `Run changelog initialization to create one.`
35
+ );
36
+ }
37
+
38
+ try {
39
+ const changelogContent = await ChangelogFileService.readChangelog(packagePath);
40
+ const versionEntries = ChangelogParser.parseChangelog(changelogContent);
41
+
42
+ const versionEntry = versionEntries.find((entry) => entry.version === version);
43
+
44
+ if (!versionEntry) {
45
+ throw new Error(
46
+ `No changelog entry found for version ${version}. ` +
47
+ `Please add an entry to ${CHANGELOG_FILENAME} before publishing.`
48
+ );
49
+ }
50
+
51
+ ChangelogValidator.validateVersionEntry(versionEntry, version);
52
+
53
+ DR.logger.success(`Changelog validation passed for version ${version}`);
54
+ } catch (error) {
55
+ const errorString = ErrorUtils.getErrorString(error);
56
+ DR.logger.error(`Changelog validation failed: ${errorString}`);
57
+ throw error;
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Initializes a changelog file for the current package if one doesn't exist.
63
+ * If a changelog already exists, validates it against existing Git tags and
64
+ * updates the most recent entry if needed to match the current version.
65
+ *
66
+ * @param version The current version for the changelog
67
+ * @param packageName The name of the package
68
+ * @param packagePath Optional path to the package directory (defaults to current working directory)
69
+ */
70
+ static async initializeChangelog(
71
+ version: string,
72
+ packageName: string,
73
+ packagePath?: string
74
+ ): Promise<void> {
75
+ const workingDir = packagePath || process.cwd();
76
+
77
+ DR.logger.info(`Initializing changelog for ${packageName} version ${version}...`);
78
+
79
+ const changelogExists = await ChangelogFileService.changelogExists(packagePath);
80
+
81
+ if (changelogExists) {
82
+ // If it exists, validate against Git tags and update if necessary
83
+ const existingContent = await ChangelogFileService.readChangelog(packagePath);
84
+ await this.validateAndUpdateExistingChangelog(
85
+ version,
86
+ packageName,
87
+ existingContent,
88
+ workingDir
89
+ );
90
+ } else {
91
+ // Changelog doesn't exist, create a new one
92
+ DR.logger.info(`Creating new changelog file`);
93
+ const repositoryInfo = await RepositoryInfoService.getRepositoryInfo(workingDir);
94
+ const initialContent = ChangelogGenerator.createInitialChangelogContent(
95
+ version,
96
+ packageName,
97
+ repositoryInfo
98
+ );
99
+ await ChangelogFileService.createChangelog(initialContent, packagePath);
100
+ }
101
+
102
+ DR.logger.success(`Changelog initialization completed for ${packageName}`);
103
+ }
104
+
105
+ /**
106
+ * Validates an existing changelog against Git tags and updates if necessary.
107
+ *
108
+ * @param currentVersion The current version
109
+ * @param packageName The package name
110
+ * @param existingContent The current changelog content
111
+ * @param workingDir The working directory
112
+ */
113
+ private static async validateAndUpdateExistingChangelog(
114
+ currentVersion: string,
115
+ packageName: string,
116
+ existingContent: string,
117
+ workingDir: string
118
+ ): Promise<void> {
119
+ const versionEntries = ChangelogParser.parseChangelog(existingContent);
120
+
121
+ if (versionEntries.length === 0) {
122
+ // No version entries exist, add the current version
123
+ DR.logger.info(
124
+ `Changelog exists but has no version entries - adding entry for ${currentVersion}`
125
+ );
126
+ await this.addVersionEntry(currentVersion, existingContent, packageName, workingDir);
127
+ return;
128
+ }
129
+
130
+ // Get existing Git tags for this package
131
+ const existingTags = GitTagService.getPackageTags(packageName, workingDir);
132
+
133
+ // Check which entries have corresponding tags and remove ones that don't (except most recent)
134
+ const mostRecentEntry = versionEntries[0];
135
+ const olderEntries = versionEntries.slice(1);
136
+ const validOlderEntries: ChangelogVersionEntry[] = [];
137
+ const removedVersions: string[] = [];
138
+
139
+ for (const entry of olderEntries) {
140
+ const expectedTag = GitTagService.getTagName(packageName, entry.version);
141
+ if (existingTags.includes(expectedTag)) {
142
+ validOlderEntries.push(entry);
143
+ } else {
144
+ removedVersions.push(entry.version);
145
+ }
146
+ }
147
+
148
+ // If we removed any older entries, we need to regenerate the changelog
149
+ if (removedVersions.length > 0) {
150
+ DR.logger.info(
151
+ `Removing changelog entries without corresponding Git tags: ${removedVersions.join(', ')}`
152
+ );
153
+
154
+ const validEntries = [mostRecentEntry, ...validOlderEntries];
155
+ const repositoryInfo = await RepositoryInfoService.getRepositoryInfo(workingDir);
156
+ const updatedContent = ChangelogGenerator.regenerateChangelogContent(
157
+ validEntries,
158
+ packageName,
159
+ repositoryInfo
160
+ );
161
+ await ChangelogFileService.writeChangelog(updatedContent, workingDir);
162
+ }
163
+
164
+ // Now handle the most recent entry
165
+ const mostRecentTag = GitTagService.getTagName(packageName, mostRecentEntry.version);
166
+ const hasTagForMostRecent = existingTags.includes(mostRecentTag);
167
+
168
+ if (hasTagForMostRecent) {
169
+ // Most recent entry has a tag, so we need to add a new entry for current version
170
+ if (mostRecentEntry.version === currentVersion) {
171
+ DR.logger.info(
172
+ `Changelog already contains entry for version ${currentVersion} with corresponding tag - no changes made`
173
+ );
174
+ return;
175
+ }
176
+
177
+ DR.logger.info(
178
+ `Most recent changelog entry has a tag - adding new entry for version ${currentVersion}`
179
+ );
180
+ await this.addVersionEntry(currentVersion, existingContent, packageName, workingDir);
181
+ } else {
182
+ // Most recent entry doesn't have a tag
183
+ if (mostRecentEntry.version === currentVersion) {
184
+ DR.logger.info(
185
+ `Changelog already contains entry for version ${currentVersion} without tag - no changes made`
186
+ );
187
+ return;
188
+ }
189
+
190
+ // Update the most recent entry to match current version
191
+ DR.logger.info(
192
+ `Updating most recent changelog entry from ${mostRecentEntry.version} to ${currentVersion}`
193
+ );
194
+ await this.updateMostRecentVersionEntry(
195
+ currentVersion,
196
+ existingContent,
197
+ packageName,
198
+ workingDir
199
+ );
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Updates the most recent version entry in the changelog.
205
+ *
206
+ * @param newVersion The new version to update to
207
+ * @param existingContent The current changelog content
208
+ * @param packageName The package name
209
+ * @param workingDir The working directory
210
+ */
211
+ private static async updateMostRecentVersionEntry(
212
+ newVersion: string,
213
+ existingContent: string,
214
+ packageName: string,
215
+ workingDir: string
216
+ ): Promise<void> {
217
+ const versionEntries = ChangelogParser.parseChangelog(existingContent);
218
+
219
+ if (versionEntries.length === 0) {
220
+ throw new Error('No version entries found to update');
221
+ }
222
+
223
+ const mostRecentEntry = versionEntries[0];
224
+ const oldVersionPattern = `## 🔖 [${mostRecentEntry.version}]`;
225
+ const newVersionPattern = `## 🔖 [${newVersion}]`;
226
+
227
+ // Replace the version in the changelog content
228
+ let updatedContent = existingContent.replace(oldVersionPattern, newVersionPattern);
229
+
230
+ // Update version links if they exist
231
+ const repositoryInfo = await RepositoryInfoService.getRepositoryInfo(workingDir);
232
+ if (repositoryInfo) {
233
+ updatedContent = ChangelogGenerator.addVersionLinksToChangelog(
234
+ updatedContent,
235
+ repositoryInfo,
236
+ packageName
237
+ );
238
+ }
239
+
240
+ await ChangelogFileService.writeChangelog(updatedContent, workingDir);
241
+ }
242
+
243
+ /**
244
+ * Adds a new version entry to an existing changelog.
245
+ *
246
+ * @param version The version to add
247
+ * @param existingContent The current changelog content
248
+ * @param packageName The package name for generating version links
249
+ * @param packagePath The package directory path
250
+ */
251
+ private static async addVersionEntry(
252
+ version: string,
253
+ existingContent: string,
254
+ packageName: string,
255
+ packagePath: string
256
+ ): Promise<void> {
257
+ const currentDate = ChangelogGenerator.getCurrentDate();
258
+ const versionEntry = ChangelogGenerator.createVersionEntryContent(version, currentDate);
259
+
260
+ // Find the position after the header to insert the new version
261
+ const lines = existingContent.split('\n');
262
+ const headerEndIndex = lines.findIndex((line) => line.startsWith('## ') && line.includes('['));
263
+
264
+ let newContent: string;
265
+ if (headerEndIndex === -1) {
266
+ // No existing version entries, add after the header
267
+ const headerLines = lines.slice(0, lines.findIndex((line) => line.trim() === '') + 1);
268
+ newContent = [...headerLines, '', versionEntry, '', ...lines.slice(headerLines.length)].join(
269
+ '\n'
270
+ );
271
+ } else {
272
+ // Insert before the first existing version
273
+ newContent = [
274
+ ...lines.slice(0, headerEndIndex),
275
+ versionEntry,
276
+ '',
277
+ ...lines.slice(headerEndIndex)
278
+ ].join('\n');
279
+ }
280
+
281
+ // Add version links if repository info is available
282
+ const repositoryInfo = await RepositoryInfoService.getRepositoryInfo(packagePath);
283
+ if (repositoryInfo) {
284
+ newContent = ChangelogGenerator.addVersionLinksToChangelog(
285
+ newContent,
286
+ repositoryInfo,
287
+ packageName
288
+ );
289
+ }
290
+
291
+ await ChangelogFileService.writeChangelog(newContent, packagePath);
292
+ }
293
+ }
@@ -0,0 +1,15 @@
1
+ import type { ChangelogVersionEntry } from './types.js';
2
+ /**
3
+ * Service for validating changelog entries and content.
4
+ */
5
+ export default class ChangelogValidator {
6
+ /**
7
+ * Validates that a version entry meets the requirements.
8
+ *
9
+ * @param versionEntry The version entry to validate
10
+ * @param version The version being validated (for error messages)
11
+ * @throws Error if validation fails
12
+ */
13
+ static validateVersionEntry(versionEntry: ChangelogVersionEntry, version: string): void;
14
+ }
15
+ //# sourceMappingURL=ChangelogValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangelogValidator.d.ts","sourceRoot":"","sources":["../../../src/services/ChangelogService/ChangelogValidator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGxD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAkB;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CAAC,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAwCxF"}
@@ -0,0 +1,44 @@
1
+ import { REQUIRED_SECTION_TYPES } from './types.js';
2
+ /**
3
+ * Service for validating changelog entries and content.
4
+ */
5
+ export default class ChangelogValidator {
6
+ /**
7
+ * Validates that a version entry meets the requirements.
8
+ *
9
+ * @param versionEntry The version entry to validate
10
+ * @param version The version being validated (for error messages)
11
+ * @throws Error if validation fails
12
+ */
13
+ static validateVersionEntry(versionEntry, version) {
14
+ const { sections } = versionEntry;
15
+ if (sections.length === 0) {
16
+ throw new Error(`Version ${version} has no changelog sections. ` +
17
+ `At least one of the following sections is required: ${REQUIRED_SECTION_TYPES.join(', ')}`);
18
+ }
19
+ let hasValidSection = false;
20
+ const emptySections = [];
21
+ for (const section of sections) {
22
+ if (REQUIRED_SECTION_TYPES.includes(section.type)) {
23
+ if (section.content && section.content.trim().length > 0) {
24
+ hasValidSection = true;
25
+ }
26
+ else {
27
+ // Section exists but is empty
28
+ emptySections.push(section.type);
29
+ }
30
+ }
31
+ }
32
+ // Fail if any section exists but is empty
33
+ if (emptySections.length > 0) {
34
+ throw new Error(`Version ${version} has empty changelog sections. ` +
35
+ `The following sections exist but have no content: ${emptySections.join(', ')}`);
36
+ }
37
+ // Fail if no section has meaningful content
38
+ if (!hasValidSection) {
39
+ throw new Error(`Version ${version} has no meaningful content in changelog sections. ` +
40
+ `At least one of the following sections must have content: ${REQUIRED_SECTION_TYPES.join(', ')}`);
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=ChangelogValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChangelogValidator.js","sourceRoot":"","sources":["../../../src/services/ChangelogService/ChangelogValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,kBAAkB;IACrC;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CAAC,YAAmC,EAAE,OAAe;QAC9E,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC;QAElC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,WAAW,OAAO,8BAA8B;gBAC9C,uDAAuD,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC7F,CAAC;QACJ,CAAC;QAED,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClD,IAAI,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACzD,eAAe,GAAG,IAAI,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,8BAA8B;oBAC9B,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;QACH,CAAC;QAED,0CAA0C;QAC1C,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,WAAW,OAAO,iCAAiC;gBACjD,qDAAqD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClF,CAAC;QACJ,CAAC;QAED,4CAA4C;QAC5C,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CACb,WAAW,OAAO,oDAAoD;gBACpE,6DAA6D,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACnG,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,55 @@
1
+ import type { ChangelogVersionEntry } from './types.js';
2
+ import { REQUIRED_SECTION_TYPES } from './types.js';
3
+
4
+ /**
5
+ * Service for validating changelog entries and content.
6
+ */
7
+ export default class ChangelogValidator {
8
+ /**
9
+ * Validates that a version entry meets the requirements.
10
+ *
11
+ * @param versionEntry The version entry to validate
12
+ * @param version The version being validated (for error messages)
13
+ * @throws Error if validation fails
14
+ */
15
+ static validateVersionEntry(versionEntry: ChangelogVersionEntry, version: string): void {
16
+ const { sections } = versionEntry;
17
+
18
+ if (sections.length === 0) {
19
+ throw new Error(
20
+ `Version ${version} has no changelog sections. ` +
21
+ `At least one of the following sections is required: ${REQUIRED_SECTION_TYPES.join(', ')}`
22
+ );
23
+ }
24
+
25
+ let hasValidSection = false;
26
+ const emptySections: string[] = [];
27
+
28
+ for (const section of sections) {
29
+ if (REQUIRED_SECTION_TYPES.includes(section.type)) {
30
+ if (section.content && section.content.trim().length > 0) {
31
+ hasValidSection = true;
32
+ } else {
33
+ // Section exists but is empty
34
+ emptySections.push(section.type);
35
+ }
36
+ }
37
+ }
38
+
39
+ // Fail if any section exists but is empty
40
+ if (emptySections.length > 0) {
41
+ throw new Error(
42
+ `Version ${version} has empty changelog sections. ` +
43
+ `The following sections exist but have no content: ${emptySections.join(', ')}`
44
+ );
45
+ }
46
+
47
+ // Fail if no section has meaningful content
48
+ if (!hasValidSection) {
49
+ throw new Error(
50
+ `Version ${version} has no meaningful content in changelog sections. ` +
51
+ `At least one of the following sections must have content: ${REQUIRED_SECTION_TYPES.join(', ')}`
52
+ );
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Service for handling Git tag operations related to changelog management.
3
+ */
4
+ export default class GitTagService {
5
+ /**
6
+ * Gets Git tags for a specific package.
7
+ *
8
+ * @param packageName The package name
9
+ * @param workingDir The working directory
10
+ * @returns Array of Git tags for the package
11
+ */
12
+ static getPackageTags(packageName: string, workingDir: string): string[];
13
+ /**
14
+ * Generates the expected Git tag name for a package version.
15
+ *
16
+ * @param packageName The package name
17
+ * @param version The version
18
+ * @returns The expected Git tag name
19
+ */
20
+ static getTagName(packageName: string, version: string): string;
21
+ /**
22
+ * Converts package name to tag prefix (removes scope if present).
23
+ *
24
+ * @param packageName The package name
25
+ * @returns The tag prefix
26
+ */
27
+ private static getTagPrefix;
28
+ }
29
+ //# sourceMappingURL=GitTagService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitTagService.d.ts","sourceRoot":"","sources":["../../../src/services/ChangelogService/GitTagService.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IAChC;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAuBxE;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAK/D;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,YAAY;CAG5B"}
@@ -0,0 +1,57 @@
1
+ import { execSync } from 'child_process';
2
+ import ErrorUtils from '../../utils/ErrorUtils.js';
3
+ import { DR } from '../DependencyRegistry.js';
4
+ /**
5
+ * Service for handling Git tag operations related to changelog management.
6
+ */
7
+ export default class GitTagService {
8
+ /**
9
+ * Gets Git tags for a specific package.
10
+ *
11
+ * @param packageName The package name
12
+ * @param workingDir The working directory
13
+ * @returns Array of Git tags for the package
14
+ */
15
+ static getPackageTags(packageName, workingDir) {
16
+ try {
17
+ // Convert package name to tag prefix (remove scope if present)
18
+ const tagPrefix = this.getTagPrefix(packageName);
19
+ const tagPattern = `${tagPrefix}-v*`;
20
+ // Get all tags matching the pattern
21
+ const output = execSync(`git tag -l "${tagPattern}"`, {
22
+ cwd: workingDir,
23
+ encoding: 'utf-8'
24
+ });
25
+ return output
26
+ .trim()
27
+ .split('\n')
28
+ .filter((tag) => tag.length > 0);
29
+ }
30
+ catch (error) {
31
+ // If git command fails (e.g., not a git repo), return empty array
32
+ DR.logger.warn(`Failed to retrieve Git tags: ${ErrorUtils.getErrorString(error)}`);
33
+ return [];
34
+ }
35
+ }
36
+ /**
37
+ * Generates the expected Git tag name for a package version.
38
+ *
39
+ * @param packageName The package name
40
+ * @param version The version
41
+ * @returns The expected Git tag name
42
+ */
43
+ static getTagName(packageName, version) {
44
+ const tagPrefix = this.getTagPrefix(packageName);
45
+ return `${tagPrefix}-v${version}`;
46
+ }
47
+ /**
48
+ * Converts package name to tag prefix (removes scope if present).
49
+ *
50
+ * @param packageName The package name
51
+ * @returns The tag prefix
52
+ */
53
+ static getTagPrefix(packageName) {
54
+ return packageName.replace(/^@[\w-]+\//, '');
55
+ }
56
+ }
57
+ //# sourceMappingURL=GitTagService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GitTagService.js","sourceRoot":"","sources":["../../../src/services/ChangelogService/GitTagService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,UAAU,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,aAAa;IAChC;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CAAC,WAAmB,EAAE,UAAkB;QAC3D,IAAI,CAAC;YACH,+DAA+D;YAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,GAAG,SAAS,KAAK,CAAC;YAErC,oCAAoC;YACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,eAAe,UAAU,GAAG,EAAE;gBACpD,GAAG,EAAE,UAAU;gBACf,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;YAEH,OAAO,MAAM;iBACV,IAAI,EAAE;iBACN,KAAK,CAAC,IAAI,CAAC;iBACX,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kEAAkE;YAClE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,gCAAgC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,UAAU,CAAC,WAAmB,EAAE,OAAe;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACjD,OAAO,GAAG,SAAS,KAAK,OAAO,EAAE,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,YAAY,CAAC,WAAmB;QAC7C,OAAO,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;CACF"}
@@ -0,0 +1,60 @@
1
+ import { execSync } from 'child_process';
2
+ import ErrorUtils from '../../utils/ErrorUtils.js';
3
+ import { DR } from '../DependencyRegistry.js';
4
+
5
+ /**
6
+ * Service for handling Git tag operations related to changelog management.
7
+ */
8
+ export default class GitTagService {
9
+ /**
10
+ * Gets Git tags for a specific package.
11
+ *
12
+ * @param packageName The package name
13
+ * @param workingDir The working directory
14
+ * @returns Array of Git tags for the package
15
+ */
16
+ static getPackageTags(packageName: string, workingDir: string): string[] {
17
+ try {
18
+ // Convert package name to tag prefix (remove scope if present)
19
+ const tagPrefix = this.getTagPrefix(packageName);
20
+ const tagPattern = `${tagPrefix}-v*`;
21
+
22
+ // Get all tags matching the pattern
23
+ const output = execSync(`git tag -l "${tagPattern}"`, {
24
+ cwd: workingDir,
25
+ encoding: 'utf-8'
26
+ });
27
+
28
+ return output
29
+ .trim()
30
+ .split('\n')
31
+ .filter((tag) => tag.length > 0);
32
+ } catch (error) {
33
+ // If git command fails (e.g., not a git repo), return empty array
34
+ DR.logger.warn(`Failed to retrieve Git tags: ${ErrorUtils.getErrorString(error)}`);
35
+ return [];
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Generates the expected Git tag name for a package version.
41
+ *
42
+ * @param packageName The package name
43
+ * @param version The version
44
+ * @returns The expected Git tag name
45
+ */
46
+ static getTagName(packageName: string, version: string): string {
47
+ const tagPrefix = this.getTagPrefix(packageName);
48
+ return `${tagPrefix}-v${version}`;
49
+ }
50
+
51
+ /**
52
+ * Converts package name to tag prefix (removes scope if present).
53
+ *
54
+ * @param packageName The package name
55
+ * @returns The tag prefix
56
+ */
57
+ private static getTagPrefix(packageName: string): string {
58
+ return packageName.replace(/^@[\w-]+\//, '');
59
+ }
60
+ }
@@ -0,0 +1,14 @@
1
+ import type { RepositoryInfo } from './types.js';
2
+ /**
3
+ * Service for extracting repository information from package.json files.
4
+ */
5
+ export default class RepositoryInfoService {
6
+ /**
7
+ * Extracts repository information from package.json
8
+ *
9
+ * @param packagePath Path to the package directory
10
+ * @returns Repository information or null if not found/invalid
11
+ */
12
+ static getRepositoryInfo(packagePath?: string): Promise<RepositoryInfo | null>;
13
+ }
14
+ //# sourceMappingURL=RepositoryInfoService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RepositoryInfoService.d.ts","sourceRoot":"","sources":["../../../src/services/ChangelogService/RepositoryInfoService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;;;;OAKG;WACU,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAiDrF"}
@@ -0,0 +1,55 @@
1
+ import { readFile } from 'fs/promises';
2
+ import path from 'path';
3
+ /**
4
+ * Service for extracting repository information from package.json files.
5
+ */
6
+ export default class RepositoryInfoService {
7
+ /**
8
+ * Extracts repository information from package.json
9
+ *
10
+ * @param packagePath Path to the package directory
11
+ * @returns Repository information or null if not found/invalid
12
+ */
13
+ static async getRepositoryInfo(packagePath) {
14
+ const workingDir = packagePath || process.cwd();
15
+ const packageJsonPath = path.join(workingDir, 'package.json');
16
+ try {
17
+ const packageJsonContent = await readFile(packageJsonPath, 'utf-8');
18
+ const packageJson = JSON.parse(packageJsonContent);
19
+ // Type guard to check if packageJson has the expected structure
20
+ if (typeof packageJson !== 'object' ||
21
+ packageJson === null ||
22
+ !('repository' in packageJson) ||
23
+ typeof packageJson.repository !== 'object' ||
24
+ packageJson.repository === null ||
25
+ !('url' in packageJson.repository) ||
26
+ typeof packageJson.repository.url !== 'string') {
27
+ return null;
28
+ }
29
+ const url = packageJson.repository.url;
30
+ // Handle different URL formats
31
+ let gitUrl = url;
32
+ if (gitUrl.startsWith('git+')) {
33
+ gitUrl = gitUrl.substring(4);
34
+ }
35
+ if (gitUrl.endsWith('.git')) {
36
+ gitUrl = gitUrl.substring(0, gitUrl.length - 4);
37
+ }
38
+ // Extract owner and repo from GitHub URL
39
+ const match = gitUrl.match(/github\.com[/:]([\w-]+)\/([\w-]+)/);
40
+ if (!match) {
41
+ return null;
42
+ }
43
+ const [, owner, repo] = match;
44
+ return {
45
+ owner,
46
+ repo,
47
+ url: `https://github.com/${owner}/${repo}`
48
+ };
49
+ }
50
+ catch {
51
+ return null;
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=RepositoryInfoService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RepositoryInfoService.js","sourceRoot":"","sources":["../../../src/services/ChangelogService/RepositoryInfoService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACxC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,WAAoB;QACjD,MAAM,UAAU,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QAE9D,IAAI,CAAC;YACH,MAAM,kBAAkB,GAAG,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YACpE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAY,CAAC;YAE9D,gEAAgE;YAChE,IACE,OAAO,WAAW,KAAK,QAAQ;gBAC/B,WAAW,KAAK,IAAI;gBACpB,CAAC,CAAC,YAAY,IAAI,WAAW,CAAC;gBAC9B,OAAO,WAAW,CAAC,UAAU,KAAK,QAAQ;gBAC1C,WAAW,CAAC,UAAU,KAAK,IAAI;gBAC/B,CAAC,CAAC,KAAK,IAAI,WAAW,CAAC,UAAU,CAAC;gBAClC,OAAO,WAAW,CAAC,UAAU,CAAC,GAAG,KAAK,QAAQ,EAC9C,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC;YAEvC,+BAA+B;YAC/B,IAAI,MAAM,GAAG,GAAG,CAAC;YACjB,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClD,CAAC;YAED,yCAAyC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;YAChE,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;YAE9B,OAAO;gBACL,KAAK;gBACL,IAAI;gBACJ,GAAG,EAAE,sBAAsB,KAAK,IAAI,IAAI,EAAE;aAC3C,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}