Skip to content

Instantly share code, notes, and snippets.

@DouglasdeMoura
Last active April 1, 2024 15:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save DouglasdeMoura/59ce418672d0e33dda7056b382b01de9 to your computer and use it in GitHub Desktop.
Save DouglasdeMoura/59ce418672d0e33dda7056b382b01de9 to your computer and use it in GitHub Desktop.
Tiny wrapper around fetch
// Extends the return of the HTTPError class
class HTTPError extends Error {
readonly response: any;
readonly status: number;
readonly statusText: string;
constructor(status: number, statusText: string, response: any) {
super(statusText);
this.status = status;
this.statusText = statusText;
this.response = response;
}
}
const createQuery =
(baseURL: RequestInfo | URL = '', baseInit?: RequestInit) =>
<TResponse = unknown>(url: RequestInfo | URL, init?: RequestInit) =>
fetch(`${baseURL}${url}`, { ...baseInit, ...init }).then(async (res) => {
// Now, we get the JSON response early
const response = await res.json()
if (!res.ok)
throw new HTTPError(res.status, res.statusText, response);
return response as TResponse
})
// In this function, we define our base URL and headers.
const query = createQuery(
'https://dummyjson.com',
{
headers: {
'Content-Type': 'application/json',
// 'Authorization': `Bearer ${getToken()}`, // If you need to add a token to the header, you can do it here.
},
})
const makeRequest = (method: RequestInit['method']) =>
<TResponse = unknown, TBody = Record<string, unknown>>(url: RequestInfo | URL, body: TBody) =>
query<TResponse>(url, {
method,
body: JSON.stringify(body),
})
export const api = {
get: query,
post: makeRequest('POST'),
delete: makeRequest('DELETE'),
put: makeRequest('PUT'),
patch: makeRequest('PATCH'),
}
@dnaumenko
Copy link

Nice! My simplified version looks like this:

class HTTPError extends Error {
  readonly response: any
  readonly status: number
  readonly statusText: string

  constructor(status: number, statusText: string, response: any) {
    super(statusText)
    this.status = status
    this.statusText = statusText
    this.response = response
  }
}

export default function createHttpClient(baseURL: string, authorization: string) {
  function makeRequest(method: string) {
    return async <TResponse>(url: string, body: Record<string, unknown>) => {
      const res = await fetch(`${baseURL}${url}`, {
        method,
        headers: {
          'Content-Type': 'application/json',
          'Authorization': authorization,
        },
        body: JSON.stringify(body),
      })

      const response = await res.json()
      if (!res.ok) throw new HTTPError(res.status, res.statusText, response)
      return response as TResponse
    }
  }

  return {
    get: makeRequest('GET'),
    post: makeRequest('POST'),
    delete: makeRequest('DELETE'),
    put: makeRequest('PUT'),
    patch: makeRequest('PATCH'),
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment