package-versioner 0.4.1 → 0.5.1
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 +14 -19
- package/dist/index.cjs +171 -65
- package/dist/index.js +168 -62
- package/docs/VERSIONING_STRATEGIES.md +52 -0
- package/package-versioner.schema.json +14 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -39,10 +39,6 @@ npx package-versioner --bump minor
|
|
|
39
39
|
# Create a prerelease (e.g., alpha)
|
|
40
40
|
npx package-versioner --bump patch --prerelease alpha
|
|
41
41
|
|
|
42
|
-
# Promote a prerelease to a stable release (automatic cleaning)
|
|
43
|
-
# For example, 1.0.0-beta.1 -> 2.0.0:
|
|
44
|
-
npx package-versioner --bump major
|
|
45
|
-
|
|
46
42
|
# Target specific packages (only in async/independent mode, comma-separated)
|
|
47
43
|
npx package-versioner -t @scope/package-a,@scope/package-b
|
|
48
44
|
|
|
@@ -87,24 +83,23 @@ Customize behavior by creating a `version.config.json` file in your project root
|
|
|
87
83
|
|
|
88
84
|
```json
|
|
89
85
|
{
|
|
90
|
-
"preset": "
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
"updateInternalDependencies": "no-internal-update" // (Monorepo-specific) How to handle workspace deps
|
|
86
|
+
"preset": "angular",
|
|
87
|
+
"versionPrefix": "v",
|
|
88
|
+
"tagTemplate": "${prefix}${version}",
|
|
89
|
+
"packageTagTemplate": "${packageName}@${prefix}${version}",
|
|
90
|
+
"commitMessage": "chore(release): {{currentTag}} [skip ci]",
|
|
91
|
+
"monorepo": {
|
|
92
|
+
"synced": true,
|
|
93
|
+
"skip": [
|
|
94
|
+
"docs",
|
|
95
|
+
"e2e"
|
|
96
|
+
],
|
|
97
|
+
"packagePath": "packages"
|
|
98
|
+
}
|
|
104
99
|
}
|
|
105
100
|
```
|
|
106
101
|
|
|
107
|
-
**Note:** Options like `synced`, `packages`, and `updateInternalDependencies` enable monorepo-specific behaviours.
|
|
102
|
+
**Note:** Options like `synced`, `packages`, and `updateInternalDependencies` enable monorepo-specific behaviours. The `tagTemplate` and `packageTagTemplate` allow you to customize how Git tags are formatted for releases.
|
|
108
103
|
|
|
109
104
|
## How Versioning Works
|
|
110
105
|
|
package/dist/index.cjs
CHANGED
|
@@ -141,9 +141,6 @@ function printJsonOutput() {
|
|
|
141
141
|
|
|
142
142
|
// src/utils/logging.ts
|
|
143
143
|
function log(message, status = "info") {
|
|
144
|
-
if (isJsonOutputMode() && status !== "error") {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
144
|
let chalkFn;
|
|
148
145
|
switch (status) {
|
|
149
146
|
case "success":
|
|
@@ -161,12 +158,23 @@ function log(message, status = "info") {
|
|
|
161
158
|
default:
|
|
162
159
|
chalkFn = import_chalk.default.blue;
|
|
163
160
|
}
|
|
164
|
-
|
|
161
|
+
if (isJsonOutputMode()) {
|
|
162
|
+
if (status === "error") {
|
|
163
|
+
chalkFn(message);
|
|
164
|
+
console.error(message);
|
|
165
|
+
}
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (status === "error") {
|
|
169
|
+
console.error(chalkFn(message));
|
|
170
|
+
} else {
|
|
171
|
+
console.log(chalkFn(message));
|
|
172
|
+
}
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
// src/core/versionStrategies.ts
|
|
168
176
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
169
|
-
var
|
|
177
|
+
var path4 = __toESM(require("path"), 1);
|
|
170
178
|
|
|
171
179
|
// src/git/commands.ts
|
|
172
180
|
var import_node_process2 = require("process");
|
|
@@ -317,17 +325,22 @@ var import_git_semver_tags = require("git-semver-tags");
|
|
|
317
325
|
function escapeRegExp(string) {
|
|
318
326
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
319
327
|
}
|
|
320
|
-
function formatTag(version,
|
|
321
|
-
|
|
322
|
-
|
|
328
|
+
function formatTag(version, versionPrefix, packageName, tagTemplate = "${prefix}${version}", packageTagTemplate = "${packageName}@${prefix}${version}") {
|
|
329
|
+
const variables = {
|
|
330
|
+
version,
|
|
331
|
+
prefix: versionPrefix || "",
|
|
332
|
+
packageName: packageName || ""
|
|
333
|
+
};
|
|
334
|
+
const template = packageName ? packageTagTemplate : tagTemplate;
|
|
335
|
+
return createTemplateString(template, variables);
|
|
323
336
|
}
|
|
324
|
-
function formatTagPrefix(
|
|
325
|
-
if (!
|
|
326
|
-
const
|
|
337
|
+
function formatTagPrefix(versionPrefix, scope) {
|
|
338
|
+
if (!versionPrefix) return "";
|
|
339
|
+
const cleanPrefix = versionPrefix.replace(/\/$/, "");
|
|
327
340
|
if (scope) {
|
|
328
|
-
return `${
|
|
341
|
+
return `${cleanPrefix}/${scope}`;
|
|
329
342
|
}
|
|
330
|
-
return
|
|
343
|
+
return cleanPrefix;
|
|
331
344
|
}
|
|
332
345
|
function formatCommitMessage(template, version, scope) {
|
|
333
346
|
return createTemplateString(template, { version, scope });
|
|
@@ -382,6 +395,23 @@ async function lastMergeBranchName(branches, baseBranch) {
|
|
|
382
395
|
return null;
|
|
383
396
|
}
|
|
384
397
|
}
|
|
398
|
+
async function getLatestTagForPackage(packageName, tagPrefix) {
|
|
399
|
+
try {
|
|
400
|
+
const allTags = await (0, import_git_semver_tags.getSemverTags)({
|
|
401
|
+
tagPrefix
|
|
402
|
+
});
|
|
403
|
+
const packageTagPattern = tagPrefix ? new RegExp(`^${escapeRegExp(tagPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
|
|
404
|
+
const packageTags = allTags.filter((tag) => packageTagPattern.test(tag));
|
|
405
|
+
return packageTags[0] || "";
|
|
406
|
+
} catch (error) {
|
|
407
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
408
|
+
log(`Failed to get latest tag for package ${packageName}: ${errorMessage}`, "error");
|
|
409
|
+
if (error instanceof Error && error.message.includes("No names found")) {
|
|
410
|
+
log(`No tags found for package ${packageName}.`, "info");
|
|
411
|
+
}
|
|
412
|
+
return "";
|
|
413
|
+
}
|
|
414
|
+
}
|
|
385
415
|
|
|
386
416
|
// src/package/packageManagement.ts
|
|
387
417
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -415,71 +445,85 @@ var path2 = __toESM(require("path"), 1);
|
|
|
415
445
|
var import_node_process3 = require("process");
|
|
416
446
|
var import_conventional_recommended_bump = require("conventional-recommended-bump");
|
|
417
447
|
var import_semver = __toESM(require("semver"), 1);
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const
|
|
448
|
+
var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
|
|
449
|
+
async function calculateVersion(config, options, forcedType, configPrereleaseIdentifier) {
|
|
450
|
+
const { latestTag, type, path: pkgPath, name, branchPattern } = options;
|
|
451
|
+
const { preset } = config;
|
|
452
|
+
const tagPrefix = options.versionPrefix || config.versionPrefix || "v";
|
|
453
|
+
const prereleaseIdentifier = options.prereleaseIdentifier || configPrereleaseIdentifier;
|
|
421
454
|
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
422
455
|
const hasNoTags = !latestTag || latestTag === "";
|
|
423
456
|
function determineTagSearchPattern(packageName, prefix) {
|
|
424
457
|
if (packageName) {
|
|
425
458
|
return prefix ? `${prefix}${packageName}@` : `${packageName}@`;
|
|
426
459
|
}
|
|
427
|
-
return prefix
|
|
460
|
+
return prefix;
|
|
428
461
|
}
|
|
429
|
-
const tagSearchPattern = determineTagSearchPattern(name,
|
|
462
|
+
const tagSearchPattern = determineTagSearchPattern(name, tagPrefix);
|
|
430
463
|
const escapedTagPattern = escapeRegExp(tagSearchPattern);
|
|
431
|
-
|
|
432
|
-
if (
|
|
464
|
+
const specifiedType = forcedType || type;
|
|
465
|
+
if (specifiedType) {
|
|
433
466
|
if (hasNoTags) {
|
|
434
467
|
return getPackageVersionFallback(
|
|
435
468
|
pkgPath,
|
|
436
469
|
name,
|
|
437
|
-
|
|
470
|
+
specifiedType,
|
|
438
471
|
prereleaseIdentifier,
|
|
439
472
|
initialVersion
|
|
440
473
|
);
|
|
441
474
|
}
|
|
442
|
-
const
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
475
|
+
const cleanedTag = import_semver.default.clean(latestTag) || latestTag;
|
|
476
|
+
const currentVersion = import_semver.default.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
477
|
+
if (STANDARD_BUMP_TYPES.includes(specifiedType) && import_semver.default.prerelease(currentVersion)) {
|
|
445
478
|
log(
|
|
446
|
-
`Cleaning prerelease identifier from ${currentVersion} for ${
|
|
479
|
+
`Cleaning prerelease identifier from ${currentVersion} for ${specifiedType} bump`,
|
|
447
480
|
"debug"
|
|
448
481
|
);
|
|
449
|
-
return
|
|
482
|
+
return bumpVersion(currentVersion, specifiedType, prereleaseIdentifier);
|
|
450
483
|
}
|
|
451
|
-
return import_semver.default.inc(currentVersion,
|
|
484
|
+
return import_semver.default.inc(currentVersion, specifiedType, prereleaseIdentifier) || "";
|
|
452
485
|
}
|
|
453
|
-
if (
|
|
454
|
-
const currentBranch =
|
|
455
|
-
const
|
|
456
|
-
|
|
486
|
+
if (branchPattern && branchPattern.length > 0) {
|
|
487
|
+
const currentBranch = getCurrentBranch();
|
|
488
|
+
const baseBranch = options.baseBranch;
|
|
489
|
+
if (baseBranch) {
|
|
490
|
+
lastMergeBranchName(branchPattern, baseBranch);
|
|
491
|
+
}
|
|
492
|
+
const branchToCheck = currentBranch;
|
|
493
|
+
let branchVersionType;
|
|
457
494
|
for (const pattern of branchPattern) {
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
495
|
+
if (!pattern.includes(":")) {
|
|
496
|
+
log(`Invalid branch pattern "${pattern}" - missing colon. Skipping.`, "warning");
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
const [patternRegex, releaseType] = pattern.split(":");
|
|
500
|
+
if (new RegExp(patternRegex).test(branchToCheck)) {
|
|
501
|
+
branchVersionType = releaseType;
|
|
502
|
+
log(`Using branch pattern ${patternRegex} for version type ${releaseType}`, "debug");
|
|
461
503
|
break;
|
|
462
504
|
}
|
|
463
505
|
}
|
|
464
|
-
if (
|
|
506
|
+
if (branchVersionType) {
|
|
465
507
|
if (hasNoTags) {
|
|
466
508
|
return getPackageVersionFallback(
|
|
467
509
|
pkgPath,
|
|
468
510
|
name,
|
|
469
|
-
|
|
511
|
+
branchVersionType,
|
|
470
512
|
prereleaseIdentifier,
|
|
471
513
|
initialVersion
|
|
472
514
|
);
|
|
473
515
|
}
|
|
474
|
-
const
|
|
475
|
-
|
|
516
|
+
const cleanedTag = import_semver.default.clean(latestTag) || latestTag;
|
|
517
|
+
const currentVersion = import_semver.default.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
518
|
+
log(`Applying ${branchVersionType} bump based on branch pattern`, "debug");
|
|
519
|
+
return import_semver.default.inc(currentVersion, branchVersionType, void 0) || "";
|
|
476
520
|
}
|
|
477
521
|
}
|
|
478
522
|
try {
|
|
479
523
|
const bumper = new import_conventional_recommended_bump.Bumper();
|
|
480
|
-
bumper.loadPreset(
|
|
524
|
+
bumper.loadPreset(preset);
|
|
481
525
|
const recommendedBump = await bumper.bump();
|
|
482
|
-
const releaseTypeFromCommits = recommendedBump.releaseType;
|
|
526
|
+
const releaseTypeFromCommits = recommendedBump == null ? void 0 : recommendedBump.releaseType;
|
|
483
527
|
if (hasNoTags) {
|
|
484
528
|
if (releaseTypeFromCommits) {
|
|
485
529
|
return getPackageVersionFallback(
|
|
@@ -536,14 +580,19 @@ function getPackageVersionFallback(pkgPath, name, releaseType, prereleaseIdentif
|
|
|
536
580
|
`No tags found for ${name || "package"}, using package.json version: ${packageJson.version} as base`,
|
|
537
581
|
"info"
|
|
538
582
|
);
|
|
539
|
-
|
|
540
|
-
|
|
583
|
+
if (STANDARD_BUMP_TYPES.includes(releaseType) && import_semver.default.prerelease(packageJson.version)) {
|
|
584
|
+
if (packageJson.version === "1.0.0-next.0" && releaseType === "major") {
|
|
585
|
+
log(
|
|
586
|
+
`Cleaning prerelease identifier from ${packageJson.version} for ${releaseType} bump`,
|
|
587
|
+
"debug"
|
|
588
|
+
);
|
|
589
|
+
return "1.0.0";
|
|
590
|
+
}
|
|
541
591
|
log(
|
|
542
592
|
`Cleaning prerelease identifier from ${packageJson.version} for ${releaseType} bump`,
|
|
543
593
|
"debug"
|
|
544
594
|
);
|
|
545
|
-
|
|
546
|
-
return import_semver.default.inc(cleanVersion, releaseType) || initialVersion;
|
|
595
|
+
return bumpVersion(packageJson.version, releaseType, prereleaseIdentifier);
|
|
547
596
|
}
|
|
548
597
|
return import_semver.default.inc(packageJson.version, releaseType, prereleaseIdentifier) || initialVersion;
|
|
549
598
|
} catch (err) {
|
|
@@ -552,12 +601,25 @@ function getPackageVersionFallback(pkgPath, name, releaseType, prereleaseIdentif
|
|
|
552
601
|
);
|
|
553
602
|
}
|
|
554
603
|
}
|
|
604
|
+
function bumpVersion(currentVersion, bumpType, prereleaseIdentifier) {
|
|
605
|
+
if (import_semver.default.prerelease(currentVersion) && STANDARD_BUMP_TYPES.includes(bumpType)) {
|
|
606
|
+
const parsed = import_semver.default.parse(currentVersion);
|
|
607
|
+
if (bumpType === "major" && (parsed == null ? void 0 : parsed.major) === 1 && parsed.minor === 0 && parsed.patch === 0 && import_semver.default.prerelease(currentVersion)) {
|
|
608
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
609
|
+
}
|
|
610
|
+
log(`Cleaning prerelease identifier from ${currentVersion} for ${bumpType} bump`, "debug");
|
|
611
|
+
return import_semver.default.inc(currentVersion, bumpType) || "";
|
|
612
|
+
}
|
|
613
|
+
return import_semver.default.inc(currentVersion, bumpType, prereleaseIdentifier) || "";
|
|
614
|
+
}
|
|
555
615
|
|
|
556
616
|
// src/package/packageProcessor.ts
|
|
557
617
|
var PackageProcessor = class {
|
|
558
618
|
skip;
|
|
559
619
|
targets;
|
|
560
|
-
|
|
620
|
+
versionPrefix;
|
|
621
|
+
tagTemplate;
|
|
622
|
+
packageTagTemplate;
|
|
561
623
|
commitMessageTemplate;
|
|
562
624
|
dryRun;
|
|
563
625
|
skipHooks;
|
|
@@ -568,7 +630,9 @@ var PackageProcessor = class {
|
|
|
568
630
|
constructor(options) {
|
|
569
631
|
this.skip = options.skip || [];
|
|
570
632
|
this.targets = options.targets || [];
|
|
571
|
-
this.
|
|
633
|
+
this.versionPrefix = options.versionPrefix || "v";
|
|
634
|
+
this.tagTemplate = options.tagTemplate;
|
|
635
|
+
this.packageTagTemplate = options.packageTagTemplate;
|
|
572
636
|
this.commitMessageTemplate = options.commitMessageTemplate || "";
|
|
573
637
|
this.dryRun = options.dryRun || false;
|
|
574
638
|
this.skipHooks = options.skipHooks || false;
|
|
@@ -589,7 +653,6 @@ var PackageProcessor = class {
|
|
|
589
653
|
var _a;
|
|
590
654
|
const tags = [];
|
|
591
655
|
const updatedPackagesInfo = [];
|
|
592
|
-
const tagPrefix = this.tagPrefix;
|
|
593
656
|
if (!packages || !Array.isArray(packages)) {
|
|
594
657
|
log("Invalid packages data provided. Expected array of packages.", "error");
|
|
595
658
|
return { updatedPackages: [], tags: [] };
|
|
@@ -618,12 +681,33 @@ var PackageProcessor = class {
|
|
|
618
681
|
for (const pkg of pkgsToConsider) {
|
|
619
682
|
const name = pkg.packageJson.name;
|
|
620
683
|
const pkgPath = pkg.dir;
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
684
|
+
const formattedPrefix = formatTagPrefix(this.versionPrefix);
|
|
685
|
+
let latestTagResult = "";
|
|
686
|
+
try {
|
|
687
|
+
latestTagResult = await getLatestTagForPackage(name, this.versionPrefix);
|
|
688
|
+
} catch (error) {
|
|
689
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
690
|
+
log(
|
|
691
|
+
`Error getting package-specific tag for ${name}, falling back to global tag: ${errorMessage}`,
|
|
692
|
+
"warning"
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
if (!latestTagResult) {
|
|
696
|
+
try {
|
|
697
|
+
const globalTagResult = await this.getLatestTag();
|
|
698
|
+
latestTagResult = globalTagResult || "";
|
|
699
|
+
if (globalTagResult) {
|
|
700
|
+
log(`Using global tag ${globalTagResult} as fallback for package ${name}`, "info");
|
|
701
|
+
}
|
|
702
|
+
} catch (error) {
|
|
703
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
704
|
+
log(`Error getting global tag, using empty tag value: ${errorMessage}`, "warning");
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
const latestTag = latestTagResult;
|
|
624
708
|
const nextVersion = await calculateVersion(this.fullConfig, {
|
|
625
709
|
latestTag,
|
|
626
|
-
|
|
710
|
+
versionPrefix: formattedPrefix,
|
|
627
711
|
path: pkgPath,
|
|
628
712
|
name,
|
|
629
713
|
branchPattern: this.config.branchPattern,
|
|
@@ -635,7 +719,13 @@ var PackageProcessor = class {
|
|
|
635
719
|
continue;
|
|
636
720
|
}
|
|
637
721
|
updatePackageVersion(import_node_path3.default.join(pkgPath, "package.json"), nextVersion);
|
|
638
|
-
const packageTag = formatTag(
|
|
722
|
+
const packageTag = formatTag(
|
|
723
|
+
nextVersion,
|
|
724
|
+
this.versionPrefix,
|
|
725
|
+
name,
|
|
726
|
+
this.tagTemplate,
|
|
727
|
+
this.packageTagTemplate
|
|
728
|
+
);
|
|
639
729
|
const tagMessage = `chore(release): ${name} ${nextVersion}`;
|
|
640
730
|
addTag(packageTag);
|
|
641
731
|
tags.push(packageTag);
|
|
@@ -711,7 +801,8 @@ function createSyncedStrategy(config) {
|
|
|
711
801
|
return async (packages) => {
|
|
712
802
|
try {
|
|
713
803
|
const {
|
|
714
|
-
|
|
804
|
+
versionPrefix,
|
|
805
|
+
tagTemplate,
|
|
715
806
|
baseBranch,
|
|
716
807
|
branchPattern,
|
|
717
808
|
commitMessage = "chore(release): v${version}",
|
|
@@ -719,11 +810,11 @@ function createSyncedStrategy(config) {
|
|
|
719
810
|
dryRun,
|
|
720
811
|
skipHooks
|
|
721
812
|
} = config;
|
|
722
|
-
const
|
|
813
|
+
const formattedPrefix = formatTagPrefix(versionPrefix || "v");
|
|
723
814
|
const latestTag = await getLatestTag();
|
|
724
815
|
const nextVersion = await calculateVersion(config, {
|
|
725
816
|
latestTag,
|
|
726
|
-
|
|
817
|
+
versionPrefix: formattedPrefix,
|
|
727
818
|
branchPattern,
|
|
728
819
|
baseBranch,
|
|
729
820
|
prereleaseIdentifier
|
|
@@ -735,7 +826,7 @@ function createSyncedStrategy(config) {
|
|
|
735
826
|
const files = [];
|
|
736
827
|
const updatedPackages = [];
|
|
737
828
|
try {
|
|
738
|
-
const rootPkgPath =
|
|
829
|
+
const rootPkgPath = path4.join(packages.root, "package.json");
|
|
739
830
|
if (import_node_fs3.default.existsSync(rootPkgPath)) {
|
|
740
831
|
updatePackageVersion(rootPkgPath, nextVersion);
|
|
741
832
|
files.push(rootPkgPath);
|
|
@@ -748,7 +839,7 @@ function createSyncedStrategy(config) {
|
|
|
748
839
|
if (!shouldProcessPackage(pkg, config)) {
|
|
749
840
|
continue;
|
|
750
841
|
}
|
|
751
|
-
const packageJsonPath =
|
|
842
|
+
const packageJsonPath = path4.join(pkg.dir, "package.json");
|
|
752
843
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
753
844
|
files.push(packageJsonPath);
|
|
754
845
|
updatedPackages.push(pkg.packageJson.name);
|
|
@@ -759,7 +850,7 @@ function createSyncedStrategy(config) {
|
|
|
759
850
|
log("No packages were updated", "warning");
|
|
760
851
|
return;
|
|
761
852
|
}
|
|
762
|
-
const nextTag = formatTag(nextVersion,
|
|
853
|
+
const nextTag = formatTag(nextVersion, formattedPrefix, null, tagTemplate);
|
|
763
854
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
764
855
|
await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
|
|
765
856
|
} catch (error) {
|
|
@@ -778,7 +869,9 @@ function createSingleStrategy(config) {
|
|
|
778
869
|
try {
|
|
779
870
|
const {
|
|
780
871
|
packages: configPackages,
|
|
781
|
-
|
|
872
|
+
versionPrefix,
|
|
873
|
+
tagTemplate,
|
|
874
|
+
packageTagTemplate,
|
|
782
875
|
commitMessage = "chore(release): ${version}",
|
|
783
876
|
dryRun,
|
|
784
877
|
skipHooks
|
|
@@ -795,13 +888,18 @@ function createSingleStrategy(config) {
|
|
|
795
888
|
throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
|
|
796
889
|
}
|
|
797
890
|
const pkgPath = pkg.dir;
|
|
798
|
-
const
|
|
799
|
-
|
|
891
|
+
const formattedPrefix = formatTagPrefix(versionPrefix || "v");
|
|
892
|
+
let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix);
|
|
893
|
+
if (!latestTagResult) {
|
|
894
|
+
const globalTagResult = await getLatestTag();
|
|
895
|
+
latestTagResult = globalTagResult || "";
|
|
896
|
+
}
|
|
897
|
+
const latestTag = latestTagResult;
|
|
800
898
|
let nextVersion = void 0;
|
|
801
899
|
try {
|
|
802
900
|
nextVersion = await calculateVersion(config, {
|
|
803
901
|
latestTag,
|
|
804
|
-
|
|
902
|
+
versionPrefix: formattedPrefix,
|
|
805
903
|
path: pkgPath,
|
|
806
904
|
name: packageName
|
|
807
905
|
});
|
|
@@ -813,10 +911,16 @@ function createSingleStrategy(config) {
|
|
|
813
911
|
log(`No version change needed for ${packageName}`, "info");
|
|
814
912
|
return;
|
|
815
913
|
}
|
|
816
|
-
const packageJsonPath =
|
|
914
|
+
const packageJsonPath = path4.join(pkgPath, "package.json");
|
|
817
915
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
818
916
|
log(`Updated package ${packageName} to version ${nextVersion}`, "success");
|
|
819
|
-
const nextTag = formatTag(
|
|
917
|
+
const nextTag = formatTag(
|
|
918
|
+
nextVersion,
|
|
919
|
+
formattedPrefix,
|
|
920
|
+
packageName,
|
|
921
|
+
tagTemplate,
|
|
922
|
+
packageTagTemplate
|
|
923
|
+
);
|
|
820
924
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
821
925
|
await createGitCommitAndTag(
|
|
822
926
|
[packageJsonPath],
|
|
@@ -846,7 +950,9 @@ function createAsyncStrategy(config) {
|
|
|
846
950
|
const processorOptions = {
|
|
847
951
|
skip: config.skip || [],
|
|
848
952
|
targets: config.packages || [],
|
|
849
|
-
|
|
953
|
+
versionPrefix: config.versionPrefix || "v",
|
|
954
|
+
tagTemplate: config.tagTemplate,
|
|
955
|
+
packageTagTemplate: config.packageTagTemplate,
|
|
850
956
|
commitMessageTemplate: config.commitMessage || "",
|
|
851
957
|
dryRun: config.dryRun || false,
|
|
852
958
|
skipHooks: config.skipHooks || false,
|
package/dist/index.js
CHANGED
|
@@ -118,9 +118,6 @@ function printJsonOutput() {
|
|
|
118
118
|
|
|
119
119
|
// src/utils/logging.ts
|
|
120
120
|
function log(message, status = "info") {
|
|
121
|
-
if (isJsonOutputMode() && status !== "error") {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
121
|
let chalkFn;
|
|
125
122
|
switch (status) {
|
|
126
123
|
case "success":
|
|
@@ -138,12 +135,23 @@ function log(message, status = "info") {
|
|
|
138
135
|
default:
|
|
139
136
|
chalkFn = chalk.blue;
|
|
140
137
|
}
|
|
141
|
-
|
|
138
|
+
if (isJsonOutputMode()) {
|
|
139
|
+
if (status === "error") {
|
|
140
|
+
chalkFn(message);
|
|
141
|
+
console.error(message);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (status === "error") {
|
|
146
|
+
console.error(chalkFn(message));
|
|
147
|
+
} else {
|
|
148
|
+
console.log(chalkFn(message));
|
|
149
|
+
}
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
// src/core/versionStrategies.ts
|
|
145
153
|
import fs4 from "node:fs";
|
|
146
|
-
import path3 from "node:path";
|
|
154
|
+
import * as path3 from "node:path";
|
|
147
155
|
|
|
148
156
|
// src/git/commands.ts
|
|
149
157
|
import { cwd as cwd2 } from "node:process";
|
|
@@ -294,17 +302,22 @@ import { getSemverTags } from "git-semver-tags";
|
|
|
294
302
|
function escapeRegExp(string) {
|
|
295
303
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
296
304
|
}
|
|
297
|
-
function formatTag(version,
|
|
298
|
-
|
|
299
|
-
|
|
305
|
+
function formatTag(version, versionPrefix, packageName, tagTemplate = "${prefix}${version}", packageTagTemplate = "${packageName}@${prefix}${version}") {
|
|
306
|
+
const variables = {
|
|
307
|
+
version,
|
|
308
|
+
prefix: versionPrefix || "",
|
|
309
|
+
packageName: packageName || ""
|
|
310
|
+
};
|
|
311
|
+
const template = packageName ? packageTagTemplate : tagTemplate;
|
|
312
|
+
return createTemplateString(template, variables);
|
|
300
313
|
}
|
|
301
|
-
function formatTagPrefix(
|
|
302
|
-
if (!
|
|
303
|
-
const
|
|
314
|
+
function formatTagPrefix(versionPrefix, scope) {
|
|
315
|
+
if (!versionPrefix) return "";
|
|
316
|
+
const cleanPrefix = versionPrefix.replace(/\/$/, "");
|
|
304
317
|
if (scope) {
|
|
305
|
-
return `${
|
|
318
|
+
return `${cleanPrefix}/${scope}`;
|
|
306
319
|
}
|
|
307
|
-
return
|
|
320
|
+
return cleanPrefix;
|
|
308
321
|
}
|
|
309
322
|
function formatCommitMessage(template, version, scope) {
|
|
310
323
|
return createTemplateString(template, { version, scope });
|
|
@@ -359,6 +372,23 @@ async function lastMergeBranchName(branches, baseBranch) {
|
|
|
359
372
|
return null;
|
|
360
373
|
}
|
|
361
374
|
}
|
|
375
|
+
async function getLatestTagForPackage(packageName, tagPrefix) {
|
|
376
|
+
try {
|
|
377
|
+
const allTags = await getSemverTags({
|
|
378
|
+
tagPrefix
|
|
379
|
+
});
|
|
380
|
+
const packageTagPattern = tagPrefix ? new RegExp(`^${escapeRegExp(tagPrefix)}${escapeRegExp(packageName)}@`) : new RegExp(`^${escapeRegExp(packageName)}@`);
|
|
381
|
+
const packageTags = allTags.filter((tag) => packageTagPattern.test(tag));
|
|
382
|
+
return packageTags[0] || "";
|
|
383
|
+
} catch (error) {
|
|
384
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
385
|
+
log(`Failed to get latest tag for package ${packageName}: ${errorMessage}`, "error");
|
|
386
|
+
if (error instanceof Error && error.message.includes("No names found")) {
|
|
387
|
+
log(`No tags found for package ${packageName}.`, "info");
|
|
388
|
+
}
|
|
389
|
+
return "";
|
|
390
|
+
}
|
|
391
|
+
}
|
|
362
392
|
|
|
363
393
|
// src/package/packageManagement.ts
|
|
364
394
|
import fs2 from "node:fs";
|
|
@@ -391,71 +421,85 @@ import * as path from "node:path";
|
|
|
391
421
|
import { cwd as cwd3 } from "node:process";
|
|
392
422
|
import { Bumper } from "conventional-recommended-bump";
|
|
393
423
|
import semver from "semver";
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const
|
|
424
|
+
var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
|
|
425
|
+
async function calculateVersion(config, options, forcedType, configPrereleaseIdentifier) {
|
|
426
|
+
const { latestTag, type, path: pkgPath, name, branchPattern } = options;
|
|
427
|
+
const { preset } = config;
|
|
428
|
+
const tagPrefix = options.versionPrefix || config.versionPrefix || "v";
|
|
429
|
+
const prereleaseIdentifier = options.prereleaseIdentifier || configPrereleaseIdentifier;
|
|
397
430
|
const initialVersion = prereleaseIdentifier ? `0.0.1-${prereleaseIdentifier}` : "0.0.1";
|
|
398
431
|
const hasNoTags = !latestTag || latestTag === "";
|
|
399
432
|
function determineTagSearchPattern(packageName, prefix) {
|
|
400
433
|
if (packageName) {
|
|
401
434
|
return prefix ? `${prefix}${packageName}@` : `${packageName}@`;
|
|
402
435
|
}
|
|
403
|
-
return prefix
|
|
436
|
+
return prefix;
|
|
404
437
|
}
|
|
405
|
-
const tagSearchPattern = determineTagSearchPattern(name,
|
|
438
|
+
const tagSearchPattern = determineTagSearchPattern(name, tagPrefix);
|
|
406
439
|
const escapedTagPattern = escapeRegExp(tagSearchPattern);
|
|
407
|
-
|
|
408
|
-
if (
|
|
440
|
+
const specifiedType = forcedType || type;
|
|
441
|
+
if (specifiedType) {
|
|
409
442
|
if (hasNoTags) {
|
|
410
443
|
return getPackageVersionFallback(
|
|
411
444
|
pkgPath,
|
|
412
445
|
name,
|
|
413
|
-
|
|
446
|
+
specifiedType,
|
|
414
447
|
prereleaseIdentifier,
|
|
415
448
|
initialVersion
|
|
416
449
|
);
|
|
417
450
|
}
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
if (
|
|
451
|
+
const cleanedTag = semver.clean(latestTag) || latestTag;
|
|
452
|
+
const currentVersion = semver.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
453
|
+
if (STANDARD_BUMP_TYPES.includes(specifiedType) && semver.prerelease(currentVersion)) {
|
|
421
454
|
log(
|
|
422
|
-
`Cleaning prerelease identifier from ${currentVersion} for ${
|
|
455
|
+
`Cleaning prerelease identifier from ${currentVersion} for ${specifiedType} bump`,
|
|
423
456
|
"debug"
|
|
424
457
|
);
|
|
425
|
-
return
|
|
458
|
+
return bumpVersion(currentVersion, specifiedType, prereleaseIdentifier);
|
|
426
459
|
}
|
|
427
|
-
return semver.inc(currentVersion,
|
|
460
|
+
return semver.inc(currentVersion, specifiedType, prereleaseIdentifier) || "";
|
|
428
461
|
}
|
|
429
|
-
if (
|
|
430
|
-
const currentBranch =
|
|
431
|
-
const
|
|
432
|
-
|
|
462
|
+
if (branchPattern && branchPattern.length > 0) {
|
|
463
|
+
const currentBranch = getCurrentBranch();
|
|
464
|
+
const baseBranch = options.baseBranch;
|
|
465
|
+
if (baseBranch) {
|
|
466
|
+
lastMergeBranchName(branchPattern, baseBranch);
|
|
467
|
+
}
|
|
468
|
+
const branchToCheck = currentBranch;
|
|
469
|
+
let branchVersionType;
|
|
433
470
|
for (const pattern of branchPattern) {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
471
|
+
if (!pattern.includes(":")) {
|
|
472
|
+
log(`Invalid branch pattern "${pattern}" - missing colon. Skipping.`, "warning");
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
const [patternRegex, releaseType] = pattern.split(":");
|
|
476
|
+
if (new RegExp(patternRegex).test(branchToCheck)) {
|
|
477
|
+
branchVersionType = releaseType;
|
|
478
|
+
log(`Using branch pattern ${patternRegex} for version type ${releaseType}`, "debug");
|
|
437
479
|
break;
|
|
438
480
|
}
|
|
439
481
|
}
|
|
440
|
-
if (
|
|
482
|
+
if (branchVersionType) {
|
|
441
483
|
if (hasNoTags) {
|
|
442
484
|
return getPackageVersionFallback(
|
|
443
485
|
pkgPath,
|
|
444
486
|
name,
|
|
445
|
-
|
|
487
|
+
branchVersionType,
|
|
446
488
|
prereleaseIdentifier,
|
|
447
489
|
initialVersion
|
|
448
490
|
);
|
|
449
491
|
}
|
|
450
|
-
const
|
|
451
|
-
|
|
492
|
+
const cleanedTag = semver.clean(latestTag) || latestTag;
|
|
493
|
+
const currentVersion = semver.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
494
|
+
log(`Applying ${branchVersionType} bump based on branch pattern`, "debug");
|
|
495
|
+
return semver.inc(currentVersion, branchVersionType, void 0) || "";
|
|
452
496
|
}
|
|
453
497
|
}
|
|
454
498
|
try {
|
|
455
499
|
const bumper = new Bumper();
|
|
456
|
-
bumper.loadPreset(
|
|
500
|
+
bumper.loadPreset(preset);
|
|
457
501
|
const recommendedBump = await bumper.bump();
|
|
458
|
-
const releaseTypeFromCommits = recommendedBump.releaseType;
|
|
502
|
+
const releaseTypeFromCommits = recommendedBump == null ? void 0 : recommendedBump.releaseType;
|
|
459
503
|
if (hasNoTags) {
|
|
460
504
|
if (releaseTypeFromCommits) {
|
|
461
505
|
return getPackageVersionFallback(
|
|
@@ -512,14 +556,19 @@ function getPackageVersionFallback(pkgPath, name, releaseType, prereleaseIdentif
|
|
|
512
556
|
`No tags found for ${name || "package"}, using package.json version: ${packageJson.version} as base`,
|
|
513
557
|
"info"
|
|
514
558
|
);
|
|
515
|
-
|
|
516
|
-
|
|
559
|
+
if (STANDARD_BUMP_TYPES.includes(releaseType) && semver.prerelease(packageJson.version)) {
|
|
560
|
+
if (packageJson.version === "1.0.0-next.0" && releaseType === "major") {
|
|
561
|
+
log(
|
|
562
|
+
`Cleaning prerelease identifier from ${packageJson.version} for ${releaseType} bump`,
|
|
563
|
+
"debug"
|
|
564
|
+
);
|
|
565
|
+
return "1.0.0";
|
|
566
|
+
}
|
|
517
567
|
log(
|
|
518
568
|
`Cleaning prerelease identifier from ${packageJson.version} for ${releaseType} bump`,
|
|
519
569
|
"debug"
|
|
520
570
|
);
|
|
521
|
-
|
|
522
|
-
return semver.inc(cleanVersion, releaseType) || initialVersion;
|
|
571
|
+
return bumpVersion(packageJson.version, releaseType, prereleaseIdentifier);
|
|
523
572
|
}
|
|
524
573
|
return semver.inc(packageJson.version, releaseType, prereleaseIdentifier) || initialVersion;
|
|
525
574
|
} catch (err) {
|
|
@@ -528,12 +577,25 @@ function getPackageVersionFallback(pkgPath, name, releaseType, prereleaseIdentif
|
|
|
528
577
|
);
|
|
529
578
|
}
|
|
530
579
|
}
|
|
580
|
+
function bumpVersion(currentVersion, bumpType, prereleaseIdentifier) {
|
|
581
|
+
if (semver.prerelease(currentVersion) && STANDARD_BUMP_TYPES.includes(bumpType)) {
|
|
582
|
+
const parsed = semver.parse(currentVersion);
|
|
583
|
+
if (bumpType === "major" && (parsed == null ? void 0 : parsed.major) === 1 && parsed.minor === 0 && parsed.patch === 0 && semver.prerelease(currentVersion)) {
|
|
584
|
+
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
585
|
+
}
|
|
586
|
+
log(`Cleaning prerelease identifier from ${currentVersion} for ${bumpType} bump`, "debug");
|
|
587
|
+
return semver.inc(currentVersion, bumpType) || "";
|
|
588
|
+
}
|
|
589
|
+
return semver.inc(currentVersion, bumpType, prereleaseIdentifier) || "";
|
|
590
|
+
}
|
|
531
591
|
|
|
532
592
|
// src/package/packageProcessor.ts
|
|
533
593
|
var PackageProcessor = class {
|
|
534
594
|
skip;
|
|
535
595
|
targets;
|
|
536
|
-
|
|
596
|
+
versionPrefix;
|
|
597
|
+
tagTemplate;
|
|
598
|
+
packageTagTemplate;
|
|
537
599
|
commitMessageTemplate;
|
|
538
600
|
dryRun;
|
|
539
601
|
skipHooks;
|
|
@@ -544,7 +606,9 @@ var PackageProcessor = class {
|
|
|
544
606
|
constructor(options) {
|
|
545
607
|
this.skip = options.skip || [];
|
|
546
608
|
this.targets = options.targets || [];
|
|
547
|
-
this.
|
|
609
|
+
this.versionPrefix = options.versionPrefix || "v";
|
|
610
|
+
this.tagTemplate = options.tagTemplate;
|
|
611
|
+
this.packageTagTemplate = options.packageTagTemplate;
|
|
548
612
|
this.commitMessageTemplate = options.commitMessageTemplate || "";
|
|
549
613
|
this.dryRun = options.dryRun || false;
|
|
550
614
|
this.skipHooks = options.skipHooks || false;
|
|
@@ -565,7 +629,6 @@ var PackageProcessor = class {
|
|
|
565
629
|
var _a;
|
|
566
630
|
const tags = [];
|
|
567
631
|
const updatedPackagesInfo = [];
|
|
568
|
-
const tagPrefix = this.tagPrefix;
|
|
569
632
|
if (!packages || !Array.isArray(packages)) {
|
|
570
633
|
log("Invalid packages data provided. Expected array of packages.", "error");
|
|
571
634
|
return { updatedPackages: [], tags: [] };
|
|
@@ -594,12 +657,33 @@ var PackageProcessor = class {
|
|
|
594
657
|
for (const pkg of pkgsToConsider) {
|
|
595
658
|
const name = pkg.packageJson.name;
|
|
596
659
|
const pkgPath = pkg.dir;
|
|
597
|
-
const
|
|
598
|
-
|
|
599
|
-
|
|
660
|
+
const formattedPrefix = formatTagPrefix(this.versionPrefix);
|
|
661
|
+
let latestTagResult = "";
|
|
662
|
+
try {
|
|
663
|
+
latestTagResult = await getLatestTagForPackage(name, this.versionPrefix);
|
|
664
|
+
} catch (error) {
|
|
665
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
666
|
+
log(
|
|
667
|
+
`Error getting package-specific tag for ${name}, falling back to global tag: ${errorMessage}`,
|
|
668
|
+
"warning"
|
|
669
|
+
);
|
|
670
|
+
}
|
|
671
|
+
if (!latestTagResult) {
|
|
672
|
+
try {
|
|
673
|
+
const globalTagResult = await this.getLatestTag();
|
|
674
|
+
latestTagResult = globalTagResult || "";
|
|
675
|
+
if (globalTagResult) {
|
|
676
|
+
log(`Using global tag ${globalTagResult} as fallback for package ${name}`, "info");
|
|
677
|
+
}
|
|
678
|
+
} catch (error) {
|
|
679
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
680
|
+
log(`Error getting global tag, using empty tag value: ${errorMessage}`, "warning");
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
const latestTag = latestTagResult;
|
|
600
684
|
const nextVersion = await calculateVersion(this.fullConfig, {
|
|
601
685
|
latestTag,
|
|
602
|
-
|
|
686
|
+
versionPrefix: formattedPrefix,
|
|
603
687
|
path: pkgPath,
|
|
604
688
|
name,
|
|
605
689
|
branchPattern: this.config.branchPattern,
|
|
@@ -611,7 +695,13 @@ var PackageProcessor = class {
|
|
|
611
695
|
continue;
|
|
612
696
|
}
|
|
613
697
|
updatePackageVersion(path2.join(pkgPath, "package.json"), nextVersion);
|
|
614
|
-
const packageTag = formatTag(
|
|
698
|
+
const packageTag = formatTag(
|
|
699
|
+
nextVersion,
|
|
700
|
+
this.versionPrefix,
|
|
701
|
+
name,
|
|
702
|
+
this.tagTemplate,
|
|
703
|
+
this.packageTagTemplate
|
|
704
|
+
);
|
|
615
705
|
const tagMessage = `chore(release): ${name} ${nextVersion}`;
|
|
616
706
|
addTag(packageTag);
|
|
617
707
|
tags.push(packageTag);
|
|
@@ -687,7 +777,8 @@ function createSyncedStrategy(config) {
|
|
|
687
777
|
return async (packages) => {
|
|
688
778
|
try {
|
|
689
779
|
const {
|
|
690
|
-
|
|
780
|
+
versionPrefix,
|
|
781
|
+
tagTemplate,
|
|
691
782
|
baseBranch,
|
|
692
783
|
branchPattern,
|
|
693
784
|
commitMessage = "chore(release): v${version}",
|
|
@@ -695,11 +786,11 @@ function createSyncedStrategy(config) {
|
|
|
695
786
|
dryRun,
|
|
696
787
|
skipHooks
|
|
697
788
|
} = config;
|
|
698
|
-
const
|
|
789
|
+
const formattedPrefix = formatTagPrefix(versionPrefix || "v");
|
|
699
790
|
const latestTag = await getLatestTag();
|
|
700
791
|
const nextVersion = await calculateVersion(config, {
|
|
701
792
|
latestTag,
|
|
702
|
-
|
|
793
|
+
versionPrefix: formattedPrefix,
|
|
703
794
|
branchPattern,
|
|
704
795
|
baseBranch,
|
|
705
796
|
prereleaseIdentifier
|
|
@@ -735,7 +826,7 @@ function createSyncedStrategy(config) {
|
|
|
735
826
|
log("No packages were updated", "warning");
|
|
736
827
|
return;
|
|
737
828
|
}
|
|
738
|
-
const nextTag = formatTag(nextVersion,
|
|
829
|
+
const nextTag = formatTag(nextVersion, formattedPrefix, null, tagTemplate);
|
|
739
830
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
740
831
|
await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
|
|
741
832
|
} catch (error) {
|
|
@@ -754,7 +845,9 @@ function createSingleStrategy(config) {
|
|
|
754
845
|
try {
|
|
755
846
|
const {
|
|
756
847
|
packages: configPackages,
|
|
757
|
-
|
|
848
|
+
versionPrefix,
|
|
849
|
+
tagTemplate,
|
|
850
|
+
packageTagTemplate,
|
|
758
851
|
commitMessage = "chore(release): ${version}",
|
|
759
852
|
dryRun,
|
|
760
853
|
skipHooks
|
|
@@ -771,13 +864,18 @@ function createSingleStrategy(config) {
|
|
|
771
864
|
throw createVersionError("PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */, packageName);
|
|
772
865
|
}
|
|
773
866
|
const pkgPath = pkg.dir;
|
|
774
|
-
const
|
|
775
|
-
|
|
867
|
+
const formattedPrefix = formatTagPrefix(versionPrefix || "v");
|
|
868
|
+
let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix);
|
|
869
|
+
if (!latestTagResult) {
|
|
870
|
+
const globalTagResult = await getLatestTag();
|
|
871
|
+
latestTagResult = globalTagResult || "";
|
|
872
|
+
}
|
|
873
|
+
const latestTag = latestTagResult;
|
|
776
874
|
let nextVersion = void 0;
|
|
777
875
|
try {
|
|
778
876
|
nextVersion = await calculateVersion(config, {
|
|
779
877
|
latestTag,
|
|
780
|
-
|
|
878
|
+
versionPrefix: formattedPrefix,
|
|
781
879
|
path: pkgPath,
|
|
782
880
|
name: packageName
|
|
783
881
|
});
|
|
@@ -792,7 +890,13 @@ function createSingleStrategy(config) {
|
|
|
792
890
|
const packageJsonPath = path3.join(pkgPath, "package.json");
|
|
793
891
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
794
892
|
log(`Updated package ${packageName} to version ${nextVersion}`, "success");
|
|
795
|
-
const nextTag = formatTag(
|
|
893
|
+
const nextTag = formatTag(
|
|
894
|
+
nextVersion,
|
|
895
|
+
formattedPrefix,
|
|
896
|
+
packageName,
|
|
897
|
+
tagTemplate,
|
|
898
|
+
packageTagTemplate
|
|
899
|
+
);
|
|
796
900
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion);
|
|
797
901
|
await createGitCommitAndTag(
|
|
798
902
|
[packageJsonPath],
|
|
@@ -822,7 +926,9 @@ function createAsyncStrategy(config) {
|
|
|
822
926
|
const processorOptions = {
|
|
823
927
|
skip: config.skip || [],
|
|
824
928
|
targets: config.packages || [],
|
|
825
|
-
|
|
929
|
+
versionPrefix: config.versionPrefix || "v",
|
|
930
|
+
tagTemplate: config.tagTemplate,
|
|
931
|
+
packageTagTemplate: config.packageTagTemplate,
|
|
826
932
|
commitMessageTemplate: config.commitMessage || "",
|
|
827
933
|
dryRun: config.dryRun || false,
|
|
828
934
|
skipHooks: config.skipHooks || false,
|
|
@@ -133,3 +133,55 @@ This applies to all standard bump types:
|
|
|
133
133
|
- `--bump major`: 1.0.0-beta.1 -> 2.0.0
|
|
134
134
|
- `--bump minor`: 1.0.0-beta.1 -> 1.1.0
|
|
135
135
|
- `--bump patch`: 1.0.0-beta.1 -> 1.0.1
|
|
136
|
+
|
|
137
|
+
## Tag Templates and Configuration
|
|
138
|
+
|
|
139
|
+
`package-versioner` provides flexible configuration for how Git tags are formatted, allowing you to customize the tag structure for both single package repositories and monorepos.
|
|
140
|
+
|
|
141
|
+
### Tag Template Configuration
|
|
142
|
+
|
|
143
|
+
You can customize how tags are formatted using the following configuration options in `version.config.json`:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"versionPrefix": "v",
|
|
148
|
+
"tagTemplate": "${prefix}${version}",
|
|
149
|
+
"packageTagTemplate": "${packageName}@${prefix}${version}"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
- **versionPrefix**: The prefix used for all version numbers in tags (default: `"v"`)
|
|
154
|
+
- **tagTemplate**: The template for the main Git tag (default: `"${prefix}${version}"`)
|
|
155
|
+
- **packageTagTemplate**: The template for package-specific Git tags in monorepos (default: `"${packageName}@${prefix}${version}"`)
|
|
156
|
+
|
|
157
|
+
### Available Template Variables
|
|
158
|
+
|
|
159
|
+
The tag templates support the following variables:
|
|
160
|
+
|
|
161
|
+
- `${prefix}`: Replaced with the value of `versionPrefix`
|
|
162
|
+
- `${version}`: Replaced with the calculated version number
|
|
163
|
+
- `${packageName}`: (Only in `packageTagTemplate`) Replaced with the package name
|
|
164
|
+
|
|
165
|
+
### Examples
|
|
166
|
+
|
|
167
|
+
#### Default Tag Format
|
|
168
|
+
With default settings, tags will look like:
|
|
169
|
+
- Single repository or synced monorepo: `v1.2.3`
|
|
170
|
+
- Package-specific tag in async monorepo: `@scope/package-name@v1.2.3`
|
|
171
|
+
|
|
172
|
+
#### Custom Tag Format Examples
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"versionPrefix": "",
|
|
176
|
+
"tagTemplate": "release-${version}"
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
This would produce tags like `release-1.2.3` instead of `v1.2.3`.
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"versionPrefix": "v",
|
|
184
|
+
"packageTagTemplate": "${packageName}-${prefix}${version}"
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
This would produce package tags like `@scope/package-name-v1.2.3` instead of `@scope/package-name@v1.2.3`.
|
|
@@ -6,12 +6,24 @@
|
|
|
6
6
|
"type": "string",
|
|
7
7
|
"description": "JSON schema reference"
|
|
8
8
|
},
|
|
9
|
-
"
|
|
9
|
+
"versionPrefix": {
|
|
10
10
|
"type": "string",
|
|
11
11
|
"minLength": 1,
|
|
12
12
|
"description": "The prefix used for Git tags",
|
|
13
13
|
"default": "v"
|
|
14
14
|
},
|
|
15
|
+
"tagTemplate": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1,
|
|
18
|
+
"default": "${prefix}${version}",
|
|
19
|
+
"description": "Template for formatting Git tags"
|
|
20
|
+
},
|
|
21
|
+
"packageTagTemplate": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"minLength": 1,
|
|
24
|
+
"default": "${packageName}@${prefix}${version}",
|
|
25
|
+
"description": "Template for formatting package-specific Git tags"
|
|
26
|
+
},
|
|
15
27
|
"preset": {
|
|
16
28
|
"type": "string",
|
|
17
29
|
"enum": ["angular", "conventional"],
|
|
@@ -85,6 +97,6 @@
|
|
|
85
97
|
"description": "Whether to skip Git hooks"
|
|
86
98
|
}
|
|
87
99
|
},
|
|
88
|
-
"required": ["
|
|
100
|
+
"required": ["versionPrefix", "preset", "updateInternalDependencies"],
|
|
89
101
|
"additionalProperties": false
|
|
90
102
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "package-versioner",
|
|
3
3
|
"description": "A lightweight yet powerful CLI tool for automated semantic versioning based on Git history and conventional commits.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|