import { type EnvironmentId, type ProjectReadFileResult, WS_METHODS } from "@t3tools/contracts"; import * as Crypto from "effect/Crypto"; import { Atom } from "effect/unstable/reactivity"; import { createAtomCommandScheduler, createEnvironmentCommand, createEnvironmentRpcCommand, createEnvironmentRpcQueryAtomFamily, } from "./runtime.ts"; import { type CreateProjectInput, type DeleteProjectInput, type UpdateProjectInput, createProject, deleteProject, updateProject, } from "../operations/commands.ts"; import type { EnvironmentRegistry } from "../connection/registry.ts"; export type { CreateProjectInput, DeleteProjectInput, UpdateProjectInput, } from "../operations/commands.ts"; export interface OptimisticProjectFile { readonly data: ProjectReadFileResult; readonly confirmedAgainst: object | null | undefined; } export interface OptimisticProjectFileTarget { readonly environmentId: EnvironmentId; readonly cwd: string; readonly relativePath: string; } function optimisticProjectFileKey(target: OptimisticProjectFileTarget): string { return JSON.stringify([target.environmentId, target.cwd, target.relativePath]); } export function createProjectEnvironmentAtoms( runtime: Atom.AtomRuntime, ) { const projectScheduler = createAtomCommandScheduler(); const fileScheduler = createAtomCommandScheduler(); const optimisticFileFamily = Atom.family((key: string) => Atom.make(null).pipe( Atom.withLabel(`environment-data:projects:optimistic-file:${key}`), ), ); const projectConcurrency = { mode: "serial" as const, key: ({ environmentId, input }: { environmentId: string; input: { projectId: string } }) => JSON.stringify([environmentId, input.projectId]), }; return { searchEntries: createEnvironmentRpcQueryAtomFamily(runtime, { label: "environment-data:projects:search-entries", tag: WS_METHODS.projectsSearchEntries, staleTimeMs: 15_000, }), listEntries: createEnvironmentRpcQueryAtomFamily(runtime, { label: "environment-data:projects:list-entries", tag: WS_METHODS.projectsListEntries, staleTimeMs: 30_000, idleTtlMs: 5 * 60_000, }), readFile: createEnvironmentRpcQueryAtomFamily(runtime, { label: "environment-data:projects:read-file", tag: WS_METHODS.projectsReadFile, staleTimeMs: 30_000, idleTtlMs: 5 * 60_000, }), optimisticFile: (target: OptimisticProjectFileTarget) => optimisticFileFamily(optimisticProjectFileKey(target)), create: createEnvironmentCommand(runtime, { label: "environment-data:commands:project:create", execute: (input: CreateProjectInput) => createProject(input), scheduler: projectScheduler, concurrency: projectConcurrency, }), update: createEnvironmentCommand(runtime, { label: "environment-data:commands:project:update", execute: (input: UpdateProjectInput) => updateProject(input), scheduler: projectScheduler, concurrency: projectConcurrency, }), delete: createEnvironmentCommand(runtime, { label: "environment-data:commands:project:delete", execute: (input: DeleteProjectInput) => deleteProject(input), scheduler: projectScheduler, concurrency: projectConcurrency, }), writeFile: createEnvironmentRpcCommand(runtime, { label: "environment-data:projects:write-file", tag: WS_METHODS.projectsWriteFile, scheduler: fileScheduler, concurrency: { mode: "serial", key: ({ environmentId, input }) => JSON.stringify([environmentId, input.cwd, input.relativePath]), }, }), }; }