versionary 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,39 @@ const node_child_process_1 = require("node:child_process");
11
11
  const node_fs_1 = __importDefault(require("node:fs"));
12
12
  const node_path_1 = __importDefault(require("node:path"));
13
13
  const load_config_js_1 = require("../../config/load-config.js");
14
+ function parseStateFile(raw, filePath) {
15
+ const parsed = JSON.parse(raw);
16
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
17
+ throw new Error(`Invalid release manifest at ${filePath}: expected an object.`);
18
+ }
19
+ const manifest = parsed;
20
+ if (manifest.manifestVersion !== undefined &&
21
+ manifest.manifestVersion !== 1) {
22
+ throw new Error(`Unsupported manifestVersion in ${filePath}: ${String(manifest.manifestVersion)}.`);
23
+ }
24
+ if (manifest.baselineSha !== undefined &&
25
+ typeof manifest.baselineSha !== "string") {
26
+ throw new Error(`Invalid release manifest at ${filePath}: baselineSha must be a string.`);
27
+ }
28
+ if (manifest.releaseTargets !== undefined &&
29
+ !Array.isArray(manifest.releaseTargets)) {
30
+ throw new Error(`Invalid release manifest at ${filePath}: releaseTargets must be an array.`);
31
+ }
32
+ if (Array.isArray(manifest.releaseTargets)) {
33
+ for (const target of manifest.releaseTargets) {
34
+ if (!target || typeof target !== "object" || Array.isArray(target)) {
35
+ throw new Error(`Invalid release manifest at ${filePath}: each release target must be an object.`);
36
+ }
37
+ const record = target;
38
+ if (typeof record.path !== "string" ||
39
+ typeof record.version !== "string" ||
40
+ typeof record.tag !== "string") {
41
+ throw new Error(`Invalid release manifest at ${filePath}: releaseTargets must contain string path, version, and tag.`);
42
+ }
43
+ }
44
+ }
45
+ return manifest;
46
+ }
14
47
  function getBaselineStatePath(cwd) {
15
48
  const loaded = (0, load_config_js_1.loadConfig)(cwd);
16
49
  const configured = loaded.config["baseline-file"];
@@ -32,7 +65,7 @@ function readBaselineSha(cwd = process.cwd()) {
32
65
  if (!node_fs_1.default.existsSync(filePath)) {
33
66
  return null;
34
67
  }
35
- const parsed = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
68
+ const parsed = parseStateFile(node_fs_1.default.readFileSync(filePath, "utf8"), filePath);
36
69
  return parsed.baselineSha ?? null;
37
70
  }
38
71
  function readReleaseTargets(cwd = process.cwd()) {
@@ -40,7 +73,7 @@ function readReleaseTargets(cwd = process.cwd()) {
40
73
  if (!node_fs_1.default.existsSync(filePath)) {
41
74
  return [];
42
75
  }
43
- const parsed = JSON.parse(node_fs_1.default.readFileSync(filePath, "utf8"));
76
+ const parsed = parseStateFile(node_fs_1.default.readFileSync(filePath, "utf8"), filePath);
44
77
  return parsed.releaseTargets ?? [];
45
78
  }
46
79
  function writeBaselineSha(cwd = process.cwd(), sha, releaseTargets = []) {
@@ -52,6 +85,7 @@ function writeBaselineSha(cwd = process.cwd(), sha, releaseTargets = []) {
52
85
  }).trim();
53
86
  const filePath = getBaselineStatePath(cwd);
54
87
  const next = {
88
+ manifestVersion: 1,
55
89
  baselineSha,
56
90
  releaseTargets,
57
91
  };
package/dist/cli/index.js CHANGED
@@ -20,27 +20,81 @@ function printVerifyResult() {
20
20
  }
21
21
  return result.ok ? 0 : 1;
22
22
  }
23
+ function parseFlags(args) {
24
+ return {
25
+ json: args.includes("--json"),
26
+ };
27
+ }
28
+ function emitJson(payload) {
29
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
30
+ }
23
31
  async function main() {
24
32
  const [, , command, ...args] = process.argv;
33
+ const flags = parseFlags(args);
34
+ const logger = flags.json ? undefined : console;
25
35
  if (!command || command === "run") {
26
36
  const subject = (0, node_child_process_1.execFileSync)("git", ["log", "-1", "--pretty=%s"], {
27
37
  encoding: "utf8",
28
38
  stdio: ["ignore", "pipe", "ignore"],
29
39
  }).trim();
30
40
  if ((0, pr_js_1.isReleaseCommitMessage)(subject)) {
41
+ if (flags.json) {
42
+ const release = await (0, release_js_1.runSimpleReleaseDetailed)(process.cwd(), {
43
+ logger,
44
+ });
45
+ if (release.action === "release-skipped") {
46
+ emitJson({
47
+ action: "release-skipped",
48
+ message: release.reason,
49
+ releaseCreated: false,
50
+ tagNames: [],
51
+ });
52
+ return 0;
53
+ }
54
+ emitJson({
55
+ action: "release-published",
56
+ message: release.message,
57
+ releaseCreated: release.releases.length > 0,
58
+ tagNames: release.releases.map((target) => target.tag),
59
+ });
60
+ return 0;
61
+ }
31
62
  const message = await (0, release_js_1.runSimpleRelease)(process.cwd());
32
63
  console.log(message);
33
64
  return 0;
34
65
  }
35
66
  const plan = (0, plan_js_1.createSimplePlan)();
36
67
  if (!plan.nextVersion) {
37
- console.log("No releasable commits found. Nothing to do.");
68
+ const message = "No releasable commits found. Nothing to do.";
69
+ if (flags.json) {
70
+ emitJson({
71
+ action: "noop",
72
+ message,
73
+ releaseCreated: false,
74
+ tagNames: [],
75
+ });
76
+ return 0;
77
+ }
78
+ console.log(message);
38
79
  return 0;
39
80
  }
40
- const pr = (0, pr_js_1.prepareSimpleReleasePr)();
81
+ const pr = (0, pr_js_1.prepareSimpleReleasePr)(process.cwd(), { logger });
41
82
  (0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
42
- const reviewResult = await (0, pr_js_1.openOrUpdateSimpleReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan);
43
- console.log(`Prepared release PR branch ${pr.branch}`);
83
+ const reviewResult = await (0, pr_js_1.openOrUpdateSimpleReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan, { logger });
84
+ const message = `Prepared release PR branch ${pr.branch}`;
85
+ if (flags.json) {
86
+ emitJson({
87
+ action: "pr-prepared",
88
+ message,
89
+ releaseCreated: false,
90
+ tagNames: [],
91
+ reviewUrl: reviewResult,
92
+ branch: pr.branch,
93
+ title: pr.title,
94
+ });
95
+ return 0;
96
+ }
97
+ console.log(message);
44
98
  console.log(`Title: ${pr.title}`);
45
99
  console.log(reviewResult);
46
100
  return 0;
@@ -76,7 +130,7 @@ async function main() {
76
130
  return 0;
77
131
  }
78
132
  if (command === "pr") {
79
- const pr = (0, pr_js_1.prepareSimpleReleasePr)();
133
+ const pr = (0, pr_js_1.prepareSimpleReleasePr)(process.cwd(), { logger: console });
80
134
  (0, pr_js_1.pushReleaseBranch)(process.cwd(), pr.branch);
81
135
  const reviewResult = await (0, pr_js_1.openOrUpdateSimpleReviewRequest)(process.cwd(), pr.branch, pr.title, pr.version, pr.previousVersion, pr.commits, pr.plan);
82
136
  console.log(`Prepared release PR branch ${pr.branch}`);
@@ -91,7 +145,7 @@ async function main() {
91
145
  }
92
146
  console.log("Usage: versionary <command>");
93
147
  console.log("Commands:");
94
- console.log(" run Auto-dispatch release PR/update or release publish by context");
148
+ console.log(" run [--json] Auto-dispatch release PR/update or release publish by context");
95
149
  console.log(" verify Validate config and basic repository shape");
96
150
  console.log(" plan Print release plan (simple mode)");
97
151
  console.log(" changelog [--write] Print or write changelog section");
@@ -2,11 +2,43 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.configSchema = void 0;
4
4
  const zod_1 = require("zod");
5
- const artifactRuleSchema = zod_1.z.object({
5
+ const artifactRuleSchema = zod_1.z
6
+ .object({
6
7
  type: zod_1.z.enum(["json", "toml", "yaml", "regex"]),
7
8
  path: zod_1.z.string().min(1),
8
9
  jsonpath: zod_1.z.string().optional(),
9
10
  pattern: zod_1.z.string().optional(),
11
+ })
12
+ .superRefine((value, ctx) => {
13
+ const needsJsonPath = value.type === "json" || value.type === "toml" || value.type === "yaml";
14
+ if (needsJsonPath && !value.jsonpath) {
15
+ ctx.addIssue({
16
+ code: zod_1.z.ZodIssueCode.custom,
17
+ message: `${value.type} artifact rules require "jsonpath".`,
18
+ path: ["jsonpath"],
19
+ });
20
+ }
21
+ if (needsJsonPath && value.pattern) {
22
+ ctx.addIssue({
23
+ code: zod_1.z.ZodIssueCode.custom,
24
+ message: `${value.type} artifact rules do not support "pattern".`,
25
+ path: ["pattern"],
26
+ });
27
+ }
28
+ if (value.type === "regex" && !value.pattern) {
29
+ ctx.addIssue({
30
+ code: zod_1.z.ZodIssueCode.custom,
31
+ message: 'regex artifact rules require "pattern".',
32
+ path: ["pattern"],
33
+ });
34
+ }
35
+ if (value.type === "regex" && value.jsonpath) {
36
+ ctx.addIssue({
37
+ code: zod_1.z.ZodIssueCode.custom,
38
+ message: 'regex artifact rules do not support "jsonpath".',
39
+ path: ["jsonpath"],
40
+ });
41
+ }
10
42
  });
11
43
  const packageSchema = zod_1.z.object({
12
44
  "release-type": zod_1.z.string().optional(),
@@ -95,7 +95,7 @@ function renderSimpleReleaseNotes(input, options = {}) {
95
95
  }
96
96
  const lines = [header, "", ...sections];
97
97
  if (options.includeFooter) {
98
- lines.push("This PR was generated by Versionary.");
98
+ lines.push("\n---\n\nThis PR was generated by [Versionary](https://github.com/jolars/versionary).");
99
99
  }
100
100
  return lines.join("\n");
101
101
  }
@@ -9,7 +9,9 @@ const node_path_1 = __importDefault(require("node:path"));
9
9
  const state_js_1 = require("../../app/release/state.js");
10
10
  const load_config_js_1 = require("../../config/load-config.js");
11
11
  const commits_js_1 = require("../../infra/git/commits.js");
12
+ const package_context_js_1 = require("../strategy/package-context.js");
12
13
  const resolve_js_1 = require("../strategy/resolve.js");
14
+ const rust_js_1 = require("../strategy/rust.js");
13
15
  const semver_js_1 = require("./semver.js");
14
16
  function getMode(configMode) {
15
17
  return configMode ?? "independent";
@@ -21,11 +23,6 @@ function createSimplePlan(cwd = process.cwd()) {
21
23
  const changelogFile = loaded.config["changelog-file"] ?? "CHANGELOG.md";
22
24
  const releaseBranchPrefix = loaded.config["release-branch"] ?? "versionary/release";
23
25
  const baselineSha = (0, state_js_1.readBaselineSha)(cwd) ?? loaded.config["bootstrap-sha"] ?? null;
24
- const versionPath = node_path_1.default.join(cwd, versionFile);
25
- if (!node_fs_1.default.existsSync(versionPath)) {
26
- throw new Error(`Versionary requires ${versionFile} to exist.`);
27
- }
28
- const currentVersion = strategy.readVersion(cwd, loaded.config);
29
26
  const allowStableMajor = loaded.config["allow-stable-major"] ?? false;
30
27
  const configuredPackages = Object.entries(loaded.config.packages ?? {}).map(([pkgPath, cfg]) => ({
31
28
  path: pkgPath,
@@ -34,6 +31,11 @@ function createSimplePlan(cwd = process.cwd()) {
34
31
  const monorepoMode = getMode(loaded.config["monorepo-mode"]);
35
32
  const hasPackages = configuredPackages.length > 0;
36
33
  if (!hasPackages) {
34
+ const versionPath = node_path_1.default.join(cwd, versionFile);
35
+ if (!node_fs_1.default.existsSync(versionPath)) {
36
+ throw new Error(`Versionary requires ${versionFile} to exist.`);
37
+ }
38
+ const currentVersion = strategy.readVersion(cwd, loaded.config);
37
39
  const parsedCommits = (0, commits_js_1.getParsedCommitsSinceLastTag)(cwd, baselineSha);
38
40
  const effectiveCommits = (0, commits_js_1.applyRevertSuppression)(parsedCommits);
39
41
  const commits = effectiveCommits;
@@ -55,29 +57,70 @@ function createSimplePlan(cwd = process.cwd()) {
55
57
  }
56
58
  const packagePlans = configuredPackages
57
59
  .map((pkg) => {
60
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, pkg.path, pkg);
61
+ const packageCurrentVersion = packageContext.strategy.readVersion(cwd, packageContext.config);
58
62
  const parsedCommits = (0, commits_js_1.getParsedCommitsForPath)(cwd, baselineSha, pkg.path, pkg["exclude-paths"] ?? []);
59
63
  const effectiveCommits = (0, commits_js_1.applyRevertSuppression)(parsedCommits);
60
64
  const commits = effectiveCommits;
61
65
  const releaseType = (0, commits_js_1.analyzeParsedCommits)(parsedCommits);
62
66
  const nextVersion = releaseType
63
- ? (0, semver_js_1.bumpVersion)(currentVersion, releaseType, { allowStableMajor })
67
+ ? (0, semver_js_1.bumpVersion)(packageCurrentVersion, releaseType, { allowStableMajor })
64
68
  : null;
65
69
  return {
66
70
  path: pkg.path,
67
71
  releaseType,
68
- currentVersion,
72
+ currentVersion: packageCurrentVersion,
69
73
  nextVersion,
70
74
  commits,
71
75
  parsedCommits,
72
76
  };
73
77
  })
74
78
  .sort((a, b) => a.path.localeCompare(b.path));
79
+ const rustManifestVersionTargets = {};
80
+ const rustPackageManifestByPath = {};
81
+ const packageCurrentVersionByPath = {};
82
+ for (const packagePlan of packagePlans) {
83
+ const packageConfig = loaded.config.packages?.[packagePlan.path] ?? {};
84
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, packagePlan.path, packageConfig);
85
+ if (packageContext.strategy.name === rust_js_1.rustVersionStrategy.name) {
86
+ rustPackageManifestByPath[packagePlan.path] = (0, rust_js_1.toCargoManifestPath)(packagePlan.path);
87
+ }
88
+ packageCurrentVersionByPath[packagePlan.path] = packagePlan.currentVersion;
89
+ if (packageContext.strategy.name === rust_js_1.rustVersionStrategy.name) {
90
+ const next = packagePlan.nextVersion;
91
+ if (next) {
92
+ rustManifestVersionTargets[packageContext.versionFile] = next;
93
+ }
94
+ }
95
+ }
96
+ const impactedRustManifests = (0, rust_js_1.detectRustDependencyImpact)(cwd, rustManifestVersionTargets, Object.values(rustPackageManifestByPath));
97
+ const impactedPaths = new Set();
98
+ for (const [pkgPath, manifest] of Object.entries(rustPackageManifestByPath)) {
99
+ if (impactedRustManifests.includes(manifest)) {
100
+ impactedPaths.add(pkgPath);
101
+ }
102
+ }
103
+ const adjustedPackages = packagePlans.map((pkgPlan) => {
104
+ if (pkgPlan.nextVersion || !impactedPaths.has(pkgPlan.path)) {
105
+ return pkgPlan;
106
+ }
107
+ const current = packageCurrentVersionByPath[pkgPlan.path] ?? pkgPlan.currentVersion;
108
+ return {
109
+ ...pkgPlan,
110
+ releaseType: "patch",
111
+ nextVersion: (0, semver_js_1.bumpVersion)(current, "patch", { allowStableMajor }),
112
+ };
113
+ });
75
114
  if (monorepoMode === "fixed") {
76
- const fixedType = (0, commits_js_1.analyzeParsedCommits)(packagePlans.flatMap((pkgPlan) => pkgPlan.parsedCommits));
115
+ const fixedType = (0, commits_js_1.analyzeParsedCommits)(adjustedPackages.flatMap((pkgPlan) => pkgPlan.parsedCommits));
116
+ const fixedBaseVersion = adjustedPackages.find((pkgPlan) => pkgPlan.path === ".")
117
+ ?.currentVersion ??
118
+ adjustedPackages[0]?.currentVersion ??
119
+ "0.0.0";
77
120
  const fixedNextVersion = fixedType
78
- ? (0, semver_js_1.bumpVersion)(currentVersion, fixedType, { allowStableMajor })
121
+ ? (0, semver_js_1.bumpVersion)(fixedBaseVersion, fixedType, { allowStableMajor })
79
122
  : null;
80
- const adjusted = packagePlans.map((pkgPlan) => ({
123
+ const adjusted = adjustedPackages.map((pkgPlan) => ({
81
124
  ...pkgPlan,
82
125
  releaseType: fixedType,
83
126
  nextVersion: fixedNextVersion,
@@ -85,7 +128,7 @@ function createSimplePlan(cwd = process.cwd()) {
85
128
  return {
86
129
  mode: "simple",
87
130
  releaseType: fixedType,
88
- currentVersion,
131
+ currentVersion: fixedBaseVersion,
89
132
  nextVersion: fixedNextVersion,
90
133
  versionFile,
91
134
  changelogFile,
@@ -95,20 +138,23 @@ function createSimplePlan(cwd = process.cwd()) {
95
138
  packages: adjusted,
96
139
  };
97
140
  }
98
- const overallType = (0, commits_js_1.analyzeParsedCommits)(packagePlans.flatMap((pkgPlan) => pkgPlan.parsedCommits));
141
+ const overallType = (0, commits_js_1.analyzeParsedCommits)(adjustedPackages.flatMap((pkgPlan) => pkgPlan.parsedCommits));
142
+ const overallBaseVersion = adjustedPackages.find((pkgPlan) => pkgPlan.path === ".")?.currentVersion ??
143
+ adjustedPackages[0]?.currentVersion ??
144
+ "0.0.0";
99
145
  const overallNextVersion = overallType
100
- ? (0, semver_js_1.bumpVersion)(currentVersion, overallType, { allowStableMajor })
146
+ ? (0, semver_js_1.bumpVersion)(overallBaseVersion, overallType, { allowStableMajor })
101
147
  : null;
102
148
  return {
103
149
  mode: "simple",
104
150
  releaseType: overallType,
105
- currentVersion,
151
+ currentVersion: overallBaseVersion,
106
152
  nextVersion: overallNextVersion,
107
153
  versionFile,
108
154
  changelogFile,
109
155
  releaseBranchPrefix,
110
156
  baselineSha,
111
- commits: packagePlans.flatMap((pkgPlan) => pkgPlan.commits),
112
- packages: packagePlans,
157
+ commits: adjustedPackages.flatMap((pkgPlan) => pkgPlan.commits),
158
+ packages: adjustedPackages,
113
159
  };
114
160
  }
@@ -6,10 +6,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.nodeVersionStrategy = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ function readJsonFile(targetPath) {
10
+ return JSON.parse(node_fs_1.default.readFileSync(targetPath, "utf8"));
11
+ }
12
+ function writeJsonFile(targetPath, value) {
13
+ node_fs_1.default.writeFileSync(targetPath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
14
+ }
15
+ function updateNodeLockfileVersion(cwd, version) {
16
+ const updated = [];
17
+ for (const lockfile of ["package-lock.json", "npm-shrinkwrap.json"]) {
18
+ const lockfilePath = node_path_1.default.join(cwd, lockfile);
19
+ if (!node_fs_1.default.existsSync(lockfilePath)) {
20
+ continue;
21
+ }
22
+ const parsed = readJsonFile(lockfilePath);
23
+ parsed.version = version;
24
+ if (parsed.packages?.[""]) {
25
+ parsed.packages[""].version = version;
26
+ }
27
+ writeJsonFile(lockfilePath, parsed);
28
+ updated.push(lockfile);
29
+ }
30
+ return updated;
31
+ }
9
32
  exports.nodeVersionStrategy = {
10
33
  name: "node",
11
34
  getVersionFile(config) {
12
- return config["version-file"] ?? "version.txt";
35
+ return config["version-file"] ?? "package.json";
13
36
  },
14
37
  readVersion(cwd, config) {
15
38
  const versionFile = this.getVersionFile(config);
@@ -17,21 +40,28 @@ exports.nodeVersionStrategy = {
17
40
  if (!node_fs_1.default.existsSync(versionPath)) {
18
41
  throw new Error(`Versionary requires ${versionFile} to exist.`);
19
42
  }
20
- return node_fs_1.default.readFileSync(versionPath, "utf8").trim();
43
+ const packageJson = readJsonFile(versionPath);
44
+ if (!packageJson.version || typeof packageJson.version !== "string") {
45
+ throw new Error(`${versionFile} is missing a valid "version" field required by release-type "node".`);
46
+ }
47
+ return packageJson.version.trim();
21
48
  },
22
49
  writeVersion(cwd, config, version) {
23
50
  const versionFile = this.getVersionFile(config);
24
51
  const versionPath = node_path_1.default.join(cwd, versionFile);
25
- node_fs_1.default.writeFileSync(versionPath, `${version}\n`, "utf8");
26
- const updatedFiles = [versionFile];
27
- const packageJsonPath = node_path_1.default.join(cwd, "package.json");
28
- if (node_fs_1.default.existsSync(packageJsonPath)) {
29
- const packageJsonRaw = node_fs_1.default.readFileSync(packageJsonPath, "utf8");
30
- const packageJson = JSON.parse(packageJsonRaw);
31
- packageJson.version = version;
32
- node_fs_1.default.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, "utf8");
33
- updatedFiles.push("package.json");
52
+ if (!node_fs_1.default.existsSync(versionPath)) {
53
+ throw new Error(`Versionary requires ${versionFile} to exist.`);
54
+ }
55
+ const packageJson = readJsonFile(versionPath);
56
+ if (!packageJson.version || typeof packageJson.version !== "string") {
57
+ throw new Error(`${versionFile} is missing a valid "version" field required by release-type "node".`);
34
58
  }
59
+ packageJson.version = version;
60
+ writeJsonFile(versionPath, packageJson);
61
+ const updatedFiles = [
62
+ versionFile,
63
+ ...updateNodeLockfileVersion(cwd, version),
64
+ ];
35
65
  return updatedFiles;
36
66
  },
37
67
  };
@@ -0,0 +1,7 @@
1
+ import type { VersionaryConfig, VersionaryPackage } from "../../types/config.js";
2
+ import type { VersionStrategy } from "./types.js";
3
+ export declare function resolvePackageStrategyContext(rootConfig: VersionaryConfig, packagePath: string, packageConfig: VersionaryPackage): {
4
+ strategy: VersionStrategy;
5
+ config: VersionaryConfig;
6
+ versionFile: string;
7
+ };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolvePackageStrategyContext = resolvePackageStrategyContext;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const resolve_js_1 = require("./resolve.js");
9
+ function withVersionFile(config, versionFile) {
10
+ return {
11
+ ...config,
12
+ "version-file": versionFile,
13
+ };
14
+ }
15
+ function resolvePackageStrategyContext(rootConfig, packagePath, packageConfig) {
16
+ const packageReleaseType = packageConfig["release-type"];
17
+ const baseConfig = packageReleaseType
18
+ ? {
19
+ ...rootConfig,
20
+ "release-type": packageReleaseType,
21
+ }
22
+ : { ...rootConfig };
23
+ const baseStrategy = (0, resolve_js_1.resolveVersionStrategy)(baseConfig);
24
+ if (!packageReleaseType) {
25
+ const versionFile = baseConfig["version-file"] ?? baseStrategy.getVersionFile(baseConfig);
26
+ const config = withVersionFile(baseConfig, versionFile);
27
+ return {
28
+ strategy: baseStrategy,
29
+ config,
30
+ versionFile,
31
+ };
32
+ }
33
+ const packageVersionFile = packagePath === "."
34
+ ? (baseConfig["version-file"] ?? baseStrategy.getVersionFile(baseConfig))
35
+ : node_path_1.default.posix.join(packagePath, baseStrategy.getVersionFile({
36
+ ...baseConfig,
37
+ "version-file": undefined,
38
+ }));
39
+ const config = withVersionFile({
40
+ ...baseConfig,
41
+ packages: undefined,
42
+ }, packageVersionFile);
43
+ const strategy = (0, resolve_js_1.resolveVersionStrategy)(config);
44
+ return {
45
+ strategy,
46
+ config,
47
+ versionFile: packageVersionFile,
48
+ };
49
+ }
@@ -0,0 +1,2 @@
1
+ import type { VersionStrategy } from "./types.js";
2
+ export declare const rVersionStrategy: VersionStrategy;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.rVersionStrategy = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ function readDescriptionVersion(content, versionFile) {
10
+ const match = content.match(/^Version:\s*(.+)\s*$/mu);
11
+ if (!match || !match[1]) {
12
+ throw new Error(`${versionFile} is missing a valid "Version:" field required by release-type "r".`);
13
+ }
14
+ return match[1].trim();
15
+ }
16
+ function writeDescriptionVersion(content, versionFile, version) {
17
+ if (!/^Version:\s*/mu.test(content)) {
18
+ throw new Error(`${versionFile} is missing a valid "Version:" field required by release-type "r".`);
19
+ }
20
+ return content.replace(/^Version:\s*.*$/mu, `Version: ${version}`);
21
+ }
22
+ exports.rVersionStrategy = {
23
+ name: "r",
24
+ getVersionFile(config) {
25
+ return config["version-file"] ?? "DESCRIPTION";
26
+ },
27
+ readVersion(cwd, config) {
28
+ const versionFile = this.getVersionFile(config);
29
+ const versionPath = node_path_1.default.join(cwd, versionFile);
30
+ if (!node_fs_1.default.existsSync(versionPath)) {
31
+ throw new Error(`Versionary requires ${versionFile} to exist.`);
32
+ }
33
+ return readDescriptionVersion(node_fs_1.default.readFileSync(versionPath, "utf8"), versionFile);
34
+ },
35
+ writeVersion(cwd, config, version) {
36
+ const versionFile = this.getVersionFile(config);
37
+ const versionPath = node_path_1.default.join(cwd, versionFile);
38
+ if (!node_fs_1.default.existsSync(versionPath)) {
39
+ throw new Error(`Versionary requires ${versionFile} to exist.`);
40
+ }
41
+ const existing = node_fs_1.default.readFileSync(versionPath, "utf8");
42
+ const updated = writeDescriptionVersion(existing, versionFile, version);
43
+ node_fs_1.default.writeFileSync(versionPath, updated, "utf8");
44
+ return [versionFile];
45
+ },
46
+ };
@@ -2,10 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveVersionStrategy = resolveVersionStrategy;
4
4
  const node_js_1 = require("./node.js");
5
+ const r_js_1 = require("./r.js");
6
+ const rust_js_1 = require("./rust.js");
5
7
  const simple_js_1 = require("./simple.js");
6
8
  function resolveVersionStrategy(config) {
7
9
  if (config["release-type"] === "node") {
8
10
  return node_js_1.nodeVersionStrategy;
9
11
  }
12
+ if (config["release-type"] === "rust") {
13
+ return rust_js_1.rustVersionStrategy;
14
+ }
15
+ if (config["release-type"] === "r") {
16
+ return r_js_1.rVersionStrategy;
17
+ }
10
18
  return simple_js_1.simpleVersionStrategy;
11
19
  }
@@ -0,0 +1,5 @@
1
+ import type { VersionStrategy } from "./types.js";
2
+ export declare function applyRustWorkspaceDependencyUpdates(cwd: string, manifestToVersion: Record<string, string>): string[];
3
+ export declare function detectRustDependencyImpact(cwd: string, manifestToVersion: Record<string, string>, candidateManifests: string[]): string[];
4
+ export declare function toCargoManifestPath(packagePath: string): string;
5
+ export declare const rustVersionStrategy: VersionStrategy;