All files / src api_method.ts

100% Statements 21/21
100% Branches 26/26
100% Functions 3/3
100% Lines 21/21

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93                                              12x 12x     12x 1798x                       10x   10x 4x         6x               6x 5x     4x     5x 5x 1x     4x               3x           3x 2x 1x   1x       3x    
/*
 * Copyright © 2019 Lisk Foundation
 *
 * See the LICENSE file at the top-level directory of this distribution
 * for licensing information.
 *
 * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation,
 * no part of this software, including this file, may be copied, modified,
 * propagated, or distributed except according to the terms contained in the
 * LICENSE file.
 *
 * Removal or modification of this copyright notice is prohibited.
 *
 */
import { AxiosRequestConfig } from 'axios';
 
import {
	APIHandler,
	APIResponse,
	HashMap,
	RequestConfig,
	Resource,
} from './api_types';
import { GET } from './constants';
import { solveURLParams, toQueryString } from './utils';
 
// Bind to resource class
export const apiMethod = (options: RequestConfig = {}): APIHandler =>
	async function apiHandler(
		this: Resource,
		// tslint:disable-next-line readonly-array
		...args: Array<number | string | object>
	): Promise<APIResponse> {
		const {
			method = GET,
			path = '',
			urlParams = [],
			validator,
			defaultData = {},
			retry = false,
		} = options;
 
		if (urlParams.length > 0 && args.length < urlParams.length) {
			throw new Error(
				`This endpoint must be supplied with the following parameters: ${urlParams.toString()}`,
			);
		}
 
		const data = {
			...defaultData,
			...(args.length > urlParams.length &&
			typeof args[urlParams.length] === 'object'
				? (args[urlParams.length] as object)
				: {}),
		};
 
		if (validator) {
			validator(data);
		}
 
		const resolvedURLObject = urlParams.reduce(
			// tslint:disable-next-line no-inferred-empty-object-type
			(accumulator: HashMap, param: string, i: number): HashMap => {
				const value = args[i];
				if (typeof value !== 'string' && typeof value !== 'number') {
					throw new Error('Parameter must be a string or a number');
				}
 
				return {
					...accumulator,
					[param]: typeof value === 'number' ? value.toString() : value,
				};
			},
			{},
		);
 
		const requestData: AxiosRequestConfig = {
			headers: this.headers,
			method,
			url: solveURLParams(`${this.resourcePath}${path}`, resolvedURLObject),
		};
 
		if (Object.keys(data).length > 0) {
			if (method === GET) {
				requestData.url += `?${toQueryString(data)}`;
			} else {
				requestData.data = data;
			}
		}
 
		return this.request(requestData, retry);
	};