api-conf is a rest client that allows to preconfigure all the fetch routes and use them with only the route itself as dependency.
This way a project can have all the api logic placed in a single location, simplifying maintainability.
npm i api-conf
api.js
import axios from 'axios'
import createApiSource from 'api-conf'
/**
* We can use anything we want as fetcher
*/
const apiConf = axios.create({
baseUrl: 'https://example.com/api/'
})
export default createApiSource(apiConf, {
beforeRequest: req => {...}, // [optional] Manage the request before is sent to fetcher (ex. axios)
afterResponse: (response, config) => {...}, // [optional] Manage the data response before is sent back to you
middleware: (fetcher, conf) => {...} // [optional] allow to set a middleware with custom behavior.
})
userapi.js
import declareApi from 'api.js'
export const getUserData = declareApi({
method: 'GET',
url: id => `user/${id}/account`,
config: {
headers: {
'X-Custom-Route-Header': 'custom-header-data'
}
}
})
export const saveUserData = declareApi({
method: 'POST',
url: 'user/account',
data: { // Data param can be added in config phase. This object will be merged with the one passed on request
userType: 'tester'
},
config: { // Custom config attributes will be directly merged to fetcher config, so it supports all the fetcher (ex. axios) params
headers: {}
},
parseRequestData: data => ({...data, isTest: true}),
parseResponseData: (response, config) => response.data,
parseRequestConfig: (conf, data) => ({...conf, headers: {}})
})
We don't need to know where and how the data is being fetched from or saved
usermanager.js
import {getUserData, saveUserData} from 'userapi'
const userData = await getUserData(1)
const response = await saveUserData({
name: 'User',
password: 'password'
})
The documentation is created by using axios
as fetcher
The api-conf
instance can be created by calling createApiSource
with following optional params:
apiConf
- The axios object or the axios pre-configured instance. see this for referencefetcherConfig
- Fetcher main configuration. This object will change the library behavior globally. Available callbacks are:beforeRequest
- Called immediately before the request, after the single route modifications has been appliedafterResponse
- Last callback after all modifications to the data has been applied by the single route modifionError
- Called when an exception is throwed during api call. The single route error has the priority if present. If no error callback is present on both the route and fetcherConfig the default exception is throwed
middleware
- Allows to completely customize the call of the fetcher function. Params:fetcher
- Fetcher function that must be calledconfig
- The complete config ready to be used
The single route is created by using the instance created by above function. Available attributes & functions:
method
- Method used ['GET', 'POST', ...]url
- Url of the api. Can be a function that will be parsed and will have data and config availabledata
- POST data that will be merged with data passed from the main functionconfig
- Configuration object that will be directly merged to the object passed to the fetcher. Useful for passing headers, timeouts etc. If method, url and data are present in this object will override the parsed onesparseRequestData
- Called before the request and has the request POST data as parameter. Returned data will be passed to the fetcherparseRequestConfig
- Called afterparseRequestData
, will contain all the config sent to fetcher. Useful for dynamic config/headers managementparseResponseData
- When data is returned we can parse it in order to return it in different formatonError
- Called when an exception is throwed during api call.
All the callbacks does have the informations about the data and configs that are available at that moment
Sometimes a api call must be redone because of external factors, such as JWT token that has expired or network errors.
The recall
function allows to redo an api call without changing its params
export const saveUserData = declareApi({
method: 'POST',
url: 'user/account',
onError: (e, {recall}) => {
...
return recall()
}
})
After route declaration we can finally perform all our API calls directly, without thinking about urls and request/data parsing. The library will pass the data to url if is a function or to data if is not a GET
const response = getUser(10)
npm i
npm test
npm run build