@williamthorsen/release-kit 4.8.0 → 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 (82) hide show
  1. package/CHANGELOG.md +74 -4
  2. package/README.md +310 -40
  3. package/cliff.toml.template +2 -1
  4. package/dist/esm/.cache +1 -1
  5. package/dist/esm/bin/release-kit.js +44 -13
  6. package/dist/esm/buildDependencyGraph.d.ts +3 -3
  7. package/dist/esm/buildDependencyGraph.js +10 -10
  8. package/dist/esm/buildReleaseSummary.js +4 -4
  9. package/dist/esm/bumpAllVersions.d.ts +1 -0
  10. package/dist/esm/bumpAllVersions.js +16 -2
  11. package/dist/esm/bumpVersion.js +3 -0
  12. package/dist/esm/commitCommand.js +1 -1
  13. package/dist/esm/compareVersions.d.ts +1 -0
  14. package/dist/esm/compareVersions.js +27 -0
  15. package/dist/esm/createGithubRelease.d.ts +6 -2
  16. package/dist/esm/createGithubRelease.js +17 -17
  17. package/dist/esm/createGithubReleaseCommand.d.ts +1 -0
  18. package/dist/esm/createGithubReleaseCommand.js +41 -0
  19. package/dist/esm/defaults.js +5 -3
  20. package/dist/esm/deriveWorkspaceConfig.d.ts +2 -0
  21. package/dist/esm/deriveWorkspaceConfig.js +37 -0
  22. package/dist/esm/detectUndeclaredTagPrefixes.d.ts +7 -0
  23. package/dist/esm/detectUndeclaredTagPrefixes.js +46 -0
  24. package/dist/esm/generateChangelogJson.js +37 -1
  25. package/dist/esm/generateChangelogs.d.ts +1 -1
  26. package/dist/esm/generateChangelogs.js +14 -3
  27. package/dist/esm/getCommitsSinceTarget.d.ts +1 -1
  28. package/dist/esm/getCommitsSinceTarget.js +8 -4
  29. package/dist/esm/index.d.ts +7 -3
  30. package/dist/esm/index.js +10 -3
  31. package/dist/esm/init/initCommand.js +1 -1
  32. package/dist/esm/init/scaffold.d.ts +1 -1
  33. package/dist/esm/init/scaffold.js +8 -5
  34. package/dist/esm/init/templates.d.ts +1 -0
  35. package/dist/esm/init/templates.js +33 -3
  36. package/dist/esm/injectReleaseNotesIntoReadme.d.ts +6 -1
  37. package/dist/esm/injectReleaseNotesIntoReadme.js +20 -7
  38. package/dist/esm/loadConfig.d.ts +2 -1
  39. package/dist/esm/loadConfig.js +65 -12
  40. package/dist/esm/parseRequestedTags.d.ts +1 -0
  41. package/dist/esm/parseRequestedTags.js +10 -0
  42. package/dist/esm/prepareCommand.d.ts +3 -1
  43. package/dist/esm/prepareCommand.js +74 -26
  44. package/dist/esm/previewTagPrefixes.d.ts +30 -0
  45. package/dist/esm/previewTagPrefixes.js +120 -0
  46. package/dist/esm/propagateBumps.d.ts +1 -0
  47. package/dist/esm/propagateBumps.js +1 -1
  48. package/dist/esm/publishCommand.js +8 -13
  49. package/dist/esm/pushCommand.js +5 -4
  50. package/dist/esm/readCurrentVersion.d.ts +1 -0
  51. package/dist/esm/readCurrentVersion.js +21 -0
  52. package/dist/esm/releasePrepare.d.ts +2 -0
  53. package/dist/esm/releasePrepare.js +72 -30
  54. package/dist/esm/releasePrepareMono.js +235 -112
  55. package/dist/esm/renderReleaseNotes.d.ts +1 -0
  56. package/dist/esm/renderReleaseNotes.js +29 -2
  57. package/dist/esm/reportPrepare.js +100 -73
  58. package/dist/esm/resolveCliffConfigPath.js +1 -1
  59. package/dist/esm/resolveCommandTags.d.ts +1 -1
  60. package/dist/esm/resolveCommandTags.js +17 -13
  61. package/dist/esm/resolveReleaseNotesConfig.d.ts +8 -1
  62. package/dist/esm/resolveReleaseNotesConfig.js +17 -7
  63. package/dist/esm/resolveReleaseTags.d.ts +2 -1
  64. package/dist/esm/resolveReleaseTags.js +19 -14
  65. package/dist/esm/showTagPrefixesCommand.d.ts +1 -0
  66. package/dist/esm/showTagPrefixesCommand.js +84 -0
  67. package/dist/esm/sync-labels/initCommand.js +1 -1
  68. package/dist/esm/sync-labels/presets.js +1 -1
  69. package/dist/esm/tagCommand.js +1 -1
  70. package/dist/esm/types.d.ts +22 -7
  71. package/dist/esm/validateConfig.js +179 -36
  72. package/dist/esm/version.d.ts +1 -1
  73. package/dist/esm/version.js +1 -1
  74. package/dist/esm/writeReleaseNotesPreviews.d.ts +18 -0
  75. package/dist/esm/writeReleaseNotesPreviews.js +65 -0
  76. package/package.json +2 -2
  77. package/dist/esm/component.d.ts +0 -2
  78. package/dist/esm/component.js +0 -14
  79. package/dist/esm/findPackageRoot.d.ts +0 -1
  80. package/dist/esm/findPackageRoot.js +0 -17
  81. package/dist/esm/githubReleaseCommand.d.ts +0 -1
  82. package/dist/esm/githubReleaseCommand.js +0 -35
