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

1.2.1 • Public • Published

api-connector

Axios wrapper that simplifies JS API SDK development.

npm version Build Status Coverage Status dependencies Status

Getting started

Installation

npm install api-connector

Import

Import api-connector:

import ApiConnector from 'api-connector';
// or
ApiConnector = require('api-connector').default;

Example

Create GET request with async/await:

const response = await ApiConnector.reqGet('https://example.com')
                                   .start();

Create GET request without a promise:

ApiConnector.reqGet('https://example.com')
            .onOk(response => console.log(response))
            .startQuietly();

Combine both:

const responseData = await ApiConnector.reqGet('https://example.com')
                                       .onOk(response => response.data)
                                       .start();

ApiRequest modes: simple/promised

As you can see in the example above there are two ApiRequest modes:

  • simple - based purely on callbacks;
  • promised - returns a Promise that will be resolved with the result of the last onOk handler or rejected with the result of the last onFail/onCancel/onError handler.

To start a simple request call the startQuietly/startSingleQuietly methods.

Example:

const request = ApiConnector.reqGet('https://example.com')
                            .onOk(response => console.log(response));

// start a promised ApiRequest:
await request.start()

// start a simple ApiRequest:
request.startQuietly();

// start a simple ApiRequest and then convert it to promised:
request.startQuietly();
await request.genPromise();

Axios configuration

ApiConnector simply wraps Axios requests thus all Axios configurations are still available.
You can create an ApiConnector instance with common axios configurations:

const generalAxiosConfigs = { base_url: 'http://localhost' };
const connector = ApiConnector.create(generalAxiosConfigs);

And/or pass the Axios configuration object directly to the request through config parameter:

const axiosConfigs = { timeout: 1000 };
const response = await connector.reqGet('/test', {param1: 'test'}, axiosConfigs).start();

Or pass configured Axios instance directly to the request through apiConfigs parameter:

const response = await connector.reqGet('/test', {param1: 'test'}, {}, { axios: anyAxiosInstance }).start();

Response validation

ApiConnector has a mechanism to determine the successfulness of the response.
By default all completed responses are considered as successful.
You can change this logic by setting a validation function. This function should accept the Axios response object and return true if response is successful and false otherwise. Specify validation function for ApiConnector instance:

const testConnector = ApiConnector.create(
  {baseURL: 'http://localhost/api'},
  response => response.data.result === 'OKAY'
);
const response = await testConnector.reqGet('/test')
                    .onOk(() => console.log('Success')) // will be called on { result: 'OKAY' ... } response
                    .onFail(() => console.log('Fail'))
                    .start();

or specify validation function only for a single request:

const axiosInstance = Axios.create({ baseURL: 'http://localhost/api/v2'});
const response = await testConnector.reqGet(
                        '/test', 
                        params, 
                        null,
                        { 
                          axios: axiosInstance,
                          validateFunc: response => response.data.result === 'OK' 
                        }
                    )
                    .onOk(() => console.log('Success')) // will be called on { result: 'OK' ... } response
                    .onFail(() => console.log('Fail'))
                    .start();

Event handling

Basic events

ApiConnector allows you to attach callbacks to the following basic events:

  • onOk - successful API response;
  • onFail - failed API response;
  • onCancel - request cancellation;
  • onError - exception;
  • onStatus - status code.

There are two ways to attach callbacks to any of the above events. The simplest one - call a method with the same name:

ApiConnector.reqGet('http://localhost')
            .onOk(processResponse)
            .onFail(alertError)
            .onCancel(alertError)
            .onError(alertError)
            .onStatus(logout, 401, 403)

Another way to attach callbacks - use onAny method:

ApiConnector.reqGet('http://localhost')
            .onAny(processResponse, 'onOk')
            .onAny(alertError, 'onFail', 'onCancel', 'onError')
            .onAny(authorizeResponse, 'onStatus=[401, 403]');

