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