@gjermundgaraba/upup 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/README.md +9 -7
- package/dist/{Tui-BiTtZ1EF.mjs → Tui-DV_6wbrQ.mjs} +42 -37
- package/dist/main.mjs +706 -287
- package/native/dist/upup-sparkle.json +1 -1
- package/native/dist/upup-sparkle.zip +0 -0
- package/package.json +16 -17
package/dist/main.mjs
CHANGED
|
@@ -20,7 +20,7 @@ import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/conte
|
|
|
20
20
|
import { Type } from "@earendil-works/pi-ai";
|
|
21
21
|
import { GenerationTask, Harness, ToolTask, createRegistry, defineDoc, defineExtension, defineTool, hook, section, watchEvents } from "@earendil-works/pi-durable";
|
|
22
22
|
import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
|
|
23
|
-
import { ChildProcess, ChildProcessSpawner } from "effect/process";
|
|
23
|
+
import { ChildProcess, ChildProcessSpawner, CommandLine } from "effect/process";
|
|
24
24
|
import { Worker } from "node:worker_threads";
|
|
25
25
|
import semver from "semver";
|
|
26
26
|
import tarStream from "tar-stream";
|
|
@@ -41,8 +41,9 @@ import { XMLParser } from "fast-xml-parser";
|
|
|
41
41
|
import { isSea } from "node:sea";
|
|
42
42
|
import * as ActionMcp from "@gjermundgaraba/effect-actions/ActionMcp";
|
|
43
43
|
import * as Action from "@gjermundgaraba/effect-actions/Action";
|
|
44
|
+
import { setup, types } from "xstate/fsm";
|
|
44
45
|
// package.json
|
|
45
|
-
var version$1 = "0.
|
|
46
|
+
var version$1 = "0.4.0";
|
|
46
47
|
// src/ai/Setup.ts
|
|
47
48
|
const Thinking = Schema.Literals([
|
|
48
49
|
"off",
|
|
@@ -283,7 +284,7 @@ const ordered = (left, right) => Number(right.signedIn) - Number(left.signedIn)
|
|
|
283
284
|
var AiFailed = class extends Schema.TaggedError()("AiFailed", { issue: Schema.String }) {};
|
|
284
285
|
var Ai = class extends Context.Service()("upup/Ai") {};
|
|
285
286
|
const failed$2 = (cause) => new AiFailed({ issue: cause instanceof Error ? cause.message : String(cause) });
|
|
286
|
-
const make$
|
|
287
|
+
const make$15 = (models, credentials = store()) => Effect.gen(function* () {
|
|
287
288
|
const settings = yield* Settings;
|
|
288
289
|
const catalogue = Effect.promise(async () => {
|
|
289
290
|
const providers = models.getProviders();
|
|
@@ -328,7 +329,7 @@ const make$14 = (models, credentials = store()) => Effect.gen(function* () {
|
|
|
328
329
|
});
|
|
329
330
|
const layer$7 = Layer.effect(Ai, Effect.suspend(() => {
|
|
330
331
|
const credentials = store();
|
|
331
|
-
return make$
|
|
332
|
+
return make$15(builtinModels({ credentials }), credentials);
|
|
332
333
|
}));
|
|
333
334
|
// src/process/lock.ts
|
|
334
335
|
var LockFailed = class extends Schema.TaggedError()("LockFailed", {
|
|
@@ -519,7 +520,7 @@ var CommandFailed = class extends Schema.TaggedError()("CommandFailed", {
|
|
|
519
520
|
output: Schema.String
|
|
520
521
|
}) {};
|
|
521
522
|
var Exec = class extends Context.Service()("upup/Exec") {};
|
|
522
|
-
const commandLine = (invocation) => [invocation.command, ...invocation.args]
|
|
523
|
+
const commandLine = (invocation) => CommandLine.display([invocation.command, ...invocation.args]);
|
|
523
524
|
const requireSuccess = (run) => (invocation) => run(invocation).pipe(Effect.filterOrFail((output) => output.exitCode === 0, (output) => new CommandFailed({
|
|
524
525
|
command: commandLine(invocation),
|
|
525
526
|
cwd: invocation.cwd,
|
|
@@ -550,7 +551,7 @@ const layer$6 = Layer.effect(Exec, Effect.gen(function* () {
|
|
|
550
551
|
}, Effect.scoped, (effect, invocation) => Effect.mapError(effect, (cause) => new CommandFailed({
|
|
551
552
|
command: commandLine(invocation),
|
|
552
553
|
cwd: invocation.cwd,
|
|
553
|
-
output: cause.message
|
|
554
|
+
output: Predicate.isError(cause.cause) ? cause.cause.message : cause.reason.description ?? cause.reason._tag
|
|
554
555
|
})));
|
|
555
556
|
return Exec.of({
|
|
556
557
|
run,
|
|
@@ -595,14 +596,14 @@ const Installed = Schema.Struct({
|
|
|
595
596
|
formulae: Schema.Array(Formula$2),
|
|
596
597
|
casks: Schema.Array(Cask$1)
|
|
597
598
|
});
|
|
598
|
-
const OutdatedEntry
|
|
599
|
+
const OutdatedEntry = Schema.Struct({
|
|
599
600
|
name: Schema.String,
|
|
600
601
|
current_version: Schema.String,
|
|
601
602
|
pinned: Schema.Boolean
|
|
602
603
|
});
|
|
603
|
-
const Outdated$
|
|
604
|
-
formulae: Schema.Array(OutdatedEntry
|
|
605
|
-
casks: Schema.Array(OutdatedEntry
|
|
604
|
+
const Outdated$1 = Schema.Struct({
|
|
605
|
+
formulae: Schema.Array(OutdatedEntry),
|
|
606
|
+
casks: Schema.Array(OutdatedEntry)
|
|
606
607
|
});
|
|
607
608
|
const brew$1 = (args, refreshMetadata = false) => ({
|
|
608
609
|
command: "brew",
|
|
@@ -653,7 +654,7 @@ const packages = (installed, outdated) => {
|
|
|
653
654
|
});
|
|
654
655
|
return [...formulae, ...casks];
|
|
655
656
|
};
|
|
656
|
-
const make$
|
|
657
|
+
const make$14 = Effect.gen(function* () {
|
|
657
658
|
const exec = yield* Exec;
|
|
658
659
|
const json = (schema, invocation) => exec.stdout(invocation).pipe(Effect.flatMap(decodeJson(schema, commandLine(invocation))));
|
|
659
660
|
const list = Effect.gen(function* () {
|
|
@@ -662,7 +663,7 @@ const make$13 = Effect.gen(function* () {
|
|
|
662
663
|
"--json=v2",
|
|
663
664
|
"--installed"
|
|
664
665
|
]));
|
|
665
|
-
const outdated = yield* json(Outdated$
|
|
666
|
+
const outdated = yield* json(Outdated$1, brew$1(["outdated", "--json=v2"], true));
|
|
666
667
|
return {
|
|
667
668
|
packages: packages(installed, outdated),
|
|
668
669
|
notices: []
|
|
@@ -695,7 +696,7 @@ const make$13 = Effect.gen(function* () {
|
|
|
695
696
|
exitCode: output.exitCode,
|
|
696
697
|
output: output.stderr
|
|
697
698
|
});
|
|
698
|
-
const outdated = yield* decodeJson(Outdated$
|
|
699
|
+
const outdated = yield* decodeJson(Outdated$1, commandLine(invocation))(output.stdout);
|
|
699
700
|
return [...outdated.formulae, ...outdated.casks].find((entry) => entry.name === pkg.name)?.current_version;
|
|
700
701
|
});
|
|
701
702
|
return {
|
|
@@ -797,7 +798,7 @@ const landingKey = (landing) => sha256(JSON.stringify([
|
|
|
797
798
|
]));
|
|
798
799
|
const unauditedReasons = {
|
|
799
800
|
app: "an app update",
|
|
800
|
-
runtime: "a runtime version
|
|
801
|
+
runtime: "a Node.js runtime version",
|
|
801
802
|
os: "an operating-system update"
|
|
802
803
|
};
|
|
803
804
|
const unauditable = (pkg) => {
|
|
@@ -2268,7 +2269,7 @@ var LookupFailed = class extends Schema.TaggedError()("LookupFailed", {
|
|
|
2268
2269
|
url: Schema.String,
|
|
2269
2270
|
issue: Schema.String
|
|
2270
2271
|
}) {};
|
|
2271
|
-
const Release$
|
|
2272
|
+
const Release$3 = Schema.fromJsonString(Schema.Struct({
|
|
2272
2273
|
vers: Schema.String,
|
|
2273
2274
|
yanked: Schema.Boolean
|
|
2274
2275
|
}));
|
|
@@ -2285,7 +2286,7 @@ const newestRelease = Effect.fn("CratesIndex.newestRelease")(function* (client,
|
|
|
2285
2286
|
issue: error.message
|
|
2286
2287
|
});
|
|
2287
2288
|
const text = yield* HttpClient.filterStatusOk(client).get(url).pipe(Effect.flatMap((response) => response.text), Effect.mapError(failed));
|
|
2288
|
-
const releases = yield* Effect.forEach(text.split("\n").filter((line) => line.trim().length > 0), (line) => Schema.decodeEffect(Release$
|
|
2289
|
+
const releases = yield* Effect.forEach(text.split("\n").filter((line) => line.trim().length > 0), (line) => Schema.decodeEffect(Release$3)(line).pipe(Effect.mapError(failed)));
|
|
2289
2290
|
return newestOffer(current, releases.filter((release) => !release.yanked).map((release) => release.vers));
|
|
2290
2291
|
});
|
|
2291
2292
|
// src/registry/Metadata.ts
|
|
@@ -6447,7 +6448,7 @@ const githubActionPreparer = (repositoryOf, options = {}) => Effect.fn("githubAc
|
|
|
6447
6448
|
const prepareGitHubAction = githubActionPreparer(githubRepository);
|
|
6448
6449
|
// src/audit/pypi.ts
|
|
6449
6450
|
const optional = (schema) => Schema.optionalKey(Schema.NullOr(schema));
|
|
6450
|
-
const Release$
|
|
6451
|
+
const Release$2 = Schema.Struct({ urls: optional(Schema.Array(Schema.Struct({
|
|
6451
6452
|
filename: optional(Schema.String),
|
|
6452
6453
|
url: optional(Schema.String),
|
|
6453
6454
|
packagetype: optional(Schema.String),
|
|
@@ -6538,7 +6539,7 @@ const artifactPlan = ([file, reason]) => {
|
|
|
6538
6539
|
};
|
|
6539
6540
|
const resolve$1 = Effect.fn("pypi.resolve")(function* (client, name, version, pythonVersion) {
|
|
6540
6541
|
const source = releaseUrl(name, version);
|
|
6541
|
-
const files = ((yield* getJson(client, source, Release$
|
|
6542
|
+
const files = ((yield* getJson(client, source, Release$2).pipe(Effect.mapError((error) => new EvidenceUnavailable({
|
|
6542
6543
|
source,
|
|
6543
6544
|
issue: error.issue
|
|
6544
6545
|
})))).urls ?? []).map((file) => ({
|
|
@@ -7748,7 +7749,7 @@ const toPackage$1 = ({ uses, resolved, source }) => {
|
|
|
7748
7749
|
};
|
|
7749
7750
|
};
|
|
7750
7751
|
const publicTags = (url) => tags(url, { timeout: lsRemoteTimeout }).pipe(Effect.mapError((error) => error.issue), Effect.result);
|
|
7751
|
-
const make$
|
|
7752
|
+
const make$13 = (root, origin, readPublic = publicTags) => Effect.gen(function* () {
|
|
7752
7753
|
const exec = yield* Exec;
|
|
7753
7754
|
const fs = yield* FileSystem.FileSystem;
|
|
7754
7755
|
const read = (file) => readText(file).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
@@ -7884,7 +7885,7 @@ const discover$4 = Effect.fn("GitHubActions.discover")(function* (dir) {
|
|
|
7884
7885
|
cwd: root
|
|
7885
7886
|
}).pipe(Effect.option);
|
|
7886
7887
|
const host = Option.isSome(origin) ? hostOf(origin.value.trim()) : void 0;
|
|
7887
|
-
return [yield* make$
|
|
7888
|
+
return [yield* make$13(root, host === "github.com" ? void 0 : host)];
|
|
7888
7889
|
});
|
|
7889
7890
|
// src/process/on-path.ts
|
|
7890
7891
|
const executable = (file) => Effect.promise(async () => await access(file, constants.X_OK).then(() => true, () => false));
|
|
@@ -7898,7 +7899,7 @@ const asRoot = (invocation) => [
|
|
|
7898
7899
|
];
|
|
7899
7900
|
const enablesTouchId = (pam) => pam.split("\n").some((line) => /^\s*auth\s+\S+\s+pam_tid\.so\b/u.test(line));
|
|
7900
7901
|
const pamFiles = ["/etc/pam.d/sudo_local", "/etc/pam.d/sudo"];
|
|
7901
|
-
const make$
|
|
7902
|
+
const make$12 = (interactive) => Effect.gen(function* () {
|
|
7902
7903
|
const exec = yield* Exec;
|
|
7903
7904
|
const fs = yield* FileSystem.FileSystem;
|
|
7904
7905
|
const asking = yield* SubscriptionRef.make(void 0);
|
|
@@ -7957,8 +7958,8 @@ const make$11 = (interactive) => Effect.gen(function* () {
|
|
|
7957
7958
|
answer
|
|
7958
7959
|
});
|
|
7959
7960
|
});
|
|
7960
|
-
const layer$4 = Layer.effect(Sudo, make$
|
|
7961
|
-
const layerNoPrompt = Layer.effect(Sudo, make$
|
|
7961
|
+
const layer$4 = Layer.effect(Sudo, make$12(true));
|
|
7962
|
+
const layerNoPrompt = Layer.effect(Sudo, make$12(false));
|
|
7962
7963
|
// src/apps/app-store.ts
|
|
7963
7964
|
const countryOf = (locale) => (/[@;]rg=(?<region>[a-z]{2})/iu.exec(locale)?.groups?.["region"] ?? /^[a-z]{2,3}[_-](?<region>[a-z]{2})\b/iu.exec(locale)?.groups?.["region"] ?? "us").toLowerCase();
|
|
7964
7965
|
const Lookup = Schema.Struct({ results: Schema.Array(Schema.Struct({
|
|
@@ -8750,7 +8751,7 @@ const locate$3 = Effect.gen(function* () {
|
|
|
8750
8751
|
return Option.isNone(manifest) || !(yield* fs.exists(zip).pipe(Effect.orElseSucceed(() => false))) ? Option.none() : yield* decode(manifest.value, zip);
|
|
8751
8752
|
});
|
|
8752
8753
|
// src/apps/swap.ts
|
|
8753
|
-
const tools = {
|
|
8754
|
+
const tools$2 = {
|
|
8754
8755
|
ps: "/bin/ps",
|
|
8755
8756
|
ditto: "/usr/bin/ditto",
|
|
8756
8757
|
mv: "/bin/mv",
|
|
@@ -9242,7 +9243,7 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9242
9243
|
return found;
|
|
9243
9244
|
});
|
|
9244
9245
|
const queue = yield* Ref.make([]);
|
|
9245
|
-
const using = options.tools ?? tools;
|
|
9246
|
+
const using = options.tools ?? tools$2;
|
|
9246
9247
|
const helper = options.sparkle === void 0 ? locate$3.pipe(Effect.provideService(FileSystem.FileSystem, fs)) : Effect.succeed(options.sparkle);
|
|
9247
9248
|
const sparkleOf = (pkg, install, build) => {
|
|
9248
9249
|
const refused = (reason) => new InstallRefused({
|
|
@@ -9442,7 +9443,7 @@ const makeWith = (options) => Effect.gen(function* () {
|
|
|
9442
9443
|
})
|
|
9443
9444
|
};
|
|
9444
9445
|
});
|
|
9445
|
-
const make$
|
|
9446
|
+
const make$11 = onPath("brew").pipe(Effect.flatMap((brewInstalled) => makeWith({
|
|
9446
9447
|
roots: ["/Applications", path.join(homedir(), "Applications")],
|
|
9447
9448
|
brew: brewInstalled
|
|
9448
9449
|
})));
|
|
@@ -9468,7 +9469,7 @@ const parseList = (text) => text.split("\n").flatMap((line) => {
|
|
|
9468
9469
|
fromCratesIo: source === void 0
|
|
9469
9470
|
}];
|
|
9470
9471
|
});
|
|
9471
|
-
const make$
|
|
9472
|
+
const make$10 = Effect.gen(function* () {
|
|
9472
9473
|
const exec = yield* Exec;
|
|
9473
9474
|
const client = yield* HttpClient.HttpClient;
|
|
9474
9475
|
const installed = exec.stdout(cargo$1(["install", "--list"])).pipe(Effect.map(parseList));
|
|
@@ -9544,18 +9545,30 @@ const locateAll = Effect.fn("locateAll")(function* (dir, nested, manifest, locat
|
|
|
9544
9545
|
const own = yield* locate(dir);
|
|
9545
9546
|
const below = yield* Effect.forEach(nested, (from) => Effect.map(Effect.result(locate(from)), (result) => [from, result]), { concurrency: 8 });
|
|
9546
9547
|
const found = /* @__PURE__ */ new Map();
|
|
9548
|
+
const claimed = /* @__PURE__ */ new Map();
|
|
9547
9549
|
const failed = [];
|
|
9548
|
-
const add = (located) => {
|
|
9549
|
-
if (Option.
|
|
9550
|
+
const add = (from, located) => {
|
|
9551
|
+
if (Option.isNone(located)) return;
|
|
9552
|
+
const { root } = located.value;
|
|
9553
|
+
if (!found.has(root)) found.set(root, located.value);
|
|
9554
|
+
claimed.set(root, [...claimed.get(root) ?? [], from]);
|
|
9550
9555
|
};
|
|
9551
|
-
add(own);
|
|
9556
|
+
add(dir, own);
|
|
9552
9557
|
const ownRoot = Option.map(own, (located) => located.root);
|
|
9553
9558
|
const outside = (located) => Option.isSome(located) && placeOf$1(dir, located.value.root) === "" && !Option.contains(ownRoot, located.value.root);
|
|
9559
|
+
const failures = below.flatMap(([from, result]) => Result.isFailure(result) ? [{
|
|
9560
|
+
from,
|
|
9561
|
+
reason: describeError(result.failure)
|
|
9562
|
+
}] : []);
|
|
9563
|
+
const repeated = (from, reason) => failures.some((other) => other.reason === reason && from.startsWith(`${other.from}${path.sep}`));
|
|
9554
9564
|
for (const [from, result] of below) if (Result.isSuccess(result)) {
|
|
9555
|
-
if (!outside(result.success)) add(result.success);
|
|
9556
|
-
} else failed.push(failing(path.join(path.relative(dir, from), manifest), result.failure));
|
|
9565
|
+
if (!outside(result.success)) add(from, result.success);
|
|
9566
|
+
} else if (!repeated(from, describeError(result.failure))) failed.push(failing(path.join(path.relative(dir, from), manifest), result.failure));
|
|
9557
9567
|
return {
|
|
9558
|
-
found: [...found.values()]
|
|
9568
|
+
found: [...found.values()].map((located) => ({
|
|
9569
|
+
...located,
|
|
9570
|
+
claimed: claimed.get(located.root) ?? []
|
|
9571
|
+
})),
|
|
9559
9572
|
failed
|
|
9560
9573
|
};
|
|
9561
9574
|
});
|
|
@@ -9642,10 +9655,11 @@ const entriesOf = (manifest, parsed) => {
|
|
|
9642
9655
|
for (const [name, spec] of Object.entries(parsed.workspace?.dependencies ?? {})) add(["workspace", "dependencies"], name, spec);
|
|
9643
9656
|
return entries;
|
|
9644
9657
|
};
|
|
9645
|
-
const cargo = (
|
|
9658
|
+
const cargo = (cwd, args) => ({
|
|
9646
9659
|
command: "cargo",
|
|
9647
9660
|
args,
|
|
9648
|
-
cwd
|
|
9661
|
+
cwd,
|
|
9662
|
+
env: { RUSTUP_AUTO_INSTALL: "0" }
|
|
9649
9663
|
});
|
|
9650
9664
|
const parseManifest = (file, text) => Effect.try({
|
|
9651
9665
|
try: () => getStaticTOMLValue(parseTOML(text)),
|
|
@@ -9670,7 +9684,7 @@ const resolvedByMember = (root, meta) => {
|
|
|
9670
9684
|
return [path.relative(root, pkg.manifest_path), deps];
|
|
9671
9685
|
}));
|
|
9672
9686
|
};
|
|
9673
|
-
const make$
|
|
9687
|
+
const make$9 = (root, place = "") => Effect.gen(function* () {
|
|
9674
9688
|
const providerName = placed("cargo", place);
|
|
9675
9689
|
const exec = yield* Exec;
|
|
9676
9690
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -9683,6 +9697,7 @@ const make$8 = (root, place = "") => Effect.gen(function* () {
|
|
|
9683
9697
|
"metadata",
|
|
9684
9698
|
"--format-version",
|
|
9685
9699
|
"1",
|
|
9700
|
+
"--all-features",
|
|
9686
9701
|
"--locked"
|
|
9687
9702
|
]);
|
|
9688
9703
|
return yield* exec.stdout(invocation).pipe(Effect.flatMap(decodeJson(Metadata, commandLine(invocation))));
|
|
@@ -9731,6 +9746,11 @@ const make$8 = (root, place = "") => Effect.gen(function* () {
|
|
|
9731
9746
|
};
|
|
9732
9747
|
});
|
|
9733
9748
|
const list = Effect.gen(function* () {
|
|
9749
|
+
const lockfile = path.join(root, "Cargo.lock");
|
|
9750
|
+
if (!(yield* fs.exists(lockfile).pipe(Effect.mapError(fileFailed("stat", lockfile))))) return {
|
|
9751
|
+
packages: [],
|
|
9752
|
+
notices: [{ message: "not listed: no Cargo.lock yet" }]
|
|
9753
|
+
};
|
|
9734
9754
|
const { declared, notices } = yield* declarations;
|
|
9735
9755
|
return {
|
|
9736
9756
|
packages: yield* Effect.forEach(declared, ({ pkg }) => newestRelease(client, pkg.artifact, pkg.current).pipe(Effect.map((target) => {
|
|
@@ -9812,21 +9832,17 @@ const locate$2 = Effect.fn("CargoWorkspace.locate")(function* (dir) {
|
|
|
9812
9832
|
const exec = yield* Exec;
|
|
9813
9833
|
const manifest = yield* findUp(dir, "Cargo.toml");
|
|
9814
9834
|
if (Option.isNone(manifest)) return Option.none();
|
|
9815
|
-
const root = yield* exec.stdout(
|
|
9816
|
-
|
|
9817
|
-
|
|
9818
|
-
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
"plain"
|
|
9822
|
-
],
|
|
9823
|
-
cwd: manifest.value
|
|
9824
|
-
});
|
|
9835
|
+
const root = yield* exec.stdout(cargo(manifest.value, [
|
|
9836
|
+
"locate-project",
|
|
9837
|
+
"--workspace",
|
|
9838
|
+
"--message-format",
|
|
9839
|
+
"plain"
|
|
9840
|
+
]));
|
|
9825
9841
|
return Option.some({ root: path.dirname(root.trim()) });
|
|
9826
9842
|
});
|
|
9827
9843
|
const discover$3 = Effect.fn("CargoWorkspace.discover")(function* (dir, nested = []) {
|
|
9828
9844
|
const { found, failed } = yield* locateAll(dir, nested, "Cargo.toml", locate$2);
|
|
9829
|
-
return [...failed, ...yield* Effect.forEach(found, ({ root }) => make$
|
|
9845
|
+
return [...failed, ...yield* Effect.forEach(found, ({ root }) => make$9(root, placeOf$1(dir, root)))];
|
|
9830
9846
|
});
|
|
9831
9847
|
// src/registry/origin.ts
|
|
9832
9848
|
const trailing = (url) => url.endsWith("/") ? url : `${url}/`;
|
|
@@ -9971,14 +9987,15 @@ const fromBuildInfo = (info, file) => {
|
|
|
9971
9987
|
current: main.Version
|
|
9972
9988
|
}) : Option.none();
|
|
9973
9989
|
};
|
|
9974
|
-
const make$
|
|
9990
|
+
const make$8 = Effect.gen(function* () {
|
|
9975
9991
|
const exec = yield* Exec;
|
|
9976
9992
|
const fs = yield* FileSystem.FileSystem;
|
|
9977
|
-
const
|
|
9993
|
+
const envInvocation = go([
|
|
9978
9994
|
"env",
|
|
9979
9995
|
"-json",
|
|
9980
9996
|
...envKeys
|
|
9981
|
-
])
|
|
9997
|
+
]);
|
|
9998
|
+
const goEnv = yield* Effect.cached(exec.stdout(envInvocation).pipe(Effect.flatMap(decodeGoJson(GoEnv, commandLine(envInvocation)))));
|
|
9982
9999
|
const binDir = goEnv.pipe(Effect.map((env) => env.GOBIN || path.join(env.GOPATH.split(":")[0] ?? env.GOPATH, "bin")));
|
|
9983
10000
|
const inspect = Effect.fn("GoInstall.inspect")(function* (dir, file) {
|
|
9984
10001
|
const invocation = go([
|
|
@@ -10066,6 +10083,7 @@ const make$7 = Effect.gen(function* () {
|
|
|
10066
10083
|
});
|
|
10067
10084
|
// src/go/GoModule.ts
|
|
10068
10085
|
const ModFile = Schema.Struct({
|
|
10086
|
+
Module: Schema.optionalKey(Schema.Struct({ Path: Schema.String })),
|
|
10069
10087
|
Require: Schema.optionalKey(Schema.Array(Schema.Struct({
|
|
10070
10088
|
Path: Schema.String,
|
|
10071
10089
|
Version: Schema.String,
|
|
@@ -10079,7 +10097,10 @@ const Selected = Schema.Struct({
|
|
|
10079
10097
|
Update: Schema.optionalKey(Schema.Struct({ Version: Schema.String })),
|
|
10080
10098
|
Error: Schema.optionalKey(Schema.Struct({ Err: Schema.String }))
|
|
10081
10099
|
});
|
|
10082
|
-
const WorkFile = Schema.Struct({
|
|
10100
|
+
const WorkFile = Schema.Struct({
|
|
10101
|
+
Use: Schema.optionalKey(Schema.Array(Schema.Struct({ DiskPath: Schema.String }))),
|
|
10102
|
+
Replace: Schema.optionalKey(Schema.Array(Schema.Struct({ Old: Schema.Struct({ Path: Schema.String }) })))
|
|
10103
|
+
});
|
|
10083
10104
|
const goEnv = {
|
|
10084
10105
|
GOWORK: "off",
|
|
10085
10106
|
GIT_TERMINAL_PROMPT: "0"
|
|
@@ -10089,26 +10110,30 @@ const GoProxyEnv = Schema.Struct({
|
|
|
10089
10110
|
GOPRIVATE: Schema.optionalKey(Schema.String),
|
|
10090
10111
|
GONOPROXY: Schema.optionalKey(Schema.String)
|
|
10091
10112
|
});
|
|
10092
|
-
const directRequirements = (mod) => {
|
|
10113
|
+
const directRequirements = (mod, local) => {
|
|
10093
10114
|
const replaced = new Set((mod.Replace ?? []).map((replace) => replace.Old.Path));
|
|
10094
|
-
return (mod.Require ?? []).filter((requirement) => requirement.Indirect !== true && !replaced.has(requirement.Path));
|
|
10115
|
+
return (mod.Require ?? []).filter((requirement) => requirement.Indirect !== true && !replaced.has(requirement.Path) && !local.has(requirement.Path));
|
|
10095
10116
|
};
|
|
10096
|
-
const
|
|
10117
|
+
const goIn = (cwd, args) => ({
|
|
10118
|
+
command: "go",
|
|
10119
|
+
args,
|
|
10120
|
+
cwd,
|
|
10121
|
+
env: goEnv
|
|
10122
|
+
});
|
|
10123
|
+
const readModFile = (exec, cwd) => {
|
|
10124
|
+
const edit = goIn(cwd, [
|
|
10125
|
+
"mod",
|
|
10126
|
+
"edit",
|
|
10127
|
+
"-json"
|
|
10128
|
+
]);
|
|
10129
|
+
return exec.stdout(edit).pipe(Effect.flatMap(decodeGoJson(ModFile, commandLine(edit))));
|
|
10130
|
+
};
|
|
10131
|
+
const make$7 = (root, moduleDir, place = "", local = /* @__PURE__ */ new Set()) => Effect.gen(function* () {
|
|
10097
10132
|
const exec = yield* Exec;
|
|
10098
10133
|
const manifest = path.join(place, path.relative(root, path.join(moduleDir, "go.mod")));
|
|
10099
|
-
const go = (args) => (
|
|
10100
|
-
command: "go",
|
|
10101
|
-
args,
|
|
10102
|
-
cwd: moduleDir,
|
|
10103
|
-
env: goEnv
|
|
10104
|
-
});
|
|
10134
|
+
const go = (args) => goIn(moduleDir, args);
|
|
10105
10135
|
const requirements = Effect.gen(function* () {
|
|
10106
|
-
|
|
10107
|
-
"mod",
|
|
10108
|
-
"edit",
|
|
10109
|
-
"-json"
|
|
10110
|
-
]);
|
|
10111
|
-
return directRequirements(yield* exec.stdout(edit).pipe(Effect.flatMap(decodeGoJson(ModFile, commandLine(edit)))));
|
|
10136
|
+
return directRequirements(yield* readModFile(exec, moduleDir), local);
|
|
10112
10137
|
});
|
|
10113
10138
|
const selected = Effect.fn("GoModule.selected")(function* (paths, withUpdates) {
|
|
10114
10139
|
if (paths.length === 0) return /* @__PURE__ */ new Map();
|
|
@@ -10211,36 +10236,56 @@ const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
|
|
|
10211
10236
|
const exec = yield* Exec;
|
|
10212
10237
|
const { found, failed } = yield* locateAll(dir, nested, "go.mod", locate$1);
|
|
10213
10238
|
const failedWorks = [];
|
|
10214
|
-
const
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
"-json"
|
|
10225
|
-
],
|
|
10226
|
-
cwd: root
|
|
10227
|
-
};
|
|
10228
|
-
const file = yield* exec.stdout(edit).pipe(Effect.flatMap(decodeGoJson(WorkFile, commandLine(edit))), Effect.result);
|
|
10239
|
+
const listed = /* @__PURE__ */ new Set();
|
|
10240
|
+
const modules = yield* Effect.forEach(found, ({ root, work, claimed }) => Effect.gen(function* () {
|
|
10241
|
+
if (!work) {
|
|
10242
|
+
listed.add(root);
|
|
10243
|
+
return [{
|
|
10244
|
+
root,
|
|
10245
|
+
moduleDir: root,
|
|
10246
|
+
local: /* @__PURE__ */ new Set()
|
|
10247
|
+
}];
|
|
10248
|
+
}
|
|
10229
10249
|
const place = placeOf$1(dir, root);
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10250
|
+
const scanned = yield* Effect.gen(function* () {
|
|
10251
|
+
const edit = {
|
|
10252
|
+
command: "go",
|
|
10253
|
+
args: [
|
|
10254
|
+
"work",
|
|
10255
|
+
"edit",
|
|
10256
|
+
"-json"
|
|
10257
|
+
],
|
|
10258
|
+
cwd: root
|
|
10259
|
+
};
|
|
10260
|
+
const file = yield* exec.stdout(edit).pipe(Effect.flatMap(decodeGoJson(WorkFile, commandLine(edit))));
|
|
10261
|
+
const used = (file.Use ?? []).map((use) => path.resolve(root, use.DiskPath));
|
|
10262
|
+
for (const moduleDir of used) listed.add(moduleDir);
|
|
10263
|
+
const paths = yield* Effect.forEach(used, (moduleDir) => Effect.gen(function* () {
|
|
10264
|
+
const mod = yield* readModFile(exec, moduleDir);
|
|
10265
|
+
if (mod.Module === void 0) return yield* new OutputMalformed({
|
|
10266
|
+
command: "go mod edit -json",
|
|
10267
|
+
issue: `no module path in ${path.join(moduleDir, "go.mod")}`
|
|
10268
|
+
});
|
|
10269
|
+
return mod.Module.Path;
|
|
10270
|
+
}), { concurrency: 8 });
|
|
10271
|
+
const local = /* @__PURE__ */ new Set([...paths, ...(file.Replace ?? []).map((replace) => replace.Old.Path)]);
|
|
10272
|
+
return used.map((moduleDir) => ({
|
|
10273
|
+
root,
|
|
10274
|
+
moduleDir,
|
|
10275
|
+
local
|
|
10276
|
+
})).filter(({ moduleDir }) => place === "" || placeOf$1(dir, moduleDir) !== "");
|
|
10277
|
+
}).pipe(Effect.result);
|
|
10278
|
+
if (Result.isSuccess(scanned)) return scanned.success;
|
|
10279
|
+
for (const moduleDir of claimed) listed.add(moduleDir);
|
|
10280
|
+
failedWorks.push(failing(path.join(place, "go.work"), scanned.failure));
|
|
10236
10281
|
return [];
|
|
10237
10282
|
}));
|
|
10238
|
-
const listed = new Set(modules.flat().map(({ moduleDir }) => moduleDir));
|
|
10239
10283
|
const outside = nested.flatMap((moduleDir) => listed.has(moduleDir) ? [] : [{
|
|
10240
10284
|
root: moduleDir,
|
|
10241
|
-
moduleDir
|
|
10285
|
+
moduleDir,
|
|
10286
|
+
local: /* @__PURE__ */ new Set()
|
|
10242
10287
|
}]);
|
|
10243
|
-
const providers = yield* Effect.forEach([...modules.flat(), ...outside], ({ root, moduleDir }) => make$
|
|
10288
|
+
const providers = yield* Effect.forEach([...modules.flat(), ...outside], ({ root, moduleDir, local }) => make$7(root, moduleDir, placeOf$1(dir, root), local));
|
|
10244
10289
|
return [
|
|
10245
10290
|
...failed,
|
|
10246
10291
|
...failedWorks,
|
|
@@ -10249,7 +10294,7 @@ const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
|
|
|
10249
10294
|
});
|
|
10250
10295
|
// src/inventory/ProviderSource.ts
|
|
10251
10296
|
var ProviderSource = class extends Context.Service()("upup/ProviderSource") {};
|
|
10252
|
-
// src/node/
|
|
10297
|
+
// src/node/release-history.ts
|
|
10253
10298
|
const minutesPerDay = 1440;
|
|
10254
10299
|
const firstPnpmMajorWithDefaultReleaseAge = 11;
|
|
10255
10300
|
const gateSettings = {
|
|
@@ -10287,16 +10332,18 @@ const exempt = (rules, name, version) => {
|
|
|
10287
10332
|
};
|
|
10288
10333
|
const isPrerelease = (version) => semver.prerelease(version) !== null;
|
|
10289
10334
|
const lineOf = (version) => (semver.prerelease(version) ?? []).map((part) => Predicate.isNumber(part) ? "#" : part).join(".");
|
|
10290
|
-
const
|
|
10335
|
+
const releaseSuccessor = (name, current, history, gate, now) => {
|
|
10291
10336
|
const line = lineOf(current);
|
|
10292
10337
|
const following = isPrerelease(current);
|
|
10293
10338
|
const pinned = Date.parse(history.time[current] ?? "");
|
|
10294
10339
|
if (following && Number.isNaN(pinned)) return Result.fail(`${name} ${current} has no publish date, so upup offers it nothing`);
|
|
10295
10340
|
const releasedBeforePrereleasePin = (published) => following && !(published > pinned);
|
|
10341
|
+
const latest = semver.valid(history.latest ?? "");
|
|
10342
|
+
const beyondLatest = (candidate) => latest !== null && semver.gt(candidate, latest);
|
|
10296
10343
|
let newest;
|
|
10297
10344
|
for (const candidate of history.versions) {
|
|
10298
10345
|
if (semver.valid(candidate) === null || !semver.gt(candidate, current)) continue;
|
|
10299
|
-
if (isPrerelease(candidate)
|
|
10346
|
+
if (isPrerelease(candidate) ? lineOf(candidate) !== line : beyondLatest(candidate)) continue;
|
|
10300
10347
|
const published = Date.parse(history.time[candidate] ?? "");
|
|
10301
10348
|
if (Number.isNaN(published) || releasedBeforePrereleasePin(published)) continue;
|
|
10302
10349
|
if (gate.minutes > 0 && now - published < gate.minutes * 6e4 && !exempt(gate.exclude, name, candidate)) continue;
|
|
@@ -10304,35 +10351,64 @@ const prereleaseSuccessor = (name, current, history, gate, now) => {
|
|
|
10304
10351
|
}
|
|
10305
10352
|
return Result.succeed(newest);
|
|
10306
10353
|
};
|
|
10307
|
-
const
|
|
10354
|
+
const ViewedRelease = Schema.Struct({
|
|
10308
10355
|
versions: Schema.Union([Schema.String, Schema.Array(Schema.String)]),
|
|
10309
|
-
time: Schema.Record(Schema.String, Schema.String)
|
|
10310
|
-
})
|
|
10311
|
-
|
|
10356
|
+
time: Schema.Record(Schema.String, Schema.String),
|
|
10357
|
+
"dist-tags": Schema.optionalKey(Schema.Struct({ latest: Schema.optionalKey(Schema.String) }))
|
|
10358
|
+
});
|
|
10359
|
+
const Viewed = Schema.Union([ViewedRelease, Schema.NonEmptyArray(ViewedRelease)]);
|
|
10360
|
+
const ViewFailed = Schema.Struct({ error: Schema.Struct({
|
|
10361
|
+
code: Schema.optionalKey(Schema.String),
|
|
10362
|
+
summary: Schema.optionalKey(Schema.String),
|
|
10363
|
+
message: Schema.optionalKey(Schema.String)
|
|
10364
|
+
}) });
|
|
10365
|
+
const releaseOffers = Effect.fn("releaseOffers")(function* (pins, manager, run, config) {
|
|
10312
10366
|
const exec = yield* Exec;
|
|
10313
10367
|
const now = yield* Clock.currentTimeMillis;
|
|
10314
|
-
const read = (artifact)
|
|
10368
|
+
const read = Effect.fn("releaseOffers.read")(function* (artifact) {
|
|
10315
10369
|
const view = run([
|
|
10316
10370
|
"view",
|
|
10317
10371
|
artifact,
|
|
10318
10372
|
"versions",
|
|
10319
10373
|
"time",
|
|
10374
|
+
"dist-tags",
|
|
10320
10375
|
"--json"
|
|
10321
10376
|
]);
|
|
10322
|
-
|
|
10377
|
+
const output = yield* exec.run(view);
|
|
10378
|
+
if (output.exitCode !== 0) {
|
|
10379
|
+
const reported = Option.getOrUndefined(Schema.decodeOption(Schema.fromJsonString(ViewFailed))(output.stdout))?.error;
|
|
10380
|
+
if (reported?.code?.includes("404") === true) return [artifact, Result.fail(`${artifact} isn't on the registry, or your credentials can't see it, so upup offers it nothing`)];
|
|
10381
|
+
return yield* new CommandFailed({
|
|
10382
|
+
command: commandLine(view),
|
|
10383
|
+
cwd: view.cwd,
|
|
10384
|
+
exitCode: output.exitCode,
|
|
10385
|
+
output: reported?.summary ?? reported?.message ?? output.stderr
|
|
10386
|
+
});
|
|
10387
|
+
}
|
|
10388
|
+
const decoded = yield* decodeJson(Viewed, commandLine(view))(output.stdout);
|
|
10389
|
+
const viewed = "versions" in decoded ? decoded : decoded[0];
|
|
10390
|
+
const latest = viewed["dist-tags"]?.latest;
|
|
10391
|
+
const history = {
|
|
10323
10392
|
versions: [viewed.versions].flat(),
|
|
10324
|
-
time: viewed.time
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
|
|
10329
|
-
const
|
|
10330
|
-
const
|
|
10393
|
+
time: viewed.time,
|
|
10394
|
+
...latest === void 0 ? {} : { latest }
|
|
10395
|
+
};
|
|
10396
|
+
return [artifact, Result.succeed(history)];
|
|
10397
|
+
});
|
|
10398
|
+
const artifacts = new Set(pins.map((pin) => pin.artifact));
|
|
10399
|
+
const reads = yield* Effect.result(Effect.forEach(artifacts, read, { concurrency: 8 }));
|
|
10400
|
+
const histories = new Map(Result.isSuccess(reads) ? reads.success : []);
|
|
10401
|
+
const notices = Result.isFailure(reads) ? [{ message: `release histories could not be read, so upup offers nothing: ${describeError(reads.failure)}` }] : [];
|
|
10402
|
+
const version = manager === "pnpm" && histories.size > 0 ? yield* exec.stdout(run(["--version"])) : "";
|
|
10331
10403
|
const gate = releaseGate(manager, version.trim(), config);
|
|
10332
|
-
|
|
10333
|
-
const history =
|
|
10334
|
-
if (history === void 0) return;
|
|
10335
|
-
return Result.
|
|
10404
|
+
const offer = (pin) => {
|
|
10405
|
+
const history = histories.get(pin.artifact);
|
|
10406
|
+
if (history === void 0) return Result.succeed(void 0);
|
|
10407
|
+
return Result.flatMap(history, (found) => releaseSuccessor(pin.artifact, pin.current, found, gate, now));
|
|
10408
|
+
};
|
|
10409
|
+
return {
|
|
10410
|
+
offer,
|
|
10411
|
+
notices
|
|
10336
10412
|
};
|
|
10337
10413
|
});
|
|
10338
10414
|
// src/node/script-policy.ts
|
|
@@ -10388,7 +10464,7 @@ const Root = Schema.Struct({
|
|
|
10388
10464
|
dependencies: Schema.optionalKey(Schema.Record(Schema.String, Dependency))
|
|
10389
10465
|
});
|
|
10390
10466
|
const Listed$1 = Schema.Union([Root, Schema.Array(Root)]);
|
|
10391
|
-
const Outdated
|
|
10467
|
+
const Outdated = Schema.Record(Schema.String, Schema.Struct({ latest: Schema.optionalKey(Schema.String) }));
|
|
10392
10468
|
const parseListed = (provider, listed) => {
|
|
10393
10469
|
const roots = Array.isArray(listed) ? listed : [listed];
|
|
10394
10470
|
const pkg = (name, version, runtime) => ({
|
|
@@ -10422,7 +10498,7 @@ const makeGlobal = (spec) => Effect.gen(function* () {
|
|
|
10422
10498
|
const latest = Effect.gen(function* () {
|
|
10423
10499
|
const outdated = invocation(spec.outdated);
|
|
10424
10500
|
const output = yield* exec.run(outdated);
|
|
10425
|
-
const parsed = yield* decodeJson(Outdated
|
|
10501
|
+
const parsed = yield* decodeJson(Outdated, commandLine(outdated))(output.stdout).pipe(Effect.catchTag("OutputMalformed", (error) => output.exitCode === 0 ? Effect.fail(error) : Effect.fail(new CommandFailed({
|
|
10426
10502
|
command: commandLine(outdated),
|
|
10427
10503
|
cwd: outdated.cwd,
|
|
10428
10504
|
exitCode: output.exitCode,
|
|
@@ -10436,20 +10512,20 @@ const makeGlobal = (spec) => Effect.gen(function* () {
|
|
|
10436
10512
|
latest,
|
|
10437
10513
|
readNpmConfig(spec.config, "/").pipe(Effect.provideService(Exec, exec))
|
|
10438
10514
|
], { concurrency: 3 });
|
|
10439
|
-
const
|
|
10515
|
+
const { offer, notices: unread } = yield* releaseOffers(packages.filter((pkg) => isPrerelease(pkg.current)), spec.config, (args) => ({
|
|
10440
10516
|
command: spec.config,
|
|
10441
10517
|
args,
|
|
10442
10518
|
cwd: "/"
|
|
10443
10519
|
}), config).pipe(Effect.provideService(Exec, exec));
|
|
10444
|
-
const notices = [];
|
|
10520
|
+
const notices = [...unread];
|
|
10445
10521
|
return {
|
|
10446
10522
|
packages: packages.map(withNpmOrigin(npmRegistries(config))).map((pkg) => {
|
|
10447
|
-
const line =
|
|
10448
|
-
if (
|
|
10523
|
+
const line = offer(pkg);
|
|
10524
|
+
if (Result.isFailure(line)) notices.push({
|
|
10449
10525
|
rowKey: rowKey(pkg),
|
|
10450
10526
|
message: line.failure
|
|
10451
10527
|
});
|
|
10452
|
-
const target =
|
|
10528
|
+
const target = isPrerelease(pkg.current) ? Result.getOrUndefined(line) : targets.get(pkg.name);
|
|
10453
10529
|
return target !== void 0 && isNewerStable(pkg.current, target) ? withTarget(pkg, target) : pkg;
|
|
10454
10530
|
}),
|
|
10455
10531
|
notices
|
|
@@ -10671,7 +10747,7 @@ const scan = Effect.fn("NodePins.scan")(function* (root, dir, nested) {
|
|
|
10671
10747
|
const files = yield* Effect.forEach(versioned.toSorted(), (file) => Effect.map(read(file), (text) => filePin(file, text)));
|
|
10672
10748
|
return [...steps, ...files.flat()];
|
|
10673
10749
|
});
|
|
10674
|
-
const make$
|
|
10750
|
+
const make$6 = (root, dir = root, nested = []) => Effect.gen(function* () {
|
|
10675
10751
|
const fs = yield* FileSystem.FileSystem;
|
|
10676
10752
|
const client = yield* HttpClient.HttpClient;
|
|
10677
10753
|
const context = yield* Effect.context();
|
|
@@ -10742,7 +10818,7 @@ const discover$1 = Effect.fn("NodePins.discover")(function* (dir, nested = []) {
|
|
|
10742
10818
|
if (Option.isNone(repository)) return [];
|
|
10743
10819
|
const pins = yield* scan(repository.value, dir, nested).pipe(Effect.result);
|
|
10744
10820
|
if (Result.isSuccess(pins) && pins.success.length === 0) return [];
|
|
10745
|
-
return [yield* make$
|
|
10821
|
+
return [yield* make$6(repository.value, dir, nested)];
|
|
10746
10822
|
});
|
|
10747
10823
|
// src/node/selector.ts
|
|
10748
10824
|
const split = (name, spec) => {
|
|
@@ -10794,20 +10870,21 @@ const Manifest = Schema.Struct({
|
|
|
10794
10870
|
optionalDependencies: Schema.optionalKey(Specs)
|
|
10795
10871
|
});
|
|
10796
10872
|
const Resolved = Schema.Record(Schema.String, Schema.Struct({ version: Schema.String }));
|
|
10797
|
-
const PnpmLock = Schema.Struct({
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10873
|
+
const PnpmLock = Schema.Struct({
|
|
10874
|
+
overrides: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
|
|
10875
|
+
importers: Schema.optionalKey(Schema.Record(Schema.String, Schema.Struct({
|
|
10876
|
+
dependencies: Schema.optionalKey(Resolved),
|
|
10877
|
+
devDependencies: Schema.optionalKey(Resolved),
|
|
10878
|
+
optionalDependencies: Schema.optionalKey(Resolved)
|
|
10879
|
+
})))
|
|
10880
|
+
});
|
|
10802
10881
|
const PnpmManagerLock = Schema.Struct({ importers: Schema.optionalKey(Schema.Record(Schema.String, Schema.Struct({ packageManagerDependencies: Schema.optionalKey(Resolved) }))) });
|
|
10803
10882
|
const NpmLock = Schema.Struct({ packages: Schema.Record(Schema.String, Schema.Struct({ version: Schema.optionalKey(Schema.String) })) });
|
|
10804
10883
|
const Workspace = Schema.Struct({
|
|
10805
10884
|
catalog: Schema.optionalKey(Specs),
|
|
10806
|
-
catalogs: Schema.optionalKey(Schema.Record(Schema.String, Specs))
|
|
10885
|
+
catalogs: Schema.optionalKey(Schema.Record(Schema.String, Specs)),
|
|
10886
|
+
overrides: Schema.optionalKey(Specs)
|
|
10807
10887
|
});
|
|
10808
|
-
const OutdatedEntry = Schema.Struct({ latest: Schema.optionalKey(Schema.String) });
|
|
10809
|
-
const Outdated = Schema.Record(Schema.String, Schema.Union([OutdatedEntry, Schema.Array(OutdatedEntry)]));
|
|
10810
|
-
const NpmError = Schema.Struct({ error: Schema.Struct({ summary: Schema.String }) });
|
|
10811
10888
|
const PackageJsonFields = Schema.Struct({
|
|
10812
10889
|
workspaces: Schema.optionalKey(Schema.Unknown),
|
|
10813
10890
|
packageManager: Schema.optionalKey(Schema.String),
|
|
@@ -10830,25 +10907,22 @@ const managerEntry = "the package manager's declaration is removed by hand, in p
|
|
|
10830
10907
|
const resolvedVersion = (version) => version?.split("(")[0];
|
|
10831
10908
|
const readJson = (schema, file) => readText(file).pipe(Effect.flatMap((text) => decodeFile(schema, file)(parse$1(text))));
|
|
10832
10909
|
const exact = (version) => semver.valid(version) === version ? version : void 0;
|
|
10910
|
+
const overriddenName = (key) => {
|
|
10911
|
+
const target = key.split(">").at(-1) ?? key;
|
|
10912
|
+
const at = target.indexOf("@", target.startsWith("@") ? 1 : 0);
|
|
10913
|
+
return at === -1 ? target : target.slice(0, at);
|
|
10914
|
+
};
|
|
10833
10915
|
const corepackHashed = (name, algorithm) => {
|
|
10834
10916
|
if (algorithm === void 0) return {};
|
|
10835
10917
|
if (algorithm === "sha512") return { hashed: true };
|
|
10836
10918
|
return { held: `${name}'s packageManager entry carries a ${algorithm} hash, which upup can work out only for sha512; move it by hand` };
|
|
10837
10919
|
};
|
|
10838
|
-
const pinOf = ({ pkg, manager: own }) => ({
|
|
10839
|
-
artifact: pkg.artifact,
|
|
10840
|
-
current: pkg.current,
|
|
10841
|
-
...own === true ? { history: true } : {}
|
|
10842
|
-
});
|
|
10843
10920
|
const editDeclaration = (text, manifest, entry, next) => {
|
|
10844
10921
|
if (next === void 0 && entry.pkg.unremovable !== void 0) return Result.fail(entry.pkg.unremovable);
|
|
10845
10922
|
if (manifest.endsWith(".yaml") && next !== void 0) return editYamlScalar(text, entry.path, next);
|
|
10846
10923
|
return editJson(text, entry.path, next);
|
|
10847
10924
|
};
|
|
10848
|
-
const
|
|
10849
|
-
const withoutLockedVersionSuffix = (key) => key.replace(/(?<=.)@[^@/ ]+$/u, "");
|
|
10850
|
-
const outdatedName = (key) => withoutLockedVersionSuffix(withoutDependencyKindMarker(key));
|
|
10851
|
-
const make$4 = (root, manager, place = "") => Effect.gen(function* () {
|
|
10925
|
+
const make$5 = (root, manager, place = "", claimed = []) => Effect.gen(function* () {
|
|
10852
10926
|
const providerName = placed(manager, place);
|
|
10853
10927
|
const exec = yield* Exec;
|
|
10854
10928
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -10929,6 +11003,9 @@ const make$4 = (root, manager, place = "") => Effect.gen(function* () {
|
|
|
10929
11003
|
onNone: () => []
|
|
10930
11004
|
})
|
|
10931
11005
|
});
|
|
11006
|
+
const lockedDirs = new Set(members.map((member) => path.normalize(member)));
|
|
11007
|
+
const unlocked = claimed.filter((dir) => !lockedDirs.has(path.normalize(dir))).toSorted((a, b) => a.localeCompare(b));
|
|
11008
|
+
if (unlocked.length > 0) notices.push({ message: `not listed: ${unlocked.join(", ")} (not in ${lockfile})` });
|
|
10932
11009
|
const catalogLocked = /* @__PURE__ */ new Map();
|
|
10933
11010
|
for (const member of members.toSorted((a, b) => a.localeCompare(b))) {
|
|
10934
11011
|
const memberDir = member === "." ? "" : member;
|
|
@@ -10963,8 +11040,25 @@ const make$4 = (root, manager, place = "") => Effect.gen(function* () {
|
|
|
10963
11040
|
["catalogs", catalog],
|
|
10964
11041
|
entries
|
|
10965
11042
|
])];
|
|
11043
|
+
const overridden = /* @__PURE__ */ new Map();
|
|
11044
|
+
for (const [key, spec] of Object.entries(workspace.overrides ?? {})) {
|
|
11045
|
+
if (!spec.startsWith("catalog:")) continue;
|
|
11046
|
+
const name = overriddenName(key);
|
|
11047
|
+
const locked = pnpm.value.overrides?.[key];
|
|
11048
|
+
const selector = locked === void 0 ? void 0 : parseSelector(name, locked);
|
|
11049
|
+
if (selector === void 0 || exact(selector.range) === void 0) continue;
|
|
11050
|
+
const id = `${spec.slice(8) || "default"}:${name}`;
|
|
11051
|
+
const versions = overridden.get(id) ?? /* @__PURE__ */ new Set();
|
|
11052
|
+
versions.add(selector.artifact === name ? selector.range : `${selector.artifact}@${selector.range}`);
|
|
11053
|
+
overridden.set(id, versions);
|
|
11054
|
+
}
|
|
10966
11055
|
for (const [catalog, catalogPath, entries] of catalogs) for (const [name, spec] of Object.entries(entries)) {
|
|
10967
|
-
const
|
|
11056
|
+
const overrides = overridden.get(`${catalog}:${name}`);
|
|
11057
|
+
if (overrides !== void 0 && overrides.size > 1) {
|
|
11058
|
+
notices.push({ message: `${catalog} catalog entry ${name} has conflicting locked overrides; run pnpm install` });
|
|
11059
|
+
continue;
|
|
11060
|
+
}
|
|
11061
|
+
const resolved = catalogLocked.get(catalog)?.get(name) ?? overrides?.values().next().value;
|
|
10968
11062
|
if (resolved === void 0) continue;
|
|
10969
11063
|
add("pnpm-workspace.yaml", catalogPath.join("."), [...catalogPath, name], name, spec, resolved);
|
|
10970
11064
|
}
|
|
@@ -11001,53 +11095,20 @@ const make$4 = (root, manager, place = "") => Effect.gen(function* () {
|
|
|
11001
11095
|
notices
|
|
11002
11096
|
};
|
|
11003
11097
|
}).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
11004
|
-
const latest = Effect.gen(function* () {
|
|
11005
|
-
const workspaces = manager === "npm" && (yield* readJson(PackageJsonFields, path.join(root, "package.json"))).workspaces !== void 0;
|
|
11006
|
-
const outdated = run(manager === "pnpm" ? [
|
|
11007
|
-
"outdated",
|
|
11008
|
-
"-r",
|
|
11009
|
-
"--format",
|
|
11010
|
-
"json"
|
|
11011
|
-
] : [
|
|
11012
|
-
"outdated",
|
|
11013
|
-
"--json",
|
|
11014
|
-
...workspaces ? ["--workspaces", "--include-workspace-root"] : []
|
|
11015
|
-
]);
|
|
11016
|
-
const output = yield* exec.run(outdated);
|
|
11017
|
-
const reported = Schema.decodeOption(Schema.fromJsonString(NpmError))(output.stdout);
|
|
11018
|
-
if (output.exitCode !== 0 && (output.stdout.trim() === "" || Option.isSome(reported))) return yield* new CommandFailed({
|
|
11019
|
-
command: commandLine(outdated),
|
|
11020
|
-
cwd: root,
|
|
11021
|
-
exitCode: output.exitCode,
|
|
11022
|
-
output: Option.isSome(reported) ? reported.value.error.summary : output.stderr
|
|
11023
|
-
});
|
|
11024
|
-
const parsed = yield* decodeJson(Outdated, commandLine(outdated))(output.stdout || "{}");
|
|
11025
|
-
const targets = /* @__PURE__ */ new Map();
|
|
11026
|
-
for (const [key, entries] of Object.entries(parsed)) {
|
|
11027
|
-
const name = outdatedName(key);
|
|
11028
|
-
const newest = [entries].flat().find((entry) => entry.latest !== void 0)?.latest;
|
|
11029
|
-
if (newest !== void 0 && !targets.has(name)) targets.set(name, newest);
|
|
11030
|
-
}
|
|
11031
|
-
return targets;
|
|
11032
|
-
}).pipe(Effect.provideService(FileSystem.FileSystem, fs));
|
|
11033
11098
|
const list = Effect.gen(function* () {
|
|
11034
|
-
const [{ declared, notices },
|
|
11035
|
-
declarations,
|
|
11036
|
-
latest,
|
|
11037
|
-
readNpmConfig(manager, root).pipe(Effect.provideService(Exec, exec))
|
|
11038
|
-
], { concurrency: 3 });
|
|
11099
|
+
const [{ declared, notices }, config] = yield* Effect.all([declarations, readNpmConfig(manager, root).pipe(Effect.provideService(Exec, exec))], { concurrency: 2 });
|
|
11039
11100
|
const origin = withNpmOrigin(npmRegistries(config));
|
|
11040
|
-
const
|
|
11101
|
+
const { offer, notices: unread } = yield* releaseOffers(declared.flatMap((entry) => entry.held === true ? [] : [entry.pkg]), manager, run, config).pipe(Effect.provideService(Exec, exec));
|
|
11041
11102
|
return {
|
|
11042
11103
|
packages: declared.map((entry) => {
|
|
11043
11104
|
const pkg = origin(entry.pkg);
|
|
11044
11105
|
if (entry.held === true) return pkg;
|
|
11045
|
-
const line =
|
|
11046
|
-
if (
|
|
11106
|
+
const line = offer(entry.pkg);
|
|
11107
|
+
if (Result.isFailure(line)) notices.push({
|
|
11047
11108
|
rowKey: rowKey(pkg),
|
|
11048
11109
|
message: line.failure
|
|
11049
11110
|
});
|
|
11050
|
-
const target =
|
|
11111
|
+
const target = Result.getOrUndefined(line);
|
|
11051
11112
|
if (target === void 0 || !isNewerStable(pkg.current, target)) return pkg;
|
|
11052
11113
|
const selector = parseSelector(pkg.name, pkg.declaration?.selector ?? "");
|
|
11053
11114
|
if (selector === void 0 || moveTo(selector, target) === void 0) {
|
|
@@ -11059,7 +11120,7 @@ const make$4 = (root, manager, place = "") => Effect.gen(function* () {
|
|
|
11059
11120
|
}
|
|
11060
11121
|
return withTarget(pkg, target);
|
|
11061
11122
|
}),
|
|
11062
|
-
notices
|
|
11123
|
+
notices: [...unread, ...notices]
|
|
11063
11124
|
};
|
|
11064
11125
|
}).pipe(Effect.withSpan(`NodeProject.list`));
|
|
11065
11126
|
const find = (pkg) => declarations.pipe(Effect.map(({ declared }) => declared.find((entry) => entry.pkg.id === pkg.id)));
|
|
@@ -11230,7 +11291,7 @@ const discover = Effect.fn("NodeProject.discover")(function* (dir, nested = [])
|
|
|
11230
11291
|
const { found, failed } = yield* locateAll(dir, nested, "package.json", locate);
|
|
11231
11292
|
const providers = [...failed];
|
|
11232
11293
|
const unlisted = [];
|
|
11233
|
-
for (const { root, manager } of found) {
|
|
11294
|
+
for (const { root, manager, claimed } of found) {
|
|
11234
11295
|
const place = placeOf$1(dir, root);
|
|
11235
11296
|
if (!isManager(manager)) {
|
|
11236
11297
|
if (place === "") providers.push(failing(manager, new Unsupported({ reason: `${path.relative(dir, root) || "This"} project uses ${manager}, which upup does not support` })));
|
|
@@ -11240,11 +11301,144 @@ const discover = Effect.fn("NodeProject.discover")(function* (dir, nested = [])
|
|
|
11240
11301
|
const lockfile = path.join(root, lockfiles[manager]);
|
|
11241
11302
|
const installed = yield* fs.exists(lockfile).pipe(Effect.mapError(fileFailed("stat", lockfile)));
|
|
11242
11303
|
if (place !== "" && !installed) unlisted.push(`${place} (no ${lockfiles[manager]} yet)`);
|
|
11243
|
-
else
|
|
11304
|
+
else {
|
|
11305
|
+
const manifests = yield* Effect.filter(claimed, (from) => fs.exists(path.join(from, "package.json")).pipe(Effect.mapError(fileFailed("stat", from))));
|
|
11306
|
+
providers.push(yield* make$5(root, manager, place, manifests.map((from) => path.relative(root, from))));
|
|
11307
|
+
}
|
|
11244
11308
|
}
|
|
11245
11309
|
if (unlisted.length > 0) providers.push(notListed(unlisted));
|
|
11246
11310
|
return providers;
|
|
11247
11311
|
});
|
|
11312
|
+
// src/node/VpEnv.ts
|
|
11313
|
+
const vp$1 = (args) => ({
|
|
11314
|
+
command: "vp",
|
|
11315
|
+
args: ["env", ...args],
|
|
11316
|
+
cwd: "/"
|
|
11317
|
+
});
|
|
11318
|
+
const defaults = vp$1(["default"]);
|
|
11319
|
+
const tools$1 = /* @__PURE__ */ new Set([
|
|
11320
|
+
"node",
|
|
11321
|
+
"npm",
|
|
11322
|
+
"pnpm",
|
|
11323
|
+
"yarn",
|
|
11324
|
+
"bun"
|
|
11325
|
+
]);
|
|
11326
|
+
const Release$1 = Schema.Struct({
|
|
11327
|
+
version: Schema.String,
|
|
11328
|
+
latest: Schema.Boolean
|
|
11329
|
+
});
|
|
11330
|
+
const NodeReleases = Schema.Struct({ node: Schema.Array(Release$1) });
|
|
11331
|
+
const ManagerReleases = Schema.Struct({ package_managers: Schema.Record(Schema.String, Schema.Array(Release$1)) });
|
|
11332
|
+
const malformed$1 = (command, issue) => new OutputMalformed({
|
|
11333
|
+
command: commandLine(command),
|
|
11334
|
+
issue
|
|
11335
|
+
});
|
|
11336
|
+
const readDefaults = Effect.fn("VpEnv.readDefaults")(function* (output) {
|
|
11337
|
+
const entries = [];
|
|
11338
|
+
const notices = [];
|
|
11339
|
+
let recognized = false;
|
|
11340
|
+
for (const line of output.split("\n").map((text) => text.trim())) {
|
|
11341
|
+
if (line.startsWith("No default Node.js version configured.") || line === "Package manager defaults: not configured") recognized = true;
|
|
11342
|
+
if (!line.startsWith("Default ")) continue;
|
|
11343
|
+
const fields = /^Default (?<name>.+) version: (?<selector>\S+)$/u.exec(line)?.groups;
|
|
11344
|
+
const label = fields?.["name"];
|
|
11345
|
+
const selector = fields?.["selector"];
|
|
11346
|
+
if (label === void 0 || selector === void 0) return yield* malformed$1(defaults, `unrecognized default: ${line}`);
|
|
11347
|
+
recognized = true;
|
|
11348
|
+
const name = label === "Node.js" ? "node" : label;
|
|
11349
|
+
if (tools$1.has(name)) entries.push({
|
|
11350
|
+
name,
|
|
11351
|
+
selector
|
|
11352
|
+
});
|
|
11353
|
+
else notices.push({ message: `Vite+ default ${name} is not supported` });
|
|
11354
|
+
}
|
|
11355
|
+
if (!recognized) return yield* malformed$1(defaults, "no global defaults found");
|
|
11356
|
+
if (entries.length === 0) return {
|
|
11357
|
+
packages: [],
|
|
11358
|
+
notices
|
|
11359
|
+
};
|
|
11360
|
+
const manifest = /^\s+Set via: (?<path>.+)$/mu.exec(output)?.groups?.["path"];
|
|
11361
|
+
if (manifest === void 0) return yield* malformed$1(defaults, "no configuration path found");
|
|
11362
|
+
return {
|
|
11363
|
+
packages: entries.map(({ name, selector }) => {
|
|
11364
|
+
const version = semver.parse(selector);
|
|
11365
|
+
return {
|
|
11366
|
+
provider: "vp-env",
|
|
11367
|
+
id: name,
|
|
11368
|
+
name,
|
|
11369
|
+
ecosystem: name === "node" ? "node" : "npm",
|
|
11370
|
+
artifact: name === "yarn" && version !== null && version.major >= 2 ? "@yarnpkg/cli-dist" : name,
|
|
11371
|
+
current: version?.version ?? selector,
|
|
11372
|
+
declaration: {
|
|
11373
|
+
manifest,
|
|
11374
|
+
section: `${name} default`,
|
|
11375
|
+
selector
|
|
11376
|
+
},
|
|
11377
|
+
description: version === null ? `Managed automatically by Vite+ (${selector})` : "Vite+ global default",
|
|
11378
|
+
unremovable: "Vite+ defaults are cleared with vp env default --unset"
|
|
11379
|
+
};
|
|
11380
|
+
}),
|
|
11381
|
+
notices
|
|
11382
|
+
};
|
|
11383
|
+
});
|
|
11384
|
+
const make$4 = Effect.gen(function* () {
|
|
11385
|
+
const exec = yield* Exec;
|
|
11386
|
+
const configured = exec.stdout(defaults).pipe(Effect.flatMap(readDefaults));
|
|
11387
|
+
const offer = Effect.fn("VpEnv.offer")(function* (pkg) {
|
|
11388
|
+
const current = semver.parse(pkg.current);
|
|
11389
|
+
if (current === null) return;
|
|
11390
|
+
const withinMajor = pkg.id === "node" || pkg.id === "yarn" && current.major === 1;
|
|
11391
|
+
const command = vp$1([
|
|
11392
|
+
"list-remote",
|
|
11393
|
+
pkg.id,
|
|
11394
|
+
...withinMajor ? [String(current.major)] : [],
|
|
11395
|
+
"--json"
|
|
11396
|
+
]);
|
|
11397
|
+
const output = yield* exec.stdout(command);
|
|
11398
|
+
const releases = pkg.id === "node" ? (yield* decodeJson(NodeReleases, commandLine(command))(output)).node : (yield* decodeJson(ManagerReleases, commandLine(command))(output)).package_managers[pkg.id];
|
|
11399
|
+
if (releases === void 0 || releases.length === 0) return yield* malformed$1(command, `no releases found for ${pkg.name}`);
|
|
11400
|
+
return newestOffer(pkg.current, releases.filter(({ version, latest }) => (withinMajor || latest) && semver.prerelease(version) === null).map(({ version }) => version));
|
|
11401
|
+
});
|
|
11402
|
+
const list = Effect.gen(function* () {
|
|
11403
|
+
const found = yield* configured;
|
|
11404
|
+
const notices = [...found.notices];
|
|
11405
|
+
return {
|
|
11406
|
+
packages: yield* Effect.forEach(found.packages, (pkg) => Effect.gen(function* () {
|
|
11407
|
+
const target = yield* Effect.result(offer(pkg));
|
|
11408
|
+
if (Result.isFailure(target)) {
|
|
11409
|
+
notices.push({
|
|
11410
|
+
rowKey: rowKey(pkg),
|
|
11411
|
+
message: describeError(target.failure)
|
|
11412
|
+
});
|
|
11413
|
+
return pkg;
|
|
11414
|
+
}
|
|
11415
|
+
return target.success === void 0 ? pkg : withTarget(pkg, target.success);
|
|
11416
|
+
})),
|
|
11417
|
+
notices
|
|
11418
|
+
};
|
|
11419
|
+
}).pipe(Effect.withSpan("VpEnv.list"));
|
|
11420
|
+
const observe = Effect.fn("VpEnv.observe")(function* (pkg) {
|
|
11421
|
+
return Option.fromUndefinedOr((yield* configured).packages.find((candidate) => candidate.id === pkg.id));
|
|
11422
|
+
});
|
|
11423
|
+
const unchanged = Effect.fn("VpEnv.unchanged")(function* (pkg) {
|
|
11424
|
+
const current = yield* observe(pkg);
|
|
11425
|
+
if (Option.isNone(current) || current.value.current !== pkg.current || current.value.declaration?.selector !== pkg.declaration?.selector) return yield* new InstallRefused({
|
|
11426
|
+
package: pkg.name,
|
|
11427
|
+
reason: "the Vite+ default changed; refresh before updating"
|
|
11428
|
+
});
|
|
11429
|
+
});
|
|
11430
|
+
return {
|
|
11431
|
+
name: "vp-env",
|
|
11432
|
+
mode: "system",
|
|
11433
|
+
list,
|
|
11434
|
+
observe,
|
|
11435
|
+
update: Effect.fn("VpEnv.update")(function* (pkg, target) {
|
|
11436
|
+
yield* exec.stdout(vp$1(["install", `${pkg.id}@${target}`]));
|
|
11437
|
+
yield* unchanged(pkg);
|
|
11438
|
+
yield* exec.stdout(vp$1(["default", `${pkg.id}@${target}`]));
|
|
11439
|
+
})
|
|
11440
|
+
};
|
|
11441
|
+
});
|
|
11248
11442
|
// src/node/VpSelf.ts
|
|
11249
11443
|
const vp = (args) => ({
|
|
11250
11444
|
command: "vp",
|
|
@@ -11272,6 +11466,10 @@ const make$3 = Effect.gen(function* () {
|
|
|
11272
11466
|
mode: "system",
|
|
11273
11467
|
list: Effect.gen(function* () {
|
|
11274
11468
|
const output = yield* exec.stdout(check$1);
|
|
11469
|
+
if (output.includes("Homebrew manages this installation.")) return {
|
|
11470
|
+
packages: [],
|
|
11471
|
+
notices: []
|
|
11472
|
+
};
|
|
11275
11473
|
const { latest, current } = /found vite-plus@(?<latest>\S+) \(current: (?<current>\S+)\)/u.exec(output)?.groups ?? {};
|
|
11276
11474
|
if (latest === void 0 || current === void 0) return yield* malformed(check$1);
|
|
11277
11475
|
const pkg = vitePlus(current);
|
|
@@ -11615,14 +11813,15 @@ const make = Effect.gen(function* () {
|
|
|
11615
11813
|
const system$1 = [
|
|
11616
11814
|
["softwareupdate", make$1],
|
|
11617
11815
|
["apt-get", make$2],
|
|
11618
|
-
["brew", make$
|
|
11619
|
-
["codesign", make$
|
|
11816
|
+
["brew", make$14],
|
|
11817
|
+
["codesign", make$11],
|
|
11620
11818
|
["npm", makeNpm],
|
|
11621
11819
|
["pnpm", makePnpm],
|
|
11622
11820
|
["vp", makeVp],
|
|
11623
11821
|
["vp", make$3],
|
|
11624
|
-
["
|
|
11625
|
-
["
|
|
11822
|
+
["vp", make$4],
|
|
11823
|
+
["cargo", make$10],
|
|
11824
|
+
["go", make$8],
|
|
11626
11825
|
["uv", make]
|
|
11627
11826
|
];
|
|
11628
11827
|
const available = (entries) => Effect.filter([...new Set(entries.map(([command]) => command))], onPath).pipe(Effect.map((found) => entries.filter(([command]) => found.includes(command))));
|
|
@@ -12491,18 +12690,17 @@ const runProvider = Effect.fn("Engine.runProvider")(function* (provider, targets
|
|
|
12491
12690
|
key: rowKey(target.pkg),
|
|
12492
12691
|
outcome
|
|
12493
12692
|
}))));
|
|
12494
|
-
const
|
|
12693
|
+
const applied = [];
|
|
12495
12694
|
for (const target of targets) {
|
|
12496
12695
|
if (yield* stopped) {
|
|
12497
12696
|
yield* finish(target, Outcome.NotStarted());
|
|
12498
12697
|
continue;
|
|
12499
12698
|
}
|
|
12500
|
-
const
|
|
12501
|
-
if (Result.isFailure(
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
for (const [target, attempt] of checked) {
|
|
12699
|
+
const checked = yield* check(target, emit);
|
|
12700
|
+
if (Result.isFailure(checked)) {
|
|
12701
|
+
yield* finish(target, checked.failure);
|
|
12702
|
+
continue;
|
|
12703
|
+
}
|
|
12506
12704
|
if (yield* stopped) {
|
|
12507
12705
|
yield* finish(target, Outcome.NotStarted());
|
|
12508
12706
|
continue;
|
|
@@ -12511,7 +12709,7 @@ const runProvider = Effect.fn("Engine.runProvider")(function* (provider, targets
|
|
|
12511
12709
|
key: rowKey(target.pkg),
|
|
12512
12710
|
phase: "applying"
|
|
12513
12711
|
}));
|
|
12514
|
-
const result = yield* Effect.result(withDecisions(
|
|
12712
|
+
const result = yield* Effect.result(withDecisions(checked.success));
|
|
12515
12713
|
if (Result.isFailure(result)) yield* finish(target, failedAs(result.failure, false));
|
|
12516
12714
|
else if (provider.reconcile === void 0) yield* finish(target, yield* verify(target, emit));
|
|
12517
12715
|
else applied.push(target);
|
|
@@ -12656,15 +12854,236 @@ const updateTools = (home) => Action.implement(UpdateActions, Effect.gen(functio
|
|
|
12656
12854
|
}));
|
|
12657
12855
|
// src/mcp.ts
|
|
12658
12856
|
const instructions = "upup reads the tools installed on this machine and the registry dependencies of a project, audits offered updates with the user's chosen model, and applies or removes them. Start with list_packages; every other tool takes its package keys. Before updating, look at package_changes or run audit_packages and poll audit_reports until no Audit is running; operating-system updates (ecosystem macos or apt) can't be audited and have no changes to read; app updates (ecosystem sparkle, electron, appstore or app) can't be audited either, and package_changes gives their release notes when the app's feed has any; ask the user to quit an open app before updating it; the Node.js versions a project pins (ecosystem node) can't be audited either and are edited in place. update_packages and remove_packages change the user's machine or project and cannot be undone by upup: confirm them with the user, and ask before passing allowScripts.";
|
|
12659
|
-
const
|
|
12857
|
+
const tools = (home) => [
|
|
12660
12858
|
inventoryTools(home),
|
|
12661
12859
|
auditTools(home),
|
|
12662
12860
|
updateTools(home)
|
|
12663
|
-
]
|
|
12861
|
+
];
|
|
12862
|
+
const serverInfo = {
|
|
12664
12863
|
name: "upup",
|
|
12665
12864
|
version: version$1,
|
|
12666
12865
|
instructions
|
|
12866
|
+
};
|
|
12867
|
+
const serve = (home) => ActionMcp.runStdio(tools(home), serverInfo);
|
|
12868
|
+
// src/session/operation.ts
|
|
12869
|
+
const machine$1 = setup({
|
|
12870
|
+
schemas: { events: {
|
|
12871
|
+
Run: types(),
|
|
12872
|
+
Stop: types(),
|
|
12873
|
+
Ask: types(),
|
|
12874
|
+
Answer: types(),
|
|
12875
|
+
Finish: types()
|
|
12876
|
+
} },
|
|
12877
|
+
states: {
|
|
12878
|
+
Idle: { schemas: { context: types() } },
|
|
12879
|
+
Running: { schemas: { context: types() } },
|
|
12880
|
+
Asking: { schemas: { context: types() } }
|
|
12881
|
+
}
|
|
12882
|
+
}).createFSM({
|
|
12883
|
+
initial: "Idle",
|
|
12884
|
+
context: {
|
|
12885
|
+
stopping: false,
|
|
12886
|
+
decision: void 0
|
|
12887
|
+
},
|
|
12888
|
+
states: {
|
|
12889
|
+
Idle: { on: { Run: { target: "Running" } } },
|
|
12890
|
+
Running: { on: {
|
|
12891
|
+
Stop: { context: { stopping: true } },
|
|
12892
|
+
Ask: ({ event }) => ({
|
|
12893
|
+
target: "Asking",
|
|
12894
|
+
context: { decision: event.decision }
|
|
12895
|
+
}),
|
|
12896
|
+
Finish: {
|
|
12897
|
+
target: "Idle",
|
|
12898
|
+
context: { stopping: false }
|
|
12899
|
+
}
|
|
12900
|
+
} },
|
|
12901
|
+
Asking: { on: {
|
|
12902
|
+
Stop: { context: { stopping: true } },
|
|
12903
|
+
Answer: {
|
|
12904
|
+
target: "Running",
|
|
12905
|
+
context: { decision: void 0 }
|
|
12906
|
+
},
|
|
12907
|
+
Finish: {
|
|
12908
|
+
target: "Idle",
|
|
12909
|
+
context: {
|
|
12910
|
+
stopping: false,
|
|
12911
|
+
decision: void 0
|
|
12912
|
+
}
|
|
12913
|
+
}
|
|
12914
|
+
} }
|
|
12915
|
+
}
|
|
12916
|
+
});
|
|
12917
|
+
const step$1 = (snapshot, event) => {
|
|
12918
|
+
const [next] = machine$1.transition(snapshot, event);
|
|
12919
|
+
return [next, next !== snapshot];
|
|
12920
|
+
};
|
|
12921
|
+
// src/session/sign-in.ts
|
|
12922
|
+
const machine = setup({
|
|
12923
|
+
schemas: { events: {
|
|
12924
|
+
SaveKey: types(),
|
|
12925
|
+
Start: types(),
|
|
12926
|
+
Noticed: types(),
|
|
12927
|
+
Prompt: types(),
|
|
12928
|
+
Answer: types(),
|
|
12929
|
+
Succeed: types(),
|
|
12930
|
+
Fail: types(),
|
|
12931
|
+
Close: types()
|
|
12932
|
+
} },
|
|
12933
|
+
states: {
|
|
12934
|
+
Idle: { schemas: { context: types() } },
|
|
12935
|
+
SavingKey: { schemas: { context: types() } },
|
|
12936
|
+
Working: { schemas: { context: types() } },
|
|
12937
|
+
Prompted: { schemas: { context: types() } },
|
|
12938
|
+
Failed: { schemas: { context: types() } },
|
|
12939
|
+
SignedIn: { schemas: { context: types() } }
|
|
12940
|
+
}
|
|
12941
|
+
}).createFSM({
|
|
12942
|
+
initial: "Idle",
|
|
12943
|
+
context: {
|
|
12944
|
+
attempt: 0,
|
|
12945
|
+
provider: void 0,
|
|
12946
|
+
notices: void 0,
|
|
12947
|
+
prompt: void 0,
|
|
12948
|
+
issue: void 0
|
|
12949
|
+
},
|
|
12950
|
+
states: {
|
|
12951
|
+
Idle: { on: {
|
|
12952
|
+
SaveKey: ({ context, event }) => ({
|
|
12953
|
+
target: "SavingKey",
|
|
12954
|
+
context: {
|
|
12955
|
+
attempt: context.attempt + 1,
|
|
12956
|
+
provider: event.provider
|
|
12957
|
+
}
|
|
12958
|
+
}),
|
|
12959
|
+
Start: ({ context, event }) => ({
|
|
12960
|
+
target: "Working",
|
|
12961
|
+
context: {
|
|
12962
|
+
attempt: context.attempt + 1,
|
|
12963
|
+
provider: event.provider,
|
|
12964
|
+
notices: []
|
|
12965
|
+
}
|
|
12966
|
+
})
|
|
12967
|
+
} },
|
|
12968
|
+
SavingKey: { on: {
|
|
12969
|
+
Succeed: ({ context, event }) => event.attempt === context.attempt ? { target: "SignedIn" } : void 0,
|
|
12970
|
+
Fail: ({ context, event }) => event.attempt === context.attempt ? {
|
|
12971
|
+
target: "Failed",
|
|
12972
|
+
context: { issue: event.issue }
|
|
12973
|
+
} : void 0,
|
|
12974
|
+
Close: {
|
|
12975
|
+
target: "Idle",
|
|
12976
|
+
context: { provider: void 0 }
|
|
12977
|
+
}
|
|
12978
|
+
} },
|
|
12979
|
+
Working: { on: {
|
|
12980
|
+
Noticed: ({ context, event }) => event.attempt === context.attempt ? { context: { notices: [...context.notices, event.notice] } } : void 0,
|
|
12981
|
+
Prompt: ({ context, event }) => event.attempt === context.attempt ? {
|
|
12982
|
+
target: "Prompted",
|
|
12983
|
+
context: { prompt: event.prompt }
|
|
12984
|
+
} : void 0,
|
|
12985
|
+
Succeed: ({ context, event }) => event.attempt === context.attempt ? {
|
|
12986
|
+
target: "SignedIn",
|
|
12987
|
+
context: { notices: void 0 }
|
|
12988
|
+
} : void 0,
|
|
12989
|
+
Fail: ({ context, event }) => event.attempt === context.attempt ? {
|
|
12990
|
+
target: "Failed",
|
|
12991
|
+
context: {
|
|
12992
|
+
notices: void 0,
|
|
12993
|
+
issue: event.issue
|
|
12994
|
+
}
|
|
12995
|
+
} : void 0,
|
|
12996
|
+
Close: {
|
|
12997
|
+
target: "Idle",
|
|
12998
|
+
context: {
|
|
12999
|
+
provider: void 0,
|
|
13000
|
+
notices: void 0
|
|
13001
|
+
}
|
|
13002
|
+
}
|
|
13003
|
+
} },
|
|
13004
|
+
Prompted: { on: {
|
|
13005
|
+
Noticed: ({ context, event }) => event.attempt === context.attempt ? { context: { notices: [...context.notices, event.notice] } } : void 0,
|
|
13006
|
+
Answer: ({ context, event }) => event.attempt === context.attempt ? {
|
|
13007
|
+
target: "Working",
|
|
13008
|
+
context: { prompt: void 0 }
|
|
13009
|
+
} : void 0,
|
|
13010
|
+
Succeed: ({ context, event }) => event.attempt === context.attempt ? {
|
|
13011
|
+
target: "SignedIn",
|
|
13012
|
+
context: {
|
|
13013
|
+
notices: void 0,
|
|
13014
|
+
prompt: void 0
|
|
13015
|
+
}
|
|
13016
|
+
} : void 0,
|
|
13017
|
+
Fail: ({ context, event }) => event.attempt === context.attempt ? {
|
|
13018
|
+
target: "Failed",
|
|
13019
|
+
context: {
|
|
13020
|
+
notices: void 0,
|
|
13021
|
+
prompt: void 0,
|
|
13022
|
+
issue: event.issue
|
|
13023
|
+
}
|
|
13024
|
+
} : void 0,
|
|
13025
|
+
Close: {
|
|
13026
|
+
target: "Idle",
|
|
13027
|
+
context: {
|
|
13028
|
+
provider: void 0,
|
|
13029
|
+
notices: void 0,
|
|
13030
|
+
prompt: void 0
|
|
13031
|
+
}
|
|
13032
|
+
}
|
|
13033
|
+
} },
|
|
13034
|
+
Failed: { on: {
|
|
13035
|
+
SaveKey: ({ context, event }) => ({
|
|
13036
|
+
target: "SavingKey",
|
|
13037
|
+
context: {
|
|
13038
|
+
attempt: context.attempt + 1,
|
|
13039
|
+
provider: event.provider,
|
|
13040
|
+
issue: void 0
|
|
13041
|
+
}
|
|
13042
|
+
}),
|
|
13043
|
+
Start: ({ context, event }) => ({
|
|
13044
|
+
target: "Working",
|
|
13045
|
+
context: {
|
|
13046
|
+
attempt: context.attempt + 1,
|
|
13047
|
+
provider: event.provider,
|
|
13048
|
+
notices: [],
|
|
13049
|
+
issue: void 0
|
|
13050
|
+
}
|
|
13051
|
+
}),
|
|
13052
|
+
Close: {
|
|
13053
|
+
target: "Idle",
|
|
13054
|
+
context: {
|
|
13055
|
+
provider: void 0,
|
|
13056
|
+
issue: void 0
|
|
13057
|
+
}
|
|
13058
|
+
}
|
|
13059
|
+
} },
|
|
13060
|
+
SignedIn: { on: {
|
|
13061
|
+
SaveKey: ({ context, event }) => ({
|
|
13062
|
+
target: "SavingKey",
|
|
13063
|
+
context: {
|
|
13064
|
+
attempt: context.attempt + 1,
|
|
13065
|
+
provider: event.provider
|
|
13066
|
+
}
|
|
13067
|
+
}),
|
|
13068
|
+
Start: ({ context, event }) => ({
|
|
13069
|
+
target: "Working",
|
|
13070
|
+
context: {
|
|
13071
|
+
attempt: context.attempt + 1,
|
|
13072
|
+
provider: event.provider,
|
|
13073
|
+
notices: []
|
|
13074
|
+
}
|
|
13075
|
+
}),
|
|
13076
|
+
Close: {
|
|
13077
|
+
target: "Idle",
|
|
13078
|
+
context: { provider: void 0 }
|
|
13079
|
+
}
|
|
13080
|
+
} }
|
|
13081
|
+
}
|
|
12667
13082
|
});
|
|
13083
|
+
const step = (snapshot, event) => {
|
|
13084
|
+
const [next] = machine.transition(snapshot, event);
|
|
13085
|
+
return [next, next !== snapshot];
|
|
13086
|
+
};
|
|
12668
13087
|
// src/session/Session.ts
|
|
12669
13088
|
const aboutKey = (pkg) => `${rowKey(pkg)}@${pkg.current}..${pkg.target ?? ""}`;
|
|
12670
13089
|
const auditKey = (pkg, mode) => {
|
|
@@ -12677,13 +13096,14 @@ const questionOf = (state) => {
|
|
|
12677
13096
|
_tag: "Password",
|
|
12678
13097
|
request: state.password
|
|
12679
13098
|
};
|
|
12680
|
-
if (state.
|
|
13099
|
+
if (state.operation.value !== "Asking") return;
|
|
13100
|
+
const { decision } = state.operation.context;
|
|
13101
|
+
return decision._tag === "ScriptsBlocked" ? {
|
|
12681
13102
|
_tag: "Scripts",
|
|
12682
|
-
blocked:
|
|
12683
|
-
}
|
|
12684
|
-
if (state.decision?._tag === "AppRunning") return {
|
|
13103
|
+
blocked: decision
|
|
13104
|
+
} : {
|
|
12685
13105
|
_tag: "Quit",
|
|
12686
|
-
running:
|
|
13106
|
+
running: decision
|
|
12687
13107
|
};
|
|
12688
13108
|
};
|
|
12689
13109
|
const initial = (mode, scope, preferences, audits = {}, settingsIssue) => ({
|
|
@@ -12694,14 +13114,12 @@ const initial = (mode, scope, preferences, audits = {}, settingsIssue) => ({
|
|
|
12694
13114
|
discoveryError: void 0,
|
|
12695
13115
|
providers: [],
|
|
12696
13116
|
selected: [],
|
|
12697
|
-
|
|
12698
|
-
stopping: false,
|
|
13117
|
+
operation: machine$1.initialState,
|
|
12699
13118
|
activity: {},
|
|
12700
13119
|
outcomes: {},
|
|
12701
13120
|
actions: {},
|
|
12702
13121
|
installed: {},
|
|
12703
13122
|
removed: {},
|
|
12704
|
-
decision: void 0,
|
|
12705
13123
|
password: void 0,
|
|
12706
13124
|
about: {},
|
|
12707
13125
|
audits,
|
|
@@ -12711,7 +13129,7 @@ const initial = (mode, scope, preferences, audits = {}, settingsIssue) => ({
|
|
|
12711
13129
|
preferences,
|
|
12712
13130
|
settingsIssue,
|
|
12713
13131
|
catalogue: void 0,
|
|
12714
|
-
signIn:
|
|
13132
|
+
signIn: machine.initialState
|
|
12715
13133
|
});
|
|
12716
13134
|
const issueOf = (error) => `${error.file} cannot be read (${error.issue}); upup keeps audit first on and changes no settings until it is fixed or deleted`;
|
|
12717
13135
|
const without = (record, key) => Object.fromEntries(Object.entries(record).filter(([entry]) => entry !== key));
|
|
@@ -12822,9 +13240,15 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
12822
13240
|
const providers = yield* Ref.make([]);
|
|
12823
13241
|
const loading = yield* FiberHandle.make();
|
|
12824
13242
|
const operation = yield* FiberHandle.make();
|
|
12825
|
-
const stopRequested = yield* Ref.make(false);
|
|
12826
13243
|
const pendingDecision = yield* Ref.make(Option.none());
|
|
12827
13244
|
const update = (f) => SubscriptionRef.update(state, f);
|
|
13245
|
+
const send = (event) => SubscriptionRef.modify(state, (current) => {
|
|
13246
|
+
const [next, handled] = step$1(current.operation, event);
|
|
13247
|
+
return [handled, handled ? {
|
|
13248
|
+
...current,
|
|
13249
|
+
operation: next
|
|
13250
|
+
} : current];
|
|
13251
|
+
});
|
|
12828
13252
|
const setProvider = (name, f) => update((current) => ({
|
|
12829
13253
|
...current,
|
|
12830
13254
|
providers: current.providers.map((entry) => entry.name === name ? f(entry) : entry)
|
|
@@ -12995,11 +13419,12 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
12995
13419
|
return {
|
|
12996
13420
|
...initial(mode, scope, current.preferences, current.audits, current.settingsIssue),
|
|
12997
13421
|
...places.get(`${mode}:${scope}`),
|
|
12998
|
-
catalogue: current.catalogue
|
|
13422
|
+
catalogue: current.catalogue,
|
|
13423
|
+
signIn: current.signIn
|
|
12999
13424
|
};
|
|
13000
13425
|
});
|
|
13001
13426
|
const open = Effect.fn("Session.open")(function* (mode, scope) {
|
|
13002
|
-
if ((yield* SubscriptionRef.get(state)).
|
|
13427
|
+
if ((yield* SubscriptionRef.get(state)).operation.value !== "Idle") return;
|
|
13003
13428
|
yield* FiberHandle.clear(loading);
|
|
13004
13429
|
yield* reset(mode, scope);
|
|
13005
13430
|
yield* FiberHandle.run(loading, discover(mode, scope));
|
|
@@ -13016,7 +13441,7 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13016
13441
|
});
|
|
13017
13442
|
const refresh = Effect.gen(function* () {
|
|
13018
13443
|
const current = yield* SubscriptionRef.get(state);
|
|
13019
|
-
if (current.
|
|
13444
|
+
if (current.operation.value !== "Idle" || current.discovering) return;
|
|
13020
13445
|
yield* FiberHandle.run(loading, discover(current.mode, current.scope));
|
|
13021
13446
|
});
|
|
13022
13447
|
const toggle = Effect.fn("Session.toggle")(function* (key) {
|
|
@@ -13038,16 +13463,11 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13038
13463
|
const ask = (decision) => Effect.gen(function* () {
|
|
13039
13464
|
const answer = yield* Deferred.make();
|
|
13040
13465
|
yield* Ref.set(pendingDecision, Option.some(answer));
|
|
13041
|
-
yield*
|
|
13042
|
-
|
|
13466
|
+
yield* send({
|
|
13467
|
+
type: "Ask",
|
|
13043
13468
|
decision
|
|
13044
|
-
})
|
|
13045
|
-
|
|
13046
|
-
yield* update((current) => ({
|
|
13047
|
-
...current,
|
|
13048
|
-
decision: void 0
|
|
13049
|
-
}));
|
|
13050
|
-
return allowed;
|
|
13469
|
+
});
|
|
13470
|
+
return yield* Deferred.await(answer);
|
|
13051
13471
|
});
|
|
13052
13472
|
const decisions = Decisions.of({
|
|
13053
13473
|
asks: true,
|
|
@@ -13056,16 +13476,9 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13056
13476
|
});
|
|
13057
13477
|
const run = Effect.fn("Session.run")(function* (action, keys, accepted = []) {
|
|
13058
13478
|
const current = yield* SubscriptionRef.get(state);
|
|
13059
|
-
if (current.running) return;
|
|
13060
13479
|
const targets = targetsFor(current, yield* Ref.get(providers), action, keys);
|
|
13061
|
-
if (targets.length === 0) return;
|
|
13062
|
-
yield* Ref.set(stopRequested, false);
|
|
13480
|
+
if (targets.length === 0 || !(yield* send({ type: "Run" }))) return;
|
|
13063
13481
|
const vetting = action === "update" && current.preferences.auditFirst;
|
|
13064
|
-
yield* update((latest) => ({
|
|
13065
|
-
...latest,
|
|
13066
|
-
running: true,
|
|
13067
|
-
stopping: false
|
|
13068
|
-
}));
|
|
13069
13482
|
const touched = [...new Set(targets.map((target) => target.provider))];
|
|
13070
13483
|
const confirmed = targets.filter((target) => accepted.includes(rowKey(target.pkg)));
|
|
13071
13484
|
const chosen = vetting ? vet(targets.filter((target) => !accepted.includes(rowKey(target.pkg))), current.mode).pipe(Effect.flatMap(({ approved, refused }) => update((latest) => ({
|
|
@@ -13085,7 +13498,7 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13085
13498
|
...latest.activity,
|
|
13086
13499
|
...Object.fromEntries(approved.map((target) => [rowKey(target.pkg), "waiting"]))
|
|
13087
13500
|
}
|
|
13088
|
-
}))), Effect.flatMap((approved) => run$1(approved,
|
|
13501
|
+
}))), Effect.flatMap((approved) => run$1(approved, SubscriptionRef.get(state).pipe(Effect.map((latest) => latest.operation.context.stopping))).pipe(Stream.runForEach((event) => update((latest) => event._tag === "Progress" ? {
|
|
13089
13502
|
...latest,
|
|
13090
13503
|
activity: {
|
|
13091
13504
|
...latest.activity,
|
|
@@ -13107,21 +13520,14 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13107
13520
|
selected: event.outcome._tag === "Completed" ? latest.selected.filter((key) => key !== event.key) : latest.selected
|
|
13108
13521
|
})), Effect.provideService(Decisions, decisions), Effect.provideService(UpdateLog, scoped(updateLog, placeOf(current))), Effect.andThen(collect$2(touched)), Effect.andThen(recallAll))), Effect.ensuring(Ref.set(pendingDecision, Option.none()).pipe(Effect.andThen(update((latest) => ({
|
|
13109
13522
|
...latest,
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
activity: {},
|
|
13113
|
-
decision: void 0
|
|
13523
|
+
operation: step$1(latest.operation, { type: "Finish" })[0],
|
|
13524
|
+
activity: {}
|
|
13114
13525
|
})))))));
|
|
13115
13526
|
});
|
|
13116
13527
|
const answerPassword = (password) => sudo.answer(password);
|
|
13117
|
-
const stop = Effect.
|
|
13118
|
-
yield* Ref.set(stopRequested, true);
|
|
13119
|
-
yield* update((current) => current.running ? {
|
|
13120
|
-
...current,
|
|
13121
|
-
stopping: true
|
|
13122
|
-
} : current);
|
|
13123
|
-
});
|
|
13528
|
+
const stop = Effect.asVoid(send({ type: "Stop" }));
|
|
13124
13529
|
const answer = Effect.fn("Session.answer")(function* (allowed) {
|
|
13530
|
+
if (!(yield* send({ type: "Answer" }))) return;
|
|
13125
13531
|
const pending = yield* Ref.getAndSet(pendingDecision, Option.none());
|
|
13126
13532
|
if (Option.isSome(pending)) yield* Deferred.succeed(pending.value, allowed);
|
|
13127
13533
|
});
|
|
@@ -13178,73 +13584,86 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
|
|
|
13178
13584
|
...stored,
|
|
13179
13585
|
auditFirst: on
|
|
13180
13586
|
}));
|
|
13181
|
-
const
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13587
|
+
const sendSignIn = (event) => SubscriptionRef.modify(state, (current) => {
|
|
13588
|
+
const stepped = step(current.signIn, event);
|
|
13589
|
+
const [next, handled] = stepped;
|
|
13590
|
+
return [stepped, handled ? {
|
|
13591
|
+
...current,
|
|
13592
|
+
signIn: next
|
|
13593
|
+
} : current];
|
|
13594
|
+
});
|
|
13595
|
+
const takeAnswer = (taken) => Ref.modify(pendingAnswer, (pending) => Option.isSome(pending) && taken(pending.value.attempt) ? [pending, Option.none()] : [Option.none(), pending]);
|
|
13596
|
+
const finish = (attempt) => Effect.matchEffect({
|
|
13597
|
+
onSuccess: () => sendSignIn({
|
|
13598
|
+
type: "Succeed",
|
|
13599
|
+
attempt
|
|
13600
|
+
}).pipe(Effect.andThen(loadCatalogue)),
|
|
13601
|
+
onFailure: (error) => sendSignIn({
|
|
13602
|
+
type: "Fail",
|
|
13603
|
+
attempt,
|
|
13194
13604
|
issue: error.issue
|
|
13195
13605
|
})
|
|
13196
|
-
})
|
|
13606
|
+
});
|
|
13607
|
+
const saveKey = (provider, key) => Effect.gen(function* () {
|
|
13608
|
+
const [saving, handled] = yield* sendSignIn({
|
|
13609
|
+
type: "SaveKey",
|
|
13610
|
+
provider
|
|
13611
|
+
});
|
|
13612
|
+
if (handled) yield* ai.setApiKey(provider, key).pipe(finish(saving.context.attempt));
|
|
13613
|
+
});
|
|
13197
13614
|
const signIn = (provider) => Effect.gen(function* () {
|
|
13198
|
-
yield*
|
|
13199
|
-
|
|
13200
|
-
provider
|
|
13201
|
-
notices: []
|
|
13615
|
+
const [working, handled] = yield* sendSignIn({
|
|
13616
|
+
type: "Start",
|
|
13617
|
+
provider
|
|
13202
13618
|
});
|
|
13619
|
+
if (!handled) return;
|
|
13620
|
+
const { attempt } = working.context;
|
|
13203
13621
|
const context = yield* Effect.context();
|
|
13204
|
-
const working = (change) => update((current) => current.signIn?._tag === "Working" && current.signIn.provider === provider ? {
|
|
13205
|
-
...current,
|
|
13206
|
-
signIn: change(current.signIn)
|
|
13207
|
-
} : current);
|
|
13208
13622
|
yield* FiberHandle.run(signing, ai.login(provider, {
|
|
13209
13623
|
notify: (event) => {
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
}))
|
|
13624
|
+
Effect.runForkWith(context)(sendSignIn({
|
|
13625
|
+
type: "Noticed",
|
|
13626
|
+
attempt,
|
|
13627
|
+
notice: noticeOf(event)
|
|
13628
|
+
}));
|
|
13215
13629
|
},
|
|
13216
13630
|
prompt: async (prompt) => await Effect.runPromiseWith(context)(Effect.gen(function* () {
|
|
13217
13631
|
const reply = yield* Deferred.make();
|
|
13218
|
-
yield* Ref.
|
|
13219
|
-
|
|
13220
|
-
|
|
13632
|
+
const replaced = yield* Ref.modify(pendingAnswer, (pending) => Option.isSome(pending) && pending.value.attempt >= attempt ? [void 0, pending] : [pending, Option.some({
|
|
13633
|
+
attempt,
|
|
13634
|
+
reply
|
|
13635
|
+
})]);
|
|
13636
|
+
if (replaced === void 0) return yield* Effect.interrupt;
|
|
13637
|
+
if (Option.isSome(replaced)) yield* Deferred.interrupt(replaced.value.reply);
|
|
13638
|
+
const [, asked] = yield* sendSignIn({
|
|
13639
|
+
type: "Prompt",
|
|
13640
|
+
attempt,
|
|
13221
13641
|
prompt
|
|
13222
|
-
})
|
|
13642
|
+
});
|
|
13643
|
+
if (!asked) {
|
|
13644
|
+
yield* takeAnswer((stored) => stored === attempt);
|
|
13645
|
+
return yield* Effect.interrupt;
|
|
13646
|
+
}
|
|
13223
13647
|
return yield* Deferred.await(reply);
|
|
13224
13648
|
}))
|
|
13225
|
-
}).pipe(
|
|
13226
|
-
onSuccess: () => setSignIn(void 0).pipe(Effect.andThen(loadCatalogue)),
|
|
13227
|
-
onFailure: (error) => setSignIn({
|
|
13228
|
-
_tag: "Failed",
|
|
13229
|
-
provider,
|
|
13230
|
-
issue: error.issue
|
|
13231
|
-
})
|
|
13232
|
-
})));
|
|
13649
|
+
}).pipe(finish(attempt)));
|
|
13233
13650
|
});
|
|
13234
13651
|
const answerSignIn = (reply) => Effect.gen(function* () {
|
|
13235
|
-
const
|
|
13236
|
-
|
|
13237
|
-
|
|
13238
|
-
|
|
13239
|
-
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
|
|
13243
|
-
|
|
13244
|
-
|
|
13245
|
-
yield*
|
|
13652
|
+
const { attempt } = (yield* SubscriptionRef.get(state)).signIn.context;
|
|
13653
|
+
const [, handled] = yield* sendSignIn({
|
|
13654
|
+
type: "Answer",
|
|
13655
|
+
attempt
|
|
13656
|
+
});
|
|
13657
|
+
if (!handled) return;
|
|
13658
|
+
const pending = yield* takeAnswer((stored) => stored === attempt);
|
|
13659
|
+
if (Option.isSome(pending)) yield* Deferred.succeed(pending.value.reply, reply);
|
|
13660
|
+
});
|
|
13661
|
+
const closeSignIn = Effect.gen(function* () {
|
|
13662
|
+
const [closed] = yield* sendSignIn({ type: "Close" });
|
|
13663
|
+
yield* FiberHandle.clear(signing);
|
|
13664
|
+
const pending = yield* takeAnswer((stored) => stored <= closed.context.attempt);
|
|
13665
|
+
if (Option.isSome(pending)) yield* Deferred.interrupt(pending.value.reply);
|
|
13246
13666
|
});
|
|
13247
|
-
const closeSignIn = FiberHandle.clear(signing).pipe(Effect.andThen(Ref.set(pendingAnswer, Option.none())), Effect.andThen(setSignIn(void 0)));
|
|
13248
13667
|
const awaitIdle = FiberHandle.awaitEmpty(operation);
|
|
13249
13668
|
return Session.of({
|
|
13250
13669
|
changes: SubscriptionRef.changes(state),
|
|
@@ -13284,7 +13703,7 @@ const silenceNodeWarningsWhileTuiDraws = () => {
|
|
|
13284
13703
|
};
|
|
13285
13704
|
const loadTui = Effect.suspend(() => {
|
|
13286
13705
|
silenceNodeWarningsWhileTuiDraws();
|
|
13287
|
-
return process.getBuiltinModule("node:ffi") === void 0 ? Effect.die(`upup's TUI needs Node 26.
|
|
13706
|
+
return process.getBuiltinModule("node:ffi") === void 0 ? Effect.die(`upup's TUI needs Node 26.13 or newer; this is Node ${process.versions.node}`) : Effect.promise(async () => await import("./Tui-DV_6wbrQ.mjs"));
|
|
13288
13707
|
});
|
|
13289
13708
|
const open$1 = (begin, projectDir) => Effect.gen(function* () {
|
|
13290
13709
|
const { launch } = yield* loadTui;
|