import * as NodeHttpClient from "@effect/platform-node/NodeHttpClient"; import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; import * as NodeServices from "@effect/platform-node/NodeServices"; import * as NodeOS from "node:os"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Electron from "electron"; import * as NetService from "@t3tools/shared/Net"; import { resolveRemoteT3CliPackageSpec } from "@t3tools/ssh/command"; import type { RemoteT3RunnerOptions } from "@t3tools/ssh/tunnel"; import serverPackageJson from "../../server/package.json" with { type: "json" }; import type { DesktopSettings as DesktopSettingsValue } from "./settings/DesktopAppSettings.ts"; import * as DesktopIpc from "./ipc/DesktopIpc.ts"; import * as ElectronApp from "./electron/ElectronApp.ts"; import * as ElectronDialog from "./electron/ElectronDialog.ts"; import * as ElectronMenu from "./electron/ElectronMenu.ts"; import * as ElectronProtocol from "./electron/ElectronProtocol.ts"; import * as DesktopSecretStorage from "./electron/ElectronSafeStorage.ts"; import * as ElectronShell from "./electron/ElectronShell.ts"; import * as ElectronTheme from "./electron/ElectronTheme.ts"; import * as ElectronUpdater from "./electron/ElectronUpdater.ts"; import * as ElectronWindow from "./electron/ElectronWindow.ts"; import * as DesktopApp from "./app/DesktopApp.ts"; import * as DesktopAppIdentity from "./app/DesktopAppIdentity.ts"; import * as DesktopCloudAuth from "./app/DesktopCloudAuth.ts"; import * as DesktopCloudAuthTokenStore from "./app/DesktopCloudAuthTokenStore.ts"; import * as DesktopApplicationMenu from "./window/DesktopApplicationMenu.ts"; import * as DesktopAssets from "./app/DesktopAssets.ts"; import * as DesktopBackendConfiguration from "./backend/DesktopBackendConfiguration.ts"; import * as DesktopBackendManager from "./backend/DesktopBackendManager.ts"; import * as DesktopEnvironment from "./app/DesktopEnvironment.ts"; import * as DesktopLifecycle from "./app/DesktopLifecycle.ts"; import * as DesktopObservability from "./app/DesktopObservability.ts"; import * as DesktopServerExposure from "./backend/DesktopServerExposure.ts"; import * as DesktopClientSettings from "./settings/DesktopClientSettings.ts"; import * as DesktopSavedEnvironments from "./settings/DesktopSavedEnvironments.ts"; import * as DesktopAppSettings from "./settings/DesktopAppSettings.ts"; import * as DesktopShellEnvironment from "./shell/DesktopShellEnvironment.ts"; import * as DesktopSshEnvironment from "./ssh/DesktopSshEnvironment.ts"; import * as DesktopSshPasswordPrompts from "./ssh/DesktopSshPasswordPrompts.ts"; import * as DesktopState from "./app/DesktopState.ts"; import * as DesktopUpdates from "./updates/DesktopUpdates.ts"; import * as DesktopWindow from "./window/DesktopWindow.ts"; const desktopEnvironmentLayer = Layer.unwrap( Effect.gen(function* () { const metadata = yield* Effect.service(ElectronApp.ElectronApp).pipe( Effect.flatMap((app) => app.metadata), ); return DesktopEnvironment.layer({ dirname: __dirname, homeDirectory: NodeOS.homedir(), platform: process.platform, processArch: process.arch, ...metadata, }); }), ); const resolveDesktopSshCliRunner = ( environment: DesktopEnvironment.DesktopEnvironmentShape, settings: DesktopSettingsValue, ): RemoteT3RunnerOptions => { const devRemoteEntryPath = Option.getOrUndefined(environment.devRemoteT3ServerEntryPath); if (environment.isDevelopment && devRemoteEntryPath !== undefined) { return { nodeScriptPath: devRemoteEntryPath, nodeEngineRange: serverPackageJson.engines.node, }; } return { packageSpec: resolveRemoteT3CliPackageSpec({ appVersion: environment.appVersion, updateChannel: settings.updateChannel, isDevelopment: environment.isDevelopment, }), nodeEngineRange: serverPackageJson.engines.node, }; }; const desktopSshEnvironmentLayer = Layer.unwrap( Effect.gen(function* () { const environment = yield* DesktopEnvironment.DesktopEnvironment; const settings = yield* DesktopAppSettings.DesktopAppSettings; return DesktopSshEnvironment.layer({ resolveCliRunner: settings.get.pipe( Effect.map((currentSettings) => resolveDesktopSshCliRunner(environment, currentSettings)), ), }); }), ); const electronLayer = Layer.mergeAll( ElectronApp.layer, ElectronDialog.layer, ElectronMenu.layer, ElectronProtocol.layer, DesktopSecretStorage.layer, ElectronShell.layer, ElectronTheme.layer, ElectronUpdater.layer, ElectronWindow.layer, Layer.succeed(DesktopIpc.DesktopIpc, DesktopIpc.make(Electron.ipcMain)), ); const desktopFoundationLayer = Layer.mergeAll( DesktopState.layer, DesktopLifecycle.layerShutdown, DesktopAppSettings.layer, DesktopClientSettings.layer, DesktopSavedEnvironments.layer, DesktopCloudAuthTokenStore.layer, DesktopAssets.layer, DesktopObservability.layer, ).pipe(Layer.provideMerge(desktopEnvironmentLayer)); const desktopSshLayer = desktopSshEnvironmentLayer.pipe( Layer.provideMerge(DesktopSshPasswordPrompts.layer()), ); const desktopServerExposureLayer = DesktopServerExposure.layer.pipe( Layer.provideMerge(DesktopServerExposure.networkInterfacesLayer), Layer.provideMerge(desktopFoundationLayer), ); const desktopWindowLayer = DesktopWindow.layer.pipe(Layer.provideMerge(desktopServerExposureLayer)); const desktopBackendLayer = DesktopBackendManager.layer.pipe( Layer.provideMerge(DesktopAppIdentity.layer), Layer.provideMerge(DesktopBackendConfiguration.layer), Layer.provideMerge(desktopWindowLayer), ); const desktopApplicationLayer = Layer.mergeAll( DesktopLifecycle.layer, DesktopApplicationMenu.layer, DesktopCloudAuth.layer, DesktopShellEnvironment.layer, desktopSshLayer, ).pipe(Layer.provideMerge(DesktopUpdates.layer), Layer.provideMerge(desktopBackendLayer)); const desktopRuntimeLayer = ElectronProtocol.layerSchemePrivileges.pipe( Layer.flatMap(() => desktopApplicationLayer.pipe( Layer.provideMerge(NodeServices.layer), Layer.provideMerge(NodeHttpClient.layerUndici), Layer.provideMerge(NetService.layer), Layer.provideMerge(electronLayer), ), ), ); DesktopApp.program.pipe(Effect.provide(desktopRuntimeLayer), NodeRuntime.runMain);