219 lines · 9.0 KB · TypeScript
RawDownload
for (const stream of [process.stdout, process.stderr]) {  stream.on("error", (err: NodeJS.ErrnoException) => {    if (err.code !== "EPIPE") throw err;  });} 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 { HostProcessArchitecture, HostProcessPlatform } from "@t3tools/shared/hostProcess";import { resolveRemoteT3CliPackageSpec } from "@t3tools/ssh/command";import type { RemoteT3RunnerOptions } from "@t3tools/ssh/tunnel";import serverPackageJson from "../../server/package.json" with { type: "json" }; 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 ElectronPowerMonitor from "./electron/ElectronPowerMonitor.ts";import * as ElectronProtocol from "./electron/ElectronProtocol.ts";import * as ElectronSafeStorage 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 DesktopConnectionCatalogStore from "./app/DesktopConnectionCatalogStore.ts";import * as DesktopClerk from "./app/DesktopClerk.ts";import * as DesktopApplicationMenu from "./window/DesktopApplicationMenu.ts";import * as DesktopAssets from "./app/DesktopAssets.ts";import * as DesktopBackendConfiguration from "./backend/DesktopBackendConfiguration.ts";import * as DesktopBackendPool from "./backend/DesktopBackendPool.ts";import * as DesktopLocalEnvironmentAuth from "./backend/DesktopLocalEnvironmentAuth.ts";import * as DesktopNetworkInterfaces from "./backend/DesktopNetworkInterfaces.ts";import * as DesktopEnvironment from "./app/DesktopEnvironment.ts";import * as DesktopLifecycle from "./app/DesktopLifecycle.ts";import * as DesktopLinuxUrlHandler from "./app/DesktopLinuxUrlHandler.ts";import * as DesktopShutdown from "./app/DesktopShutdown.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 DesktopPreReadyPlatform from "./app/DesktopPreReadyPlatform.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 DesktopTelemetryPublisher from "./telemetry/DesktopTelemetryPublisher.ts";import * as DesktopUpdates from "./updates/DesktopUpdates.ts";import * as BrowserSession from "./preview/BrowserSession.ts";import * as PreviewManager from "./preview/Manager.ts";import * as DesktopWindow from "./window/DesktopWindow.ts";import * as DesktopWslBackend from "./wsl/DesktopWslBackend.ts";import * as DesktopWslEnvironment from "./wsl/DesktopWslEnvironment.ts";import * as DesktopWslServerTree from "./wsl/DesktopWslServerTree.ts"; const desktopEnvironmentLayer = Layer.unwrap(  Effect.gen(function* () {    const metadata = yield* Effect.service(ElectronApp.ElectronApp).pipe(      Effect.flatMap((app) => app.metadata),    );    const platform = yield* HostProcessPlatform;    const processArch = yield* HostProcessArchitecture;    return DesktopEnvironment.layer({      dirname: __dirname,      homeDirectory: NodeOS.homedir(),      platform,      processArch,      ...metadata,    });  }),); const resolveDesktopSshCliRunner = (  environment: DesktopEnvironment.DesktopEnvironment["Service"],  settings: DesktopAppSettings.DesktopSettings,): 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,  ElectronPowerMonitor.layer,  ElectronProtocol.layer,  ElectronSafeStorage.layer,  ElectronShell.layer,  ElectronTheme.layer,  ElectronUpdater.layer,  ElectronWindow.layer,  DesktopIpc.layer(Electron.ipcMain),); const desktopFoundationLayer = Layer.mergeAll(  DesktopState.layer,  DesktopShutdown.layer,  DesktopAppSettings.layer,  DesktopClientSettings.layer,  DesktopConnectionCatalogStore.layer.pipe(Layer.provideMerge(DesktopSavedEnvironments.layer)),  DesktopAssets.layer,  DesktopObservability.layer,).pipe(Layer.provideMerge(desktopEnvironmentLayer)); const desktopSshLayer = desktopSshEnvironmentLayer.pipe(  Layer.provideMerge(DesktopSshPasswordPrompts.layer()),); const desktopServerExposureLayer = DesktopServerExposure.layer.pipe(  Layer.provideMerge(DesktopNetworkInterfaces.layer),  Layer.provideMerge(desktopFoundationLayer),); const desktopPreviewLayer = PreviewManager.layer.pipe(  Layer.provideMerge(BrowserSession.layer),  Layer.provideMerge(desktopFoundationLayer),); const desktopWindowLayer = DesktopWindow.layer.pipe(  Layer.provideMerge(desktopServerExposureLayer),  Layer.provideMerge(desktopPreviewLayer),); // Pool layer instantiates the backend factory once for the Windows// primary instance and exposes it via pool.primary. Consumers go through// the pool now; the legacy DesktopBackendManager service is gone. The// WSL second instance gets registered later in the migration. See// DesktopBackendPool.ts header for the full rollout plan.const desktopBackendLayer = DesktopBackendPool.layer.pipe(  Layer.provideMerge(DesktopAppIdentity.layer),  Layer.provideMerge(DesktopBackendConfiguration.layer),  Layer.provideMerge(DesktopWslEnvironment.layer),  Layer.provideMerge(DesktopWslServerTree.layer),  Layer.provideMerge(DesktopTelemetryPublisher.layer),  Layer.provideMerge(desktopWindowLayer),); // WSL orchestrator hangs off the backend layer because it needs the// pool + configuration + serverExposure; it pulls NetService and the// foundation services through the same provideMerge chain.const desktopWslBackendLayer = DesktopWslBackend.layer.pipe(  Layer.provideMerge(desktopBackendLayer),); const desktopLocalEnvironmentAuthLayer = DesktopLocalEnvironmentAuth.layer.pipe(  Layer.provideMerge(desktopBackendLayer),); const desktopApplicationLayer = Layer.mergeAll(  DesktopLifecycle.layer,  DesktopApplicationMenu.layer,  DesktopLinuxUrlHandler.layer,  DesktopShellEnvironment.layer,  desktopSshLayer,).pipe(  Layer.provideMerge(DesktopUpdates.layer),  Layer.provideMerge(desktopWslBackendLayer),  Layer.provideMerge(desktopLocalEnvironmentAuthLayer),); const desktopClerkLayer = DesktopClerk.layer.pipe(  Layer.provideMerge(desktopEnvironmentLayer),  Layer.provideMerge(NodeServices.layer),  Layer.provideMerge(ElectronApp.layer),); const desktopApplicationRuntimeLayer = desktopApplicationLayer.pipe(  Layer.provideMerge(NodeServices.layer),  Layer.provideMerge(NodeHttpClient.layerUndici),  Layer.provideMerge(NetService.layer),  Layer.provideMerge(electronLayer),); // Acquire strict pre-ready setup before Clerk, whose userData resolution can// yield and let Electron emit ready.const desktopRuntimeLayer = desktopClerkLayer.pipe(  Layer.flatMap((clerkContext) =>    desktopApplicationRuntimeLayer.pipe(Layer.provideMerge(Layer.succeedContext(clerkContext))),  ),  Layer.provideMerge(DesktopPreReadyPlatform.layer),); DesktopApp.program.pipe(Effect.provide(desktopRuntimeLayer), NodeRuntime.runMain);