package-versioner 0.2.0 → 0.3.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.
- package/README.md +36 -3
- package/dist/index.cjs +713 -576
- package/dist/index.js +711 -575
- package/docs/CI_CD_INTEGRATION.md +165 -0
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -26,90 +26,136 @@ function loadConfig(configPath) {
|
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
// src/
|
|
30
|
-
import
|
|
29
|
+
// src/core/versionEngine.ts
|
|
30
|
+
import { cwd as cwd4 } from "node:process";
|
|
31
|
+
import { getPackagesSync } from "@manypkg/get-packages";
|
|
32
|
+
|
|
33
|
+
// src/errors/gitError.ts
|
|
34
|
+
var GitError = class extends Error {
|
|
35
|
+
constructor(message, code) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.code = code;
|
|
38
|
+
this.name = "GitError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
function createGitError(code, details) {
|
|
42
|
+
const messages = {
|
|
43
|
+
["NOT_GIT_REPO" /* NOT_GIT_REPO */]: "Not a git repository",
|
|
44
|
+
["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
|
|
45
|
+
["NO_FILES" /* NO_FILES */]: "No files specified for commit",
|
|
46
|
+
["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
|
|
47
|
+
["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
|
|
48
|
+
};
|
|
49
|
+
const baseMessage = messages[code];
|
|
50
|
+
const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
|
|
51
|
+
return new GitError(fullMessage, code);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/errors/versionError.ts
|
|
55
|
+
var VersionError = class extends Error {
|
|
56
|
+
constructor(message, code) {
|
|
57
|
+
super(message);
|
|
58
|
+
this.code = code;
|
|
59
|
+
this.name = "VersionError";
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
function createVersionError(code, details) {
|
|
63
|
+
const messages = {
|
|
64
|
+
["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: "Configuration is required",
|
|
65
|
+
["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: "Failed to get packages information",
|
|
66
|
+
["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: "Failed to get workspace packages",
|
|
67
|
+
["INVALID_CONFIG" /* INVALID_CONFIG */]: "Invalid configuration",
|
|
68
|
+
["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
|
|
69
|
+
["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
|
|
70
|
+
};
|
|
71
|
+
const baseMessage = messages[code];
|
|
72
|
+
const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
|
|
73
|
+
return new VersionError(fullMessage, code);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/utils/logging.ts
|
|
31
77
|
import chalk from "chalk";
|
|
32
78
|
import figlet from "figlet";
|
|
33
79
|
|
|
34
|
-
//
|
|
35
|
-
var
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
main: "./dist/index.js",
|
|
41
|
-
module: "./dist/index.mjs",
|
|
42
|
-
types: "./dist/index.d.ts",
|
|
43
|
-
author: {
|
|
44
|
-
name: "Sam Maister",
|
|
45
|
-
email: "goosewobbler@protonmail.com"
|
|
46
|
-
},
|
|
47
|
-
repository: {
|
|
48
|
-
type: "git",
|
|
49
|
-
url: "https://github.com/goosewobbler/package-versioner",
|
|
50
|
-
homepage: "https://github.com/goosewobbler/package-versioner"
|
|
51
|
-
},
|
|
52
|
-
keywords: ["version", "semver", "git", "package"],
|
|
53
|
-
license: "MIT",
|
|
54
|
-
files: ["dist/**", "docs/**", "package-versioner.schema.json"],
|
|
55
|
-
bin: {
|
|
56
|
-
"package-versioner": "./dist/index.js"
|
|
57
|
-
},
|
|
58
|
-
scripts: {
|
|
59
|
-
build: "tsup src/index.ts --format esm,cjs --dts",
|
|
60
|
-
dev: "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
61
|
-
clean: "rm -rf node_modules && rm -rf dist",
|
|
62
|
-
test: "vitest run --coverage",
|
|
63
|
-
"test:watch": "vitest --coverage",
|
|
64
|
-
lint: "biome check .",
|
|
65
|
-
"lint:fix": "biome check --apply .",
|
|
66
|
-
format: "biome format --write .",
|
|
67
|
-
"format:check": "biome format .",
|
|
68
|
-
fix: "pnpm run lint:fix && pnpm run format",
|
|
69
|
-
prepare: "husky"
|
|
70
|
-
},
|
|
71
|
-
"lint-staged": {
|
|
72
|
-
"*.{js,ts,jsx,tsx}": ["biome check --apply", "biome format --write"]
|
|
73
|
-
},
|
|
74
|
-
devDependencies: {
|
|
75
|
-
"@biomejs/biome": "^1.9.4",
|
|
76
|
-
"@types/figlet": "^1.5.5",
|
|
77
|
-
"@types/node": "^22.14.0",
|
|
78
|
-
"@types/semver": "^7.3.13",
|
|
79
|
-
"@vitest/coverage-v8": "^3.1.1",
|
|
80
|
-
husky: "^9.1.7",
|
|
81
|
-
"lint-staged": "^15.5.0",
|
|
82
|
-
tsup: "^8.4.0",
|
|
83
|
-
typescript: "^5.8.3",
|
|
84
|
-
vitest: "^3.1.1"
|
|
85
|
-
},
|
|
86
|
-
dependencies: {
|
|
87
|
-
"@manypkg/get-packages": "^2.2.2",
|
|
88
|
-
chalk: "^5.4.1",
|
|
89
|
-
commander: "^13.1.0",
|
|
90
|
-
"conventional-changelog-angular": "^8.0.0",
|
|
91
|
-
"conventional-recommended-bump": "^11.0.0",
|
|
92
|
-
figlet: "^1.8.0",
|
|
93
|
-
"git-semver-tags": "^8.0.0",
|
|
94
|
-
semver: "^7.7.1"
|
|
95
|
-
},
|
|
96
|
-
packageManager: "pnpm@10.8.0+sha512.0e82714d1b5b43c74610193cb20734897c1d00de89d0e18420aebc5977fa13d780a9cb05734624e81ebd81cc876cd464794850641c48b9544326b5622ca29971"
|
|
80
|
+
// src/utils/jsonOutput.ts
|
|
81
|
+
var _jsonOutputMode = false;
|
|
82
|
+
var _jsonData = {
|
|
83
|
+
dryRun: false,
|
|
84
|
+
updates: [],
|
|
85
|
+
tags: []
|
|
97
86
|
};
|
|
87
|
+
function enableJsonOutput(dryRun = false) {
|
|
88
|
+
_jsonOutputMode = true;
|
|
89
|
+
_jsonData.dryRun = dryRun;
|
|
90
|
+
_jsonData.updates = [];
|
|
91
|
+
_jsonData.tags = [];
|
|
92
|
+
_jsonData.commitMessage = void 0;
|
|
93
|
+
}
|
|
94
|
+
function isJsonOutputMode() {
|
|
95
|
+
return _jsonOutputMode;
|
|
96
|
+
}
|
|
97
|
+
function addPackageUpdate(packageName, newVersion, filePath) {
|
|
98
|
+
if (!_jsonOutputMode) return;
|
|
99
|
+
_jsonData.updates.push({
|
|
100
|
+
packageName,
|
|
101
|
+
newVersion,
|
|
102
|
+
filePath
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function addTag(tag) {
|
|
106
|
+
if (!_jsonOutputMode) return;
|
|
107
|
+
_jsonData.tags.push(tag);
|
|
108
|
+
}
|
|
109
|
+
function setCommitMessage(message) {
|
|
110
|
+
if (!_jsonOutputMode) return;
|
|
111
|
+
_jsonData.commitMessage = message;
|
|
112
|
+
}
|
|
113
|
+
function printJsonOutput() {
|
|
114
|
+
if (_jsonOutputMode) {
|
|
115
|
+
console.log(JSON.stringify(_jsonData, null, 2));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
98
118
|
|
|
99
|
-
// src/utils.ts
|
|
100
|
-
|
|
119
|
+
// src/utils/logging.ts
|
|
120
|
+
function log(message, status = "info") {
|
|
121
|
+
if (isJsonOutputMode() && status !== "error") {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
let chalkFn;
|
|
125
|
+
switch (status) {
|
|
126
|
+
case "success":
|
|
127
|
+
chalkFn = chalk.green;
|
|
128
|
+
break;
|
|
129
|
+
case "warning":
|
|
130
|
+
chalkFn = chalk.yellow;
|
|
131
|
+
break;
|
|
132
|
+
case "error":
|
|
133
|
+
chalkFn = chalk.red;
|
|
134
|
+
break;
|
|
135
|
+
case "debug":
|
|
136
|
+
chalkFn = chalk.gray;
|
|
137
|
+
break;
|
|
138
|
+
default:
|
|
139
|
+
chalkFn = chalk.blue;
|
|
140
|
+
}
|
|
141
|
+
console.log(chalkFn(message));
|
|
142
|
+
}
|
|
101
143
|
|
|
102
|
-
// src/
|
|
103
|
-
import
|
|
104
|
-
import
|
|
105
|
-
|
|
144
|
+
// src/core/versionStrategies.ts
|
|
145
|
+
import fs3 from "node:fs";
|
|
146
|
+
import path2 from "node:path";
|
|
147
|
+
|
|
148
|
+
// src/git/commands.ts
|
|
106
149
|
import { cwd as cwd2 } from "node:process";
|
|
107
|
-
|
|
150
|
+
|
|
151
|
+
// src/git/commandExecutor.ts
|
|
152
|
+
import { exec, execSync as nativeExecSync } from "node:child_process";
|
|
153
|
+
var execAsync = (command, options) => {
|
|
154
|
+
const defaultOptions = { maxBuffer: 1024 * 1024 * 10, ...options };
|
|
108
155
|
return new Promise((resolve, reject) => {
|
|
109
|
-
const options = { maxBuffer: 1024 * 1024 * 10 };
|
|
110
156
|
exec(
|
|
111
157
|
command,
|
|
112
|
-
|
|
158
|
+
defaultOptions,
|
|
113
159
|
(error, stdout, stderr) => {
|
|
114
160
|
if (error) {
|
|
115
161
|
reject(error);
|
|
@@ -120,7 +166,33 @@ var execAsync = (command) => {
|
|
|
120
166
|
);
|
|
121
167
|
});
|
|
122
168
|
};
|
|
123
|
-
var execSync = (command, args) =>
|
|
169
|
+
var execSync = (command, args) => nativeExecSync(command, { maxBuffer: 1024 * 1024 * 10, ...args });
|
|
170
|
+
|
|
171
|
+
// src/git/repository.ts
|
|
172
|
+
import { existsSync, statSync } from "node:fs";
|
|
173
|
+
import { join } from "node:path";
|
|
174
|
+
function isGitRepository(directory) {
|
|
175
|
+
const gitDir = join(directory, ".git");
|
|
176
|
+
if (!existsSync(gitDir)) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
const stats = statSync(gitDir);
|
|
180
|
+
if (!stats.isDirectory()) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
execSync("git rev-parse --is-inside-work-tree", { cwd: directory });
|
|
185
|
+
return true;
|
|
186
|
+
} catch (_error) {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function getCurrentBranch() {
|
|
191
|
+
const result = execSync("git rev-parse --abbrev-ref HEAD");
|
|
192
|
+
return result.toString().trim();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/git/commands.ts
|
|
124
196
|
async function gitAdd(files) {
|
|
125
197
|
const command = `git add ${files.join(" ")}`;
|
|
126
198
|
return execAsync(command);
|
|
@@ -147,36 +219,12 @@ async function createGitTag(options) {
|
|
|
147
219
|
const command = `git tag -a -m "${message}" ${tag} ${args}`;
|
|
148
220
|
return execAsync(command);
|
|
149
221
|
}
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return Number(amount);
|
|
155
|
-
} catch {
|
|
156
|
-
return 0;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
function isGitRepository(directory) {
|
|
160
|
-
const gitDir = join(directory, ".git");
|
|
161
|
-
if (!existsSync(gitDir)) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
const stats = statSync(gitDir);
|
|
165
|
-
if (!stats.isDirectory()) {
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
try {
|
|
169
|
-
execSync("git rev-parse --is-inside-work-tree", { cwd: directory });
|
|
170
|
-
return true;
|
|
171
|
-
} catch (_error) {
|
|
172
|
-
return false;
|
|
222
|
+
async function gitProcess(options) {
|
|
223
|
+
const { files, nextTag, commitMessage, skipHooks, dryRun } = options;
|
|
224
|
+
if (!isGitRepository(cwd2())) {
|
|
225
|
+
throw createGitError("NOT_GIT_REPO" /* NOT_GIT_REPO */);
|
|
173
226
|
}
|
|
174
|
-
}
|
|
175
|
-
async function gitProcess({ files, nextTag, commitMessage, skipHooks, dryRun }) {
|
|
176
227
|
try {
|
|
177
|
-
if (!isGitRepository(cwd2())) {
|
|
178
|
-
throw new Error("Not a git repository (or any parent up to mount point /)");
|
|
179
|
-
}
|
|
180
228
|
if (!dryRun) {
|
|
181
229
|
await gitAdd(files);
|
|
182
230
|
await gitCommit({
|
|
@@ -191,503 +239,301 @@ async function gitProcess({ files, nextTag, commitMessage, skipHooks, dryRun })
|
|
|
191
239
|
});
|
|
192
240
|
}
|
|
193
241
|
} else {
|
|
194
|
-
log("
|
|
242
|
+
log("[DRY RUN] Would add files:", "info");
|
|
195
243
|
for (const file of files) {
|
|
196
|
-
log(
|
|
244
|
+
log(` - ${file}`, "info");
|
|
197
245
|
}
|
|
198
|
-
log(
|
|
246
|
+
log(`[DRY RUN] Would commit with message: "${commitMessage}"`, "info");
|
|
199
247
|
if (nextTag) {
|
|
200
|
-
log(
|
|
248
|
+
log(`[DRY RUN] Would create tag: ${nextTag}`, "info");
|
|
201
249
|
}
|
|
202
250
|
}
|
|
203
251
|
} catch (err) {
|
|
204
|
-
console.log(err);
|
|
205
252
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
206
|
-
throw
|
|
253
|
+
throw createGitError("GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */, errorMessage);
|
|
207
254
|
}
|
|
208
255
|
}
|
|
209
|
-
async function
|
|
256
|
+
async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, dryRun) {
|
|
210
257
|
try {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
258
|
+
if (!files || files.length === 0) {
|
|
259
|
+
throw createGitError("NO_FILES" /* NO_FILES */);
|
|
260
|
+
}
|
|
261
|
+
if (!commitMessage) {
|
|
262
|
+
throw createGitError("NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */);
|
|
263
|
+
}
|
|
264
|
+
setCommitMessage(commitMessage);
|
|
265
|
+
if (nextTag) {
|
|
266
|
+
addTag(nextTag);
|
|
267
|
+
}
|
|
268
|
+
await gitProcess({
|
|
269
|
+
files,
|
|
270
|
+
nextTag,
|
|
271
|
+
commitMessage,
|
|
272
|
+
skipHooks,
|
|
273
|
+
dryRun
|
|
274
|
+
});
|
|
275
|
+
if (!dryRun) {
|
|
276
|
+
log(`Created tag: ${nextTag}`, "success");
|
|
277
|
+
}
|
|
215
278
|
} catch (error) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
279
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
280
|
+
log(`Failed to create git commit and tag: ${errorMessage}`, "error");
|
|
281
|
+
if (error instanceof Error) {
|
|
282
|
+
console.error(error.stack || error.message);
|
|
283
|
+
} else {
|
|
284
|
+
console.error(error);
|
|
285
|
+
}
|
|
286
|
+
throw new GitError(`Git operation failed: ${errorMessage}`, "GIT_ERROR" /* GIT_ERROR */);
|
|
221
287
|
}
|
|
222
288
|
}
|
|
223
|
-
function getCurrentBranch() {
|
|
224
|
-
const result = execSync("git rev-parse --abbrev-ref HEAD");
|
|
225
|
-
return result.toString().trim();
|
|
226
|
-
}
|
|
227
289
|
|
|
228
|
-
// src/
|
|
229
|
-
|
|
230
|
-
const font = "Standard";
|
|
231
|
-
figlet.text(package_default.name, { font }, (err, data) => {
|
|
232
|
-
if (err) {
|
|
233
|
-
log("warning", "Could not print figlet banner: Figlet error");
|
|
234
|
-
console.error(err);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
if (data) {
|
|
238
|
-
const figletText = data;
|
|
239
|
-
const versionText = `v${package_default.version}`;
|
|
240
|
-
process.stdout.write(`${chalk.hex("#FF1F57")(figletText)}
|
|
241
|
-
`);
|
|
242
|
-
process.stdout.write(`${chalk.hex("#0096FF")(versionText)}
|
|
290
|
+
// src/git/tagsAndBranches.ts
|
|
291
|
+
import { getSemverTags } from "git-semver-tags";
|
|
243
292
|
|
|
244
|
-
|
|
293
|
+
// src/utils/formatting.ts
|
|
294
|
+
function escapeRegExp(string) {
|
|
295
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
296
|
+
}
|
|
297
|
+
function formatTag(version, tagPrefix) {
|
|
298
|
+
if (!tagPrefix) return version;
|
|
299
|
+
return tagPrefix.endsWith("/") ? `${tagPrefix}${version}` : `${tagPrefix}/${version}`;
|
|
300
|
+
}
|
|
301
|
+
function formatTagPrefix(tagPrefix, scope) {
|
|
302
|
+
if (!tagPrefix) return "";
|
|
303
|
+
const prefix = tagPrefix.replace(/\/$/, "");
|
|
304
|
+
if (scope) {
|
|
305
|
+
return `${prefix}/${scope}`;
|
|
306
|
+
}
|
|
307
|
+
return prefix;
|
|
308
|
+
}
|
|
309
|
+
function formatCommitMessage(template, version, scope) {
|
|
310
|
+
return createTemplateString(template, { version, scope });
|
|
311
|
+
}
|
|
312
|
+
function createTemplateString(template, variables) {
|
|
313
|
+
return Object.entries(variables).reduce((result, [key, value]) => {
|
|
314
|
+
if (value === void 0) {
|
|
315
|
+
return result;
|
|
245
316
|
}
|
|
246
|
-
|
|
317
|
+
const regex = new RegExp(`\\$\\{${key}\\}`, "g");
|
|
318
|
+
return result.replace(regex, value);
|
|
319
|
+
}, template);
|
|
247
320
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
321
|
+
|
|
322
|
+
// src/git/tagsAndBranches.ts
|
|
323
|
+
function getCommitsLength(pkgRoot) {
|
|
324
|
+
try {
|
|
325
|
+
const gitCommand = `git rev-list --count HEAD ^$(git describe --tags --abbrev=0) ${pkgRoot}`;
|
|
326
|
+
const amount = execSync(gitCommand).toString().trim();
|
|
327
|
+
return Number(amount);
|
|
328
|
+
} catch (error) {
|
|
329
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
330
|
+
log(`Failed to get number of commits since last tag: ${errorMessage}`, "error");
|
|
331
|
+
return 0;
|
|
332
|
+
}
|
|
257
333
|
}
|
|
258
334
|
async function getLatestTag() {
|
|
259
335
|
try {
|
|
260
336
|
const tags = await getSemverTags({});
|
|
261
337
|
return tags[0] || "";
|
|
262
338
|
} catch (error) {
|
|
263
|
-
|
|
264
|
-
|
|
339
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
340
|
+
log(`Failed to get latest tag: ${errorMessage}`, "error");
|
|
265
341
|
if (error instanceof Error && error.message.includes("No names found")) {
|
|
266
|
-
log("
|
|
342
|
+
log("No tags found in the repository.", "info");
|
|
267
343
|
}
|
|
268
344
|
return "";
|
|
269
345
|
}
|
|
270
346
|
}
|
|
271
|
-
function
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
347
|
+
async function lastMergeBranchName(branches, baseBranch) {
|
|
348
|
+
try {
|
|
349
|
+
const escapedBranches = branches.map((branch) => escapeRegExp(branch));
|
|
350
|
+
const branchesRegex = `${escapedBranches.join("/(.*)|")}/(.*)`;
|
|
351
|
+
const command = `git for-each-ref --sort=-committerdate --format='%(refname:short)' refs/heads --merged ${baseBranch} | grep -o -i -E "${branchesRegex}" | awk -F'[ ]' '{print $1}' | head -n 1`;
|
|
352
|
+
const { stdout } = await execAsync(command);
|
|
353
|
+
return stdout.trim();
|
|
354
|
+
} catch (error) {
|
|
355
|
+
console.error(
|
|
356
|
+
"Error while getting the last branch name:",
|
|
357
|
+
error instanceof Error ? error.message : String(error)
|
|
358
|
+
);
|
|
359
|
+
return null;
|
|
276
360
|
}
|
|
277
|
-
return `${tagPrefix ? tagPrefix : "v"}${version}`;
|
|
278
|
-
}
|
|
279
|
-
function formatTagPrefix(tagPrefix) {
|
|
280
|
-
return tagPrefix ? `${tagPrefix}@` : "";
|
|
281
361
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
function
|
|
286
|
-
return createTemplateString(template, { version });
|
|
287
|
-
}
|
|
288
|
-
function updatePackageVersion({ path: path2, version, name, dryRun }) {
|
|
362
|
+
|
|
363
|
+
// src/package/packageManagement.ts
|
|
364
|
+
import fs2 from "node:fs";
|
|
365
|
+
function updatePackageVersion(packagePath, version) {
|
|
289
366
|
try {
|
|
290
|
-
const
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
367
|
+
const packageContent = fs2.readFileSync(packagePath, "utf8");
|
|
368
|
+
const packageJson = JSON.parse(packageContent);
|
|
369
|
+
const packageName = packageJson.name;
|
|
370
|
+
packageJson.version = version;
|
|
371
|
+
fs2.writeFileSync(packagePath, `${JSON.stringify(packageJson, null, 2)}
|
|
295
372
|
`);
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
log("info", `[DRY RUN] Would update ${name} package.json to version ${version}`);
|
|
299
|
-
}
|
|
373
|
+
addPackageUpdate(packageName, version, packagePath);
|
|
374
|
+
log(`Updated package.json at ${packagePath} to version ${version}`, "success");
|
|
300
375
|
} catch (error) {
|
|
301
|
-
log(
|
|
302
|
-
|
|
376
|
+
log(`Failed to update package.json at ${packagePath}`, "error");
|
|
377
|
+
if (error instanceof Error) {
|
|
378
|
+
log(error.message, "error");
|
|
379
|
+
}
|
|
380
|
+
throw error;
|
|
303
381
|
}
|
|
304
382
|
}
|
|
305
383
|
|
|
306
|
-
// src/
|
|
307
|
-
import fs3 from "node:fs";
|
|
384
|
+
// src/package/packageProcessor.ts
|
|
308
385
|
import path from "node:path";
|
|
309
|
-
import {
|
|
310
|
-
|
|
386
|
+
import { exit } from "node:process";
|
|
387
|
+
|
|
388
|
+
// src/core/versionCalculator.ts
|
|
389
|
+
import { cwd as cwd3 } from "node:process";
|
|
311
390
|
import { Bumper } from "conventional-recommended-bump";
|
|
312
391
|
import semver from "semver";
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
392
|
+
async function calculateVersion(config, options) {
|
|
393
|
+
const { latestTag, type, path: path3, name, branchPattern, prereleaseIdentifier } = options;
|
|
394
|
+
const originalPrefix = config.tagPrefix || "v";
|
|
395
|
+
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
396
|
+
function determineTagSearchPattern(packageName, prefix) {
|
|
397
|
+
if (packageName) {
|
|
398
|
+
return prefix ? `${prefix}${packageName}@` : `${packageName}@`;
|
|
399
|
+
}
|
|
400
|
+
return prefix ? `${prefix}v` : "v";
|
|
317
401
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
325
|
-
const tagSearchPattern = name ? originalPrefix ? `${originalPrefix}${name}@` : `${name}@` : originalPrefix ? `${originalPrefix}v` : "v";
|
|
326
|
-
let determinedReleaseType = type || null;
|
|
327
|
-
if (determinedReleaseType) {
|
|
328
|
-
if (!latestTag) {
|
|
329
|
-
return initialVersion;
|
|
330
|
-
}
|
|
331
|
-
const currentVersion = semver.clean(latestTag.replace(tagSearchPattern, "")) || "0.0.0";
|
|
332
|
-
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
402
|
+
const tagSearchPattern = determineTagSearchPattern(name, originalPrefix);
|
|
403
|
+
const escapedTagPattern = escapeRegExp(tagSearchPattern);
|
|
404
|
+
let determinedReleaseType = type || null;
|
|
405
|
+
if (determinedReleaseType) {
|
|
406
|
+
if (!latestTag) {
|
|
407
|
+
return initialVersion;
|
|
333
408
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (!latestTag) {
|
|
347
|
-
return initialVersion;
|
|
348
|
-
}
|
|
349
|
-
const currentVersion = semver.clean(latestTag.replace(tagSearchPattern, "")) || "0.0.0";
|
|
350
|
-
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
409
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
410
|
+
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
411
|
+
}
|
|
412
|
+
if (config.versionStrategy === "branchPattern" && (branchPattern == null ? void 0 : branchPattern.length)) {
|
|
413
|
+
const currentBranch = await getCurrentBranch();
|
|
414
|
+
const mergeBranch = await lastMergeBranchName(branchPattern, config.baseBranch);
|
|
415
|
+
const branch = mergeBranch || currentBranch;
|
|
416
|
+
for (const pattern of branchPattern) {
|
|
417
|
+
const [match, releaseType] = pattern.split(":");
|
|
418
|
+
if (branch.includes(match) && releaseType) {
|
|
419
|
+
determinedReleaseType = releaseType;
|
|
420
|
+
break;
|
|
351
421
|
}
|
|
352
422
|
}
|
|
353
|
-
|
|
354
|
-
const bumper = new Bumper();
|
|
355
|
-
bumper.loadPreset(this.config.preset);
|
|
356
|
-
const recommendedBump = await bumper.bump();
|
|
357
|
-
const releaseTypeFromCommits = recommendedBump.releaseType;
|
|
423
|
+
if (determinedReleaseType) {
|
|
358
424
|
if (!latestTag) {
|
|
359
425
|
return initialVersion;
|
|
360
426
|
}
|
|
361
|
-
const
|
|
362
|
-
|
|
363
|
-
if (commitsLength === 0) {
|
|
364
|
-
log(
|
|
365
|
-
"info",
|
|
366
|
-
`No new commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
367
|
-
);
|
|
368
|
-
return "";
|
|
369
|
-
}
|
|
370
|
-
if (!releaseTypeFromCommits) {
|
|
371
|
-
log(
|
|
372
|
-
"info",
|
|
373
|
-
`No relevant commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
374
|
-
);
|
|
375
|
-
return "";
|
|
376
|
-
}
|
|
377
|
-
const currentVersion = semver.clean(latestTag.replace(tagSearchPattern, "")) || "0.0.0";
|
|
378
|
-
return semver.inc(currentVersion, releaseTypeFromCommits, prereleaseIdentifier) || "";
|
|
379
|
-
} catch (error) {
|
|
380
|
-
log("error", `Failed to calculate version for ${name || "project"}`);
|
|
381
|
-
console.error(error);
|
|
382
|
-
if (error instanceof Error && error.message.includes("No names found")) {
|
|
383
|
-
log("info", "No tags found, proceeding with initial version calculation (if applicable).");
|
|
384
|
-
return initialVersion;
|
|
385
|
-
}
|
|
386
|
-
return "";
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* Process packages based on discovery, skip list, and optional target list.
|
|
391
|
-
* Returns a list of package.json file paths that were updated (or would be in dry run).
|
|
392
|
-
*/
|
|
393
|
-
async processPackages(discoveredPackages = [], targets = []) {
|
|
394
|
-
const { tagPrefix, skip, dryRun } = this.config;
|
|
395
|
-
const files = [];
|
|
396
|
-
const pkgsToConsider = discoveredPackages.filter((pkg) => {
|
|
397
|
-
if (skip == null ? void 0 : skip.includes(pkg.packageJson.name)) {
|
|
398
|
-
log("info", `Skipping package ${pkg.packageJson.name} based on config skip list.`);
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
if (targets.length > 0) {
|
|
402
|
-
const isTargeted = targets.includes(pkg.packageJson.name);
|
|
403
|
-
if (!isTargeted) {
|
|
404
|
-
}
|
|
405
|
-
return isTargeted;
|
|
406
|
-
}
|
|
407
|
-
return true;
|
|
408
|
-
});
|
|
409
|
-
log("info", `Found ${pkgsToConsider.length} package(s) to process after filtering.`);
|
|
410
|
-
for (const pkg of pkgsToConsider) {
|
|
411
|
-
const name = pkg.packageJson.name;
|
|
412
|
-
const pkgPath = pkg.dir;
|
|
413
|
-
const prefix = formatTagPrefix(tagPrefix);
|
|
414
|
-
const latestTag = await getLatestTag();
|
|
415
|
-
const nextVersion = await this.calculateVersion({
|
|
416
|
-
latestTag,
|
|
417
|
-
tagPrefix: prefix,
|
|
418
|
-
path: pkgPath,
|
|
419
|
-
name,
|
|
420
|
-
branchPattern: this.config.branchPattern,
|
|
421
|
-
baseBranch: this.config.baseBranch,
|
|
422
|
-
prereleaseIdentifier: this.config.prereleaseIdentifier,
|
|
423
|
-
type: this.config.forceType
|
|
424
|
-
});
|
|
425
|
-
if (!nextVersion) {
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
updatePackageVersion({
|
|
429
|
-
path: pkgPath,
|
|
430
|
-
version: nextVersion,
|
|
431
|
-
name,
|
|
432
|
-
dryRun
|
|
433
|
-
});
|
|
434
|
-
files.push(path.join(pkgPath, "package.json"));
|
|
435
|
-
}
|
|
436
|
-
return files;
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Create git commit and tag
|
|
440
|
-
*/
|
|
441
|
-
async createGitCommitAndTag(files, nextTag, commitMessage, dryRun) {
|
|
442
|
-
try {
|
|
443
|
-
await gitProcess({
|
|
444
|
-
files,
|
|
445
|
-
nextTag,
|
|
446
|
-
commitMessage,
|
|
447
|
-
skipHooks: this.config.skipHooks,
|
|
448
|
-
dryRun
|
|
449
|
-
});
|
|
450
|
-
if (!dryRun) {
|
|
451
|
-
log("success", `Created tag: ${nextTag}`);
|
|
452
|
-
}
|
|
453
|
-
} catch (error) {
|
|
454
|
-
log("error", "Failed to create git commit and tag");
|
|
455
|
-
console.error(error);
|
|
456
|
-
exit(1);
|
|
427
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
428
|
+
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
457
429
|
}
|
|
458
430
|
}
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
baseBranch,
|
|
467
|
-
branchPattern,
|
|
468
|
-
commitMessage = "chore(release): v${version}",
|
|
469
|
-
prereleaseIdentifier
|
|
470
|
-
} = this.config;
|
|
471
|
-
const prefix = formatTagPrefix(tagPrefix);
|
|
472
|
-
const latestTag = await getLatestTag();
|
|
473
|
-
const nextVersion = await this.calculateVersion({
|
|
474
|
-
latestTag,
|
|
475
|
-
tagPrefix: prefix,
|
|
476
|
-
branchPattern,
|
|
477
|
-
baseBranch,
|
|
478
|
-
prereleaseIdentifier
|
|
479
|
-
});
|
|
480
|
-
if (!nextVersion) {
|
|
481
|
-
log("info", "No version change needed");
|
|
482
|
-
return;
|
|
431
|
+
try {
|
|
432
|
+
const bumper = new Bumper();
|
|
433
|
+
bumper.loadPreset(config.preset);
|
|
434
|
+
const recommendedBump = await bumper.bump();
|
|
435
|
+
const releaseTypeFromCommits = recommendedBump.releaseType;
|
|
436
|
+
if (!latestTag) {
|
|
437
|
+
return initialVersion;
|
|
483
438
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
console.error(error);
|
|
493
|
-
exit(1);
|
|
494
|
-
return;
|
|
439
|
+
const checkPath = path3 || cwd3();
|
|
440
|
+
const commitsLength = getCommitsLength(checkPath);
|
|
441
|
+
if (commitsLength === 0) {
|
|
442
|
+
log(
|
|
443
|
+
`No new commits found for ${name || "project"} since ${latestTag}, skipping version bump`,
|
|
444
|
+
"info"
|
|
445
|
+
);
|
|
446
|
+
return "";
|
|
495
447
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
version: nextVersion,
|
|
503
|
-
name: "root",
|
|
504
|
-
dryRun: this.config.dryRun
|
|
505
|
-
});
|
|
506
|
-
files.push(rootPkgPath);
|
|
507
|
-
}
|
|
508
|
-
} catch (_error) {
|
|
509
|
-
log("error", "Failed to update root package.json");
|
|
448
|
+
if (!releaseTypeFromCommits) {
|
|
449
|
+
log(
|
|
450
|
+
`No relevant commits found for ${name || "project"} since ${latestTag}, skipping version bump`,
|
|
451
|
+
"info"
|
|
452
|
+
);
|
|
453
|
+
return "";
|
|
510
454
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
dryRun: this.config.dryRun
|
|
520
|
-
});
|
|
521
|
-
files.push(path.join(pkg.dir, "package.json"));
|
|
455
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
456
|
+
return semver.inc(currentVersion, releaseTypeFromCommits, prereleaseIdentifier) || "";
|
|
457
|
+
} catch (error) {
|
|
458
|
+
log(`Failed to calculate version for ${name || "project"}`, "error");
|
|
459
|
+
console.error(error);
|
|
460
|
+
if (error instanceof Error && error.message.includes("No names found")) {
|
|
461
|
+
log("No tags found, proceeding with initial version calculation (if applicable).", "info");
|
|
462
|
+
return initialVersion;
|
|
522
463
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
464
|
+
throw error;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// src/package/packageProcessor.ts
|
|
469
|
+
var PackageProcessor = class {
|
|
470
|
+
skip;
|
|
471
|
+
targets;
|
|
472
|
+
tagPrefix;
|
|
473
|
+
commitMessageTemplate;
|
|
474
|
+
dryRun;
|
|
475
|
+
skipHooks;
|
|
476
|
+
getLatestTag;
|
|
477
|
+
config;
|
|
478
|
+
// Config for version calculation
|
|
479
|
+
fullConfig;
|
|
480
|
+
constructor(options) {
|
|
481
|
+
this.skip = options.skip || [];
|
|
482
|
+
this.targets = options.targets || [];
|
|
483
|
+
this.tagPrefix = options.tagPrefix || "v";
|
|
484
|
+
this.commitMessageTemplate = options.commitMessageTemplate || "";
|
|
485
|
+
this.dryRun = options.dryRun || false;
|
|
486
|
+
this.skipHooks = options.skipHooks || false;
|
|
487
|
+
this.getLatestTag = options.getLatestTag;
|
|
488
|
+
this.config = options.config;
|
|
489
|
+
this.fullConfig = options.fullConfig;
|
|
529
490
|
}
|
|
530
491
|
/**
|
|
531
|
-
*
|
|
492
|
+
* Set package targets to process
|
|
532
493
|
*/
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
packages: configPackages,
|
|
536
|
-
tagPrefix,
|
|
537
|
-
commitMessage = "chore(release): ${version}"
|
|
538
|
-
} = this.config;
|
|
539
|
-
if (configPackages.length !== 1) {
|
|
540
|
-
log("error", "Single mode requires exactly one package name");
|
|
541
|
-
exit(1);
|
|
542
|
-
}
|
|
543
|
-
const packageName = configPackages[0];
|
|
544
|
-
let pkgsResult;
|
|
545
|
-
try {
|
|
546
|
-
pkgsResult = getPackagesSync(cwd3());
|
|
547
|
-
if (!pkgsResult || !pkgsResult.packages) {
|
|
548
|
-
throw new Error("Failed to get packages information");
|
|
549
|
-
}
|
|
550
|
-
} catch (error) {
|
|
551
|
-
log("error", "Failed to get packages information");
|
|
552
|
-
console.error(error);
|
|
553
|
-
exit(1);
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
const pkg = pkgsResult.packages.find((p) => p.packageJson.name === packageName);
|
|
557
|
-
if (!pkg) {
|
|
558
|
-
log("error", `Package ${packageName} not found`);
|
|
559
|
-
exit(1);
|
|
560
|
-
}
|
|
561
|
-
const pkgPath = pkg.dir;
|
|
562
|
-
const prefix = formatTagPrefix(tagPrefix);
|
|
563
|
-
const latestTag = await getLatestTag();
|
|
564
|
-
let nextVersion = void 0;
|
|
565
|
-
try {
|
|
566
|
-
nextVersion = await this.calculateVersion({
|
|
567
|
-
latestTag,
|
|
568
|
-
tagPrefix: prefix,
|
|
569
|
-
path: pkgPath,
|
|
570
|
-
name: packageName
|
|
571
|
-
});
|
|
572
|
-
} catch (error) {
|
|
573
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
574
|
-
log("error", `Failed to calculate version for ${packageName}: ${errorMessage}`);
|
|
575
|
-
}
|
|
576
|
-
if (nextVersion === void 0 || nextVersion === "") {
|
|
577
|
-
log("info", `No version change needed for ${packageName}`);
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
updatePackageVersion({
|
|
581
|
-
path: pkgPath,
|
|
582
|
-
version: nextVersion,
|
|
583
|
-
name: packageName,
|
|
584
|
-
dryRun: this.config.dryRun
|
|
585
|
-
});
|
|
586
|
-
const nextTag = formatTag(
|
|
587
|
-
{ tagPrefix, name: packageName, synced: false },
|
|
588
|
-
{ tagPrefix: prefix, version: nextVersion }
|
|
589
|
-
);
|
|
590
|
-
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
591
|
-
await this.createGitCommitAndTag(
|
|
592
|
-
[path.join(pkgPath, "package.json")],
|
|
593
|
-
nextTag,
|
|
594
|
-
formattedCommitMessage,
|
|
595
|
-
this.config.dryRun
|
|
596
|
-
);
|
|
494
|
+
setTargets(targets) {
|
|
495
|
+
this.targets = targets;
|
|
597
496
|
}
|
|
598
497
|
/**
|
|
599
|
-
*
|
|
498
|
+
* Process packages based on targeting criteria
|
|
600
499
|
*/
|
|
601
|
-
async
|
|
602
|
-
if (cliTargets.length > 0) {
|
|
603
|
-
await this.asyncTargetedStrategy(cliTargets);
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
const {
|
|
607
|
-
commitMessage = "chore(release): ${version}",
|
|
608
|
-
// Align with test expectations
|
|
609
|
-
skipHooks
|
|
610
|
-
} = this.config;
|
|
611
|
-
let pkgsResult;
|
|
612
|
-
try {
|
|
613
|
-
pkgsResult = getPackagesSync(cwd3());
|
|
614
|
-
if (!pkgsResult || !pkgsResult.packages) {
|
|
615
|
-
throw new Error("Failed to get packages information");
|
|
616
|
-
}
|
|
617
|
-
} catch (error) {
|
|
618
|
-
log("error", "Failed to get packages information");
|
|
619
|
-
console.error(error);
|
|
620
|
-
exit(1);
|
|
621
|
-
return;
|
|
622
|
-
}
|
|
623
|
-
const pkgsToProcess = await this.processPackages(pkgsResult.packages, cliTargets);
|
|
624
|
-
if (pkgsToProcess.length === 0) {
|
|
625
|
-
log("info", "No packages to process based on changes and targets");
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
const formattedCommitMessage = commitMessage;
|
|
629
|
-
try {
|
|
630
|
-
await gitProcess({
|
|
631
|
-
files: pkgsToProcess,
|
|
632
|
-
nextTag: "",
|
|
633
|
-
// No tag for default async
|
|
634
|
-
commitMessage: formattedCommitMessage,
|
|
635
|
-
skipHooks,
|
|
636
|
-
dryRun: this.config.dryRun
|
|
637
|
-
});
|
|
638
|
-
if (!this.config.dryRun) {
|
|
639
|
-
log("success", `Created version commit for ${pkgsToProcess.length} package(s)`);
|
|
640
|
-
}
|
|
641
|
-
} catch (error) {
|
|
642
|
-
log("error", "Failed to create version commit");
|
|
643
|
-
console.error(error);
|
|
644
|
-
exit(1);
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
// --- NEW METHOD for Async + Targeted ---
|
|
648
|
-
async asyncTargetedStrategy(cliTargets) {
|
|
500
|
+
async processPackages(packages) {
|
|
649
501
|
var _a;
|
|
650
|
-
const
|
|
651
|
-
tagPrefix,
|
|
652
|
-
skip,
|
|
653
|
-
dryRun,
|
|
654
|
-
skipHooks,
|
|
655
|
-
commitMessage: commitMessageTemplate
|
|
656
|
-
} = this.config;
|
|
502
|
+
const tags = [];
|
|
657
503
|
const updatedPackagesInfo = [];
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
if (!pkgsResult || !pkgsResult.packages) {
|
|
663
|
-
throw new Error("Failed to get packages information");
|
|
664
|
-
}
|
|
665
|
-
} catch (error) {
|
|
666
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
667
|
-
log("error", `Failed to get packages information: ${errorMessage}`);
|
|
668
|
-
exit(1);
|
|
504
|
+
const tagPrefix = this.tagPrefix;
|
|
505
|
+
if (!packages || !Array.isArray(packages)) {
|
|
506
|
+
log("Invalid packages data provided. Expected array of packages.", "error");
|
|
507
|
+
return { updatedPackages: [], tags: [] };
|
|
669
508
|
}
|
|
670
|
-
const pkgsToConsider =
|
|
671
|
-
|
|
672
|
-
|
|
509
|
+
const pkgsToConsider = packages.filter((pkg) => {
|
|
510
|
+
var _a2;
|
|
511
|
+
const pkgName = pkg.packageJson.name;
|
|
512
|
+
if ((_a2 = this.skip) == null ? void 0 : _a2.includes(pkgName)) {
|
|
513
|
+
log(`Skipping package ${pkgName} as it's in the skip list.`, "info");
|
|
673
514
|
return false;
|
|
674
515
|
}
|
|
675
|
-
|
|
516
|
+
if (!this.targets || this.targets.length === 0) {
|
|
517
|
+
return true;
|
|
518
|
+
}
|
|
519
|
+
const isTargeted = this.targets.includes(pkgName);
|
|
676
520
|
if (!isTargeted) {
|
|
521
|
+
log(`Package ${pkgName} not in target list, skipping.`, "info");
|
|
677
522
|
}
|
|
678
523
|
return isTargeted;
|
|
679
524
|
});
|
|
680
|
-
log(
|
|
525
|
+
log(`Found ${pkgsToConsider.length} targeted package(s) to process after filtering.`, "info");
|
|
681
526
|
if (pkgsToConsider.length === 0) {
|
|
682
|
-
log("
|
|
683
|
-
return;
|
|
527
|
+
log("No matching targeted packages found to process.", "info");
|
|
528
|
+
return { updatedPackages: [], tags: [] };
|
|
684
529
|
}
|
|
685
530
|
for (const pkg of pkgsToConsider) {
|
|
686
531
|
const name = pkg.packageJson.name;
|
|
687
532
|
const pkgPath = pkg.dir;
|
|
688
533
|
const prefix = formatTagPrefix(tagPrefix);
|
|
689
|
-
const
|
|
690
|
-
const
|
|
534
|
+
const latestTagResult = await this.getLatestTag();
|
|
535
|
+
const latestTag = latestTagResult || "";
|
|
536
|
+
const nextVersion = await calculateVersion(this.fullConfig, {
|
|
691
537
|
latestTag,
|
|
692
538
|
tagPrefix: prefix,
|
|
693
539
|
path: pkgPath,
|
|
@@ -700,111 +546,401 @@ var VersionEngine = class {
|
|
|
700
546
|
if (!nextVersion) {
|
|
701
547
|
continue;
|
|
702
548
|
}
|
|
703
|
-
updatePackageVersion(
|
|
704
|
-
|
|
705
|
-
version: nextVersion,
|
|
706
|
-
name,
|
|
707
|
-
dryRun
|
|
708
|
-
});
|
|
709
|
-
const packageTag = formatTag(
|
|
710
|
-
{ synced: false, name, tagPrefix },
|
|
711
|
-
{ version: nextVersion, tagPrefix }
|
|
712
|
-
);
|
|
549
|
+
updatePackageVersion(path.join(pkgPath, "package.json"), nextVersion);
|
|
550
|
+
const packageTag = formatTag(nextVersion, tagPrefix);
|
|
713
551
|
const tagMessage = `chore(release): ${name} ${nextVersion}`;
|
|
714
|
-
|
|
552
|
+
addTag(packageTag);
|
|
553
|
+
tags.push(packageTag);
|
|
554
|
+
if (!this.dryRun) {
|
|
715
555
|
try {
|
|
716
556
|
await createGitTag({ tag: packageTag, message: tagMessage });
|
|
717
|
-
log(
|
|
557
|
+
log(`Created tag: ${packageTag}`, "success");
|
|
718
558
|
} catch (tagError) {
|
|
719
559
|
log(
|
|
720
|
-
|
|
721
|
-
|
|
560
|
+
`Failed to create tag ${packageTag} for ${name}: ${tagError.message}`,
|
|
561
|
+
"error"
|
|
722
562
|
);
|
|
723
|
-
log(
|
|
563
|
+
log(tagError.stack || "No stack trace available", "error");
|
|
724
564
|
}
|
|
725
565
|
} else {
|
|
726
|
-
log(
|
|
566
|
+
log(`[DRY RUN] Would create tag: ${packageTag}`, "info");
|
|
727
567
|
}
|
|
728
568
|
updatedPackagesInfo.push({ name, version: nextVersion, path: pkgPath });
|
|
729
569
|
}
|
|
730
570
|
if (updatedPackagesInfo.length === 0) {
|
|
731
|
-
log("
|
|
732
|
-
return;
|
|
571
|
+
log("No targeted packages required a version update.", "info");
|
|
572
|
+
return { updatedPackages: [], tags };
|
|
733
573
|
}
|
|
734
574
|
const filesToCommit = updatedPackagesInfo.map((info) => path.join(info.path, "package.json"));
|
|
735
575
|
const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
|
|
736
576
|
const representativeVersion = ((_a = updatedPackagesInfo[0]) == null ? void 0 : _a.version) || "multiple";
|
|
737
|
-
let commitMessage = commitMessageTemplate || "chore(release): publish packages";
|
|
577
|
+
let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
|
|
738
578
|
if (updatedPackagesInfo.length === 1 && commitMessage.includes("${version}")) {
|
|
739
579
|
commitMessage = formatCommitMessage(commitMessage, representativeVersion);
|
|
740
580
|
} else {
|
|
741
581
|
commitMessage = `chore(release): ${packageNames} ${representativeVersion}`;
|
|
742
582
|
}
|
|
743
583
|
commitMessage += " [skip-ci]";
|
|
744
|
-
|
|
584
|
+
setCommitMessage(commitMessage);
|
|
585
|
+
if (!this.dryRun) {
|
|
745
586
|
try {
|
|
746
587
|
await gitAdd(filesToCommit);
|
|
747
|
-
await gitCommit({ message: commitMessage, skipHooks });
|
|
748
|
-
log(
|
|
588
|
+
await gitCommit({ message: commitMessage, skipHooks: this.skipHooks });
|
|
589
|
+
log(`Created commit for targeted release: ${packageNames}`, "success");
|
|
749
590
|
} catch (commitError) {
|
|
750
|
-
log("
|
|
591
|
+
log("Failed to create commit for targeted release.", "error");
|
|
751
592
|
console.error(commitError);
|
|
752
593
|
exit(1);
|
|
753
594
|
}
|
|
754
595
|
} else {
|
|
755
|
-
log("
|
|
596
|
+
log("[DRY RUN] Would add files:", "info");
|
|
756
597
|
for (const file of filesToCommit) {
|
|
757
|
-
log(
|
|
598
|
+
log(` - ${file}`, "info");
|
|
599
|
+
}
|
|
600
|
+
log(`[DRY RUN] Would commit with message: "${commitMessage}"`, "info");
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
updatedPackages: updatedPackagesInfo,
|
|
604
|
+
commitMessage,
|
|
605
|
+
tags
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
// src/core/versionStrategies.ts
|
|
611
|
+
function shouldProcessPackage(pkg, config, targets = []) {
|
|
612
|
+
var _a;
|
|
613
|
+
const pkgName = pkg.packageJson.name;
|
|
614
|
+
if ((_a = config.skip) == null ? void 0 : _a.includes(pkgName)) {
|
|
615
|
+
return false;
|
|
616
|
+
}
|
|
617
|
+
if (!targets || targets.length === 0) {
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
return targets.includes(pkgName);
|
|
621
|
+
}
|
|
622
|
+
function createSyncedStrategy(config) {
|
|
623
|
+
return async (packages) => {
|
|
624
|
+
try {
|
|
625
|
+
const {
|
|
626
|
+
tagPrefix,
|
|
627
|
+
baseBranch,
|
|
628
|
+
branchPattern,
|
|
629
|
+
commitMessage = "chore(release): v${version}",
|
|
630
|
+
prereleaseIdentifier,
|
|
631
|
+
dryRun,
|
|
632
|
+
skipHooks
|
|
633
|
+
} = config;
|
|
634
|
+
const prefix = formatTagPrefix(tagPrefix || "v");
|
|
635
|
+
const latestTag = await getLatestTag();
|
|
636
|
+
const nextVersion = await calculateVersion(config, {
|
|
637
|
+
latestTag,
|
|
638
|
+
tagPrefix: prefix,
|
|
639
|
+
branchPattern,
|
|
640
|
+
baseBranch,
|
|
641
|
+
prereleaseIdentifier
|
|
642
|
+
});
|
|
643
|
+
if (!nextVersion) {
|
|
644
|
+
log("No version change needed", "info");
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const files = [];
|
|
648
|
+
const updatedPackages = [];
|
|
649
|
+
try {
|
|
650
|
+
const rootPkgPath = path2.join(packages.root, "package.json");
|
|
651
|
+
if (fs3.existsSync(rootPkgPath)) {
|
|
652
|
+
updatePackageVersion(rootPkgPath, nextVersion);
|
|
653
|
+
files.push(rootPkgPath);
|
|
654
|
+
updatedPackages.push("root");
|
|
655
|
+
}
|
|
656
|
+
} catch (_error) {
|
|
657
|
+
log("Failed to update root package.json", "error");
|
|
658
|
+
}
|
|
659
|
+
for (const pkg of packages.packages) {
|
|
660
|
+
if (!shouldProcessPackage(pkg, config)) {
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
const packageJsonPath = path2.join(pkg.dir, "package.json");
|
|
664
|
+
updatePackageVersion(packageJsonPath, nextVersion);
|
|
665
|
+
files.push(packageJsonPath);
|
|
666
|
+
updatedPackages.push(pkg.packageJson.name);
|
|
667
|
+
}
|
|
668
|
+
if (updatedPackages.length > 0) {
|
|
669
|
+
log(`Updated ${updatedPackages.length} package(s) to version ${nextVersion}`, "success");
|
|
670
|
+
} else {
|
|
671
|
+
log("No packages were updated", "warning");
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
const nextTag = formatTag(nextVersion, tagPrefix || "v");
|
|
675
|
+
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
676
|
+
await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
|
|
677
|
+
} catch (error) {
|
|
678
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
679
|
+
log(`Synced Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
680
|
+
} else {
|
|
681
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
682
|
+
log(`Synced Strategy failed: ${errorMessage}`, "error");
|
|
683
|
+
}
|
|
684
|
+
throw error;
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
function createSingleStrategy(config) {
|
|
689
|
+
return async (packages) => {
|
|
690
|
+
try {
|
|
691
|
+
const {
|
|
692
|
+
packages: configPackages,
|
|
693
|
+
tagPrefix,
|
|
694
|
+
commitMessage = "chore(release): ${version}",
|
|
695
|
+
dryRun,
|
|
696
|
+
skipHooks
|
|
697
|
+
} = config;
|
|
698
|
+
if (!configPackages || configPackages.length !== 1) {
|
|
699
|
+
throw createVersionError(
|
|
700
|
+
"INVALID_CONFIG" /* INVALID_CONFIG */,
|
|
701
|
+
"Single mode requires exactly one package name"
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
const packageName = configPackages[0];
|
|
705
|
+
const pkg = packages.packages.find((p) => p.packageJson.name === packageName);
|
|
706
|
+
if (!pkg) {
|
|
707
|
+
throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
|
|
708
|
+
}
|
|
709
|
+
const pkgPath = pkg.dir;
|
|
710
|
+
const prefix = formatTagPrefix(tagPrefix || "v");
|
|
711
|
+
const latestTag = await getLatestTag();
|
|
712
|
+
let nextVersion = void 0;
|
|
713
|
+
try {
|
|
714
|
+
nextVersion = await calculateVersion(config, {
|
|
715
|
+
latestTag,
|
|
716
|
+
tagPrefix: prefix,
|
|
717
|
+
path: pkgPath,
|
|
718
|
+
name: packageName
|
|
719
|
+
});
|
|
720
|
+
} catch (error) {
|
|
721
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
722
|
+
throw createVersionError("VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */, errorMessage);
|
|
723
|
+
}
|
|
724
|
+
if (nextVersion === void 0 || nextVersion === "") {
|
|
725
|
+
log(`No version change needed for ${packageName}`, "info");
|
|
726
|
+
return;
|
|
758
727
|
}
|
|
759
|
-
|
|
728
|
+
const packageJsonPath = path2.join(pkgPath, "package.json");
|
|
729
|
+
updatePackageVersion(packageJsonPath, nextVersion);
|
|
730
|
+
log(`Updated package ${packageName} to version ${nextVersion}`, "success");
|
|
731
|
+
const nextTag = formatTag(nextVersion, tagPrefix || "v");
|
|
732
|
+
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
733
|
+
await createGitCommitAndTag(
|
|
734
|
+
[packageJsonPath],
|
|
735
|
+
nextTag,
|
|
736
|
+
formattedCommitMessage,
|
|
737
|
+
skipHooks,
|
|
738
|
+
dryRun
|
|
739
|
+
);
|
|
740
|
+
} catch (error) {
|
|
741
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
742
|
+
log(
|
|
743
|
+
`Single Package Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`,
|
|
744
|
+
"error"
|
|
745
|
+
);
|
|
746
|
+
} else {
|
|
747
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
748
|
+
log(`Single Package Strategy failed: ${errorMessage}`, "error");
|
|
749
|
+
}
|
|
750
|
+
throw error;
|
|
760
751
|
}
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
function createAsyncStrategy(config) {
|
|
755
|
+
const dependencies = {
|
|
756
|
+
getLatestTag
|
|
757
|
+
};
|
|
758
|
+
const processorOptions = {
|
|
759
|
+
skip: config.skip || [],
|
|
760
|
+
targets: config.packages || [],
|
|
761
|
+
tagPrefix: config.tagPrefix || "v",
|
|
762
|
+
commitMessageTemplate: config.commitMessage || "",
|
|
763
|
+
dryRun: config.dryRun || false,
|
|
764
|
+
skipHooks: config.skipHooks || false,
|
|
765
|
+
getLatestTag: dependencies.getLatestTag,
|
|
766
|
+
fullConfig: config,
|
|
767
|
+
config: {
|
|
768
|
+
branchPattern: config.branchPattern || [],
|
|
769
|
+
baseBranch: config.baseBranch || "main",
|
|
770
|
+
prereleaseIdentifier: config.prereleaseIdentifier,
|
|
771
|
+
forceType: config.forceType
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
const packageProcessor = new PackageProcessor(processorOptions);
|
|
775
|
+
return async (packages, targets = []) => {
|
|
776
|
+
try {
|
|
777
|
+
const targetPackages = targets.length > 0 ? targets : config.packages || [];
|
|
778
|
+
packageProcessor.setTargets(targetPackages);
|
|
779
|
+
if (targetPackages.length > 0) {
|
|
780
|
+
log(`Processing targeted packages: ${targetPackages.join(", ")}`, "info");
|
|
781
|
+
} else {
|
|
782
|
+
log("No targets specified, processing all non-skipped packages", "info");
|
|
783
|
+
}
|
|
784
|
+
const result = await packageProcessor.processPackages(packages.packages);
|
|
785
|
+
if (result.updatedPackages.length === 0) {
|
|
786
|
+
log("No packages required a version update.", "info");
|
|
787
|
+
} else {
|
|
788
|
+
const packageNames = result.updatedPackages.map((p) => p.name).join(", ");
|
|
789
|
+
log(`Updated ${result.updatedPackages.length} package(s): ${packageNames}`, "success");
|
|
790
|
+
if (result.tags.length > 0) {
|
|
791
|
+
log(`Created ${result.tags.length} tag(s): ${result.tags.join(", ")}`, "success");
|
|
792
|
+
}
|
|
793
|
+
if (result.commitMessage) {
|
|
794
|
+
log(`Created commit with message: "${result.commitMessage}"`, "success");
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
} catch (error) {
|
|
798
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
799
|
+
log(`Async Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
800
|
+
} else {
|
|
801
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
802
|
+
log(`Async Strategy failed: ${errorMessage}`, "error");
|
|
803
|
+
}
|
|
804
|
+
throw error;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
function createStrategy(config) {
|
|
809
|
+
var _a;
|
|
810
|
+
if (config.synced) {
|
|
811
|
+
return createSyncedStrategy(config);
|
|
812
|
+
}
|
|
813
|
+
if (((_a = config.packages) == null ? void 0 : _a.length) === 1) {
|
|
814
|
+
return createSingleStrategy(config);
|
|
815
|
+
}
|
|
816
|
+
return createAsyncStrategy(config);
|
|
817
|
+
}
|
|
818
|
+
function createStrategyMap(config) {
|
|
819
|
+
return {
|
|
820
|
+
synced: createSyncedStrategy(config),
|
|
821
|
+
single: createSingleStrategy(config),
|
|
822
|
+
async: createAsyncStrategy(config)
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/core/versionEngine.ts
|
|
827
|
+
var VersionEngine = class {
|
|
828
|
+
config;
|
|
829
|
+
jsonMode;
|
|
830
|
+
workspaceCache = null;
|
|
831
|
+
strategies;
|
|
832
|
+
currentStrategy;
|
|
833
|
+
constructor(config, jsonMode = false) {
|
|
834
|
+
if (!config) {
|
|
835
|
+
throw createVersionError("CONFIG_REQUIRED" /* CONFIG_REQUIRED */);
|
|
836
|
+
}
|
|
837
|
+
if (!config.preset) {
|
|
838
|
+
config.preset = "conventional-commits";
|
|
839
|
+
log("No preset specified, using default: conventional-commits", "warning");
|
|
840
|
+
}
|
|
841
|
+
this.config = config;
|
|
842
|
+
this.jsonMode = jsonMode;
|
|
843
|
+
this.strategies = createStrategyMap(config);
|
|
844
|
+
this.currentStrategy = createStrategy(config);
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Get workspace packages information - with caching for performance
|
|
848
|
+
*/
|
|
849
|
+
async getWorkspacePackages() {
|
|
850
|
+
try {
|
|
851
|
+
if (this.workspaceCache) {
|
|
852
|
+
return this.workspaceCache;
|
|
853
|
+
}
|
|
854
|
+
const pkgsResult = getPackagesSync(cwd4());
|
|
855
|
+
if (!pkgsResult || !pkgsResult.packages) {
|
|
856
|
+
throw createVersionError("PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */);
|
|
857
|
+
}
|
|
858
|
+
this.workspaceCache = pkgsResult;
|
|
859
|
+
return pkgsResult;
|
|
860
|
+
} catch (error) {
|
|
861
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
862
|
+
log(`Failed to get packages information: ${errorMessage}`, "error");
|
|
863
|
+
console.error(error);
|
|
864
|
+
throw createVersionError("WORKSPACE_ERROR" /* WORKSPACE_ERROR */, errorMessage);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Run the current strategy
|
|
869
|
+
* @param targets Optional package targets to process (only used by async strategy)
|
|
870
|
+
*/
|
|
871
|
+
async run(targets = []) {
|
|
872
|
+
try {
|
|
873
|
+
const packages = await this.getWorkspacePackages();
|
|
874
|
+
return this.currentStrategy(packages, targets);
|
|
875
|
+
} catch (error) {
|
|
876
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
877
|
+
log(`Version engine failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
878
|
+
} else {
|
|
879
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
880
|
+
log(`Version engine failed: ${errorMessage}`, "error");
|
|
881
|
+
}
|
|
882
|
+
throw error;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Change the current strategy
|
|
887
|
+
* @param strategyType The strategy type to use: 'synced', 'single', or 'async'
|
|
888
|
+
*/
|
|
889
|
+
setStrategy(strategyType) {
|
|
890
|
+
this.currentStrategy = this.strategies[strategyType];
|
|
761
891
|
}
|
|
762
892
|
};
|
|
763
893
|
|
|
764
894
|
// src/index.ts
|
|
765
895
|
async function run() {
|
|
766
|
-
printFiglet();
|
|
767
896
|
const program = new Command();
|
|
768
897
|
program.name("package-versioner").description(
|
|
769
|
-
"
|
|
770
|
-
).version(
|
|
771
|
-
"--
|
|
772
|
-
"
|
|
773
|
-
).option(
|
|
774
|
-
"-t, --target <targets>",
|
|
775
|
-
"Comma-separated list of package names to target (only for async strategy)"
|
|
776
|
-
).parse(process.argv);
|
|
898
|
+
"A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
|
|
899
|
+
).version(process.env.npm_package_version || "0.0.0").option(
|
|
900
|
+
"-c, --config <path>",
|
|
901
|
+
"Path to config file (defaults to version.config.json in current directory)"
|
|
902
|
+
).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Force specific bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Force synchronized versioning across all packages").option("-j, --json", "Output results as JSON", false).option("-t, --target <packages>", "Comma-delimited list of package names to target").parse(process.argv);
|
|
777
903
|
const options = program.opts();
|
|
904
|
+
if (options.json) {
|
|
905
|
+
enableJsonOutput(options.dryRun);
|
|
906
|
+
}
|
|
778
907
|
try {
|
|
779
908
|
const config = await loadConfig(options.config);
|
|
780
|
-
log(
|
|
909
|
+
log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
|
|
781
910
|
if (options.dryRun) config.dryRun = true;
|
|
782
911
|
if (options.synced) config.synced = true;
|
|
783
912
|
if (options.bump) config.forceType = options.bump;
|
|
784
913
|
if (options.prerelease)
|
|
785
914
|
config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
|
|
786
915
|
const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
|
|
787
|
-
const engine = new VersionEngine(config);
|
|
916
|
+
const engine = new VersionEngine(config, !!options.json);
|
|
788
917
|
if (config.synced) {
|
|
789
|
-
log("
|
|
790
|
-
|
|
918
|
+
log("Using synced versioning strategy.", "info");
|
|
919
|
+
engine.setStrategy("synced");
|
|
920
|
+
await engine.run();
|
|
791
921
|
} else if (config.packages && config.packages.length === 1) {
|
|
792
|
-
log("
|
|
922
|
+
log("Using single package versioning strategy.", "info");
|
|
793
923
|
if (cliTargets.length > 0) {
|
|
794
|
-
log("
|
|
924
|
+
log("--target flag is ignored for single package strategy.", "warning");
|
|
795
925
|
}
|
|
796
|
-
|
|
926
|
+
engine.setStrategy("single");
|
|
927
|
+
await engine.run();
|
|
797
928
|
} else {
|
|
798
|
-
log("
|
|
929
|
+
log("Using async versioning strategy.", "info");
|
|
799
930
|
if (cliTargets.length > 0) {
|
|
800
|
-
log(
|
|
931
|
+
log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
|
|
801
932
|
}
|
|
802
|
-
|
|
933
|
+
engine.setStrategy("async");
|
|
934
|
+
await engine.run(cliTargets);
|
|
803
935
|
}
|
|
804
|
-
log("
|
|
936
|
+
log("Versioning process completed.", "success");
|
|
937
|
+
printJsonOutput();
|
|
805
938
|
} catch (error) {
|
|
806
|
-
log(
|
|
939
|
+
log(error instanceof Error ? error.message : String(error), "error");
|
|
807
940
|
process.exit(1);
|
|
808
941
|
}
|
|
809
942
|
}
|
|
810
|
-
run()
|
|
943
|
+
run().catch((error) => {
|
|
944
|
+
console.error("Fatal error:", error);
|
|
945
|
+
process.exit(1);
|
|
946
|
+
});
|