@enke.dev/bumper 0.0.3 → 0.0.5
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 +7 -4
- package/dist/cli.mjs +53 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,12 +19,15 @@ Dependencies are bumped by resolving each package's latest version via the repo'
|
|
|
19
19
|
manager (`pnpm view` / `npm view`, so private scoped registries + `.npmrc` auth just work),
|
|
20
20
|
rewriting `package.json` specs (preserving `^`/`~`), then letting the package manager reinstall.
|
|
21
21
|
|
|
22
|
-
Bumps are **peer-aware**: before rewriting, bumper reads the `peerDependencies` of every
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
Bumps are **peer-aware**: before rewriting, bumper reads the `peerDependencies` of every direct
|
|
23
|
+
dependency — for the version it's about to bump _to_, resolved from the registry rather than the
|
|
24
|
+
stale one in `node_modules` — and caps each shared dependency to the newest version still
|
|
25
|
+
satisfying every declared peer range. So a preset that peer-pins `typescript` to `6.0.3`
|
|
25
26
|
(e.g. [`@enke.dev/lint`](https://www.npmjs.com/package/@enke.dev/lint)) holds `typescript` at
|
|
26
27
|
`6.0.3` instead of jumping to a newer major that would break the preset — no per-repo config
|
|
27
|
-
needed, the declaration lives in the dependency itself.
|
|
28
|
+
needed, the declaration lives in the dependency itself. Because the peers are read for the target
|
|
29
|
+
version, a peer newly introduced (or changed) by that bump is honored in the **same run** — no
|
|
30
|
+
second pass needed to converge.
|
|
28
31
|
|
|
29
32
|
> **Note** — network runs through subprocesses (`curl` for the Node dist index, `pnpm`/`npm view`
|
|
30
33
|
> for versions, `actions-up` via `bunx`), so private-registry auth is handled by the tools that
|
package/dist/cli.mjs
CHANGED
|
@@ -2273,6 +2273,19 @@ async function latestVersion(pkg, tool, cwd, run2 = exec) {
|
|
|
2273
2273
|
return null;
|
|
2274
2274
|
}
|
|
2275
2275
|
}
|
|
2276
|
+
async function peerDependenciesOf(pkg, version, tool, cwd, run2 = exec) {
|
|
2277
|
+
try {
|
|
2278
|
+
const { exitCode, stdout } = await run2([tool, "view", `${pkg}@${version}`, "peerDependencies", "--json"], { cwd });
|
|
2279
|
+
const trimmed = stdout.trim();
|
|
2280
|
+
if (exitCode !== 0 || !trimmed) {
|
|
2281
|
+
return {};
|
|
2282
|
+
}
|
|
2283
|
+
const parsed = JSON.parse(trimmed);
|
|
2284
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
2285
|
+
} catch {
|
|
2286
|
+
return {};
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2276
2289
|
async function latestVersionInRange(pkg, range, tool, cwd, run2 = exec) {
|
|
2277
2290
|
try {
|
|
2278
2291
|
const { exitCode, stdout } = await run2([tool, "view", `${pkg}@${range}`, "version"], { cwd });
|
|
@@ -2298,7 +2311,7 @@ async function fetchLatestLts() {
|
|
|
2298
2311
|
}
|
|
2299
2312
|
const version = latest.version.replace(/^v/, "");
|
|
2300
2313
|
const major = Number(version.split(".")[0]);
|
|
2301
|
-
return { version, major };
|
|
2314
|
+
return { version, major, ...latest.npm ? { npm: latest.npm } : {} };
|
|
2302
2315
|
}
|
|
2303
2316
|
async function ensureNodeLts(ctx) {
|
|
2304
2317
|
ctx.nodeLts ??= await fetchLatestLts();
|
|
@@ -2491,7 +2504,11 @@ var BUCKETS2 = [
|
|
|
2491
2504
|
"peerDependencies"
|
|
2492
2505
|
];
|
|
2493
2506
|
var CONCURRENCY = 8;
|
|
2494
|
-
var defaultLookups = {
|
|
2507
|
+
var defaultLookups = {
|
|
2508
|
+
latestVersion,
|
|
2509
|
+
latestVersionInRange,
|
|
2510
|
+
peerDependencies: peerDependenciesOf
|
|
2511
|
+
};
|
|
2495
2512
|
async function collectPackages(ctx) {
|
|
2496
2513
|
const entries = await Promise.all(ctx.workspaces.map(async (dir) => [dir, await readPackageJson(dir)]));
|
|
2497
2514
|
return new Map(entries.filter((entry) => entry[1] !== null));
|
|
@@ -2503,13 +2520,20 @@ function collectNames(pkgs, managed) {
|
|
|
2503
2520
|
function collectDependencyNames(pkgs) {
|
|
2504
2521
|
return [...new Set([...pkgs.values()].flatMap((pkg) => Object.keys(allDependencies(pkg))))];
|
|
2505
2522
|
}
|
|
2506
|
-
async function
|
|
2523
|
+
async function targetVersion(cwd, dep, latest) {
|
|
2524
|
+
if (latest.has(dep)) {
|
|
2525
|
+
return latest.get(dep) ?? null;
|
|
2526
|
+
}
|
|
2527
|
+
return (await readPackageJson(join8(cwd, "node_modules", dep)))?.version ?? null;
|
|
2528
|
+
}
|
|
2529
|
+
async function collectPeerCaps(cwd, depNames, latest, managed, tool, lookups) {
|
|
2507
2530
|
const collected = new Map;
|
|
2508
2531
|
await Promise.all(depNames.map(async (dep) => {
|
|
2509
|
-
const
|
|
2510
|
-
if (!
|
|
2532
|
+
const version = await targetVersion(cwd, dep, latest);
|
|
2533
|
+
if (!version) {
|
|
2511
2534
|
return;
|
|
2512
2535
|
}
|
|
2536
|
+
const peers = await lookups.peerDependencies(dep, version, tool, cwd);
|
|
2513
2537
|
Object.entries(peers).forEach(([peer, range]) => {
|
|
2514
2538
|
if (managed.has(peer) || !isPinnable(range) && !isVersionRange(range)) {
|
|
2515
2539
|
return;
|
|
@@ -2530,7 +2554,7 @@ async function resolveLatest(names, tool, cwd, lookups) {
|
|
|
2530
2554
|
async function bumpPackageManagerField(ctx, root, lookups) {
|
|
2531
2555
|
const match = root?.packageManager?.match(/^([a-z]+)@(.+)$/);
|
|
2532
2556
|
const name = match?.[1];
|
|
2533
|
-
if (!root || !name) {
|
|
2557
|
+
if (!root || !name || name === "npm") {
|
|
2534
2558
|
return;
|
|
2535
2559
|
}
|
|
2536
2560
|
const version = await lookups.latestVersion(name, viewTool(ctx.packageManager), ctx.cwd);
|
|
@@ -2553,10 +2577,8 @@ async function upgradeAllWorkspaces(ctx, lookups = defaultLookups) {
|
|
|
2553
2577
|
return;
|
|
2554
2578
|
}
|
|
2555
2579
|
const tool = viewTool(ctx.packageManager);
|
|
2556
|
-
const
|
|
2557
|
-
|
|
2558
|
-
collectPeerCaps(ctx.cwd, collectDependencyNames(pkgs), managed)
|
|
2559
|
-
]);
|
|
2580
|
+
const latest = await resolveLatest(names, tool, ctx.cwd, lookups);
|
|
2581
|
+
const peerCaps = await collectPeerCaps(ctx.cwd, collectDependencyNames(pkgs), latest, managed, tool, lookups);
|
|
2560
2582
|
await Promise.all([...pkgs].map(async ([dir, pkg]) => {
|
|
2561
2583
|
if (await rewriteSpecs(pkg, managed, latest, peerCaps, tool, ctx.cwd, lookups)) {
|
|
2562
2584
|
await writePackageJson(dir, pkg);
|
|
@@ -2644,6 +2666,26 @@ var bunPackageManager = {
|
|
|
2644
2666
|
};
|
|
2645
2667
|
|
|
2646
2668
|
// src/modules/package-managers/npm/npm.package-manager.ts
|
|
2669
|
+
async function alignNpmToNodeLts(ctx) {
|
|
2670
|
+
const root = await readPackageJson(ctx.cwd);
|
|
2671
|
+
if (!root?.packageManager?.startsWith("npm@")) {
|
|
2672
|
+
return;
|
|
2673
|
+
}
|
|
2674
|
+
const { npm } = await ensureNodeLts(ctx);
|
|
2675
|
+
if (!npm) {
|
|
2676
|
+
return;
|
|
2677
|
+
}
|
|
2678
|
+
const next = `npm@${npm}`;
|
|
2679
|
+
if (next === root.packageManager) {
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2682
|
+
if (ctx.dryRun) {
|
|
2683
|
+
planLine(`set packageManager to ${next} (bundled with Node LTS)`);
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2686
|
+
root.packageManager = next;
|
|
2687
|
+
await writePackageJson(ctx.cwd, root);
|
|
2688
|
+
}
|
|
2647
2689
|
var npmPackageManager = {
|
|
2648
2690
|
kind: "package-manager" /* PackageManager */,
|
|
2649
2691
|
id: "npm",
|
|
@@ -2653,6 +2695,7 @@ var npmPackageManager = {
|
|
|
2653
2695
|
},
|
|
2654
2696
|
async update(ctx) {
|
|
2655
2697
|
await upgradeAllWorkspaces(ctx);
|
|
2698
|
+
await alignNpmToNodeLts(ctx);
|
|
2656
2699
|
await cleanInstall(ctx, ["npm", "install"]);
|
|
2657
2700
|
}
|
|
2658
2701
|
};
|