1 | # Axios Multi API
|
2 |
|
3 | Oftentimes projects require complex APIs setups, middlewares and another stuff to accomodate a lot of API requests. Axios API Handler simplifies API handling to the extent that developers can focus on operating on the fetched data from their APIs rather than on complex initial setups.
|
4 |
|
5 | This package helps in handling of many API endpoints in a simple, declarative fashion. It also aims to provide a possibility to use a global error handling in an easy manner.
|
6 |
|
7 | You can set up multiple API handlers for different sets of APIs from different services. This provides much better scalability for many projects.
|
8 |
|
9 | > If you’re new to Axios, please checkout [this handy Axios readme](https://github.com/axios/axios)
|
10 |
|
11 | Package was originally written to accomodate many API requests in an orderly fashion.
|
12 |
|
13 | ## Table of Contents
|
14 |
|
15 | - [Features](#features)
|
16 | - [Installation](#installation)
|
17 | - [Usage](#usage)
|
18 | - [Endpoint methods](#endpoint-methods)
|
19 | - [Accessing Axios instance](#accessing-axios-instance)
|
20 | - [Full TypeScript support](#full-typescript-support)
|
21 | - [Additional Configuration](#additional-configuration)
|
22 | - [Advanced example](#advanced-example)
|
23 | - [ToDo](#todo)
|
24 | - [Support & collaboration](#support-collaboration)
|
25 |
|
26 |
|
27 | ## Features
|
28 | - Multi APIs support
|
29 | - Support for multiple response resolving strategies
|
30 | - Support for dynamic urls
|
31 | - Multiple requests chaining (using promises)
|
32 | - Browsers & Node 10+ compatible
|
33 | - TypeScript compatible
|
34 |
|
35 | ## Installation
|
36 | [![NPM](https://nodei.co/npm/axios-multi-api.png)](https://npmjs.org/package/axios-multi-api)
|
37 |
|
38 | Run following command to install the package:
|
39 | ```bash
|
40 | npm i axios-multi-api
|
41 | ```
|
42 |
|
43 | ## Usage
|
44 |
|
45 | ```typescript
|
46 | import { createApiFetcher } from 'axios-multi-api';
|
47 |
|
48 | const api = createApiFetcher({
|
49 | apiUrl: 'https://example.com/api/',
|
50 | apiEndpoints: {
|
51 | getUserDetails: {
|
52 | method: 'get',
|
53 | url: '/user-details/get',
|
54 | },
|
55 | updateUserDetails: {
|
56 | method: 'post',
|
57 | url: '/user-details/update/:userId',
|
58 | },
|
59 | },
|
60 | });
|
61 |
|
62 | const data = api.getUserDetails({ userId: 1 });
|
63 |
|
64 | api.updateUserDetails({ name: 'Mark' }, { userId: 1 });
|
65 | ```
|
66 | In this basic example we fetch data from an API for user with an ID of 1. We also update user's name to Mark. If you prefer OOP you can import `ApiHandler` and initialize the handler using `new ApiHandler` instead.
|
67 |
|
68 | ## Endpoint methods
|
69 | ##### api.yourEndpointName(queryParams, urlParams, requestConfig)
|
70 |
|
71 | `queryParams` (optional)
|
72 |
|
73 | First argument of APIs functions is an object with query params for `GET` requests, or with a payload for `POST` requests. Another request types are supported as well.
|
74 |
|
75 | `urlParams` (optional)
|
76 |
|
77 | It gives possibility to modify urls structure in a declarative way. In our example `/user-details/update/:userId` will become `/user-details/update/1` when API request will be made.
|
78 |
|
79 | `requestConfig` (optional)
|
80 |
|
81 | The specified Axios compatible config will be merged with the instance config.
|
82 |
|
83 | ## Accessing Axios instance
|
84 |
|
85 | Under the hood, a new Axios instance is created when handler is initialized. You can call `api.getInstance()` if you want to operate on Axios instance directly, e.g. to add some interceptors.
|
86 |
|
87 |
|
88 | ## Full TypeScript support
|
89 |
|
90 | Axios-multi-api includes necessary [TypeScript](http://typescriptlang.org) definitions. For full TypeScript support for your endpoints, you could overwrite interface using Type Assertion of your `ApiHandler` and use your own for the API Endpoints provided.
|
91 |
|
92 | ### Example of interface
|
93 | ```typescript
|
94 | import {
|
95 | Endpoints,
|
96 | Endpoint,
|
97 | APIQueryParams,
|
98 | APIUrlParams,
|
99 | } from 'axios-multi-api/dist/types/api';
|
100 |
|
101 | import { createApiFetcher } from 'axios-multi-api';
|
102 |
|
103 | interface EndpointsList extends Endpoints {
|
104 | fetchMovies: Endpoint<myQueryParams, myURLParams, myResponse>;
|
105 | fetchTVSeries: Endpoint;
|
106 | };
|
107 |
|
108 | const api = createApiFetcher({
|
109 | // Your config
|
110 | }) as unknown as EndpointsList;
|
111 |
|
112 | ```
|
113 |
|
114 | Package ships interfaces with responsible defaults making it easier to add new endpoints. It exposes `Endpoints` and `Endpoint` types.
|
115 |
|
116 | ## Additional Configuration
|
117 | `strategy`
|
118 | Default: `silent`
|
119 | Available: `silent` | `reject` | `throwError`
|
120 |
|
121 | > `silent`
|
122 | > Can be used for a requests that are dispatched within asynchronous wrapper functions
|
123 | > Those functions should preferably never be awaited
|
124 | > If a request fails, promise will silently hang and no action underneath will be performed
|
125 | > Please remember that this is not what Promises were made for, however if used properly it saves developers from try/catch or additional response data checks everywhere
|
126 |
|
127 | > `reject`
|
128 | > Promise will be simply rejected and global error handling triggered right before the rejection
|
129 |
|
130 | > `throwError`
|
131 | > An exception with Error object will be triggered. Using this approach you need to remember to set try/catch per each request to catch exceptions properly.
|
132 |
|
133 |
|
134 | `flattenResponse`
|
135 | Default `true`
|
136 |
|
137 | Flattens nested response.data so you can avoid writing `response.data.data` and obtain response directly. Response is flattened when there is a "data" within Axios' response "data", and no other object properties set.
|
138 |
|
139 |
|
140 | `timeout`
|
141 | Default `30000`
|
142 |
|
143 | You can set a timeout in milliseconds.
|
144 |
|
145 |
|
146 | `logger`
|
147 | Default `console`
|
148 |
|
149 | You can additionally specify logger property with your custom logger to automatically log the errors to the console.
|
150 |
|
151 |
|
152 | `httpRequestErrorService`
|
153 | Default `null`
|
154 |
|
155 | You can specify either class or a function that will be triggered whenever an endpoint fails. If it's a class it should expose a `process` method. Axios Error Object will be sent as a first argument of it.
|
156 |
|
157 | ## Advanced example
|
158 |
|
159 | You could for example create an API service class that extends the handler, inject an error service class to handle with a store that would collect the errors.
|
160 |
|
161 | As you may notice there's also a `setupInterceptor` and `httpRequestHandler` exposed. You can operate on it instead of requesting an Axios instance prior the operation. In this way you can use all Axios configuration settings on a particular API handler.
|
162 |
|
163 |
|
164 | ```typescript
|
165 | import { ApiHandler } from 'axios-multi-api';
|
166 |
|
167 | export class ApiService extends ApiHandler {
|
168 | /**
|
169 | * Creates an instance of Api Service.
|
170 | * @param {object} payload Payload
|
171 | * @param {string} payload.apiUrl Api url
|
172 | * @param {string} payload.apiEndpoints Api endpoints
|
173 | * @param {*} payload.logger Logger instance
|
174 | * @param {*} payload.storeDispatcher A dispatcher function to dispatch data to a store
|
175 | * @memberof ApiService
|
176 | */
|
177 | public constructor({
|
178 | apiUrl,
|
179 | apiEndpoints,
|
180 | logger,
|
181 | storeDispatcher,
|
182 | }) {
|
183 | super({
|
184 | apiUrl,
|
185 | apiEndpoints,
|
186 | logger,
|
187 | httpRequestErrorService: new HttpRequestErrorService(storeDispatcher),
|
188 | });
|
189 |
|
190 | this.setupInterceptor();
|
191 | }
|
192 |
|
193 | /**
|
194 | * Setup Request Interceptor
|
195 | * @returns {void}
|
196 | */
|
197 | protected setupInterceptor(): void {
|
198 | this.httpRequestHandler.interceptRequest(onRequest);
|
199 | }
|
200 | }
|
201 |
|
202 | const api = new ApiService({
|
203 | // Your config
|
204 | });
|
205 | ```
|
206 |
|
207 | ## ToDo
|
208 | 1) Better Axios Instance exposure.
|
209 | 2) Improve Readme by adding more information.
|
210 | 3) Cancellation strategies support.
|
211 | 4) Better API exposure.
|
212 | 5) More tests.
|
213 |
|
214 | ## Support & collaboration
|
215 |
|
216 | If you have any idea for an improvement, please file an issue. Feel free to make a PR if you are willing to collaborate on the project. Thank you :)
|