rws-js-client
Version:
client for RWS frontend
241 lines (194 loc) • 8.26 kB
text/typescript
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( 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 };