import { EnvironmentId, type ExecutionEnvironmentDescriptor } from "@t3tools/contracts"; import { HostProcessArchitecture, HostProcessPlatform } from "@t3tools/shared/hostProcess"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Layer from "effect/Layer"; import * as Path from "effect/Path"; import { ServerConfig } from "../../config.ts"; import { layer as ProcessRunnerLive } from "../../processRunner.ts"; import { ServerEnvironment, type ServerEnvironmentShape } from "../Services/ServerEnvironment.ts"; import packageJson from "../../../package.json" with { type: "json" }; import { resolveServerEnvironmentLabel } from "./ServerEnvironmentLabel.ts"; function platformOs(platform: NodeJS.Platform): ExecutionEnvironmentDescriptor["platform"]["os"] { switch (platform) { case "darwin": return "darwin"; case "linux": return "linux"; case "win32": return "windows"; default: return "unknown"; } } function platformArch( architecture: NodeJS.Architecture, ): ExecutionEnvironmentDescriptor["platform"]["arch"] { switch (architecture) { case "arm64": return "arm64"; case "x64": return "x64"; default: return "other"; } } export const makeServerEnvironment = Effect.fn("makeServerEnvironment")(function* () { const fileSystem = yield* FileSystem.FileSystem; const path = yield* Path.Path; const serverConfig = yield* ServerConfig; const crypto = yield* Crypto.Crypto; const hostPlatform = yield* HostProcessPlatform; const hostArchitecture = yield* HostProcessArchitecture; const readPersistedEnvironmentId = Effect.gen(function* () { const exists = yield* fileSystem .exists(serverConfig.environmentIdPath) .pipe(Effect.orElseSucceed(() => false)); if (!exists) { return null; } const raw = yield* fileSystem .readFileString(serverConfig.environmentIdPath) .pipe(Effect.map((value) => value.trim())); return raw.length > 0 ? raw : null; }); const persistEnvironmentId = (value: string) => fileSystem.writeFileString(serverConfig.environmentIdPath, `${value}\n`); const environmentIdRaw = yield* Effect.gen(function* () { const persisted = yield* readPersistedEnvironmentId; if (persisted) { return persisted; } const generated = yield* crypto.randomUUIDv4; yield* persistEnvironmentId(generated); return generated; }); const environmentId = EnvironmentId.make(environmentIdRaw); const cwdBaseName = path.basename(serverConfig.cwd).trim(); const label = yield* resolveServerEnvironmentLabel({ cwdBaseName, }); const descriptor: ExecutionEnvironmentDescriptor = { environmentId, label, platform: { os: platformOs(hostPlatform), arch: platformArch(hostArchitecture), }, serverVersion: packageJson.version, capabilities: { repositoryIdentity: true, }, }; return { getEnvironmentId: Effect.succeed(environmentId), getDescriptor: Effect.succeed(descriptor), } satisfies ServerEnvironmentShape; }); export const ServerEnvironmentLive = Layer.effect(ServerEnvironment, makeServerEnvironment()).pipe( Layer.provide(ProcessRunnerLive), );