diff --git a/package.json b/package.json index ebe217a..d21af76 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@cocreators-ee/apity", "description": "A typed fetch client for openapi-typescript with Svelte support", - "version": "0.0.4", + "version": "0.0.5", "readme": "README.md", "engines": { "node": ">= 12.0.0", diff --git a/src/svelte/fetcher.ts b/src/svelte/fetcher.ts index f3e1aa6..394e1bc 100644 --- a/src/svelte/fetcher.ts +++ b/src/svelte/fetcher.ts @@ -14,7 +14,30 @@ import type { Method, } from '../types.js' import type { ApiRequest, ApiResponse, SvelteCreateFetch } from './types.js' -import { ApiError } from '../types.js' +import { ApiError, LimitedResponse } from '../types.js' + +const JSON_CONTENT_TYPES = ['application/json', 'application/ld+json'] + +async function getResponseBody(response: LimitedResponse) { + // no content + if (response.status === 204) { + return undefined + } + const contentType = response.headers.get('content-type') + if (contentType && JSON_CONTENT_TYPES.includes(contentType)) { + return await response.json() + } else if (contentType && contentType.indexOf('text') === -1) { + // if the response is neither JSON nor text, return binary data as is + // @ts-ignore + return await response.blob() + } + const text = await response.text() + try { + return JSON.parse(text) + } catch (e) { + return text + } +} /*** * Make an API call and compose an ApiResponse object from the result @@ -25,7 +48,7 @@ async function fetchAndParse(request: Request): Promise> { try { const response = await request.realFetch(url, init) try { - const body = response.status === 204 ? undefined : await response.json() + const body = await getResponseBody(response) if (response.ok) { return { status: response.status, @@ -40,7 +63,7 @@ async function fetchAndParse(request: Request): Promise> { } } } catch (e) { - console.warn('Failed to parse JSON from the response body', e) + console.warn('Failed to parse the response body', e) return { status: -2, data: undefined, diff --git a/src/types.ts b/src/types.ts index ddf873f..56c2e40 100644 --- a/src/types.ts +++ b/src/types.ts @@ -39,9 +39,11 @@ type OpResponseTypes = OP extends { ? S : R[S] extends { content: { 'application/json': infer C } } // openapi 3 ? C + : R[S] extends TextContentType + ? string : S extends 'default' ? R[S] - : unknown + : Blob } : never @@ -198,3 +200,13 @@ export class ApiError extends Error { this.data = response.data } } + +type TextContentType = { + content: + | { 'text/css': any } + | { 'text/csv': any } + | { 'text/html': any } + | { 'text/javascript': any } + | { 'text/plain': any } + | { 'text/xml': any } +}