Combined events

For convenience there are combined events that represents a different combinations of the basic events:

  • onResponse - combines onOk and onFail events
  • onAnyError - combines onFail, onCancel, onError events
  • then - combines onOk, onFail, onCancel, onError events

Callbacks to the combined events could be attached only by calling a method with the same name:

ApiConnector.reqGet('http://localhost')
            .onResponse(processResponse)
            .onAnyError(alertError)
            .then(sayGoodbye);

the code above is equivalent to:

ApiConnector.reqGet('http://localhost')
            .onAny(processResponse, 'onOk', 'onFail')
            .onAny(alertError, 'onFail', 'onCancel', 'onError')
            .onAny(sayGoodbye, 'onOk', 'onFail', 'onCancel', 'onError');

Multiple handlers

You could attach multiple callbacks on the same event, all these callbacks will be fired in order in which they were added.
The result from the previous callback will be passed to the next one:

const result = await ApiConnector.reqGet('http://localhost')
                                 .onOk(() => 'Hello,')
                                 .onOk(hello => hello + ' World')
                                 .then(helloWorld => helloWorld + '!')
                                 .start();
console.log(result); // 'Hello, world!'                                 

Post-handlers

Event callbacks could be attached after a request start:

const request = ApiConnector.reqGet('http://localhost');
await request.onOk(() => 'Hello, World!')
             .start();
request.onOk(res => console.log(res));  // 'Hello, World!'

Promised ApiRequest

Promised ApiRequest returns a Promise that:

  • resolves with the result of the last onOk event handler;
  • on onFail event throws the following Error:
    {
      isFail: true,
      data: any // result of the last onFail callback 
    }
  • on onCancel event throws the following Error:
    {
      isCancel: true,
      data: any // result of the last onCancel callback 
    }
  • on onError event throws the result of the last onError callback.

Example:

try {
  const response = await ApiConnector.reqGet('http://localhost')
                                     .onOk(() => 'Ok')
                                     .onFail(() => 'Failed')
                                     .onCancel(() => 'Cancelled')
                                     .onError(() => 'Error')
                                     .start();
  console.log(response); // 'Ok'
} catch (err) {
  if (err.isFail) {
    console.log(err.data); // 'Failed'
  } else if (err.isCancel) {
    console.log(err.data); // 'Cancelled'
  } else {
    console.log(err);  // 'Error'
  }
}

Request cancellation

Manual request cancellation

You could cancel request manually by calling the cancel method:

const request = ApiConnector.reqGet('http://localhost')
                            .onCancel(() => console.log('Cancelled'));
setTimeout(() => request.cancel(), 100);
request.start();

startQuietly/startSingleQuietly methods returns Axios request cancellation functions:

const cancel = ApiConnector.reqGet('http://localhost')
                           .onCancel(() => console.log('Cancelled'))
                           .startQuietly();
cancel();

Automatic request cancellation

startSingle method performs new Axios request and cancels previous pending requests with the same method, url and identifier:

ApiConnector.reqGet('http://localhost', { param1: 1}).start('same');
ApiConnector.reqGet('http://localhost', { param1: 1}).startSingle('same');  // will cancel previous request
ApiConnector.reqGet('http://localhost', { param1: 1}).startSingle('different');  // will NOT cancel any requests, because request identifiers are different
ApiConnector.reqGet('http://localhost', { param1: 2}).startSingle('different');  // will NOT cancel any requests, because request parameters are different

SDK example

Assume:

  1. you have an API with base url: https://example.com/api;
  2. all successful responses have the following format: { status: 'success', result: *};
  3. all failed responses have the following format: { status: 'fail', message: ''};
  4. there are GET /users and DELETE /user?name={name} endpoints;
  5. SDK users should get only result response field value;
  6. on error SDK should log error or message response field.

Sample SDK:

import ApiConnector from 'api-connector';

