Skip to content

Commit

Permalink
feat: $fetch.create support
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Dec 21, 2021
1 parent 7d79cdb commit d7fb8f6
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 5 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ await $fetch('/movie?lang=en', { params: { id: 123 } })

## ✔️ Interceptors

It is possible to provide async interceptors to hook into lifecycle of each `fetch` call
It is possible to provide async interceptors to hook into lifecycle events of `fetch` call.

You might want to use `$fetch.create` to set set shared interceptors.

### `onRequest({ request, options })`

Expand Down Expand Up @@ -200,6 +202,18 @@ await $fetch('/api', {
})
```

### ✔️ Create fetch with default options

This utility is useful if you need to use common options across serveral fetch calls.

**Note:** Defaults will be cloned at one level and inherrited. Be careful about nested options like `headers`.

```js
const apiFetch = $fetch.create({ baseURL: '/api' })

apiFetch('/test') // Same as $fetch('/test', { baseURL: '/api' })
```

## 💡 Adding headers

By using `headers` option, `$fetch` adds extra headers in addition to the request default headers:
Expand Down
19 changes: 15 additions & 4 deletions src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { createFetchError } from './error'
import { isPayloadMethod, isJSONSerializable, detectResponseType, ResponseType, MappedType } from './utils'

export interface CreateFetchOptions {
// eslint-disable-next-line no-use-before-define
defaults?: FetchOptions
fetch: Fetch
Headers: typeof Headers
}
Expand Down Expand Up @@ -39,6 +41,7 @@ export interface FetchOptions<R extends ResponseType = ResponseType> extends Omi
export interface $Fetch {
<T = any, R extends ResponseType = 'json'>(request: FetchRequest, opts?: FetchOptions<R>): Promise<MappedType<R, T>>
raw<T = any, R extends ResponseType = 'json'>(request: FetchRequest, opts?: FetchOptions<R>): Promise<FetchResponse<MappedType<R, T>>>
create(defaults: FetchOptions): $Fetch
}

// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
Expand All @@ -53,7 +56,7 @@ const retryStatusCodes = new Set([
504 // Gateway Timeout
])

export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {
export function createFetch (globalOptions: CreateFetchOptions): $Fetch {
function onError (ctx: FetchContext): Promise<FetchResponse<any>> {
// Retry
if (ctx.options.retry !== false) {
Expand Down Expand Up @@ -83,7 +86,7 @@ export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {
const $fetchRaw: $Fetch['raw'] = async function $fetchRaw (_request, _opts = {}) {
const ctx: FetchContext = {
request: _request,
options: _opts,
options: { ...globalOptions.defaults, ..._opts },
response: undefined,
error: undefined
}
Expand All @@ -102,7 +105,7 @@ export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {
if (ctx.options.body && isPayloadMethod(ctx.options.method)) {
if (isJSONSerializable(ctx.options.body)) {
ctx.options.body = JSON.stringify(ctx.options.body)
ctx.options.headers = new Headers(ctx.options.headers)
ctx.options.headers = new globalOptions.Headers(ctx.options.headers)
if (!ctx.options.headers.has('content-type')) {
ctx.options.headers.set('content-type', 'application/json')
}
Expand All @@ -113,7 +116,7 @@ export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {
}
}

ctx.response = await fetch(ctx.request, ctx.options as RequestInit).catch(async (error) => {
ctx.response = await globalOptions.fetch(ctx.request, ctx.options as RequestInit).catch(async (error) => {
ctx.error = error
if (ctx.options.onRequestError) {
await ctx.options.onRequestError(ctx as any)
Expand Down Expand Up @@ -153,5 +156,13 @@ export function createFetch ({ fetch, Headers }: CreateFetchOptions): $Fetch {

$fetch.raw = $fetchRaw

$fetch.create = (defaultOptions = {}) => createFetch({
...globalOptions,
defaults: {
...globalOptions.defaults,
...defaultOptions
}
})

return $fetch
}

0 comments on commit d7fb8f6

Please sign in to comment.