@cargochain/sdk-js
Version:
The CargoChain platform allows application developers to build supply chain solutions that enable the secure distribution of cargo information among trusted partners.
154 lines (134 loc) • 4.73 kB
JavaScript
const Fetcher = require('./Fetcher');
const ReferenceDataClient = require('./ReferenceDataClient');
const ProfileClient = require('./ProfileClient');
const singleton = Symbol();
const singletonEnforcer = Symbol();
/**
* This singleton class represents the CargoChain JS client. In order to call the CargoChain API,
* you have to use the instance of this class by specifying the URL of the CargoChain API.
*/
class CargoChainClient {
constructor(enforcer) {
if (enforcer !== singletonEnforcer) {
throw new Error('Cannot construct singleton');
}
this._apiServerUrl = null;
this._accessToken = null;
this._profileClient = null;
this._referenceDataClient = null;
this._onAccessTokenExpired = null;
}
/**
* Gets the instance of this class.
* @returns {CargoChainClient} The instance.
* @example
* var client = CargoChainClient.instance;
*/
static get instance() {
if (!this[singleton]) {
this[singleton] = new CargoChainClient(singletonEnforcer);
}
return this[singleton];
}
/**
* Sets the CargoChain API url.
* @param {string} apiServerUrl - A string that represents the CargoChain API url.
*/
setUrl(apiServerUrl) {
if (apiServerUrl)
this._apiServerUrl = apiServerUrl.endsWith('/') ? apiServerUrl.substring(0, apiServerUrl.length - 1) : apiServerUrl;
else
this._apiServerUrl = null;
}
/**
* Gets the CargoChain API url.
*/
getUrl() {
return this._apiServerUrl;
}
/**
* Sets the access token used by the client.
* @param {string} value - The access token.
*/
setAccessToken(value) {
this._accessToken = value;
}
/**
* Gets the access token.
*/
getAccessToken() {
return this._accessToken;
}
/**
* Occurs when the Access Token has expired or is invalid.
* This event allows to generate and specify a new access token.
* @param {function} callback
*/
setOnAccessTokenExpiredHandler(callback) {
this._onAccessTokenExpired = callback;
}
/**
* Gets the ProfileClient.
* @returns {ProfileClient} An instance of the ProfileClient.
*/
get profile() {
if (!this._profileClient) {
this._profileClient = new ProfileClient(this);
}
return this._profileClient;
}
/**
* Gets the ReferenceDataClient.
* @returns {ReferenceDataClient} An instance of the ReferenceDataClient.
*/
get referenceData() {
if (!this._referenceDataClient) {
this._referenceDataClient = new ReferenceDataClient(this);
}
return this._referenceDataClient;
}
_getFetcher() {
return Fetcher;
}
_get(url, data) {
return this._sendRequestWithRetry(() => this._getFetcher().get(this._apiServerUrl + url, data, this.getAccessToken()));
}
_getPagedResponse(url, page, data) {
var params = Object.assign({}, data, page);
return this._sendRequestWithRetry(
() => this._getFetcher().get(this._apiServerUrl + url, params, this.getAccessToken()),
res => {
return {
data: res.data.data,
page: res.data.page,
isSuccess: res.isSuccess,
message: res.message,
statusCode: res.statusCode
};
});
}
_post(url, data) {
return this._sendRequestWithRetry(() => this._getFetcher().post(this._apiServerUrl + url, data, this.getAccessToken()));
}
_sendRequestWithRetry(request, formatter) {
if (!(formatter && {}.toString.call(formatter) === '[object Function]')) {
formatter = x => x;
}
return new Promise((resolve) => {
request().then((res) => {
if (!res.isSuccess && res.statusCode === 401) {
// Retry with new access token
if (this._onAccessTokenExpired && {}.toString.call(this._onAccessTokenExpired) === '[object Function]') {
this._onAccessTokenExpired();
request().then((res2) => {
resolve(formatter(res2));
});
}
} else {
resolve(formatter(res));
}
});
});
}
}
module.exports = CargoChainClient;