export enum Method { GET = 'GET', POST = 'POST', PUT = 'PUT', PATCH = 'PATCH', } export let hasQuery = (method: Method) => { return Method.GET === method } export interface ClientOptions { baseUrl: string } export interface SchemaInterface { url: string, method: Method contentType: string | null } export class Context { debouncing?: number useMemory?: boolean memoryKey?: string } export class SchemaClient { baseUrl: string | null = null context: Context | null = null memory: Record = {} debouncing(time: number) { let context = this.grabContext() context.debouncing = time return this } useMemory(key?: string) { let context = this.grabContext() context.useMemory = true context.memoryKey = key return this } async send(schema: SchemaInterface, data: any) { let context = this.context this.context = null if (context?.useMemory) { let memoryKey = context?.memoryKey || schema.url if (typeof this.memory[memoryKey] !== 'undefined') { return this.memory[memoryKey] } } console.log('context', this.context, context) let url = `${this.baseUrl}${schema.url}` let {url: preparedUrl, data: preparedData} = this.processAttributes(url, data) if (hasQuery(schema.method)) { preparedUrl += '?' + new URLSearchParams(preparedData) } let response = await fetch(preparedUrl, { method: schema.method.toString(), headers: { ...(schema.contentType ? {'Content-Type': schema.contentType} : {}), 'X-Plugin-Token': 'passw0rd' }, body: hasQuery(schema.method) ? null : JSON.stringify(preparedData) }); let responseData = response.headers.get('Content-Type')?.toString().includes('application/json') ? await response.json() : await response.text() let result = {responseData: responseData, headers: response.headers} if (context?.useMemory) { let memoryKey = context?.memoryKey || schema.url this.memory[memoryKey] = result } return result } private processAttributes(url: string, data: any) { const preparedData = data for (const key in data) { if (url.indexOf('{' + key + '}') > -1) { url = url.replace('{' + key + '}', preparedData[key]) delete preparedData[key] } } return {url, data: preparedData } } private grabContext(): Context { if (this.context) { return this.context } return this.context = new Context() } }