Skip to content

Instantly share code, notes, and snippets.

@jpkempf
Last active June 26, 2023 16:26
Show Gist options
  • Save jpkempf/bc94bbff88b5141f1b96eb5285578681 to your computer and use it in GitHub Desktop.
Save jpkempf/bc94bbff88b5141f1b96eb5285578681 to your computer and use it in GitHub Desktop.
Helper to create fully typed fetcher functions with built-in error handling
/**
* This function returns a new function that handles HTTP calls, logging, and errors.
* It is meant for API route helpers but could be used for other kinds of calls as well.
*
* @param name the name of the new function; used for logging
* @param fetcher the function that makes the HTTP call
* @returns a new function that calls the fetcher and handles errors and logging
*/
const createFetcher =
<T extends any[]>(name: string, fetcher: (...args: T) => Promise<Response>) =>
async (...args: T) => {
const handleError = (code: number, message: string) => {
// drop in your choice of logger here
logger.error(`${name} failed`, { data: { code, message, args } })
return { error: { code, message }, value: null }
}
try {
const response = await fetcher(...args)
if (!response.ok) {
return handleError(response.status, response.statusText)
}
return { error: null, value: await response.json() }
} catch (error) {
return handleError(error.code ?? 500, error.message ?? 'Unknown error')
}
}
export const deleteThisThing = createFetcher(
'deleteThisThing',
(thingId: number) =>
fetch('/api/things/delete', {
method: 'POST',
body: JSON.stringify({ id: thingId }),
}),
)
import { deleteThisThing } from './fetchers'
export default async function main() {
const { value, error } = await deleteThisThing(123)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment