UNPKG

rws-js-client

Version:
241 lines (194 loc) 8.26 kB
import TheService from './_service'; //@4DI import ConfigService, { ConfigServiceInstance } from '../services/ConfigService'; import { upload, UploadResponse } from 'upload'; interface RequestOptions { method?: string; headers: HeadersInit; body?: string; } interface IAPIOptions { headers?: Headers, routeParams?: { [key: string]: string }, } interface IHTTProute { name: string; path: string; } interface IPrefixedHTTProutes { prefix: string; routes: IHTTProute[]; } type IBackendRoute = IHTTProute | IPrefixedHTTProutes; const _DEFAULT_CONTENT_TYPE = 'application/json'; class ApiServiceInstance extends TheService { private token?: string; constructor(@ConfigService private config: ConfigServiceInstance) { super(); } private addHeader(headers: Headers | [string, string][] | {[key: string]: string}, key: string, val: string) { if (headers instanceof Headers) { headers.append(key, val); } else if (Array.isArray(headers)) { headers.push([key, val]); } else { headers[key] = val; } } // Function to get headers private getHeaders(optHeaders: HeadersInit = {}): HeadersInit { const headers: HeadersInit = { ...optHeaders }; if (!('Content-Type' in headers)) { this.addHeader(headers, 'Content-Type', _DEFAULT_CONTENT_TYPE); } if (this.token) { this.addHeader(headers, 'Authorization', `Bearer ${this.token}`); } if(!!(headers as any)['Content-Type']){ this.addHeader(headers, 'Accept', '*/*'); }else{ this.addHeader(headers, 'Accept', (headers as any)['Content-Type']); } return headers; } public setToken(token: string) { this.token = token; } public async pureGet(url: string, options: IAPIOptions = {}): Promise<string> { try { const response = await fetch(url, { headers: this.getHeaders(options.headers), }); return await response.text(); } catch (error) { console.error('GET request failed:', error); throw error; } } public async isGetTargetReachable(url: string, options: IAPIOptions = {}): Promise<boolean> { try { return !!(await this.pureGet(url, options)); } catch (error) { return false; } } public async get<T>(url: string, options: IAPIOptions = {}): Promise<T> { try { const response = await fetch(url, { headers: this.getHeaders(options.headers), }); return await response.json(); } catch (error) { console.error('GET request failed:', error); throw error; } } public async post<T, P extends Object = {}>(url: string, payload?: P, options: IAPIOptions = {}): Promise<T> { try { const response = await fetch(url, { method: 'POST', headers: this.getHeaders(options.headers), body: payload ? JSON.stringify(payload) : null, }); return await response.json(); } catch (error) { console.error('POST request failed:', error); throw error; } } public async put<T, P extends Object = {}>(url: string, payload?: P, options: IAPIOptions = {}): Promise<T> { try { const response = await fetch(url, { method: 'PUT', headers: this.getHeaders(options.headers), body: payload ? JSON.stringify(payload) : null, }); return await response.json(); } catch (error) { console.error('PUT request failed:', error); throw error; } } public async delete<T>(url: string, options: IAPIOptions = {}): Promise<T> { try { const response = await fetch(url, { method: 'DELETE', headers: this.getHeaders(options.headers), }); return await response.json(); } catch (error) { console.error('DELETE request failed:', error); throw error; } } private getBackendUrl(routeName: string, params: {[key: string]: string} = {}) { const routesPackage = this.config.get('backendRoutes'); let routes: IHTTProute[] = []; routesPackage.forEach((item: IBackendRoute) => { // Check if item is an instance of IPrefixedHTTProutes if ('prefix' in item && 'routes' in item && Array.isArray(item.routes)) { // Handle the case where item is of type IPrefixedHTTProutes routes = [...routes, ...item.routes.map((subRouteItem: IHTTProute): IHTTProute => { const subRoute: IHTTProute = { path: item.prefix + subRouteItem.path, name: subRouteItem.name }; return subRoute; })]; } else { // Handle the case where item is of type IHTTProute routes.push(item as IHTTProute); } }); const route = routes.find((item: IHTTProute) => item.name === routeName); if(!route){ throw new Error(`Backend route '${routeName}' does not exist.`); } let apiPath = route.path; Object.keys(params).forEach((paramKey: string) => { const paramValue = params[paramKey]; apiPath = apiPath.replace(`:${paramKey}`, paramValue); }); return `${this.config.get('backendUrl')}${this.config.get('apiPrefix') || ''}${apiPath}`; } async uploadFile(url: string, file: File, onProgress: (progress: number) => void, options: IAPIOptions = {}): Promise<UploadResponse> { return upload( url, { file, }, { onProgress, headers: this.token ? { Authorization: `Bearer ${this.token}` } : null, } ); } public back = { get: <T>(routeName: string, options?: IAPIOptions): Promise<T> => this.get(this.getBackendUrl(routeName, options?.routeParams), options), post: <T, P extends Object = {}>(routeName: string, payload?: P, options?: IAPIOptions): Promise<T> => this.post(this.getBackendUrl(routeName, options?.routeParams), payload, options), put: <T, P extends Object = {}>(routeName: string, payload: P, options?: IAPIOptions): Promise<T> => this.put(this.getBackendUrl(routeName, options?.routeParams), payload, options), delete: <T>(routeName: string, options?: IAPIOptions): Promise<T> => this.delete(this.getBackendUrl(routeName, options?.routeParams), options), uploadFile: (routeName: string, file: File, onProgress: (progress: number) => void, options: IAPIOptions = {}): Promise<UploadResponse> => this.uploadFile(this.getBackendUrl(routeName, options?.routeParams), file, onProgress), }; connectToAmplify() { // "use client" // const client = generateClient<Schema>() // use this Data client for CRUDL requests // /*== STEP 3 =============================================================== // Fetch records from the database and use them in your frontend component. // (THIS SNIPPET WILL ONLY WORK IN THE FRONTEND CODE FILE.) // =========================================================================*/ // /* For example, in a React component, you can use this snippet in your // function's RETURN statement */ // // const { data: todos } = client.models.Todo.list() // // return <ul>{todos.map(todo => <li key={todo.id}>{todo.content}</li>)}</ul> } } export default ApiServiceInstance.getSingleton(); export { IBackendRoute, RequestOptions, ApiServiceInstance, IHTTProute, IPrefixedHTTProutes };