fork-version 3.0.2 → 3.1.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Fork Version
2
2
 
3
+ ## [3.1.4](https://github.com/eglavin/fork-version/compare/v3.1.3...v3.1.4) (2026-01-04)
4
+
5
+
6
+ ### Refactor
7
+
8
+ * escape tag prefix before use in regex ([061a1bb](https://github.com/eglavin/fork-version/commit/061a1bbbe85d3759e5f20e26190d8b6bf50daf0c))
9
+
10
+
11
+ ## [3.1.3](https://github.com/eglavin/fork-version/compare/v3.1.2...v3.1.3) (2026-01-04)
12
+
13
+
14
+ ### Refactor
15
+
16
+ * add ref names and tags to commit parser ([8550e66](https://github.com/eglavin/fork-version/commit/8550e664f9c6f51438b6a817b357b8eda639b0a1))
17
+
18
+
19
+ ## [3.1.2](https://github.com/eglavin/fork-version/compare/v3.1.1...v3.1.2) (2025-10-06)
20
+
21
+
22
+ ## [3.1.1](https://github.com/eglavin/fork-version/compare/v3.1.0...v3.1.1) (2025-10-06)
23
+
24
+
25
+ ## [3.1.0](https://github.com/eglavin/fork-version/compare/v3.0.2...v3.1.0) (2025-10-05)
26
+
27
+
28
+ ### Features
29
+
30
+ * implement new command flow for inspect-* commands ([d89e4e0](https://github.com/eglavin/fork-version/commit/d89e4e07803180c7b79847ed4a5e1241ee19074b))
31
+
32
+
3
33
  ## [3.0.2](https://github.com/eglavin/fork-version/compare/v3.0.1...v3.0.2) (2025-10-02)
4
34
 
5
35
 
package/README.md CHANGED
@@ -87,6 +87,17 @@ You can then add the following entry to your package.json scripts section and us
87
87
 
88
88
  For example if you use npm you can now use `npm run release` to run Fork-Version.
89
89
 
90
+ ### Commands
91
+
92
+ Fork-Version has a number of command modes which will make the program behave differently. The default "command" is the `main` mode, this mode will be used when no other command is defined.
93
+
94
+ | Command | Description |
95
+ | ------------------- | ---------------------------------------------------------------------- |
96
+ | `main` | Bumps the version, update files, generate changelog, commits, and tag. |
97
+ | `inspect-version` | Prints the current version and exit. |
98
+ | `inspect-tag` | Prints the current git tag and exit. |
99
+ | `validate-config` | Validates the configuration and exit. |
100
+
90
101
  ### Exit Codes
91
102
 
92
103
  When ran as a cli tool Fork-Version will exit with one of the following exit codes:
@@ -95,6 +106,7 @@ When ran as a cli tool Fork-Version will exit with one of the following exit cod
95
106
  | --------- | ---------------------------- |
96
107
  | 0 | Success |
97
108
  | 1 | General Error |
109
+ | 2 | Unknown Command |
98
110
  | 3 | Config File Validation Error |
99
111
 
100
112
  ### Command Line Options
@@ -105,17 +117,24 @@ The following help text can be viewed by running the following command: `npx for
105
117
 
106
118
  ```text
107
119
  Usage:
108
- $ fork-version [options]
120
+ $ fork-version [command?] [options?]
109
121
 
110
122
  Commands:
111
- --help Show this help message.
112
- --version Show the current version of Fork-Version.
113
- --inspect-version If set, Fork-Version will print the current project version and exit.
123
+ main Bumps the version, update files, generate changelog, commit, and tag. [Default when no command is provided]
124
+ inspect-version Prints the current version and exits.
125
+ inspect-tag Prints the current git tag and exits.
126
+ validate-config Validates the configuration and exits.
114
127
 
115
- Options:
128
+ General Options:
129
+ --version Show the current version of Fork-Version and exit.
130
+ --help Show this help message and exit.
131
+
132
+ Location Options:
116
133
  --file, -F List of the files to be updated. [Default: ["bower.json", "deno.json", "deno.jsonc", "jsr.json", "jsr.jsonc", "manifest.json", "npm-shrinkwrap.json", "package-lock.json", "package.json"]]
117
134
  --glob, -G Glob pattern to match files to be updated.
118
135
  --path, -P The path Fork-Version will run from. [Default: process.cwd()]
136
+
137
+ Options:
119
138
  --changelog Name of the changelog file. [Default: "CHANGELOG.md"]
120
139
  --header The header text for the changelog.
121
140
  --tag-prefix Specify a prefix for the created tag. [Default: "v"]
@@ -155,6 +174,7 @@ Conventional Changelog Overrides:
155
174
  Exit Codes:
156
175
  0: Success
157
176
  1: General Error
177
+ 2: Unknown Command
158
178
  3: Config File Validation Error
159
179
 
160
180
  Examples:
@@ -169,6 +189,9 @@ Examples:
169
189
 
170
190
  $ fork-version --glob "*/package.json"
171
191
  Run fork-version and update all "package.json" files in subdirectories.
192
+
193
+ $ fork-version inspect-version
194
+ Prints the current version and exits.
172
195
  ```
173
196
 
174
197
  <!-- END COMMAND LINE OPTIONS -->
@@ -268,7 +291,7 @@ Alternatively you can define your config using a key in your `package.json` file
268
291
 
269
292
  | Property | Type | Default | Description |
270
293
  | :---------------------------------------------------- | :--------------- | :---------------------- | :------------------------------------------------------------------------------------------------------------------ |
271
- | inspectVersion | boolean | - | Print the current version and exits |
294
+ | command | string | `main` | The command to run. Can be one of: main, inspect-version, inspect-tag, validate-config. Defaults to main. |
272
295
  | [files](#configfiles) | Array\<string> | `["package.json", ...]` | List of the files to be updated |
273
296
  | [glob](#configglob) | string | - | Glob pattern to match files to be updated |
274
297
  | path | string | `process.cwd()` | The path Fork-Version will run from |
@@ -101,11 +101,26 @@ var ChangelogPresetConfigSchema = zod.z.object({
101
101
  var ForkConfigSchema = zod.z.object({
102
102
  // Commands
103
103
  //
104
+ /**
105
+ * The command to run, can be one of the following:
106
+ *
107
+ * - `main` - Bumps the version, update files, generate changelog, commit, and tag.
108
+ * - `inspect-version` - Prints the current version and exits.
109
+ * - `inspect-tag` - Prints the current git tag and exits.
110
+ * - `validate-config` - Validates the configuration and exits.
111
+ *
112
+ * @default "main"
113
+ */
114
+ command: zod.z.literal(["main", "inspect-version", "inspect-tag", "validate-config"]).describe(
115
+ "The command to run. Can be one of: main, inspect-version, inspect-tag, validate-config. Defaults to main."
116
+ ),
104
117
  /**
105
118
  * If set, Fork-Version will print the current version and exit.
106
119
  * @default false
120
+ *
121
+ * @deprecated Set the `inspect-version` command instead.
107
122
  */
108
- inspectVersion: zod.z.boolean().describe("If set, Fork-Version will print the current version and exit."),
123
+ inspectVersion: zod.z.boolean().optional().describe("If set, Fork-Version will print the current version and exit."),
109
124
  // Options
110
125
  //
111
126
  /**
@@ -294,6 +309,13 @@ var ForkConfigSchema = zod.z.object({
294
309
  */
295
310
  releaseMessageSuffix: zod.z.string().optional().describe("Add a suffix to the release commit message.")
296
311
  });
312
+
313
+ // src/utils/escape-regex.ts
314
+ function escapeRegex(input) {
315
+ return input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
316
+ }
317
+
318
+ // src/services/git.ts
297
319
  var Git = class {
298
320
  constructor(config) {
299
321
  this.config = config;
@@ -474,12 +496,13 @@ var Git = class {
474
496
  const logOutput = await this.log("--decorate", "--no-color", "--date-order");
475
497
  const TAG_REGEX = /tag:\s*(?<tag>.+?)[,)]/gi;
476
498
  const tags = [];
499
+ const escapedTagPrefix = tagPrefix ? escapeRegex(tagPrefix) : void 0;
477
500
  let tagMatch = null;
478
501
  while (tagMatch = TAG_REGEX.exec(logOutput)) {
479
502
  const { tag = "" } = tagMatch.groups ?? {};
480
503
  if (tagPrefix) {
481
504
  if (tag.startsWith(tagPrefix)) {
482
- const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
505
+ const tagWithoutPrefix = tag.replace(new RegExp(`^${escapedTagPrefix}`), "");
483
506
  if (semver__default.default.valid(tagWithoutPrefix)) {
484
507
  tags.push(tag);
485
508
  }
@@ -512,9 +535,10 @@ var Git = class {
512
535
  */
513
536
  async getCleanedTags(tagPrefix) {
514
537
  const tags = await this.getTags(tagPrefix);
538
+ const escapedTagPrefix = tagPrefix ? escapeRegex(tagPrefix) : void 0;
515
539
  const cleanedTags = [];
516
540
  for (const tag of tags) {
517
- const tagWithoutPrefix = tag.replace(new RegExp(`^${tagPrefix}`), "");
541
+ const tagWithoutPrefix = tag.replace(new RegExp(`^${escapedTagPrefix}`), "");
518
542
  const cleanedTag = semver__default.default.clean(tagWithoutPrefix);
519
543
  if (cleanedTag) {
520
544
  cleanedTags.push(cleanedTag);
@@ -562,6 +586,8 @@ var Git = class {
562
586
  // body
563
587
  "%H",
564
588
  // hash
589
+ "%d",
590
+ // ref names
565
591
  "%cI",
566
592
  // committer date
567
593
  "%cN",
@@ -656,7 +682,7 @@ function getChangelogPresetConfig(mergedConfig, cliArguments, detectedGitHost) {
656
682
  // src/config/defaults.ts
657
683
  var DEFAULT_CONFIG = {
658
684
  // Commands
659
- inspectVersion: false,
685
+ command: "main",
660
686
  // Options
661
687
  files: [
662
688
  "package.json",
@@ -792,12 +818,12 @@ function mergeFiles(configFiles, cliFiles, globResults) {
792
818
 
793
819
  // src/config/user-config.ts
794
820
  async function getUserConfig(cliArguments) {
795
- const cwd = cliArguments.path ? path.resolve(cliArguments.path) : process.cwd();
821
+ const cwd = cliArguments.flags.path ? path.resolve(cliArguments.flags.path) : process.cwd();
796
822
  const configFile = await loadConfigFile(cwd);
797
823
  const mergedConfig = {
798
824
  ...DEFAULT_CONFIG,
799
825
  ...configFile,
800
- ...cliArguments
826
+ ...cliArguments.flags
801
827
  };
802
828
  let globResults = [];
803
829
  if (mergedConfig.glob) {
@@ -807,21 +833,33 @@ async function getUserConfig(cliArguments) {
807
833
  nodir: true
808
834
  });
809
835
  }
810
- const files = mergeFiles(configFile?.files, cliArguments?.files, globResults);
836
+ const files = mergeFiles(configFile?.files, cliArguments.flags.files, globResults);
811
837
  const detectedGitHost = await detectGitHost(cwd);
812
838
  const changelogPresetConfig = getChangelogPresetConfig(
813
839
  mergedConfig,
814
- cliArguments,
840
+ cliArguments.flags,
815
841
  detectedGitHost
816
842
  );
843
+ let command = DEFAULT_CONFIG.command;
844
+ if (cliArguments.input.length > 0 && cliArguments.input[0].trim()) {
845
+ command = cliArguments.input[0].trim().toLowerCase();
846
+ } else if (mergedConfig.command.trim()) {
847
+ command = mergedConfig.command.trim().toLowerCase();
848
+ }
849
+ if (mergedConfig.inspectVersion) {
850
+ command = "inspect-version";
851
+ }
852
+ const shouldBeSilent = ![DEFAULT_CONFIG.command].includes(command);
817
853
  return {
818
854
  ...mergedConfig,
855
+ command,
819
856
  files,
820
857
  path: cwd,
821
858
  preRelease: (
822
859
  // Meow doesn't support multiple flags with the same name, so we need to check both.
823
- cliArguments.preReleaseTag ?? cliArguments.preRelease ?? configFile.preRelease
860
+ cliArguments.flags.preReleaseTag ?? cliArguments.flags.preRelease ?? configFile.preRelease
824
861
  ),
862
+ silent: shouldBeSilent || mergedConfig.silent,
825
863
  changelogPresetConfig
826
864
  };
827
865
  }
@@ -834,7 +872,7 @@ var Logger = class {
834
872
  this.warn = this.warn.bind(this);
835
873
  this.error = this.error.bind(this);
836
874
  this.debug = this.debug.bind(this);
837
- this.disableLogs = this.config.silent || this.config.inspectVersion;
875
+ this.disableLogs = this.config.silent;
838
876
  }
839
877
  disableLogs = false;
840
878
  log(...messages) {
@@ -1170,6 +1208,76 @@ var FileManager = class {
1170
1208
  }
1171
1209
  };
1172
1210
 
1211
+ // src/commands/validate-config.ts
1212
+ function validateConfig(config) {
1213
+ console.log(`
1214
+ \u2699\uFE0F Configuration:
1215
+ ${JSON.stringify(config, null, 2)}
1216
+
1217
+ \u2705 Configuration is valid.
1218
+ `);
1219
+ }
1220
+ async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate) {
1221
+ const files = [];
1222
+ const versions = /* @__PURE__ */ new Set();
1223
+ for (const file of filesToUpdate) {
1224
+ if (await git.isIgnored(file)) {
1225
+ logger.debug(`[Git Ignored] ${file}`);
1226
+ continue;
1227
+ }
1228
+ const fileState = fileManager.read(file);
1229
+ if (fileState) {
1230
+ files.push(fileState);
1231
+ if (!config.currentVersion) {
1232
+ versions.add(fileState.version);
1233
+ }
1234
+ }
1235
+ }
1236
+ if (config.currentVersion) {
1237
+ versions.add(config.currentVersion);
1238
+ }
1239
+ if (versions.size === 0 && config.gitTagFallback) {
1240
+ const version = await git.getHighestSemverVersionFromTags(config.tagPrefix);
1241
+ if (version) {
1242
+ logger.warn(`Using latest git tag as fallback`);
1243
+ versions.add(version);
1244
+ }
1245
+ }
1246
+ if (versions.size === 0) {
1247
+ throw new Error("Unable to find current version");
1248
+ } else if (versions.size > 1) {
1249
+ if (!config.allowMultipleVersions) {
1250
+ throw new Error("Found multiple versions");
1251
+ }
1252
+ logger.warn(
1253
+ `Found multiple versions (${Array.from(versions).join(", ")}), using the higher semver version`
1254
+ );
1255
+ }
1256
+ const currentVersion = semver__default.default.rsort(Array.from(versions))[0];
1257
+ logger.log(`Current version: ${currentVersion}`);
1258
+ return {
1259
+ files,
1260
+ version: currentVersion
1261
+ };
1262
+ }
1263
+
1264
+ // src/commands/inspect-version.ts
1265
+ async function inspectVersion(config, logger, fileManager, git) {
1266
+ let foundVersion = "";
1267
+ try {
1268
+ const currentVersion = await getCurrentVersion(config, logger, git, fileManager, config.files);
1269
+ if (currentVersion) foundVersion = currentVersion.version;
1270
+ } catch {
1271
+ }
1272
+ console.log(foundVersion);
1273
+ }
1274
+
1275
+ // src/commands/inspect-tag.ts
1276
+ async function inspectTag(config, git) {
1277
+ const tag = await git.getMostRecentTag(config.tagPrefix);
1278
+ console.log(tag ?? "");
1279
+ }
1280
+
1173
1281
  // src/utils/trim-string-array.ts
1174
1282
  function trimStringArray(array) {
1175
1283
  const items = [];
@@ -1268,6 +1376,7 @@ var CommitParser = class {
1268
1376
  subject: "",
1269
1377
  body: "",
1270
1378
  hash: "",
1379
+ refNames: "",
1271
1380
  date: "",
1272
1381
  name: "",
1273
1382
  email: "",
@@ -1279,7 +1388,8 @@ var CommitParser = class {
1279
1388
  revert: null,
1280
1389
  notes: [],
1281
1390
  mentions: [],
1282
- references: []
1391
+ references: [],
1392
+ tags: []
1283
1393
  };
1284
1394
  }
1285
1395
  /**
@@ -1302,6 +1412,7 @@ var CommitParser = class {
1302
1412
  const email = parts.pop();
1303
1413
  const name = parts.pop();
1304
1414
  const date = parts.pop();
1415
+ const refNames = parts.pop();
1305
1416
  const hash = parts.pop();
1306
1417
  if (email) parsedCommit.email = email.trim();
1307
1418
  if (name) parsedCommit.name = name.trim();
@@ -1311,6 +1422,17 @@ var CommitParser = class {
1311
1422
  throw new ParserError("Unable to parse commit date", rawCommit);
1312
1423
  }
1313
1424
  }
1425
+ if (refNames) {
1426
+ parsedCommit.refNames = refNames.trim();
1427
+ const TAG_REGEX = /tag:\s*(?<tag>.+?)[,)]/gi;
1428
+ let tagMatch = null;
1429
+ while (tagMatch = TAG_REGEX.exec(refNames)) {
1430
+ const { tag = "" } = tagMatch.groups ?? {};
1431
+ if (tag) {
1432
+ parsedCommit.tags.push(tag);
1433
+ }
1434
+ }
1435
+ }
1314
1436
  if (hash) parsedCommit.hash = hash.trim();
1315
1437
  const subject = parts.shift()?.trimStart();
1316
1438
  if (subject) {
@@ -1644,53 +1766,6 @@ async function getCommitsSinceTag(config, logger, git) {
1644
1766
  commits: filteredCommits
1645
1767
  };
1646
1768
  }
1647
- async function getCurrentVersion(config, logger, git, fileManager, filesToUpdate) {
1648
- const files = [];
1649
- const versions = /* @__PURE__ */ new Set();
1650
- for (const file of filesToUpdate) {
1651
- if (await git.isIgnored(file)) {
1652
- logger.debug(`[Git Ignored] ${file}`);
1653
- continue;
1654
- }
1655
- const fileState = fileManager.read(file);
1656
- if (fileState) {
1657
- files.push(fileState);
1658
- if (!config.currentVersion) {
1659
- versions.add(fileState.version);
1660
- }
1661
- }
1662
- }
1663
- if (config.currentVersion) {
1664
- versions.add(config.currentVersion);
1665
- }
1666
- if (versions.size === 0 && config.gitTagFallback) {
1667
- const version = await git.getHighestSemverVersionFromTags(config.tagPrefix);
1668
- if (version) {
1669
- logger.warn(`Using latest git tag as fallback`);
1670
- versions.add(version);
1671
- }
1672
- }
1673
- if (versions.size === 0) {
1674
- throw new Error("Unable to find current version");
1675
- } else if (versions.size > 1) {
1676
- if (!config.allowMultipleVersions) {
1677
- throw new Error("Found multiple versions");
1678
- }
1679
- logger.warn(
1680
- `Found multiple versions (${Array.from(versions).join(", ")}), using the higher semver version`
1681
- );
1682
- }
1683
- const currentVersion = semver__default.default.rsort(Array.from(versions))[0];
1684
- if (config.inspectVersion) {
1685
- console.log(currentVersion);
1686
- process.exit(0);
1687
- }
1688
- logger.log(`Current version: ${currentVersion}`);
1689
- return {
1690
- files,
1691
- version: currentVersion
1692
- };
1693
- }
1694
1769
  function getPriority(type) {
1695
1770
  return ["patch", "minor", "major"].indexOf(type ?? "");
1696
1771
  }
@@ -1922,6 +1997,29 @@ async function tagChanges(config, logger, git, nextVersion) {
1922
1997
  );
1923
1998
  }
1924
1999
 
2000
+ // src/commands/main.ts
2001
+ async function main(config, logger, fileManager, git) {
2002
+ logger.log(`Running fork-version - ${(/* @__PURE__ */ new Date()).toUTCString()}`);
2003
+ logger.warn(config.dryRun ? "[Dry Run] No changes will be written to disk.\n" : "");
2004
+ const commits = await getCommitsSinceTag(config, logger, git);
2005
+ const current = await getCurrentVersion(config, logger, git, fileManager, config.files);
2006
+ const next = await getNextVersion(config, logger, commits.commits, current.version);
2007
+ logger.log("Updating files: ");
2008
+ for (const outFile of current.files) {
2009
+ logger.log(` - ${outFile.path}`);
2010
+ fileManager.write(outFile, next.version);
2011
+ }
2012
+ await updateChangelog(config, logger, next.version);
2013
+ await commitChanges(config, logger, git, current.files, next.version);
2014
+ await tagChanges(config, logger, git, next.version);
2015
+ return {
2016
+ config,
2017
+ commits,
2018
+ current,
2019
+ next
2020
+ };
2021
+ }
2022
+
1925
2023
  exports.CommitParser = CommitParser;
1926
2024
  exports.FileManager = FileManager;
1927
2025
  exports.ForkConfigSchema = ForkConfigSchema;
@@ -1934,7 +2032,11 @@ exports.getCommitsSinceTag = getCommitsSinceTag;
1934
2032
  exports.getCurrentVersion = getCurrentVersion;
1935
2033
  exports.getNextVersion = getNextVersion;
1936
2034
  exports.getUserConfig = getUserConfig;
2035
+ exports.inspectTag = inspectTag;
2036
+ exports.inspectVersion = inspectVersion;
2037
+ exports.main = main;
1937
2038
  exports.tagChanges = tagChanges;
1938
2039
  exports.updateChangelog = updateChangelog;
1939
- //# sourceMappingURL=chunk-YSWJMT7B.cjs.map
1940
- //# sourceMappingURL=chunk-YSWJMT7B.cjs.map
2040
+ exports.validateConfig = validateConfig;
2041
+ //# sourceMappingURL=chunk-2VYOEMMB.cjs.map
2042
+ //# sourceMappingURL=chunk-2VYOEMMB.cjs.map