Skip to content

Instantly share code, notes, and snippets.

@bagus2x
Last active December 6, 2023 08:42
Show Gist options
  • Save bagus2x/06071a40dce62cab71b55039d89c5b9d to your computer and use it in GitHub Desktop.
Save bagus2x/06071a40dce62cab71b55039d89c5b9d to your computer and use it in GitHub Desktop.
Useful rest client interceptor with next-auth 5 and nextjs fetch.
import { auth } from '@pengode/auth'
const getBearer = async () => {
const session = await auth()
if (!session?.user.accessToken) return
return `Bearer ${session.user.accessToken}`
}
export type RestClientRequest = Omit<RequestInit, 'body'> & {
url: string
body?: any
}
export class RestError<T> extends Error {
constructor(
readonly res: Response,
readonly message: string,
readonly data: T,
) {
super(message)
}
}
export const withAuth = (
method: <T>(req: RestClientRequest) => Promise<T>,
): (<T>(req: RestClientRequest) => Promise<T>) => {
return async (req) => {
const bearer = await getBearer()
if (bearer) {
req.headers = {
...req.headers,
Authorization: bearer,
}
}
return await method(req)
}
}
export async function get<T>({
url,
body,
headers,
...customInit
}: RestClientRequest): Promise<T> {
const init: RequestInit = {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
...customInit,
}
const res = await fetch(url, init)
const data = await res.json()
if (!res.ok) {
throw new RestError(res, 'Failed to get ' + url, data)
}
return data
}
export async function post<T>({
url,
body,
headers,
...customInit
}: RestClientRequest): Promise<T> {
const init: RequestInit = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
...customInit,
}
const res = await fetch(url, init)
const data = await res.json()
if (!res.ok) {
throw new RestError(res, 'Failed to post ' + url, data)
}
return data
}
export async function put<T>({
url,
body,
headers,
...customInit
}: RestClientRequest): Promise<T> {
const init: RequestInit = {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
...customInit,
}
const res = await fetch(url, init)
const data = await res.json()
if (!res.ok) {
throw new RestError(res, 'Failed to put ' + url, data)
}
return data
}
export async function patch<T>({
url,
body,
headers,
...customInit
}: RestClientRequest): Promise<T> {
const init: RequestInit = {
method: 'PATCH',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
...customInit,
}
const res = await fetch(url, init)
const data = await res.json()
if (!res.ok) {
throw new RestError(res, 'Failed to patch ' + url, data)
}
return data
}
export async function del<T>({
url,
body,
headers,
...customInit
}: RestClientRequest): Promise<T> {
const init: RequestInit = {
method: 'DELETE',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
...customInit,
}
const res = await fetch(url, init)
const data = await res.json()
if (!res.ok) {
throw new RestError(res, 'Failed to delete ' + url, data)
}
return data
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment