effect-fetch

fetch but with super-powers
- 🖇 Interceptors
- 🔐 Strongly typed errors
- 🕓 Timeouts
Install
npm install effect-fetch effect
yarn add effect-fetch effect
pnpm add effect-fetch effect
<script src="https://unpkg.com/effect-fetch/dist/index.js"></script>
effect is a required peer dependency
Example
import * as Effect from "effect/Effect";
import * as Fetch from "effect-fetch/Fetch";
import * as Result from "effect-fetch/Response";
import * as Adapter from "effect-fetch/Adapters/Fetch";
const program = Effect.gen(function* () {
const result = yield* Fetch.fetch("/users");
const res = yield* Result.filterStatusOk(result);
const users = yield* Result.json(res);
});
const program = Effect.gen(function* () {
const fetch = yield* Fetch.Fetch;
const result = yield* fetch("/users");
const res = yield* Result.filterStatusOk(result);
const users = yield* Result.json(res);
});
With interceptor
import * as Interceptor from "effect-fetch/Interceptor";
import { Url as BaseURL } from "effect-fetch/interceptors/Url";
const baseURL = "https://reqres.in/api";
const interceptors = Interceptor.of(BaseURL(baseURL));
const interceptor = Interceptor.provide(
Interceptor.make(interceptors),
Adapter.fetch
);
const adapter = Fetch.effect(interceptor);
const result = await Effect.runPromise(Effect.provide(program, adapter));
POST Request
const program = Effect.gen(function* () {
const result = yield* Fetch.fetch("/users", { method: "POST" });
const res = yield* Result.filterStatusOk(result);
const users = yield* Result.json(res);
});
Interceptors
effect-fetch ships with default interceptors
- Base URL
- Timeout
- Logger
- Status Filter
- Bearer and Basic authentication
Status Filter
To avoid manually forking the response into the error and success paths
const program = pipe(
Fetch.fetch("/users"),
Effect.flatMap((response) => Result.filterStatusOk(response)),
Effect.flatMap((response) => response.json()),
Effect.catchTag("StatusError", (error) => error)
);
We can delegate that to an interceptor. So we can decode the response body without worrying about the OK status
const program = pipe(
Fetch.fetch("/users"),
Effect.flatMap((response) => response.json())
);
const interceptors = Interceptor.of(StatusOK);
const interceptor = Interceptor.provide(
Interceptor.make(interceptors),
Adapter.fetch
);
const adapter = Fetch.effect(interceptor);
const result = await program.pipe(
Effect.provide(adapter),
Effect.catchTag("StatusError", (error) => error),
Effect.runPromise
);
Writing your own interceptor
import * as Interceptor from "effect-fetch/Interceptor";
const program = Effect.gen(function* () {
const chain = yield* Interceptor.Chain;
const clone = chain.request.clone();
const response = yield* chain.proceed(chain.request);
return response;
});
Interceptors are executed in the order which they were added (top to bottom).
Error handling
import * as Interceptor from "effect-fetch/Interceptor";
import { StatusOK } from "effect-fetch/interceptors/StatusFilter";
const program = Effect.gen(function* () {
const result = yield* Fetch.fetch("/users");
return yield* Result.text(res);
});
const interceptors = Interceptor.empty().pipe(
Interceptor.add(BaseURL(baseURL)),
Interceptor.add(StatusOK)
);
const interceptor = Interceptor.provide(
Interceptor.make(interceptors),
Adapter.fetch
);
const adapter = Fetch.effect(interceptor);
const result = Effect.provide(program, adapter);
more examples