package-versioner 0.2.0 → 0.4.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 +40 -3
- package/dist/index.cjs +721 -576
- package/dist/index.js +719 -575
- package/docs/CI_CD_INTEGRATION.md +165 -0
- package/docs/VERSIONING_STRATEGIES.md +39 -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,309 @@ 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
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
*/
|
|
321
|
-
async calculateVersion(options) {
|
|
322
|
-
const { latestTag, type, path: path2, name, branchPattern, prereleaseIdentifier } = options;
|
|
323
|
-
const originalPrefix = this.config.tagPrefix || "";
|
|
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) || "";
|
|
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}@`;
|
|
333
399
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
break;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
if (determinedReleaseType) {
|
|
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) || "";
|
|
351
|
-
}
|
|
400
|
+
return prefix ? `${prefix}v` : "v";
|
|
401
|
+
}
|
|
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;
|
|
352
408
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const checkPath = path2 || cwd3();
|
|
362
|
-
const commitsLength = await getCommitsLength(checkPath);
|
|
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 "";
|
|
409
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
410
|
+
const standardBumpTypes = ["major", "minor", "patch"];
|
|
411
|
+
if (standardBumpTypes.includes(determinedReleaseType) && semver.prerelease(currentVersion)) {
|
|
412
|
+
log(
|
|
413
|
+
`Cleaning prerelease identifier from ${currentVersion} for ${determinedReleaseType} bump`,
|
|
414
|
+
"debug"
|
|
415
|
+
);
|
|
416
|
+
return semver.inc(currentVersion, determinedReleaseType) || "";
|
|
387
417
|
}
|
|
418
|
+
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
388
419
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
log("info", `Skipping package ${pkg.packageJson.name} based on config skip list.`);
|
|
399
|
-
return false;
|
|
420
|
+
if (config.versionStrategy === "branchPattern" && (branchPattern == null ? void 0 : branchPattern.length)) {
|
|
421
|
+
const currentBranch = await getCurrentBranch();
|
|
422
|
+
const mergeBranch = await lastMergeBranchName(branchPattern, config.baseBranch);
|
|
423
|
+
const branch = mergeBranch || currentBranch;
|
|
424
|
+
for (const pattern of branchPattern) {
|
|
425
|
+
const [match, releaseType] = pattern.split(":");
|
|
426
|
+
if (branch.includes(match) && releaseType) {
|
|
427
|
+
determinedReleaseType = releaseType;
|
|
428
|
+
break;
|
|
400
429
|
}
|
|
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
430
|
}
|
|
436
|
-
|
|
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}`);
|
|
431
|
+
if (determinedReleaseType) {
|
|
432
|
+
if (!latestTag) {
|
|
433
|
+
return initialVersion;
|
|
452
434
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
console.error(error);
|
|
456
|
-
exit(1);
|
|
435
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
436
|
+
return semver.inc(currentVersion, determinedReleaseType, prereleaseIdentifier) || "";
|
|
457
437
|
}
|
|
458
438
|
}
|
|
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;
|
|
439
|
+
try {
|
|
440
|
+
const bumper = new Bumper();
|
|
441
|
+
bumper.loadPreset(config.preset);
|
|
442
|
+
const recommendedBump = await bumper.bump();
|
|
443
|
+
const releaseTypeFromCommits = recommendedBump.releaseType;
|
|
444
|
+
if (!latestTag) {
|
|
445
|
+
return initialVersion;
|
|
483
446
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
console.error(error);
|
|
493
|
-
exit(1);
|
|
494
|
-
return;
|
|
447
|
+
const checkPath = path3 || cwd3();
|
|
448
|
+
const commitsLength = getCommitsLength(checkPath);
|
|
449
|
+
if (commitsLength === 0) {
|
|
450
|
+
log(
|
|
451
|
+
`No new commits found for ${name || "project"} since ${latestTag}, skipping version bump`,
|
|
452
|
+
"info"
|
|
453
|
+
);
|
|
454
|
+
return "";
|
|
495
455
|
}
|
|
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");
|
|
456
|
+
if (!releaseTypeFromCommits) {
|
|
457
|
+
log(
|
|
458
|
+
`No relevant commits found for ${name || "project"} since ${latestTag}, skipping version bump`,
|
|
459
|
+
"info"
|
|
460
|
+
);
|
|
461
|
+
return "";
|
|
510
462
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
dryRun: this.config.dryRun
|
|
520
|
-
});
|
|
521
|
-
files.push(path.join(pkg.dir, "package.json"));
|
|
463
|
+
const currentVersion = semver.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
464
|
+
return semver.inc(currentVersion, releaseTypeFromCommits, prereleaseIdentifier) || "";
|
|
465
|
+
} catch (error) {
|
|
466
|
+
log(`Failed to calculate version for ${name || "project"}`, "error");
|
|
467
|
+
console.error(error);
|
|
468
|
+
if (error instanceof Error && error.message.includes("No names found")) {
|
|
469
|
+
log("No tags found, proceeding with initial version calculation (if applicable).", "info");
|
|
470
|
+
return initialVersion;
|
|
522
471
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
472
|
+
throw error;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// src/package/packageProcessor.ts
|
|
477
|
+
var PackageProcessor = class {
|
|
478
|
+
skip;
|
|
479
|
+
targets;
|
|
480
|
+
tagPrefix;
|
|
481
|
+
commitMessageTemplate;
|
|
482
|
+
dryRun;
|
|
483
|
+
skipHooks;
|
|
484
|
+
getLatestTag;
|
|
485
|
+
config;
|
|
486
|
+
// Config for version calculation
|
|
487
|
+
fullConfig;
|
|
488
|
+
constructor(options) {
|
|
489
|
+
this.skip = options.skip || [];
|
|
490
|
+
this.targets = options.targets || [];
|
|
491
|
+
this.tagPrefix = options.tagPrefix || "v";
|
|
492
|
+
this.commitMessageTemplate = options.commitMessageTemplate || "";
|
|
493
|
+
this.dryRun = options.dryRun || false;
|
|
494
|
+
this.skipHooks = options.skipHooks || false;
|
|
495
|
+
this.getLatestTag = options.getLatestTag;
|
|
496
|
+
this.config = options.config;
|
|
497
|
+
this.fullConfig = options.fullConfig;
|
|
529
498
|
}
|
|
530
499
|
/**
|
|
531
|
-
*
|
|
500
|
+
* Set package targets to process
|
|
532
501
|
*/
|
|
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
|
-
);
|
|
502
|
+
setTargets(targets) {
|
|
503
|
+
this.targets = targets;
|
|
597
504
|
}
|
|
598
505
|
/**
|
|
599
|
-
*
|
|
506
|
+
* Process packages based on targeting criteria
|
|
600
507
|
*/
|
|
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) {
|
|
508
|
+
async processPackages(packages) {
|
|
649
509
|
var _a;
|
|
650
|
-
const
|
|
651
|
-
tagPrefix,
|
|
652
|
-
skip,
|
|
653
|
-
dryRun,
|
|
654
|
-
skipHooks,
|
|
655
|
-
commitMessage: commitMessageTemplate
|
|
656
|
-
} = this.config;
|
|
510
|
+
const tags = [];
|
|
657
511
|
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);
|
|
512
|
+
const tagPrefix = this.tagPrefix;
|
|
513
|
+
if (!packages || !Array.isArray(packages)) {
|
|
514
|
+
log("Invalid packages data provided. Expected array of packages.", "error");
|
|
515
|
+
return { updatedPackages: [], tags: [] };
|
|
669
516
|
}
|
|
670
|
-
const pkgsToConsider =
|
|
671
|
-
|
|
672
|
-
|
|
517
|
+
const pkgsToConsider = packages.filter((pkg) => {
|
|
518
|
+
var _a2;
|
|
519
|
+
const pkgName = pkg.packageJson.name;
|
|
520
|
+
if ((_a2 = this.skip) == null ? void 0 : _a2.includes(pkgName)) {
|
|
521
|
+
log(`Skipping package ${pkgName} as it's in the skip list.`, "info");
|
|
673
522
|
return false;
|
|
674
523
|
}
|
|
675
|
-
|
|
524
|
+
if (!this.targets || this.targets.length === 0) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
const isTargeted = this.targets.includes(pkgName);
|
|
676
528
|
if (!isTargeted) {
|
|
529
|
+
log(`Package ${pkgName} not in target list, skipping.`, "info");
|
|
677
530
|
}
|
|
678
531
|
return isTargeted;
|
|
679
532
|
});
|
|
680
|
-
log(
|
|
533
|
+
log(`Found ${pkgsToConsider.length} targeted package(s) to process after filtering.`, "info");
|
|
681
534
|
if (pkgsToConsider.length === 0) {
|
|
682
|
-
log("
|
|
683
|
-
return;
|
|
535
|
+
log("No matching targeted packages found to process.", "info");
|
|
536
|
+
return { updatedPackages: [], tags: [] };
|
|
684
537
|
}
|
|
685
538
|
for (const pkg of pkgsToConsider) {
|
|
686
539
|
const name = pkg.packageJson.name;
|
|
687
540
|
const pkgPath = pkg.dir;
|
|
688
541
|
const prefix = formatTagPrefix(tagPrefix);
|
|
689
|
-
const
|
|
690
|
-
const
|
|
542
|
+
const latestTagResult = await this.getLatestTag();
|
|
543
|
+
const latestTag = latestTagResult || "";
|
|
544
|
+
const nextVersion = await calculateVersion(this.fullConfig, {
|
|
691
545
|
latestTag,
|
|
692
546
|
tagPrefix: prefix,
|
|
693
547
|
path: pkgPath,
|
|
@@ -700,111 +554,401 @@ var VersionEngine = class {
|
|
|
700
554
|
if (!nextVersion) {
|
|
701
555
|
continue;
|
|
702
556
|
}
|
|
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
|
-
);
|
|
557
|
+
updatePackageVersion(path.join(pkgPath, "package.json"), nextVersion);
|
|
558
|
+
const packageTag = formatTag(nextVersion, tagPrefix);
|
|
713
559
|
const tagMessage = `chore(release): ${name} ${nextVersion}`;
|
|
714
|
-
|
|
560
|
+
addTag(packageTag);
|
|
561
|
+
tags.push(packageTag);
|
|
562
|
+
if (!this.dryRun) {
|
|
715
563
|
try {
|
|
716
564
|
await createGitTag({ tag: packageTag, message: tagMessage });
|
|
717
|
-
log(
|
|
565
|
+
log(`Created tag: ${packageTag}`, "success");
|
|
718
566
|
} catch (tagError) {
|
|
719
567
|
log(
|
|
720
|
-
|
|
721
|
-
|
|
568
|
+
`Failed to create tag ${packageTag} for ${name}: ${tagError.message}`,
|
|
569
|
+
"error"
|
|
722
570
|
);
|
|
723
|
-
log(
|
|
571
|
+
log(tagError.stack || "No stack trace available", "error");
|
|
724
572
|
}
|
|
725
573
|
} else {
|
|
726
|
-
log(
|
|
574
|
+
log(`[DRY RUN] Would create tag: ${packageTag}`, "info");
|
|
727
575
|
}
|
|
728
576
|
updatedPackagesInfo.push({ name, version: nextVersion, path: pkgPath });
|
|
729
577
|
}
|
|
730
578
|
if (updatedPackagesInfo.length === 0) {
|
|
731
|
-
log("
|
|
732
|
-
return;
|
|
579
|
+
log("No targeted packages required a version update.", "info");
|
|
580
|
+
return { updatedPackages: [], tags };
|
|
733
581
|
}
|
|
734
582
|
const filesToCommit = updatedPackagesInfo.map((info) => path.join(info.path, "package.json"));
|
|
735
583
|
const packageNames = updatedPackagesInfo.map((p) => p.name).join(", ");
|
|
736
584
|
const representativeVersion = ((_a = updatedPackagesInfo[0]) == null ? void 0 : _a.version) || "multiple";
|
|
737
|
-
let commitMessage = commitMessageTemplate || "chore(release): publish packages";
|
|
585
|
+
let commitMessage = this.commitMessageTemplate || "chore(release): publish packages";
|
|
738
586
|
if (updatedPackagesInfo.length === 1 && commitMessage.includes("${version}")) {
|
|
739
587
|
commitMessage = formatCommitMessage(commitMessage, representativeVersion);
|
|
740
588
|
} else {
|
|
741
589
|
commitMessage = `chore(release): ${packageNames} ${representativeVersion}`;
|
|
742
590
|
}
|
|
743
591
|
commitMessage += " [skip-ci]";
|
|
744
|
-
|
|
592
|
+
setCommitMessage(commitMessage);
|
|
593
|
+
if (!this.dryRun) {
|
|
745
594
|
try {
|
|
746
595
|
await gitAdd(filesToCommit);
|
|
747
|
-
await gitCommit({ message: commitMessage, skipHooks });
|
|
748
|
-
log(
|
|
596
|
+
await gitCommit({ message: commitMessage, skipHooks: this.skipHooks });
|
|
597
|
+
log(`Created commit for targeted release: ${packageNames}`, "success");
|
|
749
598
|
} catch (commitError) {
|
|
750
|
-
log("
|
|
599
|
+
log("Failed to create commit for targeted release.", "error");
|
|
751
600
|
console.error(commitError);
|
|
752
601
|
exit(1);
|
|
753
602
|
}
|
|
754
603
|
} else {
|
|
755
|
-
log("
|
|
604
|
+
log("[DRY RUN] Would add files:", "info");
|
|
756
605
|
for (const file of filesToCommit) {
|
|
757
|
-
log(
|
|
606
|
+
log(` - ${file}`, "info");
|
|
758
607
|
}
|
|
759
|
-
log(
|
|
608
|
+
log(`[DRY RUN] Would commit with message: "${commitMessage}"`, "info");
|
|
760
609
|
}
|
|
610
|
+
return {
|
|
611
|
+
updatedPackages: updatedPackagesInfo,
|
|
612
|
+
commitMessage,
|
|
613
|
+
tags
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// src/core/versionStrategies.ts
|
|
619
|
+
function shouldProcessPackage(pkg, config, targets = []) {
|
|
620
|
+
var _a;
|
|
621
|
+
const pkgName = pkg.packageJson.name;
|
|
622
|
+
if ((_a = config.skip) == null ? void 0 : _a.includes(pkgName)) {
|
|
623
|
+
return false;
|
|
624
|
+
}
|
|
625
|
+
if (!targets || targets.length === 0) {
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
return targets.includes(pkgName);
|
|
629
|
+
}
|
|
630
|
+
function createSyncedStrategy(config) {
|
|
631
|
+
return async (packages) => {
|
|
632
|
+
try {
|
|
633
|
+
const {
|
|
634
|
+
tagPrefix,
|
|
635
|
+
baseBranch,
|
|
636
|
+
branchPattern,
|
|
637
|
+
commitMessage = "chore(release): v${version}",
|
|
638
|
+
prereleaseIdentifier,
|
|
639
|
+
dryRun,
|
|
640
|
+
skipHooks
|
|
641
|
+
} = config;
|
|
642
|
+
const prefix = formatTagPrefix(tagPrefix || "v");
|
|
643
|
+
const latestTag = await getLatestTag();
|
|
644
|
+
const nextVersion = await calculateVersion(config, {
|
|
645
|
+
latestTag,
|
|
646
|
+
tagPrefix: prefix,
|
|
647
|
+
branchPattern,
|
|
648
|
+
baseBranch,
|
|
649
|
+
prereleaseIdentifier
|
|
650
|
+
});
|
|
651
|
+
if (!nextVersion) {
|
|
652
|
+
log("No version change needed", "info");
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
const files = [];
|
|
656
|
+
const updatedPackages = [];
|
|
657
|
+
try {
|
|
658
|
+
const rootPkgPath = path2.join(packages.root, "package.json");
|
|
659
|
+
if (fs3.existsSync(rootPkgPath)) {
|
|
660
|
+
updatePackageVersion(rootPkgPath, nextVersion);
|
|
661
|
+
files.push(rootPkgPath);
|
|
662
|
+
updatedPackages.push("root");
|
|
663
|
+
}
|
|
664
|
+
} catch (_error) {
|
|
665
|
+
log("Failed to update root package.json", "error");
|
|
666
|
+
}
|
|
667
|
+
for (const pkg of packages.packages) {
|
|
668
|
+
if (!shouldProcessPackage(pkg, config)) {
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const packageJsonPath = path2.join(pkg.dir, "package.json");
|
|
672
|
+
updatePackageVersion(packageJsonPath, nextVersion);
|
|
673
|
+
files.push(packageJsonPath);
|
|
674
|
+
updatedPackages.push(pkg.packageJson.name);
|
|
675
|
+
}
|
|
676
|
+
if (updatedPackages.length > 0) {
|
|
677
|
+
log(`Updated ${updatedPackages.length} package(s) to version ${nextVersion}`, "success");
|
|
678
|
+
} else {
|
|
679
|
+
log("No packages were updated", "warning");
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
const nextTag = formatTag(nextVersion, tagPrefix || "v");
|
|
683
|
+
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
684
|
+
await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
|
|
685
|
+
} catch (error) {
|
|
686
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
687
|
+
log(`Synced Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
688
|
+
} else {
|
|
689
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
690
|
+
log(`Synced Strategy failed: ${errorMessage}`, "error");
|
|
691
|
+
}
|
|
692
|
+
throw error;
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function createSingleStrategy(config) {
|
|
697
|
+
return async (packages) => {
|
|
698
|
+
try {
|
|
699
|
+
const {
|
|
700
|
+
packages: configPackages,
|
|
701
|
+
tagPrefix,
|
|
702
|
+
commitMessage = "chore(release): ${version}",
|
|
703
|
+
dryRun,
|
|
704
|
+
skipHooks
|
|
705
|
+
} = config;
|
|
706
|
+
if (!configPackages || configPackages.length !== 1) {
|
|
707
|
+
throw createVersionError(
|
|
708
|
+
"INVALID_CONFIG" /* INVALID_CONFIG */,
|
|
709
|
+
"Single mode requires exactly one package name"
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
const packageName = configPackages[0];
|
|
713
|
+
const pkg = packages.packages.find((p) => p.packageJson.name === packageName);
|
|
714
|
+
if (!pkg) {
|
|
715
|
+
throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
|
|
716
|
+
}
|
|
717
|
+
const pkgPath = pkg.dir;
|
|
718
|
+
const prefix = formatTagPrefix(tagPrefix || "v");
|
|
719
|
+
const latestTag = await getLatestTag();
|
|
720
|
+
let nextVersion = void 0;
|
|
721
|
+
try {
|
|
722
|
+
nextVersion = await calculateVersion(config, {
|
|
723
|
+
latestTag,
|
|
724
|
+
tagPrefix: prefix,
|
|
725
|
+
path: pkgPath,
|
|
726
|
+
name: packageName
|
|
727
|
+
});
|
|
728
|
+
} catch (error) {
|
|
729
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
730
|
+
throw createVersionError("VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */, errorMessage);
|
|
731
|
+
}
|
|
732
|
+
if (nextVersion === void 0 || nextVersion === "") {
|
|
733
|
+
log(`No version change needed for ${packageName}`, "info");
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const packageJsonPath = path2.join(pkgPath, "package.json");
|
|
737
|
+
updatePackageVersion(packageJsonPath, nextVersion);
|
|
738
|
+
log(`Updated package ${packageName} to version ${nextVersion}`, "success");
|
|
739
|
+
const nextTag = formatTag(nextVersion, tagPrefix || "v");
|
|
740
|
+
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
741
|
+
await createGitCommitAndTag(
|
|
742
|
+
[packageJsonPath],
|
|
743
|
+
nextTag,
|
|
744
|
+
formattedCommitMessage,
|
|
745
|
+
skipHooks,
|
|
746
|
+
dryRun
|
|
747
|
+
);
|
|
748
|
+
} catch (error) {
|
|
749
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
750
|
+
log(
|
|
751
|
+
`Single Package Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`,
|
|
752
|
+
"error"
|
|
753
|
+
);
|
|
754
|
+
} else {
|
|
755
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
756
|
+
log(`Single Package Strategy failed: ${errorMessage}`, "error");
|
|
757
|
+
}
|
|
758
|
+
throw error;
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
function createAsyncStrategy(config) {
|
|
763
|
+
const dependencies = {
|
|
764
|
+
getLatestTag
|
|
765
|
+
};
|
|
766
|
+
const processorOptions = {
|
|
767
|
+
skip: config.skip || [],
|
|
768
|
+
targets: config.packages || [],
|
|
769
|
+
tagPrefix: config.tagPrefix || "v",
|
|
770
|
+
commitMessageTemplate: config.commitMessage || "",
|
|
771
|
+
dryRun: config.dryRun || false,
|
|
772
|
+
skipHooks: config.skipHooks || false,
|
|
773
|
+
getLatestTag: dependencies.getLatestTag,
|
|
774
|
+
fullConfig: config,
|
|
775
|
+
config: {
|
|
776
|
+
branchPattern: config.branchPattern || [],
|
|
777
|
+
baseBranch: config.baseBranch || "main",
|
|
778
|
+
prereleaseIdentifier: config.prereleaseIdentifier,
|
|
779
|
+
forceType: config.forceType
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
const packageProcessor = new PackageProcessor(processorOptions);
|
|
783
|
+
return async (packages, targets = []) => {
|
|
784
|
+
try {
|
|
785
|
+
const targetPackages = targets.length > 0 ? targets : config.packages || [];
|
|
786
|
+
packageProcessor.setTargets(targetPackages);
|
|
787
|
+
if (targetPackages.length > 0) {
|
|
788
|
+
log(`Processing targeted packages: ${targetPackages.join(", ")}`, "info");
|
|
789
|
+
} else {
|
|
790
|
+
log("No targets specified, processing all non-skipped packages", "info");
|
|
791
|
+
}
|
|
792
|
+
const result = await packageProcessor.processPackages(packages.packages);
|
|
793
|
+
if (result.updatedPackages.length === 0) {
|
|
794
|
+
log("No packages required a version update.", "info");
|
|
795
|
+
} else {
|
|
796
|
+
const packageNames = result.updatedPackages.map((p) => p.name).join(", ");
|
|
797
|
+
log(`Updated ${result.updatedPackages.length} package(s): ${packageNames}`, "success");
|
|
798
|
+
if (result.tags.length > 0) {
|
|
799
|
+
log(`Created ${result.tags.length} tag(s): ${result.tags.join(", ")}`, "success");
|
|
800
|
+
}
|
|
801
|
+
if (result.commitMessage) {
|
|
802
|
+
log(`Created commit with message: "${result.commitMessage}"`, "success");
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
} catch (error) {
|
|
806
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
807
|
+
log(`Async Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
808
|
+
} else {
|
|
809
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
810
|
+
log(`Async Strategy failed: ${errorMessage}`, "error");
|
|
811
|
+
}
|
|
812
|
+
throw error;
|
|
813
|
+
}
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function createStrategy(config) {
|
|
817
|
+
var _a;
|
|
818
|
+
if (config.synced) {
|
|
819
|
+
return createSyncedStrategy(config);
|
|
820
|
+
}
|
|
821
|
+
if (((_a = config.packages) == null ? void 0 : _a.length) === 1) {
|
|
822
|
+
return createSingleStrategy(config);
|
|
823
|
+
}
|
|
824
|
+
return createAsyncStrategy(config);
|
|
825
|
+
}
|
|
826
|
+
function createStrategyMap(config) {
|
|
827
|
+
return {
|
|
828
|
+
synced: createSyncedStrategy(config),
|
|
829
|
+
single: createSingleStrategy(config),
|
|
830
|
+
async: createAsyncStrategy(config)
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// src/core/versionEngine.ts
|
|
835
|
+
var VersionEngine = class {
|
|
836
|
+
config;
|
|
837
|
+
jsonMode;
|
|
838
|
+
workspaceCache = null;
|
|
839
|
+
strategies;
|
|
840
|
+
currentStrategy;
|
|
841
|
+
constructor(config, jsonMode = false) {
|
|
842
|
+
if (!config) {
|
|
843
|
+
throw createVersionError("CONFIG_REQUIRED" /* CONFIG_REQUIRED */);
|
|
844
|
+
}
|
|
845
|
+
if (!config.preset) {
|
|
846
|
+
config.preset = "conventional-commits";
|
|
847
|
+
log("No preset specified, using default: conventional-commits", "warning");
|
|
848
|
+
}
|
|
849
|
+
this.config = config;
|
|
850
|
+
this.jsonMode = jsonMode;
|
|
851
|
+
this.strategies = createStrategyMap(config);
|
|
852
|
+
this.currentStrategy = createStrategy(config);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Get workspace packages information - with caching for performance
|
|
856
|
+
*/
|
|
857
|
+
async getWorkspacePackages() {
|
|
858
|
+
try {
|
|
859
|
+
if (this.workspaceCache) {
|
|
860
|
+
return this.workspaceCache;
|
|
861
|
+
}
|
|
862
|
+
const pkgsResult = getPackagesSync(cwd4());
|
|
863
|
+
if (!pkgsResult || !pkgsResult.packages) {
|
|
864
|
+
throw createVersionError("PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */);
|
|
865
|
+
}
|
|
866
|
+
this.workspaceCache = pkgsResult;
|
|
867
|
+
return pkgsResult;
|
|
868
|
+
} catch (error) {
|
|
869
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
870
|
+
log(`Failed to get packages information: ${errorMessage}`, "error");
|
|
871
|
+
console.error(error);
|
|
872
|
+
throw createVersionError("WORKSPACE_ERROR" /* WORKSPACE_ERROR */, errorMessage);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Run the current strategy
|
|
877
|
+
* @param targets Optional package targets to process (only used by async strategy)
|
|
878
|
+
*/
|
|
879
|
+
async run(targets = []) {
|
|
880
|
+
try {
|
|
881
|
+
const packages = await this.getWorkspacePackages();
|
|
882
|
+
return this.currentStrategy(packages, targets);
|
|
883
|
+
} catch (error) {
|
|
884
|
+
if (error instanceof VersionError || error instanceof GitError) {
|
|
885
|
+
log(`Version engine failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
|
|
886
|
+
} else {
|
|
887
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
888
|
+
log(`Version engine failed: ${errorMessage}`, "error");
|
|
889
|
+
}
|
|
890
|
+
throw error;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Change the current strategy
|
|
895
|
+
* @param strategyType The strategy type to use: 'synced', 'single', or 'async'
|
|
896
|
+
*/
|
|
897
|
+
setStrategy(strategyType) {
|
|
898
|
+
this.currentStrategy = this.strategies[strategyType];
|
|
761
899
|
}
|
|
762
900
|
};
|
|
763
901
|
|
|
764
902
|
// src/index.ts
|
|
765
903
|
async function run() {
|
|
766
|
-
printFiglet();
|
|
767
904
|
const program = new Command();
|
|
768
905
|
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);
|
|
906
|
+
"A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits."
|
|
907
|
+
).version(process.env.npm_package_version || "0.0.0").option(
|
|
908
|
+
"-c, --config <path>",
|
|
909
|
+
"Path to config file (defaults to version.config.json in current directory)"
|
|
910
|
+
).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
911
|
const options = program.opts();
|
|
912
|
+
if (options.json) {
|
|
913
|
+
enableJsonOutput(options.dryRun);
|
|
914
|
+
}
|
|
778
915
|
try {
|
|
779
916
|
const config = await loadConfig(options.config);
|
|
780
|
-
log(
|
|
917
|
+
log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
|
|
781
918
|
if (options.dryRun) config.dryRun = true;
|
|
782
919
|
if (options.synced) config.synced = true;
|
|
783
920
|
if (options.bump) config.forceType = options.bump;
|
|
784
921
|
if (options.prerelease)
|
|
785
922
|
config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
|
|
786
923
|
const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
|
|
787
|
-
const engine = new VersionEngine(config);
|
|
924
|
+
const engine = new VersionEngine(config, !!options.json);
|
|
788
925
|
if (config.synced) {
|
|
789
|
-
log("
|
|
790
|
-
|
|
926
|
+
log("Using synced versioning strategy.", "info");
|
|
927
|
+
engine.setStrategy("synced");
|
|
928
|
+
await engine.run();
|
|
791
929
|
} else if (config.packages && config.packages.length === 1) {
|
|
792
|
-
log("
|
|
930
|
+
log("Using single package versioning strategy.", "info");
|
|
793
931
|
if (cliTargets.length > 0) {
|
|
794
|
-
log("
|
|
932
|
+
log("--target flag is ignored for single package strategy.", "warning");
|
|
795
933
|
}
|
|
796
|
-
|
|
934
|
+
engine.setStrategy("single");
|
|
935
|
+
await engine.run();
|
|
797
936
|
} else {
|
|
798
|
-
log("
|
|
937
|
+
log("Using async versioning strategy.", "info");
|
|
799
938
|
if (cliTargets.length > 0) {
|
|
800
|
-
log(
|
|
939
|
+
log(`Targeting specific packages: ${cliTargets.join(", ")}`, "info");
|
|
801
940
|
}
|
|
802
|
-
|
|
941
|
+
engine.setStrategy("async");
|
|
942
|
+
await engine.run(cliTargets);
|
|
803
943
|
}
|
|
804
|
-
log("
|
|
944
|
+
log("Versioning process completed.", "success");
|
|
945
|
+
printJsonOutput();
|
|
805
946
|
} catch (error) {
|
|
806
|
-
log(
|
|
947
|
+
log(error instanceof Error ? error.message : String(error), "error");
|
|
807
948
|
process.exit(1);
|
|
808
949
|
}
|
|
809
950
|
}
|
|
810
|
-
run()
|
|
951
|
+
run().catch((error) => {
|
|
952
|
+
console.error("Fatal error:", error);
|
|
953
|
+
process.exit(1);
|
|
954
|
+
});
|