package-versioner 0.8.6 → 0.9.2

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 CHANGED
@@ -130,7 +130,7 @@ Customize behaviour by creating a `version.config.json` file in your project roo
130
130
  "updateChangelog": true,
131
131
  "changelogFormat": "keep-a-changelog",
132
132
  "strictReachable": false,
133
- "synced": true,
133
+ "sync": true,
134
134
  "skip": [
135
135
  "docs",
136
136
  "e2e"
@@ -160,7 +160,7 @@ Customize behaviour by creating a `version.config.json` file in your project roo
160
160
  - `paths`: Directories to search for Cargo.toml files (optional)
161
161
 
162
162
  #### Monorepo-Specific Options
163
- - `synced`: Whether all packages should be versioned together (default: true)
163
+ - `sync`: Whether all packages should be versioned together (default: true)
164
164
  - `skip`: Array of package names or patterns to exclude from versioning. Supports exact names, scope wildcards, path patterns, and global wildcards (e.g., ["@scope/package-a", "@scope/*", "packages/**/*"])
165
165
  - `packages`: Array of package names or patterns to target for versioning. Supports exact names, scope wildcards, path patterns and global wildcards (e.g., ["@scope/package-a", "@scope/*", "*"])
166
166
  - `mainPackage`: Package name whose commit history should drive version determination
@@ -234,7 +234,7 @@ This option works in conjunction with `tagTemplate` to control tag formatting. T
234
234
 
235
235
  **Examples:**
236
236
 
237
- For single-package repositories or synced monorepos:
237
+ For single-package repositories or sync monorepos:
238
238
  ```json
239
239
  {
240
240
  "packageSpecificTags": true,
@@ -253,8 +253,8 @@ For global versioning:
253
253
  Creates tags like `v1.2.3`
254
254
 
255
255
  **Important Notes:**
256
- - In **synced mode** with a single package, `packageSpecificTags: true` will use the package name even though all packages are versioned together
257
- - In **synced mode** with multiple packages, package names are not used regardless of the setting
256
+ - In **sync mode** with a single package, `packageSpecificTags: true` will use the package name even though all packages are versioned together
257
+ - In **sync mode** with multiple packages, package names are not used regardless of the setting
258
258
  - In **async mode**, each package gets its own tag when `packageSpecificTags` is enabled
259
259
 
260
260
  With package-specific tagging enabled, the tool will:
@@ -269,7 +269,7 @@ With package-specific tagging enabled, the tool will:
269
269
  1. **Conventional Commits:** Analyzes commit messages (like `feat:`, `fix:`, `BREAKING CHANGE:`) since the last tag.
270
270
  2. **Branch Pattern:** Determines the bump based on the current or recently merged branch name matching predefined patterns.
271
271
 
272
- For a detailed explanation of these concepts and monorepo modes (Synced vs. Async), see [Versioning Strategies and Concepts](./docs/versioning.md).
272
+ For a detailed explanation of these concepts and monorepo modes (Sync vs. Async), see [Versioning Strategies and Concepts](./docs/versioning.md).
273
273
 
274
274
  ## Documentation
275
275
 
@@ -0,0 +1,6 @@
1
+ import {
2
+ BasePackageVersionerError
3
+ } from "./chunk-IXZZQDKS.js";
4
+ export {
5
+ BasePackageVersionerError
6
+ };
@@ -0,0 +1,122 @@
1
+ // src/utils/logging.ts
2
+ import chalk from "chalk";
3
+ import figlet from "figlet";
4
+
5
+ // src/utils/jsonOutput.ts
6
+ var _jsonOutputMode = false;
7
+ var _jsonData = {
8
+ dryRun: false,
9
+ updates: [],
10
+ tags: []
11
+ };
12
+ function enableJsonOutput(dryRun = false) {
13
+ _jsonOutputMode = true;
14
+ _jsonData.dryRun = dryRun;
15
+ _jsonData.updates = [];
16
+ _jsonData.tags = [];
17
+ _jsonData.commitMessage = void 0;
18
+ }
19
+ function isJsonOutputMode() {
20
+ return _jsonOutputMode;
21
+ }
22
+ function addPackageUpdate(packageName, newVersion, filePath) {
23
+ if (!_jsonOutputMode) return;
24
+ _jsonData.updates.push({
25
+ packageName,
26
+ newVersion,
27
+ filePath
28
+ });
29
+ }
30
+ function addTag(tag) {
31
+ if (!_jsonOutputMode) return;
32
+ _jsonData.tags.push(tag);
33
+ }
34
+ function setCommitMessage(message) {
35
+ if (!_jsonOutputMode) return;
36
+ _jsonData.commitMessage = message;
37
+ }
38
+ function printJsonOutput() {
39
+ if (_jsonOutputMode) {
40
+ console.log(JSON.stringify(_jsonData, null, 2));
41
+ }
42
+ }
43
+
44
+ // src/utils/logging.ts
45
+ function log(message, level = "info") {
46
+ const showDebug = process.env.DEBUG === "true" || process.env.DEBUG === "1";
47
+ if (level === "debug" && !showDebug) {
48
+ return;
49
+ }
50
+ let chalkFn;
51
+ switch (level) {
52
+ case "success":
53
+ chalkFn = chalk.green;
54
+ break;
55
+ case "warning":
56
+ chalkFn = chalk.yellow;
57
+ break;
58
+ case "error":
59
+ chalkFn = chalk.red;
60
+ break;
61
+ case "debug":
62
+ chalkFn = chalk.gray;
63
+ break;
64
+ default:
65
+ chalkFn = chalk.blue;
66
+ }
67
+ if (isJsonOutputMode()) {
68
+ if (level === "error") {
69
+ chalkFn(message);
70
+ console.error(message);
71
+ }
72
+ return;
73
+ }
74
+ const formattedMessage = level === "debug" ? `[DEBUG] ${message}` : message;
75
+ if (level === "error") {
76
+ console.error(chalkFn(formattedMessage));
77
+ } else {
78
+ console.log(chalkFn(formattedMessage));
79
+ }
80
+ }
81
+
82
+ // src/errors/baseError.ts
83
+ var BasePackageVersionerError = class _BasePackageVersionerError extends Error {
84
+ constructor(message, code, suggestions) {
85
+ super(message);
86
+ this.code = code;
87
+ this.suggestions = suggestions;
88
+ this.name = this.constructor.name;
89
+ }
90
+ /**
91
+ * Log the error with consistent formatting and optional suggestions
92
+ * This centralizes all error output formatting and behavior
93
+ */
94
+ logError() {
95
+ var _a;
96
+ log(this.message, "error");
97
+ if ((_a = this.suggestions) == null ? void 0 : _a.length) {
98
+ log("\nSuggested solutions:", "info");
99
+ this.suggestions.forEach((suggestion, i) => {
100
+ log(`${i + 1}. ${suggestion}`, "info");
101
+ });
102
+ }
103
+ }
104
+ /**
105
+ * Type guard to check if an error is a package-versioner error
106
+ * @param error Error to check
107
+ * @returns true if error is a BasePackageVersionerError
108
+ */
109
+ static isPackageVersionerError(error) {
110
+ return error instanceof _BasePackageVersionerError;
111
+ }
112
+ };
113
+
114
+ export {
115
+ enableJsonOutput,
116
+ addPackageUpdate,
117
+ addTag,
118
+ setCommitMessage,
119
+ printJsonOutput,
120
+ log,
121
+ BasePackageVersionerError
122
+ };
package/dist/index.cjs CHANGED
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,32 +31,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- run: () => run
35
- });
36
- module.exports = __toCommonJS(index_exports);
37
- var fs10 = __toESM(require("fs"), 1);
38
- var import_node_path8 = __toESM(require("path"), 1);
39
- var import_commander = require("commander");
40
-
41
- // src/changelog/changelogRegenerator.ts
42
- var import_node_child_process2 = require("child_process");
43
- var import_node_fs = __toESM(require("fs"), 1);
44
- var import_node_path = __toESM(require("path"), 1);
45
-
46
- // src/utils/logging.ts
47
- var import_chalk = __toESM(require("chalk"), 1);
48
- var import_figlet = __toESM(require("figlet"), 1);
49
-
50
34
  // src/utils/jsonOutput.ts
51
- var _jsonOutputMode = false;
52
- var _jsonData = {
53
- dryRun: false,
54
- updates: [],
55
- tags: []
56
- };
57
35
  function enableJsonOutput(dryRun = false) {
58
36
  _jsonOutputMode = true;
59
37
  _jsonData.dryRun = dryRun;
@@ -85,6 +63,18 @@ function printJsonOutput() {
85
63
  console.log(JSON.stringify(_jsonData, null, 2));
86
64
  }
87
65
  }
66
+ var _jsonOutputMode, _jsonData;
67
+ var init_jsonOutput = __esm({
68
+ "src/utils/jsonOutput.ts"() {
69
+ "use strict";
70
+ _jsonOutputMode = false;
71
+ _jsonData = {
72
+ dryRun: false,
73
+ updates: [],
74
+ tags: []
75
+ };
76
+ }
77
+ });
88
78
 
89
79
  // src/utils/logging.ts
90
80
  function log(message, level = "info") {
@@ -123,9 +113,78 @@ function log(message, level = "info") {
123
113
  console.log(chalkFn(formattedMessage));
124
114
  }
125
115
  }
116
+ var import_chalk, import_figlet;
117
+ var init_logging = __esm({
118
+ "src/utils/logging.ts"() {
119
+ "use strict";
120
+ import_chalk = __toESM(require("chalk"), 1);
121
+ import_figlet = __toESM(require("figlet"), 1);
122
+ init_jsonOutput();
123
+ }
124
+ });
125
+
126
+ // src/errors/baseError.ts
127
+ var baseError_exports = {};
128
+ __export(baseError_exports, {
129
+ BasePackageVersionerError: () => BasePackageVersionerError
130
+ });
131
+ var BasePackageVersionerError;
132
+ var init_baseError = __esm({
133
+ "src/errors/baseError.ts"() {
134
+ "use strict";
135
+ init_logging();
136
+ BasePackageVersionerError = class _BasePackageVersionerError extends Error {
137
+ constructor(message, code, suggestions) {
138
+ super(message);
139
+ this.code = code;
140
+ this.suggestions = suggestions;
141
+ this.name = this.constructor.name;
142
+ }
143
+ /**
144
+ * Log the error with consistent formatting and optional suggestions
145
+ * This centralizes all error output formatting and behavior
146
+ */
147
+ logError() {
148
+ var _a;
149
+ log(this.message, "error");
150
+ if ((_a = this.suggestions) == null ? void 0 : _a.length) {
151
+ log("\nSuggested solutions:", "info");
152
+ this.suggestions.forEach((suggestion, i) => {
153
+ log(`${i + 1}. ${suggestion}`, "info");
154
+ });
155
+ }
156
+ }
157
+ /**
158
+ * Type guard to check if an error is a package-versioner error
159
+ * @param error Error to check
160
+ * @returns true if error is a BasePackageVersionerError
161
+ */
162
+ static isPackageVersionerError(error) {
163
+ return error instanceof _BasePackageVersionerError;
164
+ }
165
+ };
166
+ }
167
+ });
168
+
169
+ // src/index.ts
170
+ var index_exports = {};
171
+ __export(index_exports, {
172
+ run: () => run
173
+ });
174
+ module.exports = __toCommonJS(index_exports);
175
+ var fs10 = __toESM(require("fs"), 1);
176
+ var import_node_path8 = __toESM(require("path"), 1);
177
+ var import_commander = require("commander");
178
+
179
+ // src/changelog/changelogRegenerator.ts
180
+ var import_node_child_process2 = require("child_process");
181
+ var import_node_fs = __toESM(require("fs"), 1);
182
+ var import_node_path = __toESM(require("path"), 1);
183
+ init_logging();
126
184
 
127
185
  // src/changelog/commitParser.ts
128
186
  var import_node_child_process = require("child_process");
187
+ init_logging();
129
188
  var CONVENTIONAL_COMMIT_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?: (.+)(?:\n\n([\s\S]*))?/;
130
189
  var BREAKING_CHANGE_REGEX = /BREAKING CHANGE: ([\s\S]+?)(?:\n\n|$)/;
131
190
  function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
@@ -640,12 +699,8 @@ var import_node_process5 = require("process");
640
699
  var import_get_packages = require("@manypkg/get-packages");
641
700
 
642
701
  // src/errors/gitError.ts
643
- var GitError = class extends Error {
644
- constructor(message, code) {
645
- super(message);
646
- this.code = code;
647
- this.name = "GitError";
648
- }
702
+ init_baseError();
703
+ var GitError = class extends BasePackageVersionerError {
649
704
  };
650
705
  function createGitError(code, details) {
651
706
  const messages = {
@@ -653,20 +708,32 @@ function createGitError(code, details) {
653
708
  ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
654
709
  ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
655
710
  ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
656
- ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
711
+ ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed",
712
+ ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: "Git tag already exists"
713
+ };
714
+ const suggestions = {
715
+ ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: [
716
+ "Initialize git repository with: git init",
717
+ "Ensure you are in the correct directory"
718
+ ],
719
+ ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: [
720
+ "Delete the existing tag: git tag -d <tag-name>",
721
+ "Use a different version by incrementing manually",
722
+ "Check if this version was already released"
723
+ ],
724
+ ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: void 0,
725
+ ["NO_FILES" /* NO_FILES */]: void 0,
726
+ ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: void 0,
727
+ ["GIT_ERROR" /* GIT_ERROR */]: void 0
657
728
  };
658
729
  const baseMessage = messages[code];
659
730
  const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
660
- return new GitError(fullMessage, code);
731
+ return new GitError(fullMessage, code, suggestions[code]);
661
732
  }
662
733
 
663
734
  // src/errors/versionError.ts
664
- var VersionError = class extends Error {
665
- constructor(message, code) {
666
- super(message);
667
- this.code = code;
668
- this.name = "VersionError";
669
- }
735
+ init_baseError();
736
+ var VersionError = class extends BasePackageVersionerError {
670
737
  };
671
738
  function createVersionError(code, details) {
672
739
  const messages = {
@@ -677,14 +744,49 @@ function createVersionError(code, details) {
677
744
  ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
678
745
  ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
679
746
  };
747
+ const suggestions = {
748
+ ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: [
749
+ "Create a version.config.json file in your project root",
750
+ "Check the documentation for configuration examples"
751
+ ],
752
+ ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: [
753
+ "Ensure package.json or Cargo.toml files exist in your project",
754
+ "Check workspace configuration (pnpm-workspace.yaml, etc.)",
755
+ "Verify file permissions and paths"
756
+ ],
757
+ ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: [
758
+ "Verify workspace configuration files are valid",
759
+ "Check that workspace packages are accessible",
760
+ "Ensure proper monorepo structure"
761
+ ],
762
+ ["INVALID_CONFIG" /* INVALID_CONFIG */]: [
763
+ "Validate version.config.json syntax",
764
+ "Check configuration against schema",
765
+ "Review documentation for valid configuration options"
766
+ ],
767
+ ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: [
768
+ "Verify package name spelling and case",
769
+ "Check if package exists in workspace",
770
+ "Review packages configuration in version.config.json"
771
+ ],
772
+ ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: [
773
+ "Ensure git repository has commits",
774
+ "Check conventional commit message format",
775
+ "Verify git tags are properly formatted"
776
+ ]
777
+ };
680
778
  const baseMessage = messages[code];
681
779
  const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
682
- return new VersionError(fullMessage, code);
780
+ return new VersionError(fullMessage, code, suggestions[code]);
683
781
  }
684
782
 
783
+ // src/core/versionEngine.ts
784
+ init_logging();
785
+
685
786
  // src/utils/packageFiltering.ts
686
787
  var import_node_path2 = __toESM(require("path"), 1);
687
788
  var import_micromatch = __toESM(require("micromatch"), 1);
789
+ init_logging();
688
790
  function filterPackagesByConfig(packages, configTargets, workspaceRoot) {
689
791
  if (configTargets.length === 0) {
690
792
  log("No config targets specified, returning all packages", "debug");
@@ -770,6 +872,7 @@ var path8 = __toESM(require("path"), 1);
770
872
  // src/changelog/changelogManager.ts
771
873
  var fs3 = __toESM(require("fs"), 1);
772
874
  var path3 = __toESM(require("path"), 1);
875
+ init_logging();
773
876
  function updateChangelog(packagePath, packageName, version, entries, repoUrl, format = "keep-a-changelog") {
774
877
  try {
775
878
  const changelogPath = path3.join(packagePath, "CHANGELOG.md");
@@ -844,8 +947,13 @@ ${newVersionContent}
844
947
  }
845
948
  }
846
949
 
950
+ // src/core/versionStrategies.ts
951
+ init_baseError();
952
+
847
953
  // src/git/commands.ts
848
954
  var import_node_process2 = require("process");
955
+ init_jsonOutput();
956
+ init_logging();
849
957
 
850
958
  // src/git/commandExecutor.ts
851
959
  var import_node_child_process3 = require("child_process");
@@ -916,7 +1024,18 @@ async function gitCommit(options) {
916
1024
  async function createGitTag(options) {
917
1025
  const { tag, message = "", args = "" } = options;
918
1026
  const command = `git tag -a -m "${message}" ${tag} ${args}`;
919
- return execAsync(command);
1027
+ try {
1028
+ return await execAsync(command);
1029
+ } catch (error) {
1030
+ const errorMessage = error instanceof Error ? error.message : String(error);
1031
+ if (errorMessage.includes("already exists")) {
1032
+ throw createGitError(
1033
+ "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
1034
+ `Tag '${tag}' already exists in the repository. Please use a different version or delete the existing tag first.`
1035
+ );
1036
+ }
1037
+ throw createGitError("GIT_ERROR" /* GIT_ERROR */, errorMessage);
1038
+ }
920
1039
  }
921
1040
  async function gitProcess(options) {
922
1041
  const { files, nextTag, commitMessage, skipHooks, dryRun } = options;
@@ -949,6 +1068,13 @@ async function gitProcess(options) {
949
1068
  }
950
1069
  } catch (err) {
951
1070
  const errorMessage = err instanceof Error ? err.message : String(err);
1071
+ if (errorMessage.includes("already exists") && nextTag) {
1072
+ log(`Tag '${nextTag}' already exists in the repository.`, "error");
1073
+ throw createGitError(
1074
+ "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
1075
+ `Tag '${nextTag}' already exists in the repository. Please use a different version or delete the existing tag first.`
1076
+ );
1077
+ }
952
1078
  log(`Git process error: ${errorMessage}`, "error");
953
1079
  if (err instanceof Error && err.stack) {
954
1080
  console.error("Git process stack trace:");
@@ -980,6 +1106,9 @@ async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, d
980
1106
  log(`Created tag: ${nextTag}`, "success");
981
1107
  }
982
1108
  } catch (error) {
1109
+ if (error instanceof GitError) {
1110
+ throw error;
1111
+ }
983
1112
  const errorMessage = error instanceof Error ? error.message : String(error);
984
1113
  log(`Failed to create git commit and tag: ${errorMessage}`, "error");
985
1114
  if (error instanceof Error) {
@@ -1003,6 +1132,7 @@ var import_git_semver_tags = require("git-semver-tags");
1003
1132
  var import_semver = __toESM(require("semver"), 1);
1004
1133
 
1005
1134
  // src/utils/formatting.ts
1135
+ init_logging();
1006
1136
  function escapeRegExp(string) {
1007
1137
  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1008
1138
  }
@@ -1012,7 +1142,7 @@ function formatVersionPrefix(prefix) {
1012
1142
  function formatTag(version, prefix, packageName, template, packageSpecificTags) {
1013
1143
  if ((template == null ? void 0 : template.includes("${packageName}")) && !packageName) {
1014
1144
  log(
1015
- 'Warning: Your tagTemplate contains ${packageName} but no package name is available.\nThis will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true in your config to enable package names in tags\n\u2022 If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
1145
+ 'Warning: Your tagTemplate contains ${packageName} but no package name is available.\nThis will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").\n\nTo fix this:\n\u2022 If using sync mode: Set "packageSpecificTags": true in your config to enable package names in tags\n\u2022 If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
1016
1146
  "warning"
1017
1147
  );
1018
1148
  }
@@ -1027,7 +1157,7 @@ function formatTag(version, prefix, packageName, template, packageSpecificTags)
1027
1157
  function formatCommitMessage(template, version, packageName, additionalContext) {
1028
1158
  if (template.includes("${packageName}") && !packageName) {
1029
1159
  log(
1030
- 'Warning: Your commitMessage template contains ${packageName} but no package name is available.\nThis will result in an empty package name in the commit message (e.g., "Release @v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true to enable package names in commits\n\u2022 If you want generic commit messages: Remove ${packageName} from your commitMessage template\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
1160
+ 'Warning: Your commitMessage template contains ${packageName} but no package name is available.\nThis will result in an empty package name in the commit message (e.g., "Release @v1.0.0").\n\nTo fix this:\n\u2022 If using sync mode: Set "packageSpecificTags": true to enable package names in commits\n\u2022 If you want generic commit messages: Remove ${packageName} from your commitMessage template\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
1031
1161
  "warning"
1032
1162
  );
1033
1163
  }
@@ -1045,6 +1175,7 @@ function formatCommitMessage(template, version, packageName, additionalContext)
1045
1175
  }
1046
1176
 
1047
1177
  // src/git/tagsAndBranches.ts
1178
+ init_logging();
1048
1179
  function getCommitsLength(pkgRoot, sinceTag) {
1049
1180
  try {
1050
1181
  let gitCommand;
@@ -1242,6 +1373,8 @@ var import_node_path5 = __toESM(require("path"), 1);
1242
1373
  var import_node_fs3 = __toESM(require("fs"), 1);
1243
1374
  var import_node_path4 = __toESM(require("path"), 1);
1244
1375
  var TOML = __toESM(require("smol-toml"), 1);
1376
+ init_jsonOutput();
1377
+ init_logging();
1245
1378
  function getCargoInfo(cargoPath) {
1246
1379
  var _a;
1247
1380
  if (!import_node_fs3.default.existsSync(cargoPath)) {
@@ -1302,6 +1435,8 @@ function updateCargoVersion(cargoPath, version) {
1302
1435
  }
1303
1436
 
1304
1437
  // src/package/packageManagement.ts
1438
+ init_jsonOutput();
1439
+ init_logging();
1305
1440
  function updatePackageVersion(packagePath, version) {
1306
1441
  if (isCargoToml(packagePath)) {
1307
1442
  updateCargoVersion(packagePath, version);
@@ -1334,10 +1469,12 @@ var import_node_process4 = require("process");
1334
1469
  var import_node_process3 = require("process");
1335
1470
  var import_conventional_recommended_bump = require("conventional-recommended-bump");
1336
1471
  var import_semver3 = __toESM(require("semver"), 1);
1472
+ init_logging();
1337
1473
 
1338
1474
  // src/utils/manifestHelpers.ts
1339
1475
  var import_node_fs5 = __toESM(require("fs"), 1);
1340
1476
  var import_node_path6 = __toESM(require("path"), 1);
1477
+ init_logging();
1341
1478
  function getVersionFromManifests(packageDir) {
1342
1479
  const packageJsonPath = import_node_path6.default.join(packageDir, "package.json");
1343
1480
  const cargoTomlPath = import_node_path6.default.join(packageDir, "Cargo.toml");
@@ -1419,6 +1556,7 @@ function verifyTag(tagName, cwd5) {
1419
1556
  }
1420
1557
 
1421
1558
  // src/utils/versionUtils.ts
1559
+ init_logging();
1422
1560
  var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
1423
1561
  function normalizePrereleaseIdentifier(prereleaseIdentifier, config) {
1424
1562
  if (prereleaseIdentifier === true) {
@@ -1668,8 +1806,13 @@ async function calculateVersion(config, options) {
1668
1806
  }
1669
1807
  }
1670
1808
 
1809
+ // src/package/packageProcessor.ts
1810
+ init_jsonOutput();
1811
+ init_logging();
1812
+
1671
1813
  // src/utils/packageMatching.ts
1672
1814
  var import_micromatch2 = __toESM(require("micromatch"), 1);
1815
+ init_logging();
1673
1816
  function matchesPackageTarget(packageName, target) {
1674
1817
  if (packageName === target) {
1675
1818
  return true;
@@ -1993,11 +2136,12 @@ var PackageProcessor = class {
1993
2136
  };
1994
2137
 
1995
2138
  // src/core/versionStrategies.ts
2139
+ init_logging();
1996
2140
  function shouldProcessPackage2(pkg, config) {
1997
2141
  const pkgName = pkg.packageJson.name;
1998
2142
  return shouldProcessPackage(pkgName, config.skip);
1999
2143
  }
2000
- function createSyncedStrategy(config) {
2144
+ function createSyncStrategy(config) {
2001
2145
  return async (packages) => {
2002
2146
  try {
2003
2147
  const {
@@ -2124,8 +2268,8 @@ function createSyncedStrategy(config) {
2124
2268
  );
2125
2269
  await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
2126
2270
  } catch (error) {
2127
- if (error instanceof VersionError || error instanceof GitError) {
2128
- log(`Synced Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2271
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2272
+ log(`Synced Strategy failed: ${error.message} (${error.code})`, "error");
2129
2273
  } else {
2130
2274
  const errorMessage = error instanceof Error ? error.message : String(error);
2131
2275
  log(`Synced Strategy failed: ${errorMessage}`, "error");
@@ -2274,8 +2418,8 @@ function createSingleStrategy(config) {
2274
2418
  log(`Would create tag: ${tagName}`, "info");
2275
2419
  }
2276
2420
  } catch (error) {
2277
- if (error instanceof VersionError || error instanceof GitError) {
2278
- log(`Single Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2421
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2422
+ log(`Single Strategy failed: ${error.message} (${error.code})`, "error");
2279
2423
  } else {
2280
2424
  const errorMessage = error instanceof Error ? error.message : String(error);
2281
2425
  log(`Single Strategy failed: ${errorMessage}`, "error");
@@ -2306,10 +2450,21 @@ function createAsyncStrategy(config) {
2306
2450
  }
2307
2451
  };
2308
2452
  const packageProcessor = new PackageProcessor(processorOptions);
2309
- return async (packages, _targets = []) => {
2453
+ return async (packages, targets = []) => {
2310
2454
  try {
2311
- log(`Processing ${packages.packages.length} pre-filtered packages`, "info");
2312
- const result = await packageProcessor.processPackages(packages.packages);
2455
+ let packagesToProcess = packages.packages;
2456
+ if (targets.length > 0) {
2457
+ const beforeCount = packagesToProcess.length;
2458
+ packagesToProcess = packagesToProcess.filter(
2459
+ (pkg) => targets.includes(pkg.packageJson.name)
2460
+ );
2461
+ log(
2462
+ `Runtime targets filter: ${beforeCount} \u2192 ${packagesToProcess.length} packages (${targets.join(", ")})`,
2463
+ "info"
2464
+ );
2465
+ }
2466
+ log(`Processing ${packagesToProcess.length} packages`, "info");
2467
+ const result = await packageProcessor.processPackages(packagesToProcess);
2313
2468
  if (result.updatedPackages.length === 0) {
2314
2469
  log("No packages required a version update.", "info");
2315
2470
  } else {
@@ -2323,8 +2478,8 @@ function createAsyncStrategy(config) {
2323
2478
  }
2324
2479
  }
2325
2480
  } catch (error) {
2326
- if (error instanceof VersionError || error instanceof GitError) {
2327
- log(`Async Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2481
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2482
+ log(`Async Strategy failed: ${error.message} (${error.code})`, "error");
2328
2483
  } else {
2329
2484
  const errorMessage = error instanceof Error ? error.message : String(error);
2330
2485
  log(`Async Strategy failed: ${errorMessage}`, "error");
@@ -2334,14 +2489,14 @@ function createAsyncStrategy(config) {
2334
2489
  };
2335
2490
  }
2336
2491
  function createStrategy(config) {
2337
- if (config.synced) {
2338
- return createSyncedStrategy(config);
2492
+ if (config.sync) {
2493
+ return createSyncStrategy(config);
2339
2494
  }
2340
2495
  return createAsyncStrategy(config);
2341
2496
  }
2342
2497
  function createStrategyMap(config) {
2343
2498
  return {
2344
- synced: createSyncedStrategy(config),
2499
+ sync: createSyncStrategy(config),
2345
2500
  single: createSingleStrategy(config),
2346
2501
  async: createAsyncStrategy(config)
2347
2502
  };
@@ -2442,7 +2597,7 @@ var VersionEngine = class {
2442
2597
  }
2443
2598
  /**
2444
2599
  * Change the current strategy
2445
- * @param strategyType The strategy type to use: 'synced', 'single', or 'async'
2600
+ * @param strategyType The strategy type to use: 'sync', 'single', or 'async'
2446
2601
  */
2447
2602
  setStrategy(strategyType) {
2448
2603
  this.currentStrategy = this.strategies[strategyType];
@@ -2450,6 +2605,8 @@ var VersionEngine = class {
2450
2605
  };
2451
2606
 
2452
2607
  // src/index.ts
2608
+ init_jsonOutput();
2609
+ init_logging();
2453
2610
  var import_meta = {};
2454
2611
  function getPackageVersion() {
2455
2612
  try {
@@ -2477,7 +2634,7 @@ async function run() {
2477
2634
  program.command("version", { isDefault: true }).description("Version a package or packages based on configuration").option(
2478
2635
  "-c, --config <path>",
2479
2636
  "Path to config file (defaults to version.config.json in current directory)"
2480
- ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use 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").option("--project-dir <path>", "Project directory to run commands in", process.cwd()).action(async (options) => {
2637
+ ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --sync", "Use 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").option("--project-dir <path>", "Project directory to run commands in", process.cwd()).action(async (options) => {
2481
2638
  if (options.json) {
2482
2639
  enableJsonOutput(options.dryRun);
2483
2640
  }
@@ -2496,22 +2653,26 @@ async function run() {
2496
2653
  const config = await loadConfig(options.config);
2497
2654
  log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
2498
2655
  if (options.dryRun) config.dryRun = true;
2499
- if (options.synced) config.synced = true;
2656
+ if (options.sync) config.sync = true;
2500
2657
  if (options.bump) config.type = options.bump;
2501
2658
  if (options.prerelease) {
2502
2659
  config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
2503
2660
  config.isPrerelease = true;
2504
2661
  }
2505
2662
  const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
2663
+ if (cliTargets.length > 0) {
2664
+ config.packages = cliTargets;
2665
+ log(`CLI targets specified: ${cliTargets.join(", ")}`, "info");
2666
+ }
2506
2667
  const engine = new VersionEngine(config, !!options.json);
2507
2668
  const pkgsResult = await engine.getWorkspacePackages();
2508
2669
  const resolvedCount = pkgsResult.packages.length;
2509
2670
  log(`Resolved ${resolvedCount} packages from workspace`, "debug");
2510
2671
  log(`Config packages: ${JSON.stringify(config.packages)}`, "debug");
2511
- log(`Config synced: ${config.synced}`, "debug");
2512
- if (config.synced) {
2513
- log("Using synced versioning strategy.", "info");
2514
- engine.setStrategy("synced");
2672
+ log(`Config sync: ${config.sync}`, "debug");
2673
+ if (config.sync) {
2674
+ log("Using sync versioning strategy.", "info");
2675
+ engine.setStrategy("sync");
2515
2676
  await engine.run(pkgsResult);
2516
2677
  } else if (resolvedCount === 1) {
2517
2678
  log("Using single package versioning strategy.", "info");
@@ -2533,14 +2694,19 @@ async function run() {
2533
2694
  log("Versioning process completed.", "success");
2534
2695
  printJsonOutput();
2535
2696
  } catch (error) {
2536
- log(error instanceof Error ? error.message : String(error), "error");
2537
- if (error instanceof Error) {
2538
- console.error("Error details:");
2539
- console.error(error.stack || error.message);
2540
- if (error.message.includes("Command failed:")) {
2541
- const cmdOutput = error.message.split("Command failed:")[1];
2542
- if (cmdOutput) {
2543
- console.error("Command output:", cmdOutput.trim());
2697
+ const { BasePackageVersionerError: BasePackageVersionerError2 } = await Promise.resolve().then(() => (init_baseError(), baseError_exports));
2698
+ if (BasePackageVersionerError2.isPackageVersionerError(error)) {
2699
+ error.logError();
2700
+ } else {
2701
+ log(error instanceof Error ? error.message : String(error), "error");
2702
+ if (error instanceof Error) {
2703
+ console.error("Error details:");
2704
+ console.error(error.stack || error.message);
2705
+ if (error.message.includes("Command failed:")) {
2706
+ const cmdOutput = error.message.split("Command failed:")[1];
2707
+ if (cmdOutput) {
2708
+ console.error("Command output:", cmdOutput.trim());
2709
+ }
2544
2710
  }
2545
2711
  }
2546
2712
  }
package/dist/index.js CHANGED
@@ -1,4 +1,13 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ BasePackageVersionerError,
4
+ addPackageUpdate,
5
+ addTag,
6
+ enableJsonOutput,
7
+ log,
8
+ printJsonOutput,
9
+ setCommitMessage
10
+ } from "./chunk-IXZZQDKS.js";
2
11
 
3
12
  // src/index.ts
4
13
  import * as fs10 from "fs";
@@ -10,87 +19,6 @@ import { execSync as execSync2 } from "child_process";
10
19
  import fs from "fs";
11
20
  import path from "path";
12
21
 
13
- // src/utils/logging.ts
14
- import chalk from "chalk";
15
- import figlet from "figlet";
16
-
17
- // src/utils/jsonOutput.ts
18
- var _jsonOutputMode = false;
19
- var _jsonData = {
20
- dryRun: false,
21
- updates: [],
22
- tags: []
23
- };
24
- function enableJsonOutput(dryRun = false) {
25
- _jsonOutputMode = true;
26
- _jsonData.dryRun = dryRun;
27
- _jsonData.updates = [];
28
- _jsonData.tags = [];
29
- _jsonData.commitMessage = void 0;
30
- }
31
- function isJsonOutputMode() {
32
- return _jsonOutputMode;
33
- }
34
- function addPackageUpdate(packageName, newVersion, filePath) {
35
- if (!_jsonOutputMode) return;
36
- _jsonData.updates.push({
37
- packageName,
38
- newVersion,
39
- filePath
40
- });
41
- }
42
- function addTag(tag) {
43
- if (!_jsonOutputMode) return;
44
- _jsonData.tags.push(tag);
45
- }
46
- function setCommitMessage(message) {
47
- if (!_jsonOutputMode) return;
48
- _jsonData.commitMessage = message;
49
- }
50
- function printJsonOutput() {
51
- if (_jsonOutputMode) {
52
- console.log(JSON.stringify(_jsonData, null, 2));
53
- }
54
- }
55
-
56
- // src/utils/logging.ts
57
- function log(message, level = "info") {
58
- const showDebug = process.env.DEBUG === "true" || process.env.DEBUG === "1";
59
- if (level === "debug" && !showDebug) {
60
- return;
61
- }
62
- let chalkFn;
63
- switch (level) {
64
- case "success":
65
- chalkFn = chalk.green;
66
- break;
67
- case "warning":
68
- chalkFn = chalk.yellow;
69
- break;
70
- case "error":
71
- chalkFn = chalk.red;
72
- break;
73
- case "debug":
74
- chalkFn = chalk.gray;
75
- break;
76
- default:
77
- chalkFn = chalk.blue;
78
- }
79
- if (isJsonOutputMode()) {
80
- if (level === "error") {
81
- chalkFn(message);
82
- console.error(message);
83
- }
84
- return;
85
- }
86
- const formattedMessage = level === "debug" ? `[DEBUG] ${message}` : message;
87
- if (level === "error") {
88
- console.error(chalkFn(formattedMessage));
89
- } else {
90
- console.log(chalkFn(formattedMessage));
91
- }
92
- }
93
-
94
22
  // src/changelog/commitParser.ts
95
23
  import { execSync } from "child_process";
96
24
  var CONVENTIONAL_COMMIT_REGEX = /^(\w+)(?:\(([^)]+)\))?(!)?: (.+)(?:\n\n([\s\S]*))?/;
@@ -607,12 +535,7 @@ import { cwd as cwd4 } from "process";
607
535
  import { getPackagesSync } from "@manypkg/get-packages";
608
536
 
609
537
  // src/errors/gitError.ts
610
- var GitError = class extends Error {
611
- constructor(message, code) {
612
- super(message);
613
- this.code = code;
614
- this.name = "GitError";
615
- }
538
+ var GitError = class extends BasePackageVersionerError {
616
539
  };
617
540
  function createGitError(code, details) {
618
541
  const messages = {
@@ -620,20 +543,31 @@ function createGitError(code, details) {
620
543
  ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: "Failed to create new version",
621
544
  ["NO_FILES" /* NO_FILES */]: "No files specified for commit",
622
545
  ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: "Commit message is required",
623
- ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed"
546
+ ["GIT_ERROR" /* GIT_ERROR */]: "Git operation failed",
547
+ ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: "Git tag already exists"
548
+ };
549
+ const suggestions = {
550
+ ["NOT_GIT_REPO" /* NOT_GIT_REPO */]: [
551
+ "Initialize git repository with: git init",
552
+ "Ensure you are in the correct directory"
553
+ ],
554
+ ["TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */]: [
555
+ "Delete the existing tag: git tag -d <tag-name>",
556
+ "Use a different version by incrementing manually",
557
+ "Check if this version was already released"
558
+ ],
559
+ ["GIT_PROCESS_ERROR" /* GIT_PROCESS_ERROR */]: void 0,
560
+ ["NO_FILES" /* NO_FILES */]: void 0,
561
+ ["NO_COMMIT_MESSAGE" /* NO_COMMIT_MESSAGE */]: void 0,
562
+ ["GIT_ERROR" /* GIT_ERROR */]: void 0
624
563
  };
625
564
  const baseMessage = messages[code];
626
565
  const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
627
- return new GitError(fullMessage, code);
566
+ return new GitError(fullMessage, code, suggestions[code]);
628
567
  }
629
568
 
630
569
  // src/errors/versionError.ts
631
- var VersionError = class extends Error {
632
- constructor(message, code) {
633
- super(message);
634
- this.code = code;
635
- this.name = "VersionError";
636
- }
570
+ var VersionError = class extends BasePackageVersionerError {
637
571
  };
638
572
  function createVersionError(code, details) {
639
573
  const messages = {
@@ -644,9 +578,40 @@ function createVersionError(code, details) {
644
578
  ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: "Package not found",
645
579
  ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: "Failed to calculate version"
646
580
  };
581
+ const suggestions = {
582
+ ["CONFIG_REQUIRED" /* CONFIG_REQUIRED */]: [
583
+ "Create a version.config.json file in your project root",
584
+ "Check the documentation for configuration examples"
585
+ ],
586
+ ["PACKAGES_NOT_FOUND" /* PACKAGES_NOT_FOUND */]: [
587
+ "Ensure package.json or Cargo.toml files exist in your project",
588
+ "Check workspace configuration (pnpm-workspace.yaml, etc.)",
589
+ "Verify file permissions and paths"
590
+ ],
591
+ ["WORKSPACE_ERROR" /* WORKSPACE_ERROR */]: [
592
+ "Verify workspace configuration files are valid",
593
+ "Check that workspace packages are accessible",
594
+ "Ensure proper monorepo structure"
595
+ ],
596
+ ["INVALID_CONFIG" /* INVALID_CONFIG */]: [
597
+ "Validate version.config.json syntax",
598
+ "Check configuration against schema",
599
+ "Review documentation for valid configuration options"
600
+ ],
601
+ ["PACKAGE_NOT_FOUND" /* PACKAGE_NOT_FOUND */]: [
602
+ "Verify package name spelling and case",
603
+ "Check if package exists in workspace",
604
+ "Review packages configuration in version.config.json"
605
+ ],
606
+ ["VERSION_CALCULATION_ERROR" /* VERSION_CALCULATION_ERROR */]: [
607
+ "Ensure git repository has commits",
608
+ "Check conventional commit message format",
609
+ "Verify git tags are properly formatted"
610
+ ]
611
+ };
647
612
  const baseMessage = messages[code];
648
613
  const fullMessage = details ? `${baseMessage}: ${details}` : baseMessage;
649
- return new VersionError(fullMessage, code);
614
+ return new VersionError(fullMessage, code, suggestions[code]);
650
615
  }
651
616
 
652
617
  // src/utils/packageFiltering.ts
@@ -883,7 +848,18 @@ async function gitCommit(options) {
883
848
  async function createGitTag(options) {
884
849
  const { tag, message = "", args = "" } = options;
885
850
  const command = `git tag -a -m "${message}" ${tag} ${args}`;
886
- return execAsync(command);
851
+ try {
852
+ return await execAsync(command);
853
+ } catch (error) {
854
+ const errorMessage = error instanceof Error ? error.message : String(error);
855
+ if (errorMessage.includes("already exists")) {
856
+ throw createGitError(
857
+ "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
858
+ `Tag '${tag}' already exists in the repository. Please use a different version or delete the existing tag first.`
859
+ );
860
+ }
861
+ throw createGitError("GIT_ERROR" /* GIT_ERROR */, errorMessage);
862
+ }
887
863
  }
888
864
  async function gitProcess(options) {
889
865
  const { files, nextTag, commitMessage, skipHooks, dryRun } = options;
@@ -916,6 +892,13 @@ async function gitProcess(options) {
916
892
  }
917
893
  } catch (err) {
918
894
  const errorMessage = err instanceof Error ? err.message : String(err);
895
+ if (errorMessage.includes("already exists") && nextTag) {
896
+ log(`Tag '${nextTag}' already exists in the repository.`, "error");
897
+ throw createGitError(
898
+ "TAG_ALREADY_EXISTS" /* TAG_ALREADY_EXISTS */,
899
+ `Tag '${nextTag}' already exists in the repository. Please use a different version or delete the existing tag first.`
900
+ );
901
+ }
919
902
  log(`Git process error: ${errorMessage}`, "error");
920
903
  if (err instanceof Error && err.stack) {
921
904
  console.error("Git process stack trace:");
@@ -947,6 +930,9 @@ async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, d
947
930
  log(`Created tag: ${nextTag}`, "success");
948
931
  }
949
932
  } catch (error) {
933
+ if (error instanceof GitError) {
934
+ throw error;
935
+ }
950
936
  const errorMessage = error instanceof Error ? error.message : String(error);
951
937
  log(`Failed to create git commit and tag: ${errorMessage}`, "error");
952
938
  if (error instanceof Error) {
@@ -979,7 +965,7 @@ function formatVersionPrefix(prefix) {
979
965
  function formatTag(version, prefix, packageName, template, packageSpecificTags) {
980
966
  if ((template == null ? void 0 : template.includes("${packageName}")) && !packageName) {
981
967
  log(
982
- 'Warning: Your tagTemplate contains ${packageName} but no package name is available.\nThis will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true in your config to enable package names in tags\n\u2022 If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
968
+ 'Warning: Your tagTemplate contains ${packageName} but no package name is available.\nThis will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").\n\nTo fix this:\n\u2022 If using sync mode: Set "packageSpecificTags": true in your config to enable package names in tags\n\u2022 If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
983
969
  "warning"
984
970
  );
985
971
  }
@@ -994,7 +980,7 @@ function formatTag(version, prefix, packageName, template, packageSpecificTags)
994
980
  function formatCommitMessage(template, version, packageName, additionalContext) {
995
981
  if (template.includes("${packageName}") && !packageName) {
996
982
  log(
997
- 'Warning: Your commitMessage template contains ${packageName} but no package name is available.\nThis will result in an empty package name in the commit message (e.g., "Release @v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true to enable package names in commits\n\u2022 If you want generic commit messages: Remove ${packageName} from your commitMessage template\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
983
+ 'Warning: Your commitMessage template contains ${packageName} but no package name is available.\nThis will result in an empty package name in the commit message (e.g., "Release @v1.0.0").\n\nTo fix this:\n\u2022 If using sync mode: Set "packageSpecificTags": true to enable package names in commits\n\u2022 If you want generic commit messages: Remove ${packageName} from your commitMessage template\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
998
984
  "warning"
999
985
  );
1000
986
  }
@@ -1964,7 +1950,7 @@ function shouldProcessPackage2(pkg, config) {
1964
1950
  const pkgName = pkg.packageJson.name;
1965
1951
  return shouldProcessPackage(pkgName, config.skip);
1966
1952
  }
1967
- function createSyncedStrategy(config) {
1953
+ function createSyncStrategy(config) {
1968
1954
  return async (packages) => {
1969
1955
  try {
1970
1956
  const {
@@ -2091,8 +2077,8 @@ function createSyncedStrategy(config) {
2091
2077
  );
2092
2078
  await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
2093
2079
  } catch (error) {
2094
- if (error instanceof VersionError || error instanceof GitError) {
2095
- log(`Synced Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2080
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2081
+ log(`Synced Strategy failed: ${error.message} (${error.code})`, "error");
2096
2082
  } else {
2097
2083
  const errorMessage = error instanceof Error ? error.message : String(error);
2098
2084
  log(`Synced Strategy failed: ${errorMessage}`, "error");
@@ -2241,8 +2227,8 @@ function createSingleStrategy(config) {
2241
2227
  log(`Would create tag: ${tagName}`, "info");
2242
2228
  }
2243
2229
  } catch (error) {
2244
- if (error instanceof VersionError || error instanceof GitError) {
2245
- log(`Single Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2230
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2231
+ log(`Single Strategy failed: ${error.message} (${error.code})`, "error");
2246
2232
  } else {
2247
2233
  const errorMessage = error instanceof Error ? error.message : String(error);
2248
2234
  log(`Single Strategy failed: ${errorMessage}`, "error");
@@ -2273,10 +2259,21 @@ function createAsyncStrategy(config) {
2273
2259
  }
2274
2260
  };
2275
2261
  const packageProcessor = new PackageProcessor(processorOptions);
2276
- return async (packages, _targets = []) => {
2262
+ return async (packages, targets = []) => {
2277
2263
  try {
2278
- log(`Processing ${packages.packages.length} pre-filtered packages`, "info");
2279
- const result = await packageProcessor.processPackages(packages.packages);
2264
+ let packagesToProcess = packages.packages;
2265
+ if (targets.length > 0) {
2266
+ const beforeCount = packagesToProcess.length;
2267
+ packagesToProcess = packagesToProcess.filter(
2268
+ (pkg) => targets.includes(pkg.packageJson.name)
2269
+ );
2270
+ log(
2271
+ `Runtime targets filter: ${beforeCount} \u2192 ${packagesToProcess.length} packages (${targets.join(", ")})`,
2272
+ "info"
2273
+ );
2274
+ }
2275
+ log(`Processing ${packagesToProcess.length} packages`, "info");
2276
+ const result = await packageProcessor.processPackages(packagesToProcess);
2280
2277
  if (result.updatedPackages.length === 0) {
2281
2278
  log("No packages required a version update.", "info");
2282
2279
  } else {
@@ -2290,8 +2287,8 @@ function createAsyncStrategy(config) {
2290
2287
  }
2291
2288
  }
2292
2289
  } catch (error) {
2293
- if (error instanceof VersionError || error instanceof GitError) {
2294
- log(`Async Strategy failed: ${error.message} (${error.code || "UNKNOWN"})`, "error");
2290
+ if (BasePackageVersionerError.isPackageVersionerError(error)) {
2291
+ log(`Async Strategy failed: ${error.message} (${error.code})`, "error");
2295
2292
  } else {
2296
2293
  const errorMessage = error instanceof Error ? error.message : String(error);
2297
2294
  log(`Async Strategy failed: ${errorMessage}`, "error");
@@ -2301,14 +2298,14 @@ function createAsyncStrategy(config) {
2301
2298
  };
2302
2299
  }
2303
2300
  function createStrategy(config) {
2304
- if (config.synced) {
2305
- return createSyncedStrategy(config);
2301
+ if (config.sync) {
2302
+ return createSyncStrategy(config);
2306
2303
  }
2307
2304
  return createAsyncStrategy(config);
2308
2305
  }
2309
2306
  function createStrategyMap(config) {
2310
2307
  return {
2311
- synced: createSyncedStrategy(config),
2308
+ sync: createSyncStrategy(config),
2312
2309
  single: createSingleStrategy(config),
2313
2310
  async: createAsyncStrategy(config)
2314
2311
  };
@@ -2409,7 +2406,7 @@ var VersionEngine = class {
2409
2406
  }
2410
2407
  /**
2411
2408
  * Change the current strategy
2412
- * @param strategyType The strategy type to use: 'synced', 'single', or 'async'
2409
+ * @param strategyType The strategy type to use: 'sync', 'single', or 'async'
2413
2410
  */
2414
2411
  setStrategy(strategyType) {
2415
2412
  this.currentStrategy = this.strategies[strategyType];
@@ -2443,7 +2440,7 @@ async function run() {
2443
2440
  program.command("version", { isDefault: true }).description("Version a package or packages based on configuration").option(
2444
2441
  "-c, --config <path>",
2445
2442
  "Path to config file (defaults to version.config.json in current directory)"
2446
- ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --synced", "Use 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").option("--project-dir <path>", "Project directory to run commands in", process.cwd()).action(async (options) => {
2443
+ ).option("-d, --dry-run", "Dry run (no changes made)", false).option("-b, --bump <type>", "Specify bump type (patch|minor|major)").option("-p, --prerelease [identifier]", "Create prerelease version").option("-s, --sync", "Use 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").option("--project-dir <path>", "Project directory to run commands in", process.cwd()).action(async (options) => {
2447
2444
  if (options.json) {
2448
2445
  enableJsonOutput(options.dryRun);
2449
2446
  }
@@ -2462,22 +2459,26 @@ async function run() {
2462
2459
  const config = await loadConfig(options.config);
2463
2460
  log(`Loaded configuration from ${options.config || "version.config.json"}`, "info");
2464
2461
  if (options.dryRun) config.dryRun = true;
2465
- if (options.synced) config.synced = true;
2462
+ if (options.sync) config.sync = true;
2466
2463
  if (options.bump) config.type = options.bump;
2467
2464
  if (options.prerelease) {
2468
2465
  config.prereleaseIdentifier = options.prerelease === true ? "next" : options.prerelease;
2469
2466
  config.isPrerelease = true;
2470
2467
  }
2471
2468
  const cliTargets = options.target ? options.target.split(",").map((t) => t.trim()) : [];
2469
+ if (cliTargets.length > 0) {
2470
+ config.packages = cliTargets;
2471
+ log(`CLI targets specified: ${cliTargets.join(", ")}`, "info");
2472
+ }
2472
2473
  const engine = new VersionEngine(config, !!options.json);
2473
2474
  const pkgsResult = await engine.getWorkspacePackages();
2474
2475
  const resolvedCount = pkgsResult.packages.length;
2475
2476
  log(`Resolved ${resolvedCount} packages from workspace`, "debug");
2476
2477
  log(`Config packages: ${JSON.stringify(config.packages)}`, "debug");
2477
- log(`Config synced: ${config.synced}`, "debug");
2478
- if (config.synced) {
2479
- log("Using synced versioning strategy.", "info");
2480
- engine.setStrategy("synced");
2478
+ log(`Config sync: ${config.sync}`, "debug");
2479
+ if (config.sync) {
2480
+ log("Using sync versioning strategy.", "info");
2481
+ engine.setStrategy("sync");
2481
2482
  await engine.run(pkgsResult);
2482
2483
  } else if (resolvedCount === 1) {
2483
2484
  log("Using single package versioning strategy.", "info");
@@ -2499,14 +2500,19 @@ async function run() {
2499
2500
  log("Versioning process completed.", "success");
2500
2501
  printJsonOutput();
2501
2502
  } catch (error) {
2502
- log(error instanceof Error ? error.message : String(error), "error");
2503
- if (error instanceof Error) {
2504
- console.error("Error details:");
2505
- console.error(error.stack || error.message);
2506
- if (error.message.includes("Command failed:")) {
2507
- const cmdOutput = error.message.split("Command failed:")[1];
2508
- if (cmdOutput) {
2509
- console.error("Command output:", cmdOutput.trim());
2503
+ const { BasePackageVersionerError: BasePackageVersionerError2 } = await import("./baseError-XWEU2UI6.js");
2504
+ if (BasePackageVersionerError2.isPackageVersionerError(error)) {
2505
+ error.logError();
2506
+ } else {
2507
+ log(error instanceof Error ? error.message : String(error), "error");
2508
+ if (error instanceof Error) {
2509
+ console.error("Error details:");
2510
+ console.error(error.stack || error.message);
2511
+ if (error.message.includes("Command failed:")) {
2512
+ const cmdOutput = error.message.split("Command failed:")[1];
2513
+ if (cmdOutput) {
2514
+ console.error("Command output:", cmdOutput.trim());
2515
+ }
2510
2516
  }
2511
2517
  }
2512
2518
  }
@@ -334,7 +334,7 @@ Warning: Your tagTemplate contains ${packageName} but no package name is availab
334
334
  This will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").
335
335
 
336
336
  To fix this:
337
- • If using synced mode: Set "packageSpecificTags": true in your config to enable package names in tags
337
+ • If using sync mode: Set "packageSpecificTags": true in your config to enable package names in tags
338
338
  • If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")
339
339
  • If using single/async mode: Ensure your package.json has a valid "name" field
340
340
  ```
@@ -344,7 +344,7 @@ To fix this:
344
344
  1. **For Synced Mode with Package Names**: Enable package-specific tags
345
345
  ```json
346
346
  {
347
- "synced": true,
347
+ "sync": true,
348
348
  "packageSpecificTags": true,
349
349
  "tagTemplate": "${packageName}@${prefix}${version}"
350
350
  }
@@ -397,11 +397,11 @@ For global commit messages, use templates without `${packageName}`:
397
397
 
398
398
  ## Monorepo Versioning Modes
399
399
 
400
- While primarily used for single packages now, `package-versioner` retains options for monorepo workflows, controlled mainly by the `synced` flag in `version.config.json`.
400
+ While primarily used for single packages now, `package-versioner` retains options for monorepo workflows, controlled mainly by the `sync` flag in `version.config.json`.
401
401
 
402
- ### Synced Mode (`synced: true`)
402
+ ### Sync Mode (`sync: true`)
403
403
 
404
- This is the default if the `synced` flag is present and true.
404
+ This is the default if the `sync` flag is present and true.
405
405
 
406
406
  - **Behaviour:** The tool calculates **one** version bump based on the overall history (or branch pattern). This single new version is applied to **all** packages within the repository (or just the root `package.json` if not a structured monorepo). A single Git tag is created.
407
407
  - **Tag Behaviour:**
@@ -409,7 +409,7 @@ This is the default if the `synced` flag is present and true.
409
409
  - In **single-package repositories**: Respects the `packageSpecificTags` setting - can create either `v1.2.3` or `package-name@v1.2.3`
410
410
  - **Use Case:** Suitable for monorepos where all packages are tightly coupled and released together with the same version number. Also the effective mode for single-package repositories.
411
411
 
412
- ### Async Mode (`synced: false`)
412
+ ### Async Mode (`sync: false`)
413
413
 
414
414
  *(Note: This mode relies heavily on monorepo tooling and structure, like `pnpm workspaces` and correctly configured package dependencies.)*
415
415
 
@@ -41,7 +41,7 @@
41
41
  "description": "The main branch for versioning",
42
42
  "default": "main"
43
43
  },
44
- "synced": {
44
+ "sync": {
45
45
  "type": "boolean",
46
46
  "default": false,
47
47
  "description": "Whether packages should be versioned together"
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.8.6",
4
+ "version": "0.9.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",