import * as A from 'fp-ts/Array';
import { pipe } from 'fp-ts/function';
import * as O from 'fp-ts/Option';
import * as RTE from 'fp-ts/ReaderTaskEither';
import * as TE from 'fp-ts/TaskEither';
type Item = { id: string; name: string; year: number };
const items: Array<Item> = [
{ id: '1', name: 'foo', year: 2020 },
{ id: '2', name: 'bar', year: 2021 },
{ id: '3', name: 'baz', year: 2022 },
];
type Database = {
findById: (id: string) => TE.TaskEither<Error, Item>;
findManyByYear: (year: number) => TE.TaskEither<Error, Array<Item>>;
findManyByName: (name: string) => TE.TaskEither<Error, Array<Item>>;
};
const createDB = (): Database => {
return {
findById: (id) =>
pipe(
items,
A.findFirst((item) => item.id === id),
O.fold(
() => TE.left(new Error('not found')),
(item) => TE.right(item)
)
),
findManyByYear: (year) =>
pipe(
items,
A.filter((item) => item.year === year),
(items) => TE.right(items)
),
findManyByName: (name) =>
pipe(
items,
A.filter((item) => item.name === name),
(items) => TE.right(items)
),
};
};
type Deps = Pick<Database, 'findById'>;
function getItemById(id: string): RTE.ReaderTaskEither<Deps, Error, Item> {
return pipe(
RTE.ask<Deps>(),
RTE.chainTaskEitherK(({ findById }) => findById(id))
);
}
function createDatabaseAndGetId(): TE.TaskEither<Error, Item> {
const { findById } = createDB();
return pipe(
{ findById }, // context
getItemById('1')
);
}