apiWrapper.ts60 lines · main
1import type { JwtPayload } from '@supabase/supabase-js'
2import type { NextApiRequest, NextApiResponse } from 'next'
3
4import { IS_PLATFORM } from '../constants'
5import { apiAuthenticate } from './apiAuthenticate'
6import { ResponseError, ResponseFailure } from '@/types'
7
8export function isResponseOk<T>(response: T | ResponseFailure | undefined): response is T {
9 if (response === undefined || response === null) {
10 return false
11 }
12
13 if (response instanceof ResponseError) {
14 return false
15 }
16
17 if (typeof response === 'object' && 'error' in response && Boolean(response.error)) {
18 return false
19 }
20
21 return true
22}
23
24// Purpose of this apiWrapper is to function like a global catchall for ANY errors
25// It's a safety net as the API service should never drop, nor fail
26
27async function apiWrapper(
28 req: NextApiRequest,
29 res: NextApiResponse,
30 handler: (
31 req: NextApiRequest,
32 res: NextApiResponse,
33 claims?: JwtPayload
34 ) => Promise<NextApiResponse | Response | void>,
35 options?: { withAuth: boolean }
36): Promise<NextApiResponse | Response | void> {
37 try {
38 const { withAuth } = options || {}
39 let claims: JwtPayload | undefined
40
41 if (IS_PLATFORM && withAuth) {
42 const response = await apiAuthenticate(req, res)
43 if (!isResponseOk(response)) {
44 return res.status(401).json({
45 error: {
46 message: `Unauthorized: ${response.error.message}`,
47 },
48 })
49 }
50 claims = response
51 }
52
53 return handler(req, res, claims)
54 } catch (error) {
55 return res.status(500).json({ error })
56 }
57}
58
59export { apiWrapper }
60export default apiWrapper