Skip to content

Commit

Permalink
Add .request() method for making requests of any HTTP method
Browse files Browse the repository at this point in the history
  • Loading branch information
danbahrami committed Aug 31, 2024
1 parent 8ea103f commit b05be66
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 14 deletions.
9 changes: 6 additions & 3 deletions src/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
DecoratedResponse,
DecoratedResponsePromise,
Modifiers,
SoFetchRequestInit,
} from "@/types";
import { callbackStore, mergeHeaders } from "@/utils";

Expand Down Expand Up @@ -53,14 +52,14 @@ export const createClient = (options: ClientOptions = {}): Client => {
};

const _createMethod = (methodInit: RequestInit) => {
return (info: RequestInfo, init: SoFetchRequestInit = {}) => {
return (info: RequestInfo, init?: RequestInit & { json?: unknown }) => {
const result = (async (): Promise<DecoratedResponse> => {
/**
* Combine the incoming RequestInit with the default RequestInit
* and set "content-type" header to "application/json" by
* default if JSON is passed as the request body.
*/
const { json, ...requestInit } = init;
const { json, ...requestInit } = init ?? {};
const combinedRequestInit: RequestInit = {
...methodInit,
...requestInit,
Expand Down Expand Up @@ -211,6 +210,10 @@ export const createClient = (options: ClientOptions = {}): Client => {
};

return {
request: _createMethod({
...options.defaults?.request,
}),

get: _createMethod({
method: "GET",
...options.defaults?.get,
Expand Down
27 changes: 16 additions & 11 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import {
NetworkError,
} from "./errors";

export type SoFetchRequestInit = Omit<RequestInit, "method"> & {
json?: unknown;
};

export type Callbacks = {
onRequestStart: (details: { request: Request }) => Promise<void> | void;
onSuccessResponse: (details: {
Expand Down Expand Up @@ -79,60 +75,68 @@ export type DecoratedResponsePromise = Omit<
};

export type Client = {
/**
* Perform an HTTP request using any HTTP method (defaults to GET)
*/
request: (
input: RequestInfo,
init?: RequestInit & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP GET request
*/
get: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP PUT request
*/
put: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP POST request
*/
post: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP PATCH request
*/
patch: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP DELETE request
*/
delete: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP OPTIONS request
*/
options: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

/**
* Perform a HTTP HEAD request
*/
head: (
input: RequestInfo,
init?: SoFetchRequestInit
init?: Omit<RequestInit, "method"> & { json?: unknown }
) => DecoratedResponsePromise;

callbacks: {
Expand All @@ -152,6 +156,7 @@ export type Client = {

export type ClientOptions = {
defaults?: {
request: RequestInit;
get: Omit<RequestInit, "method">;
put: Omit<RequestInit, "method">;
post: Omit<RequestInit, "method">;
Expand Down
24 changes: 24 additions & 0 deletions test/f.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ const mockConsoleError = () => {

const HOST = "http://that-is-so-fetch.com";

describe("f.request()", () => {
test("When no method is specified it performs a GET request and returns a response", async () => {
nock(HOST)
.get("/api/user")
.reply(200, { firstName: "Shane", lastName: "MacGowan", age: 65 });

const response = await f.request(HOST + "/api/user");
expect(response).toBeInstanceOf(Response);
expect(response.status).toBe(200);
expect(response.statusText).toBe("OK");
});

test("You can provide an HTTP method", async () => {
nock(HOST)
.put("/api/user")
.reply(200, { firstName: "Shane", lastName: "MacGowan", age: 65 });

const response = await f.request(HOST + "/api/user", { method: "put" });
expect(response).toBeInstanceOf(Response);
expect(response.status).toBe(200);
expect(response.statusText).toBe("OK");
});
});

describe("f.get()", () => {
test("It performs a GET request and returns a response", async () => {
nock(HOST)
Expand Down

0 comments on commit b05be66

Please sign in to comment.