magnetar/fe_calckey/frontend/magnetar-common/src/be-api.ts

113 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-11-03 12:17:53 +00:00
import {FrontendApiEndpoint, FrontendApiEndpoints} from "./fe-api";
import {GetNoteById} from "./types/endpoints/GetNoteById";
type Method = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
export interface BackendApiEndpoint<M extends Method, T, R> {
method: M;
endpoint: string;
pathParams: [string],
request?: T;
response?: R;
}
function nestedUrlSearchParams(data: any, topLevel: boolean = true): string {
switch (typeof data) {
case "string":
case "bigint":
case "boolean":
case "number":
case "symbol":
if (topLevel)
return encodeURIComponent(data.toString()) + "=";
return data.toString();
case "object":
if (data === null)
return "null";
if (Array.isArray(data))
return data.map(d => nestedUrlSearchParams(d, true))
.map(encodeURIComponent)
.join("&");
const inner = Object.entries(data)
.map(([k, v]) => [k, nestedUrlSearchParams(v, false)]);
return new URLSearchParams(inner).toString();
default:
return "";
}
}
type MagApiErrorCode = "Client:GenericApiError" | string;
export interface MagApiError {
status: number;
code: MagApiErrorCode,
message: string,
}
export class MagApiClient {
private readonly baseUrl: string;
constructor(baseUrl: string) {
this.baseUrl = baseUrl;
}
async call<M extends Method, T extends BackendApiEndpoint<M, T["request"], T["response"]>>(
endpoint: T["endpoint"],
method: M,
data: T["request"],
pathParams: Record<string, string>,
token?: string | null | undefined
): Promise<T["response"]> {
type Response = T["response"];
const authorizationToken = token ?? undefined;
const authorization = authorizationToken
? `Bearer ${authorizationToken}`
: undefined;
let url = `${this.baseUrl}/${endpoint}`;
if (method === "GET") {
const query = nestedUrlSearchParams(data as any);
if (query) {
url += `?${query}`;
}
}
return await fetch(url, {
method,
body: method !== "GET" ? JSON.stringify(data) : undefined,
credentials: "omit",
cache: "no-cache",
headers: authorization ? {authorization} : {},
})
.then(async (res) => {
const body = res.status === 204 ? null : await res.json();
if (res.status === 200) {
return body as Response;
} else if (res.status === 204) {
return null as any as Response;
} else {
throw body as MagApiError;
}
})
.catch((e) => {
throw ({
status: -1,
code: "Client:GenericApiError",
message: e
}) as MagApiError;
});
}
}
const a = new MagApiClient("https://aaa");
a.call<"GET", GetNoteById>("", "",{}, {})