@bunq-community/bunq-js-client
Version:
[ ](https://www.npmjs.com/package/@bunq-community/bunq-js-client) [ ](https://www.npmjs.com/p
187 lines (186 loc) • 8.09 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const CustomError_1 = require("./Interfaces/CustomError");
const RequestLimitFactory_1 = require("./RequestLimitFactory");
const Request_1 = require("./HTTP/Request");
const SignRequestHandler_1 = require("./HTTP/SignRequestHandler");
const EncryptRequestHandler_1 = require("./HTTP/EncryptRequestHandler");
const VerifyResponseHandler_1 = require("./HTTP/VerifyResponseHandler");
const ErrorCodes_1 = require("./Helpers/ErrorCodes");
exports.BUNQ_SERVER_SIGNATURE_HEADER_KEY = "X-Bunq-Server-Signature";
exports.BUNQ_REQUEST_SIGNATURE_HEADER_KEY = "X-Bunq-Client-Signature";
exports.BUNQ_REQUEST_AUTHENTICATION_HEADER_KEY = "X-Bunq-Client-Authentication";
class ApiAdapter {
constructor(Session, loggerInterface, BunqJSClient) {
/**
* Checks if the session is valid and waits for it to be refreshed
* @returns {Promise<void>}
*/
this.sessionValidationCheck = async () => {
// check if a new session is being fetched
if (this.BunqJSClient.fetchingNewSession) {
// wait for the new session to be loaded
await this.BunqJSClient.fetchingNewSession;
}
else {
// check if keepAlive is enabled and continue if it isn't
if (this.BunqJSClient.keepAlive === false) {
// check if a valid session is set
await this.BunqJSClient.registerSession();
}
}
// calculate amount of milliseconds until expire time
const expiresInMilliseconds = this.BunqJSClient.calculateSessionExpiry();
if (expiresInMilliseconds < 30000) {
// this request will extend the expiry timer
const extendByMilliseconds = this.BunqJSClient.calculateSessionExpiry(true);
// add milliseconds to current time
const currentDate = new Date();
currentDate.setTime(currentDate.getTime() + extendByMilliseconds);
// set updated session expiry time
this.Session.sessionExpiryTime = currentDate;
this.logger.debug(`Request in last 30 seconds: (${expiresInMilliseconds / 1000})`);
this.logger.debug(`Set session expiry to ${this.Session.sessionExpiryTime}`);
}
};
this.Session = Session;
this.logger = loggerInterface;
this.BunqJSClient = BunqJSClient;
this.RequestLimitFactory = new RequestLimitFactory_1.default(this.logger);
this.SignRequestHandler = new SignRequestHandler_1.default(this.Session, this.logger, this.BunqJSClient);
this.EncryptRequestHandler = new EncryptRequestHandler_1.default(this.Session, this.logger, this.BunqJSClient);
this.VerifyResponseHandler = new VerifyResponseHandler_1.default(this.Session, this.logger, this.BunqJSClient);
this.language = "en_US";
this.region = "nl_NL";
this.geoLocation = "0 0 0 0 000";
}
async setup() { }
/**
* @param {string} url
* @param headers
* @param {ApiAdapterOptions} options
* @param {AxiosInstance | false} axiosInstance
* @returns {Promise<void>}
*/
async get(url, headers = {}, options = {}, axiosInstance = false) {
const response = await this.request(url, "GET", "", headers, options, axiosInstance);
return response.data;
}
/**
* @param {string} url
* @param headers
* @param {ApiAdapterOptions} options
* @param {AxiosInstance | false} axiosInstance
* @returns {Promise<void>}
*/
async delete(url, headers = {}, options = {}, axiosInstance = false) {
const response = await this.request(url, "DELETE", {}, headers, options, axiosInstance);
return response.data;
}
/**
* @param {string} url
* @param data
* @param headers
* @param {ApiAdapterOptions} options
* @param {AxiosInstance | false} axiosInstance
* @returns {Promise<void>}
*/
async post(url, data = {}, headers = {}, options = {}, axiosInstance = false) {
const response = await this.request(url, "POST", data, headers, options, axiosInstance);
return response.data;
}
/**
* @param {string} url
* @param data
* @param headers
* @param {ApiAdapterOptions} options
* @param {AxiosInstance | false} axiosInstance
* @returns {Promise<void>}
*/
async put(url, data = {}, headers = {}, options = {}, axiosInstance = false) {
const response = await this.request(url, "PUT", data, headers, options, axiosInstance);
return response.data;
}
/**
* @param {string} url
* @param {string} method
* @param data
* @param headers
* @param {ApiAdapterOptions} options
* @param {AxiosInstance | false} axiosInstance
* @returns {Promise<any>}
*/
async request(url, method = "GET", data = {}, headers = {}, options = {}, axiosInstance = false) {
// default to standard axios instance
if (!axiosInstance)
axiosInstance = axios_1.default;
if (!options.axiosOptions)
options.axiosOptions = {};
const paramsString = options.axiosOptions.params ? JSON.stringify(options.axiosOptions.params) : "";
this.logger.debug(`${method}: ${url} ${paramsString}`);
const request = new Request_1.default(url, method, data, headers, options.axiosOptions);
if (!options.skipSessionCheck) {
await this.sessionValidationCheck();
}
if (options.disableAuthentication !== true) {
// use session token or fallback to install taken if we have one
if (this.Session.sessionToken !== null) {
request.setAuthenticated(this.Session.sessionToken);
}
else if (this.Session.installToken !== null) {
request.setAuthenticated(this.Session.installToken);
}
}
if (options.isEncrypted === true) {
await this.EncryptRequestHandler.encryptRequest(request, options);
}
if (options.disableSigning !== true) {
await this.SignRequestHandler.signRequest(request, options);
}
// complete relative urls
if (request.url[0] === "/") {
request.setUrl(`${this.Session.environmentUrl}${request.url}`);
}
let response;
try {
response = await axiosInstance.request(request.requestConfig);
}
catch (error) {
this.requestErrorHandler(error);
}
if (options.disableVerification !== true) {
const verifyResult = await this.VerifyResponseHandler.verifyResponse(response);
if (!verifyResult && (!process.env.ENV_CI || process.env.ENV_CI === "false")) {
// invalid response in a non-ci environment
throw new CustomError_1.default("We couldn't verify the received response", response, ErrorCodes_1.default.INVALID_RESPONSE_RECEIVED);
}
}
try {
// attempt to turn string result back into json when possible
response.data = JSON.parse(response.data);
return response;
}
catch (error) { }
return response;
}
/**
* Attempts to improve the error data and defaults to rethrowing it
* @param error
*/
requestErrorHandler(error) {
// get the data from the request if it fails
if (error.response && error.response.data) {
// parse json response if possible
try {
// attempt to turn string result back into json when possible
error.response.data = JSON.parse(error.response.data);
throw error;
}
catch (error) { }
}
// rethrow if no json data could be found
throw error;
}
}
exports.default = ApiAdapter;