diff --git a/api-client/deno.json b/api-client/deno.json index cf82ffe..ab952e7 100644 --- a/api-client/deno.json +++ b/api-client/deno.json @@ -3,7 +3,7 @@ "@preact/signals": "npm:@preact/signals@^2.5.1" }, "name": "@01edu/api-client", - "version": "0.1.3", + "version": "0.1.4", "license": "MIT", "exports": { ".": "./mod.ts" }, "compilerOptions": { diff --git a/api-client/mod.ts b/api-client/mod.ts index 01fd63b..a95db10 100644 --- a/api-client/mod.ts +++ b/api-client/mod.ts @@ -107,9 +107,12 @@ type RequestState = at: number } +type ReplacerType = (key: string, value: unknown) => unknown + type Options = { headers?: HeadersInit signal?: AbortSignal + replacer?: ReplacerType } const withoutBody = new Set([ @@ -155,7 +158,9 @@ export const makeClient = (baseUrl = ''): { input?: HandlerIO[0] | undefined, options?: Options | undefined, ) => Promise[1]> - signal: () => RequestState[1]> & { + signal: ( + options?: { replacer?: ReplacerType }, + ) => RequestState[1]> & { $: Signal[1]>> reset: () => void fetch: ( @@ -177,6 +182,7 @@ export const makeClient = (baseUrl = ''): { const defaultHeaders = { 'Content-Type': 'application/json' } async function fetcher(input?: Input, options?: Options | undefined) { + const { replacer, ...fetchOptions } = options || {} let url = `${baseUrl}${path}` let headers = options?.headers if (!headers) { @@ -197,13 +203,16 @@ export const makeClient = (baseUrl = ''): { const response = await fetch( url, - { ...options, method, headers, body: bodyInput }, + { ...fetchOptions, method, headers, body: bodyInput }, ) if (withoutBody.has(response.status)) return null as unknown as Output const body = await response.text() let payload + const contentType = response.headers.get('content-type') try { - payload = JSON.parse(body) + payload = contentType?.includes('application/json') + ? JSON.parse(body, replacer) + : body if (response.ok) return payload as Output } catch { throw new ErrorWithBody(body, { response }) @@ -212,7 +221,7 @@ export const makeClient = (baseUrl = ''): { throw new ErrorWithData(message, data) } - const signal = () => { + const signal = (options: { replacer?: ReplacerType } = {}) => { const $ = new Signal>({ pending: 0 }) return { $, @@ -226,9 +235,10 @@ export const makeClient = (baseUrl = ''): { const controller = new AbortController() prev.controller?.abort() $.value = { pending: Date.now(), controller, data: prev.data } + const { replacer } = options const { signal } = controller $.value = { - data: await fetcher(input, { signal, headers }), + data: await fetcher(input, { replacer, signal, headers }), at: Date.now(), } } catch (err) {