mirror of
https://github.com/supabase/supabase.git
synced 2026-07-05 00:14:35 +08:00
* feat(content api): add error endpoint
Add an endpoint to return the details of a Supabase error, given the
error code and service.
Schema additions:
```graphql
type RootQueryType {
"...previous root queries"
"""Get the details of an error code returned from a Supabase service"""
error(code: String!, service: Service!): Error
}
"""An error returned by a Supabase service"""
type Error {
"""
The unique code identifying the error. The code is stable, and can be used for string matching during error handling.
"""
code: String!
"""The Supabase service that returns this error."""
service: Service!
"""The HTTP status code returned with this error."""
httpStatusCode: Int
"""
A human-readable message describing the error. The message is not stable, and should not be used for string matching during error handling. Use the code instead.
"""
message: String
}
enum Service {
AUTH
REALTIME
STORAGE
}
```
* test(content api): add tests for top-level query `error`
85 lines
1.8 KiB
TypeScript
85 lines
1.8 KiB
TypeScript
import { type PostgrestError } from '@supabase/supabase-js'
|
|
import { type ZodError } from 'zod'
|
|
|
|
type ObjectOrNever = object | never
|
|
|
|
export type ApiErrorGeneric = ApiError<ObjectOrNever>
|
|
|
|
export class ApiError<Details extends ObjectOrNever = never> extends Error {
|
|
constructor(
|
|
message: string,
|
|
public source?: unknown,
|
|
public details?: Details
|
|
) {
|
|
super(message)
|
|
}
|
|
|
|
isPrivate() {
|
|
return true
|
|
}
|
|
|
|
isUserError() {
|
|
return false
|
|
}
|
|
|
|
statusCode() {
|
|
return 500
|
|
}
|
|
}
|
|
|
|
export class InvalidRequestError<Details extends ObjectOrNever = never> extends ApiError<Details> {
|
|
constructor(message: string, source?: unknown, details?: Details) {
|
|
super(`Invalid request: ${message}`, source, details)
|
|
}
|
|
|
|
isPrivate() {
|
|
return false
|
|
}
|
|
|
|
isUserError() {
|
|
return true
|
|
}
|
|
|
|
statusCode() {
|
|
return 400
|
|
}
|
|
}
|
|
|
|
export class NoDataError<Details extends ObjectOrNever = never> extends ApiError<Details> {
|
|
constructor(message: string, source?: unknown, details?: Details) {
|
|
super(`Data not found: ${message}`, source, details)
|
|
}
|
|
|
|
isPrivate() {
|
|
return false
|
|
}
|
|
|
|
isUserError() {
|
|
return true
|
|
}
|
|
|
|
statusCode() {
|
|
return 404
|
|
}
|
|
}
|
|
|
|
export function convertUnknownToApiError(error: unknown): ApiError {
|
|
return new ApiError('Unknown error', error)
|
|
}
|
|
|
|
export function convertPostgrestToApiError(error: PostgrestError): ApiError {
|
|
const message = `${error.code}: ${error.hint}`
|
|
return new ApiError(message, error)
|
|
}
|
|
|
|
export function convertZodToInvalidRequestError(
|
|
error: ZodError,
|
|
prelude?: string
|
|
): InvalidRequestError {
|
|
const issue = error.issues[0]
|
|
const pathStr = issue.path.join('.')
|
|
const message = `${prelude ? `${prelude}: ` : ''}${issue.message} at key "${pathStr}"`
|
|
|
|
return new InvalidRequestError(message, error)
|
|
}
|