api library

This commit is contained in:
Rachel Lambda Samuelsson 2024-07-20 18:57:27 +02:00
parent e59748a285
commit 8255663005

76
front/src/api/index.ts Normal file
View File

@ -0,0 +1,76 @@
export interface QueryParams {
[key: string]: (string | number)
}
export interface APIDef {
[key: string]: ({
kind: "POST",
query?: QueryParams,
request?: Object,
response: Object,
} | {
kind: "GET",
query?: QueryParams,
response: Object,
})
}
type A = {
"/api/blah": {
kind: "GET",
request: {
mjau: number
cat: string
}
response: {
status: number
}
}
}
export type ValidEndPointForMethod<T, U extends (keyof T & string), method extends "GET" | "POST">
= T[U] extends { kind: method } ? U : never
export type QR = { query: Object, request: Object }
export class API<T extends APIDef> {
base: string;
constructor(base: string) {
this.base = base;
}
private dispatch(method : "POST" | "GET",
endpoint : keyof T & string,
req : T[typeof endpoint] & QR):
Promise<T[typeof endpoint]["response"]> {
let url : URL = new URL(endpoint, this.base)
let opts : RequestInit = { method }
if (req.query != null) {
const params = new URLSearchParams()
for (const [key, value] of Object.entries(req.query)) {
params.set(key, typeof(value) == "string" ? value : value.toString())
}
url = new URL(params.toString(), url)
}
if (method == "POST" && req.request != null) {
opts.body = JSON.stringify(req.request)
opts.headers = { "Content-Type": "application/json" }
}
return fetch(url, opts)
}
get(endpoint : ValidEndPointForMethod<T, string, "GET">,
req: T[typeof endpoint] & QR):
Promise<T[typeof endpoint]["response"]> {
return this.dispatch("GET", endpoint, req)
}
post(endpoint : ValidEndPointForMethod<T, string, "POST">,
req: T[typeof endpoint] & QR):
Promise<T[typeof endpoint]["response"]> {
return this.dispatch("POST", endpoint, req)
}
}
const test = new API<A>("mjau")