@varlock/bumpy 0.0.1 → 0.0.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.
Files changed (38) hide show
  1. package/dist/add-BjyVIUlr.mjs +175 -0
  2. package/dist/{ai-B8ZL2x8z.mjs → ai-CQhUyHAG.mjs} +2 -2
  3. package/dist/{apply-release-plan-DtU3rVyL.mjs → apply-release-plan-D6TSrcwX.mjs} +11 -6
  4. package/dist/changelog-github-Du62krXi.mjs +193 -0
  5. package/dist/{changeset-ClCYsChu.mjs → changeset-UCZdSRDv.mjs} +36 -3
  6. package/dist/{check-CkRubvuk.mjs → check-jIwike9F.mjs} +5 -11
  7. package/dist/ci-D6LQbR38.mjs +585 -0
  8. package/dist/ci-setup-C6FlOfW5.mjs +211 -0
  9. package/dist/clack-CDRCHrC-.mjs +1216 -0
  10. package/dist/cli.mjs +20 -16
  11. package/dist/{config-CJ2orhTL.mjs → config-BkwIEaQg.mjs} +2 -2
  12. package/dist/{fs-DbNNEyzq.mjs → fs-0AtnPUUe.mjs} +1 -1
  13. package/dist/{generate-oOFD9ABC.mjs → generate-Btrsn1qi.mjs} +28 -9
  14. package/dist/git-CGHVXXKw.mjs +78 -0
  15. package/dist/index.d.mts +10 -2
  16. package/dist/index.mjs +8 -8
  17. package/dist/{init-Blw2GfC_.mjs → init-B0q3wEQW.mjs} +2 -2
  18. package/dist/logger-C2dEe5Su.mjs +135 -0
  19. package/dist/{migrate-DvOrXSw0.mjs → migrate-CfQNwD0T.mjs} +18 -11
  20. package/dist/{names-C-u50ofE.mjs → names-Ck8cun7B.mjs} +2 -1
  21. package/dist/package-manager-DcI5TdDE.mjs +80 -0
  22. package/dist/{publish-DZ3m7qkX.mjs → publish-D_7RqEYL.mjs} +74 -20
  23. package/dist/{publish-pipeline-1M5GmbdP.mjs → publish-pipeline-ChnqW8nR.mjs} +40 -54
  24. package/dist/{release-plan-CFnutSHD.mjs → release-plan-BEzwApuK.mjs} +2 -2
  25. package/dist/{semver-DWO6NFKN.mjs → semver-BTzYh8vc.mjs} +1 -1
  26. package/dist/shell-Dj7JRD_q.mjs +92 -0
  27. package/dist/{status-DRpq_Mha.mjs → status--Q8yAxQ4.mjs} +7 -7
  28. package/dist/{version-CJwf8XIA.mjs → version-cAUkfYPx.mjs} +60 -21
  29. package/dist/workspace-CxEKakDm.mjs +107 -0
  30. package/package.json +4 -2
  31. package/dist/add-u5V9V3L7.mjs +0 -131
  32. package/dist/changelog-github-n-3zV1p9.mjs +0 -59
  33. package/dist/ci-8KWWhjXl.mjs +0 -224
  34. package/dist/logger-ZqggsyGZ.mjs +0 -176
  35. package/dist/prompt-BP8toAOI.mjs +0 -46
  36. package/dist/shell-DPlltpzb.mjs +0 -44
  37. package/dist/workspace-mVjawG8g.mjs +0 -183
  38. /package/dist/{dep-graph-DiLeAhl9.mjs → dep-graph-E-9-eQ2J.mjs} +0 -0
