import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'; import qs from 'qs'; export interface ActionParams { filterByTk?: any; [key: string]: any; } type ResourceActionOptions

= { resource?: string; resourceOf?: any; action?: string; params?: P; }; export interface IResource { list?: (params?: ActionParams) => Promise; get?: (params?: ActionParams) => Promise; create?: (params?: ActionParams) => Promise; update?: (params?: ActionParams) => Promise; destroy?: (params?: ActionParams) => Promise; [key: string]: (params?: ActionParams) => Promise; } class Auth { protected api: APIClient; protected token: string; protected role: string; constructor(api: APIClient) { this.api = api; this.api.axios.interceptors.request.use((config) => { config.headers['X-Hostname'] = window.location.hostname; if (this.role) { config.headers['X-Role'] = this.role; } if (this.token) { config.headers['Authorization'] = `Bearer ${this.token}`; } return config; }); } setToken(token: string) { this.token = token; } setRole(role: string) { this.role = role; } async signIn(values) { const response = await this.api.request({ method: 'post', url: 'users:signin', data: values, }); const data = response?.data?.data; this.token = data; return data; } async signOut() { await this.api.request({ method: 'post', url: 'users:signout', }); this.token = null; } } export class APIClient { axios: AxiosInstance; auth: Auth; constructor(instance?: AxiosInstance | AxiosRequestConfig) { if (typeof instance === 'function') { this.axios = instance; } else { this.axios = axios.create(instance); } this.auth = new Auth(this); this.qsMiddleware(); } qsMiddleware() { this.axios.interceptors.request.use((config) => { config.paramsSerializer = (params) => { return qs.stringify(params, { strictNullHandling: true, arrayFormat: 'brackets', }); }; return config; }); } request, D = any>(config: AxiosRequestConfig | ResourceActionOptions): Promise { const { resource, resourceOf, action, params } = config as any; if (resource) { return this.resource(resource, resourceOf)[action](params); } return this.axios.request(config); } resource(name: string, of?: any): IResource { const target = {}; const handler = { get: (_: any, actionName: string) => { let url = name.split('.').join(`/${of || '_'}/`); url += `:${actionName}`; const config: AxiosRequestConfig = { url }; if (['get', 'list'].includes(actionName)) { config['method'] = 'get'; } else { config['method'] = 'post'; } return async (params?: ActionParams) => { const { values, filter, ...others } = params || {}; config['params'] = others; if (filter) { if (typeof filter === 'string') { config['params']['filter'] = filter; } else { config['params']['filter'] = JSON.stringify(filter); } } if (config.method !== 'get') { config['data'] = values || {}; } return await this.request(config); }; }, }; return new Proxy(target, handler); } }