rolldown-pnpm-config 2.2.0 → 2.2.1
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/cli/commands/export.js +3 -6
- package/cli/commands/upgrade.js +10 -18
- package/cli/diff/build.js +4 -4
- package/cli/interop-live.js +2 -14
- package/cli/interop.js +8 -2
- package/cli/load-config.js +13 -10
- package/cli/local-merge.js +2 -4
- package/cli/resolve.js +1 -1
- package/cli/select-file.js +4 -8
- package/cli/simulated-view.js +2 -1
- package/cli/version.js +1 -1
- package/cli/workspace-file.js +12 -15
- package/cli/workspace-resolve.js +6 -5
- package/package.json +11 -11
- package/plugin/allowed-versions.js +2 -1
- package/plugin/freeze.js +2 -2
- package/plugin/overrides-from-catalogs.js +2 -1
- package/plugin/serialize.js +3 -1
- package/runtime/strategies/arrays.js +4 -2
- package/tsdoc-metadata.json +1 -1
package/cli/commands/export.js
CHANGED
|
@@ -14,10 +14,10 @@ import { printView } from "../render/print.js";
|
|
|
14
14
|
import { failureDoc } from "../render/report.js";
|
|
15
15
|
import { findConfigFiles, pickConfigCandidate } from "../select-file.js";
|
|
16
16
|
import { overlayWorkspace } from "../workspace-overlay.js";
|
|
17
|
-
import { Data, Effect, Option, Predicate } from "effect";
|
|
17
|
+
import { Data, Effect, FileSystem, Option, Predicate } from "effect";
|
|
18
18
|
import { dirname, relative } from "node:path";
|
|
19
19
|
import { CliDoc, CliMessage } from "@effected/cli";
|
|
20
|
-
import { existsSync
|
|
20
|
+
import { existsSync } from "node:fs";
|
|
21
21
|
import { Argument, Command, Flag } from "effect/cli";
|
|
22
22
|
|
|
23
23
|
// src/cli/commands/export.ts
|
|
@@ -90,10 +90,7 @@ function runExport(opts) {
|
|
|
90
90
|
diff,
|
|
91
91
|
report
|
|
92
92
|
};
|
|
93
|
-
yield* Effect.
|
|
94
|
-
try: () => writeFileSync(path, rendered, "utf8"),
|
|
95
|
-
catch: () => new ExportError({ message: `Cannot write ${path}` })
|
|
96
|
-
});
|
|
93
|
+
yield* (yield* FileSystem.FileSystem).writeFileString(path, rendered).pipe(Effect.mapError(() => new ExportError({ message: `Cannot write ${path}` })));
|
|
97
94
|
return {
|
|
98
95
|
path,
|
|
99
96
|
rendered,
|
package/cli/commands/upgrade.js
CHANGED
|
@@ -18,10 +18,9 @@ import { summaryDoc } from "../summary.js";
|
|
|
18
18
|
import { validateEdits } from "../validate.js";
|
|
19
19
|
import { buildWalkItems } from "../walk-plan.js";
|
|
20
20
|
import { findWorkspaceRoot, makeWorkspaceResolver } from "../workspace-resolve.js";
|
|
21
|
-
import { Clock, Data, Effect, Option, Result } from "effect";
|
|
21
|
+
import { Clock, Data, Effect, FileSystem, Option, Result } from "effect";
|
|
22
22
|
import { dirname } from "node:path";
|
|
23
23
|
import { CliDoc, CliExit, CliFormat, CliInteractive, CliMessage, Doc, Fmt } from "@effected/cli";
|
|
24
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
25
24
|
import { Argument, Command, Flag } from "effect/cli";
|
|
26
25
|
import { CliUi } from "@effected/cli/ui";
|
|
27
26
|
import { ReleaseAgeGate } from "@effected/npm";
|
|
@@ -71,13 +70,14 @@ var CheckFailedError = class extends Data.TaggedError("CheckFailedError") {
|
|
|
71
70
|
return failureDoc(`${CHECK_FAILED_LABEL}\n${indent(this.message)}`);
|
|
72
71
|
}
|
|
73
72
|
};
|
|
73
|
+
/** Write the rewritten config source back to `file`. */
|
|
74
|
+
function writeSource(file, next) {
|
|
75
|
+
return Effect.flatMap(FileSystem.FileSystem, (fs) => fs.writeFileString(file, next).pipe(Effect.mapError(() => new UpgradeError({ message: `Cannot write ${file}` }))));
|
|
76
|
+
}
|
|
74
77
|
/** Read a config file and statically discover its catalog entries. @internal */
|
|
75
78
|
function readCatalogSource(file) {
|
|
76
79
|
return Effect.gen(function* () {
|
|
77
|
-
const source = yield* Effect.
|
|
78
|
-
try: () => readFileSync(file, "utf8"),
|
|
79
|
-
catch: () => new UpgradeError({ message: `Cannot read ${file}` })
|
|
80
|
-
});
|
|
80
|
+
const source = yield* (yield* FileSystem.FileSystem).readFileString(file).pipe(Effect.mapError(() => new UpgradeError({ message: `Cannot read ${file}` })));
|
|
81
81
|
const { entries, skipped } = yield* Effect.try({
|
|
82
82
|
try: () => discoverCatalogEntries(source, file),
|
|
83
83
|
catch: (e) => new UpgradeError({ message: Fmt.describe(e) })
|
|
@@ -165,16 +165,15 @@ function resolveGatedVersions(entries, resolver, gate, now, onProgress, workspac
|
|
|
165
165
|
* @internal
|
|
166
166
|
*/
|
|
167
167
|
function resolveProgress(report) {
|
|
168
|
-
const noun = (n) => `${n} package${n === 1 ? "" : "s"}`;
|
|
169
168
|
const finished = (total) => report({
|
|
170
169
|
_tag: "Finished",
|
|
171
|
-
label: `Resolved ${
|
|
170
|
+
label: `Resolved ${Fmt.plural(total, "package")}`
|
|
172
171
|
});
|
|
173
172
|
return (resolved, total) => {
|
|
174
173
|
if (resolved === 0) {
|
|
175
174
|
const begin = report({
|
|
176
175
|
_tag: "Phase",
|
|
177
|
-
label: `Resolving ${
|
|
176
|
+
label: `Resolving ${Fmt.plural(total, "package")}`,
|
|
178
177
|
total
|
|
179
178
|
});
|
|
180
179
|
return total === 0 ? Effect.andThen(begin, finished(total)) : begin;
|
|
@@ -283,10 +282,7 @@ function runUpgrade(opts) {
|
|
|
283
282
|
const allEdits = [...accepted, ...interopEdits];
|
|
284
283
|
if (allEdits.length > 0 && !opts.dryRun) {
|
|
285
284
|
const next = applyEdits(source, allEdits);
|
|
286
|
-
yield*
|
|
287
|
-
try: () => writeFileSync(opts.file, next, "utf8"),
|
|
288
|
-
catch: () => new UpgradeError({ message: `Cannot write ${opts.file}` })
|
|
289
|
-
});
|
|
285
|
+
yield* writeSource(opts.file, next);
|
|
290
286
|
}
|
|
291
287
|
return {
|
|
292
288
|
updated: changedSpans.size,
|
|
@@ -316,11 +312,7 @@ function applyInteropAndDecisions(file, source, nonInteropEdits, interopEdits) {
|
|
|
316
312
|
return Effect.gen(function* () {
|
|
317
313
|
const edits = [...nonInteropEdits, ...interopEdits];
|
|
318
314
|
if (edits.length === 0) return;
|
|
319
|
-
|
|
320
|
-
yield* Effect.try({
|
|
321
|
-
try: () => writeFileSync(file, next, "utf8"),
|
|
322
|
-
catch: () => new UpgradeError({ message: `Cannot write ${file}` })
|
|
323
|
-
});
|
|
315
|
+
yield* writeSource(file, applyEdits(source, edits));
|
|
324
316
|
});
|
|
325
317
|
}
|
|
326
318
|
/**
|
package/cli/diff/build.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Predicate } from "effect";
|
|
1
|
+
import { Order, Predicate } from "effect";
|
|
2
2
|
|
|
3
3
|
// src/cli/diff/build.ts
|
|
4
4
|
const isObject = Predicate.isObject;
|
|
@@ -49,7 +49,7 @@ function diffArray(key, path, before, after, tag) {
|
|
|
49
49
|
const here = [...path, key];
|
|
50
50
|
const b = new Set(before.map(String));
|
|
51
51
|
const a = new Set(after.map(String));
|
|
52
|
-
const children = [.../* @__PURE__ */ new Set([...b, ...a])].sort(
|
|
52
|
+
const children = [.../* @__PURE__ */ new Set([...b, ...a])].sort(Order.String).map((el) => {
|
|
53
53
|
const inB = b.has(el);
|
|
54
54
|
const inA = a.has(el);
|
|
55
55
|
const kind = inB && inA ? "unchanged" : inA ? "added" : "removed";
|
|
@@ -73,7 +73,7 @@ function diffArray(key, path, before, after, tag) {
|
|
|
73
73
|
function diffValue(key, path, before, after, tag) {
|
|
74
74
|
const here = [...path, key];
|
|
75
75
|
if (isObject(before) && isObject(after)) {
|
|
76
|
-
const children = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].sort(
|
|
76
|
+
const children = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].sort(Order.String).map((k) => {
|
|
77
77
|
if (!(k in before)) return uniform(k, here, after[k], "added");
|
|
78
78
|
if (!(k in after)) return uniform(k, here, before[k], "removed");
|
|
79
79
|
return diffValue(k, here, before[k], after[k]);
|
|
@@ -104,7 +104,7 @@ function diffValue(key, path, before, after, tag) {
|
|
|
104
104
|
* @internal
|
|
105
105
|
*/
|
|
106
106
|
function buildDiff(before, after, meta) {
|
|
107
|
-
const children = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].sort(
|
|
107
|
+
const children = [.../* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])].sort(Order.String).map((k) => {
|
|
108
108
|
const tag = meta.localKeys.has(k) ? "local" : meta.managedKeys.has(k) ? void 0 : "unmanaged";
|
|
109
109
|
if (!(k in before)) return uniform(k, [], after[k], "added", tag);
|
|
110
110
|
if (!(k in after)) return uniform(k, [], before[k], "removed", tag);
|
package/cli/interop-live.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bareVersion, parseRange, parseVersion } from "../semver-util.js";
|
|
2
|
-
import "./interop.js";
|
|
2
|
+
import { lowestVersion } from "./interop.js";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
|
|
5
5
|
// src/cli/interop-live.ts
|
|
@@ -28,19 +28,7 @@ function computeGroupPeers(model, selected) {
|
|
|
28
28
|
for (const m of model.members) {
|
|
29
29
|
const v = selected.get(m);
|
|
30
30
|
if (v === void 0) continue;
|
|
31
|
-
|
|
32
|
-
if (declared?.length) {
|
|
33
|
-
let minStr = declared[0];
|
|
34
|
-
let minSv = model.ver.get(minStr) ?? null;
|
|
35
|
-
for (const f of declared.slice(1)) {
|
|
36
|
-
const sv = model.ver.get(f) ?? null;
|
|
37
|
-
if (sv && (minSv === null || sv.compare(minSv) < 0)) {
|
|
38
|
-
minSv = sv;
|
|
39
|
-
minStr = f;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
peer.set(m, `^${minStr}`);
|
|
43
|
-
} else peer.set(m, `^${v}`);
|
|
31
|
+
peer.set(m, `^${lowestVersion(declaredFloors.get(m) ?? []) ?? v}`);
|
|
44
32
|
}
|
|
45
33
|
const conflict = /* @__PURE__ */ new Map();
|
|
46
34
|
for (const m of model.members) {
|
package/cli/interop.js
CHANGED
|
@@ -50,7 +50,13 @@ function deriveFloors(resolved, fetchPeer) {
|
|
|
50
50
|
return out;
|
|
51
51
|
});
|
|
52
52
|
}
|
|
53
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* The lowest parseable version string in `list`, or null when none parses.
|
|
55
|
+
* Shared by the `--yes` resolver and the interactive table so both write the
|
|
56
|
+
* same peer floor.
|
|
57
|
+
*
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
54
60
|
function lowestVersion(list) {
|
|
55
61
|
let best = null;
|
|
56
62
|
for (const f of list) {
|
|
@@ -223,4 +229,4 @@ function buildInteropEdits(entries, result) {
|
|
|
223
229
|
return edits;
|
|
224
230
|
}
|
|
225
231
|
|
|
226
|
-
export { buildInteropEdits, deriveFloors, interopEntryChanged, makePeerFetcher, resolveGroup, runInterop };
|
|
232
|
+
export { buildInteropEdits, deriveFloors, interopEntryChanged, lowestVersion, makePeerFetcher, resolveGroup, runInterop };
|
package/cli/load-config.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { parseWorkspace } from "./workspace-file.js";
|
|
2
2
|
import { evaluatePluginConfig } from "./evaluate.js";
|
|
3
|
-
import { Effect, Predicate } from "effect";
|
|
3
|
+
import { Effect, FileSystem, Predicate } from "effect";
|
|
4
4
|
import { Fmt } from "@effected/cli";
|
|
5
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
6
5
|
|
|
7
6
|
// src/cli/load-config.ts
|
|
8
7
|
/**
|
|
@@ -11,22 +10,26 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
11
10
|
* parse the workspace file when present. `mkError` wraps each failure
|
|
12
11
|
* message in the command's own error type.
|
|
13
12
|
*
|
|
13
|
+
* IO goes through the platform `FileSystem`. Only a workspace file that is
|
|
14
|
+
* NOT FOUND reads as absent (`fs.exists` maps `NotFound` to `false`); an
|
|
15
|
+
* existence check that fails for any other reason (EACCES, ENOTDIR, EIO) is a
|
|
16
|
+
* `Cannot read or parse` failure, never a silent "create it fresh".
|
|
17
|
+
*
|
|
14
18
|
* @internal
|
|
15
19
|
*/
|
|
16
20
|
function loadConfigAndWorkspace(opts, mkError) {
|
|
17
21
|
return Effect.gen(function* () {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
catch: () => mkError(`Cannot read ${opts.configFile}`)
|
|
21
|
-
});
|
|
22
|
+
const fs = yield* FileSystem.FileSystem;
|
|
23
|
+
const configSource = yield* fs.readFileString(opts.configFile).pipe(Effect.mapError(() => mkError(`Cannot read ${opts.configFile}`)));
|
|
22
24
|
const { config, errors } = evaluatePluginConfig(configSource, opts.configFile);
|
|
23
25
|
if (config === null) return yield* Effect.fail(mkError(`No PnpmConfigPlugin call found in ${opts.configFile}`));
|
|
24
26
|
if (errors.length > 0) return yield* Effect.fail(mkError(`Non-literal config values: ${errors.join("; ")}`));
|
|
25
27
|
const path = opts.workspacePath;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const cannotRead = (e) => mkError(`Cannot read or parse ${path}: ${Fmt.errorText(e)}`);
|
|
29
|
+
const parsed = (yield* fs.exists(path).pipe(Effect.mapError(cannotRead))) ? yield* fs.readFileString(path).pipe(Effect.mapError(cannotRead), Effect.flatMap((text) => Effect.try({
|
|
30
|
+
try: () => parseWorkspace(text),
|
|
31
|
+
catch: cannotRead
|
|
32
|
+
}))) : {};
|
|
30
33
|
return {
|
|
31
34
|
config,
|
|
32
35
|
localCfg: Predicate.isObject(config.local) ? config.local : void 0,
|
package/cli/local-merge.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Predicate } from "effect";
|
|
1
|
+
import { Array as Array$1, Predicate } from "effect";
|
|
2
2
|
|
|
3
3
|
// src/cli/local-merge.ts
|
|
4
4
|
/** Default protocols whose existing-file override entries are preserved. @internal */
|
|
@@ -30,9 +30,7 @@ function combine(managed, value, strategy) {
|
|
|
30
30
|
if (Array.isArray(managed) || Array.isArray(value)) {
|
|
31
31
|
const m = Array.isArray(managed) ? managed : [];
|
|
32
32
|
const v = Array.isArray(value) ? value : [];
|
|
33
|
-
|
|
34
|
-
const drop = new Set(v.map((x) => JSON.stringify(x)));
|
|
35
|
-
return m.filter((x) => !drop.has(JSON.stringify(x)));
|
|
33
|
+
return strategy === "union" ? Array$1.dedupe(Array$1.appendAll(m, v)) : Array$1.difference(m, v);
|
|
36
34
|
}
|
|
37
35
|
const m = Predicate.isObject(managed) ? managed : {};
|
|
38
36
|
const v = Predicate.isObject(value) ? value : {};
|
package/cli/resolve.js
CHANGED
|
@@ -86,7 +86,7 @@ const RegistryResolverLive = Layer.effect(RegistryResolver, Effect.gen(function*
|
|
|
86
86
|
"--json"
|
|
87
87
|
])).pipe(Effect.map(stripPnpmNotices), Effect.mapError((e) => new ResolveError({
|
|
88
88
|
pkg,
|
|
89
|
-
message: Fmt.
|
|
89
|
+
message: Fmt.errorText(e)
|
|
90
90
|
})));
|
|
91
91
|
return {
|
|
92
92
|
versions: (pkg) => pnpmView(pkg, pkg, "versions").pipe(Effect.flatMap((out) => parseVersions(pkg, out))),
|
package/cli/select-file.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { discoverCatalogEntries } from "./discover.js";
|
|
2
|
-
import { Effect, Result } from "effect";
|
|
2
|
+
import { Effect, FileSystem, Result } from "effect";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { GlobPattern, GlobPatternOptions } from "@effected/glob";
|
|
5
5
|
import { descendSync } from "@effected/walker";
|
|
6
6
|
import { nodeWalkerSyncOps } from "@effected/walker/node-sync";
|
|
7
|
-
import { readFileSync } from "node:fs";
|
|
8
7
|
|
|
9
8
|
// src/cli/select-file.ts
|
|
10
9
|
/** Top-level `.ts` FILES of a directory, no dotfiles, sorted. */
|
|
@@ -20,7 +19,8 @@ const TS_FILES = Result.getOrThrow(GlobPattern.compileResult("*.ts", GlobPattern
|
|
|
20
19
|
* @internal
|
|
21
20
|
*/
|
|
22
21
|
function findConfigFiles(dir) {
|
|
23
|
-
return Effect.
|
|
22
|
+
return Effect.gen(function* () {
|
|
23
|
+
const fs = yield* FileSystem.FileSystem;
|
|
24
24
|
const names = Result.getOrElse(descendSync(TS_FILES, {
|
|
25
25
|
cwd: dir,
|
|
26
26
|
...nodeWalkerSyncOps
|
|
@@ -29,11 +29,7 @@ function findConfigFiles(dir) {
|
|
|
29
29
|
for (const name of names) {
|
|
30
30
|
if (name.endsWith(".d.ts")) continue;
|
|
31
31
|
const path = join(dir, name);
|
|
32
|
-
try
|
|
33
|
-
const source = readFileSync(path, "utf8");
|
|
34
|
-
const { entries } = discoverCatalogEntries(source, path);
|
|
35
|
-
if (entries.length > 0) matches.push(path);
|
|
36
|
-
} catch {}
|
|
32
|
+
if (yield* fs.readFileString(path).pipe(Effect.flatMap((source) => Effect.try(() => discoverCatalogEntries(source, path).entries.length > 0)), Effect.orElseSucceed(() => false))) matches.push(path);
|
|
37
33
|
}
|
|
38
34
|
return matches;
|
|
39
35
|
});
|
package/cli/simulated-view.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canonicalize } from "./workspace-file.js";
|
|
2
2
|
import { row, tone } from "./render/tone.js";
|
|
3
3
|
import { scalarText } from "./diff/render.js";
|
|
4
|
+
import { Predicate } from "effect";
|
|
4
5
|
import { Doc } from "@effected/cli";
|
|
5
6
|
|
|
6
7
|
// src/cli/simulated-view.ts
|
|
@@ -42,7 +43,7 @@ function annotation(entry) {
|
|
|
42
43
|
/** Flatten one key/value into YAML-shaped plain lines; `ann` annotates the head. */
|
|
43
44
|
function flatten(key, value, depth, ann) {
|
|
44
45
|
if (Array.isArray(value)) return [row(" ", depth, [tone(`${key}:`, "plain"), ...ann]), ...value.map((el) => row(" ", depth + 1, [tone(`- ${scalarText(el)}`, "plain")]))];
|
|
45
|
-
if (value
|
|
46
|
+
if (Predicate.isObject(value)) return [row(" ", depth, [tone(`${key}:`, "plain"), ...ann]), ...Object.entries(value).flatMap(([k, v]) => flatten(k, v, depth + 1, []))];
|
|
46
47
|
return [row(" ", depth, [tone(`${key}: ${scalarText(value)}`, "plain"), ...ann])];
|
|
47
48
|
}
|
|
48
49
|
/**
|
package/cli/version.js
CHANGED
package/cli/workspace-file.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Result } from "effect";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Order, Predicate, Result } from "effect";
|
|
2
|
+
import { locateWorkspaceRootSync } from "@effected/workspaces";
|
|
3
|
+
import { nodeSyncOps } from "@effected/workspaces/node-sync";
|
|
4
4
|
import { Yaml, YamlStringifyOptions } from "@effected/yaml";
|
|
5
5
|
|
|
6
6
|
// src/cli/workspace-file.ts
|
|
@@ -23,31 +23,28 @@ function allPrimitive(arr) {
|
|
|
23
23
|
function canonicalize(value) {
|
|
24
24
|
if (Array.isArray(value)) {
|
|
25
25
|
const mapped = value.map(canonicalize);
|
|
26
|
-
return allPrimitive(mapped) ? [...mapped].sort((a, b) => String(a)
|
|
26
|
+
return allPrimitive(mapped) ? [...mapped].sort((a, b) => Order.String(String(a), String(b))) : mapped;
|
|
27
27
|
}
|
|
28
|
-
if (value
|
|
28
|
+
if (Predicate.isObject(value)) return Object.fromEntries(Object.entries(value).sort(([a], [b]) => Order.String(a, b)).map(([k, v]) => [k, canonicalize(v)]));
|
|
29
29
|
return value;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Walk up from `startDir` to the nearest directory containing a
|
|
33
|
-
* pnpm-workspace.yaml; returns the file path or null.
|
|
33
|
+
* pnpm-workspace.yaml; returns the file path or null. A `package.json`
|
|
34
|
+
* `workspaces` field is not a marker here: this tool targets pnpm only.
|
|
34
35
|
*
|
|
35
36
|
* @internal
|
|
36
37
|
*/
|
|
37
38
|
function findWorkspaceFile(startDir) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const parent = dirname(dir);
|
|
43
|
-
if (parent === dir) return null;
|
|
44
|
-
dir = parent;
|
|
45
|
-
}
|
|
39
|
+
return locateWorkspaceRootSync(startDir, {
|
|
40
|
+
...nodeSyncOps,
|
|
41
|
+
markers: [FILENAME]
|
|
42
|
+
})?.path ?? null;
|
|
46
43
|
}
|
|
47
44
|
/** Parse pnpm-workspace.yaml source; empty/whitespace yields an empty object. @internal */
|
|
48
45
|
function parseWorkspace(source) {
|
|
49
46
|
const parsed = Result.getOrThrow(Yaml.parseResult(source));
|
|
50
|
-
return parsed
|
|
47
|
+
return Predicate.isObject(parsed) ? parsed : {};
|
|
51
48
|
}
|
|
52
49
|
/** Render a workspace object: deterministic key sort + yaml.stringify. @internal */
|
|
53
50
|
function renderWorkspace(obj) {
|
package/cli/workspace-resolve.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { parseVersion } from "../semver-util.js";
|
|
2
|
-
import { findWorkspaceFile } from "./workspace-file.js";
|
|
3
2
|
import { ResolveError } from "./resolve.js";
|
|
4
3
|
import { Effect, Layer, Result } from "effect";
|
|
5
|
-
import {
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
6
5
|
import { GlobPattern, GlobPatternOptions } from "@effected/glob";
|
|
7
6
|
import { descendSync } from "@effected/walker";
|
|
8
7
|
import { nodeWalkerSyncOps } from "@effected/walker/node-sync";
|
|
9
8
|
import { readFileSync } from "node:fs";
|
|
10
|
-
import { getWorkspacePackagesSync } from "@effected/workspaces";
|
|
9
|
+
import { findWorkspaceRootSync, getWorkspacePackagesSync } from "@effected/workspaces";
|
|
11
10
|
import { nodeSyncOps } from "@effected/workspaces/node-sync";
|
|
12
11
|
|
|
13
12
|
// src/cli/workspace-resolve.ts
|
|
@@ -159,8 +158,10 @@ function makeWorkspaceResolver(rootDir) {
|
|
|
159
158
|
* @internal
|
|
160
159
|
*/
|
|
161
160
|
function findWorkspaceRoot(startDir) {
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
return findWorkspaceRootSync(startDir, {
|
|
162
|
+
...nodeSyncOps,
|
|
163
|
+
markers: ["pnpm-workspace.yaml"]
|
|
164
|
+
}) ?? resolve(startDir);
|
|
164
165
|
}
|
|
165
166
|
|
|
166
167
|
export { findWorkspaceRoot, makeWorkspaceResolver, readManifests, readWorkspaceVersions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rolldown-pnpm-config",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A dogfooding example of our plugin",
|
|
6
6
|
"repository": {
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"rolldown-pnpm-config": "bin/rolldown-pnpm-config.js"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@effect/platform-node": "^4.0.
|
|
39
|
-
"@effected/cli": "^0.
|
|
40
|
-
"@effected/env": "^0.
|
|
41
|
-
"@effected/glob": "^0.
|
|
42
|
-
"@effected/npm": "^0.
|
|
43
|
-
"@effected/semver": "^0.
|
|
44
|
-
"@effected/walker": "^0.
|
|
45
|
-
"@effected/workspaces": "^0.
|
|
46
|
-
"@effected/yaml": "^0.
|
|
47
|
-
"effect": "^4.0.
|
|
38
|
+
"@effect/platform-node": "^4.0.7",
|
|
39
|
+
"@effected/cli": "^0.24.0",
|
|
40
|
+
"@effected/env": "^0.7.0",
|
|
41
|
+
"@effected/glob": "^0.16.0",
|
|
42
|
+
"@effected/npm": "^0.28.0",
|
|
43
|
+
"@effected/semver": "^0.19.0",
|
|
44
|
+
"@effected/walker": "^0.22.0",
|
|
45
|
+
"@effected/workspaces": "^0.40.0",
|
|
46
|
+
"@effected/yaml": "^0.26.0",
|
|
47
|
+
"effect": "^4.0.7",
|
|
48
48
|
"ink": "^8.0.0",
|
|
49
49
|
"oxc-parser": "^0.156.0",
|
|
50
50
|
"react": "^19.3.1"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { rangeOf } from "../catalogs.js";
|
|
2
2
|
import { bareVersion } from "../semver-util.js";
|
|
3
|
+
import { Predicate } from "effect";
|
|
3
4
|
|
|
4
5
|
// src/plugin/allowed-versions.ts
|
|
5
6
|
/** An exact version: no range operator, no wildcard — `X.Y.Z` with an optional prerelease. */
|
|
@@ -43,7 +44,7 @@ function deriveAllowedVersions(catalogs, directives) {
|
|
|
43
44
|
* @internal
|
|
44
45
|
*/
|
|
45
46
|
function resolvePeerDependencyRules(value, catalogs) {
|
|
46
|
-
if (value
|
|
47
|
+
if (!Predicate.isObject(value) || !("allowedVersionsFromCatalogs" in value)) return value;
|
|
47
48
|
const { allowedVersionsFromCatalogs, ...rest } = value;
|
|
48
49
|
const merged = {
|
|
49
50
|
...deriveAllowedVersions(catalogs, allowedVersionsFromCatalogs),
|
package/plugin/freeze.js
CHANGED
|
@@ -3,7 +3,7 @@ import { DESCRIPTORS, deriveSchemas } from "../descriptors/index.js";
|
|
|
3
3
|
import { FIELD_REGISTRY } from "../registry.js";
|
|
4
4
|
import { resolvePeerDependencyRules } from "./allowed-versions.js";
|
|
5
5
|
import { resolveOverrides } from "./overrides-from-catalogs.js";
|
|
6
|
-
import { Data, Effect, Schema } from "effect";
|
|
6
|
+
import { Data, Effect, Predicate, Schema } from "effect";
|
|
7
7
|
import { Fmt } from "@effected/cli";
|
|
8
8
|
|
|
9
9
|
// src/plugin/freeze.ts
|
|
@@ -33,7 +33,7 @@ const WRAPPED_KEYS = /* @__PURE__ */ new Set([
|
|
|
33
33
|
* @internal
|
|
34
34
|
*/
|
|
35
35
|
function isWrappedField(input) {
|
|
36
|
-
if (input
|
|
36
|
+
if (!Predicate.isObject(input)) return false;
|
|
37
37
|
const keys = Object.keys(input);
|
|
38
38
|
return keys.includes("value") && keys.every((k) => WRAPPED_KEYS.has(k));
|
|
39
39
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { rangeOf } from "../catalogs.js";
|
|
2
2
|
import { bareVersion } from "../semver-util.js";
|
|
3
|
+
import { Predicate } from "effect";
|
|
3
4
|
|
|
4
5
|
// src/plugin/overrides-from-catalogs.ts
|
|
5
6
|
/** A plain release version: `X.Y.Z`, no prerelease, no build metadata. */
|
|
@@ -58,7 +59,7 @@ function deriveOverrides(catalogs, directives) {
|
|
|
58
59
|
function resolveOverrides(authored, directives, catalogs) {
|
|
59
60
|
if (directives === void 0) return authored;
|
|
60
61
|
const derived = deriveOverrides(catalogs, directives);
|
|
61
|
-
const manual = authored
|
|
62
|
+
const manual = Predicate.isObject(authored) ? authored : {};
|
|
62
63
|
return {
|
|
63
64
|
...derived,
|
|
64
65
|
...manual
|
package/plugin/serialize.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { Order, Predicate } from "effect";
|
|
2
|
+
|
|
1
3
|
// src/plugin/serialize.ts
|
|
2
4
|
/** Recursively sort object keys for deterministic output; arrays keep order. */
|
|
3
5
|
function sortKeys(value) {
|
|
4
6
|
if (Array.isArray(value)) return value.map(sortKeys);
|
|
5
|
-
if (value
|
|
7
|
+
if (Predicate.isObject(value)) return Object.fromEntries(Object.entries(value).sort(([a], [b]) => Order.String(a, b)).map(([k, v]) => [k, sortKeys(v)]));
|
|
6
8
|
return value;
|
|
7
9
|
}
|
|
8
10
|
/** Source for the `catalogs` virtual module: a sorted Map literal (plain-JS branch). */
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// src/runtime/strategies/arrays.ts
|
|
2
|
+
/** Code-unit order: locale-independent, so the render is the same on every machine. */
|
|
3
|
+
const byCodeUnit = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
2
4
|
/** Union `managed` with `local` (when present), deduped and sorted for a stable render. @internal */
|
|
3
5
|
function unionSort(managed, local) {
|
|
4
6
|
const set = new Set(managed);
|
|
5
7
|
for (const item of local ?? []) set.add(item);
|
|
6
|
-
return [...set].sort(
|
|
8
|
+
return [...set].sort(byCodeUnit);
|
|
7
9
|
}
|
|
8
10
|
/**
|
|
9
11
|
* Union + sort string arrays; child entries are added to the managed set. Quiet.
|
|
@@ -24,7 +26,7 @@ const arrayRecordUnion = (base, local) => {
|
|
|
24
26
|
const child = local ?? {};
|
|
25
27
|
const keys = /* @__PURE__ */ new Set([...Object.keys(managed), ...Object.keys(child)]);
|
|
26
28
|
const result = {};
|
|
27
|
-
for (const key of [...keys].sort(
|
|
29
|
+
for (const key of [...keys].sort(byCodeUnit)) {
|
|
28
30
|
const merged = unionSort(managed[key] ?? [], child[key]);
|
|
29
31
|
if (merged.length > 0) result[key] = merged;
|
|
30
32
|
}
|