Skip to content

Commit

Permalink
remove need for ResponseType, and use response content-type instead
Browse files Browse the repository at this point in the history
  • Loading branch information
JeromeBu committed Nov 25, 2024
1 parent 17ae80a commit 62515c9
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 31 deletions.
11 changes: 1 addition & 10 deletions src/axios/createAxiosSharedClient.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import type { AxiosInstance, ResponseType as AxiosResponseType } from "axios";
import type { AxiosInstance } from "axios";
import type { UnknownSharedRoute, Url } from "..";
import { configureCreateHttpClient, HandlerCreator } from "..";
import { ResponseType } from "../defineRoutes";
import {
HttpClientOptions,
validateInputParams,
validateSchemaWithExplicitError,
} from "../validations";

const toAxiosResponseType: Record<ResponseType, AxiosResponseType> = {
arrayBuffer: "arraybuffer",
blob: "blob",
json: "json",
text: "text",
};

export const createAxiosHandlerCreator =
<SharedRoutes extends Record<string, UnknownSharedRoute>>(
axios: AxiosInstance,
Expand All @@ -34,7 +26,6 @@ export const createAxiosHandlerCreator =
url: replaceParamsInUrl(route.url, urlParams as Url),
data: body,
params: queryParams,
responseType: toAxiosResponseType[route.responseType],
headers: {
...axios.defaults.headers,
...(headers ?? ({} as any)),
Expand Down
4 changes: 0 additions & 4 deletions src/defineRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,11 @@ export type ResponsesToHttpResponse<Responses extends UnknownResponses> = ValueO
{ [K in keyof Responses & number]: HttpResponse<K, z.infer<Responses[K]>> }
>;

export type ResponseType = "json" | "arrayBuffer" | "blob" | "text";

type OptionalFields<RequestBody, Query, Responses extends UnknownResponses, Headers> = {
requestBodySchema?: z.Schema<RequestBody>;
queryParamsSchema?: z.Schema<Query>;
responses?: Responses;
headersSchema?: z.Schema<Headers>;
responseType?: ResponseType;
};

export type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
Expand Down Expand Up @@ -73,7 +70,6 @@ export const defineRoute = <
responses: { 201: z.void().or(z.string().max(0)) } as any, // as some framework return "" instead of void (like express)
headersSchema: z.object({}) as any,
...route,
responseType: route.responseType ?? "json",
});

const verifyRoutesUniqAndListRoutes = <T extends Record<string, UnknownSharedRoute>>(
Expand Down
55 changes: 38 additions & 17 deletions src/fetch/createFetchSharedClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { HttpResponse, UnknownSharedRoute, Url } from "..";
import { configureCreateHttpClient, HandlerCreator } from "..";
import { ResponseType } from "../defineRoutes";
import { convertToFormData } from "./convertToFormData";
import {
HttpClientOptions,
Expand Down Expand Up @@ -83,9 +82,8 @@ export const createFetchHandlerCreator =
},
);

const processedBody = await responseTypeToResponseBody(res, route.responseType);

const headersAsObject = objectFromEntries((res.headers as any).entries());
const processedBody = await responseTypeToResponseBody(res);

if (options?.onResponseSideEffect) {
options.onResponseSideEffect({
Expand Down Expand Up @@ -124,21 +122,44 @@ export const createFetchHandlerCreator =
};
};

const responseTypeToResponseBody = (res: Response, responseType: ResponseType) => {
switch (responseType) {
case "json":
return res.json();
case "text":
return res.text();
case "blob":
return res.blob();
case "arrayBuffer":
return res.arrayBuffer();
default: {
const exhaustiveCheck: never = responseType;
return exhaustiveCheck;
}
const responseTypeToResponseBody = (res: Response) => {
const contentType = res.headers.get("content-type")?.toLowerCase() || "";

if (
contentType.includes("application/json") ||
contentType.includes("application/ld+json")
) {
return res.json();
}

// Binary/blob types
if (
contentType.includes("image/") ||
contentType.includes("audio/") ||
contentType.includes("video/") ||
contentType.includes("application/pdf") ||
contentType.includes("application/zip") ||
contentType.includes("application/octet-stream") ||
contentType.includes("application/vnd.")
) {
return res.blob();
}

// Form data
if (contentType.includes("multipart/form-data")) {
return res.formData();
}

// ArrayBuffer for binary data that needs processing
if (
contentType.includes("application/java-archive") ||
contentType.includes("application/x-shockwave-flash")
) {
return res.arrayBuffer();
}

// Default to text for everything else (html, plain text, xml, css, etc)
return res.text();
};

export const createFetchSharedClient = <
Expand Down

0 comments on commit 62515c9

Please sign in to comment.