Files
web2.0-frontend/src/api/backend.ts
T
2022-07-21 21:11:32 +03:00

132 lines
3.7 KiB
TypeScript

import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { getAccessTokenCookie } from "@utils/auth";
const axiosInstance: AxiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
});
export enum APIPath {
TAGS = "/tags/:id",
EVENTS = "/events/:id",
FEED = "/feed/:id",
JOBADS = "/jobads/:id",
SIGNUPS = "/signup/:id",
SIGNUPS_EDIT = "/signup/:id/edit",
SIGNUP_FORMS = "/signupForm/:id",
SIGNUP_FORMS_EMAIL = "/signupForm/:id/sendemail",
SIGNUP_FORMS_SIGNUPS = "/signupForm/:id/signups",
AUTH_TOKEN_GENERATE = "/token",
AUTH_TOKEN_VERIFY = "/token/verify",
AUTH_TOKEN_REFRESH = "/token/refresh",
}
export type API = {
path: APIPath;
urlParams?: {
id?: string | number;
};
queryParams?: {
limit?: number;
offset?: number;
since?: Date;
uuid?: string;
};
authenticated?: boolean;
};
type Headers = {
Authorization?: string;
};
const getAuthHeader = (): string => {
const jwt = getAccessTokenCookie();
return `Bearer ${jwt}`;
};
const getHeaders = (auth?: boolean): Headers => {
if (auth) {
return {
Authorization: getAuthHeader(),
};
}
return {};
};
const fillUrlParams = (apiPath: APIPath, params: API["urlParams"] = {}): string => {
const path = apiPath
.split("/")
.map((urlComponent) => {
// fill in each placeholder component like ':id' with value from params
if (urlComponent.startsWith(":")) {
const key = urlComponent.substring(1);
const value = params[key] ?? "";
return value;
}
return urlComponent;
})
.filter(Boolean)
.join("/");
// code above strips leading and trailing '/' from path
return `/${path}/`;
};
const callBackendAPI = async <RequestType, ResponseType>(
path: APIPath,
urlParams: API["urlParams"],
queryParams: API["queryParams"],
method: AxiosRequestConfig["method"],
headers: Headers,
requestBody: RequestType,
): Promise<ResponseType> => {
const url = fillUrlParams(path, urlParams);
const request: AxiosRequestConfig = {
url,
method,
headers,
params: queryParams,
data: requestBody,
responseType: "json",
};
const response = await axiosInstance.request<ResponseType>(request);
const arrayResp = (response.data as { results?: ResponseType });
if (Array.isArray(arrayResp.results)) {
return arrayResp.results;
}
return response.data;
};
export const getBackendAPI = async <ResponseType>({
path, urlParams, queryParams, authenticated,
}: API): Promise<ResponseType> => {
const headers = getHeaders(authenticated);
return callBackendAPI<undefined, ResponseType>(path, urlParams, queryParams, "GET", headers, undefined);
};
export const postBackendAPI = async <RequestType, ResponseType>({
path, urlParams, queryParams, authenticated,
}: API, body: RequestType): Promise<ResponseType> => {
const headers = getHeaders(authenticated);
return callBackendAPI<RequestType, ResponseType>(path, urlParams, queryParams, "POST", headers, body);
};
export const putBackendAPI = async <RequestType, ResponseType>({
path, urlParams, queryParams, authenticated,
}: API, body: RequestType): Promise<ResponseType> => {
const headers = getHeaders(authenticated);
return callBackendAPI<RequestType, ResponseType>(path, urlParams, queryParams, "PUT", headers, body);
};
export const deleteBackendAPI = async <ResponseType>({
path, urlParams, queryParams, authenticated,
}: API): Promise<ResponseType> => {
const headers = getHeaders(authenticated);
return callBackendAPI<undefined, ResponseType>(path, urlParams, queryParams, "DELETE", headers, undefined);
};
export const fetcher = <ResponseType>({
path, urlParams, queryParams, authenticated,
}: API) => getBackendAPI<ResponseType>({
path, urlParams, queryParams, authenticated,
});