upfetch
Use up-fetch when you need a reusable fetch client with request-scoped defaults, automatic request/response shaping, runtime validation, retries, and lifecycle hooks.
Mental model
up(fetchFn, getDefaultOptions?) creates the reusable client.
getDefaultOptions(input, options, ctx) runs on every request.
upfetch(input, options?, ctx?) performs one request.
- Keep
SKILL.md high-level; load the relevant file under references/ for details.
Minimum pattern
import { up } from 'up-fetch'
import { z } from 'zod'
export const upfetch = up(fetch, () => ({
baseUrl: 'https://api.example.com',
headers: {
Authorization: readToken() ? `Bearer ${readToken()}` : undefined,
},
timeout: 5000,
}))
const user = await upfetch('/users/1', {
schema: z.object({
id: z.number(),
name: z.string(),
}),
})
Workflow
- Start with client setup and dynamic defaults.
- If the request needs auth, params, body shaping, or merge semantics, read auth and request shaping.
- If the response contract matters, read validation, parsing, and errors.
- If retries, timeouts, or hook timing matter, read retries, timeouts, and lifecycle.
- If streaming or runtime quirks matter, read streaming and runtime caveats.
High-value rules
- Pass a function as the second argument to
up(), not a plain object.
- Read auth and other mutable defaults inside that function so values stay fresh.
- Use
params and body instead of hand-serializing query strings or JSON.
- Use
schema when you need runtime trust; TypeScript generics alone do not validate payloads.
- If you want error-as-value behavior, set
reject: () => false before relying on parseResponse.
- Prefer
globalThis.fetch over imported undici.fetch.
References
- Client setup and dynamic defaults
- Auth and request shaping
- Validation, parsing, and errors
- Retries, timeouts, and lifecycle
- Streaming and runtime caveats
1---2name: upfetch3description: Load this skill for any up-fetch task: `up(fetch, getDefaultOptions?)`, `upfetch(url, options?)`. Covers dynamic defaults, auth, request shaping, validation, error handling, lifecycle timing, and runtime caveats.4---5
6# upfetch
7
8Use `up-fetch` when you need a reusable fetch client with request-scoped defaults, automatic request/response shaping, runtime validation, retries, and lifecycle hooks.
9
10## Mental model
11
12- `up(fetchFn, getDefaultOptions?)` creates the reusable client.
13- `getDefaultOptions(input, options, ctx)` runs on every request.
14- `upfetch(input, options?, ctx?)` performs one request.
15- Keep `SKILL.md` high-level; load the relevant file under `references/` for details.
16
17## Minimum pattern
18
19```ts
20import { up } from 'up-fetch'
21import { z } from 'zod'
22
23export const upfetch = up(fetch, () => ({
24 baseUrl: 'https://api.example.com',
25 headers: {
26 Authorization: readToken() ? `Bearer ${readToken()}` : undefined,
27 },
28 timeout: 5000,
29}))
30
31const user = await upfetch('/users/1', {
32 schema: z.object({
33 id: z.number(),
34 name: z.string(),
35 }),
36})
37```
38
39## Workflow
40
411. Start with [client setup and dynamic defaults](references/client-setup-and-dynamic-defaults.md).
422. If the request needs auth, params, body shaping, or merge semantics, read [auth and request shaping](references/auth-and-request-shaping.md).
433. If the response contract matters, read [validation, parsing, and errors](references/validation-parsing-and-errors.md).
444. If retries, timeouts, or hook timing matter, read [retries, timeouts, and lifecycle](references/retries-timeouts-and-lifecycle.md).
455. If streaming or runtime quirks matter, read [streaming and runtime caveats](references/streaming-and-runtime-caveats.md).
46
47## High-value rules
48
49- Pass a function as the second argument to `up()`, not a plain object.
50- Read auth and other mutable defaults inside that function so values stay fresh.
51- Use `params` and `body` instead of hand-serializing query strings or JSON.
52- Use `schema` when you need runtime trust; TypeScript generics alone do not validate payloads.
53- If you want error-as-value behavior, set `reject: () => false` before relying on `parseResponse`.
54- Prefer `globalThis.fetch` over imported `undici.fetch`.
55
56## References
57
58- [Client setup and dynamic defaults](references/client-setup-and-dynamic-defaults.md)
59- [Auth and request shaping](references/auth-and-request-shaping.md)
60- [Validation, parsing, and errors](references/validation-parsing-and-errors.md)
61- [Retries, timeouts, and lifecycle](references/retries-timeouts-and-lifecycle.md)
62- [Streaming and runtime caveats](references/streaming-and-runtime-caveats.md)