@ima/plugin-http-client
Version:
Generic http client for the IMA application framework.
152 lines (151 loc) • 4.75 kB
JavaScript
import { GenericError } from '@ima/core';
import { HttpClient } from '../HttpClient';
/**
* AbstractResource will help with creating paths to the API as well as working with entities.
*/ export class AbstractResource {
#httpClient;
#baseApiUrl;
static get $dependencies() {
return [
HttpClient,
'$Settings.plugin.httpClient.rest'
];
}
/**
* PathType is set of constant for use in getter path
* @class
*/ static get PathType() {
return {
GET: 'get',
CREATE: 'create',
UPDATE: 'update',
REPLACE: 'replace',
DELETE: 'delete'
};
}
/**
* This getter should return paths to API for concrete PathType
*/ get path() {
throw new GenericError(`AbstractResource: getter "path" must be overriden.`);
}
/**
* Optionally getter for EntityProcessor
*/ get entityClass() {
return null;
}
constructor(httpClient, settings){
this.#httpClient = httpClient;
if (!settings?.baseApiUrl) {
throw new GenericError(`$Settings.plugin.httpClient.rest.baseApiUrl is not set.`);
}
this.#baseApiUrl = settings.baseApiUrl;
}
getBaseApiUrl() {
return this.#baseApiUrl;
}
update(data, options, pathType = this.constructor.PathType.UPDATE) {
return this.#restClientRequest('patch', pathType, data, options);
}
create(data, options, pathType = this.constructor.PathType.CREATE) {
return this.#restClientRequest('post', pathType, data, options);
}
delete(data, options, pathType = this.constructor.PathType.DELETE) {
return this.#restClientRequest('delete', pathType, data, options);
}
get(data, options, pathType = this.constructor.PathType.GET) {
return this.#restClientRequest('get', pathType, data, options);
}
replace(data, options, pathType = this.constructor.PathType.REPLACE) {
return this.#restClientRequest('put', pathType, data, options);
}
/**
* Method invalidate cache for given params
* @param method
* @param data
* @param pathType
*/ invalidateCache(method, data, pathType) {
const url = this.getUrl(pathType, data);
this.#httpClient.invalidateCache(method, url, this.prepareData(data));
}
/**
* Return pathTemplate by pathType
*
* @param pathType
* @private
*/ #getPathTemplate(pathType) {
const pathTemplate = this.path[pathType];
if (!pathTemplate) {
throw new GenericError(`AbstractResource: getter "path" does not contain '${pathType}' pathType in ${this.constructor.name}`);
}
return pathTemplate;
}
/**
* Create URL to API by baseApiUrl settings and processed path
*
* @param pathType
* @param data
*/ getUrl(pathType, data) {
const pathTemplate = this.#getPathTemplate(pathType);
const path = this.processPathTemplate(pathTemplate, data);
return this.getBaseApiUrl() + path;
}
/**
* Prepare data for request
* @param data
*/ prepareData(data) {
return {
...data
};
}
/**
* Prepare options for request
* @param options
*/ prepareOptions(options) {
return {
...options
};
}
/**
* Process path - replace variables by values from data.
*
* @param pathTemplate
* @param data
* @private
*/ processPathTemplate(pathTemplate, data) {
let path = pathTemplate;
const regexFindVariables = new RegExp('{(.*?)}', 'g');
const keys = [];
let matches;
while(matches = regexFindVariables.exec(pathTemplate)){
keys.push(matches[1]);
}
keys.forEach((key)=>{
if (key === undefined || !(key in data)) {
throw new GenericError(`AbstractResource: No attribute of key {${key}} found in data in ${this.constructor.name}.`);
}
path = path.replace(`{${key}}`, data[key]);
delete data[key];
});
return path;
}
async #restClientRequest(method, pathType, data, options) {
const url = this.getUrl(pathType, data);
const { response } = await this.#httpClient.request({
method,
url,
data: this.prepareData(data),
options: this.prepareOptions(options)
}, this.getResourceInfo(pathType));
return response;
}
/**
* Returns additionalParams for processors
* @param pathType
*/ getResourceInfo(pathType) {
return {
resource: this,
pathType
};
}
}
//# sourceMappingURL=AbstractResource.js.map