@varlock/bumpy 0.0.0 → 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.
- package/.claude-plugin/plugin.json +13 -0
- package/dist/add-BjyVIUlr.mjs +175 -0
- package/dist/ai-CQhUyHAG.mjs +82 -0
- package/dist/apply-release-plan-D6TSrcwX.mjs +137 -0
- package/dist/changelog-github-Du62krXi.mjs +193 -0
- package/dist/changeset-UCZdSRDv.mjs +108 -0
- package/dist/check-jIwike9F.mjs +51 -0
- package/dist/ci-D6LQbR38.mjs +585 -0
- package/dist/ci-setup-C6FlOfW5.mjs +211 -0
- package/dist/clack-CDRCHrC-.mjs +1216 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +214 -0
- package/dist/config-BkwIEaQg.mjs +215 -0
- package/dist/dep-graph-E-9-eQ2J.mjs +64 -0
- package/dist/fs-0AtnPUUe.mjs +51 -0
- package/dist/generate-Btrsn1qi.mjs +177 -0
- package/dist/git-CGHVXXKw.mjs +78 -0
- package/dist/index.d.mts +262 -0
- package/dist/index.mjs +9 -0
- package/dist/init-B0q3wEQW.mjs +22 -0
- package/dist/js-yaml-DpZfOoD4.mjs +2031 -0
- package/dist/logger-C2dEe5Su.mjs +135 -0
- package/dist/migrate-CfQNwD0T.mjs +121 -0
- package/dist/names-Ck8cun7B.mjs +144 -0
- package/dist/package-manager-DcI5TdDE.mjs +80 -0
- package/dist/publish-D_7RqEYL.mjs +251 -0
- package/dist/publish-pipeline-ChnqW8nR.mjs +277 -0
- package/dist/release-plan-BEzwApuK.mjs +173 -0
- package/dist/semver-BTzYh8vc.mjs +1360 -0
- package/dist/shell-Dj7JRD_q.mjs +92 -0
- package/dist/status--Q8yAxQ4.mjs +106 -0
- package/dist/version-cAUkfYPx.mjs +120 -0
- package/dist/workspace-CxEKakDm.mjs +107 -0
- package/package.json +38 -6
- package/skills/add-change/SKILL.md +108 -0
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as log, t as colorize } from "./logger-C2dEe5Su.mjs";
|
|
3
|
+
import { n as findRoot } from "./config-BkwIEaQg.mjs";
|
|
4
|
+
//#region src/cli.ts
|
|
5
|
+
const args = process.argv.slice(2);
|
|
6
|
+
const command = args[0];
|
|
7
|
+
function parseFlags(args) {
|
|
8
|
+
const flags = {};
|
|
9
|
+
for (let i = 0; i < args.length; i++) {
|
|
10
|
+
const arg = args[i];
|
|
11
|
+
if (arg.startsWith("--")) {
|
|
12
|
+
const key = arg.slice(2);
|
|
13
|
+
const next = args[i + 1];
|
|
14
|
+
if (next && !next.startsWith("--")) {
|
|
15
|
+
flags[key] = next;
|
|
16
|
+
i++;
|
|
17
|
+
} else flags[key] = true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return flags;
|
|
21
|
+
}
|
|
22
|
+
async function main() {
|
|
23
|
+
const flags = parseFlags(args.slice(1));
|
|
24
|
+
try {
|
|
25
|
+
switch (command) {
|
|
26
|
+
case "init": {
|
|
27
|
+
const rootDir = await findRoot();
|
|
28
|
+
const { initCommand } = await import("./init-B0q3wEQW.mjs");
|
|
29
|
+
await initCommand(rootDir);
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
case "add": {
|
|
33
|
+
const rootDir = await findRoot();
|
|
34
|
+
const { addCommand } = await import("./add-BjyVIUlr.mjs");
|
|
35
|
+
await addCommand(rootDir, {
|
|
36
|
+
packages: flags.packages,
|
|
37
|
+
message: flags.message,
|
|
38
|
+
name: flags.name,
|
|
39
|
+
empty: flags.empty === true
|
|
40
|
+
});
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case "status": {
|
|
44
|
+
const rootDir = await findRoot();
|
|
45
|
+
const { statusCommand } = await import("./status--Q8yAxQ4.mjs");
|
|
46
|
+
await statusCommand(rootDir, {
|
|
47
|
+
json: flags.json === true,
|
|
48
|
+
packagesOnly: flags.packages === true,
|
|
49
|
+
bumpType: flags.bump,
|
|
50
|
+
filter: flags.filter,
|
|
51
|
+
verbose: flags.verbose === true
|
|
52
|
+
});
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
case "version": {
|
|
56
|
+
const rootDir = await findRoot();
|
|
57
|
+
const { versionCommand } = await import("./version-cAUkfYPx.mjs");
|
|
58
|
+
await versionCommand(rootDir);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case "generate": {
|
|
62
|
+
const rootDir = await findRoot();
|
|
63
|
+
const { generateCommand } = await import("./generate-Btrsn1qi.mjs");
|
|
64
|
+
await generateCommand(rootDir, {
|
|
65
|
+
from: flags.from,
|
|
66
|
+
dryRun: flags["dry-run"] === true,
|
|
67
|
+
name: flags.name
|
|
68
|
+
});
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case "migrate": {
|
|
72
|
+
const rootDir = await findRoot();
|
|
73
|
+
const { migrateCommand } = await import("./migrate-CfQNwD0T.mjs");
|
|
74
|
+
await migrateCommand(rootDir, { force: flags.force === true });
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
case "check": {
|
|
78
|
+
const rootDir = await findRoot();
|
|
79
|
+
const { checkCommand } = await import("./check-jIwike9F.mjs");
|
|
80
|
+
await checkCommand(rootDir);
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
case "ci": {
|
|
84
|
+
const rootDir = await findRoot();
|
|
85
|
+
const subcommand = args[1];
|
|
86
|
+
const ciFlags = parseFlags(args.slice(2));
|
|
87
|
+
if (subcommand === "check") {
|
|
88
|
+
const { ciCheckCommand } = await import("./ci-D6LQbR38.mjs");
|
|
89
|
+
await ciCheckCommand(rootDir, {
|
|
90
|
+
comment: ciFlags.comment !== void 0 ? ciFlags.comment === true : void 0,
|
|
91
|
+
failOnMissing: ciFlags["fail-on-missing"] === true
|
|
92
|
+
});
|
|
93
|
+
} else if (subcommand === "release") {
|
|
94
|
+
const { ciReleaseCommand } = await import("./ci-D6LQbR38.mjs");
|
|
95
|
+
await ciReleaseCommand(rootDir, {
|
|
96
|
+
mode: ciFlags["auto-publish"] === true ? "auto-publish" : "version-pr",
|
|
97
|
+
tag: ciFlags.tag,
|
|
98
|
+
branch: ciFlags.branch
|
|
99
|
+
});
|
|
100
|
+
} else if (subcommand === "setup") {
|
|
101
|
+
const { ciSetupCommand } = await import("./ci-setup-C6FlOfW5.mjs");
|
|
102
|
+
await ciSetupCommand(rootDir);
|
|
103
|
+
} else {
|
|
104
|
+
log.error(`Unknown ci subcommand: ${subcommand}. Use "ci check", "ci release", or "ci setup".`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case "publish": {
|
|
110
|
+
const rootDir = await findRoot();
|
|
111
|
+
const { publishCommand } = await import("./publish-D_7RqEYL.mjs");
|
|
112
|
+
await publishCommand(rootDir, {
|
|
113
|
+
dryRun: flags["dry-run"] === true,
|
|
114
|
+
tag: flags.tag,
|
|
115
|
+
noPush: flags["no-push"] === true,
|
|
116
|
+
filter: flags.filter
|
|
117
|
+
});
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case "ai": {
|
|
121
|
+
const rootDir = await findRoot();
|
|
122
|
+
const subcommand = args[1];
|
|
123
|
+
const aiFlags = parseFlags(args.slice(2));
|
|
124
|
+
if (subcommand === "setup") {
|
|
125
|
+
const { aiSetupCommand } = await import("./ai-CQhUyHAG.mjs");
|
|
126
|
+
await aiSetupCommand(rootDir, { target: aiFlags.target });
|
|
127
|
+
} else {
|
|
128
|
+
log.error(`Unknown ai subcommand: ${subcommand}. Use "ai setup".`);
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "--version":
|
|
134
|
+
case "-v":
|
|
135
|
+
console.log(`bumpy 0.0.2`);
|
|
136
|
+
break;
|
|
137
|
+
case "help":
|
|
138
|
+
case "--help":
|
|
139
|
+
case "-h":
|
|
140
|
+
case void 0:
|
|
141
|
+
printHelp();
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
log.error(`Unknown command: ${command}`);
|
|
145
|
+
printHelp();
|
|
146
|
+
process.exit(1);
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
log.error(err instanceof Error ? err.message : String(err));
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function printHelp() {
|
|
154
|
+
console.log(`
|
|
155
|
+
${colorize(`🐸 bumpy v0.0.2`, "bold")} - Modern monorepo versioning
|
|
156
|
+
|
|
157
|
+
Usage: bumpy <command> [options]
|
|
158
|
+
|
|
159
|
+
Commands:
|
|
160
|
+
init Initialize .bumpy/ directory
|
|
161
|
+
add Create a new changeset
|
|
162
|
+
generate Generate changeset from conventional commits
|
|
163
|
+
status Show pending releases
|
|
164
|
+
check Verify changed packages have changesets (for pre-push hooks)
|
|
165
|
+
version Apply changesets and bump versions
|
|
166
|
+
publish Publish versioned packages
|
|
167
|
+
ci check PR check — report pending releases, comment on PR
|
|
168
|
+
ci release Release — create version PR or auto-publish
|
|
169
|
+
ci setup Set up a token for triggering CI on version PRs
|
|
170
|
+
migrate Migrate from .changeset/ to .bumpy/
|
|
171
|
+
ai setup Install AI skill for creating changesets
|
|
172
|
+
|
|
173
|
+
Add options:
|
|
174
|
+
--packages <list> Package bumps (e.g., "pkg-a:minor,pkg-b:patch")
|
|
175
|
+
--message <text> Changeset summary
|
|
176
|
+
--name <name> Changeset filename
|
|
177
|
+
--empty Create an empty changeset
|
|
178
|
+
|
|
179
|
+
Generate options:
|
|
180
|
+
--from <ref> Git ref to scan from (default: last version tag)
|
|
181
|
+
--dry-run Preview without creating a changeset
|
|
182
|
+
--name <name> Changeset filename
|
|
183
|
+
|
|
184
|
+
Status options:
|
|
185
|
+
--json Output as JSON (includes dirs, changesets, packageNames)
|
|
186
|
+
--packages Output only package names, one per line
|
|
187
|
+
--bump <types> Filter by bump type (e.g., "major", "minor,patch")
|
|
188
|
+
--filter <names> Filter by package name/glob (e.g., "@myorg/*")
|
|
189
|
+
--verbose Show changeset details
|
|
190
|
+
|
|
191
|
+
Publish options:
|
|
192
|
+
--dry-run Preview without publishing
|
|
193
|
+
--tag <tag> npm dist-tag (e.g., "next", "beta")
|
|
194
|
+
--no-push Skip pushing git tags to remote
|
|
195
|
+
--filter <names> Publish only matching packages (e.g., "@myorg/*")
|
|
196
|
+
|
|
197
|
+
CI check options:
|
|
198
|
+
--comment Force PR comment on/off (auto-detected in CI)
|
|
199
|
+
--fail-on-missing Exit 1 if no changesets found
|
|
200
|
+
|
|
201
|
+
CI release options:
|
|
202
|
+
--auto-publish Version + publish directly (default: create version PR)
|
|
203
|
+
--tag <tag> npm dist-tag for auto-publish
|
|
204
|
+
--branch <name> Branch name for version PR (default: bumpy/version-packages)
|
|
205
|
+
|
|
206
|
+
AI setup options:
|
|
207
|
+
--target <tool> Target AI tool: opencode, cursor, codex
|
|
208
|
+
|
|
209
|
+
${colorize("https://github.com/dmno-dev/bumpy", "dim")}
|
|
210
|
+
`);
|
|
211
|
+
}
|
|
212
|
+
main();
|
|
213
|
+
//#endregion
|
|
214
|
+
export {};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
|
+
import { a as readJson, n as exists } from "./fs-0AtnPUUe.mjs";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
//#region src/types.ts
|
|
5
|
+
const BUMP_LEVELS = {
|
|
6
|
+
patch: 0,
|
|
7
|
+
minor: 1,
|
|
8
|
+
major: 2
|
|
9
|
+
};
|
|
10
|
+
function bumpLevel(type) {
|
|
11
|
+
return BUMP_LEVELS[type];
|
|
12
|
+
}
|
|
13
|
+
function parseIsolatedBump(type) {
|
|
14
|
+
if (type.endsWith("-isolated")) return {
|
|
15
|
+
bump: type.replace("-isolated", ""),
|
|
16
|
+
isolated: true
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
bump: type,
|
|
20
|
+
isolated: false
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function maxBump(a, b) {
|
|
24
|
+
if (!a) return b;
|
|
25
|
+
return bumpLevel(a) >= bumpLevel(b) ? a : b;
|
|
26
|
+
}
|
|
27
|
+
const DEFAULT_BUMP_RULES = {
|
|
28
|
+
dependencies: {
|
|
29
|
+
trigger: "patch",
|
|
30
|
+
bumpAs: "patch"
|
|
31
|
+
},
|
|
32
|
+
peerDependencies: {
|
|
33
|
+
trigger: "major",
|
|
34
|
+
bumpAs: "major"
|
|
35
|
+
},
|
|
36
|
+
devDependencies: {
|
|
37
|
+
trigger: "none",
|
|
38
|
+
bumpAs: "patch"
|
|
39
|
+
},
|
|
40
|
+
optionalDependencies: {
|
|
41
|
+
trigger: "minor",
|
|
42
|
+
bumpAs: "patch"
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const DEP_TYPES = [
|
|
46
|
+
"dependencies",
|
|
47
|
+
"devDependencies",
|
|
48
|
+
"peerDependencies",
|
|
49
|
+
"optionalDependencies"
|
|
50
|
+
];
|
|
51
|
+
const DEFAULT_PUBLISH_CONFIG = {
|
|
52
|
+
packManager: "auto",
|
|
53
|
+
publishManager: "npm",
|
|
54
|
+
publishArgs: [],
|
|
55
|
+
protocolResolution: "pack"
|
|
56
|
+
};
|
|
57
|
+
const DEFAULT_CONFIG = {
|
|
58
|
+
baseBranch: "main",
|
|
59
|
+
access: "public",
|
|
60
|
+
commit: false,
|
|
61
|
+
changelog: "default",
|
|
62
|
+
fixed: [],
|
|
63
|
+
linked: [],
|
|
64
|
+
ignore: [],
|
|
65
|
+
include: [],
|
|
66
|
+
updateInternalDependencies: "out-of-range",
|
|
67
|
+
dependencyBumpRules: {},
|
|
68
|
+
privatePackages: {
|
|
69
|
+
version: false,
|
|
70
|
+
tag: false
|
|
71
|
+
},
|
|
72
|
+
packages: {},
|
|
73
|
+
publish: { ...DEFAULT_PUBLISH_CONFIG },
|
|
74
|
+
aggregateRelease: false,
|
|
75
|
+
gitUser: {
|
|
76
|
+
name: "bumpy-bot",
|
|
77
|
+
email: "276066384+bumpy-bot@users.noreply.github.com"
|
|
78
|
+
},
|
|
79
|
+
versionPr: {
|
|
80
|
+
title: "🐸 Versioned release",
|
|
81
|
+
branch: "bumpy/version-packages",
|
|
82
|
+
preamble: [
|
|
83
|
+
`<a href="https://github.com/dmno-dev/bumpy"><img src="https://raw.githubusercontent.com/dmno-dev/bumpy/main/images/frog-talking.png" alt="bumpy-frog" width="60" align="left" style="image-rendering: pixelated;" title="Hi! I'm bumpy!" /></a>`,
|
|
84
|
+
"",
|
|
85
|
+
`This PR was created and will be kept in sync by [bumpy](https://github.com/dmno-dev/bumpy) based on your .bumpy changeset files. Merge it when you are ready to release the packages listed below:`,
|
|
86
|
+
"<br clear=\"left\" />"
|
|
87
|
+
].join("\n")
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
function hasCascade(r) {
|
|
91
|
+
return "cascade" in r && Object.keys(r.cascade).length > 0;
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
//#region src/core/config.ts
|
|
95
|
+
var config_exports = /* @__PURE__ */ __exportAll({
|
|
96
|
+
findRoot: () => findRoot,
|
|
97
|
+
getBumpyDir: () => getBumpyDir,
|
|
98
|
+
isPackageManaged: () => isPackageManaged,
|
|
99
|
+
loadConfig: () => loadConfig,
|
|
100
|
+
loadPackageConfig: () => loadPackageConfig,
|
|
101
|
+
matchGlob: () => matchGlob
|
|
102
|
+
});
|
|
103
|
+
const BUMPY_DIR = ".bumpy";
|
|
104
|
+
const CONFIG_FILE = "_config.json";
|
|
105
|
+
/** Find the monorepo root by walking up from cwd looking for .bumpy/ */
|
|
106
|
+
async function findRoot(startDir = process.cwd()) {
|
|
107
|
+
let dir = resolve(startDir);
|
|
108
|
+
while (true) {
|
|
109
|
+
if (await exists(resolve(dir, BUMPY_DIR))) return dir;
|
|
110
|
+
if (await exists(resolve(dir, "package.json"))) try {
|
|
111
|
+
if ((await readJson(resolve(dir, "package.json"))).workspaces) return dir;
|
|
112
|
+
} catch {}
|
|
113
|
+
const parent = resolve(dir, "..");
|
|
114
|
+
if (parent === dir) break;
|
|
115
|
+
dir = parent;
|
|
116
|
+
}
|
|
117
|
+
return resolve(startDir);
|
|
118
|
+
}
|
|
119
|
+
/** Load the root bumpy config, merging with defaults */
|
|
120
|
+
async function loadConfig(rootDir) {
|
|
121
|
+
const configPath = resolve(rootDir, BUMPY_DIR, CONFIG_FILE);
|
|
122
|
+
let userConfig = {};
|
|
123
|
+
if (await exists(configPath)) userConfig = await readJson(configPath);
|
|
124
|
+
return mergeConfig(DEFAULT_CONFIG, userConfig);
|
|
125
|
+
}
|
|
126
|
+
/** Load per-package bumpy config from package.json["bumpy"] or .bumpy.config.json */
|
|
127
|
+
async function loadPackageConfig(pkgDir, rootConfig, pkgName) {
|
|
128
|
+
const rootPkgConfig = findPackageConfig(rootConfig, pkgName);
|
|
129
|
+
let pkgJsonConfig = {};
|
|
130
|
+
try {
|
|
131
|
+
const pkg = await readJson(resolve(pkgDir, "package.json"));
|
|
132
|
+
if (pkg.bumpy && typeof pkg.bumpy === "object") pkgJsonConfig = pkg.bumpy;
|
|
133
|
+
} catch {}
|
|
134
|
+
return mergePackageConfig(rootPkgConfig, pkgJsonConfig);
|
|
135
|
+
}
|
|
136
|
+
/** Find a package config from the root config, supporting glob patterns */
|
|
137
|
+
function findPackageConfig(config, pkgName) {
|
|
138
|
+
if (config.packages[pkgName]) return config.packages[pkgName];
|
|
139
|
+
for (const [pattern, pkgConfig] of Object.entries(config.packages)) if (matchGlob(pkgName, pattern)) return pkgConfig;
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
/** Simple glob matching for package names (supports * and **) */
|
|
143
|
+
function matchGlob(name, pattern) {
|
|
144
|
+
if (name === pattern) return true;
|
|
145
|
+
const regexStr = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{DOUBLE}}").replace(/\*/g, "[^/]*").replace(/{{DOUBLE}}/g, ".*");
|
|
146
|
+
return new RegExp(`^${regexStr}$`).test(name);
|
|
147
|
+
}
|
|
148
|
+
function mergeConfig(defaults, user) {
|
|
149
|
+
return {
|
|
150
|
+
...defaults,
|
|
151
|
+
...user,
|
|
152
|
+
dependencyBumpRules: {
|
|
153
|
+
...defaults.dependencyBumpRules,
|
|
154
|
+
...user.dependencyBumpRules
|
|
155
|
+
},
|
|
156
|
+
privatePackages: {
|
|
157
|
+
...defaults.privatePackages,
|
|
158
|
+
...user.privatePackages
|
|
159
|
+
},
|
|
160
|
+
publish: {
|
|
161
|
+
...defaults.publish,
|
|
162
|
+
...user.publish
|
|
163
|
+
},
|
|
164
|
+
packages: {
|
|
165
|
+
...defaults.packages,
|
|
166
|
+
...user.packages
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function mergePackageConfig(...configs) {
|
|
171
|
+
const result = {};
|
|
172
|
+
for (const cfg of configs) {
|
|
173
|
+
Object.assign(result, cfg);
|
|
174
|
+
if (cfg.dependencyBumpRules) result.dependencyBumpRules = {
|
|
175
|
+
...result.dependencyBumpRules,
|
|
176
|
+
...cfg.dependencyBumpRules
|
|
177
|
+
};
|
|
178
|
+
if (cfg.specificDependencyRules) result.specificDependencyRules = {
|
|
179
|
+
...result.specificDependencyRules,
|
|
180
|
+
...cfg.specificDependencyRules
|
|
181
|
+
};
|
|
182
|
+
if (cfg.cascadeTo) result.cascadeTo = {
|
|
183
|
+
...result.cascadeTo,
|
|
184
|
+
...cfg.cascadeTo
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
function getBumpyDir(rootDir) {
|
|
190
|
+
return resolve(rootDir, BUMPY_DIR);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Determine if a package should be managed by bumpy.
|
|
194
|
+
* Resolution order:
|
|
195
|
+
* 1. Per-package `managed: false` → skip (explicit opt-out)
|
|
196
|
+
* 2. `config.ignore` glob match → skip
|
|
197
|
+
* 3. Per-package `managed: true` → include (explicit opt-in, overrides private)
|
|
198
|
+
* 4. `config.include` glob match → include (overrides private)
|
|
199
|
+
* 5. Private package + `config.privatePackages.version` false → skip
|
|
200
|
+
* 6. Otherwise → include
|
|
201
|
+
*/
|
|
202
|
+
function isPackageManaged(pkgName, isPrivate, config, pkgBumpy) {
|
|
203
|
+
if (pkgBumpy?.managed === false) return false;
|
|
204
|
+
if (config.ignore.some((pattern) => matchGlob(pkgName, pattern))) {
|
|
205
|
+
if (pkgBumpy?.managed === true) return true;
|
|
206
|
+
if (config.include.some((pattern) => matchGlob(pkgName, pattern))) return true;
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (pkgBumpy?.managed === true) return true;
|
|
210
|
+
if (config.include.some((pattern) => matchGlob(pkgName, pattern))) return true;
|
|
211
|
+
if (isPrivate && !config.privatePackages.version) return false;
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
export { loadConfig as a, BUMP_LEVELS as c, DEFAULT_PUBLISH_CONFIG as d, DEP_TYPES as f, parseIsolatedBump as g, maxBump as h, isPackageManaged as i, DEFAULT_BUMP_RULES as l, hasCascade as m, findRoot as n, loadPackageConfig as o, bumpLevel as p, getBumpyDir as r, matchGlob as s, config_exports as t, DEFAULT_CONFIG as u };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/core/dep-graph.ts
|
|
2
|
+
var DependencyGraph = class {
|
|
3
|
+
/** Map from package name → packages that depend on it */
|
|
4
|
+
dependents = /* @__PURE__ */ new Map();
|
|
5
|
+
/** Set of all internal package names */
|
|
6
|
+
internalPackages;
|
|
7
|
+
constructor(packages) {
|
|
8
|
+
this.internalPackages = new Set(packages.keys());
|
|
9
|
+
this.build(packages);
|
|
10
|
+
}
|
|
11
|
+
build(packages) {
|
|
12
|
+
for (const [name, pkg] of packages) {
|
|
13
|
+
const depTypes = [
|
|
14
|
+
["dependencies", pkg.dependencies],
|
|
15
|
+
["devDependencies", pkg.devDependencies],
|
|
16
|
+
["peerDependencies", pkg.peerDependencies],
|
|
17
|
+
["optionalDependencies", pkg.optionalDependencies]
|
|
18
|
+
];
|
|
19
|
+
for (const [depType, deps] of depTypes) for (const [depName, versionRange] of Object.entries(deps)) {
|
|
20
|
+
if (!this.internalPackages.has(depName)) continue;
|
|
21
|
+
if (!this.dependents.has(depName)) this.dependents.set(depName, []);
|
|
22
|
+
this.dependents.get(depName).push({
|
|
23
|
+
name,
|
|
24
|
+
depType,
|
|
25
|
+
versionRange
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Get all packages that depend on the given package */
|
|
31
|
+
getDependents(pkgName) {
|
|
32
|
+
return this.dependents.get(pkgName) || [];
|
|
33
|
+
}
|
|
34
|
+
/** Check if a package is an internal workspace package */
|
|
35
|
+
isInternal(pkgName) {
|
|
36
|
+
return this.internalPackages.has(pkgName);
|
|
37
|
+
}
|
|
38
|
+
/** Get all internal package names */
|
|
39
|
+
allPackages() {
|
|
40
|
+
return [...this.internalPackages];
|
|
41
|
+
}
|
|
42
|
+
/** Topological sort — returns packages in dependency order (deps first) */
|
|
43
|
+
topologicalSort(packages) {
|
|
44
|
+
const visited = /* @__PURE__ */ new Set();
|
|
45
|
+
const result = [];
|
|
46
|
+
const visit = (name) => {
|
|
47
|
+
if (visited.has(name)) return;
|
|
48
|
+
visited.add(name);
|
|
49
|
+
const pkg = packages.get(name);
|
|
50
|
+
if (!pkg) return;
|
|
51
|
+
for (const deps of [
|
|
52
|
+
pkg.dependencies,
|
|
53
|
+
pkg.devDependencies,
|
|
54
|
+
pkg.peerDependencies,
|
|
55
|
+
pkg.optionalDependencies
|
|
56
|
+
]) for (const depName of Object.keys(deps)) if (this.internalPackages.has(depName)) visit(depName);
|
|
57
|
+
result.push(name);
|
|
58
|
+
};
|
|
59
|
+
for (const name of this.internalPackages) visit(name);
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
//#endregion
|
|
64
|
+
export { DependencyGraph as t };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { a as __exportAll } from "./logger-C2dEe5Su.mjs";
|
|
2
|
+
import { access, mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
//#region src/utils/fs.ts
|
|
4
|
+
var fs_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
ensureDir: () => ensureDir,
|
|
6
|
+
exists: () => exists,
|
|
7
|
+
listFiles: () => listFiles,
|
|
8
|
+
readJson: () => readJson,
|
|
9
|
+
readText: () => readText,
|
|
10
|
+
removeFile: () => removeFile,
|
|
11
|
+
writeJson: () => writeJson,
|
|
12
|
+
writeText: () => writeText
|
|
13
|
+
});
|
|
14
|
+
async function readJson(filePath) {
|
|
15
|
+
const content = await readFile(filePath, "utf-8");
|
|
16
|
+
return JSON.parse(content);
|
|
17
|
+
}
|
|
18
|
+
async function writeJson(filePath, data, indent = 2) {
|
|
19
|
+
await writeFile(filePath, JSON.stringify(data, null, indent) + "\n", "utf-8");
|
|
20
|
+
}
|
|
21
|
+
async function readText(filePath) {
|
|
22
|
+
return readFile(filePath, "utf-8");
|
|
23
|
+
}
|
|
24
|
+
async function writeText(filePath, content) {
|
|
25
|
+
await writeFile(filePath, content, "utf-8");
|
|
26
|
+
}
|
|
27
|
+
async function exists(filePath) {
|
|
28
|
+
try {
|
|
29
|
+
await access(filePath);
|
|
30
|
+
return true;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function listFiles(dir, ext) {
|
|
36
|
+
try {
|
|
37
|
+
const entries = await readdir(dir);
|
|
38
|
+
if (ext) return entries.filter((e) => e.endsWith(ext));
|
|
39
|
+
return entries;
|
|
40
|
+
} catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function removeFile(filePath) {
|
|
45
|
+
await unlink(filePath);
|
|
46
|
+
}
|
|
47
|
+
async function ensureDir(dir) {
|
|
48
|
+
await mkdir(dir, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { readJson as a, writeJson as c, listFiles as i, writeText as l, exists as n, readText as o, fs_exports as r, removeFile as s, ensureDir as t };
|