Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/joshamaju/effect-fetch
💪🏽 fetch but with super-powers for effect
https://github.com/joshamaju/effect-fetch
ajax fetch http request
Last synced: 3 months ago
JSON representation
💪🏽 fetch but with super-powers for effect
- Host: GitHub
- URL: https://github.com/joshamaju/effect-fetch
- Owner: joshamaju
- Created: 2023-11-14T10:50:50.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-08-26T09:10:01.000Z (4 months ago)
- Last Synced: 2024-09-21T15:24:44.625Z (3 months ago)
- Topics: ajax, fetch, http, request
- Language: TypeScript
- Homepage: https://joshamaju.github.io/effect-fetch/
- Size: 145 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# effect-fetch
[![Publish to npm](https://github.com/joshamaju/effect-fetch/actions/workflows/release.yml/badge.svg)](https://github.com/joshamaju/effect-fetch/actions/workflows/release.yml)
`fetch` but with super-powers
- 🖇 Interceptors
- 🔐 Strongly typed errors
- 🕓 Timeouts## Install
```bash
npm install effect-fetch effect
``````bash
yarn add effect-fetch effect
``````bash
pnpm add effect-fetch effect
``````html
```
> `effect` is a required peer dependency
## Example
```ts
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);
});// or
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
```ts
import * as Interceptor from "effect-fetch/Interceptor";
import { Url as BaseURL } from "effect-fetch/interceptors/Url";const baseURL = "https://reqres.in/api";
// our list of interceptors
const interceptors = Interceptor.of(BaseURL(baseURL));// make function that executes our interceptors
const interceptor = Interceptor.provide(
Interceptor.make(interceptors),
Adapter.fetch
);// we finally make the HTTP adapter using the native Fetch API
const adapter = Fetch.effect(interceptor);const result = await Effect.runPromise(Effect.provide(program, adapter));
```## POST Request
```ts
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
```ts
const program = pipe(
Fetch.fetch("/users"),
// equivalent to response.ok ? response.json() : // handle not ok status
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
```ts
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
```ts
import * as Interceptor from "effect-fetch/Interceptor";const program = Effect.gen(function* () {
const chain = yield* Interceptor.Chain;
const clone = chain.request.clone(); // do something with request
const response = yield* chain.proceed(chain.request);
// do something with response
return response;
});
```> Interceptors are executed in the order which they were added (top to bottom).
## Error handling
```ts
import * as Interceptor from "effect-fetch/Interceptor";
import { StatusOK } from "effect-fetch/interceptors/StatusFilter";// Effect
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) // Effect
);const interceptor = Interceptor.provide(
Interceptor.make(interceptors),
Adapter.fetch
);const adapter = Fetch.effect(interceptor);
// Interceptors errors get carried over into the final computation type.
// Unlike other HTTP libraries, we don't loose type information// Effect
const result = Effect.provide(program, adapter);
```[more examples](/test)