mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(server): introduce user friendly server errors (#7111)
This commit is contained in:
@@ -102,11 +102,8 @@ describe('GraphQL fetcher', () => {
|
||||
)
|
||||
);
|
||||
|
||||
await expect(gql({ query, variables: void 0 })).rejects
|
||||
.toMatchInlineSnapshot(`
|
||||
[
|
||||
[GraphQLError: error],
|
||||
]
|
||||
`);
|
||||
await expect(
|
||||
gql({ query, variables: void 0 })
|
||||
).rejects.toMatchInlineSnapshot(`[GraphQLError: error]`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,26 +1,59 @@
|
||||
import { GraphQLError as BaseGraphQLError } from 'graphql';
|
||||
import { identity } from 'lodash-es';
|
||||
|
||||
interface KnownGraphQLErrorExtensions {
|
||||
code: number;
|
||||
status: string;
|
||||
originalError?: unknown;
|
||||
import { type ErrorDataUnion, ErrorNames } from './schema';
|
||||
|
||||
export interface UserFriendlyErrorResponse {
|
||||
status: number;
|
||||
code: string;
|
||||
type: string;
|
||||
name: ErrorNames;
|
||||
message: string;
|
||||
args?: any;
|
||||
stacktrace?: string;
|
||||
}
|
||||
|
||||
export class UserFriendlyError implements UserFriendlyErrorResponse {
|
||||
status = this.response.status;
|
||||
code = this.response.code;
|
||||
type = this.response.type;
|
||||
name = this.response.name;
|
||||
message = this.response.message;
|
||||
args = this.response.args;
|
||||
stacktrace = this.response.stacktrace;
|
||||
|
||||
static fromAnyError(response: any) {
|
||||
if (response instanceof GraphQLError) {
|
||||
return new UserFriendlyError(response.extensions);
|
||||
}
|
||||
|
||||
if (typeof response === 'object' && response.type && response.name) {
|
||||
return new UserFriendlyError(response);
|
||||
}
|
||||
|
||||
return new UserFriendlyError({
|
||||
status: 500,
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
type: 'INTERNAL_SERVER_ERROR',
|
||||
name: ErrorNames.INTERNAL_SERVER_ERROR,
|
||||
message: 'Internal server error',
|
||||
});
|
||||
}
|
||||
|
||||
constructor(private readonly response: UserFriendlyErrorResponse) {}
|
||||
}
|
||||
|
||||
export class GraphQLError extends BaseGraphQLError {
|
||||
// @ts-expect-error better to be a known type without any type casting
|
||||
override extensions!: KnownGraphQLErrorExtensions;
|
||||
}
|
||||
export function findGraphQLError(
|
||||
errOrArr: any,
|
||||
filter: (err: GraphQLError) => boolean = identity
|
||||
): GraphQLError | undefined {
|
||||
if (errOrArr instanceof GraphQLError) {
|
||||
return filter(errOrArr) ? errOrArr : undefined;
|
||||
} else if (Array.isArray(errOrArr)) {
|
||||
return errOrArr.find(err => err instanceof GraphQLError && filter(err));
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
override extensions!: UserFriendlyErrorResponse;
|
||||
}
|
||||
|
||||
type ToPascalCase<S extends string> = S extends `${infer A}_${infer B}`
|
||||
? `${Capitalize<Lowercase<A>>}${ToPascalCase<B>}`
|
||||
: Capitalize<Lowercase<S>>;
|
||||
|
||||
export type ErrorData = {
|
||||
[K in ErrorNames]: Extract<
|
||||
ErrorDataUnion,
|
||||
{ __typename?: `${ToPascalCase<K>}DataType` }
|
||||
>;
|
||||
};
|
||||
|
||||
@@ -195,9 +195,9 @@ export const gqlFetcherFactory = (
|
||||
const result = (await res.json()) as ExecutionResult;
|
||||
if (res.status >= 400 || result.errors) {
|
||||
if (result.errors && result.errors.length > 0) {
|
||||
throw result.errors.map(
|
||||
error => new GraphQLError(error.message, error)
|
||||
);
|
||||
// throw the first error is enough
|
||||
const firstError = result.errors[0];
|
||||
throw new GraphQLError(firstError.message, firstError);
|
||||
} else {
|
||||
throw new GraphQLError('Empty GraphQL error body');
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user