# request

A thin `fetch` wrapper with base URL configuration and streaming progress callbacks.

---

## Configuration

### `requestGlobalOptions({ baseUrl })`

Sets the global base URL prepended to every string URL passed to `request`.

```typescript
requestGlobalOptions({ baseUrl: "https://api.example.com" });
```

### `createApiUrl(url: string): string`

Returns the full URL by prepending the configured base URL.

```typescript
createApiUrl("/users"); // → "https://api.example.com/users"
```

---

## `request(url, options?): Promise<Response>`

Fetches a resource and returns a `Response`. Supports three input types:

| Input | Behaviour |
|-------|-----------|
| `string` | Fetches `createApiUrl(url)` |
| `Response` | Passed through directly |
| `ReadableStream` | Wrapped in `new Response(stream)` |

**Error responses (status ≥ 400)** are returned immediately without re-wrapping.

**Successful responses (status < 400)** are re-wrapped in a new `ReadableStream` so that `onProgress` can track byte counts.

### Options

All standard `RequestInit` fields are supported, plus:

| Option | Type | Description |
|--------|------|-------------|
| `onProgress` | `(progress: number) => void` | Called with cumulative byte count as each chunk arrives |

---

## Example

```typescript
import { request, requestGlobalOptions } from "./request";

requestGlobalOptions({ baseUrl: "https://api.example.com" });

// Basic fetch
const res = await request("/data");
const json = await res.json();

// With progress tracking
const res2 = await request("/large-file", {
    onProgress: (bytes) => console.log(`Downloaded ${bytes} bytes`),
});
const buffer = await res2.arrayBuffer();

// Pass an existing Response through
const existing = new Response("data", { status: 200 });
const wrapped = await request(existing);

// Check for errors
if (res.status >= 400) {
    console.error("Request failed:", res.status);
}
```

---

## Types

```typescript
interface RequestOptions extends RequestInit {
    onProgress?: (progress: number) => void;
}
```
