import type { EnvironmentId, ServerConfig } from "@t3tools/contracts"; import * as Effect from "effect/Effect"; import * as Option from "effect/Option"; import * as Stream from "effect/Stream"; import * as SubscriptionRef from "effect/SubscriptionRef"; import { AsyncResult, Atom } from "effect/unstable/reactivity"; import { EnvironmentRegistry } from "../connection/registry.ts"; import type { PreparedConnection } from "../connection/model.ts"; import { EnvironmentSupervisor } from "../connection/supervisor.ts"; import { safeErrorLogAttributes } from "../errors/safeLog.ts"; import { followStreamInEnvironment } from "./runtime.ts"; export function initialConfigOption( initialConfig: Effect.Effect, ): Effect.Effect> { return initialConfig.pipe( Effect.map(Option.some), Effect.catch((error) => Effect.logWarning("Could not load the initial environment configuration.").pipe( Effect.annotateLogs({ ...safeErrorLogAttributes(error) }), Effect.as(Option.none()), ), ), ); } export function createEnvironmentSessionAtoms( runtime: Atom.AtomRuntime, ) { const initialConfigAtom = Atom.family((environmentId: EnvironmentId) => runtime.atom( followStreamInEnvironment( environmentId, Stream.unwrap( EnvironmentSupervisor.pipe( Effect.map((supervisor) => SubscriptionRef.changes(supervisor.session).pipe( Stream.mapEffect( Option.match({ onNone: () => Effect.succeed(Option.none()), onSome: (session) => initialConfigOption(session.initialConfig), }), ), ), ), ), ), ), { initialValue: Option.none() }, ), ); // This is only the bootstrap config captured when a transport session is // established. Consumers that need current provider/settings state must use // createServerEnvironmentAtoms(...).configValueAtom instead. const initialConfigValueAtom = Atom.family((environmentId: EnvironmentId) => Atom.make((get): ServerConfig | null => Option.getOrNull( Option.getOrElse(AsyncResult.value(get(initialConfigAtom(environmentId))), () => Option.none(), ), ), ).pipe(Atom.withLabel(`environment-config-value:${environmentId}`)), ); const preparedConnectionAtom = Atom.family((environmentId: EnvironmentId) => runtime.atom( followStreamInEnvironment( environmentId, Stream.unwrap( EnvironmentSupervisor.pipe( Effect.map((supervisor) => SubscriptionRef.changes(supervisor.prepared)), ), ), ), { initialValue: Option.none() }, ), ); const preparedConnectionValueAtom = Atom.family((environmentId: EnvironmentId) => Atom.make((get) => Option.getOrElse(AsyncResult.value(get(preparedConnectionAtom(environmentId))), () => Option.none(), ), ).pipe(Atom.withLabel(`environment-prepared-connection:${environmentId}`)), ); return { initialConfigAtom, initialConfigValueAtom, preparedConnectionAtom, preparedConnectionValueAtom, }; }