import { EnvironmentId, type AssetResource, WS_METHODS } from "@t3tools/contracts"; import { Atom } from "effect/unstable/reactivity"; import type { EnvironmentRegistry } from "../connection/registry.ts"; import { createEnvironmentRpcQueryAtomFamily } from "./runtime.ts"; const ASSET_URL_REFRESH_INTERVAL_MS = 30 * 60_000; const ASSET_URL_STALE_TIME_MS = 5 * 60_000; const ASSET_URL_IDLE_TTL_MS = 60 * 60_000; export function resolveAssetUrl(httpBaseUrl: string, relativeUrl: string): string | null { try { return new URL(relativeUrl, httpBaseUrl).toString(); } catch { return null; } } export function createAssetEnvironmentAtoms( runtime: Atom.AtomRuntime, ) { const createUrl = createEnvironmentRpcQueryAtomFamily(runtime, { label: "environment-data:assets:create-url", tag: WS_METHODS.assetsCreateUrl, staleTimeMs: ASSET_URL_STALE_TIME_MS, idleTtlMs: ASSET_URL_IDLE_TTL_MS, refreshIntervalMs: ASSET_URL_REFRESH_INTERVAL_MS, }); const createUrlsFamily = Atom.family((key: string) => { const [rawEnvironmentId, resources] = JSON.parse(key) as [string, ReadonlyArray]; const environmentId = EnvironmentId.make(rawEnvironmentId); return Atom.make((get) => resources.map((resource) => get( createUrl({ environmentId, input: { resource }, }), ), ), ).pipe( Atom.setIdleTTL(ASSET_URL_IDLE_TTL_MS), Atom.withLabel(`environment-data:assets:create-urls:${key}`), ); }); return { createUrl, createUrls: (target: { readonly environmentId: EnvironmentId; readonly resources: ReadonlyArray; }) => createUrlsFamily(JSON.stringify([target.environmentId, target.resources])), }; }