import { type Operation, resource } from "effection"; import { taskable, type StartableTask } from "./taskable.ts"; import type { ServiceDefinition, ServiceGraph, ServiceGraphRunner } from "./service-graph.ts"; type ServiceMap = Record>; export type ServiceTestRig = { graph: ServiceGraph; with: W; }; export type ServiceTestRigOptions = { subset?: Array; createWith?: (context: { graph: ServiceGraph }) => W; }; export type ServiceTestRigTask = StartableTask>; export type ServiceTestRigOperationFactory = () => Operation< ServiceTestRig >; export type ServiceTestRigTaskFactory = () => ServiceTestRigTask; export type ServiceTestRigFor unknown> = ReturnType extends Operation ? T : ReturnType extends StartableTask ? T : never; export function useServiceTestRig>( serviceGraph: ServiceGraphRunner, options: ServiceTestRigOptions = {}, ): ServiceTestRigOperationFactory { return () => resource>(function* (provide) { const graph = yield* serviceGraph(options.subset); const withValue = options.createWith ? options.createWith({ graph }) : ({} as W); yield* provide({ graph, with: withValue }); }); } export function createServiceTestRig>( serviceGraph: ServiceGraphRunner, options: ServiceTestRigOptions = {}, ): ServiceTestRigTaskFactory { const useRig = useServiceTestRig(serviceGraph, options); return () => taskable(useRig()).task() as ServiceTestRigTask; }