From 94418630fa4a8e0f69b703e43d7b5ebe6a21268d Mon Sep 17 00:00:00 2001 From: Diogo Biazus Date: Thu, 1 Aug 2024 16:31:58 -0400 Subject: [PATCH] Add third parameter with response to trace and allow it to be asynchronous --- README.md | 3 +++ src/api.test.ts | 2 ++ src/api.ts | 4 ++-- src/types.ts | 6 +++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dc953f4..bb6144b 100644 --- a/README.md +++ b/README.md @@ -408,8 +408,11 @@ await enhancedFetch("https://example.com/api/users/:role", { // method: 'POST', // body: '{"some":{"object":{"as":{"body":{}}}}}', // } +// Response {} ``` +The `trace` function can also return a `Promise` in order to send traces to an external service or database. + ## typedResponse A type-safe wrapper around the `Response` object. It adds a `json` and `text` method that will parse the response with a given zod schema. If you don't provide a schema, it will return `unknown` instead of `any`, then you can also give it a generic to type cast the result. diff --git a/src/api.test.ts b/src/api.test.ts index 75840f0..1ab64bc 100644 --- a/src/api.test.ts +++ b/src/api.test.ts @@ -198,6 +198,7 @@ describe('enhancedFetch', () => { method: 'POST', body: `{"id":1,"name":{"first":"John","last":"Doe"}}`, }, + expect.any(Response), ) }) @@ -358,6 +359,7 @@ describe('makeFetcher', () => { body: `{"id":1,"name":{"first":"John","last":"Doe"}}`, headers: new Headers(), }, + expect.any(Response), ) }) }) diff --git a/src/api.ts b/src/api.ts index 5501291..7a65fb8 100644 --- a/src/api.ts +++ b/src/api.ts @@ -67,7 +67,7 @@ function typedResponse( * @param requestInit the requestInit to be passed to the fetch request. It is the same as the `RequestInit` type, but it also accepts a JSON-like `body` and an object-like `query` parameter. * @param requestInit.body the body of the request. It will be automatically stringified so you can send a JSON-like object * @param requestInit.query the query parameters to be added to the URL - * @param requestInit.trace a function that receives the URL and the requestInit and can be used to log the request + * @param requestInit.trace a function that receives the URL, the requestInit and a clone of the response in order to log or troubleshoot the request * @returns a Response with typed json and text methods * @example const response = await fetch("https://example.com/api/users"); * const users = await response.json(userSchema); @@ -85,8 +85,8 @@ async function enhancedFetch( const fullURL = addQueryToURL(withParams, query) const enhancedReqInit = { ...reqInit, body } - trace?.(fullURL, enhancedReqInit) const response = await fetch(fullURL, enhancedReqInit) + await trace?.(fullURL, enhancedReqInit, response.clone()) return typedResponse(response) } diff --git a/src/types.ts b/src/types.ts index bf41b59..e46763c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,7 +28,11 @@ type EnhancedRequestInit = Omit & { body?: JSONValue | BodyInit | null query?: SearchParams params?: PathParams - trace?: (...args: Parameters) => void + trace?: ( + input: Parameters[0], + init?: Parameters[1], + response?: Awaited>, + ) => void | Promise } type ServiceRequestInit = Omit, 'method'>