mirror of
https://github.com/supabase/supabase.git
synced 2026-10-16 22:59:11 +03:00
* fix: response error codes * upgrade docs * remove request url modification middleware * move api routes for self-hosted to platform folder * remove some lib/common/fetch usage * docs: use middleware for openapi-fetch (#30600) Get rid of the unauthedAllowedPost function (I don't think there's any harm in letting any requests that require authentication to just 403, they should be disabled at the React Query level and if not they will fail gracefully enough...) * fix local count query * add default values for clone mutation * fix ts and codegen * add missing lodash dep to playwright tests * Fix the playwright tests to match the new folder structure for selfhosted variant. * remove unused import * Remove unused state * remove unused sql debug mutation * remove unused export * fix notifications query * fix jwt updating status * fix typescript * save sql snippet after renaming * update codegen & fix ts error * override array querySerializer --------- Co-authored-by: Charis <26616127+charislam@users.noreply.github.com> Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: Ivan Vasilov <vasilov.ivan@gmail.com>
126 lines
3.5 KiB
TypeScript
126 lines
3.5 KiB
TypeScript
import * as Sentry from '@sentry/nextjs'
|
|
import { API_URL } from 'lib/constants'
|
|
import { getAccessToken } from 'lib/gotrue'
|
|
import { uuidv4 } from 'lib/helpers'
|
|
import createClient from 'openapi-fetch'
|
|
import { ResponseError } from 'types'
|
|
import type { paths } from './api' // generated from openapi-typescript
|
|
|
|
const DEFAULT_HEADERS = {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json',
|
|
}
|
|
|
|
// This file will eventually replace what we currently have in lib/fetchWrapper, but will be currently unused until we get to that refactor
|
|
|
|
const client = createClient<paths>({
|
|
// [Joshen] Just FYI, the replace is temporary until we update env vars API_URL to remove /platform or /v1 - should just be the base URL
|
|
baseUrl: API_URL?.replace('/platform', ''),
|
|
referrerPolicy: 'no-referrer-when-downgrade',
|
|
headers: DEFAULT_HEADERS,
|
|
credentials: 'include',
|
|
querySerializer: {
|
|
array: {
|
|
style: 'form',
|
|
explode: false,
|
|
},
|
|
},
|
|
})
|
|
|
|
export async function constructHeaders(headersInit?: HeadersInit | undefined) {
|
|
const requestId = uuidv4()
|
|
const headers = new Headers(headersInit)
|
|
|
|
headers.set('X-Request-Id', requestId)
|
|
|
|
if (!headers.has('Authorization')) {
|
|
const accessToken = await getAccessToken()
|
|
if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`)
|
|
}
|
|
|
|
return headers
|
|
}
|
|
|
|
// Middleware
|
|
client.use(
|
|
{
|
|
// Middleware to add authorization headers to the request
|
|
async onRequest({ request }) {
|
|
const headers = await constructHeaders()
|
|
headers.forEach((value, key) => request.headers.set(key, value))
|
|
|
|
return request
|
|
},
|
|
},
|
|
{
|
|
// Middleware to format errors
|
|
async onResponse({ request, response }) {
|
|
if (response.ok) {
|
|
return response
|
|
}
|
|
|
|
// handle errors
|
|
try {
|
|
// attempt to parse the response body as JSON
|
|
let body = await response.clone().json()
|
|
|
|
// add code field to body
|
|
body.code = response.status
|
|
body.requestId = request.headers.get('X-Request-Id')
|
|
|
|
return new Response(JSON.stringify(body), {
|
|
headers: response.headers,
|
|
status: response.status,
|
|
statusText: response.statusText,
|
|
})
|
|
} catch {
|
|
// noop
|
|
}
|
|
|
|
return response
|
|
},
|
|
}
|
|
)
|
|
|
|
export const {
|
|
GET: get,
|
|
POST: post,
|
|
PUT: put,
|
|
PATCH: patch,
|
|
DELETE: del,
|
|
HEAD: head,
|
|
TRACE: trace,
|
|
OPTIONS: options,
|
|
} = client
|
|
|
|
export const handleError = (error: unknown): never => {
|
|
if (error && typeof error === 'object') {
|
|
const errorMessage =
|
|
'msg' in error && typeof error.msg === 'string'
|
|
? error.msg
|
|
: 'message' in error && typeof error.message === 'string'
|
|
? error.message
|
|
: undefined
|
|
|
|
const errorCode = 'code' in error && typeof error.code === 'number' ? error.code : undefined
|
|
const requestId =
|
|
'requestId' in error && typeof error.requestId === 'string' ? error.requestId : undefined
|
|
|
|
if (errorMessage) {
|
|
throw new ResponseError(errorMessage, errorCode, requestId)
|
|
}
|
|
}
|
|
|
|
if (error !== null && typeof error === 'object' && 'stack' in error) {
|
|
console.error(error.stack)
|
|
}
|
|
|
|
// the error doesn't have a message or msg property, so we can't throw it as an error. Log it via Sentry so that we can
|
|
// add handling for it.
|
|
Sentry.captureException(error)
|
|
|
|
// throw a generic error if we don't know what the error is. The message is intentionally vague because it might show
|
|
// up in the UI.
|
|
throw new ResponseError(undefined)
|
|
}
|