rolldown-pnpm-config 0.3.0 → 0.4.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.
- package/bin/rolldown-pnpm-config.js +3 -6
- package/cli/commands/export.js +4 -4
- package/cli/commands/preview.js +2 -2
- package/cli/commands/upgrade.js +25 -28
- package/cli/interop.js +10 -10
- package/cli/peer-range.js +1 -1
- package/cli/plan.js +3 -3
- package/cli/resolve.js +31 -11
- package/cli/ui/run-preview.js +1 -1
- package/cli/ui/run-walk.js +1 -1
- package/cli/validate.js +3 -3
- package/cli/workspace-file.js +7 -7
- package/descriptors/build.js +6 -1
- package/descriptors/hoisting.js +17 -3
- package/descriptors/misc.js +10 -2
- package/descriptors/resolution.js +2 -5
- package/descriptors/runtime-cfg.js +12 -2
- package/descriptors/schemas.js +4 -16
- package/descriptors/workspace.js +13 -4
- package/package.json +6 -16
- package/plugin/freeze.js +2 -2
- package/virtual.d.ts +12 -2
|
@@ -3,8 +3,8 @@ import { exportCommand } from "../cli/commands/export.js";
|
|
|
3
3
|
import { previewCommand } from "../cli/commands/preview.js";
|
|
4
4
|
import { upgradeCommand } from "../cli/commands/upgrade.js";
|
|
5
5
|
import { Effect } from "effect";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { NodeRuntime, NodeServices } from "@effect/platform-node";
|
|
7
|
+
import { Command } from "effect/unstable/cli";
|
|
8
8
|
|
|
9
9
|
//#region src/cli/bin.ts
|
|
10
10
|
const root = Command.make("rolldown-pnpm-config").pipe(Command.withSubcommands([
|
|
@@ -12,10 +12,7 @@ const root = Command.make("rolldown-pnpm-config").pipe(Command.withSubcommands([
|
|
|
12
12
|
exportCommand,
|
|
13
13
|
previewCommand
|
|
14
14
|
]));
|
|
15
|
-
Command.run(root, {
|
|
16
|
-
name: "rolldown-pnpm-config",
|
|
17
|
-
version: "0.3.0"
|
|
18
|
-
})(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain);
|
|
15
|
+
Command.run(root, { version: "0.4.0" }).pipe(Effect.provide(NodeServices.layer), NodeRuntime.runMain);
|
|
19
16
|
|
|
20
17
|
//#endregion
|
|
21
18
|
export { };
|
package/cli/commands/export.js
CHANGED
|
@@ -16,7 +16,7 @@ import { overlayWorkspace } from "../workspace-overlay.js";
|
|
|
16
16
|
import { Data, Effect, Option } from "effect";
|
|
17
17
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
18
18
|
import { dirname, join, relative } from "node:path";
|
|
19
|
-
import {
|
|
19
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
20
20
|
|
|
21
21
|
//#region src/cli/commands/export.ts
|
|
22
22
|
/**
|
|
@@ -110,9 +110,9 @@ function runExport(opts) {
|
|
|
110
110
|
};
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
|
-
const pathArg =
|
|
114
|
-
const dryRunFlag =
|
|
115
|
-
const fullFlag =
|
|
113
|
+
const pathArg = Argument.file("path").pipe(Argument.optional);
|
|
114
|
+
const dryRunFlag = Flag.boolean("dry-run").pipe(Flag.withDefault(false));
|
|
115
|
+
const fullFlag = Flag.boolean("full").pipe(Flag.withDefault(false));
|
|
116
116
|
/**
|
|
117
117
|
* The "export" command. Materializes the plugin config into pnpm-workspace.yaml.
|
|
118
118
|
* An optional path argument overrides the auto-detected workspace file. --dry-run
|
package/cli/commands/preview.js
CHANGED
|
@@ -11,7 +11,7 @@ import { runPreview } from "../ui/run-preview.js";
|
|
|
11
11
|
import { Data, Effect, Option } from "effect";
|
|
12
12
|
import { existsSync, readFileSync } from "node:fs";
|
|
13
13
|
import { dirname, join } from "node:path";
|
|
14
|
-
import {
|
|
14
|
+
import { Argument, Command } from "effect/unstable/cli";
|
|
15
15
|
|
|
16
16
|
//#region src/cli/commands/preview.ts
|
|
17
17
|
/** Typed failure for the preview run. @internal */
|
|
@@ -48,7 +48,7 @@ function runPreviewViews(opts) {
|
|
|
48
48
|
});
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
|
-
const pathArg =
|
|
51
|
+
const pathArg = Argument.file("path").pipe(Argument.optional);
|
|
52
52
|
/**
|
|
53
53
|
* The "preview" command: interactive ink-tab explorer of the export diff
|
|
54
54
|
* (Changes / Full / Simulated). Falls back to printing the Changes view when
|
package/cli/commands/upgrade.js
CHANGED
|
@@ -14,10 +14,10 @@ import { renderSummary } from "../summary.js";
|
|
|
14
14
|
import { runWalk } from "../ui/run-walk.js";
|
|
15
15
|
import { validateEdits } from "../validate.js";
|
|
16
16
|
import { buildWalkItems } from "../walk-plan.js";
|
|
17
|
-
import { Data, Effect, Option } from "effect";
|
|
17
|
+
import { Data, Effect, Option, Result } from "effect";
|
|
18
18
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
19
|
+
import { NodeServices } from "@effect/platform-node";
|
|
20
|
+
import { Argument, Command, Flag } from "effect/unstable/cli";
|
|
21
21
|
|
|
22
22
|
//#region src/cli/commands/upgrade.ts
|
|
23
23
|
/**
|
|
@@ -29,9 +29,9 @@ var UpgradeError = class extends Data.TaggedError("UpgradeError") {};
|
|
|
29
29
|
/** Combine the config-declared and pnpm-resolved release-age gates (strictest of both). @internal */
|
|
30
30
|
function computeGate(source, file, resolver) {
|
|
31
31
|
return Effect.gen(function* () {
|
|
32
|
-
const { config } = yield* Effect.try(() => evaluatePluginConfig(source, file)).pipe(Effect.
|
|
32
|
+
const { config } = yield* Effect.try(() => evaluatePluginConfig(source, file)).pipe(Effect.catch(() => Effect.succeed({ config: null })));
|
|
33
33
|
const cfg = readConfigReleaseAge(config);
|
|
34
|
-
const [age, exc] = yield* Effect.all([resolver.pnpmConfig("minimumReleaseAge").pipe(Effect.
|
|
34
|
+
const [age, exc] = yield* Effect.all([resolver.pnpmConfig("minimumReleaseAge").pipe(Effect.catch(() => Effect.succeed(null))), resolver.pnpmConfig("minimumReleaseAgeExclude").pipe(Effect.catch(() => Effect.succeed(null)))], { concurrency: "unbounded" });
|
|
35
35
|
return combineReleaseAge(cfg, parsePnpmGate(age, exc));
|
|
36
36
|
});
|
|
37
37
|
}
|
|
@@ -52,8 +52,8 @@ function resolveGatedVersions(entries, resolver, gate, now, onProgress) {
|
|
|
52
52
|
let resolved = 0;
|
|
53
53
|
onProgress?.(0, total);
|
|
54
54
|
return Effect.forEach(uniquePkgs, (pkg) => Effect.gen(function* () {
|
|
55
|
-
const vr = yield* resolver.versions(pkg).pipe(Effect.
|
|
56
|
-
if (vr
|
|
55
|
+
const vr = yield* resolver.versions(pkg).pipe(Effect.result);
|
|
56
|
+
if (Result.isFailure(vr)) {
|
|
57
57
|
onProgress?.(++resolved, total);
|
|
58
58
|
return [
|
|
59
59
|
pkg,
|
|
@@ -61,12 +61,12 @@ function resolveGatedVersions(entries, resolver, gate, now, onProgress) {
|
|
|
61
61
|
[]
|
|
62
62
|
];
|
|
63
63
|
}
|
|
64
|
-
const times = gate.ageMinutes > 0 ? yield* resolver.times(pkg).pipe(Effect.
|
|
64
|
+
const times = gate.ageMinutes > 0 ? yield* resolver.times(pkg).pipe(Effect.catch(() => Effect.succeed({}))) : {};
|
|
65
65
|
onProgress?.(++resolved, total);
|
|
66
66
|
return [
|
|
67
67
|
pkg,
|
|
68
|
-
filterByReleaseAge(vr.
|
|
69
|
-
vr.
|
|
68
|
+
filterByReleaseAge(vr.success, times, gate, pkg, now),
|
|
69
|
+
vr.success
|
|
70
70
|
];
|
|
71
71
|
}), { concurrency: 12 }).pipe(Effect.map((triples) => ({
|
|
72
72
|
gated: new Map(triples.map(([pkg, gated]) => [pkg, gated])),
|
|
@@ -148,12 +148,12 @@ function runUpgrade(opts) {
|
|
|
148
148
|
kind: "peer",
|
|
149
149
|
value
|
|
150
150
|
});
|
|
151
|
-
const derived = entry.strategy ? yield* derivePeerRange(entry.currentRange, entry.strategy).pipe(Effect.
|
|
151
|
+
const derived = entry.strategy ? yield* derivePeerRange(entry.currentRange, entry.strategy).pipe(Effect.catch(() => Effect.succeed(null))) : null;
|
|
152
152
|
if (derived?.warning) warnings.push(`${entry.pkg}: ${derived.warning.message}`);
|
|
153
153
|
if (versions.length === 0) {
|
|
154
154
|
const at = entry.rangeSpan[1];
|
|
155
155
|
if (entry.peer && entry.strategy) {
|
|
156
|
-
const expected = yield* detectPeerDrift(entry).pipe(Effect.
|
|
156
|
+
const expected = yield* detectPeerDrift(entry).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
157
157
|
if (expected !== null) {
|
|
158
158
|
edits.push(peerEdit(entry.peer.span, expected));
|
|
159
159
|
changedSpans.add(entry.rangeSpan[0]);
|
|
@@ -167,7 +167,7 @@ function runUpgrade(opts) {
|
|
|
167
167
|
skipped.push(`${entry.catalog}.${entry.pkg}`);
|
|
168
168
|
continue;
|
|
169
169
|
}
|
|
170
|
-
const inRange = (yield* planEntry(entry, versions).pipe(Effect.
|
|
170
|
+
const inRange = (yield* planEntry(entry, versions).pipe(Effect.catch(() => Effect.succeed([])))).find((c) => c.kind === "in-range");
|
|
171
171
|
const at = entry.rangeSpan[1];
|
|
172
172
|
if (inRange) {
|
|
173
173
|
edits.push(rangeEdit(entry.rangeSpan, inRange.range));
|
|
@@ -178,7 +178,7 @@ function runUpgrade(opts) {
|
|
|
178
178
|
edits.push(peerInsert(at, derived.range));
|
|
179
179
|
changedSpans.add(entry.rangeSpan[0]);
|
|
180
180
|
} else if (entry.peer && entry.strategy) {
|
|
181
|
-
const expected = yield* detectPeerDrift(entry).pipe(Effect.
|
|
181
|
+
const expected = yield* detectPeerDrift(entry).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
182
182
|
if (expected !== null) {
|
|
183
183
|
edits.push(peerEdit(entry.peer.span, expected));
|
|
184
184
|
changedSpans.add(entry.rangeSpan[0]);
|
|
@@ -197,7 +197,7 @@ function runUpgrade(opts) {
|
|
|
197
197
|
const members = [];
|
|
198
198
|
for (const e of group) {
|
|
199
199
|
const versions = versionsByPkg.gated.get(e.pkg) ?? [];
|
|
200
|
-
const inRange = (yield* planEntry(e, versions).pipe(Effect.
|
|
200
|
+
const inRange = (yield* planEntry(e, versions).pipe(Effect.catch(() => Effect.succeed([])))).find((c) => c.kind === "in-range");
|
|
201
201
|
const ceiling = inRange ? inRange.version : e.currentRange.replace(/^[\^~]/, "");
|
|
202
202
|
members.push({
|
|
203
203
|
pkg: e.pkg,
|
|
@@ -334,7 +334,7 @@ function runUpgradePreview(opts) {
|
|
|
334
334
|
});
|
|
335
335
|
const gate = yield* computeGate(source, opts.file, opts.resolver);
|
|
336
336
|
const versions = yield* resolveGatedVersions(discovered.entries, opts.resolver, gate, Date.now());
|
|
337
|
-
const text = renderSummary(projectDecisions(yield* buildWalkItems(discovered.entries, versions.gated).pipe(Effect.
|
|
337
|
+
const text = renderSummary(projectDecisions(yield* buildWalkItems(discovered.entries, versions.gated).pipe(Effect.catch((e) => Effect.fail(new UpgradeError({ message: e.message })))), opts.full), void 0, { color: opts.color ?? false });
|
|
338
338
|
return versions.unresolved.length > 0 ? `${text}\n⚠ ${unresolvedMessage(versions.unresolved)}` : text;
|
|
339
339
|
});
|
|
340
340
|
}
|
|
@@ -352,15 +352,12 @@ function resolveTargetFile(fileOpt) {
|
|
|
352
352
|
return picked.file;
|
|
353
353
|
});
|
|
354
354
|
}
|
|
355
|
-
const fileArg =
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
const
|
|
361
|
-
const catalogOption = Options.text("catalog").pipe(Options.optional);
|
|
362
|
-
const previewFlag = Options.boolean("preview").pipe(Options.withDefault(false));
|
|
363
|
-
const fullFlag = Options.boolean("full").pipe(Options.withDefault(false));
|
|
355
|
+
const fileArg = Argument.file("file", { mustExist: true }).pipe(Argument.optional);
|
|
356
|
+
const yesFlag = Flag.boolean("yes").pipe(Flag.withAlias("y"), Flag.withDefault(false));
|
|
357
|
+
const dryRunFlag = Flag.boolean("dry-run").pipe(Flag.withDefault(false));
|
|
358
|
+
const catalogOption = Flag.string("catalog").pipe(Flag.optional);
|
|
359
|
+
const previewFlag = Flag.boolean("preview").pipe(Flag.withDefault(false));
|
|
360
|
+
const fullFlag = Flag.boolean("full").pipe(Flag.withDefault(false));
|
|
364
361
|
/**
|
|
365
362
|
* The "upgrade" command. The default path runs the interactive table;
|
|
366
363
|
* --yes applies latest-in-range non-interactively; --dry-run runs the identical
|
|
@@ -415,7 +412,7 @@ const upgradeCommand = Command.make("upgrade", {
|
|
|
415
412
|
const catalogName = Option.getOrUndefined(catalog);
|
|
416
413
|
const entries = filterEntriesByCatalog(discovered.entries, catalogName);
|
|
417
414
|
const versions = yield* resolveGatedVersions(entries, resolver, yield* computeGate(source, file, resolver), Date.now(), caps.interactive ? writeResolveProgress : void 0);
|
|
418
|
-
const items = yield* buildWalkItems(entries, versions.gated).pipe(Effect.
|
|
415
|
+
const items = yield* buildWalkItems(entries, versions.gated).pipe(Effect.catch((e) => Effect.fail(new UpgradeError({ message: e.message }))));
|
|
419
416
|
if (!caps.interactive) {
|
|
420
417
|
const text = renderSummary(projectDecisions(items, full), void 0, { color: caps.color });
|
|
421
418
|
const note = dryRun ? "(dry run — nothing written)" : "(non-interactive terminal — run with --yes to apply, or in a TTY to choose)";
|
|
@@ -466,7 +463,7 @@ const upgradeCommand = Command.make("upgrade", {
|
|
|
466
463
|
const all = versions.gated.get(rc.pkg) ?? [];
|
|
467
464
|
cappedVersions.set(rc.pkg, rc.cap === null ? all : yield* capVersions(all, rc.cap));
|
|
468
465
|
}
|
|
469
|
-
const reDecisions = yield* runWalk(yield* buildWalkItems(capEntries, cappedVersions).pipe(Effect.
|
|
466
|
+
const reDecisions = yield* runWalk(yield* buildWalkItems(capEntries, cappedVersions).pipe(Effect.catch((err) => Effect.fail(new UpgradeError({ message: err.message })))));
|
|
470
467
|
const before = new Map(members.map((m) => [m.pkg, m.ceiling]));
|
|
471
468
|
members = members.map((m) => {
|
|
472
469
|
const rd = reDecisions.find((d) => d.item.entry.pkg === m.pkg);
|
|
@@ -504,7 +501,7 @@ const upgradeCommand = Command.make("upgrade", {
|
|
|
504
501
|
const changed = countChangedDecisions(nonInteropDecisions.filter((d) => acceptedPkgs.has(d.item.entry.pkg))) + interopChanged;
|
|
505
502
|
yield* Effect.sync(() => process.stdout.write(dryRun ? `Dry run — no changes written. ${changed} change(s) would be applied.\n` : `Applied ${changed} change(s).\n`));
|
|
506
503
|
if (versions.unresolved.length > 0) yield* Effect.sync(() => process.stdout.write(`\n⚠ ${unresolvedMessage(versions.unresolved)}\n`));
|
|
507
|
-
}).pipe(Effect.provide(RegistryResolverLive), Effect.provide(
|
|
504
|
+
}).pipe(Effect.provide(RegistryResolverLive), Effect.provide(NodeServices.layer))).pipe(Command.withDescription("Upgrade catalog versions in a config file"));
|
|
508
505
|
|
|
509
506
|
//#endregion
|
|
510
507
|
export { UpgradeError, actionableWalkItems, applyInteropAndDecisions, computeGate, countChangedDecisions, nothingToUpgradeMessage, projectDecisions, resolveGatedVersions, resolveTargetFile, runUpgrade, runUpgradePreview, unresolvedMessage, upgradeCommand, writeResolveProgress };
|
package/cli/interop.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { Range, SemVer } from "semver
|
|
2
|
+
import { Range, SemVer } from "@effected/semver";
|
|
3
3
|
|
|
4
4
|
//#region src/cli/interop.ts
|
|
5
5
|
/** Maximum number of concurrent peerDependencies fetches inside runInterop. @internal */
|
|
@@ -34,7 +34,7 @@ function deriveFloors(resolved, fetchPeer) {
|
|
|
34
34
|
const valid = (yield* Effect.forEach(declared, (f) => SemVer.parse(f).pipe(Effect.map((sv) => ({
|
|
35
35
|
f,
|
|
36
36
|
sv
|
|
37
|
-
})), Effect.
|
|
37
|
+
})), Effect.catch(() => Effect.succeed(null))))).filter((x) => x !== null);
|
|
38
38
|
valid.sort((a, b) => a.sv.compare(b.sv));
|
|
39
39
|
out.set(pkg, `^${valid[0]?.f ?? version}`);
|
|
40
40
|
} else out.set(pkg, `^${version}`);
|
|
@@ -45,9 +45,9 @@ function deriveFloors(resolved, fetchPeer) {
|
|
|
45
45
|
/** Does `version` satisfy `range`? Unparseable input is treated as not-satisfied. */
|
|
46
46
|
function satisfies(version, range) {
|
|
47
47
|
return Effect.gen(function* () {
|
|
48
|
-
const r = yield* Range.parse(range).pipe(Effect.
|
|
48
|
+
const r = yield* Range.parse(range).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
49
49
|
if (!r) return false;
|
|
50
|
-
const v = yield* SemVer.parse(version).pipe(Effect.
|
|
50
|
+
const v = yield* SemVer.parse(version).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
51
51
|
return v ? r.test(v) : false;
|
|
52
52
|
});
|
|
53
53
|
}
|
|
@@ -81,8 +81,8 @@ function resolveGroup(members, fetchPeer) {
|
|
|
81
81
|
const resolved = new Map(members.map((m) => [m.pkg, m.ceiling]));
|
|
82
82
|
const ceilingOf = new Map(members.map((m) => [m.pkg, m.ceiling]));
|
|
83
83
|
const leq = (a, b) => Effect.gen(function* () {
|
|
84
|
-
const av = yield* SemVer.parse(a).pipe(Effect.
|
|
85
|
-
const bv = yield* SemVer.parse(b).pipe(Effect.
|
|
84
|
+
const av = yield* SemVer.parse(a).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
85
|
+
const bv = yield* SemVer.parse(b).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
86
86
|
return av && bv ? av.compare(bv) <= 0 : false;
|
|
87
87
|
});
|
|
88
88
|
const maxIter = members.reduce((n, m) => n + m.candidates.length, 0) + members.length + 1;
|
|
@@ -130,7 +130,7 @@ function sortDesc(versions) {
|
|
|
130
130
|
const parsed = yield* Effect.forEach(versions, (v) => SemVer.parse(v).pipe(Effect.map((sv) => ({
|
|
131
131
|
v,
|
|
132
132
|
sv
|
|
133
|
-
})), Effect.
|
|
133
|
+
})), Effect.catch(() => Effect.succeed({
|
|
134
134
|
v,
|
|
135
135
|
sv: null
|
|
136
136
|
}))));
|
|
@@ -165,7 +165,7 @@ function runInterop(members, resolver, cache = /* @__PURE__ */ new Map()) {
|
|
|
165
165
|
const k = key(pkg, v);
|
|
166
166
|
const cached = cache.get(k);
|
|
167
167
|
if (cached !== void 0) return Effect.succeed(cached);
|
|
168
|
-
return resolver.peerDependencies(pkg, v).pipe(Effect.
|
|
168
|
+
return resolver.peerDependencies(pkg, v).pipe(Effect.catch(() => Effect.succeed({}))).pipe(Effect.map((deps) => {
|
|
169
169
|
cache.set(k, deps);
|
|
170
170
|
return deps;
|
|
171
171
|
}));
|
|
@@ -270,11 +270,11 @@ function buildInteropEdits(entries, result) {
|
|
|
270
270
|
*/
|
|
271
271
|
function capVersions(list, max) {
|
|
272
272
|
return Effect.gen(function* () {
|
|
273
|
-
const mv = yield* SemVer.parse(max).pipe(Effect.
|
|
273
|
+
const mv = yield* SemVer.parse(max).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
274
274
|
if (!mv) return [...list];
|
|
275
275
|
const out = [];
|
|
276
276
|
for (const v of list) {
|
|
277
|
-
const sv = yield* SemVer.parse(v).pipe(Effect.
|
|
277
|
+
const sv = yield* SemVer.parse(v).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
278
278
|
if (sv && sv.compare(mv) <= 0) out.push(v);
|
|
279
279
|
}
|
|
280
280
|
return out;
|
package/cli/peer-range.js
CHANGED
package/cli/plan.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { derivePeerRange } from "./peer-range.js";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
|
-
import { Range, SemVer } from "semver
|
|
3
|
+
import { Range, SemVer } from "@effected/semver";
|
|
4
4
|
|
|
5
5
|
//#region src/cli/plan.ts
|
|
6
6
|
/** Parse a version, returning null instead of failing (filters junk tags). */
|
|
7
|
-
const parseOrNull = (v) => SemVer.parse(v).pipe(Effect.
|
|
7
|
+
const parseOrNull = (v) => SemVer.parse(v).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
8
8
|
/**
|
|
9
9
|
* Compute the candidate versions for one catalog entry against the list of
|
|
10
10
|
* published versions. Order: latest in-range (when newer than current), latest
|
|
@@ -16,7 +16,7 @@ const parseOrNull = (v) => SemVer.parse(v).pipe(Effect.catchAll(() => Effect.suc
|
|
|
16
16
|
*/
|
|
17
17
|
function planEntry(entry, versions) {
|
|
18
18
|
return Effect.gen(function* () {
|
|
19
|
-
const range = yield* Range.parse(entry.currentRange).pipe(Effect.
|
|
19
|
+
const range = yield* Range.parse(entry.currentRange).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
20
20
|
const currentStripped = entry.currentRange.replace(/^[\^~]/, "");
|
|
21
21
|
const current = yield* parseOrNull(currentStripped);
|
|
22
22
|
const currentMajor = current?.major ?? 0;
|
package/cli/resolve.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Context, Data, Effect, Layer } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
|
|
3
3
|
|
|
4
4
|
//#region src/cli/resolve.ts
|
|
5
|
+
const Spawner = ChildProcessSpawner.ChildProcessSpawner;
|
|
5
6
|
/**
|
|
6
7
|
* Typed failure raised when a package's versions cannot be resolved.
|
|
7
8
|
*
|
|
@@ -15,7 +16,7 @@ var ResolveError = class extends Data.TaggedError("ResolveError") {};
|
|
|
15
16
|
*
|
|
16
17
|
* @internal
|
|
17
18
|
*/
|
|
18
|
-
var RegistryResolver = class extends Context.
|
|
19
|
+
var RegistryResolver = class extends Context.Service()("RegistryResolver") {};
|
|
19
20
|
/** Parse `pnpm view ... versions --json` stdout: a JSON array, or a single JSON string. */
|
|
20
21
|
function parseVersions(pkg, stdout) {
|
|
21
22
|
return Effect.try({
|
|
@@ -75,32 +76,51 @@ function parsePeerDeps(pkg, stdout) {
|
|
|
75
76
|
* @internal
|
|
76
77
|
*/
|
|
77
78
|
const RegistryResolverLive = Layer.effect(RegistryResolver, Effect.gen(function* () {
|
|
78
|
-
const
|
|
79
|
+
const spawner = yield* Spawner;
|
|
79
80
|
return {
|
|
80
81
|
versions: (pkg) => Effect.gen(function* () {
|
|
81
|
-
const cmd =
|
|
82
|
-
|
|
82
|
+
const cmd = ChildProcess.make("pnpm", [
|
|
83
|
+
"view",
|
|
84
|
+
pkg,
|
|
85
|
+
"versions",
|
|
86
|
+
"--json"
|
|
87
|
+
]);
|
|
88
|
+
return yield* parseVersions(pkg, yield* spawner.string(cmd).pipe(Effect.mapError((e) => new ResolveError({
|
|
83
89
|
pkg,
|
|
84
90
|
message: String(e)
|
|
85
91
|
}))));
|
|
86
92
|
}),
|
|
87
93
|
times: (pkg) => Effect.gen(function* () {
|
|
88
|
-
const cmd =
|
|
89
|
-
|
|
94
|
+
const cmd = ChildProcess.make("pnpm", [
|
|
95
|
+
"view",
|
|
96
|
+
pkg,
|
|
97
|
+
"time",
|
|
98
|
+
"--json"
|
|
99
|
+
]);
|
|
100
|
+
return yield* parseTimes(pkg, yield* spawner.string(cmd).pipe(Effect.mapError((e) => new ResolveError({
|
|
90
101
|
pkg,
|
|
91
102
|
message: String(e)
|
|
92
103
|
}))));
|
|
93
104
|
}),
|
|
94
105
|
peerDependencies: (pkg, version) => Effect.gen(function* () {
|
|
95
|
-
const cmd =
|
|
96
|
-
|
|
106
|
+
const cmd = ChildProcess.make("pnpm", [
|
|
107
|
+
"view",
|
|
108
|
+
`${pkg}@${version}`,
|
|
109
|
+
"peerDependencies",
|
|
110
|
+
"--json"
|
|
111
|
+
]);
|
|
112
|
+
return yield* parsePeerDeps(pkg, yield* spawner.string(cmd).pipe(Effect.mapError((e) => new ResolveError({
|
|
97
113
|
pkg,
|
|
98
114
|
message: String(e)
|
|
99
115
|
}))));
|
|
100
116
|
}),
|
|
101
117
|
pnpmConfig: (key) => Effect.gen(function* () {
|
|
102
|
-
const cmd =
|
|
103
|
-
|
|
118
|
+
const cmd = ChildProcess.make("pnpm", [
|
|
119
|
+
"config",
|
|
120
|
+
"get",
|
|
121
|
+
key
|
|
122
|
+
]);
|
|
123
|
+
return yield* spawner.string(cmd).pipe(Effect.map((s) => s.trim()), Effect.catch(() => Effect.succeed(null)));
|
|
104
124
|
})
|
|
105
125
|
};
|
|
106
126
|
}));
|
package/cli/ui/run-preview.js
CHANGED
package/cli/ui/run-walk.js
CHANGED
|
@@ -12,7 +12,7 @@ import { createElement } from "react";
|
|
|
12
12
|
* @internal
|
|
13
13
|
*/
|
|
14
14
|
function runWalk(items, dryRun = false, unresolved = []) {
|
|
15
|
-
return Effect.
|
|
15
|
+
return Effect.callback((resume) => {
|
|
16
16
|
let collected = [];
|
|
17
17
|
render(createElement(Walk, {
|
|
18
18
|
items,
|
package/cli/validate.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import { Range, SemVer } from "semver
|
|
2
|
+
import { Range, SemVer } from "@effected/semver";
|
|
3
3
|
|
|
4
4
|
//#region src/cli/validate.ts
|
|
5
5
|
/**
|
|
@@ -21,10 +21,10 @@ import { Range, SemVer } from "semver-effect";
|
|
|
21
21
|
function rangeIsSatisfiable(range, versions) {
|
|
22
22
|
return Effect.gen(function* () {
|
|
23
23
|
if (versions.length === 0) return true;
|
|
24
|
-
const parsedRange = yield* Range.parse(range).pipe(Effect.
|
|
24
|
+
const parsedRange = yield* Range.parse(range).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
25
25
|
if (parsedRange === null) return true;
|
|
26
26
|
for (const v of versions) {
|
|
27
|
-
const sv = yield* SemVer.parse(v).pipe(Effect.
|
|
27
|
+
const sv = yield* SemVer.parse(v).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
28
28
|
if (sv && parsedRange.test(sv)) return true;
|
|
29
29
|
}
|
|
30
30
|
return false;
|
package/cli/workspace-file.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { dirname, join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
+
import { Yaml, YamlStringifyOptions } from "@effected/yaml";
|
|
4
5
|
|
|
5
6
|
//#region src/cli/workspace-file.ts
|
|
6
7
|
const FILENAME = "pnpm-workspace.yaml";
|
|
7
|
-
const STRINGIFY_OPTIONS = {
|
|
8
|
+
const STRINGIFY_OPTIONS = YamlStringifyOptions.make({
|
|
8
9
|
indent: 2,
|
|
9
|
-
lineWidth: 0
|
|
10
|
-
|
|
11
|
-
};
|
|
10
|
+
lineWidth: 0
|
|
11
|
+
});
|
|
12
12
|
/** True when every element is a string/number/boolean (safe to sort). */
|
|
13
13
|
function allPrimitive(arr) {
|
|
14
14
|
return arr.every((v) => v === null || typeof v !== "object" && typeof v !== "function");
|
|
@@ -46,12 +46,12 @@ function findWorkspaceFile(startDir) {
|
|
|
46
46
|
}
|
|
47
47
|
/** Parse pnpm-workspace.yaml source; empty/whitespace yields an empty object. @internal */
|
|
48
48
|
function parseWorkspace(source) {
|
|
49
|
-
const parsed = parse(source);
|
|
49
|
+
const parsed = Effect.runSync(Yaml.parse(source));
|
|
50
50
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
51
51
|
}
|
|
52
52
|
/** Render a workspace object: deterministic key sort + yaml.stringify. @internal */
|
|
53
53
|
function renderWorkspace(obj) {
|
|
54
|
-
return stringify(canonicalize(obj), STRINGIFY_OPTIONS);
|
|
54
|
+
return Effect.runSync(Yaml.stringify(canonicalize(obj), STRINGIFY_OPTIONS));
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
//#endregion
|
package/descriptors/build.js
CHANGED
|
@@ -104,7 +104,12 @@ const build = {
|
|
|
104
104
|
anchor: "nodeoptions"
|
|
105
105
|
},
|
|
106
106
|
verifyDepsBeforeRun: {
|
|
107
|
-
schema: Schema.Union(Schema.
|
|
107
|
+
schema: Schema.Union([Schema.Literals([
|
|
108
|
+
"install",
|
|
109
|
+
"warn",
|
|
110
|
+
"error",
|
|
111
|
+
"prompt"
|
|
112
|
+
]), Schema.Boolean]),
|
|
108
113
|
kind: "union",
|
|
109
114
|
strategy: "scalar",
|
|
110
115
|
enforcement: "absent",
|
package/descriptors/hoisting.js
CHANGED
|
@@ -41,7 +41,11 @@ const hoisting = {
|
|
|
41
41
|
anchor: "shamefullyhoist"
|
|
42
42
|
},
|
|
43
43
|
hoistingLimits: {
|
|
44
|
-
schema: Schema.
|
|
44
|
+
schema: Schema.Literals([
|
|
45
|
+
"none",
|
|
46
|
+
"workspaces",
|
|
47
|
+
"dependencies"
|
|
48
|
+
]),
|
|
45
49
|
kind: "enum",
|
|
46
50
|
strategy: "scalar",
|
|
47
51
|
enforcement: "absent",
|
|
@@ -63,7 +67,11 @@ const hoisting = {
|
|
|
63
67
|
anchor: "modulesdir"
|
|
64
68
|
},
|
|
65
69
|
nodeLinker: {
|
|
66
|
-
schema: Schema.
|
|
70
|
+
schema: Schema.Literals([
|
|
71
|
+
"isolated",
|
|
72
|
+
"hoisted",
|
|
73
|
+
"pnp"
|
|
74
|
+
]),
|
|
67
75
|
kind: "enum",
|
|
68
76
|
strategy: "scalar",
|
|
69
77
|
enforcement: "absent",
|
|
@@ -121,7 +129,13 @@ const hoisting = {
|
|
|
121
129
|
anchor: "virtualstoreonly"
|
|
122
130
|
},
|
|
123
131
|
packageImportMethod: {
|
|
124
|
-
schema: Schema.
|
|
132
|
+
schema: Schema.Literals([
|
|
133
|
+
"auto",
|
|
134
|
+
"hardlink",
|
|
135
|
+
"copy",
|
|
136
|
+
"clone",
|
|
137
|
+
"clone-or-copy"
|
|
138
|
+
]),
|
|
125
139
|
kind: "enum",
|
|
126
140
|
strategy: "scalar",
|
|
127
141
|
enforcement: "absent",
|
package/descriptors/misc.js
CHANGED
|
@@ -5,7 +5,11 @@ import { Schema } from "effect";
|
|
|
5
5
|
/** The 14 resolution/misc preference fields. @internal */
|
|
6
6
|
const misc = {
|
|
7
7
|
resolutionMode: {
|
|
8
|
-
schema: Schema.
|
|
8
|
+
schema: Schema.Literals([
|
|
9
|
+
"highest",
|
|
10
|
+
"time-based",
|
|
11
|
+
"lowest-direct"
|
|
12
|
+
]),
|
|
9
13
|
kind: "enum",
|
|
10
14
|
strategy: "scalar",
|
|
11
15
|
enforcement: "absent",
|
|
@@ -18,7 +22,11 @@ const misc = {
|
|
|
18
22
|
}
|
|
19
23
|
},
|
|
20
24
|
savePrefix: {
|
|
21
|
-
schema: Schema.
|
|
25
|
+
schema: Schema.Literals([
|
|
26
|
+
"^",
|
|
27
|
+
"~",
|
|
28
|
+
""
|
|
29
|
+
]),
|
|
22
30
|
kind: "enum",
|
|
23
31
|
strategy: "scalar",
|
|
24
32
|
enforcement: "absent",
|
|
@@ -19,10 +19,7 @@ const PeerRulesSchema = Schema.Struct({
|
|
|
19
19
|
*/
|
|
20
20
|
const resolution = {
|
|
21
21
|
catalogs: {
|
|
22
|
-
schema: Schema.Record(
|
|
23
|
-
key: Str,
|
|
24
|
-
value: StringRecord
|
|
25
|
-
}),
|
|
22
|
+
schema: Schema.Record(Str, StringRecord),
|
|
26
23
|
kind: "object",
|
|
27
24
|
strategy: "catalogs",
|
|
28
25
|
enforcement: "warn",
|
|
@@ -205,7 +202,7 @@ const resolution = {
|
|
|
205
202
|
anchor: "minimumreleaseageignoremissingtime"
|
|
206
203
|
},
|
|
207
204
|
trustPolicy: {
|
|
208
|
-
schema: Schema.
|
|
205
|
+
schema: Schema.Literals(["off", "no-downgrade"]),
|
|
209
206
|
kind: "enum",
|
|
210
207
|
strategy: "scalar",
|
|
211
208
|
enforcement: "warn",
|
|
@@ -32,7 +32,12 @@ const runtimeCfg = {
|
|
|
32
32
|
anchor: "managepackagemanagerversions"
|
|
33
33
|
},
|
|
34
34
|
pmOnFail: {
|
|
35
|
-
schema: Schema.
|
|
35
|
+
schema: Schema.Literals([
|
|
36
|
+
"download",
|
|
37
|
+
"error",
|
|
38
|
+
"warn",
|
|
39
|
+
"ignore"
|
|
40
|
+
]),
|
|
36
41
|
kind: "enum",
|
|
37
42
|
strategy: "scalar",
|
|
38
43
|
enforcement: "absent",
|
|
@@ -45,7 +50,12 @@ const runtimeCfg = {
|
|
|
45
50
|
}
|
|
46
51
|
},
|
|
47
52
|
runtimeOnFail: {
|
|
48
|
-
schema: Schema.
|
|
53
|
+
schema: Schema.Literals([
|
|
54
|
+
"download",
|
|
55
|
+
"error",
|
|
56
|
+
"warn",
|
|
57
|
+
"ignore"
|
|
58
|
+
]),
|
|
49
59
|
kind: "enum",
|
|
50
60
|
strategy: "scalar",
|
|
51
61
|
enforcement: "absent",
|
package/descriptors/schemas.js
CHANGED
|
@@ -5,22 +5,10 @@ import { Schema } from "effect";
|
|
|
5
5
|
/** @internal */ const Num = Schema.Number;
|
|
6
6
|
/** @internal */ const Str = Schema.String;
|
|
7
7
|
/** @internal */ const StringArray = Schema.Array(Schema.String);
|
|
8
|
-
/** @internal */ const StringRecord = Schema.Record(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/** @internal */ const BooleanRecord = Schema.Record({
|
|
13
|
-
key: Schema.String,
|
|
14
|
-
value: Schema.Boolean
|
|
15
|
-
});
|
|
16
|
-
/** @internal */ const UnknownRecord = Schema.Record({
|
|
17
|
-
key: Schema.String,
|
|
18
|
-
value: Schema.Unknown
|
|
19
|
-
});
|
|
20
|
-
/** @internal */ const StringArrayRecord = Schema.Record({
|
|
21
|
-
key: Schema.String,
|
|
22
|
-
value: StringArray
|
|
23
|
-
});
|
|
8
|
+
/** @internal */ const StringRecord = Schema.Record(Schema.String, Schema.String);
|
|
9
|
+
/** @internal */ const BooleanRecord = Schema.Record(Schema.String, Schema.Boolean);
|
|
10
|
+
/** @internal */ const UnknownRecord = Schema.Record(Schema.String, Schema.Unknown);
|
|
11
|
+
/** @internal */ const StringArrayRecord = Schema.Record(Schema.String, StringArray);
|
|
24
12
|
|
|
25
13
|
//#endregion
|
|
26
14
|
export { Bool, BooleanRecord, Num, Str, StringArray, StringArrayRecord, StringRecord, UnknownRecord };
|
package/descriptors/workspace.js
CHANGED
|
@@ -5,7 +5,11 @@ import { Schema } from "effect";
|
|
|
5
5
|
/** The 10 catalog + workspace + audit fields. @internal */
|
|
6
6
|
const workspace = {
|
|
7
7
|
catalogMode: {
|
|
8
|
-
schema: Schema.
|
|
8
|
+
schema: Schema.Literals([
|
|
9
|
+
"strict",
|
|
10
|
+
"prefer",
|
|
11
|
+
"manual"
|
|
12
|
+
]),
|
|
9
13
|
kind: "enum",
|
|
10
14
|
strategy: "scalar",
|
|
11
15
|
enforcement: "absent",
|
|
@@ -27,7 +31,7 @@ const workspace = {
|
|
|
27
31
|
anchor: "cleanupunusedcatalogs"
|
|
28
32
|
},
|
|
29
33
|
linkWorkspacePackages: {
|
|
30
|
-
schema: Schema.Union(Schema.Boolean, Schema.
|
|
34
|
+
schema: Schema.Union([Schema.Boolean, Schema.Literals(["deep"])]),
|
|
31
35
|
kind: "union",
|
|
32
36
|
strategy: "scalar",
|
|
33
37
|
enforcement: "absent",
|
|
@@ -49,7 +53,7 @@ const workspace = {
|
|
|
49
53
|
anchor: "preferworkspacepackages"
|
|
50
54
|
},
|
|
51
55
|
saveWorkspaceProtocol: {
|
|
52
|
-
schema: Schema.Union(Schema.Boolean, Schema.
|
|
56
|
+
schema: Schema.Union([Schema.Boolean, Schema.Literals(["rolling"])]),
|
|
53
57
|
kind: "union",
|
|
54
58
|
strategy: "scalar",
|
|
55
59
|
enforcement: "absent",
|
|
@@ -98,7 +102,12 @@ const workspace = {
|
|
|
98
102
|
anchor: "workspaceconcurrency"
|
|
99
103
|
},
|
|
100
104
|
auditLevel: {
|
|
101
|
-
schema: Schema.
|
|
105
|
+
schema: Schema.Literals([
|
|
106
|
+
"low",
|
|
107
|
+
"moderate",
|
|
108
|
+
"high",
|
|
109
|
+
"critical"
|
|
110
|
+
]),
|
|
102
111
|
kind: "enum",
|
|
103
112
|
strategy: "scalar",
|
|
104
113
|
enforcement: "absent",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rolldown-pnpm-config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A dogfooding example of our plugin",
|
|
6
6
|
"repository": {
|
|
@@ -33,26 +33,16 @@
|
|
|
33
33
|
"rolldown-pnpm-config": "bin/rolldown-pnpm-config.js"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@effect/
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"
|
|
40
|
-
"@effect/platform-node": "^0.107.0",
|
|
41
|
-
"@effect/printer": "^0.49.0",
|
|
42
|
-
"@effect/printer-ansi": "^0.49.0",
|
|
43
|
-
"@effect/rpc": "^0.75.1",
|
|
44
|
-
"@effect/sql": "^0.51.1",
|
|
45
|
-
"@effect/typeclass": "^0.40.0",
|
|
46
|
-
"@effect/workflow": "^0.18.2",
|
|
47
|
-
"effect": "^3.21.4",
|
|
36
|
+
"@effect/platform-node": "4.0.0-beta.98",
|
|
37
|
+
"@effected/semver": "^0.1.0",
|
|
38
|
+
"@effected/yaml": "^0.1.0",
|
|
39
|
+
"effect": "4.0.0-beta.98",
|
|
48
40
|
"ink": "^7.1.0",
|
|
49
41
|
"ink-tab": "^5.2.0",
|
|
50
42
|
"oxc-parser": "^0.140.0",
|
|
51
43
|
"react": "^19.2.7",
|
|
52
|
-
"semver-effect": "^0.3.1",
|
|
53
44
|
"std-env": "^4.2.0",
|
|
54
|
-
"std-osc8": "^0.2.0"
|
|
55
|
-
"yaml": "^2.9.0"
|
|
45
|
+
"std-osc8": "^0.2.0"
|
|
56
46
|
},
|
|
57
47
|
"peerDependencies": {
|
|
58
48
|
"rolldown": "^1.1.0"
|
package/plugin/freeze.js
CHANGED
|
@@ -48,7 +48,7 @@ function freeze(config) {
|
|
|
48
48
|
return Effect.gen(function* () {
|
|
49
49
|
const base = {};
|
|
50
50
|
const manifest = {};
|
|
51
|
-
base.catalogs = yield* Schema.
|
|
51
|
+
base.catalogs = yield* Schema.decodeUnknownEffect(CatalogsSchema)(normalizeCatalogs(config.catalogs)).pipe(Effect.mapError((error) => new ConfigError({ message: `Invalid catalogs: ${String(error)}` })));
|
|
52
52
|
manifest.catalogs = {
|
|
53
53
|
strategy: "catalogs",
|
|
54
54
|
enforcement: "warn"
|
|
@@ -60,7 +60,7 @@ function freeze(config) {
|
|
|
60
60
|
if (raw === void 0) continue;
|
|
61
61
|
const decl = normalizeField(raw);
|
|
62
62
|
const schema = FIELD_SCHEMAS[field];
|
|
63
|
-
base[field] = schema ? yield* Schema.
|
|
63
|
+
base[field] = schema ? yield* Schema.decodeUnknownEffect(schema)(decl.value).pipe(Effect.mapError((error) => new ConfigError({ message: `Invalid ${field}: ${String(error)}` }))) : decl.value;
|
|
64
64
|
manifest[field] = {
|
|
65
65
|
strategy: reg.strategy,
|
|
66
66
|
enforcement: decl.enforcement ?? reg.enforcement,
|
package/virtual.d.ts
CHANGED
|
@@ -9,8 +9,18 @@
|
|
|
9
9
|
// per-module boilerplate.
|
|
10
10
|
|
|
11
11
|
declare module "rolldown-pnpm-config/virtual/pnpmfile" {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
// Inlined rather than imported from "rolldown-pnpm-config/runtime": this file is
|
|
13
|
+
// shipped byte-for-byte (never compiled), so any cross-module import here resolves
|
|
14
|
+
// against this package's own *source* `exports` map during the build's declaration
|
|
15
|
+
// pass and pulls a raw .ts file into API Extractor's analysis (ae-wrong-input-file-type).
|
|
16
|
+
// Keep this shape in sync with `PnpmConfig`/`PnpmHooks` in `src/runtime/types.ts`.
|
|
17
|
+
interface PnpmConfig {
|
|
18
|
+
catalogs?: Record<string, Record<string, string>>;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
export const hooks: {
|
|
22
|
+
updateConfig(config: PnpmConfig): PnpmConfig;
|
|
23
|
+
};
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
declare module "rolldown-pnpm-config/virtual/catalogs" {
|