rolldown-pnpm-config 0.2.2 → 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/README.md +2 -2
- 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 +168 -98
- package/cli/drift.js +8 -2
- package/cli/edits.js +28 -18
- package/cli/interop.js +10 -10
- package/cli/peer-range.js +30 -4
- package/cli/plan.js +10 -8
- package/cli/resolve.js +31 -11
- package/cli/summary.js +94 -67
- package/cli/ui/Walk.js +53 -27
- package/cli/ui/run-preview.js +1 -1
- package/cli/ui/run-walk.js +7 -5
- package/cli/validate.js +88 -0
- package/cli/walk-plan.js +11 -3
- package/cli/walk-reducer.js +90 -35
- 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 +7 -17
- package/plugin/freeze.js +2 -2
- package/virtual.d.ts +12 -2
package/cli/validate.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { Range, SemVer } from "@effected/semver";
|
|
3
|
+
|
|
4
|
+
//#region src/cli/validate.ts
|
|
5
|
+
/**
|
|
6
|
+
* Whether at least one published version satisfies `range`.
|
|
7
|
+
*
|
|
8
|
+
* The predicate is deliberately "some published version satisfies this range",
|
|
9
|
+
* NOT "this exact version was published": `^3.4.0` is a valid lock-minor floor
|
|
10
|
+
* even when 3.4.0 itself never shipped but 3.4.1 did. Conversely `^3.0.0`
|
|
11
|
+
* against a package with only `3.0.0-next.*` releases matches nothing.
|
|
12
|
+
*
|
|
13
|
+
* Fails OPEN — an empty version list (fetch failure, fully age-gated package)
|
|
14
|
+
* or an unparseable range yields `true`. Validation is a safety net against
|
|
15
|
+
* ranges we DERIVED wrongly, not a gate on the author's own hand-written
|
|
16
|
+
* ranges, and rejecting everything the moment the registry is unreachable would
|
|
17
|
+
* break offline peer materialization.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
function rangeIsSatisfiable(range, versions) {
|
|
22
|
+
return Effect.gen(function* () {
|
|
23
|
+
if (versions.length === 0) return true;
|
|
24
|
+
const parsedRange = yield* Range.parse(range).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
25
|
+
if (parsedRange === null) return true;
|
|
26
|
+
for (const v of versions) {
|
|
27
|
+
const sv = yield* SemVer.parse(v).pipe(Effect.catch(() => Effect.succeed(null)));
|
|
28
|
+
if (sv && parsedRange.test(sv)) return true;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Partition planned edits into those whose range some published version
|
|
35
|
+
* satisfies and those none does — ATOMICALLY per package. A catalog package
|
|
36
|
+
* with a `strategy` produces a `range` edit and a `peer` edit as a pair; if
|
|
37
|
+
* either is unsatisfiable, BOTH are rejected. Writing one half of the pair
|
|
38
|
+
* (say, an accepted range bump next to a rejected, stale peer) would leave the
|
|
39
|
+
* file internally inconsistent — the peer no longer matches what the strategy
|
|
40
|
+
* derives from the new range — and every subsequent run would re-report the
|
|
41
|
+
* same drift and re-reject it forever. A package is either fully updated or
|
|
42
|
+
* not touched at all.
|
|
43
|
+
*
|
|
44
|
+
* `versionsByPkg` MUST be the UNGATED version list. Validating against the
|
|
45
|
+
* release-age-gated list would spuriously reject a package whose only matching
|
|
46
|
+
* version was published inside the gate window.
|
|
47
|
+
*
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
function validateEdits(edits, versionsByPkg) {
|
|
51
|
+
return Effect.gen(function* () {
|
|
52
|
+
const byPkg = /* @__PURE__ */ new Map();
|
|
53
|
+
for (const e of edits) {
|
|
54
|
+
const group = byPkg.get(e.pkg) ?? [];
|
|
55
|
+
group.push(e);
|
|
56
|
+
byPkg.set(e.pkg, group);
|
|
57
|
+
}
|
|
58
|
+
const accepted = [];
|
|
59
|
+
const rejected = [];
|
|
60
|
+
for (const [pkg, group] of byPkg) {
|
|
61
|
+
const versions = versionsByPkg.get(pkg) ?? [];
|
|
62
|
+
const checked = [];
|
|
63
|
+
for (const e of group) checked.push({
|
|
64
|
+
edit: e,
|
|
65
|
+
ok: yield* rangeIsSatisfiable(e.value, versions)
|
|
66
|
+
});
|
|
67
|
+
const failing = checked.filter((c) => !c.ok);
|
|
68
|
+
if (failing.length === 0) {
|
|
69
|
+
accepted.push(...group);
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const failingKinds = failing.map((f) => f.edit.kind).join(" and ");
|
|
73
|
+
for (const { edit, ok } of checked) rejected.push({
|
|
74
|
+
pkg,
|
|
75
|
+
kind: edit.kind,
|
|
76
|
+
value: edit.value,
|
|
77
|
+
reason: ok ? `dropped along with its ${failingKinds} edit for ${pkg}, which is unsatisfiable` : `no published version of ${pkg} satisfies ${edit.value}`
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
accepted,
|
|
82
|
+
rejected
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
export { rangeIsSatisfiable, validateEdits };
|
package/cli/walk-plan.js
CHANGED
|
@@ -7,7 +7,8 @@ import { Effect } from "effect";
|
|
|
7
7
|
/**
|
|
8
8
|
* Build the interactive walk items: for each entry, its candidate list (from
|
|
9
9
|
* planEntry against the resolved versions), an up-to-date flag (only the keep
|
|
10
|
-
* candidate remains),
|
|
10
|
+
* candidate remains), any peer drift resync target, any peer to materialize,
|
|
11
|
+
* and any strategy/prerelease incompatibility warning.
|
|
11
12
|
*
|
|
12
13
|
* @internal
|
|
13
14
|
*/
|
|
@@ -17,14 +18,21 @@ function buildWalkItems(entries, versionsByPkg) {
|
|
|
17
18
|
for (const entry of entries) {
|
|
18
19
|
const candidates = yield* planEntry(entry, [...versionsByPkg.get(entry.pkg) ?? []]);
|
|
19
20
|
const driftPeer = yield* detectPeerDrift(entry);
|
|
20
|
-
|
|
21
|
+
let peerWarning = null;
|
|
22
|
+
let materializePeer = null;
|
|
23
|
+
if (entry.strategy && entry.strategy !== "interop") {
|
|
24
|
+
const derived = yield* derivePeerRange(entry.currentRange, entry.strategy);
|
|
25
|
+
peerWarning = derived.warning;
|
|
26
|
+
if (!entry.peer) materializePeer = derived.range;
|
|
27
|
+
}
|
|
21
28
|
const upToDate = candidates.length === 1 && driftPeer === null && materializePeer === null;
|
|
22
29
|
items.push({
|
|
23
30
|
entry,
|
|
24
31
|
candidates,
|
|
25
32
|
upToDate,
|
|
26
33
|
driftPeer,
|
|
27
|
-
materializePeer
|
|
34
|
+
materializePeer,
|
|
35
|
+
peerWarning
|
|
28
36
|
});
|
|
29
37
|
}
|
|
30
38
|
return items;
|
package/cli/walk-reducer.js
CHANGED
|
@@ -1,61 +1,116 @@
|
|
|
1
1
|
//#region src/cli/walk-reducer.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
const ORDER = {
|
|
3
|
+
keep: 0,
|
|
4
|
+
"in-range": 1,
|
|
5
|
+
latest: 2
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* The row's options in display order: keep first (always index 0, always the
|
|
9
|
+
* default), then the in-range bump, then the latest-overall bump. `planEntry`
|
|
10
|
+
* emits them in the opposite order, with keep last.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
function displayCandidates(item) {
|
|
15
|
+
return [...item.candidates].sort((a, b) => ORDER[a.kind] - ORDER[b.kind]);
|
|
6
16
|
}
|
|
7
17
|
/**
|
|
8
|
-
* Initialize the
|
|
9
|
-
*
|
|
18
|
+
* Initialize the table: cursor on the first row, keep selected on every row, so
|
|
19
|
+
* the default state applies nothing.
|
|
10
20
|
*
|
|
11
21
|
* @internal
|
|
12
22
|
*/
|
|
13
|
-
function
|
|
14
|
-
const index = nextActionable(items, 0);
|
|
23
|
+
function initTable(items) {
|
|
15
24
|
return {
|
|
16
|
-
index: index === -1 ? items.length : index,
|
|
17
25
|
cursor: 0,
|
|
18
|
-
|
|
19
|
-
done:
|
|
26
|
+
picks: items.map(() => 0),
|
|
27
|
+
done: false,
|
|
28
|
+
cancelled: false
|
|
20
29
|
};
|
|
21
30
|
}
|
|
31
|
+
const clamp = (n, max) => n < 0 ? 0 : n > max ? max : n;
|
|
22
32
|
/**
|
|
23
|
-
* Advance the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
33
|
+
* Advance the table by a key. up/down move between rows; left/right move the
|
|
34
|
+
* radio selection within the row under the cursor; submit applies; cancel exits
|
|
35
|
+
* without applying. Both axes clamp at their ends rather than wrapping.
|
|
26
36
|
*
|
|
27
37
|
* @internal
|
|
28
38
|
*/
|
|
29
|
-
function
|
|
39
|
+
function tableStep(state, items, key) {
|
|
30
40
|
if (state.done) return state;
|
|
31
|
-
|
|
32
|
-
const count = item.candidates.length;
|
|
33
|
-
if (key === "up") return {
|
|
41
|
+
if (key === "submit") return {
|
|
34
42
|
...state,
|
|
35
|
-
|
|
43
|
+
done: true
|
|
36
44
|
};
|
|
37
|
-
if (key === "
|
|
45
|
+
if (key === "cancel") return {
|
|
38
46
|
...state,
|
|
39
|
-
|
|
47
|
+
done: true,
|
|
48
|
+
cancelled: true
|
|
40
49
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
item,
|
|
44
|
-
chosen
|
|
45
|
-
}];
|
|
46
|
-
const next = nextActionable(items, state.index + 1);
|
|
47
|
-
if (next === -1) return {
|
|
50
|
+
if (items.length === 0) return state;
|
|
51
|
+
if (key === "up") return {
|
|
48
52
|
...state,
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
cursor: clamp(state.cursor - 1, items.length - 1)
|
|
54
|
+
};
|
|
55
|
+
if (key === "down") return {
|
|
56
|
+
...state,
|
|
57
|
+
cursor: clamp(state.cursor + 1, items.length - 1)
|
|
51
58
|
};
|
|
59
|
+
const count = displayCandidates(items[state.cursor]).length;
|
|
60
|
+
const delta = key === "right" ? 1 : -1;
|
|
61
|
+
const picks = [...state.picks];
|
|
62
|
+
picks[state.cursor] = clamp(picks[state.cursor] + delta, count - 1);
|
|
52
63
|
return {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
decisions,
|
|
56
|
-
done: false
|
|
64
|
+
...state,
|
|
65
|
+
picks
|
|
57
66
|
};
|
|
58
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Project the table's selections into decisions. A cancelled table yields none,
|
|
70
|
+
* so nothing is written.
|
|
71
|
+
*
|
|
72
|
+
* @internal
|
|
73
|
+
*/
|
|
74
|
+
function tableDecisions(state, items) {
|
|
75
|
+
if (state.cancelled) return [];
|
|
76
|
+
return items.map((item, i) => ({
|
|
77
|
+
item,
|
|
78
|
+
chosen: displayCandidates(item)[state.picks[i] ?? 0]
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The peer range that would be written for a row's currently chosen candidate.
|
|
83
|
+
* Non-keep candidates carry their own recomputed `peerRange`; keep reuses
|
|
84
|
+
* whichever peer source the item already resolved (a drift resync, a
|
|
85
|
+
* materialize target, or the entry's existing literal), falling back to an
|
|
86
|
+
* em dash placeholder when none applies.
|
|
87
|
+
*
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
function peerFor(item, chosen) {
|
|
91
|
+
if (chosen.kind !== "keep") return chosen.peerRange ?? "—";
|
|
92
|
+
if (item.driftPeer) return item.driftPeer;
|
|
93
|
+
if (item.materializePeer) return item.materializePeer;
|
|
94
|
+
return item.entry.peer?.value ?? "—";
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The Ink color for one candidate cell, or null for the terminal's default.
|
|
98
|
+
*
|
|
99
|
+
* Only a SELECTED UPGRADE is colored — green in-range, yellow for a major. A
|
|
100
|
+
* selected KEEP is deliberately left uncolored: it is the current value, not a
|
|
101
|
+
* change, and coloring it dim made the column the eye lands on first read as
|
|
102
|
+
* disabled. Unselected cells are always default.
|
|
103
|
+
*
|
|
104
|
+
* Extracted from the render so it can be unit-tested: `ink-testing-library`
|
|
105
|
+
* strips ANSI from `lastFrame()`, so a color assertion is impossible against
|
|
106
|
+
* the rendered output.
|
|
107
|
+
*
|
|
108
|
+
* @internal
|
|
109
|
+
*/
|
|
110
|
+
function cellColor(candidate, selected) {
|
|
111
|
+
if (!selected || candidate.kind === "keep") return null;
|
|
112
|
+
return candidate.isMajor ? "yellow" : "green";
|
|
113
|
+
}
|
|
59
114
|
|
|
60
115
|
//#endregion
|
|
61
|
-
export {
|
|
116
|
+
export { cellColor, displayCandidates, initTable, peerFor, tableDecisions, tableStep };
|
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
|
-
"oxc-parser": "^0.
|
|
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" {
|