package-versioner 0.0.1 → 0.1.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 +10 -1
- package/dist/index.cjs +165 -114
- package/dist/index.d.cts +1 -0
- package/dist/index.js +168 -121
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# package-versioner
|
|
2
2
|
|
|
3
|
+
|
|
4
|
+
<a href="https://www.npmjs.com/package/package-versioner" alt="NPM Version">
|
|
5
|
+
<img src="https://img.shields.io/npm/v/package-versioner" /></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/package-versioner" alt="NPM Downloads">
|
|
7
|
+
<img src="https://img.shields.io/npm/dw/package-versioner" /></a>
|
|
8
|
+
|
|
3
9
|
A powerful CLI tool for automated semantic versioning based on Git history and conventional commits. Simplifies version management in JavaScript/TypeScript projects.
|
|
4
10
|
|
|
5
11
|
## Features
|
|
@@ -32,6 +38,9 @@ npx package-versioner --bump minor
|
|
|
32
38
|
# Create a prerelease (e.g., alpha)
|
|
33
39
|
npx package-versioner --bump patch --prerelease alpha
|
|
34
40
|
|
|
41
|
+
# Target specific packages (only in async/independent mode, comma-separated)
|
|
42
|
+
npx package-versioner -t @scope/package-a,@scope/package-b
|
|
43
|
+
|
|
35
44
|
# Perform a dry run: calculates version, logs actions, but makes no file changes or Git commits/tags
|
|
36
45
|
npx package-versioner --dry-run
|
|
37
46
|
```
|
|
@@ -82,7 +91,7 @@ npx package-versioner --help
|
|
|
82
91
|
|
|
83
92
|
## Acknowledgements
|
|
84
93
|
|
|
85
|
-
This project was originally forked from and inspired by `jucian0/turbo-version`
|
|
94
|
+
This project was originally forked from and inspired by [`jucian0/turbo-version`](https://github.com/jucian0/turbo-version). We appreciate the foundational work done by the original authors.
|
|
86
95
|
|
|
87
96
|
## License
|
|
88
97
|
|
package/dist/index.cjs
CHANGED
|
@@ -15,21 +15,50 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
return to;
|
|
16
16
|
};
|
|
17
17
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
18
22
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
19
23
|
mod
|
|
20
24
|
));
|
|
21
25
|
|
|
22
26
|
// src/index.ts
|
|
23
|
-
var import_node_process4 = require("process");
|
|
24
|
-
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
25
27
|
var import_commander = require("commander");
|
|
28
|
+
|
|
29
|
+
// src/config.ts
|
|
30
|
+
var fs = __toESM(require("fs"), 1);
|
|
31
|
+
var import_node_process = require("process");
|
|
32
|
+
function loadConfig(configPath) {
|
|
33
|
+
const localProcess = (0, import_node_process.cwd)();
|
|
34
|
+
const filePath = configPath || `${localProcess}/version.config.json`;
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
fs.readFile(filePath, "utf-8", (err, data) => {
|
|
37
|
+
if (err) {
|
|
38
|
+
reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const config = JSON.parse(data);
|
|
43
|
+
resolve(config);
|
|
44
|
+
} catch (err2) {
|
|
45
|
+
const errorMessage = err2 instanceof Error ? err2.message : String(err2);
|
|
46
|
+
reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/utils.ts
|
|
53
|
+
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
54
|
+
var import_chalk = __toESM(require("chalk"), 1);
|
|
26
55
|
var import_figlet = __toESM(require("figlet"), 1);
|
|
27
56
|
|
|
28
57
|
// package.json
|
|
29
58
|
var package_default = {
|
|
30
59
|
name: "package-versioner",
|
|
31
60
|
description: "A powerful CLI tool for automated semantic versioning based on Git history and conventional commits. Supports monorepos with synchronized or independent package versioning strategies.",
|
|
32
|
-
version: "0.0.
|
|
61
|
+
version: "0.0.2",
|
|
33
62
|
type: "module",
|
|
34
63
|
main: "./dist/index.js",
|
|
35
64
|
module: "./dist/index.mjs",
|
|
@@ -43,9 +72,17 @@ var package_default = {
|
|
|
43
72
|
url: "https://github.com/goosewobbler/package-versioner",
|
|
44
73
|
homepage: "https://github.com/goosewobbler/package-versioner"
|
|
45
74
|
},
|
|
46
|
-
keywords: [
|
|
75
|
+
keywords: [
|
|
76
|
+
"version",
|
|
77
|
+
"semver",
|
|
78
|
+
"git",
|
|
79
|
+
"package"
|
|
80
|
+
],
|
|
47
81
|
license: "MIT",
|
|
48
|
-
files: [
|
|
82
|
+
files: [
|
|
83
|
+
"dist/**",
|
|
84
|
+
"package-versioner.schema.json"
|
|
85
|
+
],
|
|
49
86
|
bin: {
|
|
50
87
|
"package-versioner": "./dist/index.js"
|
|
51
88
|
},
|
|
@@ -63,17 +100,20 @@ var package_default = {
|
|
|
63
100
|
prepare: "husky"
|
|
64
101
|
},
|
|
65
102
|
"lint-staged": {
|
|
66
|
-
"*.{js,ts,jsx,tsx}": [
|
|
103
|
+
"*.{js,ts,jsx,tsx}": [
|
|
104
|
+
"biome check --apply",
|
|
105
|
+
"biome format --write"
|
|
106
|
+
]
|
|
67
107
|
},
|
|
68
108
|
devDependencies: {
|
|
69
109
|
"@biomejs/biome": "^1.9.4",
|
|
70
110
|
"@types/figlet": "^1.5.5",
|
|
71
|
-
"@types/node": "^
|
|
111
|
+
"@types/node": "^22.14.0",
|
|
72
112
|
"@types/semver": "^7.3.13",
|
|
73
113
|
"@vitest/coverage-v8": "^3.1.1",
|
|
74
114
|
husky: "^9.1.7",
|
|
75
115
|
"lint-staged": "^15.5.0",
|
|
76
|
-
tsup: "^
|
|
116
|
+
tsup: "^8.4.0",
|
|
77
117
|
typescript: "^5.8.3",
|
|
78
118
|
vitest: "^3.1.1"
|
|
79
119
|
},
|
|
@@ -90,32 +130,7 @@ var package_default = {
|
|
|
90
130
|
packageManager: "pnpm@10.8.0+sha512.0e82714d1b5b43c74610193cb20734897c1d00de89d0e18420aebc5977fa13d780a9cb05734624e81ebd81cc876cd464794850641c48b9544326b5622ca29971"
|
|
91
131
|
};
|
|
92
132
|
|
|
93
|
-
// src/config.ts
|
|
94
|
-
var fs = __toESM(require("fs"), 1);
|
|
95
|
-
var import_node_process = require("process");
|
|
96
|
-
function loadConfig(configPath) {
|
|
97
|
-
const localProcess = (0, import_node_process.cwd)();
|
|
98
|
-
const filePath = configPath || `${localProcess}/version.config.json`;
|
|
99
|
-
return new Promise((resolve, reject) => {
|
|
100
|
-
fs.readFile(filePath, "utf-8", (err, data) => {
|
|
101
|
-
if (err) {
|
|
102
|
-
reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
try {
|
|
106
|
-
const config = JSON.parse(data);
|
|
107
|
-
resolve(config);
|
|
108
|
-
} catch (err2) {
|
|
109
|
-
const errorMessage = err2 instanceof Error ? err2.message : String(err2);
|
|
110
|
-
reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
133
|
// src/utils.ts
|
|
117
|
-
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
118
|
-
var import_chalk = __toESM(require("chalk"), 1);
|
|
119
134
|
var import_git_semver_tags = require("git-semver-tags");
|
|
120
135
|
|
|
121
136
|
// src/git.ts
|
|
@@ -202,7 +217,7 @@ async function gitProcess({ files, nextTag, commitMessage, skipHooks, dryRun })
|
|
|
202
217
|
message: commitMessage,
|
|
203
218
|
skipHooks
|
|
204
219
|
});
|
|
205
|
-
const tagMessage = `New Version ${nextTag} generated at ${new Date().toISOString()}`;
|
|
220
|
+
const tagMessage = `New Version ${nextTag} generated at ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
206
221
|
await createGitTag({
|
|
207
222
|
tag: nextTag,
|
|
208
223
|
message: tagMessage
|
|
@@ -241,6 +256,25 @@ function getCurrentBranch() {
|
|
|
241
256
|
}
|
|
242
257
|
|
|
243
258
|
// src/utils.ts
|
|
259
|
+
function printFiglet() {
|
|
260
|
+
const font = "Standard";
|
|
261
|
+
import_figlet.default.text(package_default.name, { font }, (err, data) => {
|
|
262
|
+
if (err) {
|
|
263
|
+
log("warning", "Could not print figlet banner: Figlet error");
|
|
264
|
+
console.error(err);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (data) {
|
|
268
|
+
const figletText = data;
|
|
269
|
+
const versionText = `v${package_default.version}`;
|
|
270
|
+
process.stdout.write(`${import_chalk.default.hex("#FF1F57")(figletText)}
|
|
271
|
+
`);
|
|
272
|
+
process.stdout.write(`${import_chalk.default.hex("#0096FF")(versionText)}
|
|
273
|
+
|
|
274
|
+
`);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
244
278
|
function log(status, message) {
|
|
245
279
|
const statusColors = {
|
|
246
280
|
info: import_chalk.default.blue("\u2139"),
|
|
@@ -265,10 +299,10 @@ async function getLatestTag() {
|
|
|
265
299
|
}
|
|
266
300
|
}
|
|
267
301
|
function formatTag(options, props) {
|
|
268
|
-
const { name
|
|
302
|
+
const { name, synced, tagPrefix } = options;
|
|
269
303
|
const { version } = props;
|
|
270
|
-
if (!synced &&
|
|
271
|
-
return `${tagPrefix ? tagPrefix : ""}${
|
|
304
|
+
if (!synced && name) {
|
|
305
|
+
return `${tagPrefix ? tagPrefix : ""}${name}@${version}`;
|
|
272
306
|
}
|
|
273
307
|
return `${tagPrefix ? tagPrefix : "v"}${version}`;
|
|
274
308
|
}
|
|
@@ -281,7 +315,7 @@ function createTemplateString(template, data) {
|
|
|
281
315
|
function formatCommitMessage(template, version) {
|
|
282
316
|
return createTemplateString(template, { version });
|
|
283
317
|
}
|
|
284
|
-
function updatePackageVersion({ path: path2, version, name
|
|
318
|
+
function updatePackageVersion({ path: path2, version, name, dryRun }) {
|
|
285
319
|
try {
|
|
286
320
|
const pkgPath = `${path2}/package.json`;
|
|
287
321
|
const pkg = JSON.parse(import_node_fs2.default.readFileSync(pkgPath, "utf8"));
|
|
@@ -289,12 +323,12 @@ function updatePackageVersion({ path: path2, version, name: name2, dryRun }) {
|
|
|
289
323
|
if (!dryRun) {
|
|
290
324
|
import_node_fs2.default.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
291
325
|
`);
|
|
292
|
-
log("success", `${
|
|
326
|
+
log("success", `${name}: ${version}`);
|
|
293
327
|
} else {
|
|
294
|
-
log("info", `[DRY RUN] Would update ${
|
|
328
|
+
log("info", `[DRY RUN] Would update ${name} package.json to version ${version}`);
|
|
295
329
|
}
|
|
296
330
|
} catch (error) {
|
|
297
|
-
log("error", `Failed to update ${
|
|
331
|
+
log("error", `Failed to update ${name} to version ${version}`);
|
|
298
332
|
console.error(error);
|
|
299
333
|
}
|
|
300
334
|
}
|
|
@@ -307,14 +341,18 @@ var import_get_packages = require("@manypkg/get-packages");
|
|
|
307
341
|
var import_conventional_recommended_bump = require("conventional-recommended-bump");
|
|
308
342
|
var import_semver = __toESM(require("semver"), 1);
|
|
309
343
|
var VersionEngine = class {
|
|
344
|
+
config;
|
|
310
345
|
constructor(config) {
|
|
311
346
|
this.config = config;
|
|
312
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Calculate the next version based on options
|
|
350
|
+
*/
|
|
313
351
|
async calculateVersion(options) {
|
|
314
|
-
const { latestTag, type, path: path2, name
|
|
352
|
+
const { latestTag, type, path: path2, name, branchPattern, prereleaseIdentifier } = options;
|
|
315
353
|
const originalPrefix = this.config.tagPrefix || "";
|
|
316
354
|
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
317
|
-
const tagSearchPattern =
|
|
355
|
+
const tagSearchPattern = name ? originalPrefix ? `${originalPrefix}${name}@` : `${name}@` : originalPrefix ? `${originalPrefix}v` : "v";
|
|
318
356
|
let determinedReleaseType = type || null;
|
|
319
357
|
if (determinedReleaseType) {
|
|
320
358
|
if (!latestTag) {
|
|
@@ -355,21 +393,21 @@ var VersionEngine = class {
|
|
|
355
393
|
if (commitsLength === 0) {
|
|
356
394
|
log(
|
|
357
395
|
"info",
|
|
358
|
-
`No new commits found for ${
|
|
396
|
+
`No new commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
359
397
|
);
|
|
360
398
|
return "";
|
|
361
399
|
}
|
|
362
400
|
if (!releaseTypeFromCommits) {
|
|
363
401
|
log(
|
|
364
402
|
"info",
|
|
365
|
-
`No relevant commits found for ${
|
|
403
|
+
`No relevant commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
366
404
|
);
|
|
367
405
|
return "";
|
|
368
406
|
}
|
|
369
407
|
const currentVersion = import_semver.default.clean(latestTag.replace(tagSearchPattern, "")) || "0.0.0";
|
|
370
408
|
return import_semver.default.inc(currentVersion, releaseTypeFromCommits, prereleaseIdentifier) || "";
|
|
371
409
|
} catch (error) {
|
|
372
|
-
log("error", `Failed to calculate version for ${
|
|
410
|
+
log("error", `Failed to calculate version for ${name || "project"}`);
|
|
373
411
|
console.error(error);
|
|
374
412
|
if (error instanceof Error && error.message.includes("No names found")) {
|
|
375
413
|
log("info", "No tags found, proceeding with initial version calculation (if applicable).");
|
|
@@ -378,30 +416,44 @@ var VersionEngine = class {
|
|
|
378
416
|
return "";
|
|
379
417
|
}
|
|
380
418
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
419
|
+
/**
|
|
420
|
+
* Process packages based on discovery, skip list, and optional target list.
|
|
421
|
+
* Returns a list of package.json file paths that were updated (or would be in dry run).
|
|
422
|
+
*/
|
|
423
|
+
async processPackages(discoveredPackages = [], targets = []) {
|
|
424
|
+
const { tagPrefix, skip } = this.config;
|
|
384
425
|
const files = [];
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
426
|
+
const pkgsToConsider = discoveredPackages.filter((pkg) => {
|
|
427
|
+
if (skip == null ? void 0 : skip.includes(pkg.packageJson.name)) {
|
|
428
|
+
log("info", `Skipping package ${pkg.packageJson.name} based on config skip list.`);
|
|
388
429
|
return false;
|
|
389
430
|
}
|
|
390
|
-
|
|
431
|
+
if (targets.length > 0) {
|
|
432
|
+
const isTargeted = targets.includes(pkg.packageJson.name);
|
|
433
|
+
if (!isTargeted) {
|
|
434
|
+
}
|
|
435
|
+
return isTargeted;
|
|
436
|
+
}
|
|
437
|
+
return true;
|
|
391
438
|
});
|
|
392
|
-
|
|
393
|
-
|
|
439
|
+
log("info", `Found ${pkgsToConsider.length} package(s) to process after filtering.`);
|
|
440
|
+
for (const pkg of pkgsToConsider) {
|
|
441
|
+
const name = pkg.packageJson.name;
|
|
394
442
|
const pkgPath = pkg.dir;
|
|
395
443
|
const prefix = formatTagPrefix(tagPrefix);
|
|
396
444
|
const latestTag = await getLatestTag();
|
|
397
445
|
const nextVersion = await this.calculateVersion({
|
|
398
446
|
latestTag,
|
|
447
|
+
// This might need refinement for async based on package-specific tags
|
|
399
448
|
tagPrefix: prefix,
|
|
400
449
|
path: pkgPath,
|
|
401
|
-
name
|
|
450
|
+
name,
|
|
451
|
+
// Pass name for potential package-specific tag lookups
|
|
402
452
|
branchPattern: this.config.branchPattern,
|
|
403
453
|
baseBranch: this.config.baseBranch,
|
|
404
|
-
prereleaseIdentifier: this.config.prereleaseIdentifier
|
|
454
|
+
prereleaseIdentifier: this.config.prereleaseIdentifier,
|
|
455
|
+
type: this.config.forceType
|
|
456
|
+
// Pass forced type if provided
|
|
405
457
|
});
|
|
406
458
|
if (!nextVersion) {
|
|
407
459
|
continue;
|
|
@@ -409,13 +461,16 @@ var VersionEngine = class {
|
|
|
409
461
|
updatePackageVersion({
|
|
410
462
|
path: pkgPath,
|
|
411
463
|
version: nextVersion,
|
|
412
|
-
name
|
|
464
|
+
name,
|
|
413
465
|
dryRun: this.config.dryRun
|
|
414
466
|
});
|
|
415
467
|
files.push(import_node_path2.default.join(pkgPath, "package.json"));
|
|
416
468
|
}
|
|
417
469
|
return files;
|
|
418
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* Create git commit and tag
|
|
473
|
+
*/
|
|
419
474
|
async createGitCommitAndTag(files, nextTag, commitMessage, dryRun) {
|
|
420
475
|
try {
|
|
421
476
|
await gitProcess({
|
|
@@ -434,6 +489,9 @@ var VersionEngine = class {
|
|
|
434
489
|
(0, import_node_process3.exit)(1);
|
|
435
490
|
}
|
|
436
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Synced versioning strategy (all packages get the same version)
|
|
494
|
+
*/
|
|
437
495
|
async syncedStrategy() {
|
|
438
496
|
var _a;
|
|
439
497
|
const {
|
|
@@ -502,6 +560,9 @@ var VersionEngine = class {
|
|
|
502
560
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
503
561
|
await this.createGitCommitAndTag(files, nextTag, formattedCommitMessage, this.config.dryRun);
|
|
504
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Single package versioning strategy
|
|
565
|
+
*/
|
|
505
566
|
async singleStrategy() {
|
|
506
567
|
const {
|
|
507
568
|
packages: configPackages,
|
|
@@ -561,11 +622,15 @@ var VersionEngine = class {
|
|
|
561
622
|
this.config.dryRun
|
|
562
623
|
);
|
|
563
624
|
}
|
|
564
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Async versioning strategy (each package gets its own version)
|
|
627
|
+
*/
|
|
628
|
+
async asyncStrategy(cliTargets = []) {
|
|
565
629
|
const {
|
|
566
|
-
packages: configPackages,
|
|
567
630
|
commitMessage = "chore(release): ${version}",
|
|
631
|
+
// Align with test expectations
|
|
568
632
|
skipHooks
|
|
633
|
+
// Add skipHooks here
|
|
569
634
|
} = this.config;
|
|
570
635
|
let pkgsResult;
|
|
571
636
|
try {
|
|
@@ -579,9 +644,9 @@ var VersionEngine = class {
|
|
|
579
644
|
(0, import_node_process3.exit)(1);
|
|
580
645
|
return;
|
|
581
646
|
}
|
|
582
|
-
const pkgsToProcess = await this.processPackages(pkgsResult.packages,
|
|
647
|
+
const pkgsToProcess = await this.processPackages(pkgsResult.packages, cliTargets);
|
|
583
648
|
if (pkgsToProcess.length === 0) {
|
|
584
|
-
log("info", "No packages to process");
|
|
649
|
+
log("info", "No packages to process based on changes and targets");
|
|
585
650
|
return;
|
|
586
651
|
}
|
|
587
652
|
const formattedCommitMessage = commitMessage;
|
|
@@ -594,7 +659,7 @@ var VersionEngine = class {
|
|
|
594
659
|
dryRun: this.config.dryRun
|
|
595
660
|
});
|
|
596
661
|
if (!this.config.dryRun) {
|
|
597
|
-
log("success",
|
|
662
|
+
log("success", `Created version commit for ${pkgsToProcess.length} package(s)`);
|
|
598
663
|
}
|
|
599
664
|
} catch (error) {
|
|
600
665
|
log("error", "Failed to create version commit");
|
|
@@ -605,63 +670,49 @@ var VersionEngine = class {
|
|
|
605
670
|
};
|
|
606
671
|
|
|
607
672
|
// src/index.ts
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
program
|
|
611
|
-
program.
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
"
|
|
615
|
-
"
|
|
616
|
-
|
|
617
|
-
"
|
|
618
|
-
"
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
if (!validBumps.includes(value)) {
|
|
622
|
-
log("error", `Invalid bump type '${value}'. Valid options are: ${validBumps.join(", ")}`);
|
|
623
|
-
process.exit(1);
|
|
624
|
-
}
|
|
625
|
-
return value;
|
|
626
|
-
}).option("--base-branch <branch>", "override the base branch for this operation").option("--synced", "force synced versioning mode").option("--no-synced", "force async versioning mode").option(
|
|
627
|
-
"--skip <packages>",
|
|
628
|
-
"comma-separated list of packages to skip",
|
|
629
|
-
(value) => value.split(",")
|
|
630
|
-
).option("--prerelease <identifier>", "set prerelease identifier (e.g., alpha, beta)").option("--skip-hooks", "skip Git hooks for this operation").option("--config <path>", "specify a custom config file path").option("--dry-run", "Calculate version and log actions without changing files or Git state");
|
|
631
|
-
program.description("Version packages based on Git context and conventional commits").action(async (options) => {
|
|
632
|
-
const figletText = import_figlet.default.textSync(name);
|
|
633
|
-
const versionText = `v${package_default.version}`;
|
|
634
|
-
process.stdout.write(`${import_chalk2.default.hex("#FF1F57")(figletText)}
|
|
635
|
-
`);
|
|
636
|
-
process.stdout.write(`${import_chalk2.default.hex("#0096FF")(versionText)}
|
|
637
|
-
|
|
638
|
-
`);
|
|
673
|
+
async function run() {
|
|
674
|
+
printFiglet();
|
|
675
|
+
const program = new import_commander.Command();
|
|
676
|
+
program.name("package-versioner").description(
|
|
677
|
+
"Automated semantic versioning based on Git history and conventional commits. Supports monorepos with synchronized or independent package versioning strategies."
|
|
678
|
+
).version("0.0.2").option("--config <path>", "Path to the configuration file").option("--dry-run", "Simulate the versioning process without making changes").option("--synced", "Force synced versioning strategy (overrides config)").option("--bump <type>", "Force a specific release type (patch, minor, major)").option(
|
|
679
|
+
"--prerelease <identifier>",
|
|
680
|
+
"Create a prerelease version with the specified identifier"
|
|
681
|
+
).option(
|
|
682
|
+
"-t, --target <targets>",
|
|
683
|
+
"Comma-separated list of package names to target (only for async strategy)"
|
|
684
|
+
).parse(process.argv);
|
|
685
|
+
const options = program.opts();
|
|
639
686
|
try {
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
if (options.
|
|
643
|
-
|
|
644
|
-
if (options.
|
|
645
|
-
config.synced = options.synced;
|
|
646
|
-
if (options.skip)
|
|
647
|
-
config.skip = options.skip;
|
|
687
|
+
const config = await loadConfig(options.config);
|
|
688
|
+
log("info", `Loaded configuration from ${options.config || "version.config.json"}`);
|
|
689
|
+
if (options.dryRun) config.dryRun = true;
|
|
690
|
+
if (options.synced) config.synced = true;
|
|
691
|
+
if (options.bump) config.forceType = options.bump;
|
|
648
692
|
if (options.prerelease)
|
|
649
|
-
config.prereleaseIdentifier = options.prerelease;
|
|
650
|
-
|
|
651
|
-
config.skipHooks = options.skipHooks;
|
|
652
|
-
if (options.dryRun !== void 0)
|
|
653
|
-
config.dryRun = options.dryRun;
|
|
693
|
+
config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
|
|
694
|
+
const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
|
|
654
695
|
const engine = new VersionEngine(config);
|
|
655
696
|
if (config.synced) {
|
|
697
|
+
log("info", "Using synced versioning strategy.");
|
|
656
698
|
await engine.syncedStrategy();
|
|
657
|
-
} else if (
|
|
699
|
+
} else if (config.packages && config.packages.length === 1) {
|
|
700
|
+
log("info", "Using single package versioning strategy.");
|
|
701
|
+
if (cliTargets.length > 0) {
|
|
702
|
+
log("warning", "--target flag is ignored for single package strategy.");
|
|
703
|
+
}
|
|
658
704
|
await engine.singleStrategy();
|
|
659
705
|
} else {
|
|
660
|
-
|
|
706
|
+
log("info", "Using async versioning strategy.");
|
|
707
|
+
if (cliTargets.length > 0) {
|
|
708
|
+
log("info", `Targeting specific packages: ${cliTargets.join(", ")}`);
|
|
709
|
+
}
|
|
710
|
+
await engine.asyncStrategy(cliTargets);
|
|
661
711
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
(
|
|
712
|
+
log("success", "Versioning process completed.");
|
|
713
|
+
} catch (error) {
|
|
714
|
+
log("error", error instanceof Error ? error.message : String(error));
|
|
715
|
+
process.exit(1);
|
|
665
716
|
}
|
|
666
|
-
}
|
|
667
|
-
|
|
717
|
+
}
|
|
718
|
+
run();
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { exit as exit2 } from "process";
|
|
5
|
-
import chalk2 from "chalk";
|
|
6
4
|
import { Command } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/config.ts
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import { cwd } from "node:process";
|
|
9
|
+
function loadConfig(configPath) {
|
|
10
|
+
const localProcess = cwd();
|
|
11
|
+
const filePath = configPath || `${localProcess}/version.config.json`;
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
fs.readFile(filePath, "utf-8", (err, data) => {
|
|
14
|
+
if (err) {
|
|
15
|
+
reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
try {
|
|
19
|
+
const config = JSON.parse(data);
|
|
20
|
+
resolve(config);
|
|
21
|
+
} catch (err2) {
|
|
22
|
+
const errorMessage = err2 instanceof Error ? err2.message : String(err2);
|
|
23
|
+
reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/utils.ts
|
|
30
|
+
import fs2 from "node:fs";
|
|
31
|
+
import chalk from "chalk";
|
|
7
32
|
import figlet from "figlet";
|
|
8
33
|
|
|
9
34
|
// package.json
|
|
10
35
|
var package_default = {
|
|
11
36
|
name: "package-versioner",
|
|
12
37
|
description: "A powerful CLI tool for automated semantic versioning based on Git history and conventional commits. Supports monorepos with synchronized or independent package versioning strategies.",
|
|
13
|
-
version: "0.0.
|
|
38
|
+
version: "0.0.2",
|
|
14
39
|
type: "module",
|
|
15
40
|
main: "./dist/index.js",
|
|
16
41
|
module: "./dist/index.mjs",
|
|
@@ -24,9 +49,17 @@ var package_default = {
|
|
|
24
49
|
url: "https://github.com/goosewobbler/package-versioner",
|
|
25
50
|
homepage: "https://github.com/goosewobbler/package-versioner"
|
|
26
51
|
},
|
|
27
|
-
keywords: [
|
|
52
|
+
keywords: [
|
|
53
|
+
"version",
|
|
54
|
+
"semver",
|
|
55
|
+
"git",
|
|
56
|
+
"package"
|
|
57
|
+
],
|
|
28
58
|
license: "MIT",
|
|
29
|
-
files: [
|
|
59
|
+
files: [
|
|
60
|
+
"dist/**",
|
|
61
|
+
"package-versioner.schema.json"
|
|
62
|
+
],
|
|
30
63
|
bin: {
|
|
31
64
|
"package-versioner": "./dist/index.js"
|
|
32
65
|
},
|
|
@@ -44,17 +77,20 @@ var package_default = {
|
|
|
44
77
|
prepare: "husky"
|
|
45
78
|
},
|
|
46
79
|
"lint-staged": {
|
|
47
|
-
"*.{js,ts,jsx,tsx}": [
|
|
80
|
+
"*.{js,ts,jsx,tsx}": [
|
|
81
|
+
"biome check --apply",
|
|
82
|
+
"biome format --write"
|
|
83
|
+
]
|
|
48
84
|
},
|
|
49
85
|
devDependencies: {
|
|
50
86
|
"@biomejs/biome": "^1.9.4",
|
|
51
87
|
"@types/figlet": "^1.5.5",
|
|
52
|
-
"@types/node": "^
|
|
88
|
+
"@types/node": "^22.14.0",
|
|
53
89
|
"@types/semver": "^7.3.13",
|
|
54
90
|
"@vitest/coverage-v8": "^3.1.1",
|
|
55
91
|
husky: "^9.1.7",
|
|
56
92
|
"lint-staged": "^15.5.0",
|
|
57
|
-
tsup: "^
|
|
93
|
+
tsup: "^8.4.0",
|
|
58
94
|
typescript: "^5.8.3",
|
|
59
95
|
vitest: "^3.1.1"
|
|
60
96
|
},
|
|
@@ -71,39 +107,14 @@ var package_default = {
|
|
|
71
107
|
packageManager: "pnpm@10.8.0+sha512.0e82714d1b5b43c74610193cb20734897c1d00de89d0e18420aebc5977fa13d780a9cb05734624e81ebd81cc876cd464794850641c48b9544326b5622ca29971"
|
|
72
108
|
};
|
|
73
109
|
|
|
74
|
-
// src/config.ts
|
|
75
|
-
import * as fs from "fs";
|
|
76
|
-
import { cwd } from "process";
|
|
77
|
-
function loadConfig(configPath) {
|
|
78
|
-
const localProcess = cwd();
|
|
79
|
-
const filePath = configPath || `${localProcess}/version.config.json`;
|
|
80
|
-
return new Promise((resolve, reject) => {
|
|
81
|
-
fs.readFile(filePath, "utf-8", (err, data) => {
|
|
82
|
-
if (err) {
|
|
83
|
-
reject(new Error(`Could not locate the config file at ${filePath}: ${err.message}`));
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
try {
|
|
87
|
-
const config = JSON.parse(data);
|
|
88
|
-
resolve(config);
|
|
89
|
-
} catch (err2) {
|
|
90
|
-
const errorMessage = err2 instanceof Error ? err2.message : String(err2);
|
|
91
|
-
reject(new Error(`Failed to parse config file ${filePath}: ${errorMessage}`));
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
110
|
// src/utils.ts
|
|
98
|
-
import fs2 from "fs";
|
|
99
|
-
import chalk from "chalk";
|
|
100
111
|
import { getSemverTags } from "git-semver-tags";
|
|
101
112
|
|
|
102
113
|
// src/git.ts
|
|
103
|
-
import { exec, execSync as syncExec } from "child_process";
|
|
104
|
-
import { existsSync, statSync } from "fs";
|
|
105
|
-
import { join } from "path";
|
|
106
|
-
import { cwd as cwd2 } from "process";
|
|
114
|
+
import { exec, execSync as syncExec } from "node:child_process";
|
|
115
|
+
import { existsSync, statSync } from "node:fs";
|
|
116
|
+
import { join } from "node:path";
|
|
117
|
+
import { cwd as cwd2 } from "node:process";
|
|
107
118
|
var execAsync = (command) => {
|
|
108
119
|
return new Promise((resolve, reject) => {
|
|
109
120
|
const options = { maxBuffer: 1024 * 1024 * 10 };
|
|
@@ -183,7 +194,7 @@ async function gitProcess({ files, nextTag, commitMessage, skipHooks, dryRun })
|
|
|
183
194
|
message: commitMessage,
|
|
184
195
|
skipHooks
|
|
185
196
|
});
|
|
186
|
-
const tagMessage = `New Version ${nextTag} generated at ${new Date().toISOString()}`;
|
|
197
|
+
const tagMessage = `New Version ${nextTag} generated at ${(/* @__PURE__ */ new Date()).toISOString()}`;
|
|
187
198
|
await createGitTag({
|
|
188
199
|
tag: nextTag,
|
|
189
200
|
message: tagMessage
|
|
@@ -222,6 +233,25 @@ function getCurrentBranch() {
|
|
|
222
233
|
}
|
|
223
234
|
|
|
224
235
|
// src/utils.ts
|
|
236
|
+
function printFiglet() {
|
|
237
|
+
const font = "Standard";
|
|
238
|
+
figlet.text(package_default.name, { font }, (err, data) => {
|
|
239
|
+
if (err) {
|
|
240
|
+
log("warning", "Could not print figlet banner: Figlet error");
|
|
241
|
+
console.error(err);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (data) {
|
|
245
|
+
const figletText = data;
|
|
246
|
+
const versionText = `v${package_default.version}`;
|
|
247
|
+
process.stdout.write(`${chalk.hex("#FF1F57")(figletText)}
|
|
248
|
+
`);
|
|
249
|
+
process.stdout.write(`${chalk.hex("#0096FF")(versionText)}
|
|
250
|
+
|
|
251
|
+
`);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
225
255
|
function log(status, message) {
|
|
226
256
|
const statusColors = {
|
|
227
257
|
info: chalk.blue("\u2139"),
|
|
@@ -246,10 +276,10 @@ async function getLatestTag() {
|
|
|
246
276
|
}
|
|
247
277
|
}
|
|
248
278
|
function formatTag(options, props) {
|
|
249
|
-
const { name
|
|
279
|
+
const { name, synced, tagPrefix } = options;
|
|
250
280
|
const { version } = props;
|
|
251
|
-
if (!synced &&
|
|
252
|
-
return `${tagPrefix ? tagPrefix : ""}${
|
|
281
|
+
if (!synced && name) {
|
|
282
|
+
return `${tagPrefix ? tagPrefix : ""}${name}@${version}`;
|
|
253
283
|
}
|
|
254
284
|
return `${tagPrefix ? tagPrefix : "v"}${version}`;
|
|
255
285
|
}
|
|
@@ -262,7 +292,7 @@ function createTemplateString(template, data) {
|
|
|
262
292
|
function formatCommitMessage(template, version) {
|
|
263
293
|
return createTemplateString(template, { version });
|
|
264
294
|
}
|
|
265
|
-
function updatePackageVersion({ path: path2, version, name
|
|
295
|
+
function updatePackageVersion({ path: path2, version, name, dryRun }) {
|
|
266
296
|
try {
|
|
267
297
|
const pkgPath = `${path2}/package.json`;
|
|
268
298
|
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
|
|
@@ -270,32 +300,36 @@ function updatePackageVersion({ path: path2, version, name: name2, dryRun }) {
|
|
|
270
300
|
if (!dryRun) {
|
|
271
301
|
fs2.writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
272
302
|
`);
|
|
273
|
-
log("success", `${
|
|
303
|
+
log("success", `${name}: ${version}`);
|
|
274
304
|
} else {
|
|
275
|
-
log("info", `[DRY RUN] Would update ${
|
|
305
|
+
log("info", `[DRY RUN] Would update ${name} package.json to version ${version}`);
|
|
276
306
|
}
|
|
277
307
|
} catch (error) {
|
|
278
|
-
log("error", `Failed to update ${
|
|
308
|
+
log("error", `Failed to update ${name} to version ${version}`);
|
|
279
309
|
console.error(error);
|
|
280
310
|
}
|
|
281
311
|
}
|
|
282
312
|
|
|
283
313
|
// src/versionEngine.ts
|
|
284
|
-
import fs3 from "fs";
|
|
285
|
-
import path from "path";
|
|
286
|
-
import { cwd as cwd3, exit } from "process";
|
|
314
|
+
import fs3 from "node:fs";
|
|
315
|
+
import path from "node:path";
|
|
316
|
+
import { cwd as cwd3, exit } from "node:process";
|
|
287
317
|
import { getPackagesSync } from "@manypkg/get-packages";
|
|
288
318
|
import { Bumper } from "conventional-recommended-bump";
|
|
289
319
|
import semver from "semver";
|
|
290
320
|
var VersionEngine = class {
|
|
321
|
+
config;
|
|
291
322
|
constructor(config) {
|
|
292
323
|
this.config = config;
|
|
293
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Calculate the next version based on options
|
|
327
|
+
*/
|
|
294
328
|
async calculateVersion(options) {
|
|
295
|
-
const { latestTag, type, path: path2, name
|
|
329
|
+
const { latestTag, type, path: path2, name, branchPattern, prereleaseIdentifier } = options;
|
|
296
330
|
const originalPrefix = this.config.tagPrefix || "";
|
|
297
331
|
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
298
|
-
const tagSearchPattern =
|
|
332
|
+
const tagSearchPattern = name ? originalPrefix ? `${originalPrefix}${name}@` : `${name}@` : originalPrefix ? `${originalPrefix}v` : "v";
|
|
299
333
|
let determinedReleaseType = type || null;
|
|
300
334
|
if (determinedReleaseType) {
|
|
301
335
|
if (!latestTag) {
|
|
@@ -336,21 +370,21 @@ var VersionEngine = class {
|
|
|
336
370
|
if (commitsLength === 0) {
|
|
337
371
|
log(
|
|
338
372
|
"info",
|
|
339
|
-
`No new commits found for ${
|
|
373
|
+
`No new commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
340
374
|
);
|
|
341
375
|
return "";
|
|
342
376
|
}
|
|
343
377
|
if (!releaseTypeFromCommits) {
|
|
344
378
|
log(
|
|
345
379
|
"info",
|
|
346
|
-
`No relevant commits found for ${
|
|
380
|
+
`No relevant commits found for ${name || "project"} since ${latestTag}, skipping version bump`
|
|
347
381
|
);
|
|
348
382
|
return "";
|
|
349
383
|
}
|
|
350
384
|
const currentVersion = semver.clean(latestTag.replace(tagSearchPattern, "")) || "0.0.0";
|
|
351
385
|
return semver.inc(currentVersion, releaseTypeFromCommits, prereleaseIdentifier) || "";
|
|
352
386
|
} catch (error) {
|
|
353
|
-
log("error", `Failed to calculate version for ${
|
|
387
|
+
log("error", `Failed to calculate version for ${name || "project"}`);
|
|
354
388
|
console.error(error);
|
|
355
389
|
if (error instanceof Error && error.message.includes("No names found")) {
|
|
356
390
|
log("info", "No tags found, proceeding with initial version calculation (if applicable).");
|
|
@@ -359,30 +393,44 @@ var VersionEngine = class {
|
|
|
359
393
|
return "";
|
|
360
394
|
}
|
|
361
395
|
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
396
|
+
/**
|
|
397
|
+
* Process packages based on discovery, skip list, and optional target list.
|
|
398
|
+
* Returns a list of package.json file paths that were updated (or would be in dry run).
|
|
399
|
+
*/
|
|
400
|
+
async processPackages(discoveredPackages = [], targets = []) {
|
|
401
|
+
const { tagPrefix, skip } = this.config;
|
|
365
402
|
const files = [];
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
|
|
403
|
+
const pkgsToConsider = discoveredPackages.filter((pkg) => {
|
|
404
|
+
if (skip == null ? void 0 : skip.includes(pkg.packageJson.name)) {
|
|
405
|
+
log("info", `Skipping package ${pkg.packageJson.name} based on config skip list.`);
|
|
369
406
|
return false;
|
|
370
407
|
}
|
|
371
|
-
|
|
408
|
+
if (targets.length > 0) {
|
|
409
|
+
const isTargeted = targets.includes(pkg.packageJson.name);
|
|
410
|
+
if (!isTargeted) {
|
|
411
|
+
}
|
|
412
|
+
return isTargeted;
|
|
413
|
+
}
|
|
414
|
+
return true;
|
|
372
415
|
});
|
|
373
|
-
|
|
374
|
-
|
|
416
|
+
log("info", `Found ${pkgsToConsider.length} package(s) to process after filtering.`);
|
|
417
|
+
for (const pkg of pkgsToConsider) {
|
|
418
|
+
const name = pkg.packageJson.name;
|
|
375
419
|
const pkgPath = pkg.dir;
|
|
376
420
|
const prefix = formatTagPrefix(tagPrefix);
|
|
377
421
|
const latestTag = await getLatestTag();
|
|
378
422
|
const nextVersion = await this.calculateVersion({
|
|
379
423
|
latestTag,
|
|
424
|
+
// This might need refinement for async based on package-specific tags
|
|
380
425
|
tagPrefix: prefix,
|
|
381
426
|
path: pkgPath,
|
|
382
|
-
name
|
|
427
|
+
name,
|
|
428
|
+
// Pass name for potential package-specific tag lookups
|
|
383
429
|
branchPattern: this.config.branchPattern,
|
|
384
430
|
baseBranch: this.config.baseBranch,
|
|
385
|
-
prereleaseIdentifier: this.config.prereleaseIdentifier
|
|
431
|
+
prereleaseIdentifier: this.config.prereleaseIdentifier,
|
|
432
|
+
type: this.config.forceType
|
|
433
|
+
// Pass forced type if provided
|
|
386
434
|
});
|
|
387
435
|
if (!nextVersion) {
|
|
388
436
|
continue;
|
|
@@ -390,13 +438,16 @@ var VersionEngine = class {
|
|
|
390
438
|
updatePackageVersion({
|
|
391
439
|
path: pkgPath,
|
|
392
440
|
version: nextVersion,
|
|
393
|
-
name
|
|
441
|
+
name,
|
|
394
442
|
dryRun: this.config.dryRun
|
|
395
443
|
});
|
|
396
444
|
files.push(path.join(pkgPath, "package.json"));
|
|
397
445
|
}
|
|
398
446
|
return files;
|
|
399
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Create git commit and tag
|
|
450
|
+
*/
|
|
400
451
|
async createGitCommitAndTag(files, nextTag, commitMessage, dryRun) {
|
|
401
452
|
try {
|
|
402
453
|
await gitProcess({
|
|
@@ -415,6 +466,9 @@ var VersionEngine = class {
|
|
|
415
466
|
exit(1);
|
|
416
467
|
}
|
|
417
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* Synced versioning strategy (all packages get the same version)
|
|
471
|
+
*/
|
|
418
472
|
async syncedStrategy() {
|
|
419
473
|
var _a;
|
|
420
474
|
const {
|
|
@@ -483,6 +537,9 @@ var VersionEngine = class {
|
|
|
483
537
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
484
538
|
await this.createGitCommitAndTag(files, nextTag, formattedCommitMessage, this.config.dryRun);
|
|
485
539
|
}
|
|
540
|
+
/**
|
|
541
|
+
* Single package versioning strategy
|
|
542
|
+
*/
|
|
486
543
|
async singleStrategy() {
|
|
487
544
|
const {
|
|
488
545
|
packages: configPackages,
|
|
@@ -542,11 +599,15 @@ var VersionEngine = class {
|
|
|
542
599
|
this.config.dryRun
|
|
543
600
|
);
|
|
544
601
|
}
|
|
545
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Async versioning strategy (each package gets its own version)
|
|
604
|
+
*/
|
|
605
|
+
async asyncStrategy(cliTargets = []) {
|
|
546
606
|
const {
|
|
547
|
-
packages: configPackages,
|
|
548
607
|
commitMessage = "chore(release): ${version}",
|
|
608
|
+
// Align with test expectations
|
|
549
609
|
skipHooks
|
|
610
|
+
// Add skipHooks here
|
|
550
611
|
} = this.config;
|
|
551
612
|
let pkgsResult;
|
|
552
613
|
try {
|
|
@@ -560,9 +621,9 @@ var VersionEngine = class {
|
|
|
560
621
|
exit(1);
|
|
561
622
|
return;
|
|
562
623
|
}
|
|
563
|
-
const pkgsToProcess = await this.processPackages(pkgsResult.packages,
|
|
624
|
+
const pkgsToProcess = await this.processPackages(pkgsResult.packages, cliTargets);
|
|
564
625
|
if (pkgsToProcess.length === 0) {
|
|
565
|
-
log("info", "No packages to process");
|
|
626
|
+
log("info", "No packages to process based on changes and targets");
|
|
566
627
|
return;
|
|
567
628
|
}
|
|
568
629
|
const formattedCommitMessage = commitMessage;
|
|
@@ -575,7 +636,7 @@ var VersionEngine = class {
|
|
|
575
636
|
dryRun: this.config.dryRun
|
|
576
637
|
});
|
|
577
638
|
if (!this.config.dryRun) {
|
|
578
|
-
log("success",
|
|
639
|
+
log("success", `Created version commit for ${pkgsToProcess.length} package(s)`);
|
|
579
640
|
}
|
|
580
641
|
} catch (error) {
|
|
581
642
|
log("error", "Failed to create version commit");
|
|
@@ -586,63 +647,49 @@ var VersionEngine = class {
|
|
|
586
647
|
};
|
|
587
648
|
|
|
588
649
|
// src/index.ts
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
program
|
|
592
|
-
program.
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
"
|
|
596
|
-
"
|
|
597
|
-
|
|
598
|
-
"
|
|
599
|
-
"
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
if (!validBumps.includes(value)) {
|
|
603
|
-
log("error", `Invalid bump type '${value}'. Valid options are: ${validBumps.join(", ")}`);
|
|
604
|
-
process.exit(1);
|
|
605
|
-
}
|
|
606
|
-
return value;
|
|
607
|
-
}).option("--base-branch <branch>", "override the base branch for this operation").option("--synced", "force synced versioning mode").option("--no-synced", "force async versioning mode").option(
|
|
608
|
-
"--skip <packages>",
|
|
609
|
-
"comma-separated list of packages to skip",
|
|
610
|
-
(value) => value.split(",")
|
|
611
|
-
).option("--prerelease <identifier>", "set prerelease identifier (e.g., alpha, beta)").option("--skip-hooks", "skip Git hooks for this operation").option("--config <path>", "specify a custom config file path").option("--dry-run", "Calculate version and log actions without changing files or Git state");
|
|
612
|
-
program.description("Version packages based on Git context and conventional commits").action(async (options) => {
|
|
613
|
-
const figletText = figlet.textSync(name);
|
|
614
|
-
const versionText = `v${package_default.version}`;
|
|
615
|
-
process.stdout.write(`${chalk2.hex("#FF1F57")(figletText)}
|
|
616
|
-
`);
|
|
617
|
-
process.stdout.write(`${chalk2.hex("#0096FF")(versionText)}
|
|
618
|
-
|
|
619
|
-
`);
|
|
650
|
+
async function run() {
|
|
651
|
+
printFiglet();
|
|
652
|
+
const program = new Command();
|
|
653
|
+
program.name("package-versioner").description(
|
|
654
|
+
"Automated semantic versioning based on Git history and conventional commits. Supports monorepos with synchronized or independent package versioning strategies."
|
|
655
|
+
).version("0.0.2").option("--config <path>", "Path to the configuration file").option("--dry-run", "Simulate the versioning process without making changes").option("--synced", "Force synced versioning strategy (overrides config)").option("--bump <type>", "Force a specific release type (patch, minor, major)").option(
|
|
656
|
+
"--prerelease <identifier>",
|
|
657
|
+
"Create a prerelease version with the specified identifier"
|
|
658
|
+
).option(
|
|
659
|
+
"-t, --target <targets>",
|
|
660
|
+
"Comma-separated list of package names to target (only for async strategy)"
|
|
661
|
+
).parse(process.argv);
|
|
662
|
+
const options = program.opts();
|
|
620
663
|
try {
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
if (options.
|
|
624
|
-
|
|
625
|
-
if (options.
|
|
626
|
-
config.synced = options.synced;
|
|
627
|
-
if (options.skip)
|
|
628
|
-
config.skip = options.skip;
|
|
664
|
+
const config = await loadConfig(options.config);
|
|
665
|
+
log("info", `Loaded configuration from ${options.config || "version.config.json"}`);
|
|
666
|
+
if (options.dryRun) config.dryRun = true;
|
|
667
|
+
if (options.synced) config.synced = true;
|
|
668
|
+
if (options.bump) config.forceType = options.bump;
|
|
629
669
|
if (options.prerelease)
|
|
630
|
-
config.prereleaseIdentifier = options.prerelease;
|
|
631
|
-
|
|
632
|
-
config.skipHooks = options.skipHooks;
|
|
633
|
-
if (options.dryRun !== void 0)
|
|
634
|
-
config.dryRun = options.dryRun;
|
|
670
|
+
config.prereleaseIdentifier = options.prerelease === true ? "rc" : options.prerelease;
|
|
671
|
+
const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
|
|
635
672
|
const engine = new VersionEngine(config);
|
|
636
673
|
if (config.synced) {
|
|
674
|
+
log("info", "Using synced versioning strategy.");
|
|
637
675
|
await engine.syncedStrategy();
|
|
638
|
-
} else if (
|
|
676
|
+
} else if (config.packages && config.packages.length === 1) {
|
|
677
|
+
log("info", "Using single package versioning strategy.");
|
|
678
|
+
if (cliTargets.length > 0) {
|
|
679
|
+
log("warning", "--target flag is ignored for single package strategy.");
|
|
680
|
+
}
|
|
639
681
|
await engine.singleStrategy();
|
|
640
682
|
} else {
|
|
641
|
-
|
|
683
|
+
log("info", "Using async versioning strategy.");
|
|
684
|
+
if (cliTargets.length > 0) {
|
|
685
|
+
log("info", `Targeting specific packages: ${cliTargets.join(", ")}`);
|
|
686
|
+
}
|
|
687
|
+
await engine.asyncStrategy(cliTargets);
|
|
642
688
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
689
|
+
log("success", "Versioning process completed.");
|
|
690
|
+
} catch (error) {
|
|
691
|
+
log("error", error instanceof Error ? error.message : String(error));
|
|
692
|
+
process.exit(1);
|
|
646
693
|
}
|
|
647
|
-
}
|
|
648
|
-
|
|
694
|
+
}
|
|
695
|
+
run();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "package-versioner",
|
|
3
3
|
"description": "A powerful CLI tool for automated semantic versioning based on Git history and conventional commits. Supports monorepos with synchronized or independent package versioning strategies.",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -38,12 +38,12 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@biomejs/biome": "^1.9.4",
|
|
40
40
|
"@types/figlet": "^1.5.5",
|
|
41
|
-
"@types/node": "^
|
|
41
|
+
"@types/node": "^22.14.0",
|
|
42
42
|
"@types/semver": "^7.3.13",
|
|
43
43
|
"@vitest/coverage-v8": "^3.1.1",
|
|
44
44
|
"husky": "^9.1.7",
|
|
45
45
|
"lint-staged": "^15.5.0",
|
|
46
|
-
"tsup": "^
|
|
46
|
+
"tsup": "^8.4.0",
|
|
47
47
|
"typescript": "^5.8.3",
|
|
48
48
|
"vitest": "^3.1.1"
|
|
49
49
|
},
|