import ky from 'ky'; import { isArray, isEmpty } from "lodash"; export type ValidResponse = { result: true } export type InvalidResponse = { result: false; reason: string; } export type RawArgType = Record | Record[] | undefined; interface BasicAPICallT { (args: ArgType): Promise; (args: ArgType, returnError: false): Promise; (args: ArgType, returnError: true): Promise; } interface EmptyAPICallT { (): Promise; (args: undefined): Promise; (args: undefined, returnError: false): Promise; (args: undefined, returnError: true): Promise; } // eslint-disable-next-line @typescript-eslint/no-explicit-any export type ArgTypeOf = T extends APICallT ? A : never; export type APICallT< ArgType extends RawArgType, ResultType extends ValidResponse = ValidResponse, ErrorType extends InvalidResponse = InvalidResponse > = ArgType extends undefined ? EmptyAPICallT : BasicAPICallT; type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'; export type APITail = typeof GET | typeof POST | typeof PUT | typeof PATCH | typeof HEAD | typeof DELETE; const httpMethodMap = new Map([ [GET, 'get'], [POST, 'post'], [PUT, 'put'], [PATCH, 'patch'], [HEAD, 'head'], [DELETE, 'delete'], ]); export function extractHttpMethod(tail: APITail): HttpMethod { return httpMethodMap.get(tail) ?? 'post'; } export async function callSammoAPI(method: HttpMethod, path: string | string[], args: RawArgType, paramArgs: Record | undefined): Promise; export async function callSammoAPI(method: HttpMethod, path: string | string[], args: RawArgType, paramArgs: Record | undefined, returnError: false): Promise; export async function callSammoAPI(method: HttpMethod, path: string | string[], args: RawArgType, paramArgs: Record | undefined, returnError: true): Promise; export async function callSammoAPI(method: HttpMethod, path: string | string[], args: RawArgType, paramArgs: Record | undefined, returnError = false): Promise { if (isArray(path)) { path = path.join('/'); } if (args && isEmpty(args)) { args = undefined; } const result = await ky('api.php', { searchParams: { ...paramArgs, path, }, method, json: args, headers: { 'content-type': 'application/json' } }).json() as ErrorType | ResultType; if (!result.result) { if (returnError) { return result; } throw result.reason; } return result; } export async function GET(args?: ArgType): Promise; export async function GET(args: ArgType | undefined, returnError: false): Promise; export async function GET(args: ArgType | undefined, returnError: true): Promise; export async function GET(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call GET. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('get', [], args, undefined, true); } export async function POST(args?: ArgType): Promise; export async function POST(args: ArgType | undefined, returnError: false): Promise; export async function POST(args: ArgType | undefined, returnError: true): Promise; export async function POST(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call POST. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('post', [], args, undefined, true); } export async function PUT(args?: ArgType): Promise; export async function PUT(args: ArgType | undefined, returnError: false): Promise; export async function PUT(args: ArgType | undefined, returnError: true): Promise; export async function PUT(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call PUT. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('put', [], args, undefined, true); } export async function PATCH(args?: ArgType): Promise; export async function PATCH(args: ArgType | undefined, returnError: false): Promise; export async function PATCH(args: ArgType | undefined, returnError: true): Promise; export async function PATCH(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call PATCH. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('patch', [], args, undefined, true); } export async function HEAD(args?: ArgType): Promise; export async function HEAD(args: ArgType | undefined, returnError: false): Promise; export async function HEAD(args: ArgType | undefined, returnError: true): Promise; export async function HEAD(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call HEAD. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('head', [], args, undefined, true); } export async function DELETE(args?: ArgType): Promise; export async function DELETE(args: ArgType | undefined, returnError: false): Promise; export async function DELETE(args: ArgType | undefined, returnError: true): Promise; export async function DELETE(args?: ArgType, returnError = false): Promise { console.error(`Can't directly call DELETE. ${args}, ${returnError}. Use auto-generated path API.`); return callSammoAPI('patch', [], args, undefined, true); }