# Plugins (/docs/plugins)



Plugins are optional. Each one is a separate import, so you only ship the ones you use.

## `services`: several APIs, one login [#services-several-apis-one-login]

```ts
import { createClient } from "@mrzr/api-client";
import { services } from "@mrzr/api-client/services";

const api = createClient({
  baseUrl: "https://api.example.com",
  plugins: [
    services({
      files: "https://files.example.com",
      search: { baseUrl: "https://search.example.com", timeout: 5_000 },
      maps: { baseUrl: "https://maps.thirdparty.com", auth: false },
    }),
  ],
});

await api.service("files").get("/uploads");
api.service("fiels");   // type error: not a declared service
```

Every service shares the client's session, refresh and cancellation. A service gets the token unless you set `auth: false`, which you should for third-party APIs.

| Option    | Default  | Meaning                           |
| --------- | -------- | --------------------------------- |
| `baseUrl` | required | Where the service lives           |
| `auth`    | `true`   | Send the token and refresh on 401 |
| `timeout` | client's | Default timeout for this service  |
| `headers` | –        | Added to every call               |

If two APIs need *different* logins, create two clients with different `storageKey`s instead.

## Writing a plugin [#writing-a-plugin]

A plugin is an object with a `name` and any of four hooks:

```ts
import type { ApiPlugin } from "@mrzr/api-client";

const traceIds: ApiPlugin = {
  name: "trace-ids",
  beforeRequest: (request) => ({
    ...request,
    config: {
      ...request.config,
      headers: { ...request.config?.headers, "X-Trace-Id": crypto.randomUUID() },
    },
  }),
};

createClient({ baseUrl, plugins: [traceIds] });
```

| Hook                             | Runs                                            | Use it to                         |
| -------------------------------- | ----------------------------------------------- | --------------------------------- |
| `configure(options)`             | Once, before the client is created              | Change client options             |
| `beforeRequest(request)`         | Before each `get`/`post`/`put`/`patch`/`delete` | Rewrite the URL, body or config   |
| `afterResponse(result, request)` | After each of those calls                       | Reshape results, collect metrics  |
| `extend(client)`                 | Once, after the client is created               | Add methods, like `api.service()` |

Plugins run in the page, so they never see the access token. A plugin that throws fails only that one call, with an error naming the plugin. `login`, `logout` and refresh don't pass through plugins.