@@ -0,0 +1,175 @@
1
+ import { n as log, o as __toESM, r as require_picocolors } from "./logger-C2dEe5Su.mjs";
2
+ import { n as exists, t as ensureDir } from "./fs-0AtnPUUe.mjs";
3
+ import { a as loadConfig, r as getBumpyDir, s as matchGlob } from "./config-BkwIEaQg.mjs";
4
+ import { t as discoverPackages } from "./workspace-CxEKakDm.mjs";
5
+ import { t as DependencyGraph } from "./dep-graph-E-9-eQ2J.mjs";
6
+ import { i as writeChangeset } from "./changeset-UCZdSRDv.mjs";
7
+ import { c as ot, d as yt, i as _t, l as pt, o as gt, r as Ot, s as mt, t as unwrap, u as wt } from "./clack-CDRCHrC-.mjs";
8
+ import { n as slugify, t as randomName } from "./names-Ck8cun7B.mjs";
9
+ import { resolve } from "node:path";
10
+ //#region src/commands/add.ts
11
+ var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
12
+ const BUMP_CHOICES = [
13
+ {
14
+ label: "patch",
15
+ value: "patch"
16
+ },
17
+ {
18
+ label: "minor",
19
+ value: "minor"
20
+ },
21
+ {
22
+ label: "major",
23
+ value: "major"
24
+ },
25
+ {
26
+ label: "patch (isolated)",
27
+ value: "patch-isolated",
28
+ hint: "no cascade"
29
+ },
30
+ {
31
+ label: "minor (isolated)",
32
+ value: "minor-isolated",
33
+ hint: "no cascade"
34
+ }
35
+ ];
36
+ const CASCADE_CHOICES = [
37
+ {
38
+ label: "patch",
39
+ value: "patch"
40
+ },
41
+ {
42
+ label: "minor",
43
+ value: "minor"
44
+ },
45
+ {
46
+ label: "major",
47
+ value: "major"
48
+ }
49
+ ];
50
+ async function addCommand(rootDir, opts) {
51
+ const config = await loadConfig(rootDir);
52
+ const bumpyDir = getBumpyDir(rootDir);
53
+ await ensureDir(bumpyDir);
54
+ if (opts.empty) {
55
+ const filename = opts.name ? slugify(opts.name) : randomName();
56
+ const filePath = resolve(bumpyDir, `${filename}.md`);
57
+ const { writeText } = await import("./fs-0AtnPUUe.mjs").then((n) => n.r);
58
+ await writeText(filePath, "---\n---\n");
59
+ log.success(`Created empty changeset: .bumpy/${filename}.md`);
60
+ return;
61
+ }
62
+ let releases;
63
+ let summary;
64
+ let filename;
65
+ if (opts.packages) {
66
+ releases = parsePackagesFlag(opts.packages);
67
+ summary = opts.message || "";
68
+ filename = opts.name ? slugify(opts.name) : randomName();
69
+ } else {
70
+ mt(import_picocolors.default.bgCyan(import_picocolors.default.black(" bumpy add ")));
71
+ const pkgs = await discoverPackages(rootDir, config);
72
+ const depGraph = new DependencyGraph(pkgs);
73
+ if (pkgs.size === 0) {
74
+ pt("No managed packages found in this workspace.");
75
+ process.exit(1);
76
+ }
77
+ const selected = unwrap(await yt({
78
+ message: "Which packages should be included in this changeset?",
79
+ options: [...pkgs.values()].map((pkg) => ({
80
+ label: pkg.name,
81
+ value: pkg.name,
82
+ hint: pkg.version
83
+ })),
84
+ required: true
85
+ }));
86
+ releases = [];
87
+ for (const name of selected) {
88
+ const bumpType = unwrap(await _t({
89
+ message: `Bump type for ${import_picocolors.default.cyan(name)}`,
90
+ options: BUMP_CHOICES
91
+ }));
92
+ const release = {
93
+ name,
94
+ type: bumpType
95
+ };
96
+ if (!bumpType.endsWith("-isolated")) {
97
+ const dependents = depGraph.getDependents(name);
98
+ const cascadeTargets = pkgs.get(name).bumpy?.cascadeTo;
99
+ if (dependents.length > 0 || cascadeTargets) {
100
+ if (unwrap(await ot({
101
+ message: `${import_picocolors.default.cyan(name)} has ${import_picocolors.default.bold(String(dependents.length))} dependents. Specify explicit cascades?`,
102
+ initialValue: false
103
+ }))) {
104
+ const allTargets = /* @__PURE__ */ new Set();
105
+ for (const d of dependents) allTargets.add(d.name);
106
+ if (cascadeTargets) {
107
+ for (const pattern of Object.keys(cascadeTargets)) for (const [pName] of pkgs) if (matchGlob(pName, pattern)) allTargets.add(pName);
108
+ }
109
+ const cascadeSelected = unwrap(await yt({
110
+ message: "Which packages should cascade?",
111
+ options: [...allTargets].map((n) => ({
112
+ label: n,
113
+ value: n
114
+ })),
115
+ required: false
116
+ }));
117
+ if (cascadeSelected.length > 0) {
118
+ const cascadeBump = unwrap(await _t({
119
+ message: "Cascade bump type",
120
+ options: CASCADE_CHOICES
121
+ }));
122
+ const cascade = {};
123
+ for (const target of cascadeSelected) cascade[target] = cascadeBump;
124
+ release.cascade = cascade;
125
+ }
126
+ }
127
+ }
128
+ }
129
+ releases.push(release);
130
+ }
131
+ summary = unwrap(await Ot({
132
+ message: "Summary (what changed and why)",
133
+ placeholder: "A short description of the change",
134
+ validate: (value) => {
135
+ if (!value || !value.trim()) return "Summary is required";
136
+ }
137
+ }));
138
+ const defaultName = randomName();
139
+ filename = slugify(unwrap(await Ot({
140
+ message: "Changeset name",
141
+ placeholder: defaultName,
142
+ defaultValue: defaultName,
143
+ validate: (value) => {
144
+ if (!value) return void 0;
145
+ if (!slugify(value)) return "Name must contain at least one alphanumeric character";
146
+ }
147
+ }))) || defaultName;
148
+ }
149
+ if (await exists(resolve(bumpyDir, `${filename}.md`))) filename = `${filename}-${Date.now()}`;
150
+ await writeChangeset(rootDir, filename, releases, summary);
151
+ if (opts.packages) {
152
+ log.success(`Created changeset: .bumpy/${filename}.md`);
153
+ for (const r of releases) log.dim(` ${r.name}: ${r.type}${formatCascade(r)}`);
154
+ } else {
155
+ wt(releases.map((r) => `${import_picocolors.default.cyan(r.name)} ${import_picocolors.default.dim("→")} ${import_picocolors.default.bold(r.type)}${formatCascade(r)}`).join("\n"), "Changeset");
156
+ gt(import_picocolors.default.green(`Created .bumpy/${filename}.md`));
157
+ }
158
+ }
159
+ function formatCascade(r) {
160
+ if (!("cascade" in r) || Object.keys(r.cascade).length === 0) return "";
161
+ const parts = Object.entries(r.cascade).map(([k, v]) => `${k}:${v}`);
162
+ return import_picocolors.default.dim(` (cascade: ${parts.join(", ")})`);
163
+ }
164
+ function parsePackagesFlag(input) {
165
+ return input.split(",").map((entry) => {
166
+ const [name, type] = entry.trim().split(":");
167
+ if (!name || !type) throw new Error(`Invalid package format: "${entry}". Expected "name:bumpType"`);
168
+ return {
169
+ name: name.trim(),
170
+ type: type.trim()
171
+ };
172
+ });
173
+ }
174
+ //#endregion
175
+ export { addCommand };
@@ -1,5 +1,5 @@
1
- import { n as log } from "./logger-ZqggsyGZ.mjs";
2
- import { l as writeText, n as exists, t as ensureDir } from "./fs-DbNNEyzq.mjs";
1
+ import { n as log } from "./logger-C2dEe5Su.mjs";
2
+ import { l as writeText, n as exists, t as ensureDir } from "./fs-0AtnPUUe.mjs";
3
3
  import { dirname, resolve } from "node:path";
