import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, describe, it } from "@effect/vitest";import * as Effect from "effect/Effect";import * as FileSystem from "effect/FileSystem";import * as Layer from "effect/Layer";import * as Logger from "effect/Logger";import * as ManagedRuntime from "effect/ManagedRuntime";import * as Option from "effect/Option";import * as Path from "effect/Path";import * as PlatformError from "effect/PlatformError";import * as Schema from "effect/Schema";import { ChildProcessSpawner } from "effect/unstable/process"; import * as DesktopEnvironment from "../app/DesktopEnvironment.ts";import * as DesktopBackendConfiguration from "./DesktopBackendConfiguration.ts";import * as DesktopConfig from "../app/DesktopConfig.ts";import * as DesktopServerExposure from "./DesktopServerExposure.ts";import * as DesktopAppSettings from "../settings/DesktopAppSettings.ts";import * as DesktopWslEnvironment from "../wsl/DesktopWslEnvironment.ts";import * as DesktopWslServerTree from "../wsl/DesktopWslServerTree.ts"; const PersistedServerObservabilitySettingsDocument = Schema.Struct({ observability: Schema.Struct({ otlpTracesUrl: Schema.String, otlpMetricsUrl: Schema.String, }),}); const encodePersistedServerObservabilitySettingsDocument = Schema.encodeEffect( Schema.fromJsonString(PersistedServerObservabilitySettingsDocument),); const isDesktopBackendObservabilitySettingsReadError = Schema.is( DesktopBackendConfiguration.DesktopBackendObservabilitySettingsReadError,); const serverExposureLayer = Layer.succeed(DesktopServerExposure.DesktopServerExposure, { getState: Effect.die("unexpected getState"), backendConfig: Effect.succeed({ port: 4888, bindHost: "0.0.0.0", httpBaseUrl: new URL("http://127.0.0.1:4888"), tailscaleServeEnabled: true, tailscaleServePort: 8443, }), configureFromSettings: () => Effect.die("unexpected configureFromSettings"), setMode: () => Effect.die("unexpected setMode"), setTailscaleServeEnabled: () => Effect.die("unexpected setTailscaleServeEnabled"), getAdvertisedEndpoints: Effect.succeed([]),} satisfies DesktopServerExposure.DesktopServerExposure["Service"]); function makeEnvironmentLayer( baseDir: string, options?: { readonly appPath?: string; readonly dirname?: string; readonly isPackaged?: boolean; readonly devServerUrl?: string; readonly platform?: NodeJS.Platform; readonly resourcesPath?: string; readonly appVersion?: string; readonly processArch?: NodeJS.Architecture; },) { return DesktopEnvironment.layer({ dirname: options?.dirname ?? "/repo/apps/desktop/src", homeDirectory: baseDir, platform: options?.platform ?? "darwin", processArch: options?.processArch ?? "x64", appVersion: options?.appVersion ?? "1.2.3", appPath: options?.appPath ?? "/repo", isPackaged: options?.isPackaged ?? true, resourcesPath: options?.resourcesPath ?? "/missing/resources", runningUnderArm64Translation: false, }).pipe( Layer.provide( Layer.mergeAll( NodeServices.layer, DesktopConfig.layerTest({ T3CODE_HOME: baseDir, T3CODE_PORT: "9999", T3CODE_MODE: "desktop", T3CODE_DESKTOP_LAN_HOST: "192.168.1.50", VITE_DEV_SERVER_URL: options?.devServerUrl, }), ), ), );} const restoreEnv = (name: string, value: string | undefined) => { if (value === undefined) { delete process.env[name]; } else { process.env[name] = value; }}; const withHarness = <A, E, R>( effect: Effect.Effect< A, E, | R | DesktopEnvironment.DesktopEnvironment | FileSystem.FileSystem | DesktopBackendConfiguration.DesktopBackendConfiguration >,) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); return yield* effect.pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslEnvironment.layerTest()), Layer.provideMerge(DesktopWslServerTree.layerTest()), Layer.provideMerge(makeEnvironmentLayer(baseDir)), ), ), ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)); interface PackagedWslHarnessContext { readonly baseDir: string; readonly archivePath: string; readonly hashPath: string; readonly archiveHash: string; readonly mountedAppRoot: string; readonly mountedEntryPath: string;} const withPackagedWslHarness = <A, E, R>( input: { readonly archiveHash: string; readonly wsl: ( context: PackagedWslHarnessContext, ) => DesktopWslEnvironment.DesktopWslEnvironmentTestStub; readonly forbidFallback?: string; readonly cleanupLegacy?: Effect.Effect<void>; readonly forbidCleanup?: string; }, effect: ( context: PackagedWslHarnessContext, ) => Effect.Effect< A, E, R | FileSystem.FileSystem | Path.Path | DesktopBackendConfiguration.DesktopBackendConfiguration >,) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const archivePath = path.join(baseDir, "wsl-runtime.tar.gz"); const hashPath = `${archivePath}.sha256`; const mountedAppRoot = "/mnt/c/app.asar.unpacked"; const mountedEntryPath = path.join(baseDir, "app.asar.unpacked/apps/server/dist/bin.mjs"); yield* fileSystem.makeDirectory(path.dirname(mountedEntryPath), { recursive: true }); yield* fileSystem.writeFileString(mountedEntryPath, ""); yield* fileSystem.writeFileString(archivePath, "archive"); yield* fileSystem.writeFileString(hashPath, `${input.archiveHash}\n`); const context = { baseDir, archivePath, hashPath, archiveHash: input.archiveHash, mountedAppRoot, mountedEntryPath, } satisfies PackagedWslHarnessContext; const serverTreeLayer = input.forbidFallback ? Layer.succeed( DesktopWslServerTree.DesktopWslServerTree, DesktopWslServerTree.DesktopWslServerTree.of({ ensure: Effect.die(input.forbidFallback), cleanupLegacy: input.forbidCleanup ? Effect.die(input.forbidCleanup) : (input.cleanupLegacy ?? Effect.void), }), ) : DesktopWslServerTree.layerTest({ result: { ok: true, root: path.join(baseDir, "app.asar.unpacked") }, cleanupLegacy: input.cleanupLegacy ?? Effect.void, }); return yield* effect(context).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(serverTreeLayer), Layer.provideMerge( DesktopWslEnvironment.layerTest({ isAvailable: true, distros: [{ name: "Ubuntu", isDefault: true, version: 2 }], windowsToWslPath: () => Option.some(mountedAppRoot), getDistroIp: () => Option.some("172.27.0.99"), ...input.wsl(context), }), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: baseDir, platform: "win32", resourcesPath: baseDir, }), ), ), ), ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)); describe("DesktopBackendConfiguration", () => { it("accepts only normalized SHA-256 archive identities", () => { assert.equal( DesktopBackendConfiguration.parseWslRuntimeArchiveHash(` ${"A".repeat(64)}\n`), "a".repeat(64), ); assert.isNull(DesktopBackendConfiguration.parseWslRuntimeArchiveHash("abc123")); }); it.effect("resolvePrimary produces a stable scoped bootstrap token", () => withHarness( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const first = yield* configuration.resolvePrimary; const second = yield* configuration.resolvePrimary; assert.equal(first.executablePath, process.execPath); assert.equal(first.entryPath, environment.backendEntryPath); assert.equal(first.cwd, environment.backendCwd); assert.equal(first.captureOutput, true); assert.equal(first.env.ELECTRON_RUN_AS_NODE, "1"); assert.isUndefined(first.env.T3CODE_PORT); assert.isUndefined(first.env.T3CODE_MODE); assert.isUndefined(first.env.T3CODE_DESKTOP_LAN_HOST); assert.equal(first.bootstrap.mode, "desktop"); assert.equal(first.bootstrap.noBrowser, true); assert.equal(first.bootstrap.port, 4888); assert.equal(first.bootstrap.host, "0.0.0.0"); assert.equal(first.bootstrap.t3Home, environment.baseDir); assert.equal(first.bootstrap.tailscaleServeEnabled, true); assert.equal(first.bootstrap.tailscaleServePort, 8443); assert.match(first.bootstrap.desktopBootstrapToken, /^[0-9a-f]{48}$/i); assert.equal(second.bootstrap.desktopBootstrapToken, first.bootstrap.desktopBootstrapToken); }), ), ); it.effect("resolvePrimary starts from server.asar without materializing the WSL tree", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const resourcesPath = path.join(baseDir, "resources"); const config = yield* Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; return yield* configuration.resolvePrimary; }).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslEnvironment.layerTest()), Layer.provideMerge( Layer.succeed( DesktopWslServerTree.DesktopWslServerTree, DesktopWslServerTree.DesktopWslServerTree.of({ ensure: Effect.die("Windows primary must not extract the WSL server tree"), cleanupLegacy: Effect.die("Windows primary must not clean the WSL server tree"), }), ), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: `${resourcesPath}/app.asar`, platform: "win32", resourcesPath, }), ), ), ), ); assert.equal( config.entryPath, path.join(resourcesPath, "server.asar/apps/server/dist/bin.mjs"), ); assert.equal(config.env.ELECTRON_RUN_AS_NODE, "1"); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("resolveWsl reuses the primary's bootstrap token", () => withHarness( Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const primary = yield* configuration.resolvePrimary; const wsl = yield* configuration.resolveWsl({ port: 5000, distro: null }); assert.equal(wsl.bootstrap.desktopBootstrapToken, primary.bootstrap.desktopBootstrapToken); }), ), ); it.effect("resolveWsl pins a default-tracking run to the concrete default distro", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const entryPath = path.join(baseDir, "apps/server/dist/bin.mjs"); yield* fileSystem.makeDirectory(path.dirname(entryPath), { recursive: true }); yield* fileSystem.writeFileString(entryPath, ""); const observedDistros: Array<string | null> = []; const config = yield* Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; return yield* configuration.resolveWsl({ port: 5000, distro: null }); }).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslServerTree.layerTest()), Layer.provideMerge( DesktopWslEnvironment.layerTest({ isAvailable: true, distros: [ { name: "Debian", isDefault: false, version: 2 }, { name: "Ubuntu", isDefault: true, version: 2 }, ], windowsToWslPath: (distro) => { observedDistros.push(distro); return Option.some("/repo"); }, ensureNodePty: (distro) => { observedDistros.push(distro); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, getDistroIp: (distro) => { observedDistros.push(distro); return Option.some("172.27.0.99"); }, }), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: baseDir, platform: "win32", resourcesPath: baseDir, }), ), ), ), ); assert.equal(config.runningDistro, "Ubuntu"); assert.deepEqual(config.args.slice(0, 2), ["-d", "Ubuntu"]); assert.deepEqual(observedDistros, ["Ubuntu", "Ubuntu", "Ubuntu"]); assert.isTrue(Option.isNone(config.preflightFailure)); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("resolveWsl launches a packaged backend from the WSL-local runtime cache", () => { const observedArchives: Array<{ windowsArchivePath: string; runtimeId: string; sha256: string; }> = []; const observedNodePtyRoots: string[] = []; let legacyCleanupCount = 0; const linuxAppRoot = "/home/test/.t3/wsl-runtime/1.2.3-x64"; return withPackagedWslHarness( { archiveHash: "a".repeat(64), forbidFallback: "A valid WSL archive must not extract the Windows fallback", cleanupLegacy: Effect.sync(() => { legacyCleanupCount += 1; }), wsl: () => ({ prepareRuntime: (_distro, archive) => { observedArchives.push({ windowsArchivePath: archive.windowsPath, runtimeId: archive.runtimeId, sha256: archive.sha256, }); return { ok: true, linuxAppRoot }; }, ensureNodePty: (_distro, root) => { observedNodePtyRoots.push(root); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, }), }, ({ archiveHash, archivePath, baseDir }) => Effect.gen(function* () { const path = yield* Path.Path; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const config = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedArchives, [ { windowsArchivePath: archivePath, runtimeId: `sha256-${archiveHash}`, sha256: archiveHash, }, ]); assert.deepEqual(observedNodePtyRoots, [linuxAppRoot]); assert.equal( config.entryPath, path.join(baseDir, "server.asar/apps/server/dist/bin.mjs"), ); assert.include(config.args, `${linuxAppRoot}/apps/server/dist/bin.mjs`); assert.equal(config.wslRuntimeId, `sha256-${archiveHash}`); assert.equal(legacyCleanupCount, 1); assert.isTrue(Option.isNone(config.preflightFailure)); }), ); }); it.effect("resolveWsl changes the cache id when the packaged archive changes", () => { const firstHash = "a".repeat(64); const secondHash = "b".repeat(64); const observedRuntimeIds: string[] = []; return withPackagedWslHarness( { archiveHash: firstHash, wsl: () => ({ prepareRuntime: (_distro, archive) => { observedRuntimeIds.push(archive.runtimeId); return { ok: true, linuxAppRoot: `/runtime/${archive.runtimeId}` }; }, ensureNodePty: () => ({ ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin", }), }), }, ({ hashPath, mountedAppRoot }) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const first = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); yield* fileSystem.writeFileString(hashPath, secondHash); const second = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); yield* fileSystem.writeFileString(hashPath, "not-a-sha256"); const invalidIdentity = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedRuntimeIds, [`sha256-${firstHash}`, `sha256-${secondHash}`]); assert.equal(first.wslRuntimeId, observedRuntimeIds[0]); assert.equal(second.wslRuntimeId, observedRuntimeIds[1]); assert.isUndefined(invalidIdentity.wslRuntimeId); assert.include(invalidIdentity.args, `${mountedAppRoot}/apps/server/dist/bin.mjs`); }), ); }); it.effect("resolveWsl falls back to the mounted runtime when archive staging fails", () => { const observedNodePtyRoots: string[] = []; return withPackagedWslHarness( { archiveHash: "b".repeat(64), wsl: () => ({ prepareRuntime: () => ({ ok: false, reason: "archive is corrupt" }), ensureNodePty: (_distro, root) => { observedNodePtyRoots.push(root); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, }), }, ({ mountedAppRoot, mountedEntryPath }) => Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const config = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedNodePtyRoots, [mountedAppRoot]); assert.equal(config.entryPath, mountedEntryPath); assert.include(config.args, `${mountedAppRoot}/apps/server/dist/bin.mjs`); assert.isUndefined(config.wslRuntimeId); assert.isTrue(Option.isNone(config.preflightFailure)); }), ); });Lines 1–500 of 1371. Load more
import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, describe, it } from "@effect/vitest"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Logger from "effect/Logger"; import * as ManagedRuntime from "effect/ManagedRuntime"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as PlatformError from "effect/PlatformError"; import * as Schema from "effect/Schema"; import { ChildProcessSpawner } from "effect/unstable/process"; import * as DesktopEnvironment from "../app/DesktopEnvironment.ts"; import * as DesktopBackendConfiguration from "./DesktopBackendConfiguration.ts"; import * as DesktopConfig from "../app/DesktopConfig.ts"; import * as DesktopServerExposure from "./DesktopServerExposure.ts"; import * as DesktopAppSettings from "../settings/DesktopAppSettings.ts"; import * as DesktopWslEnvironment from "../wsl/DesktopWslEnvironment.ts"; import * as DesktopWslServerTree from "../wsl/DesktopWslServerTree.ts"; const PersistedServerObservabilitySettingsDocument = Schema.Struct({ observability: Schema.Struct({ otlpTracesUrl: Schema.String, otlpMetricsUrl: Schema.String, }), }); const encodePersistedServerObservabilitySettingsDocument = Schema.encodeEffect( Schema.fromJsonString(PersistedServerObservabilitySettingsDocument), ); const isDesktopBackendObservabilitySettingsReadError = Schema.is( DesktopBackendConfiguration.DesktopBackendObservabilitySettingsReadError, ); const serverExposureLayer = Layer.succeed(DesktopServerExposure.DesktopServerExposure, { getState: Effect.die("unexpected getState"), backendConfig: Effect.succeed({ port: 4888, bindHost: "0.0.0.0", httpBaseUrl: new URL("http://127.0.0.1:4888"), tailscaleServeEnabled: true, tailscaleServePort: 8443, }), configureFromSettings: () => Effect.die("unexpected configureFromSettings"), setMode: () => Effect.die("unexpected setMode"), setTailscaleServeEnabled: () => Effect.die("unexpected setTailscaleServeEnabled"), getAdvertisedEndpoints: Effect.succeed([]), } satisfies DesktopServerExposure.DesktopServerExposure["Service"]); function makeEnvironmentLayer( baseDir: string, options?: { readonly appPath?: string; readonly dirname?: string; readonly isPackaged?: boolean; readonly devServerUrl?: string; readonly platform?: NodeJS.Platform; readonly resourcesPath?: string; readonly appVersion?: string; readonly processArch?: NodeJS.Architecture; }, ) { return DesktopEnvironment.layer({ dirname: options?.dirname ?? "/repo/apps/desktop/src", homeDirectory: baseDir, platform: options?.platform ?? "darwin", processArch: options?.processArch ?? "x64", appVersion: options?.appVersion ?? "1.2.3", appPath: options?.appPath ?? "/repo", isPackaged: options?.isPackaged ?? true, resourcesPath: options?.resourcesPath ?? "/missing/resources", runningUnderArm64Translation: false, }).pipe( Layer.provide( Layer.mergeAll( NodeServices.layer, DesktopConfig.layerTest({ T3CODE_HOME: baseDir, T3CODE_PORT: "9999", T3CODE_MODE: "desktop", T3CODE_DESKTOP_LAN_HOST: "192.168.1.50", VITE_DEV_SERVER_URL: options?.devServerUrl, }), ), ), ); } const restoreEnv = (name: string, value: string | undefined) => { if (value === undefined) { delete process.env[name]; } else { process.env[name] = value; } }; const withHarness = <A, E, R>( effect: Effect.Effect< A, E, | R | DesktopEnvironment.DesktopEnvironment | FileSystem.FileSystem | DesktopBackendConfiguration.DesktopBackendConfiguration >, ) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); return yield* effect.pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslEnvironment.layerTest()), Layer.provideMerge(DesktopWslServerTree.layerTest()), Layer.provideMerge(makeEnvironmentLayer(baseDir)), ), ), ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)); interface PackagedWslHarnessContext { readonly baseDir: string; readonly archivePath: string; readonly hashPath: string; readonly archiveHash: string; readonly mountedAppRoot: string; readonly mountedEntryPath: string; } const withPackagedWslHarness = <A, E, R>( input: { readonly archiveHash: string; readonly wsl: ( context: PackagedWslHarnessContext, ) => DesktopWslEnvironment.DesktopWslEnvironmentTestStub; readonly forbidFallback?: string; readonly cleanupLegacy?: Effect.Effect<void>; readonly forbidCleanup?: string; }, effect: ( context: PackagedWslHarnessContext, ) => Effect.Effect< A, E, R | FileSystem.FileSystem | Path.Path | DesktopBackendConfiguration.DesktopBackendConfiguration >, ) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const archivePath = path.join(baseDir, "wsl-runtime.tar.gz"); const hashPath = `${archivePath}.sha256`; const mountedAppRoot = "/mnt/c/app.asar.unpacked"; const mountedEntryPath = path.join(baseDir, "app.asar.unpacked/apps/server/dist/bin.mjs"); yield* fileSystem.makeDirectory(path.dirname(mountedEntryPath), { recursive: true }); yield* fileSystem.writeFileString(mountedEntryPath, ""); yield* fileSystem.writeFileString(archivePath, "archive"); yield* fileSystem.writeFileString(hashPath, `${input.archiveHash}\n`); const context = { baseDir, archivePath, hashPath, archiveHash: input.archiveHash, mountedAppRoot, mountedEntryPath, } satisfies PackagedWslHarnessContext; const serverTreeLayer = input.forbidFallback ? Layer.succeed( DesktopWslServerTree.DesktopWslServerTree, DesktopWslServerTree.DesktopWslServerTree.of({ ensure: Effect.die(input.forbidFallback), cleanupLegacy: input.forbidCleanup ? Effect.die(input.forbidCleanup) : (input.cleanupLegacy ?? Effect.void), }), ) : DesktopWslServerTree.layerTest({ result: { ok: true, root: path.join(baseDir, "app.asar.unpacked") }, cleanupLegacy: input.cleanupLegacy ?? Effect.void, }); return yield* effect(context).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(serverTreeLayer), Layer.provideMerge( DesktopWslEnvironment.layerTest({ isAvailable: true, distros: [{ name: "Ubuntu", isDefault: true, version: 2 }], windowsToWslPath: () => Option.some(mountedAppRoot), getDistroIp: () => Option.some("172.27.0.99"), ...input.wsl(context), }), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: baseDir, platform: "win32", resourcesPath: baseDir, }), ), ), ), ); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)); describe("DesktopBackendConfiguration", () => { it("accepts only normalized SHA-256 archive identities", () => { assert.equal( DesktopBackendConfiguration.parseWslRuntimeArchiveHash(` ${"A".repeat(64)}\n`), "a".repeat(64), ); assert.isNull(DesktopBackendConfiguration.parseWslRuntimeArchiveHash("abc123")); }); it.effect("resolvePrimary produces a stable scoped bootstrap token", () => withHarness( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const first = yield* configuration.resolvePrimary; const second = yield* configuration.resolvePrimary; assert.equal(first.executablePath, process.execPath); assert.equal(first.entryPath, environment.backendEntryPath); assert.equal(first.cwd, environment.backendCwd); assert.equal(first.captureOutput, true); assert.equal(first.env.ELECTRON_RUN_AS_NODE, "1"); assert.isUndefined(first.env.T3CODE_PORT); assert.isUndefined(first.env.T3CODE_MODE); assert.isUndefined(first.env.T3CODE_DESKTOP_LAN_HOST); assert.equal(first.bootstrap.mode, "desktop"); assert.equal(first.bootstrap.noBrowser, true); assert.equal(first.bootstrap.port, 4888); assert.equal(first.bootstrap.host, "0.0.0.0"); assert.equal(first.bootstrap.t3Home, environment.baseDir); assert.equal(first.bootstrap.tailscaleServeEnabled, true); assert.equal(first.bootstrap.tailscaleServePort, 8443); assert.match(first.bootstrap.desktopBootstrapToken, /^[0-9a-f]{48}$/i); assert.equal(second.bootstrap.desktopBootstrapToken, first.bootstrap.desktopBootstrapToken); }), ), ); it.effect("resolvePrimary starts from server.asar without materializing the WSL tree", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const resourcesPath = path.join(baseDir, "resources"); const config = yield* Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; return yield* configuration.resolvePrimary; }).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslEnvironment.layerTest()), Layer.provideMerge( Layer.succeed( DesktopWslServerTree.DesktopWslServerTree, DesktopWslServerTree.DesktopWslServerTree.of({ ensure: Effect.die("Windows primary must not extract the WSL server tree"), cleanupLegacy: Effect.die("Windows primary must not clean the WSL server tree"), }), ), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: `${resourcesPath}/app.asar`, platform: "win32", resourcesPath, }), ), ), ), ); assert.equal( config.entryPath, path.join(resourcesPath, "server.asar/apps/server/dist/bin.mjs"), ); assert.equal(config.env.ELECTRON_RUN_AS_NODE, "1"); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("resolveWsl reuses the primary's bootstrap token", () => withHarness( Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const primary = yield* configuration.resolvePrimary; const wsl = yield* configuration.resolveWsl({ port: 5000, distro: null }); assert.equal(wsl.bootstrap.desktopBootstrapToken, primary.bootstrap.desktopBootstrapToken); }), ), ); it.effect("resolveWsl pins a default-tracking run to the concrete default distro", () => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-backend-config-test-", }); const entryPath = path.join(baseDir, "apps/server/dist/bin.mjs"); yield* fileSystem.makeDirectory(path.dirname(entryPath), { recursive: true }); yield* fileSystem.writeFileString(entryPath, ""); const observedDistros: Array<string | null> = []; const config = yield* Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; return yield* configuration.resolveWsl({ port: 5000, distro: null }); }).pipe( Effect.provide( DesktopBackendConfiguration.layer.pipe( Layer.provideMerge(serverExposureLayer), Layer.provideMerge(DesktopAppSettings.layerTest()), Layer.provideMerge(DesktopWslServerTree.layerTest()), Layer.provideMerge( DesktopWslEnvironment.layerTest({ isAvailable: true, distros: [ { name: "Debian", isDefault: false, version: 2 }, { name: "Ubuntu", isDefault: true, version: 2 }, ], windowsToWslPath: (distro) => { observedDistros.push(distro); return Option.some("/repo"); }, ensureNodePty: (distro) => { observedDistros.push(distro); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, getDistroIp: (distro) => { observedDistros.push(distro); return Option.some("172.27.0.99"); }, }), ), Layer.provideMerge( makeEnvironmentLayer(baseDir, { appPath: baseDir, platform: "win32", resourcesPath: baseDir, }), ), ), ), ); assert.equal(config.runningDistro, "Ubuntu"); assert.deepEqual(config.args.slice(0, 2), ["-d", "Ubuntu"]); assert.deepEqual(observedDistros, ["Ubuntu", "Ubuntu", "Ubuntu"]); assert.isTrue(Option.isNone(config.preflightFailure)); }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)), ); it.effect("resolveWsl launches a packaged backend from the WSL-local runtime cache", () => { const observedArchives: Array<{ windowsArchivePath: string; runtimeId: string; sha256: string; }> = []; const observedNodePtyRoots: string[] = []; let legacyCleanupCount = 0; const linuxAppRoot = "/home/test/.t3/wsl-runtime/1.2.3-x64"; return withPackagedWslHarness( { archiveHash: "a".repeat(64), forbidFallback: "A valid WSL archive must not extract the Windows fallback", cleanupLegacy: Effect.sync(() => { legacyCleanupCount += 1; }), wsl: () => ({ prepareRuntime: (_distro, archive) => { observedArchives.push({ windowsArchivePath: archive.windowsPath, runtimeId: archive.runtimeId, sha256: archive.sha256, }); return { ok: true, linuxAppRoot }; }, ensureNodePty: (_distro, root) => { observedNodePtyRoots.push(root); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, }), }, ({ archiveHash, archivePath, baseDir }) => Effect.gen(function* () { const path = yield* Path.Path; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const config = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedArchives, [ { windowsArchivePath: archivePath, runtimeId: `sha256-${archiveHash}`, sha256: archiveHash, }, ]); assert.deepEqual(observedNodePtyRoots, [linuxAppRoot]); assert.equal( config.entryPath, path.join(baseDir, "server.asar/apps/server/dist/bin.mjs"), ); assert.include(config.args, `${linuxAppRoot}/apps/server/dist/bin.mjs`); assert.equal(config.wslRuntimeId, `sha256-${archiveHash}`); assert.equal(legacyCleanupCount, 1); assert.isTrue(Option.isNone(config.preflightFailure)); }), ); }); it.effect("resolveWsl changes the cache id when the packaged archive changes", () => { const firstHash = "a".repeat(64); const secondHash = "b".repeat(64); const observedRuntimeIds: string[] = []; return withPackagedWslHarness( { archiveHash: firstHash, wsl: () => ({ prepareRuntime: (_distro, archive) => { observedRuntimeIds.push(archive.runtimeId); return { ok: true, linuxAppRoot: `/runtime/${archive.runtimeId}` }; }, ensureNodePty: () => ({ ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin", }), }), }, ({ hashPath, mountedAppRoot }) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const first = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); yield* fileSystem.writeFileString(hashPath, secondHash); const second = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); yield* fileSystem.writeFileString(hashPath, "not-a-sha256"); const invalidIdentity = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedRuntimeIds, [`sha256-${firstHash}`, `sha256-${secondHash}`]); assert.equal(first.wslRuntimeId, observedRuntimeIds[0]); assert.equal(second.wslRuntimeId, observedRuntimeIds[1]); assert.isUndefined(invalidIdentity.wslRuntimeId); assert.include(invalidIdentity.args, `${mountedAppRoot}/apps/server/dist/bin.mjs`); }), ); }); it.effect("resolveWsl falls back to the mounted runtime when archive staging fails", () => { const observedNodePtyRoots: string[] = []; return withPackagedWslHarness( { archiveHash: "b".repeat(64), wsl: () => ({ prepareRuntime: () => ({ ok: false, reason: "archive is corrupt" }), ensureNodePty: (_distro, root) => { observedNodePtyRoots.push(root); return { ok: true, nodePath: "/usr/bin/node", resolvedPath: "/usr/bin:/bin" }; }, }), }, ({ mountedAppRoot, mountedEntryPath }) => Effect.gen(function* () { const configuration = yield* DesktopBackendConfiguration.DesktopBackendConfiguration; const config = yield* configuration.resolveWsl({ port: 5000, distro: "Ubuntu" }); assert.deepEqual(observedNodePtyRoots, [mountedAppRoot]); assert.equal(config.entryPath, mountedEntryPath); assert.include(config.args, `${mountedAppRoot}/apps/server/dist/bin.mjs`); assert.isUndefined(config.wslRuntimeId); assert.isTrue(Option.isNone(config.preflightFailure)); }), ); });