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 Option from "effect/Option";import * as Schema from "effect/Schema"; import * as DesktopConfig from "../app/DesktopConfig.ts";import * as DesktopEnvironment from "../app/DesktopEnvironment.ts";import * as DesktopAppSettings from "./DesktopAppSettings.ts"; const DesktopSettingsPatch = Schema.Struct({ linuxPasswordStore: Schema.optionalKey( Schema.Literals(["auto", "gnome-libsecret", "kwallet", "kwallet5", "kwallet6"]), ), mainWindowBounds: Schema.optionalKey( Schema.NullOr( Schema.Struct({ x: Schema.Number, y: Schema.Number, width: Schema.Number, height: Schema.Number, }), ), ), mainWindowMaximized: Schema.optionalKey(Schema.Boolean), serverExposureMode: Schema.optionalKey(Schema.Literals(["local-only", "network-accessible"])), tailscaleServeEnabled: Schema.optionalKey(Schema.Boolean), tailscaleServePort: Schema.optionalKey(Schema.Number), updateChannel: Schema.optionalKey(Schema.Literals(["latest", "nightly"])), updateChannelConfiguredByUser: Schema.optionalKey(Schema.Boolean), wslBackendEnabled: Schema.optionalKey(Schema.Boolean), wslMode: Schema.optionalKey(Schema.Literals(["local", "wsl"])), wslDistro: Schema.optionalKey(Schema.NullOr(Schema.String)), wslOnly: Schema.optionalKey(Schema.Boolean),}); const decodeDesktopSettingsPatch = Schema.decodeEffect(Schema.fromJsonString(DesktopSettingsPatch));const encodeDesktopSettingsPatch = Schema.encodeEffect(Schema.fromJsonString(DesktopSettingsPatch)); function makeEnvironmentLayer(baseDir: string, appVersion = "0.0.17") { return DesktopEnvironment.layer({ dirname: "/repo/apps/desktop/src", homeDirectory: baseDir, platform: "darwin", processArch: "x64", appVersion, appPath: "/repo", isPackaged: true, resourcesPath: "/missing/resources", runningUnderArm64Translation: false, }).pipe( Layer.provide( Layer.mergeAll(NodeServices.layer, DesktopConfig.layerTest({ T3CODE_HOME: baseDir })), ), );} const withSettings = <A, E, R>( effect: Effect.Effect< A, E, R | DesktopAppSettings.DesktopAppSettings | DesktopEnvironment.DesktopEnvironment >, options?: { readonly appVersion?: string },) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-settings-test-", }); return yield* effect.pipe( Effect.provide( DesktopAppSettings.layer.pipe( Layer.provideMerge(makeEnvironmentLayer(baseDir, options?.appVersion)), Layer.provideMerge(NodeServices.layer), ), ), ); }).pipe(Effect.provide(NodeServices.layer), Effect.scoped); function writeSettingsPatch(patch: typeof DesktopSettingsPatch.Type) { return Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const encoded = yield* encodeDesktopSettingsPatch(patch); yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString(environment.desktopSettingsPath, `${encoded}\n`); });} describe("DesktopSettings", () => { it.effect("loads defaults when no settings file exists", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; assert.deepEqual(yield* settings.load, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); assert.deepEqual(yield* settings.get, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); }), ), ); it("defaults packaged nightly builds to the nightly update channel", () => { assert.deepEqual( DesktopAppSettings.resolveDefaultDesktopSettings("0.0.17-nightly.20260415.1"), { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "nightly", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings, ); }); it.effect("loads persisted settings and applies semantic updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ linuxPasswordStore: "gnome-libsecret", serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: true, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "gnome-libsecret", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); const exposure = yield* settings.setServerExposureMode("local-only"); assert.isTrue(exposure.changed); assert.equal(exposure.settings.serverExposureMode, "local-only"); const tailscale = yield* settings.setTailscaleServe({ enabled: true, port: Option.some(9443), }); assert.isTrue(tailscale.changed); assert.equal(tailscale.settings.tailscaleServePort, 9443); const updateChannel = yield* settings.setUpdateChannel("nightly"); assert.isTrue(updateChannel.changed); assert.equal(updateChannel.settings.updateChannel, "nightly"); assert.equal(updateChannel.settings.updateChannelConfiguredByUser, true); }), ), ); it.effect("reports the failed desktop settings write operation and path", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.desktopSettingsPath, { recursive: true }); const error = yield* settings.setServerExposureMode("network-accessible").pipe(Effect.flip); assert.instanceOf(error, DesktopAppSettings.DesktopSettingsWriteError); assert.equal(error.operation, "replace-settings-file"); assert.equal(error.path, environment.desktopSettingsPath); assert.exists(error.cause); assert.equal( error.message, `Desktop settings write failed during replace-settings-file at ${environment.desktopSettingsPath}.`, ); }), ), ); it.effect("does not persist no-op semantic updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; const exposure = yield* settings.setServerExposureMode("local-only"); assert.isFalse(exposure.changed); const tailscale = yield* settings.setTailscaleServe({ enabled: false, port: Option.none(), }); assert.isFalse(tailscale.changed); const updateChannel = yield* settings.setUpdateChannel("latest"); assert.isFalse(updateChannel.changed); assert.equal(updateChannel.settings.updateChannelConfiguredByUser, false); }), ), ); it.effect("falls back to defaults when the settings file is malformed", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString(environment.desktopSettingsPath, "{not-json"); assert.deepEqual(yield* settings.load, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); }), ), ); it.effect("loads lenient persisted desktop settings JSON", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString( environment.desktopSettingsPath, `{ // JSONC-style comments and trailing commas match server settings parsing. "serverExposureMode": "network-accessible", "tailscaleServeEnabled": true, "tailscaleServePort": 8443, "mainWindowBounds": { "x": 120, "y": 80, "width": 1280, "height": 900 }, }\n`, ); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: { x: 120, y: 80, width: 1280, height: 900 }, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("rejects window bounds that do not satisfy the domain schema", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ mainWindowBounds: { x: 10.5, y: 20, width: 839, height: 620 }, mainWindowMaximized: true, serverExposureMode: "network-accessible", }); const loaded = yield* settings.load; assert.isNull(loaded.mainWindowBounds); assert.isFalse(loaded.mainWindowMaximized); assert.equal(loaded.serverExposureMode, "network-accessible"); }), ), ); it.effect( "normalizes unsupported linux password-store values without dropping other settings", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString( environment.desktopSettingsPath, `{ "linuxPasswordStore": "unsupported-store", "serverExposureMode": "network-accessible", "tailscaleServeEnabled": true, "tailscaleServePort": 8443, "updateChannel": "nightly", "updateChannelConfiguredByUser": true }\n`, ); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "nightly", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("persists sparse desktop settings documents", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* settings.setMainWindowBounds({ x: -1200, y: 40, width: 1440, height: 960 }, true); yield* settings.setServerExposureMode("network-accessible"); const persisted = yield* decodeDesktopSettingsPatch( yield* fileSystem.readFileString(environment.desktopSettingsPath), ); assert.deepEqual(persisted, { mainWindowBounds: { x: -1200, y: 40, width: 1440, height: 960 }, mainWindowMaximized: true, serverExposureMode: "network-accessible", } satisfies typeof DesktopSettingsPatch.Type); }), ), ); it.effect("migrates legacy implicit update channels to the runtime default", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ serverExposureMode: "local-only", updateChannel: "latest", }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "nightly", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), { appVersion: "0.0.17-nightly.20260415.1" }, ), ); it.effect("preserves explicit stable update channel on nightly builds", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ serverExposureMode: "local-only", updateChannel: "latest", updateChannelConfiguredByUser: true, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "latest", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), { appVersion: "0.0.17-nightly.20260415.1" }, ), ); it.effect("normalizes invalid persisted Tailscale Serve ports", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ tailscaleServeEnabled: true, tailscaleServePort: 0, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: true, tailscaleServePort: 443, updateChannel: "latest", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("persists wsl backend toggle and normalizes invalid distro names", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; const enable = yield* settings.setWslBackendEnabled(true); assert.isTrue(enable.changed); assert.equal(enable.settings.wslBackendEnabled, true); const distro = yield* settings.setWslDistro("Ubuntu-22.04"); assert.isTrue(distro.changed); assert.equal(distro.settings.wslDistro, "Ubuntu-22.04"); const reloaded = yield* settings.load; assert.equal(reloaded.wslBackendEnabled, true); assert.equal(reloaded.wslDistro, "Ubuntu-22.04"); const reject = yield* settings.setWslDistro("bad name!"); assert.equal(reject.settings.wslDistro, null); const noop = yield* settings.setWslDistro(null); assert.isFalse(noop.changed); }), ), ); it.effect("applies WSL Windows fallback with persisted and volatile updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* settings.setWslBackendEnabled(true); yield* settings.setWslOnly(true); const persistedFallback = yield* settings.applyWslWindowsFallback; assert.isTrue(persistedFallback.changed); assert.equal(persistedFallback.settings.wslBackendEnabled, false); assert.equal(persistedFallback.settings.wslOnly, false); const persistedReload = yield* settings.load; assert.equal(persistedReload.wslBackendEnabled, false); assert.equal(persistedReload.wslOnly, false); yield* settings.setWslBackendEnabled(true); yield* settings.setWslOnly(true); const volatileFallback = yield* settings.applyWslWindowsFallbackInMemory; assert.isTrue(volatileFallback.changed); assert.equal(volatileFallback.settings.wslBackendEnabled, false); assert.equal(volatileFallback.settings.wslOnly, false); const current = yield* settings.get; assert.equal(current.wslBackendEnabled, false); assert.equal(current.wslOnly, false); const diskReload = yield* settings.load; assert.equal(diskReload.wslBackendEnabled, true); assert.equal(diskReload.wslOnly, true); }), ), ); it.effect("migrates legacy wslMode=wsl to wslBackendEnabled on load", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ wslMode: "wsl", wslDistro: "Ubuntu-22.04", }); const loaded = yield* settings.load; assert.equal(loaded.wslBackendEnabled, true); assert.equal(loaded.wslDistro, "Ubuntu-22.04"); }), ), ); it.effect("drops invalid persisted wsl distro values on load", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ wslBackendEnabled: true, wslDistro: "bad/name",Lines 1–500 of 508. 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 Option from "effect/Option"; import * as Schema from "effect/Schema"; import * as DesktopConfig from "../app/DesktopConfig.ts"; import * as DesktopEnvironment from "../app/DesktopEnvironment.ts"; import * as DesktopAppSettings from "./DesktopAppSettings.ts"; const DesktopSettingsPatch = Schema.Struct({ linuxPasswordStore: Schema.optionalKey( Schema.Literals(["auto", "gnome-libsecret", "kwallet", "kwallet5", "kwallet6"]), ), mainWindowBounds: Schema.optionalKey( Schema.NullOr( Schema.Struct({ x: Schema.Number, y: Schema.Number, width: Schema.Number, height: Schema.Number, }), ), ), mainWindowMaximized: Schema.optionalKey(Schema.Boolean), serverExposureMode: Schema.optionalKey(Schema.Literals(["local-only", "network-accessible"])), tailscaleServeEnabled: Schema.optionalKey(Schema.Boolean), tailscaleServePort: Schema.optionalKey(Schema.Number), updateChannel: Schema.optionalKey(Schema.Literals(["latest", "nightly"])), updateChannelConfiguredByUser: Schema.optionalKey(Schema.Boolean), wslBackendEnabled: Schema.optionalKey(Schema.Boolean), wslMode: Schema.optionalKey(Schema.Literals(["local", "wsl"])), wslDistro: Schema.optionalKey(Schema.NullOr(Schema.String)), wslOnly: Schema.optionalKey(Schema.Boolean), }); const decodeDesktopSettingsPatch = Schema.decodeEffect(Schema.fromJsonString(DesktopSettingsPatch)); const encodeDesktopSettingsPatch = Schema.encodeEffect(Schema.fromJsonString(DesktopSettingsPatch)); function makeEnvironmentLayer(baseDir: string, appVersion = "0.0.17") { return DesktopEnvironment.layer({ dirname: "/repo/apps/desktop/src", homeDirectory: baseDir, platform: "darwin", processArch: "x64", appVersion, appPath: "/repo", isPackaged: true, resourcesPath: "/missing/resources", runningUnderArm64Translation: false, }).pipe( Layer.provide( Layer.mergeAll(NodeServices.layer, DesktopConfig.layerTest({ T3CODE_HOME: baseDir })), ), ); } const withSettings = <A, E, R>( effect: Effect.Effect< A, E, R | DesktopAppSettings.DesktopAppSettings | DesktopEnvironment.DesktopEnvironment >, options?: { readonly appVersion?: string }, ) => Effect.gen(function* () { const fileSystem = yield* FileSystem.FileSystem; const baseDir = yield* fileSystem.makeTempDirectoryScoped({ prefix: "t3-desktop-settings-test-", }); return yield* effect.pipe( Effect.provide( DesktopAppSettings.layer.pipe( Layer.provideMerge(makeEnvironmentLayer(baseDir, options?.appVersion)), Layer.provideMerge(NodeServices.layer), ), ), ); }).pipe(Effect.provide(NodeServices.layer), Effect.scoped); function writeSettingsPatch(patch: typeof DesktopSettingsPatch.Type) { return Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const encoded = yield* encodeDesktopSettingsPatch(patch); yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString(environment.desktopSettingsPath, `${encoded}\n`); }); } describe("DesktopSettings", () => { it.effect("loads defaults when no settings file exists", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; assert.deepEqual(yield* settings.load, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); assert.deepEqual(yield* settings.get, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); }), ), ); it("defaults packaged nightly builds to the nightly update channel", () => { assert.deepEqual( DesktopAppSettings.resolveDefaultDesktopSettings("0.0.17-nightly.20260415.1"), { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "nightly", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings, ); }); it.effect("loads persisted settings and applies semantic updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ linuxPasswordStore: "gnome-libsecret", serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: true, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "gnome-libsecret", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); const exposure = yield* settings.setServerExposureMode("local-only"); assert.isTrue(exposure.changed); assert.equal(exposure.settings.serverExposureMode, "local-only"); const tailscale = yield* settings.setTailscaleServe({ enabled: true, port: Option.some(9443), }); assert.isTrue(tailscale.changed); assert.equal(tailscale.settings.tailscaleServePort, 9443); const updateChannel = yield* settings.setUpdateChannel("nightly"); assert.isTrue(updateChannel.changed); assert.equal(updateChannel.settings.updateChannel, "nightly"); assert.equal(updateChannel.settings.updateChannelConfiguredByUser, true); }), ), ); it.effect("reports the failed desktop settings write operation and path", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.desktopSettingsPath, { recursive: true }); const error = yield* settings.setServerExposureMode("network-accessible").pipe(Effect.flip); assert.instanceOf(error, DesktopAppSettings.DesktopSettingsWriteError); assert.equal(error.operation, "replace-settings-file"); assert.equal(error.path, environment.desktopSettingsPath); assert.exists(error.cause); assert.equal( error.message, `Desktop settings write failed during replace-settings-file at ${environment.desktopSettingsPath}.`, ); }), ), ); it.effect("does not persist no-op semantic updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; const exposure = yield* settings.setServerExposureMode("local-only"); assert.isFalse(exposure.changed); const tailscale = yield* settings.setTailscaleServe({ enabled: false, port: Option.none(), }); assert.isFalse(tailscale.changed); const updateChannel = yield* settings.setUpdateChannel("latest"); assert.isFalse(updateChannel.changed); assert.equal(updateChannel.settings.updateChannelConfiguredByUser, false); }), ), ); it.effect("falls back to defaults when the settings file is malformed", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString(environment.desktopSettingsPath, "{not-json"); assert.deepEqual(yield* settings.load, DesktopAppSettings.DEFAULT_DESKTOP_SETTINGS); }), ), ); it.effect("loads lenient persisted desktop settings JSON", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString( environment.desktopSettingsPath, `{ // JSONC-style comments and trailing commas match server settings parsing. "serverExposureMode": "network-accessible", "tailscaleServeEnabled": true, "tailscaleServePort": 8443, "mainWindowBounds": { "x": 120, "y": 80, "width": 1280, "height": 900 }, }\n`, ); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: { x: 120, y: 80, width: 1280, height: 900 }, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "latest", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("rejects window bounds that do not satisfy the domain schema", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ mainWindowBounds: { x: 10.5, y: 20, width: 839, height: 620 }, mainWindowMaximized: true, serverExposureMode: "network-accessible", }); const loaded = yield* settings.load; assert.isNull(loaded.mainWindowBounds); assert.isFalse(loaded.mainWindowMaximized); assert.equal(loaded.serverExposureMode, "network-accessible"); }), ), ); it.effect( "normalizes unsupported linux password-store values without dropping other settings", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* fileSystem.makeDirectory(environment.stateDir, { recursive: true }); yield* fileSystem.writeFileString( environment.desktopSettingsPath, `{ "linuxPasswordStore": "unsupported-store", "serverExposureMode": "network-accessible", "tailscaleServeEnabled": true, "tailscaleServePort": 8443, "updateChannel": "nightly", "updateChannelConfiguredByUser": true }\n`, ); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "network-accessible", tailscaleServeEnabled: true, tailscaleServePort: 8443, updateChannel: "nightly", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("persists sparse desktop settings documents", () => withSettings( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const fileSystem = yield* FileSystem.FileSystem; const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* settings.setMainWindowBounds({ x: -1200, y: 40, width: 1440, height: 960 }, true); yield* settings.setServerExposureMode("network-accessible"); const persisted = yield* decodeDesktopSettingsPatch( yield* fileSystem.readFileString(environment.desktopSettingsPath), ); assert.deepEqual(persisted, { mainWindowBounds: { x: -1200, y: 40, width: 1440, height: 960 }, mainWindowMaximized: true, serverExposureMode: "network-accessible", } satisfies typeof DesktopSettingsPatch.Type); }), ), ); it.effect("migrates legacy implicit update channels to the runtime default", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ serverExposureMode: "local-only", updateChannel: "latest", }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "nightly", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), { appVersion: "0.0.17-nightly.20260415.1" }, ), ); it.effect("preserves explicit stable update channel on nightly builds", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ serverExposureMode: "local-only", updateChannel: "latest", updateChannelConfiguredByUser: true, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: false, tailscaleServePort: 443, updateChannel: "latest", updateChannelConfiguredByUser: true, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), { appVersion: "0.0.17-nightly.20260415.1" }, ), ); it.effect("normalizes invalid persisted Tailscale Serve ports", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ tailscaleServeEnabled: true, tailscaleServePort: 0, }); assert.deepEqual(yield* settings.load, { linuxPasswordStore: "auto", mainWindowBounds: null, mainWindowMaximized: false, serverExposureMode: "local-only", tailscaleServeEnabled: true, tailscaleServePort: 443, updateChannel: "latest", updateChannelConfiguredByUser: false, wslBackendEnabled: false, wslOnly: false, wslDistro: null, } satisfies DesktopAppSettings.DesktopSettings); }), ), ); it.effect("persists wsl backend toggle and normalizes invalid distro names", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; const enable = yield* settings.setWslBackendEnabled(true); assert.isTrue(enable.changed); assert.equal(enable.settings.wslBackendEnabled, true); const distro = yield* settings.setWslDistro("Ubuntu-22.04"); assert.isTrue(distro.changed); assert.equal(distro.settings.wslDistro, "Ubuntu-22.04"); const reloaded = yield* settings.load; assert.equal(reloaded.wslBackendEnabled, true); assert.equal(reloaded.wslDistro, "Ubuntu-22.04"); const reject = yield* settings.setWslDistro("bad name!"); assert.equal(reject.settings.wslDistro, null); const noop = yield* settings.setWslDistro(null); assert.isFalse(noop.changed); }), ), ); it.effect("applies WSL Windows fallback with persisted and volatile updates", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* settings.setWslBackendEnabled(true); yield* settings.setWslOnly(true); const persistedFallback = yield* settings.applyWslWindowsFallback; assert.isTrue(persistedFallback.changed); assert.equal(persistedFallback.settings.wslBackendEnabled, false); assert.equal(persistedFallback.settings.wslOnly, false); const persistedReload = yield* settings.load; assert.equal(persistedReload.wslBackendEnabled, false); assert.equal(persistedReload.wslOnly, false); yield* settings.setWslBackendEnabled(true); yield* settings.setWslOnly(true); const volatileFallback = yield* settings.applyWslWindowsFallbackInMemory; assert.isTrue(volatileFallback.changed); assert.equal(volatileFallback.settings.wslBackendEnabled, false); assert.equal(volatileFallback.settings.wslOnly, false); const current = yield* settings.get; assert.equal(current.wslBackendEnabled, false); assert.equal(current.wslOnly, false); const diskReload = yield* settings.load; assert.equal(diskReload.wslBackendEnabled, true); assert.equal(diskReload.wslOnly, true); }), ), ); it.effect("migrates legacy wslMode=wsl to wslBackendEnabled on load", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ wslMode: "wsl", wslDistro: "Ubuntu-22.04", }); const loaded = yield* settings.load; assert.equal(loaded.wslBackendEnabled, true); assert.equal(loaded.wslDistro, "Ubuntu-22.04"); }), ), ); it.effect("drops invalid persisted wsl distro values on load", () => withSettings( Effect.gen(function* () { const settings = yield* DesktopAppSettings.DesktopAppSettings; yield* writeSettingsPatch({ wslBackendEnabled: true, wslDistro: "bad/name",