TodoRepository work

This commit is contained in:
Julien Valverdé
2024-06-28 22:33:40 +02:00
parent c6612bf4a5
commit ade042e5b1

View File

@@ -1,9 +1,10 @@
import { Todo } from "@todo-tests/common/data" import { Todo } from "@todo-tests/common/data"
import { Array, Context, Effect, Option, Ref, SubscriptionRef } from "effect" import { Array, Context, Data, Effect, Option, Ref, SubscriptionRef } from "effect"
export class TodoRepository extends Context.Tag("TodoRepository")<TodoRepository, Ref.Ref<Todo[]>>() {} export class TodoRepository extends Context.Tag("TodoRepository")<TodoRepository, Ref.Ref<Todo[]>>() {}
export class TodoRepositoryService { export class TodoRepositoryService {
constructor( constructor(
readonly ref: SubscriptionRef.SubscriptionRef<(Todo & { id: Option.Some<string> })[]> readonly ref: SubscriptionRef.SubscriptionRef<(Todo & { id: Option.Some<string> })[]>
@@ -14,29 +15,59 @@ export class TodoRepositoryService {
Effect.map(Array.findFirst(todo => todo.id.value === id)) Effect.map(Array.findFirst(todo => todo.id.value === id))
) )
} }
getIndex(id: string) { getIndex(id: string) {
return this.ref.get.pipe( return this.ref.get.pipe(
Effect.map(Array.findFirstIndex(todo => todo.id.value === id)) Effect.map(Array.findFirstIndex(todo => todo.id.value === id))
) )
} }
add(todo: Todo & { id: Option.None<string> }) { add(todo: Todo) {
return Ref.update(this.ref, todos => return Effect.gen(this, function*() {
Array.append(todos, new Todo({ if (Option.isSome(todo.id))
...todo, return yield* Effect.fail(new TodoHasID({ todo }))
id: Option.some(""),
})) yield* Ref.update(this.ref, todos =>
) Array.append(todos, new Todo({
...todo,
id: Option.some(""),
}) as Todo & { id: Option.Some<string> })
)
})
} }
update(todo: Todo & { id: Option.Some<string> }) { update(todo: Todo) {
return Effect.gen(this, function*() { return Effect.gen(this, function*() {
const index = yield* yield* this.getIndex(todo.id.value) if (Option.isNone(todo.id))
yield* Ref.update(this.ref, Array.replace(index, todo)) return yield* Effect.fail(new TodoHasNoID({ todo }))
yield* Ref.update(this.ref, Array.replace(
yield* yield* this.getIndex(todo.id.value),
todo as Todo & { id: Option.Some<string> },
))
})
}
remove(todo: Todo) {
return Effect.gen(this, function*() {
if (Option.isNone(todo.id))
return yield* Effect.fail(new TodoHasNoID({ todo }))
yield* Ref.update(this.ref, Array.remove(
yield* yield* this.getIndex(todo.id.value)
))
}) })
} }
} }
export class TodoHasID extends Data.TaggedError("TodoHasID")<{
todo: Todo
}> {}
export class TodoHasNoID extends Data.TaggedError("TodoHasNoID")<{
todo: Todo
}> {}
export const createDefaultTodos = TodoRepository.pipe(Effect.flatMap(repo => export const createDefaultTodos = TodoRepository.pipe(Effect.flatMap(repo =>
Ref.update(repo, todos => Ref.update(repo, todos =>