diff --git a/.changeset/spotty-flies-knock.md b/.changeset/spotty-flies-knock.md new file mode 100644 index 00000000..302c097a --- /dev/null +++ b/.changeset/spotty-flies-knock.md @@ -0,0 +1,6 @@ +--- +"openapi-react-query": patch +--- + +- Fixed empty value check in queryFn: only throws error for undefined, other falsy values are allowed +- Fixed empty value check in mutationFn: allow falsy values diff --git a/.vscode/settings.json b/.vscode/settings.json index 47555f79..6c78a8f7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,7 +8,7 @@ "[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, - "[typescript]": { + "[typescript][typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" } } diff --git a/docs/scripts/update-contributors.js b/docs/scripts/update-contributors.js index b627ef75..f93d43a6 100644 --- a/docs/scripts/update-contributors.js +++ b/docs/scripts/update-contributors.js @@ -182,7 +182,7 @@ const CONTRIBUTORS = { "armandabric", "illright", ]), - "openapi-react-query": new Set(["drwpow", "kerwanp", "yoshi2no"]), + "openapi-react-query": new Set(["drwpow", "kerwanp", "yoshi2no", "HugeLetters"]), "swr-openapi": new Set(["htunnicliff"]), "openapi-metadata": new Set(["kerwanp", "drwpow"]), }; diff --git a/packages/openapi-react-query/src/index.ts b/packages/openapi-react-query/src/index.ts index 97d83a68..cbee066c 100644 --- a/packages/openapi-react-query/src/index.ts +++ b/packages/openapi-react-query/src/index.ts @@ -115,9 +115,10 @@ export default function createClient; const fn = client[mth] as ClientMethod; const { data, error } = await fn(path, { signal, ...(init as any) }); // TODO: find a way to avoid as any - if (error || !data) { + if (error) { throw error; } + return data; }; @@ -141,10 +142,11 @@ export default function createClient; const fn = client[mth] as ClientMethod; const { data, error } = await fn(path, init as InitWithUnknowns); - if (error || !data) { + if (error) { throw error; } - return data; + + return data as Exclude; }, ...options, }, diff --git a/packages/openapi-react-query/test/index.test.tsx b/packages/openapi-react-query/test/index.test.tsx index 97550d44..294175df 100644 --- a/packages/openapi-react-query/test/index.test.tsx +++ b/packages/openapi-react-query/test/index.test.tsx @@ -283,6 +283,50 @@ describe("client", () => { expect(data).toBeUndefined(); }); + it("should resolve data properly and have error as null when queryFn returns null", async () => { + const fetchClient = createFetchClient({ baseUrl }); + const client = createClient(fetchClient); + + useMockRequestHandler({ + baseUrl, + method: "get", + path: "/string-array", + status: 200, + body: null, + }); + + const { result } = renderHook(() => client.useQuery("get", "/string-array"), { wrapper }); + + await waitFor(() => expect(result.current.isFetching).toBe(false)); + + const { data, error } = result.current; + + expect(data).toBeNull(); + expect(error).toBeNull(); + }); + + it("should resolve error properly and have undefined data when queryFn returns undefined", async () => { + const fetchClient = createFetchClient({ baseUrl }); + const client = createClient(fetchClient); + + useMockRequestHandler({ + baseUrl, + method: "get", + path: "/string-array", + status: 200, + body: undefined, + }); + + const { result } = renderHook(() => client.useQuery("get", "/string-array"), { wrapper }); + + await waitFor(() => expect(result.current.isFetching).toBe(false)); + + const { data, error } = result.current; + + expect(error).toBeInstanceOf(Error); + expect(data).toBeUndefined(); + }); + it("should infer correct data and error type", async () => { const fetchClient = createFetchClient({ baseUrl, fetch: fetchInfinite }); const client = createClient(fetchClient); @@ -560,6 +604,54 @@ describe("client", () => { expect(error?.message).toBe("Something went wrong"); }); + it("should resolve data properly and have error as null when mutationFn returns null", async () => { + const fetchClient = createFetchClient({ baseUrl }); + const client = createClient(fetchClient); + + useMockRequestHandler({ + baseUrl, + method: "put", + path: "/comment", + status: 200, + body: null, + }); + + const { result } = renderHook(() => client.useMutation("put", "/comment"), { wrapper }); + + result.current.mutate({ body: { message: "Hello", replied_at: 0 } }); + + await waitFor(() => expect(result.current.isPending).toBe(false)); + + const { data, error } = result.current; + + expect(data).toBeNull(); + expect(error).toBeNull(); + }); + + it("should resolve data properly and have error as null when mutationFn returns undefined", async () => { + const fetchClient = createFetchClient({ baseUrl }); + const client = createClient(fetchClient); + + useMockRequestHandler({ + baseUrl, + method: "put", + path: "/comment", + status: 200, + body: undefined, + }); + + const { result } = renderHook(() => client.useMutation("put", "/comment"), { wrapper }); + + result.current.mutate({ body: { message: "Hello", replied_at: 0 } }); + + await waitFor(() => expect(result.current.isPending).toBe(false)); + + const { data, error } = result.current; + + expect(error).toBeNull(); + expect(data).toBeUndefined(); + }); + it("should use provided custom queryClient", async () => { const fetchClient = createFetchClient({ baseUrl }); const client = createClient(fetchClient);