const api = ApiConnector.create(
        { baseURL: 'https://example.com/api' }, // 1.
        response => response.data.status === 'success'  // 2.
    );

function addCommonHandlers(apiRequest) {
    return apiRequest.onOk(response => response.data.result)  // 5.
                     .onFail(response => response.data.message);  // 6.
}

const SDK = {
    getUsers: async () => await addCommonHandlers(api.reqGet('/users')).start(),
    deleteUser: async (username) => await addCommonHandlers(api.reqDelete('/user', { name: username })),
}; // 4.

try {
    const users = await SDK.getUsers();
    console.log('Total users count: ', users.length);

    await SDK.deleteUser('John');
} catch (e) {
    if (e.isFail) {
      console.log(e.data);
    } else if (!e.isCancel) {
      console.log(e);
    }
}

ApiConnector API

.create(configs?, validateFunc?)

Create ApiConnector with Axios configs:

myApiConn = ApiConn.create({baseURL: 'https://example.com'});

Provided validate function will be used in response status evaluation:

myApiConn = ApiConn.create({}, response => response.data.status === 'ok');

.request(axiosConfig, apiConfig)

Creates and returns ApiRequest using Axios request configs and ApiConnector request configs.

req = ApiConn.request({method: 'GET', url: 'https://example.com'}, { validateFunc: response => !!response.data });

.req* Aliases

For convenience aliases have been provided for some request methods:

.reqGet(url, params?, axiosConfig?, apiConfig?)
.reqPost(url, data?, params?, axiosConfig?, apiConfig?)
.reqPatch(url, data?, params?, axiosConfig?, apiConfig?)
.reqPut(url, data?, params?, axiosConfig?, apiConfig?)
.reqDelete(url, params?, axiosConfig?, apiConfig?)

These methods just calls .request method, e.g, .reqPost is equal to ApiConn.request({method: 'POST', url, data, params, ...config}, apiConfig).

ApiRequest API

start(identifier='')

Performs http request. Returns a Promise:

  • onOk event will resolve the Promise with a data returned by the last onOk handler.
  • onFail event will reject the Promise with the following Error:
    {
      isFail: true,
      data: any // result of the last onFail callback 
    }
  • onCancel event will reject the Promise with the following Error:
    {
      isCancel: true,
      data: any // result of the last onCancel callback 
    }
  • onError event will reject the Promise with the result of the last onError callback.

startSingle(identifier='')

Similar to start method but cancels previous pending requests with the same method, url and identifier.

.on* event callbacks

You can attach callbacks to the following events

  • successful API response (.onOk)
  • failed API response (.onFail)
  • any API response (.onResponse)
  • request cancellation (.onCancel)
  • exception (.onError)
  • after any of the above (.then)
  • after failed API response, or cancellation, or exception (onAnyError)
  • status code (.onStatus)
  • any event combination (.onAny)
.onAny(callback, ...eventNames)

Attaches callback to all given events.
Supported event names: 'onOk', 'onFail', 'onCancel', 'onError', 'onStatus={status}', 'onStatus=[{status1}, {status2}]'.
All unsupported event names will be ignored.

Attach callback to request cancellation and response with status code 401:

await ApiConn.reqGet('https://example.com')
             .onAny(callback, 'onCancel', 'onStatus=401')
             .start();
.onStatus(callback, ...statuses)

Adds callback to response with exact status code.

Attach callback to responses with 201 and 202 status codes.

await ApiConn.reqGet('https://example.com')
             .onStatus(callback, 201, '202')
             .start();

License

MIT License

Versions

Current Tags

  • Version
    Downloads (Last 7 Days)
    • Tag
  • 1.2.1
    7
    • latest

Version History

Package Sidebar

Install

npm i api-connector

Weekly Downloads

9

Version

1.2.1

License

MIT

Unpacked Size

37.7 kB

Total Files

6

Last publish

Collaborators

  • iliyasappazov