@oazapfts/runtime
Version:
Runtime for OpenApi TypeScript client generator
1 lines • 12.1 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/runtime.ts","../src/index.ts"],"sourcesContent":["import * as qs from \"./query\";\nimport { joinUrl } from \"./util\";\nimport { ok } from \"./index\";\nimport { CustomHeaders, mergeHeaders, normalizeHeaders } from \"./headers\";\n\nexport { type CustomHeaders };\n\nexport type RequestOpts = {\n baseUrl?: string;\n fetch?: typeof fetch;\n formDataConstructor?: new () => FormData;\n headers?: HeadersInit | CustomHeaders;\n} & Omit<RequestInit, \"body\" | \"headers\">;\n\nexport type Defaults<Headers extends RequestOpts[\"headers\"] = CustomHeaders> =\n Omit<RequestOpts, \"headers\" | \"baseUrl\"> & {\n baseUrl: string;\n headers: Headers;\n };\n\ntype FetchRequestOpts = RequestOpts & {\n body?: string | FormData | Blob;\n};\n\ntype JsonRequestOpts = RequestOpts & {\n body?: any;\n};\n\ntype FormRequestOpts = RequestOpts & {\n body?: Record<string, any>;\n};\n\nexport type ApiResponse = { status: number; data?: any };\n\nexport type WithHeaders<T extends ApiResponse> = T & { headers: Headers };\n\ntype MultipartRequestOpts = RequestOpts & {\n body?: Record<string, unknown>;\n};\n\nexport function runtime(defaults: RequestOpts = {}) {\n async function fetchText(url: string, req?: FetchRequestOpts) {\n const res = await doFetch(url, req);\n let data;\n try {\n data = await res.text();\n } catch (err) {}\n\n return {\n status: res.status,\n headers: res.headers,\n contentType: res.headers.get(\"content-type\"),\n data,\n };\n }\n\n async function fetchJson<T extends ApiResponse>(\n url: string,\n req: FetchRequestOpts = {},\n ) {\n const { status, headers, contentType, data } = await fetchText(url, {\n ...req,\n headers: mergeHeaders(\n {\n Accept: \"application/json\",\n },\n req.headers,\n ),\n });\n\n const isJson = contentType ? contentType.includes(\"json\") : false;\n\n if (isJson) {\n return {\n status,\n headers,\n data: data ? JSON.parse(data) : null,\n } as WithHeaders<T>;\n }\n\n return { status, headers, data } as WithHeaders<T>;\n }\n\n async function fetchBlob<T extends ApiResponse>(\n url: string,\n req: FetchRequestOpts = {},\n ) {\n const res = await doFetch(url, req);\n let data;\n try {\n data = await res.blob();\n } catch (err) {}\n return { status: res.status, headers: res.headers, data } as WithHeaders<T>;\n }\n\n async function doFetch(url: string, req: FetchRequestOpts = {}) {\n const {\n baseUrl,\n fetch: customFetch,\n ...init\n } = {\n ...defaults,\n ...req,\n headers: mergeHeaders(defaults.headers, req.headers),\n };\n const href = joinUrl(baseUrl, url);\n const res = await (customFetch || fetch)(href, init);\n return res;\n }\n\n return {\n ok,\n fetchText,\n fetchJson,\n fetchBlob,\n mergeHeaders,\n\n json({ body, headers, ...req }: JsonRequestOpts) {\n return {\n ...req,\n ...(body != null && { body: JSON.stringify(body) }),\n headers: mergeHeaders(\n {\n \"Content-Type\": \"application/json\",\n },\n headers,\n ),\n };\n },\n\n form({ body, headers, ...req }: FormRequestOpts) {\n return {\n ...req,\n ...(body != null && { body: qs.form(body) }),\n headers: mergeHeaders(\n {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n headers,\n ),\n };\n },\n\n multipart({ body, headers, ...req }: MultipartRequestOpts) {\n if (body == null)\n return { ...req, body, headers: normalizeHeaders(headers) };\n\n const data = new (defaults.formDataConstructor ||\n req.formDataConstructor ||\n FormData)();\n\n const append = (name: string, value: unknown) => {\n if (typeof value === \"string\" || value instanceof Blob) {\n data.append(name, value);\n } else if (typeof value === \"number\" || typeof value === \"boolean\") {\n data.append(name, String(value));\n } else {\n data.append(\n name,\n new Blob([JSON.stringify(value)], { type: \"application/json\" }),\n );\n }\n };\n\n Object.entries(body).forEach(([name, value]) => {\n if (Array.isArray(value)) {\n value.forEach((v) => append(name, v));\n } else {\n append(name, value);\n }\n });\n\n return {\n ...req,\n body: data,\n headers: normalizeHeaders(headers),\n };\n },\n };\n}\n","import type { ApiResponse, WithHeaders } from \"./runtime\";\n\nexport * from \"./runtime\";\n\n/**\n * Type to access a response's data property for a given status.\n */\nexport type DataType<T extends ApiResponse, S extends number> = T extends {\n status: S;\n}\n ? T[\"data\"]\n : never;\n\n/**\n * Object with methods to handle possible status codes of an ApiResponse.\n */\nexport type ResponseHandler<T extends ApiResponse> = {\n [P in T[\"status\"]]?: (res: DataType<T, P>) => any;\n} & {\n default?: (status: number, data: any) => any;\n};\n\nexport type FunctionReturnType<T> = T extends (...args: any[]) => any\n ? ReturnType<T>\n : never;\n\n/**\n * Utility function to handle different status codes.\n *\n * Example:\n *\n * const userId = await handle(api.register({ email, password }), {\n * 200: (user: User) => user.id,\n * 400: (err: string) => console.log(err),\n * })\n **/\nexport async function handle<\n T extends WithHeaders<ApiResponse>,\n H extends ResponseHandler<T>,\n>(promise: Promise<T>, handler: H): Promise<FunctionReturnType<H[keyof H]>> {\n const { status, data, headers } = await promise;\n const statusHandler = (handler as any)[status];\n if (statusHandler) return statusHandler(data);\n if (handler.default) return handler.default(status, data);\n throw new HttpError(status, data, headers);\n}\n\nexport const SUCCESS_CODES = [200, 201, 202, 204] as const;\nexport type SuccessCodes = (typeof SUCCESS_CODES)[number];\n\nexport type SuccessResponse<T extends ApiResponse> = DataType<T, SuccessCodes>;\n\n/**\n * Utility function to directly return any successful response\n * and throw a HttpError otherwise.\n *\n * Example:\n *\n * try {\n * const userId = await ok(api.register({ email, password }));\n * }\n * catch (err) {\n * console.log(err.status)\n * }\n */\nexport async function ok<T extends WithHeaders<ApiResponse>>(\n promise: Promise<T>,\n): Promise<SuccessResponse<T>> {\n const res = await promise;\n if (SUCCESS_CODES.some((s) => s == res.status)) return res.data;\n throw new HttpError(res.status, res.data, res.headers);\n}\n\nexport type Args<T> = T extends (...args: infer U) => any ? U : any;\nexport type ApiFunction = (...args: any[]) => Promise<WithHeaders<ApiResponse>>;\nexport type AsyncReturnType<T> = T extends (...args: any[]) => Promise<infer V>\n ? V\n : never;\n\nexport type OkResponse<T extends ApiFunction> = SuccessResponse<\n AsyncReturnType<T>\n>;\n\nexport type Okify<T extends ApiFunction> = (\n ...args: Args<T>\n) => Promise<OkResponse<T>>;\n\n/**\n * Utility function to wrap an API function with `ok(...)`.\n */\nexport function okify<T extends ApiFunction>(fn: T): Okify<T> {\n return (...args: Args<T>) => ok(fn(...args));\n}\n\ntype OptimisticApi<T> = {\n [K in keyof T]: T[K] extends ApiFunction ? Okify<T[K]> : T[K];\n};\n\n/**\n * Utility to `okify` each function of an API.\n */\nexport function optimistic<T extends Record<string, ApiFunction | unknown>>(\n api: T,\n): OptimisticApi<T> {\n const okApi: any = {};\n Object.entries(api).forEach(([key, value]) => {\n okApi[key] = typeof value === \"function\" ? okify(value as any) : value;\n });\n return okApi;\n}\n\nexport class HttpError extends Error {\n status: number;\n data?: any;\n headers: Headers;\n\n constructor(status: number, data: any, headers: Headers) {\n super(`Error: ${status}`);\n this.status = status;\n this.data = data;\n this.headers = headers;\n }\n}\n"],"names":["runtime","defaults","fetchText","url","req","__async","res","doFetch","data","err","fetchJson","_0","status","headers","contentType","__spreadProps","__spreadValues","mergeHeaders","fetchBlob","_a","baseUrl","customFetch","init","__objRest","href","joinUrl","ok","_b","body","_c","_d","qs.form","_e","_f","normalizeHeaders","append","name","value","v","handle","promise","handler","statusHandler","HttpError","SUCCESS_CODES","s","okify","fn","args","optimistic","api","okApi","key","__publicField"],"mappings":"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"}