Lightweight hooks over the openapi-fetch client and React Query. An integrator pattern — the reference webapp does not use React Query.
These hooks wrap the TypeScript client with
React Query for caching, refetching, and pagination.
This is a suggested integrator pattern, not a mirror of the reference
webapp. The reference FE is plain JavaScript with axios and Redux — it
does not use React Query or generated clients. Adopt or ignore as
suits your stack.
These generic wrappers use any internally — they give you React Query
ergonomics but not end-to-end path/param type safety. For strict
typing, call fd.GET("/events/{id}", ...) directly (the
TypeScript client is fully typed) and wrap
only where you want caching. Don’t mistake the generic hook for a typed
client.
src/fd/hooks.ts
import { useQuery, useMutation, useQueryClient, type UseQueryOptions } from "@tanstack/react-query";import { fd } from "./client";// Stable query key: include partnerId so cache is partitioned per tenant.function keyFor(partnerId: string, path: string, params?: unknown) { return [partnerId, path, params ?? null] as const;}// Generic GET — NOT strictly typed (uses any). Convenience over safety.export function useFd( partnerId: string, path: string, params?: any, opts?: Partial<UseQueryOptions<any>>,) { return useQuery({ queryKey: keyFor(partnerId, path, params), queryFn: async () => { const { data, error } = await (fd as any).GET(path, { params }); if (error) throw error; return data; }, ...opts, });}// Generic mutation. `invalidate` takes the SAME [partnerId, path, params]// key shape used by useFd — not concrete URL strings.export function useFdMutation( method: "POST" | "PUT" | "DELETE" | "PATCH", path: string, opts: { invalidateKeys?: readonly unknown[][] } = {},) { const qc = useQueryClient(); return useMutation({ mutationFn: async (vars: { params?: any; body?: any }) => { const fn = (fd as any)[method] as Function; const { data, error } = await fn(path, { params: vars.params, body: vars.body }); if (error) throw error; return data; }, onSuccess: () => opts.invalidateKeys?.forEach((k) => qc.invalidateQueries({ queryKey: k })), });}