@@ -8,11 +8,12 @@ function validateConfig(raw) {
8
8
  const knownFields = /* @__PURE__ */ new Set([
9
9
  "changelogJson",
10
10
  "cliffConfigPath",
11
- "components",
12
11
  "formatCommand",
13
12
  "releaseNotes",
13
+ "retiredPackages",
14
14
  "scopeAliases",
15
15
  "versionPatterns",
16
+ "workspaces",
16
17
  "workTypes"
17
18
  ]);
18
19
  for (const key of Object.keys(raw)) {
@@ -21,26 +22,20 @@ function validateConfig(raw) {
21
22
  }
22
23
  }
23
24
  validateChangelogJson(raw.changelogJson, config, errors);
24
- validateComponents(raw.components, config, errors);
25
+ validateWorkspaces(raw.workspaces, config, errors);
25
26
  validateReleaseNotes(raw.releaseNotes, config, errors);
26
27
  validateVersionPatterns(raw.versionPatterns, config, errors);
27
28
  validateWorkTypes(raw.workTypes, config, errors);
28
29
  validateStringField("formatCommand", raw.formatCommand, config, errors);
29
30
  validateStringField("cliffConfigPath", raw.cliffConfigPath, config, errors);
30
31
  validateScopeAliases(raw.scopeAliases, config, errors);
32
+ validateRetiredPackages(raw.retiredPackages, config, errors);
31
33
  const warnings = [];
32
34
  const changelogJsonEnabled = config.changelogJson?.enabled ?? true;
33
- if (!changelogJsonEnabled) {
34
- if (config.releaseNotes?.shouldCreateGithubRelease) {
35
- warnings.push(
36
- "releaseNotes.shouldCreateGithubRelease is enabled but changelogJson.enabled is false; GitHub Releases will be skipped at runtime"
37
- );
38
- }
39
- if (config.releaseNotes?.shouldInjectIntoReadme) {
40
- warnings.push(
41
- "releaseNotes.shouldInjectIntoReadme is enabled but changelogJson.enabled is false; README injection will be skipped at runtime"
42
- );
43
- }
35
+ if (!changelogJsonEnabled && config.releaseNotes?.shouldInjectIntoReadme) {
36
+ warnings.push(
37
+ "releaseNotes.shouldInjectIntoReadme is enabled but changelogJson.enabled is false; README injection will be skipped at runtime"
38
+ );
44
39
  }
45
40
  return { config, errors, warnings };
46
41
  }
@@ -86,10 +81,16 @@ function validateReleaseNotes(value, config, errors) {
86
81
  errors.push("'releaseNotes' must be an object");
87
82
  return;
88
83
  }
89
- const knownReleaseNotesFields = /* @__PURE__ */ new Set(["shouldInjectIntoReadme", "shouldCreateGithubRelease"]);
84
+ const knownReleaseNotesFields = /* @__PURE__ */ new Set(["shouldInjectIntoReadme"]);
90
85
  for (const key of Object.keys(value)) {
91
86
  if (!knownReleaseNotesFields.has(key)) {
92
- errors.push(`releaseNotes: unknown field '${key}'`);
87
+ if (key === "shouldCreateGithubRelease") {
88
+ errors.push(
89
+ "releaseNotes.shouldCreateGithubRelease is no longer supported. Adoption is now signaled by installing the create-github-release workflow. Remove this field from your config; see README for the updated workflow."
90
+ );
91
+ } else {
92
+ errors.push(`releaseNotes: unknown field '${key}'`);
93
+ }
93
94
  }
94
95
  }
95
96
  const result = {};
@@ -100,57 +101,199 @@ function validateReleaseNotes(value, config, errors) {
100
101
  errors.push("releaseNotes.shouldInjectIntoReadme: must be a boolean");
101
102
  }
102
103
  }
