@modulify/conventional-release 0.1.0 → 0.1.2

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/bin/cli.mjs CHANGED
@@ -1,291 +1,30 @@
1
+ import { run } from "../dist/index.mjs";
2
+ import { parseArgv } from "../dist/cli/args.mjs";
3
+ import { createReporter } from "../dist/cli/reporter.mjs";
4
+ import { ConsoleOutput, Output } from "../dist/cli/output.mjs";
1
5
  import { GitCommander } from "@modulify/git-toolkit";
2
6
  import { Runner } from "@modulify/git-toolkit/shell";
3
- import { run } from "../dist/index.mjs";
4
- import yargs from "yargs";
5
- import { hideBin } from "yargs/helpers";
6
- import chalk from "chalk";
7
- import figures from "figures";
8
- import * as util from "node:util";
9
- const DEFAULTS = {
10
- dry: false,
11
- verbose: false,
12
- tags: false
13
- };
14
- class CliParseError extends Error {
15
- help;
16
- }
17
- async function parseArgv(argv = process.argv) {
18
- const parser = yargs(hideBin(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
19
- alias: "r",
20
- describe: "Specify the release type (major|minor|patch)",
21
- requiresArg: true,
22
- string: true
23
- }).option("prerelease", {
24
- alias: "p",
25
- describe: "Specify the prerelease type (alpha|beta|rc)",
26
- requiresArg: true,
27
- string: true
28
- }).option("dry", {
29
- type: "boolean",
30
- default: DEFAULTS.dry,
31
- describe: "See the commands that running release would run"
32
- }).option("verbose", {
33
- type: "boolean",
34
- default: DEFAULTS.verbose,
35
- describe: "Show detailed per-slice progress output"
36
- }).option("tags", {
37
- type: "boolean",
38
- default: DEFAULTS.tags,
39
- describe: "Show generated tags in the final output"
40
- }).exitProcess(false).check((options) => {
41
- if (!["alpha", "beta", "rc", void 0].includes(options.prerelease)) {
42
- throw new Error("prerelease should be one of alpha, beta, rc or undefined");
43
- }
44
- return true;
45
- }).showHelpOnFail(false).fail((message) => {
46
- throw new Error(message);
47
- }).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
48
- let parsed;
49
- try {
50
- parsed = await parser.parseAsync();
51
- } catch (error) {
52
- const failure = new CliParseError(error.message);
53
- const help = await parser.getHelp();
54
- failure.help = [help].flat().join("\n");
55
- throw failure;
56
- }
57
- return {
58
- releaseAs: parsed.releaseAs,
59
- prerelease: parsed.prerelease,
60
- dry: parsed.dry,
61
- verbose: parsed.verbose,
62
- tags: parsed.tags
63
- };
64
- }
65
- function createReporter({
66
- output,
67
- git,
68
- showTags = false,
69
- verbosity = "summary"
70
- }) {
71
- if (verbosity === "detailed") {
72
- return new DetailedReporter({
73
- output,
74
- git,
75
- showTags
76
- });
77
- }
78
- return new SummaryReporter({
79
- output,
80
- git,
81
- showTags
82
- });
83
- }
84
- class SummaryReporter {
85
- output;
86
- git;
87
- showTags;
88
- scope = null;
89
- position = /* @__PURE__ */ new Map();
90
- constructor({
91
- output,
92
- git,
93
- showTags
94
- }) {
95
- this.output = output;
96
- this.git = git;
97
- this.showTags = showTags;
98
- }
99
- async onStart(context) {
100
- this.output.info(
101
- context.dry ? "Starting dry release" : "Starting release"
102
- );
103
- }
104
- async onScope(scope, context) {
105
- this.scope = scope;
106
- this.position = new Map(
107
- scope.slices.map((slice, index) => [slice.id, index + 1])
108
- );
109
- }
110
- async onSliceStart(slice) {
111
- this.output.info("Running slice %s", [this.describeProgress(slice)]);
112
- }
113
- async onSuccess(result) {
114
- if (!result.changed) {
115
- this.output.success("No changes since last release");
116
- return;
117
- }
118
- const changed = result.slices.filter((slice) => slice.changed);
119
- const primary = changed[0];
120
- const packages = collectPackages(changed);
121
- this.output.success("Release slices: %s", [String(changed.length)]);
122
- this.output.success("Updated packages: %s", [String(packages.length)]);
123
- if (primary) {
124
- this.output.success("Next version: %s", [primary.nextVersion]);
125
- }
126
- if (result.dry) {
127
- this.output.info("No committing or tagging since this was a dry run");
128
- return;
129
- }
130
- this.output.success("Committed %s staged files", [String(result.files.length)]);
131
- if (this.showTags) {
132
- const tags = collectTags(changed);
133
- if (tags.length) {
134
- this.output.success("Tags: %s", [tags.join(", ")]);
135
- }
136
- }
137
- this.output.info("Run `%s` to publish", [
138
- `git push --follow-tags origin ${await this.resolveBranch()}`
139
- ]);
140
- }
141
- async onError(error) {
142
- const message = error instanceof Error ? error.message : String(error);
143
- this.output.error(message);
144
- }
145
- describeProgress(slice) {
146
- const position = this.position.get(slice.id);
147
- const total = this.scope?.slices.length;
148
- const label = describeSlice(slice);
149
- return position && total ? `${position}/${total}: ${label}` : label;
150
- }
151
- async resolveBranch() {
152
- try {
153
- return await this.git.revParse("HEAD", { abbrevRef: true });
154
- } catch {
155
- return "%branch%";
156
- }
157
- }
158
- }
159
- class DetailedReporter extends SummaryReporter {
160
- async onScope(scope, context) {
161
- await super.onScope(scope, context);
162
- this.output.info("%s scope: %s packages, %s affected, %s slices", [
163
- scope.mode,
164
- String(scope.packages.length),
165
- String(scope.affected.length),
166
- String(scope.slices.length)
167
- ]);
168
- }
169
- async onSliceSuccess(slice) {
170
- if (!slice.changed) {
171
- this.output.warn("Completed slice %s without version changes (%s)", [
172
- describeSlice(slice),
173
- slice.currentVersion
174
- ]);
175
- return;
176
- }
177
- this.output.success("Completed slice %s: %s -> %s (%s)", [
178
- describeSlice(slice),
179
- slice.currentVersion,
180
- slice.nextVersion,
181
- slice.releaseType
182
- ]);
183
- if (this.showTags && slice.tag) {
184
- this.output.info("Tag: %s", [slice.tag]);
185
- }
186
- }
187
- async onSuccess(result) {
188
- await super.onSuccess(result);
189
- if (!result.changed) {
190
- return;
191
- }
192
- const packages = collectPackages(result.slices.filter((slice) => slice.changed));
193
- this.output.info("Updated packages: %s", [describePackages(packages)]);
194
- }
195
- }
196
- function describeSlice(slice) {
197
- if (slice.partition) {
198
- return `${slice.partition} [${describePackages(slice.packages)}]`;
199
- }
200
- return describePackages(slice.packages);
201
- }
202
- function describePackages(packages) {
203
- return packages.map((pkg) => pkg.name ?? pkg.path).join(", ");
204
- }
205
- function collectTags(slices) {
206
- return slices.map((slice) => slice.tag).filter((tag) => !!tag);
207
- }
208
- function collectPackages(slices) {
209
- const packages = [];
210
- const seen = /* @__PURE__ */ new Set();
211
- for (const slice of slices) {
212
- for (const pkg of slice.packages) {
213
- const identity = pkg.name ?? pkg.path;
214
- if (seen.has(identity)) {
215
- continue;
216
- }
217
- seen.add(identity);
218
- packages.push(pkg);
219
- }
220
- }
221
- return packages;
222
- }
223
- class ConsoleOutput {
224
- write(message) {
225
- console.info(message);
226
- }
227
- writeError(message) {
228
- console.error(message);
229
- }
230
- }
231
- class Output {
232
- output;
233
- theme;
234
- constructor({
235
- dry,
236
- output = new ConsoleOutput(),
237
- theme = createDefaultTheme(dry)
238
- }) {
239
- this.output = output;
240
- this.theme = theme;
241
- }
242
- info(template, context = [], figure = this.theme.info) {
243
- this.output.write(format(template, context, figure));
244
- }
245
- success(template, context = [], figure = this.theme.success) {
246
- this.output.write(format(template, context, figure));
247
- }
248
- warn(template, context = [], figure = this.theme.warning) {
249
- this.output.write(format(template, context, figure));
250
- }
251
- error(template, context = [], figure = this.theme.error) {
252
- this.output.writeError(format(template, context, figure));
253
- }
254
- }
255
- function createDefaultTheme(dry) {
256
- return {
257
- success: dry ? chalk.yellow(figures.tick) : chalk.green(figures.tick),
258
- warning: chalk.yellow(figures.warning),
259
- error: chalk.red(figures.cross),
260
- info: chalk.blue(figures.info)
261
- };
262
- }
263
- function format(template, context, figure) {
264
- const bold = (arg) => chalk.bold(arg);
265
- const message = util.format(template, ...context.map(bold));
266
- return `${figure} ${message}`;
267
- }
7
+ //#region src/cli.ts
268
8
  async function main(argv = process.argv) {
269
- const cwd = process.cwd();
270
- const options = await parseArgv(argv);
271
- const output = new Output({
272
- dry: options.dry,
273
- output: new ConsoleOutput()
274
- });
275
- const git = new GitCommander({ sh: new Runner(cwd) });
276
- await run({
277
- cwd,
278
- dry: options.dry,
279
- releaseAs: options.releaseAs,
280
- prerelease: options.prerelease,
281
- reporter: createReporter({
282
- output,
283
- git,
284
- showTags: options.tags,
285
- verbosity: options.verbose ? "detailed" : "summary"
286
- })
287
- });
288
- }
289
- export {
290
- main
291
- };
9
+ const cwd = process.cwd();
10
+ const options = await parseArgv(argv);
11
+ const output = new Output({
12
+ dry: options.dry,
13
+ output: new ConsoleOutput()
14
+ });
15
+ const git = new GitCommander({ sh: new Runner(cwd) });
16
+ await run({
17
+ cwd,
18
+ dry: options.dry,
19
+ releaseAs: options.releaseAs,
20
+ prerelease: options.prerelease,
21
+ reporter: createReporter({
22
+ output,
23
+ git,
24
+ showTags: options.tags,
25
+ verbosity: options.verbose ? "detailed" : "summary"
26
+ })
27
+ });
28
+ }
29
+ //#endregion
30
+ export { main };
@@ -0,0 +1,23 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ exports.__toESM = __toESM;
@@ -0,0 +1,67 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ let yargs = require("yargs");
3
+ yargs = require_runtime.__toESM(yargs, 1);
4
+ let yargs_helpers = require("yargs/helpers");
5
+ //#region src/cli/args.ts
6
+ var DEFAULTS = {
7
+ releaseAs: void 0,
8
+ prerelease: void 0,
9
+ dry: false,
10
+ verbose: false,
11
+ tags: false
12
+ };
13
+ var CliParseError = class extends Error {
14
+ help;
15
+ };
16
+ async function parseArgv(argv = process.argv) {
17
+ const parser = (0, yargs.default)((0, yargs_helpers.hideBin)(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
18
+ alias: "r",
19
+ describe: "Specify the release type (major|minor|patch)",
20
+ requiresArg: true,
21
+ string: true
22
+ }).option("prerelease", {
23
+ alias: "p",
24
+ describe: "Specify the prerelease type (alpha|beta|rc)",
25
+ requiresArg: true,
26
+ string: true
27
+ }).option("dry", {
28
+ type: "boolean",
29
+ default: DEFAULTS.dry,
30
+ describe: "See the commands that running release would run"
31
+ }).option("verbose", {
32
+ type: "boolean",
33
+ default: DEFAULTS.verbose,
34
+ describe: "Show detailed per-slice progress output"
35
+ }).option("tags", {
36
+ type: "boolean",
37
+ default: DEFAULTS.tags,
38
+ describe: "Show generated tags in the final output"
39
+ }).exitProcess(false).check((options) => {
40
+ if (![
41
+ "alpha",
42
+ "beta",
43
+ "rc",
44
+ void 0
45
+ ].includes(options.prerelease)) throw new Error("prerelease should be one of alpha, beta, rc or undefined");
46
+ return true;
47
+ }).showHelpOnFail(false).fail((message) => {
48
+ throw new Error(message);
49
+ }).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
50
+ let parsed;
51
+ try {
52
+ parsed = await parser.parseAsync();
53
+ } catch (error) {
54
+ const failure = new CliParseError(error.message);
55
+ failure.help = [await parser.getHelp()].flat().join("\n");
56
+ throw failure;
57
+ }
58
+ return {
59
+ releaseAs: parsed.releaseAs,
60
+ prerelease: parsed.prerelease,
61
+ dry: parsed.dry,
62
+ verbose: parsed.verbose,
63
+ tags: parsed.tags
64
+ };
65
+ }
66
+ //#endregion
67
+ exports.parseArgv = parseArgv;
@@ -0,0 +1,65 @@
1
+ import yargs from "yargs";
2
+ import { hideBin } from "yargs/helpers";
3
+ //#region src/cli/args.ts
4
+ var DEFAULTS = {
5
+ releaseAs: void 0,
6
+ prerelease: void 0,
7
+ dry: false,
8
+ verbose: false,
9
+ tags: false
10
+ };
11
+ var CliParseError = class extends Error {
12
+ help;
13
+ };
14
+ async function parseArgv(argv = process.argv) {
15
+ const parser = yargs(hideBin(argv)).locale("en").scriptName("conventional-release").usage("Usage: $0 [options]").option("release-as", {
16
+ alias: "r",
17
+ describe: "Specify the release type (major|minor|patch)",
18
+ requiresArg: true,
19
+ string: true
20
+ }).option("prerelease", {
21
+ alias: "p",
22
+ describe: "Specify the prerelease type (alpha|beta|rc)",
23
+ requiresArg: true,
24
+ string: true
25
+ }).option("dry", {
26
+ type: "boolean",
27
+ default: DEFAULTS.dry,
28
+ describe: "See the commands that running release would run"
29
+ }).option("verbose", {
30
+ type: "boolean",
31
+ default: DEFAULTS.verbose,
32
+ describe: "Show detailed per-slice progress output"
33
+ }).option("tags", {
34
+ type: "boolean",
35
+ default: DEFAULTS.tags,
36
+ describe: "Show generated tags in the final output"
37
+ }).exitProcess(false).check((options) => {
38
+ if (![
39
+ "alpha",
40
+ "beta",
41
+ "rc",
42
+ void 0
43
+ ].includes(options.prerelease)) throw new Error("prerelease should be one of alpha, beta, rc or undefined");
44
+ return true;
45
+ }).showHelpOnFail(false).fail((message) => {
46
+ throw new Error(message);
47
+ }).alias("version", "v").alias("help", "h").example("$0", "Update changelog and tag release").example("$0 --dry --verbose", "Show a detailed dry-run release preview").pkgConf("release").wrap(97);
48
+ let parsed;
49
+ try {
50
+ parsed = await parser.parseAsync();
51
+ } catch (error) {
52
+ const failure = new CliParseError(error.message);
53
+ failure.help = [await parser.getHelp()].flat().join("\n");
54
+ throw failure;
55
+ }
56
+ return {
57
+ releaseAs: parsed.releaseAs,
58
+ prerelease: parsed.prerelease,
59
+ dry: parsed.dry,
60
+ verbose: parsed.verbose,
61
+ tags: parsed.tags
62
+ };
63
+ }
64
+ //#endregion
65
+ export { parseArgv };
@@ -0,0 +1,51 @@
1
+ const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
2
+ let chalk = require("chalk");
3
+ chalk = require_runtime.__toESM(chalk, 1);
4
+ let figures = require("figures");
5
+ figures = require_runtime.__toESM(figures, 1);
6
+ let node_util = require("node:util");
7
+ node_util = require_runtime.__toESM(node_util, 1);
8
+ //#region src/cli/output.ts
9
+ var ConsoleOutput = class {
10
+ write(message) {
11
+ console.info(message);
12
+ }
13
+ writeError(message) {
14
+ console.error(message);
15
+ }
16
+ };
17
+ var Output = class {
18
+ output;
19
+ theme;
20
+ constructor({ dry, output = new ConsoleOutput(), theme = createDefaultTheme(dry) }) {
21
+ this.output = output;
22
+ this.theme = theme;
23
+ }
24
+ info(template, context = [], figure = this.theme.info) {
25
+ this.output.write(format(template, context, figure));
26
+ }
27
+ success(template, context = [], figure = this.theme.success) {
28
+ this.output.write(format(template, context, figure));
29
+ }
30
+ warn(template, context = [], figure = this.theme.warning) {
31
+ this.output.write(format(template, context, figure));
32
+ }
33
+ error(template, context = [], figure = this.theme.error) {
34
+ this.output.writeError(format(template, context, figure));
35
+ }
36
+ };
37
+ function createDefaultTheme(dry) {
38
+ return {
39
+ success: dry ? chalk.default.yellow(figures.default.tick) : chalk.default.green(figures.default.tick),
40
+ warning: chalk.default.yellow(figures.default.warning),
41
+ error: chalk.default.red(figures.default.cross),
42
+ info: chalk.default.blue(figures.default.info)
43
+ };
44
+ }
45
+ function format(template, context, figure) {
46
+ const bold = (arg) => chalk.default.bold(arg);
47
+ return `${figure} ${node_util.format(template, ...context.map(bold))}`;
48
+ }
49
+ //#endregion
50
+ exports.ConsoleOutput = ConsoleOutput;
51
+ exports.Output = Output;
@@ -0,0 +1,46 @@
1
+ import chalk from "chalk";
2
+ import figures from "figures";
3
+ import * as util from "node:util";
4
+ //#region src/cli/output.ts
5
+ var ConsoleOutput = class {
6
+ write(message) {
7
+ console.info(message);
8
+ }
9
+ writeError(message) {
10
+ console.error(message);
11
+ }
12
+ };
13
+ var Output = class {
14
+ output;
15
+ theme;
16
+ constructor({ dry, output = new ConsoleOutput(), theme = createDefaultTheme(dry) }) {
17
+ this.output = output;
18
+ this.theme = theme;
19
+ }
20
+ info(template, context = [], figure = this.theme.info) {
21
+ this.output.write(format(template, context, figure));
22
+ }
23
+ success(template, context = [], figure = this.theme.success) {
24
+ this.output.write(format(template, context, figure));
25
+ }
26
+ warn(template, context = [], figure = this.theme.warning) {
27
+ this.output.write(format(template, context, figure));
28
+ }
29
+ error(template, context = [], figure = this.theme.error) {
30
+ this.output.writeError(format(template, context, figure));
31
+ }
32
+ };
33
+ function createDefaultTheme(dry) {
34
+ return {
35
+ success: dry ? chalk.yellow(figures.tick) : chalk.green(figures.tick),
36
+ warning: chalk.yellow(figures.warning),
37
+ error: chalk.red(figures.cross),
38
+ info: chalk.blue(figures.info)
39
+ };
40
+ }
41
+ function format(template, context, figure) {
42
+ const bold = (arg) => chalk.bold(arg);
43
+ return `${figure} ${util.format(template, ...context.map(bold))}`;
44
+ }
45
+ //#endregion
46
+ export { ConsoleOutput, Output };
@@ -0,0 +1,127 @@
1
+ //#region src/cli/reporter.ts
2
+ function createReporter({ output, git, showTags = false, verbosity = "summary" }) {
3
+ if (verbosity === "detailed") return new DetailedReporter({
4
+ output,
5
+ git,
6
+ showTags
7
+ });
8
+ return new SummaryReporter({
9
+ output,
10
+ git,
11
+ showTags
12
+ });
13
+ }
14
+ var SummaryReporter = class {
15
+ output;
16
+ git;
17
+ showTags;
18
+ scope = null;
19
+ position = /* @__PURE__ */ new Map();
20
+ constructor({ output, git, showTags }) {
21
+ this.output = output;
22
+ this.git = git;
23
+ this.showTags = showTags;
24
+ }
25
+ async onStart(context) {
26
+ this.output.info(context.dry ? "Starting dry release" : "Starting release");
27
+ }
28
+ async onScope(scope, context) {
29
+ this.scope = scope;
30
+ this.position = new Map(scope.slices.map((slice, index) => [slice.id, index + 1]));
31
+ }
32
+ async onSliceStart(slice) {
33
+ this.output.info("Running slice %s", [this.describeProgress(slice)]);
34
+ }
35
+ async onSuccess(result) {
36
+ if (!result.changed) {
37
+ this.output.success("No changes since last release");
38
+ return;
39
+ }
40
+ const changed = result.slices.filter((slice) => slice.changed);
41
+ const primary = changed[0];
42
+ const packages = collectPackages(changed);
43
+ this.output.success("Release slices: %s", [String(changed.length)]);
44
+ this.output.success("Updated packages: %s", [String(packages.length)]);
45
+ if (primary) this.output.success("Next version: %s", [primary.nextVersion]);
46
+ if (result.dry) {
47
+ this.output.info("No committing or tagging since this was a dry run");
48
+ return;
49
+ }
50
+ this.output.success("Committed %s staged files", [String(result.files.length)]);
51
+ if (this.showTags) {
52
+ const tags = collectTags(changed);
53
+ if (tags.length) this.output.success("Tags: %s", [tags.join(", ")]);
54
+ }
55
+ this.output.info("Run `%s` to publish", [`git push --follow-tags origin ${await this.resolveBranch()}`]);
56
+ }
57
+ async onError(error) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ this.output.error(message);
60
+ }
61
+ describeProgress(slice) {
62
+ const position = this.position.get(slice.id);
63
+ const total = this.scope?.slices.length;
64
+ const label = describeSlice(slice);
65
+ return position && total ? `${position}/${total}: ${label}` : label;
66
+ }
67
+ async resolveBranch() {
68
+ try {
69
+ return await this.git.revParse("HEAD", { abbrevRef: true });
70
+ } catch {
71
+ return "%branch%";
72
+ }
73
+ }
74
+ };
75
+ var DetailedReporter = class extends SummaryReporter {
76
+ async onScope(scope, context) {
77
+ await super.onScope(scope, context);
78
+ this.output.info("%s scope: %s packages, %s affected, %s slices", [
79
+ scope.mode,
80
+ String(scope.packages.length),
81
+ String(scope.affected.length),
82
+ String(scope.slices.length)
83
+ ]);
84
+ }
85
+ async onSliceSuccess(slice) {
86
+ if (!slice.changed) {
87
+ this.output.warn("Completed slice %s without version changes (%s)", [describeSlice(slice), slice.currentVersion]);
88
+ return;
89
+ }
90
+ this.output.success("Completed slice %s: %s -> %s (%s)", [
91
+ describeSlice(slice),
92
+ slice.currentVersion,
93
+ slice.nextVersion,
94
+ slice.releaseType
95
+ ]);
96
+ if (this.showTags && slice.tag) this.output.info("Tag: %s", [slice.tag]);
97
+ }
98
+ async onSuccess(result) {
99
+ await super.onSuccess(result);
100
+ if (!result.changed) return;
101
+ const packages = collectPackages(result.slices.filter((slice) => slice.changed));
102
+ this.output.info("Updated packages: %s", [describePackages(packages)]);
103
+ }
104
+ };
105
+ function describeSlice(slice) {
106
+ if (slice.partition) return `${slice.partition} [${describePackages(slice.packages)}]`;
107
+ return describePackages(slice.packages);
108
+ }
109
+ function describePackages(packages) {
110
+ return packages.map((pkg) => pkg.name ?? pkg.path).join(", ");
111
+ }
112
+ function collectTags(slices) {
113
+ return slices.map((slice) => slice.tag).filter((tag) => !!tag);
114
+ }
115
+ function collectPackages(slices) {
116
+ const packages = [];
117
+ const seen = /* @__PURE__ */ new Set();
118
+ for (const slice of slices) for (const pkg of slice.packages) {
119
+ const identity = pkg.name ?? pkg.path;
120
+ if (seen.has(identity)) continue;
121
+ seen.add(identity);
122
+ packages.push(pkg);
123
+ }
124
+ return packages;
125
+ }
126
+ //#endregion
127
+ exports.createReporter = createReporter;