import { expect, it } from "@effect/vitest";import * as NodeServices from "@effect/platform-node/NodeServices";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Path from "effect/Path";import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"; import * as ProcessRunner from "../processRunner.ts";import { ensureDeviceHub, isDeviceHubInstalled } from "./DeviceToolchain.ts"; it.effect("failed installation cleans staging and exposes only a safe failure message", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-device-install-" }); const result = { code: ChildProcessSpawner.ExitCode(1), stdout: "", stderr: "registry rejected https://private:credential@example.test/package", timedOut: false, stdoutTruncated: false, stderrTruncated: false, stdoutInvalidUtf8: false, stderrInvalidUtf8: false, }; const error = yield* ensureDeviceHub(baseDir).pipe( Effect.provideService(ProcessRunner.ProcessRunner, { run: () => Effect.succeed(result), }), Effect.flip, ); expect(error.message).toBe( "Installing expo-device-hub failed while running npm install (exit code 1).", ); expect(error.cause).toBe(result); expect(yield* isDeviceHubInstalled(baseDir)).toBe(false); expect(yield* fs.readDirectory(path.join(baseDir, "tools", "expo-device-hub"))).toEqual([]); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),);
import { expect, it } from "@effect/vitest";
import * as NodeServices from "@effect/platform-node/NodeServices";
import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Path from "effect/Path";
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
import * as ProcessRunner from "../processRunner.ts";
import { ensureDeviceHub, isDeviceHubInstalled } from "./DeviceToolchain.ts";
it.effect("failed installation cleans staging and exposes only a safe failure message", () =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-device-install-" });
const result = {
code: ChildProcessSpawner.ExitCode(1),
stdout: "",
stderr: "registry rejected https://private:credential@example.test/package",
timedOut: false,
stdoutTruncated: false,
stderrTruncated: false,
stdoutInvalidUtf8: false,
stderrInvalidUtf8: false,
};
const error = yield* ensureDeviceHub(baseDir).pipe(
Effect.provideService(ProcessRunner.ProcessRunner, {
run: () => Effect.succeed(result),
}),
Effect.flip,
);
expect(error.message).toBe(
"Installing expo-device-hub failed while running npm install (exit code 1).",
);
expect(error.cause).toBe(result);
expect(yield* isDeviceHubInstalled(baseDir)).toBe(false);
expect(yield* fs.readDirectory(path.join(baseDir, "tools", "expo-device-hub"))).toEqual([]);
}).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
);