Minimal Effect system for TypeScript. Lazy, composable, cancellable.
npm install mini-effect
Load and display TODOs from https://jsonplaceholder.typicode.com.
import * as Effect from "mini-effect";
import * as Concurrency from "mini-effect/concurrency";
import * as Fetch from "mini-effect/fetch";
import * as Schema from "mini-effect/schema";
const log = (...values: unknown[]) => {
console.log(...values);
return Effect.succeed();
};
const TodoSchema = Schema.object({
id: Schema.number(),
title: Schema.string(),
completed: Schema.boolean(),
});
const loadTodo = (id: number) =>
Effect.retry(
1,
Fetch.request(`https://jsonplaceholder.typicode.com/todos/${id}`).pipe(
Fetch.json,
Schema.validate(TodoSchema),
),
);
const loadManyTodos = (ids: number[]) => Concurrency.all(ids.map(loadTodo));
const logTodo = (todo: Schema.InferOutput<typeof TodoSchema>) =>
log(`
TODO ${todo.id}
title: ${todo.title}
completed: ${todo.completed}
`);
const logManyTodos = (todos: Schema.InferOutput<typeof TodoSchema>[]) =>
Effect.gen(function* () {
for (const todo of todos) yield* logTodo(todo);
});
const getIdsToLoad = Effect.fn(() => process.argv.slice(2)).pipe(
Schema.validate(
Schema.array(Schema.pipe(Schema.string(), Schema.toNumber())),
),
);
const loadAndDisplayTodos = Effect.pipe(
getIdsToLoad,
loadManyTodos,
logManyTodos,
);
const program = loadAndDisplayTodos.pipe(
Effect.catchTags({
FailedToFetch: () => log("Failed to fetch todos."),
FailedToRead: () => log("Failed to parse todos JSON."),
FailedToValidate: () => log("Failed to validate data."),
}),
);
await Effect.run(program);
MIT