axios-multi-api
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.5 • Public • Published

    Axios Multi API

    NPM version Blazing Fast Code Coverage npm downloads install size

    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.

    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.

    You can set up multiple API handlers for different sets of APIs from different services. This provides much better scalability for many projects.

    If you’re new to Axios, please checkout this handy Axios readme

    Package was originally written to accomodate many API requests in an orderly fashion.

    Table of Contents

    Features

    • Multi APIs support
    • Global error handler for requests
    • Automatically cancel previous requests
    • Multiple response resolving strategies
    • Dynamic urls support
    • Multiple requests chaining (using promises)
    • Browsers & Node 12+ compatible
    • TypeScript compatible
    • All Axios options are supported
    • 4.42 KB gzipped

    Todo

    • Per request cache (localstorage/sessions)
    • Full fetch() API support

    Please open an issue for future requests!

    Installation

    NPM

    Run following command to install the package:

    npm i axios-multi-api

    Usage

    import { createApiFetcher } from 'axios-multi-api';
    
    const api = createApiFetcher({
        apiUrl: 'https://example.com/api',
        strategy: 'reject',
        apiEndpoints: {
          getUserDetails: {
            method: 'get',
            url: '/user-details/get',
          },
          updateUserDetails: {
            method: 'post',
            url: '/user-details/update/:userId',
          },
        },
        // Optional
        onError(error) {
          console.log('Request failed', error);
        },
        // All Axios instace config properties are supported
        headers: {
          'my-auth-key': 'example-auth-key-32rjjfa',
        }
    });
    
    // You can await for your request. Check "strategy" for details. response returns data directly
    const response = await api.getUserDetails({ userId: 1 });
    
    console.log('User details', response);
    
    await api.updateUserDetails({ name: 'Mark' }, { userId: 1 });
    
    console.log('User details updated');

    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.

    API methods

    api.yourEndpointName(queryParams, urlParams, requestConfig)

    queryParams / payload (optional)

    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.

    Query params accepts strings, numbers, and even arrays so you pass { foo: [1, 2] } and it will become: foo[]=1&foo[]=2 automatically.

    urlParams (optional)

    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.

    requestConfig (optional)

    Axios compatible Request Config for particular endpoint. It will overwrite the global settings.

    You can also specify following argument: cancellable so to have more granular control over specific endpoints.

    api.getInstance()

    When API handler is firstly initialized, a new Axios instance is created. You can call api.getInstance() if you want to get that instance directly, for example to add some interceptors.

    Global Settings

    Global settings are passed to createApiFetcher() function. You can pass all Axios Request Config. Additional options are listed below.

    Option Type Default Description
    apiUrl string Your API base url.
    apiEndpoints object List of your endpoints. Check Per Endpoint Settings for options.
    strategy string silent Error handling strategies - basically what to return when an error occurs. It can be a default data, promise can be hanged (nothing would be returned) or rejected so to use try/catch. Available: silent, reject, defaultResponse

    silent can be used for a requests that are dispatched within asynchronous wrapper functions. If a request fails, promise will silently hang and no action will be performed. It will never be resolved or rejected when there is an error. 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. You can use is in combination with onError so to handle errors globally.

    reject will simply reject the promise. Global error handling will be triggered right before the rejection. You will need to remember to set try/catch per each request to catch exceptions properly.

    defaultResponse will return default response specified in either global defaultResponse or per endpoint defaultResponse setting. Promise will not be rejected! Data from default response will be returned instead. It could be used together with object destructuring by setting defaultResponse: {} so to provide a responsible defaults.
    cancellable boolean false If set to true any previously dispatched requests to same url & of method will be cancelled, if a successive request is made meanwhile. This let's you avoid unnecessary requests to the backend.
    flattenResponse boolean true Flattens nested response.data so you can avoid writing response.data.data and obtain response directly. Response is flattened whenever there is a "data" within response "data", and no other object properties set.
    defaultResponse any null Default response when there is no data or when endpoint fails depending on the chosen strategy
    timeout int 30000 You can set a timeout in milliseconds.
    logger object console You can additionally specify logger object with your custom logger to automatically log the errors to the console. It should contain at least error and warn functions. console.log is used by default.
    onError function You can specify a function or class that will be triggered when 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.

    Per Endpoint Settings

    Each endpoint in apiEndpoints is an object that accepts properties below. You can also pass these options as a 3rd argument when calling an endpoint so to have a more granular control.

    Option Type Default Description
    method string Default request method e.g. GET, POST, DELETE, PUT etc.
    url string Url path e.g. /user-details/get
    cancellable boolean false Whether previous requests should be automatically cancelled. See global settings for more info.
    rejectCancelled boolean false If true and request is set to cancellable, a cancelled request promise will be rejected. By default instead of rejecting the promise, defaultResponse from global options is returned.
    defaultResponse any null Default response when there is no data or when endpoint fails depending on a chosen strategy
    strategy string You can control strategy per each request. Global strategy is applied by default.
    onError function You can specify a function that will be triggered when an endpoint fails.

    Full TypeScript support

    Axios-multi-api includes necessary TypeScript 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.

    Example of interface

    import {
      Endpoints,
      Endpoint,
      APIQueryParams,
      APIUrlParams,
    } from 'axios-multi-api/dist/types/api';
    
    import { createApiFetcher } from 'axios-multi-api';
    
    interface myQueryParams {
      newMovies: boolean;
    }
    
    interface EndpointsList extends Endpoints {
      fetchMovies: Endpoint<myQueryParams, myURLParams, myResponse>;
    
      // Or you can use just Endpoint
      fetchTVSeries: Endpoint;
    }
    
    const api = createApiFetcher({
      // Your config
    }) as unknown as EndpointsList;
    
    // Will return an error since "newMovies" should be a boolean
    api.fetchMovies( { newMovies: 1 } );

    Package ships interfaces with responsible defaults making it easier to add new endpoints. It exposes Endpoints and Endpoint types.

    Examples

    Per Request Error handling

    import { createApiFetcher } from 'axios-multi-api';
    
    const api = createApiFetcher({
      apiUrl: 'https://example.com/api',
      apiEndpoints: {
        sendMessage: {
          method: 'get',
          url: '/send-message/:postId',
        },
      },
    });
    
    async function sendMessage() {
      await api.sendMessage({ message: 'Something..' }, { postId: 1 }, {
        onError(error) {
          if (error.response) {
            // The request was made and the server responded with a status code
            // that falls out of the range of 2xx
            console.log(error.response.data);
            console.log(error.response.status);
            console.log(error.response.headers);
          } else if (error.request) {
            // The request was made but no response was received
            // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
            // http.ClientRequest in node.js
            console.log(error.request);
          } else {
            // Something happened in setting up the request that triggered an Error
            console.log('Error', error.message);
          }
          console.log(error.config);
        }
      });
    
      console.log('Message sent successfully');
    }
    
    sendMessage();

    OOP style with custom Error Handler (advanced)

    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.

    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. This way you can use all Axios settings for a particular API handler.

    import { ApiHandler } from 'axios-multi-api';
    
    class MyCustomHttpRequestError {
      public constructor(myCallback) {
        this.myCallback = myCallback
      }
    
      public process(error) {
        this.myCallback('Request error', error);
      }
    }
    
    class ApiService extends ApiHandler {
        /**
         * Creates an instance of Api Service.
         * @param {object}  payload                   Payload
         * @param {string}  payload.apiUrl            Api url
         * @param {string}  payload.apiEndpoints      Api endpoints
         * @param {*}       payload.logger                 Logger instance
         * @param {*}       payload.myCallback             Callback function, could be a dispatcher that e.g. forwards error data to a store
         */
        public constructor({
            apiUrl,
            apiEndpoints,
            logger,
            myCallback,
        }) {
            // Pass settings to API Handler
            super({
                apiUrl,
                apiEndpoints,
                logger,
                onError: new MyCustomHttpRequestError(myCallback),
            });
    
            this.setupInterceptor();
        }
    
        /**
         * Setup Request Interceptor
         * @returns {void}
         */
        protected setupInterceptor(): void {
            this.getInstance().interceptRequest(onRequest);
        }
    }
    
    const api = new ApiService({
      // Your config
    });

    Support & collaboration

    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 :)

    Install

    npm i axios-multi-api

    DownloadsWeekly Downloads

    65

    Version

    1.2.5

    License

    MIT

    Unpacked Size

    132 kB

    Total Files

    13

    Last publish

    Collaborators

    • mattccc