Gathering detailed insights and metrics for @cardbrother/up-fetch
Gathering detailed insights and metrics for @cardbrother/up-fetch
Gathering detailed insights and metrics for @cardbrother/up-fetch
Gathering detailed insights and metrics for @cardbrother/up-fetch
npm install @cardbrother/up-fetch
Typescript
Module System
Min. Node Version
Node Version
NPM Version
TypeScript (96.53%)
JavaScript (3.47%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
603 Commits
2 Branches
1 Contributors
Updated on Mar 19, 2025
Latest Version
1.3.6-beta.7
Package Id
@cardbrother/up-fetch@1.3.6-beta.7
Unpacked Size
174.06 kB
Size
30.90 kB
File Count
24
NPM Version
9.6.7
Node Version
23.6.1
Published on
Mar 10, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
upfetch is an advanced fetch client builder with standard schema validation, automatic response parsing, smart defaults and more. Designed to make data fetching type-safe and developer-friendly while keeping the familiar fetch API.
Version 2 of upfetch is now available in beta! The changes mainly impact advanced use cases, so most projects won’t require any modifications. Give it a try with:
1npm i up-fetch@2.0.0-beta.3
Check out the Migration Guide for details about changes and how to upgrade.
For a complete overview of new features, see the v2 documentation.
params
and body
, get parsed responses automaticallybaseUrl
or headers
once, use everywhere1npm i up-fetch
Create a new upfetch instance:
1import { up } from 'up-fetch' 2 3export const upfetch = up(fetch)
Make a fetch request with schema validation:
1import { upfetch } from './upfetch' 2import { z } from 'zod' 3 4const user = await upfetch('https://a.b.c/users/1', { 5 schema: z.object({ 6 id: z.number(), 7 name: z.string(), 8 avatar: z.string().url(), 9 }), 10})
The response is already parsed and properly typed based on the schema.
upfetch extends the native fetch API, which means all standard fetch options are available.
Set defaults for all requests when creating an instance:
1const upfetch = up(fetch, () => ({ 2 baseUrl: 'https://a.b.c', 3 timeout: 30000, 4}))
Check out the the API Reference for the full list of options.
👎 With raw fetch:
1fetch( 2 `https://api.example.com/todos?search=${search}&skip=${skip}&take=${take}`, 3)
👍 With upfetch:
1upfetch('/todos', { 2 params: { search, skip, take }, 3})
Use the serializeParams option to customize the query parameter serialization.
👎 With raw fetch:
1fetch('https://api.example.com/todos', { 2 method: 'POST', 3 headers: { 'Content-Type': 'application/json' }, 4 body: JSON.stringify({ title: 'New Todo' }), 5})
👍 With upfetch:
1upfetch('/todos', { 2 method: 'POST', 3 body: { title: 'New Todo' }, 4})
upfetch also supports all fetch body types.
Check out the serializeBody option to customize the body serialization.
Since upfetch follows the Standard Schema Specification it can be used with any schema library that implements the spec.
See the full list here.
👉 With zod 3.24+
1import { z } from 'zod' 2 3const posts = await upfetch('/posts/1', { 4 schema: z.object({ 5 id: z.number(), 6 title: z.string(), 7 }), 8})
👉 With valibot 1.0+
1import { object, string, number } from 'valibot' 2 3const posts = await upfetch('/posts/1', { 4 schema: object({ 5 id: number(), 6 title: string(), 7 }), 8})
Control request/response lifecycle with simple hooks:
1const upfetch = up(fetch, () => ({ 2 onRequest: (options) => { 3 // Called before the request is made, options might be mutated here 4 }, 5 onSuccess: (data, options) => { 6 // Called when the request successfully completes 7 }, 8 onError: (error, options) => { 9 // Called when the request fails 10 }, 11}))
Set a timeout for one request:
1upfetch('/todos', { 2 timeout: 3000, 3})
Set a default timeout for all requests:
1const upfetch = up(fetch, () => ({ 2 timeout: 5000, 3}))
Raised when response.ok
is false
.
Use isResponseError
to identify this error type.
1import { isResponseError } from 'up-fetch' 2 3try { 4 await upfetch('/todos/1') 5} catch (error) { 6 if (isResponseError(error)) { 7 console.log(error.status) 8 } 9}
Raised when schema validation fails.
Use isValidationError
to identify this error type.
1import { isValidationError } from 'up-fetch' 2 3try { 4 await upfetch('/todos/1', { schema: todoSchema }) 5} catch (error) { 6 if (isValidationError(error)) { 7 console.log(error.issues) 8 } 9}
You can easily add authentication to all requests by setting a default header:
1const upfetch = up(fetch, () => ({ 2 headers: { Authorization: localStorage.getItem('bearer-token') }, 3}))
The bearer token will be retrieved from localStorage
before each request.
Simply pass undefined
:
1upfetch('/todos', { 2 signal: undefined, 3})
Grab the FormData from a form
.
1const form = document.querySelector('#my-form') 2 3upfetch('/todos', { 4 method: 'POST', 5 body: new FormData(form), 6})
Or create FormData from an object:
1import { serialize } from 'object-to-formdata' 2 3const upfetch = up(fetch, () => ({ 4 serializeBody: (body) => serialize(body), 5})) 6 7upfetch('https://a.b.c', { 8 method: 'POST', 9 body: { file: new File(['foo'], 'foo.txt') }, 10})
Since upfetch is "fetch agnostic", you can use undici instead of the native fetch implementation.
On a single request:
1import { fetch, Agent } from 'undici' 2 3const upfetch = up(fetch) 4 5const data = await upfetch('https://a.b.c', { 6 dispatcher: new Agent({ 7 keepAliveTimeout: 10, 8 keepAliveMaxTimeout: 10, 9 }), 10})
On all requests:
1import { fetch, Agent } from 'undici' 2 3const upfetch = up(fetch, () => ({ 4 dispatcher: new Agent({ 5 keepAliveTimeout: 10, 6 keepAliveMaxTimeout: 10, 7 }), 8}))
You can create multiple upfetch instances with different defaults:
1const fetchMovie = up(fetch, () => ({ 2 baseUrl: "https://api.themoviedb.org", 3 headers: { 4 accept: "application/json", 5 Authorization: `Bearer ${process.env.API_KEY}`, 6 }, 7})) 8 9const fetchFile = up(fetch, () => ({ 10 parseResponse: async (res) => { 11 const name = res.url.split('/').at(-1) ?? '' 12 const type = res.headers.get('content-type') ?? '' 13 return new File([await res.blob()], name, { type }) 14 }, 15}))
While the Fetch API does not throw an error when the response is not ok, upfetch throws a ResponseError
instead.
If you'd rather handle errors as values, set reject
to return false
.
This allows you to customize the parseResponse
function to return both successful data and error responses in a structured format.
1const upfetch = up(fetch, () => ({ 2 reject: () => false, 3 parseResponse: async (response) => { 4 const json = await response.json() 5 return response.ok 6 ? { data: json, error: null } 7 : { data: null, error: json } 8 }, 9}))
Usage:
1const { data, error } = await upfetch('/users/1')
By default upfetch is able to parse json
and text
sucessful responses automatically.
The parseResponse
method is called when reject
returns false
.
You can use that option to parse other response types.
1const upfetch = up(fetch, () => ({ 2 parseResponse: (response) => response.blob(), 3}))
💡 Note that the parseResponse
method is called only when reject
returns false
.
By default upfetch throws a ResponseError
when reject
returns true
.
If you want to throw a custom error instead, you can pass a function to the parseRejected
option.
1const upfetch = up(fetch, () => ({ 2 parseRejected: async (response) => { 3 const status = response.status 4 const data = await response.json() 5 return new CustomError(status, data) 6 }, 7}))
By default upfetch serializes the params using URLSearchParams
.
You can customize the params serialization by passing a function to the serializeParams
option.
1import queryString from 'query-string' 2 3const upfetch = up(fetch, () => ({ 4 serializeParams: (params) => queryString.stringify(params), 5}))
By default upfetch serializes the plain objects using JSON.stringify
.
You can customize the body serialization by passing a function to the serializeBody
option. It lets you:
BodyInit
typeThe following example show how to restrict the valid body type to Record<string, any>
and serialize it using JSON.stringify
:
1// Restrict the body type to Record<string, any> and serialize it 2const upfetch = up(fetch, () => ({ 3 serializeBody: (body: Record<string, any>) => JSON.stringify(body), 4})) 5 6// ❌ type error: the body is not a Record<string, any> 7upfetch('https://a.b.c/todos', { 8 method: 'POST', 9 body: [['title', 'New Todo']], 10}) 11 12// ✅ works fine with Record<string, any> 13upfetch('https://a.b.c/todos', { 14 method: 'POST', 15 body: { title: 'New Todo' }, 16})
The following example uses superjson
to serialize the body. The valid body type is inferred from SuperJSON.stringify
.
1import SuperJSON from 'superjson' 2 3const upfetch = up(fetch, () => ({ 4 serializeBody: SuperJSON.stringify, 5}))
The default options receive the fetcher arguments, this allows you to tailor the defaults based on the actual request.
1const upfetch = up(fetch, (input, options) => ({ 2 baseUrl: 'https://example.com/', 3 headers: { 4 // Add authentication only for protected routes 5 Authorization: 6 typeof input === 'string' && input.startsWith('/api/protected/') 7 ? `Bearer ${getToken()}` 8 : undefined, 9 }, 10 // Add tracking params only for public endpoints 11 params: { 12 trackingId: 13 typeof input === 'string' && input.startsWith('/public/') 14 ? crypto.randomUUID() 15 : undefined, 16 }, 17 // Increase timeout for long-running operations 18 timeout: 19 typeof input === 'string' && input.startsWith('/export/') ? 30000 : 5000, 20}))
Creates a new upfetch instance with optional default options.
1function up( 2 fetchFn: typeof globalThis.fetch, 3 getDefaultOptions?: (fetcherOptions: FetcherOptions) => DefaultOptions, 4): UpFetch
Option | Signature | Description |
---|---|---|
baseUrl | string | Base URL for all requests. |
params | object | The default query parameters. |
onRequest | (options) => void | Executes before the request is made. |
onError | (error, options) => void | Executes on error. |
onSuccess | (data, options) => void | Executes when the request successfully completes. |
parseResponse | (response, options) => data | The default success response parser. If omitted json and text response are parsed automatically. |
parseRejected | (response, options) => error | The default error response parser. If omitted json and text response are parsed automatically |
serializeBody | (body) => BodyInit | The default body serializer. Restrict the valid body type by typing its first argument. |
serializeParams | (params) => string | The default query parameter serializer. |
timeout | number | The default timeout in milliseconds. |
reject | (response) => boolean | Decide when to reject the response. |
...and all other fetch options |
Makes a fetch request with the given options.
1function upfetch( 2 url: string | URL | Request, 3 options?: FetcherOptions, 4): Promise<any>
Options:
Option | Signature | Description |
---|---|---|
baseUrl | string | Base URL for the request. |
params | object | The query parameters. |
parseResponse | (response, options) => data | The success response parser. |
parseRejected | (response, options) => error | The error response parser. |
schema | StandardSchemaV1 | The schema to validate the response against. The schema must follow the Standard Schema Specification. |
serializeBody | (body) => BodyInit | The body serializer. Restrict the valid body type by typing its first argument. |
serializeParams | (params) => string | The query parameter serializer. |
timeout | number | The timeout in milliseconds. |
reject | (response) => boolean | Decide when to reject the response. |
...and all other fetch options |
Checks if the error is a ResponseError
.
Checks if the error is a ValidationError
.
Determines whether a value can be safely converted to json
.
Are considered jsonifiable:
toJSON
methodCheck out the Feature Comparison table to see how upfetch compares to other fetching libraries.
No vulnerabilities found.
No security vulnerabilities found.