|
|
|
import {AuthenticationInterface} from "./authentication";
|
|
|
|
|
|
|
|
export enum Method {
|
|
|
|
GET = 'GET',
|
|
|
|
POST = 'POST',
|
|
|
|
PUT = 'PUT',
|
|
|
|
PATCH = 'PATCH',
|
|
|
|
}
|
|
|
|
|
|
|
|
export let hasQuery = (method: Method) => {
|
|
|
|
return Method.GET === method
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface SchemaInterface {
|
|
|
|
url: string,
|
|
|
|
method: Method
|
|
|
|
contentType: string | null
|
|
|
|
}
|
|
|
|
|
|
|
|
export class Context {
|
|
|
|
debouncing?: number
|
|
|
|
useMemory?: boolean
|
|
|
|
memoryKey?: string
|
|
|
|
}
|
|
|
|
|
|
|
|
interface SchemaClientOptionsInterface {
|
|
|
|
baseUrl?: string
|
|
|
|
authentication?: AuthenticationInterface
|
|
|
|
}
|
|
|
|
|
|
|
|
export class SchemaClient {
|
|
|
|
baseUrl: string | null = null
|
|
|
|
authentication: AuthenticationInterface | null = null
|
|
|
|
context: Context | null = null
|
|
|
|
|
|
|
|
memory: Record<string, any> = {}
|
|
|
|
|
|
|
|
constructor(options: SchemaClientOptionsInterface) {
|
|
|
|
this.baseUrl = options.baseUrl || null
|
|
|
|
this.authentication = options.authentication || null
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
if (this.baseUrl === null) {
|
|
|
|
throw new Error('Base url not defined!');
|
|
|
|
}
|
|
|
|
|
|
|
|
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]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let url = `${this.baseUrl}${schema.url}`
|
|
|
|
let {url: preparedUrl, data: preparedData} = this.processAttributes(url, data)
|
|
|
|
|
|
|
|
if (hasQuery(schema.method)) {
|
|
|
|
preparedUrl += '?' + new URLSearchParams(preparedData)
|
|
|
|
}
|
|
|
|
|
|
|
|
let token = ''
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
|
|
let tokenId = localStorage.getItem('token')
|
|
|
|
token = localStorage.getItem(tokenId || '') || ''
|
|
|
|
}
|
|
|
|
|
|
|
|
let headers: Record<string, any> = {
|
|
|
|
...(schema.contentType ? {'Content-Type': schema.contentType} : {}),
|
|
|
|
'X-Plugin-Token': 'passw0rd',
|
|
|
|
}
|
|
|
|
if (this.authentication) {
|
|
|
|
headers[this.authentication.key] = this.authentication.token();
|
|
|
|
}
|
|
|
|
let response = await fetch(preparedUrl, {
|
|
|
|
method: schema.method.toString(),
|
|
|
|
headers,
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|