import { Todo } from "@todo-tests/common/data" import { Array, Context, Effect, Option, Ref, SubscriptionRef } from "effect" export class TodoRepository extends Context.Tag("TodoRepository")>() {} export class TodoRepositoryService { constructor( readonly ref: SubscriptionRef.SubscriptionRef<(Todo & { id: Option.Some })[]> ) {} get(id: string) { return this.ref.get.pipe( Effect.map(Array.findFirst(todo => todo.id.value === id)) ) } getIndex(id: string) { return this.ref.get.pipe( Effect.map(Array.findFirstIndex(todo => todo.id.value === id)) ) } add(todo: Todo & { id: Option.None }) { return Ref.update(this.ref, todos => Array.append(todos, new Todo({ ...todo, id: Option.some(""), })) ) } update(todo: Todo & { id: Option.Some }) { return Effect.gen(this, function*() { const index = yield* yield* this.getIndex(todo.id.value) yield* Ref.update(this.ref, Array.replace(index, todo)) }) } } export const createDefaultTodos = TodoRepository.pipe(Effect.flatMap(repo => Ref.update(repo, todos => Array.appendAll(todos, [ new Todo({ id: Option.some("1"), title: "A test todo", content: "Lorem ipsum", due: Option.none(), completed: false, createdAt: new Date(), updatedAt: new Date(), }) ]) ) ))