UNPKG

@protorians/air-rest

Version:
321 lines (157 loc) 5.11 kB
import type { IAirRestServer, IAirRestEndPoint, IAirMethods, IEndpointPayload, IEndpointResponse } from "./types"; export function stringifyPayload(payload: IEndpointPayload): string[] { const out: string[] = []; Object.entries(payload).forEach(({ 0: key, 1: value }) => { if (typeof value == 'object') { out[out.length] = (`${key}=${encodeURIComponent(JSON.stringify(value))}`); } else { out[out.length] = (`${key}=${encodeURIComponent(value)}`); } }); return out } export function render<R extends IEndpointResponse>( endpoint: RequestInfo, options: RequestInit | undefined ) { return new Promise<R>((done, fail) => { fetch(endpoint, { ...options }) .then(r => r.json()) .then(data => done(data as R)) .catch(er => fail(er)) }) } export function useEndpoint<P extends IEndpointPayload, R extends IEndpointResponse>() { return new AirRestEndPoint<P, R>(); } /** * Création d'un point de chute */ export class AirRestEndPoint<P extends IEndpointPayload, R extends IEndpointResponse> implements IAirRestEndPoint<P, R>{ #rest: IAirRestServer | undefined = undefined; #route: string | number = ''; #payload: P | FormData = {} as (P | FormData); #method: IAirMethods = 'GET'; #transpilate: boolean = true; get _route() { return this.#route; } get _payload() { return this.#payload; } get _method() { return this.#method; } get _transpilate() { return this.#transpilate; } /** * Utilisation avec un serveur de points de chutes * @param rest */ use(rest: IAirRestServer) { this.#rest = rest; return this; } method(method: IAirMethods) { this.#method = method; return this; } route(route: string | number) { this.#route = route; return this; } useForm(form: HTMLFormElement) { const data = new FormData(form) this.#transpilate = false; this.#payload = data; return this; } useFormData(formData: FormData) { this.#transpilate = false; this.#payload = formData; return this; } slugs(...slugs: (string | number)[]) { slugs.forEach((slug, key) => { key++; this.#route = this._route.toString().replace(new RegExp(`\\$${key}`, 'gi'), `${slug}`) }) return this; } payload(payload: P) { this.#payload = payload; return this; } send(): Promise<R> | undefined { switch (this._method) { case 'POST': return this.#rest?.post<R>(this); case 'PUT': return this.#rest?.put<R>(this); case 'PATCH': return this.#rest?.patch<R>(this); case 'DELETE': return this.#rest?.delete<R>(this); default: return this.#rest?.get<R>(this); } } } export function transpilatePayload(payload?: object): BodyInit { const formData = new FormData(); if (payload) { Object.entries(payload).forEach(({ 0: name, 1: value }) => formData.append(name, value) ) } return formData; } export class AirRestServer implements IAirRestServer { server: string; options: RequestInit | undefined; constructor(server: string, options: RequestInit | undefined) { this.server = server; this.options = options; } get<R extends IEndpointResponse>(endpoint: IAirRestEndPoint<IEndpointPayload, R>) { const query = endpoint._payload ? stringifyPayload(endpoint._payload).join('&') : ''; return render<R>( `${this.server}${endpoint._route as string}${endpoint._payload ? "?" + query : ''}`, { ...this.options, method: 'GET', } ) } post<R extends IEndpointResponse>(endpoint: IAirRestEndPoint<IEndpointPayload, R>): Promise<R> { return render<R>( `${this.server}${endpoint._route as string}`, { ...this.options, method: 'POST', body: endpoint._transpilate ? transpilatePayload(endpoint._payload) : (endpoint._payload as BodyInit), } ) } put<R extends IEndpointResponse>(endpoint: IAirRestEndPoint<IEndpointPayload, R>) { return render<R>( `${this.server}${endpoint._route as string}`, { ...this.options, method: 'PUT', body: endpoint._transpilate ? transpilatePayload(endpoint._payload) : (endpoint._payload as BodyInit), } ) } patch<R extends IEndpointResponse>(endpoint: IAirRestEndPoint<IEndpointPayload, R>) { return render<R>( `${this.server}${endpoint._route as string}`, { ...this.options, method: 'PATCH', body: endpoint._transpilate ? transpilatePayload(endpoint._payload) : (endpoint._payload as BodyInit), } ) } delete<R extends IEndpointResponse>(endpoint: IAirRestEndPoint<IEndpointPayload, R>) { return render<R>( `${this.server}${endpoint._route as string}`, { ...this.options, method: 'DELETE', body: endpoint._transpilate ? transpilatePayload(endpoint._payload) : (endpoint._payload as BodyInit), }) } } export default class AirRest { static Server = AirRestServer; static Endpoint = AirRestEndPoint; }