Skip to content

Commit

Permalink
Add shortcut methods for all response types
Browse files Browse the repository at this point in the history
  • Loading branch information
danbahrami committed Sep 4, 2024
1 parent dafacbd commit a6b7682
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 22 deletions.
59 changes: 44 additions & 15 deletions src/createClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,47 @@ export const createClient = (options: ClientOptions = {}): Client => {
};
};

/**
* Decorate the promise returned from a request method with some response body shortcut methods .
* - await f.get().json()
* - await f.get().text()
* - await f.get().blob()
* - await f.get().formData()
* - await f.get().arrayBuffer()
*/
const _decorateResponsePromise = (
promise: Promise<DecoratedResponse>
): DecoratedResponsePromise => {
const decoratedPromise = promise as DecoratedResponsePromise;

decoratedPromise.json = async <T = unknown>() => {
const response = await promise;
return response.json<T>();
};

decoratedPromise.text = async () => {
const response = await promise;
return response.text();
};

decoratedPromise.blob = async () => {
const response = await promise;
return response.blob();
};

decoratedPromise.formData = async () => {
const response = await promise;
return response.formData();
};

decoratedPromise.arrayBuffer = async () => {
const response = await promise;
return response.arrayBuffer();
};

return decoratedPromise;
};

/**
* `_createMethod()` is where all the complex stuff happens. It's what we
* use to build the public methods: `.get()`, `.post()`, `.request()` etc.
Expand Down Expand Up @@ -226,21 +267,9 @@ export const createClient = (options: ClientOptions = {}): Client => {

throw e;
}
})() as DecoratedResponsePromise;

/**
* Decorate the response with a .json() method so you can call it
* directly on the response promise.
*
* @example
* const user = get("/api/user").json<User>();
*/
result.json = async <T = unknown>() => {
const response = await result;
return await response.json<T>();
};

return result;
})();

return _decorateResponsePromise(result);
};
};

Expand Down
24 changes: 17 additions & 7 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,28 @@ export type DecoratedResponse = Omit<Response, "json"> & {
};

/**
* This type enhances the promise that's returned from client methods so that
* you can call `.json()` on it immediately without having to do it inside
* `.then()`
* When you make a request, the promise that's returned has some additional
* methods bound to it which act as shortcuts for deserializing the reponse
* body.
*
* @example
* So instead of manually accessing response JSON like so:
*
* ```
* const user = await f.get(url).then(r => r.json<User>());
* ```
*
*```ts
*f.get(url).json<User>();
*```
* You can do it straight on the response promise like so:
*
* ```
* const user = await f.get(url).json<User>();
* ```
*/
export type DecoratedResponsePromise = Omit<Promise<DecoratedResponse>, "json"> & {
json: <T = unknown>() => Promise<T>;
text: () => Promise<string>;
blob: () => Promise<Blob>;
formData: () => Promise<FormData>;
arrayBuffer: () => Promise<ArrayBuffer>;
};

export type ClientOptions = {
Expand Down

0 comments on commit a6b7682

Please sign in to comment.