@riribreizh/apifetch

0.1.0 • Public • Published

apifetch

An API focused simplified fetch.

Install

$ npm i @riribreizh/apifetch

Basic usage

import api from '@riribreizh/apifetch'

// with import we get a default instance of the API
// we can change a few properties (see options paragraph)
api.setBaseURL('http://myserver.api/v1')

// and make requests, JSON by default
let allUSers = await api.get('users')
let oneUser = await api.get('users', {
  email: 'username@domain.any'
})

// on POST requests the second argument is for additional parameters
// the third will make the json body
let newUser = await api.post('users', null, {
  email: 'username@domain.any',
  password: 'secret'
})

await api.delete('users', { id: newUser.id })

Additional instances

But we can create new instances with specific options.

import { createApiInstance } from '@riribreizh/apifetch'

const gitlabApi = createApiInstance({
    baseURL: 'https://gitlab.example.com/api/v4'
})

export gitlabApi

Options

The apifetch object uses a set of options for each instance. You can set there any fetch options, plus a few ones that are specific to apifetch:

Option Default Description
baseURL '' URL prefix for all requests
autoJson true enables automatically converting data to JSON in requests and JSON to data in responses
cached true enables cache feature
beforeRequest [] see Interceptors
afterResponse [] see Interceptors

Methods

The first set of methods are to alter options after instance creation.

setBaseURL(baseURL)

It's the URL prefix used for all requests. Hence, the resource parameter in request calls can be relative to this prefix, and really represent a resource.

api.setBaseURL('https://gitlab.example.com/api/v4')

setAutoJson(enable)

If set, any request with a body, and if no Content-Type header has been specified, will have the body converted to a JSON string.

In the other way, all responses with a Content-Type matching /json/ will have their bodies converted to objects (or arrays)

If not enabled, the request requires a body as described by the fetch API and the response will be the bare body as returned by fetch.

setCached(enable)

For all GET requests, a cache is maintained to avoid fetching the same data too quickly over the network. This cache is enabled by default, but can be disabled this way.

When data is cached for a specific URL, no network fetch is performed at all (unless a request interceptor is made to do it).

api.setCached(false)

setCacheLife(milliseconds)

Cached data is considered dirty after an amount of time (1000 milliseconds by default). You can tweak the amount of time the cached data will remain valid for a specific URL.

api.setCacheLife(500)

updateAuthorization(token, type)

The Authorization header can be automatically set for all requests to manage... authorization. For this, you call this method with a token (or not to remove the authorization), and optionnaly a type which will be the header content prefix (defaults to Bearer).

// enable authorization if mytoken is not null
api.updateAuthorization(myToken) // Authorization: Bearer {myToken}
// set authorization to API client ID
api.updateAuthorization(clientID, 'ClientID') // Authorization: ClientID {clientID}
// remove authorization header from all requests
api.updateAuthorization()
api.updateAuthorization(false) // same, more explicit

Request methods

Unlike fetch you don't put query parameters in the URL directly (although you can if you want). The resource centric API style of apifetch separates the endpoint (base URL) from the resource denomination and its filtering through parameters.

The params parameter is an object containing query parameters (they all need to have a value, so myurl?isNotPossible is not available).

It's not possible either to mix query parameters in the resource and params parameters. apifetch is dumb and will try to insert two ? in the URL.

api.get(resource, params, additionalFetchOptions)
api.post(resource, params, body, additionalFetchOptions)
api.put(resource, params, body, additionalFetchOptions)
api.delete(resource, params, additionalFetchOptions)
api.patch(resource, params, body, additionalFetchOptions)
api.head(resource, params, additionalFetchOptions)

There is also a generic call where you can set your own method:

api.request(method, resource, params, body, additionalFetchOptions)

Interceptors

Interceptors permit to tweak requests and responses around fetch calls, through the beforeRequest and afterResponse options, which should be arrays of functions.

In beforeRequest each request function receives the final url and options passed to fetch and can either return:

  • a FetchParams object containing modified url and options in its input and init properties respectively
  • a Response object, in which case process is stopped and this response is returned to caller (hint: that's how mock can be implemented)
import { FetchParams, createApiInstance } from 'apifetch'

const api = createApiInstance({
  // ...
  beforeRequest: [
    // dummy request interceptor
    async (url, options) => new FetchParams(url, options),
    // shortcuting interceptor sending a response
    async (url, options) => new Response('{}', {
      status: 200,
      statusText: 'I faked it!',
    })
  ]
})

Likewise, after fetch returns its response, this one can be altered with afterResponse interceptors with the request's url and options, plus a copy of the latest response (from fetch or previous interceptor).

const api = createApiInstance({
  // ...
  afterResponse: [
    // dummy response interceptor
    async (url, options, response) => response
  ]
})

IMPORTANT

Interceptors must be inserted on the instance creation, or sent through requests options parameters. They can't be altered with methods.

But you can manage arrays yourself and modify them after giving them by reference, to get the same result.

const myRequestInterceptors = [
  async (url, options) => new FetchParams(url, options)
]

const api = createApiInstance({
  // ...
  beforeRequest: myRequestInterceptors
})

myRequestInterceptors.push(
  async (url, options) => new Response('{}', {
    status: 200,
    statusText: 'I faked it!',
  })
)

Package Sidebar

Install

npm i @riribreizh/apifetch

Weekly Downloads

0

Version

0.1.0

License

MIT

Unpacked Size

33.2 kB

Total Files

11

Last publish

Collaborators

  • riribreizh