Files
chatwoot/app/javascript/dashboard/api/ApiClient.js
T
2024-11-27 11:05:06 -08:00

153 lines
3.7 KiB
JavaScript

/* global axios */
const DEFAULT_API_VERSION = 'v1';
const DEFAULT_OPTIONS = {
apiVersion: DEFAULT_API_VERSION,
enterprise: false,
accountScoped: false,
cancelPreviousRequests: false,
};
class ApiClient {
constructor(resource, options = {}) {
this.options = { ...DEFAULT_OPTIONS, ...options };
this.apiVersion = `/api/${this.options.apiVersion}`;
this.resource = resource;
this.abortControllers = new Map();
this.activeRequests = new Map();
}
get url() {
return `${this.baseUrl()}/${this.resource}`;
}
// eslint-disable-next-line class-methods-use-this
get accountIdFromRoute() {
const isInsideAccountScopedURLs =
window.location.pathname.includes('/app/accounts');
if (isInsideAccountScopedURLs) {
return window.location.pathname.split('/')[3];
}
return '';
}
baseUrl() {
let url = this.apiVersion;
if (this.options.enterprise) {
url = `/enterprise${url}`;
}
if (this.options.accountScoped && this.accountIdFromRoute) {
url = `${url}/accounts/${this.accountIdFromRoute}`;
}
return url;
}
generateRequestKey(method, id = '', customRequestKey = '') {
if (customRequestKey) return customRequestKey;
return `${method}-${this.url}${id ? `/${id}` : ''}`;
}
cancelRequest(requestKey) {
const controller = this.abortControllers.get(requestKey);
if (controller) {
controller.abort();
this.abortControllers.delete(requestKey);
return true;
}
return false;
}
setupRequest(method, options = {}) {
if (!this.options.cancelPreviousRequests) {
return {};
}
const { id, customRequestKey } = options;
const requestKey = this.generateRequestKey(method, id, customRequestKey);
const previousRequests = this.activeRequests.get(method) || [];
const remainingRequests = previousRequests.filter(key => {
if (key === requestKey) {
this.cancelRequest(key);
return false;
}
return true;
});
this.activeRequests.set(method, [...remainingRequests, requestKey]);
const controller = new AbortController();
this.abortControllers.set(requestKey, controller);
return { requestKey, signal: controller.signal };
}
async request(method, config = {}) {
const { id, data, customRequestKey, ...axiosConfig } = config;
const { requestKey, signal } = this.setupRequest(method, {
id,
customRequestKey,
});
try {
const url = id ? `${this.url}/${id}` : this.url;
return await axios({
method,
url,
data,
signal,
...axiosConfig,
});
} finally {
this.abortControllers.delete(requestKey);
if (this.options.cancelPreviousRequests) {
const methodRequests = this.activeRequests.get(method) || [];
this.activeRequests.set(
method,
methodRequests.filter(key => key !== requestKey)
);
}
}
}
get(config = {}) {
return this.request('GET', config);
}
show(id, config = {}) {
return this.request('GET', { ...config, id });
}
create(data, config = {}) {
return this.request('POST', { ...config, data });
}
update(id, data, config = {}) {
return this.request('PATCH', { ...config, id, data });
}
delete(id, config = {}) {
return this.request('DELETE', { ...config, id });
}
cancelAllRequests() {
this.abortControllers.forEach(controller => controller.abort());
this.abortControllers.clear();
this.activeRequests.clear();
}
// Get all active request keys
getActiveRequests() {
return Array.from(this.abortControllers.keys());
}
destroy() {
this.cancelAllRequests();
}
}
export default ApiClient;