> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Fetcher

> Lightweight, chainable HTTP client built on fetch with typed JSON responses and header management.

`@ooneex/fetcher` wraps the native `fetch` API in a small `Fetcher` class. It manages a base URL, typed headers, authentication tokens, and request bodies, automatically serializing JSON and parsing JSON responses. Every helper returns a typed response, and configuration methods are chainable.

## Installation

Add the package with Bun.

```bash theme={null}
bun add @ooneex/fetcher
```

## Usage

Create a `Fetcher`, optionally with a base URL, then call the verb helpers. Request bodies passed as plain objects are JSON-serialized automatically and responses are parsed as JSON.

### Basic requests

```typescript theme={null}
import { Fetcher } from "@ooneex/fetcher";

const api = new Fetcher("https://api.example.com");

type User = { id: string; name: string };

const user = await api.get<User>("/users/1");

const created = await api.post<User>("/users", {
  name: "Ada",
});

await api.put<User>("/users/1", { name: "Ada Lovelace" });
await api.patch<User>("/users/1", { name: "Ada L." });
await api.delete("/users/1");
```

### Authentication and headers

Header and auth setters are chainable and persist across requests made by the same instance.

```typescript theme={null}
import { Fetcher } from "@ooneex/fetcher";

const api = new Fetcher("https://api.example.com")
  .setBearerToken("my-access-token")
  .setLang("en");

await api.get("/me");

// Switch auth or content type as needed
api.clearBearerToken().setBasicToken("base64-credentials");
api.setContentType("application/json");
```

### Uploading files

`upload` sends `multipart/form-data`, clearing the JSON content type so the boundary is set correctly.

```typescript theme={null}
import { Fetcher } from "@ooneex/fetcher";

const api = new Fetcher("https://api.example.com");

const file = new File(["hello"], "note.txt", { type: "text/plain" });
await api.upload("/files", file);            // field name defaults to "file"
await api.upload("/files", file, "document"); // custom field name
```

### Aborting and cloning

```typescript theme={null}
import { Fetcher } from "@ooneex/fetcher";

const api = new Fetcher("https://api.example.com");

const pending = api.get("/slow");
api.abort(); // cancels in-flight requests, then resets for new ones

const copy = api.clone(); // a fresh instance sharing the same base URL
```

## When to use it

* You call external or internal REST APIs that return JSON and want typed responses without writing `fetch` boilerplate each time.
* You need a single client that carries a base URL, auth token, and language header across many requests.
* You want simple file uploads, request aborting, and chainable configuration out of the box.
* Not needed for one-off, non-JSON requests where the native `fetch` is already sufficient.