4
4
  import { readFile } from "node:fs/promises";
5
5
  import { fileURLToPath } from "node:url";
@@ -1,6 +1,6 @@
1
- import { n as log } from "./logger-ZqggsyGZ.mjs";
2
- import { a as readJson, c as writeJson, l as writeText, n as exists, o as readText } from "./fs-DbNNEyzq.mjs";
3
- import { t as deleteChangesets } from "./changeset-ClCYsChu.mjs";
1
+ import { n as log } from "./logger-C2dEe5Su.mjs";
2
+ import { a as readJson, c as writeJson, l as writeText, n as exists, o as readText } from "./fs-0AtnPUUe.mjs";
3
+ import { t as deleteChangesets } from "./changeset-UCZdSRDv.mjs";
4
4
  import { resolve } from "node:path";
5
5
  //#region src/core/changelog.ts
6
6
  /** Default formatter — version heading, date, bullet points */
@@ -27,7 +27,7 @@ const defaultFormatter = (ctx) => {
27
27
  const BUILTIN_FORMATTERS = {
28
28
  default: defaultFormatter,
29
29
  github: async () => {
30
- const { createGithubFormatter } = await import("./changelog-github-n-3zV1p9.mjs");
30
+ const { createGithubFormatter } = await import("./changelog-github-Du62krXi.mjs");
31
31
  return createGithubFormatter();
32
32
  }
33
33
  };
@@ -43,11 +43,16 @@ async function loadFormatter(changelog, rootDir) {
43
43
  return builtin;
44
44
  }
45
45
  if (name === "github") {
46
- const { createGithubFormatter } = await import("./changelog-github-n-3zV1p9.mjs");
46
+ const { createGithubFormatter } = await import("./changelog-github-Du62krXi.mjs");
47
47
  return createGithubFormatter(options);
48
48
  }
49
49
  if (typeof name === "string") try {
50
- const mod = await (name.startsWith(".") ? import(resolve(rootDir, name)) : import(name));
50
+ let modulePath;
51
+ if (name.startsWith(".")) {
52
+ modulePath = resolve(rootDir, name);
53
+ if (!modulePath.startsWith(rootDir + "/")) throw new Error(`Changelog formatter path "${name}" resolves outside the project root`);
54
+ } else modulePath = name;
55
+ const mod = await import(modulePath);
51
56
  const exported = mod.default || mod.changelogFormatter;
52
57
  if (typeof exported === "function") {
53
58
  const result = exported(options);
@@ -0,0 +1,193 @@
1
+ import { o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
2
+ //#region src/core/changelog-github.ts
3
+ /**
4
+ * GitHub-enhanced changelog formatter.
5
+ * Adds PR links, commit links, and contributor attribution when git/gh info is available.
6
+ *
7
+ * Usage in config:
8
+ * "changelog": "github"
9
+ * "changelog": ["github", { "repo": "dmno-dev/bumpy" }]
10
+ * "changelog": ["github", { "repo": "dmno-dev/bumpy", "internalAuthors": ["theoephraim"] }]
11
+ */
12
+ function createGithubFormatter(options = {}) {
13
+ const internalAuthorsSet = new Set((options.internalAuthors ?? []).map((a) => a.toLowerCase()));
14
+ return async (ctx) => {
15
+ const { release, changesets, date } = ctx;
16
+ const repoSlug = options.repo ?? detectRepo();
17
+ const serverUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
18
+ const lines = [];
19
+ lines.push(`## ${release.newVersion}`);
20
+ lines.push("");
21
+ lines.push(`_${date}_`);
22
+ lines.push("");
23
+ const relevantChangesets = changesets.filter((cs) => release.changesets.includes(cs.id));
24
+ if (relevantChangesets.length > 0) for (const cs of relevantChangesets) {
25
+ if (!cs.summary) continue;
26
+ const { cleanSummary, overrides } = extractSummaryMeta(cs.summary);
27
+ const gitInfo = resolveChangesetInfo(cs.id, repoSlug, serverUrl, overrides);
28
+ const summaryLines = cleanSummary.split("\n");
29
+ const firstLine = linkifyIssueRefs(summaryLines[0], serverUrl, repoSlug);
30
+ const prefix = formatPrefix(gitInfo, serverUrl, repoSlug, internalAuthorsSet);
31
+ lines.push(`-${prefix ? ` ${prefix} -` : ""} ${firstLine}`);
32
+ for (let i = 1; i < summaryLines.length; i++) if (summaryLines[i].trim()) lines.push(` ${linkifyIssueRefs(summaryLines[i], serverUrl, repoSlug)}`);
33
+ }
34
+ if (release.isDependencyBump && relevantChangesets.length === 0) lines.push("- Updated dependencies");
35
+ if (release.isCascadeBump && !release.isDependencyBump && relevantChangesets.length === 0) lines.push("- Version bump via cascade rule");
36
+ lines.push("");
37
+ return lines.join("\n");
38
+ };
39
+ }
40
+ /**
41
+ * Extract metadata lines (pr, commit, author) from a changeset summary.
42
+ * These override git-derived info, matching the behavior of @changesets/changelog-github.
43
+ */
44
+ function extractSummaryMeta(summary) {
45
+ const overrides = {};
46
+ return {
47
+ cleanSummary: summary.replace(/^\s*(?:pr|pull|pull\s+request):\s*#?(\d+)/im, (_, pr) => {
48
+ const num = Number(pr);
49
+ if (!isNaN(num)) overrides.pr = num;
50
+ return "";
51
+ }).replace(/^\s*commit:\s*([^\s]+)/im, (_, commit) => {
52
+ overrides.commit = commit;
53
+ return "";
54
+ }).replace(/^\s*(?:author|user):\s*@?([^\s]+)/gim, (_, user) => {
55
+ overrides.authors ??= [];
56
+ overrides.authors.push(user);
57
+ return "";
58
+ }).trim(),
59
+ overrides
60
+ };
61
+ }
62
+ /**
63
+ * Resolve PR, commit, and author info for a changeset.
64
+ * Summary overrides take precedence over git-derived info.
65
+ */
66
+ function resolveChangesetInfo(changesetId, repo, serverUrl, overrides) {
67
+ if (overrides.pr !== void 0) {
68
+ const prInfo = lookupPr(overrides.pr, repo);
69
+ return {
70
+ prNumber: overrides.pr,
71
+ prUrl: prInfo?.url ?? `${serverUrl}/${repo}/pull/${overrides.pr}`,
72
+ commitHash: overrides.commit ?? prInfo?.commitHash,
73
+ author: overrides.authors?.[0] ?? prInfo?.author
74
+ };
75
+ }
76
+ const gitInfo = findChangesetCommitInfo(changesetId, repo);
77
+ return {
78
+ prNumber: gitInfo?.prNumber,
79
+ prUrl: gitInfo?.prUrl,
80
+ commitHash: overrides.commit ?? gitInfo?.commitHash,
81
+ author: overrides.authors?.[0] ?? gitInfo?.author
82
+ };
83
+ }
84
+ /** Look up a PR by number using gh CLI */
85
+ function lookupPr(prNumber, repo) {
86
+ try {
87
+ const ghArgs = [
88
+ "gh",
89
+ "pr",
90
+ "view",
91
+ String(prNumber),
92
+ "--json",
93
+ "url,author,mergeCommit"
94
+ ];
95
+ if (repo) ghArgs.push("--repo", repo);
96
+ const result = tryRunArgs(ghArgs);
97
+ if (!result) return null;
98
+ const pr = JSON.parse(result);
99
+ return {
100
+ url: pr.url,
101
+ author: pr.author?.login,
102
+ commitHash: pr.mergeCommit?.oid
103
+ };
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+ /**
109
+ * Find the PR that introduced a changeset file by checking git log
110
+ * for the commit that added the file, then looking up the PR.
111
+ */
112
+ function findChangesetCommitInfo(changesetId, repo) {
113
+ try {
114
+ const commitOutput = tryRunArgs([
115
+ "git",
116
+ "log",
117
+ "--diff-filter=A",
118
+ "--format=%H",
119
+ "--",
120
+ `.bumpy/${changesetId}.md`,
121
+ `.changeset/${changesetId}.md`
122
+ ]);
123
+ if (!commitOutput) return null;
124
+ const commitHash = commitOutput.split("\n")[0].trim();
125
+ if (!commitHash) return null;
126
+ const ghArgs = [
127
+ "gh",
128
+ "pr",
129
+ "list",
130
+ "--search",
131
+ commitHash,
132
+ "--state",
133
+ "merged",
134
+ "--json",
135
+ "number,url,author",
136
+ "--jq",
137
+ ".[0]"
138
+ ];
139
+ if (repo) ghArgs.push("--repo", repo);
140
+ const prJson = tryRunArgs(ghArgs);
141
+ if (!prJson) return { commitHash };
142
+ const pr = JSON.parse(prJson);
143
+ if (!pr.number) return { commitHash };
144
+ return {
145
+ prNumber: pr.number,
146
+ prUrl: pr.url,
147
+ commitHash,
148
+ author: pr.author?.login
149
+ };
150
+ } catch {
151
+ return null;
152
+ }
153
+ }
154
+ /**
155
+ * Build the prefix portion of a changelog line: PR link, commit link, thanks.
156
+ * Matches the format used by @changesets/changelog-github.
157
+ */
158
+ function formatPrefix(info, serverUrl, repo, internalAuthors) {
159
+ const parts = [];
160
+ if (info.prNumber && info.prUrl) parts.push(`[#${info.prNumber}](${info.prUrl})`);
161
+ if (info.commitHash && repo) {
162
+ const short = info.commitHash.slice(0, 7);
163
+ parts.push(`[\`${short}\`](${serverUrl}/${repo}/commit/${info.commitHash})`);
164
+ }
165
+ if (info.author && !internalAuthors.has(info.author.toLowerCase())) parts.push(`Thanks [@${info.author}](${serverUrl}/${info.author})!`);
166
+ return parts.join(" ");
167
+ }
168
+ /**
169
+ * Linkify bare issue/PR references like #123 in text,
170
+ * but skip references already inside markdown links.
171
+ */
172
+ function linkifyIssueRefs(line, serverUrl, repo) {
173
+ if (!repo) return line;
174
+ return line.replace(/\[.*?\]\(.*?\)|\B#([1-9]\d*)\b/g, (match, issue) => issue ? `[#${issue}](${serverUrl}/${repo}/issues/${issue})` : match);
175
+ }
176
+ /** Try to detect the repo slug from the gh CLI */
177
+ function detectRepo() {
178
+ try {
179
+ return tryRunArgs([
180
+ "gh",
181
+ "repo",
182
+ "view",
183
+ "--json",
184
+ "nameWithOwner",
185
+ "--jq",
186
+ ".nameWithOwner"
187
+ ])?.trim() || void 0;
188
+ } catch {
189
+ return;
190
+ }
191
+ }
192
+ //#endregion
193
+ export { createGithubFormatter };
@@ -1,9 +1,10 @@
1
- import { i as listFiles, l as writeText, o as readText, s as removeFile } from "./fs-DbNNEyzq.mjs";
2
- import { r as getBumpyDir } from "./config-CJ2orhTL.mjs";
1
+ import { i as listFiles, l as writeText, o as readText, s as removeFile } from "./fs-0AtnPUUe.mjs";
2
+ import { r as getBumpyDir } from "./config-BkwIEaQg.mjs";
3
3
  import { t as jsYaml } from "./js-yaml-DpZfOoD4.mjs";
4
+ import { o as tryRunArgs } from "./shell-Dj7JRD_q.mjs";
4
5
  import { resolve } from "node:path";
5
6
  //#region src/core/changeset.ts
6
- /** Read all changeset files from .bumpy/ directory */
7
+ /** Read all changeset files from .bumpy/ directory, sorted by git creation order */
7
8
  async function readChangesets(rootDir) {
8
9
  const dir = getBumpyDir(rootDir);
9
10
  const files = await listFiles(dir, ".md");
@@ -13,8 +14,40 @@ async function readChangesets(rootDir) {
13
14
  const cs = await parseChangesetFile(resolve(dir, file));
14
15
  if (cs) changesets.push(cs);
15
16
  }
17
+ const creationOrder = getChangesetCreationOrder(rootDir);
18
+ if (creationOrder.size > 0) changesets.sort((a, b) => {
19
+ return (creationOrder.get(a.id) ?? Infinity) - (creationOrder.get(b.id) ?? Infinity) || a.id.localeCompare(b.id);
20
+ });
16
21
  return changesets;
17
22
  }
23
+ /**
24
+ * Use `git log` to get the commit timestamp when each changeset file was first added.
25
+ * Returns a map of changeset ID → unix timestamp (seconds).
26
+ */
27
+ function getChangesetCreationOrder(rootDir) {
28
+ const order = /* @__PURE__ */ new Map();
29
+ const result = tryRunArgs([
30
+ "git",
31
+ "log",
32
+ "--diff-filter=A",
33
+ "--format=%at",
34
+ "--name-only",
35
+ "--",
36
+ ".bumpy/*.md"
37
+ ], { cwd: rootDir });
38
+ if (!result) return order;
39
+ let currentTimestamp = 0;
40
+ for (const line of result.split("\n")) {
41
+ const trimmed = line.trim();
42
+ if (!trimmed) continue;
43
+ if (/^\d+$/.test(trimmed)) currentTimestamp = parseInt(trimmed, 10);
44
+ else if (trimmed.startsWith(".bumpy/") && trimmed.endsWith(".md")) {
45
+ const id = trimmed.replace(/^\.bumpy\//, "").replace(/\.md$/, "");
46
+ order.set(id, currentTimestamp);
47
+ }
48
+ }
49
+ return order;
50
+ }
18
51
  /** Parse a single changeset markdown file */
19
52
  async function parseChangesetFile(filePath) {
20
53
  return parseChangeset(await readText(filePath), fileToId(filePath));
@@ -1,8 +1,8 @@
1
- import { n as log, t as colorize } from "./logger-ZqggsyGZ.mjs";
2
- import { a as loadConfig } from "./config-CJ2orhTL.mjs";
3
- import { n as discoverWorkspace } from "./workspace-mVjawG8g.mjs";
4
- import { r as readChangesets } from "./changeset-ClCYsChu.mjs";
5
- import { i as tryRun } from "./shell-DPlltpzb.mjs";
1
+ import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
2
+ import { a as loadConfig } from "./config-BkwIEaQg.mjs";
3
+ import { n as discoverWorkspace } from "./workspace-CxEKakDm.mjs";
4
+ import { r as readChangesets } from "./changeset-UCZdSRDv.mjs";
5
+ import { n as getChangedFiles } from "./git-CGHVXXKw.mjs";
6
6
  import { relative } from "node:path";
7
7
  //#region src/commands/check.ts
8
8
  /**
@@ -38,12 +38,6 @@ async function checkCommand(rootDir) {
38
38
  log.dim("Run `bumpy add` to create a changeset, or `bumpy add --empty` if no release is needed.");
39
39
  process.exit(1);
40
40
  }
41
- /** Get files changed on this branch compared to the base branch */
42
- function getChangedFiles(rootDir, baseBranch) {
43
- const diff = tryRun(`git diff --name-only ${tryRun(`git merge-base HEAD origin/${baseBranch}`, { cwd: rootDir }) || `origin/${baseBranch}`}`, { cwd: rootDir });
44
- if (!diff) return [];
45
- return diff.split("\n").filter(Boolean);
46
- }
47
41
  /** Map changed files to the packages they belong to */
48
42
  function findChangedPackages(changedFiles, packages, rootDir) {
49
43
  const changed = /* @__PURE__ */ new Set();