103
- if (value.shouldCreateGithubRelease !== void 0) {
104
- if (typeof value.shouldCreateGithubRelease === "boolean") {
105
- result.shouldCreateGithubRelease = value.shouldCreateGithubRelease;
106
- } else {
107
- errors.push("releaseNotes.shouldCreateGithubRelease: must be a boolean");
108
- }
109
- }
110
104
  config.releaseNotes = result;
111
105
  }
112
106
  function isStringArray(value) {
113
107
  return Array.isArray(value) && value.every((item) => typeof item === "string");
114
108
  }
115
- function validateComponents(value, config, errors) {
109
+ function validateWorkspaces(value, config, errors) {
116
110
  if (value === void 0) return;
117
111
  if (!Array.isArray(value)) {
118
- errors.push("'components' must be an array");
112
+ errors.push("'workspaces' must be an array");
119
113
  return;
120
114
  }
121
- const components = [];
122
- const knownComponentFields = /* @__PURE__ */ new Set(["dir", "shouldExclude"]);
115
+ const workspaces = [];
116
+ const knownWorkspaceFields = /* @__PURE__ */ new Set(["dir", "shouldExclude", "legacyIdentities"]);
123
117
  for (const [i, entry] of value.entries()) {
124
118
  if (!isRecord(entry)) {
125
- errors.push(`components[${i}]: must be an object`);
119
+ errors.push(`workspaces[${i}]: must be an object`);
126
120
  continue;
127
121
  }
128
122
  if (typeof entry.dir !== "string" || entry.dir === "") {
129
- errors.push(`components[${i}]: 'dir' is required`);
123
+ errors.push(`workspaces[${i}]: 'dir' is required`);
130
124
  continue;
131
125
  }
132
126
  for (const key of Object.keys(entry)) {
133
- if (!knownComponentFields.has(key)) {
127
+ if (!knownWorkspaceFields.has(key)) {
134
128
  if (key === "tagPrefix") {
135
129
  errors.push(
136
- `components[${i}]: 'tagPrefix' is no longer supported; remove it to use the default '${entry.dir}-v'`
130
+ `workspaces[${i}]: 'tagPrefix' is no longer supported; remove it to use the default '${entry.dir}-v'`
131
+ );
132
+ } else if (key === "legacyTagPrefixes") {
133
+ errors.push(
134
+ `workspaces[${i}]: 'legacyTagPrefixes' is no longer supported; use 'legacyIdentities: [{ name, tagPrefix }, ...]' instead`
137
135
  );
138
136
  } else {
139
- errors.push(`components[${i}]: unknown field '${key}'`);
137
+ errors.push(`workspaces[${i}]: unknown field '${key}'`);
140
138
  }
141
139
  }
142
140
  }
143
- const component = { dir: entry.dir };
141
+ const workspace = { dir: entry.dir };
144
142
  if (entry.shouldExclude !== void 0) {
145
143
  if (typeof entry.shouldExclude === "boolean") {
146
- component.shouldExclude = entry.shouldExclude;
144
+ workspace.shouldExclude = entry.shouldExclude;
147
145
  } else {
148
- errors.push(`components[${i}]: 'shouldExclude' must be a boolean`);
146
+ errors.push(`workspaces[${i}]: 'shouldExclude' must be a boolean`);
147
+ }
148
+ }
149
+ if (entry.legacyIdentities !== void 0) {
150
+ const identities = validateLegacyIdentities(entry.legacyIdentities, i, errors);
151
+ if (identities !== void 0) {
152
+ workspace.legacyIdentities = identities;
153
+ }
154
+ }
155
+ workspaces.push(workspace);
156
+ }
157
+ config.workspaces = workspaces;
158
+ }
159
+ function validateLegacyIdentities(value, workspaceIndex, errors) {
160
+ if (!Array.isArray(value)) {
161
+ errors.push(`workspaces[${workspaceIndex}]: 'legacyIdentities' must be an array`);
162
+ return void 0;
163
+ }
164
+ const knownIdentityFields = /* @__PURE__ */ new Set(["name", "tagPrefix"]);
165
+ const identities = [];
166
+ const seenTuples = /* @__PURE__ */ new Set();
167
+ for (const [entryIndex, entry] of value.entries()) {
168
+ if (!isRecord(entry)) {
169
+ errors.push(`workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}]: must be an object`);
170
+ continue;
171
+ }
172
+ let entryValid = true;
173
+ for (const key2 of Object.keys(entry)) {
174
+ if (!knownIdentityFields.has(key2)) {
175
+ errors.push(`workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}]: unknown field '${key2}'`);
176
+ entryValid = false;
177
+ }
178
+ }
179
+ const { name, tagPrefix } = entry;
180
+ if (typeof name !== "string") {
181
+ errors.push(`workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}].name: must be a string`);
182
+ entryValid = false;
183
+ } else if (name === "") {
184
+ errors.push(`workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}].name: must be a non-empty string`);
185
+ entryValid = false;
186
+ }
187
+ if (typeof tagPrefix !== "string") {
188
+ errors.push(`workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}].tagPrefix: must be a string`);
189
+ entryValid = false;
190
+ } else if (tagPrefix === "") {
191
+ errors.push(
192
+ `workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}].tagPrefix: must be a non-empty string`
193
+ );
194
+ entryValid = false;
195
+ }
196
+ if (!entryValid || typeof name !== "string" || typeof tagPrefix !== "string") {
197
+ continue;
198
+ }
199
+ const key = `${name}\0${tagPrefix}`;
200
+ if (seenTuples.has(key)) {
201
+ errors.push(
202
+ `workspaces[${workspaceIndex}].legacyIdentities[${entryIndex}]: duplicate identity (name='${name}', tagPrefix='${tagPrefix}')`
203
+ );
204
+ continue;
205
+ }
206
+ seenTuples.add(key);
207
+ identities.push({ name, tagPrefix });
208
+ }
209
+ return identities;
210
+ }
211
+ function validateRetiredPackages(value, config, errors) {
212
+ if (value === void 0) return;
213
+ if (!Array.isArray(value)) {
214
+ errors.push("'retiredPackages' must be an array");
215
+ return;
216
+ }
217
+ const validEntries = [];
218
+ const seenTuples = /* @__PURE__ */ new Set();
219
+ for (const [i, entry] of value.entries()) {
220
+ const retired = validateRetiredPackageEntry(entry, i, errors);
221
+ if (retired === void 0) continue;
222
+ const key = `${retired.name}\0${retired.tagPrefix}`;
223
+ if (seenTuples.has(key)) {
224
+ errors.push(
225
+ `retiredPackages[${i}]: duplicate package (name='${retired.name}', tagPrefix='${retired.tagPrefix}')`
226
+ );
227
+ continue;
228
+ }
229
+ seenTuples.add(key);
230
+ validEntries.push({ entry: retired, rawIndex: i });
231
+ }
232
+ detectRetiredVsLegacyCollisions(validEntries, config, errors);
233
+ config.retiredPackages = validEntries.map(({ entry }) => entry);
234
+ }
235
+ function validateRetiredPackageEntry(entry, i, errors) {
236
+ if (!isRecord(entry)) {
237
+ errors.push(`retiredPackages[${i}]: must be an object`);
238
+ return void 0;
239
+ }
240
+ const knownRetiredFields = /* @__PURE__ */ new Set(["name", "tagPrefix", "successor"]);
241
+ let entryValid = true;
242
+ for (const key of Object.keys(entry)) {
243
+ if (!knownRetiredFields.has(key)) {
244
+ errors.push(`retiredPackages[${i}]: unknown field '${key}'`);
245
+ entryValid = false;
246
+ }
247
+ }
248
+ const { name, tagPrefix, successor } = entry;
249
+ if (!validateNonEmptyString(name, `retiredPackages[${i}].name`, errors)) {
250
+ entryValid = false;
251
+ }
252
+ if (!validateNonEmptyString(tagPrefix, `retiredPackages[${i}].tagPrefix`, errors)) {
253
+ entryValid = false;
254
+ }
255
+ if (successor !== void 0 && !validateNonEmptyString(successor, `retiredPackages[${i}].successor`, errors)) {
256
+ entryValid = false;
257
+ }
258
+ if (!entryValid || typeof name !== "string" || typeof tagPrefix !== "string") {
259
+ return void 0;
260
+ }
261
+ const retired = { name, tagPrefix };
262
+ if (typeof successor === "string" && successor !== "") {
263
+ retired.successor = successor;
264
+ }
265
+ return retired;
266
+ }
267
+ function detectRetiredVsLegacyCollisions(retiredPackages, config, errors) {
268
+ if (config.workspaces === void 0) return;
269
+ const legacyPrefixToWorkspace = /* @__PURE__ */ new Map();
270
+ for (const workspace of config.workspaces) {
271
+ if (workspace.legacyIdentities === void 0) continue;
272
+ for (const identity of workspace.legacyIdentities) {
273
+ if (!legacyPrefixToWorkspace.has(identity.tagPrefix)) {
274
+ legacyPrefixToWorkspace.set(identity.tagPrefix, workspace.dir);
149
275
  }
150
276
  }
151
- components.push(component);
152
277
  }
153
- config.components = components;
278
+ for (const { entry: retired, rawIndex } of retiredPackages) {
279
+ const collidingDir = legacyPrefixToWorkspace.get(retired.tagPrefix);
280
+ if (collidingDir !== void 0) {
281
+ errors.push(
282
+ `retiredPackages[${rawIndex}]: tagPrefix '${retired.tagPrefix}' collides with a declared legacyIdentities[].tagPrefix on workspace '${collidingDir}'`
283
+ );
284
+ }
285
+ }
286
+ }
287
+ function validateNonEmptyString(value, fieldPath, errors) {
288
+ if (typeof value !== "string") {
289
+ errors.push(`${fieldPath}: must be a string`);
290
+ return false;
291
+ }
292
+ if (value === "") {
293
+ errors.push(`${fieldPath}: must be a non-empty string`);
294
+ return false;
295
+ }
296
+ return true;
154
297
  }
155
298
  function validateVersionPatterns(value, config, errors) {
156
299
  if (value === void 0) return;
@@ -1 +1 @@
1
- export declare const VERSION = "4.8.0";
1
+ export declare const VERSION = "5.0.0";
@@ -1,4 +1,4 @@
1
- const VERSION = "4.8.0";
1
+ const VERSION = "5.0.0";
2
2
  export {
3
3
  VERSION
4
4
  };
@@ -0,0 +1,18 @@
1
+ export interface WriteReleaseNotesPreviewsOptions {
2
+ workspacePath: string;
3
+ tag: string;
4
+ changelogJsonPath: string;
5
+ sectionOrder: string[];
6
+ dryRun: boolean;
7
+ }
8
+ export interface PreviewFileResult {
9
+ filePath: string;
10
+ outcome: 'created' | 'overwritten' | 'skipped-no-readme' | 'failed' | 'dry-run';
11
+ error?: string;
12
+ }
13
+ export interface WriteReleaseNotesPreviewsResult {
14
+ injectedReadme?: PreviewFileResult;
15
+ releaseNotes?: PreviewFileResult;
16
+ renderSkipped: boolean;
17
+ }
18
+ export declare function writeReleaseNotesPreviews(options: WriteReleaseNotesPreviewsOptions): WriteReleaseNotesPreviewsResult;
@@ -0,0 +1,65 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { writeFileWithCheck } from "@williamthorsen/nmr-core";
4
+ import { extractVersion } from "./changelogJsonUtils.js";
5
+ import { dim } from "./format.js";
6
+ import { renderInjectedReadme } from "./injectReleaseNotesIntoReadme.js";
7
+ function writeReleaseNotesPreviews(options) {
8
+ const { workspacePath, tag, changelogJsonPath, sectionOrder, dryRun } = options;
9
+ const version = extractVersion(tag);
10
+ const readmePath = path.join(workspacePath, "README.md");
11
+ let readmeExists = existsSync(readmePath);
12
+ let readmeUnreadable = false;
13
+ let readmeContent = "";
14
+ if (readmeExists) {
15
+ try {
16
+ readmeContent = readFileSync(readmePath, "utf8");
17
+ } catch (error) {
18
+ const message = error instanceof Error ? error.message : String(error);
19
+ console.warn(`Warning: failed to read ${readmePath}: ${message}; skipping injected-README preview`);
20
+ readmeExists = false;
21
+ readmeUnreadable = true;
22
+ }
23
+ }
24
+ const rendered = renderInjectedReadme(readmeContent, changelogJsonPath, tag, sectionOrder);
25
+ if (rendered === void 0) {
26
+ return { renderSkipped: true };
27
+ }
28
+ const docsDir = path.join(workspacePath, "docs");
29
+ const readmePreviewPath = path.join(docsDir, `README.v${version}.md`);
30
+ const releaseNotesPreviewPath = path.join(docsDir, `RELEASE_NOTES.v${version}.md`);
31
+ let injectedReadme;
32
+ if (readmeExists) {
33
+ injectedReadme = writePreviewFile(readmePreviewPath, rendered.injectedReadme, dryRun);
34
+ } else {
35
+ if (!readmeUnreadable) {
36
+ console.warn(
37
+ `Warning: ${readmePath} not found; skipping injected-README preview but still writing standalone release notes`
38
+ );
39
+ }
40
+ injectedReadme = { filePath: readmePreviewPath, outcome: "skipped-no-readme" };
41
+ }
42
+ const releaseNotesContent = rendered.releaseNotesMarkdown.endsWith("\n") ? rendered.releaseNotesMarkdown : `${rendered.releaseNotesMarkdown}
43
+ `;
44
+ const releaseNotes = writePreviewFile(releaseNotesPreviewPath, releaseNotesContent, dryRun);
45
+ return { injectedReadme, releaseNotes, renderSkipped: false };
46
+ }
47
+ function writePreviewFile(filePath, content, dryRun) {
48
+ if (dryRun) {
49
+ console.info(dim(` [dry-run] Would write ${filePath}`));
50
+ return { filePath, outcome: "dry-run" };
51
+ }
52
+ const result = writeFileWithCheck(filePath, content, { dryRun: false, overwrite: true });
53
+ if (result.outcome === "failed") {
54
+ console.error(`Error writing ${filePath}: ${result.error ?? "unknown error"}`);
55
+ return { filePath, outcome: "failed", ...result.error === void 0 ? {} : { error: result.error } };
56
+ }
57
+ if (result.outcome === "created" || result.outcome === "overwritten") {
58
+ console.info(dim(` Wrote ${filePath}`));
59
+ return { filePath, outcome: result.outcome };
60
+ }
61
+ return { filePath, outcome: "failed", error: `unexpected outcome: ${result.outcome}` };
62
+ }
63
+ export {
64
+ writeReleaseNotesPreviews
65
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "4.8.0",
3
+ "version": "5.0.0",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/release-kit#readme",
@@ -35,7 +35,7 @@
35
35
  "jiti": "2.6.1",
36
36
  "js-yaml": "4.1.1",
37
37
  "json-stringify-pretty-compact": "4.0.0",
38
- "@williamthorsen/node-monorepo-core": "0.2.7"
38
+ "@williamthorsen/nmr-core": "0.3.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/js-yaml": "4.0.9",
@@ -1,2 +0,0 @@
1
- import type { ComponentConfig } from './types.ts';
2
- export declare function component(workspacePath: string): ComponentConfig;
@@ -1,14 +0,0 @@
1
- import { basename } from "node:path";
2
- function component(workspacePath) {
3
- const dir = basename(workspacePath);
4
- return {
5
- dir,
6
- tagPrefix: `${dir}-v`,
7
- packageFiles: [`${workspacePath}/package.json`],
8
- changelogPaths: [workspacePath],
9
- paths: [`${workspacePath}/**`]
10
- };
11
- }
12
- export {
13
- component
14
- };
@@ -1 +0,0 @@
1
- export declare function findPackageRoot(fromUrl: string): string;
@@ -1,17 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- function findPackageRoot(fromUrl) {
5
- let dir = dirname(fileURLToPath(fromUrl));
6
- while (!existsSync(resolve(dir, "package.json"))) {
7
- const parent = dirname(dir);
8
- if (parent === dir) {
9
- throw new Error("Could not find package root from " + fromUrl);
10
- }
11
- dir = parent;
12
- }
13
- return dir;
14
- }
15
- export {
16
- findPackageRoot
17
- };
@@ -1 +0,0 @@
1
- export declare function githubReleaseCommand(argv: string[]): Promise<void>;
@@ -1,35 +0,0 @@
1
- import { parseArgs, translateParseError } from "@williamthorsen/node-monorepo-core";
2
- import { createGithubReleases } from "./createGithubRelease.js";
3
- import { resolveCommandTags } from "./resolveCommandTags.js";
4
- import { resolveReleaseNotesConfig } from "./resolveReleaseNotesConfig.js";
5
- const githubReleaseFlagSchema = {
6
- dryRun: { long: "--dry-run", type: "boolean" },
7
- only: { long: "--only", type: "string" }
8
- };
9
- async function githubReleaseCommand(argv) {
10
- let parsed;
11
- try {
12
- parsed = parseArgs(argv, githubReleaseFlagSchema);
13
- } catch (error) {
14
- console.error(`Error: ${translateParseError(error)}`);
15
- process.exit(1);
16
- }
17
- const { dryRun } = parsed.flags;
18
- const only = parsed.flags.only?.split(",");
19
- const resolvedTags = await resolveCommandTags(only);
20
- const { releaseNotes, changelogJsonOutputPath } = await resolveReleaseNotesConfig();
21
- try {
22
- createGithubReleases(
23
- resolvedTags,
24
- { ...releaseNotes, shouldCreateGithubRelease: true },
25
- changelogJsonOutputPath,
26
- dryRun
27
- );
28
- } catch (error) {
29
- console.error(`Error creating GitHub Releases: ${error instanceof Error ? error.message : String(error)}`);
30
- process.exit(1);
31
- }
32
- }
33
- export {
34
- githubReleaseCommand
35
- };