종단 간 GraphQL 오류 처리?
11918 단어 urqltypescriptgraphqlsvelte
백엔드
포장 오류 정보
내가 알아낸 것처럼 GraphQL 끝점에서 오류를 반환하는 유일한 방법은 리졸버에서 오류를 발생시키는 것입니다. 이 디자인은 백엔드와 프런트엔드 간에 오류 데이터를 전송하는 데 몇 가지 제한 사항을 부과합니다. 서버가 처리할 수 없는 잘못된 요청이 와서 오류와 정확히 무엇이 잘못되었는지에 대한 세부 정보를 반환하려고 한다고 가정해 보겠습니다. 다음 인터페이스에서 모든 정보를 압축한다고 가정합니다.
type ApiError = {
code: 400,
message: "The request was bad :("
}
제한으로 돌아가서 - 객체와 같은 것을
new Error(arg)
호출에 인수로 넣을 수 있는 방법은 없지만 ApiError
객체를 JSON 문자열로 변환할 수 있습니다. 그것은 모든 정보를 throwable에 패킹할 수 있는 이상한 작은 트릭입니다. 이것이 정보 전송에 관한 전부이지만 코드 구성에 대한 몇 가지 사항이 더 있습니다.오류를 발생시켜 GraphQL 끝점에서 오류를 반환하는 것은 편리할 수 있으며 Typescript 어설션 함수를 사용하면 유형이 안전할 수 있습니다. return 문을
if
문으로 래핑할 필요가 없습니다. 오류를 던지고 플랫 코드 구조를 유지하십시오. 정보를 오류 개체에 패킹하는 것과 결합해 보겠습니다.export const newApiError = (errorObject: ApiError) => {
return new Error(JSON.stringify(errorObject))
}
이제 할 수 있습니다
throw newApiError(apiError)
.하지만
if
문을 던질 필요가 있는지 확인하는 것은 여전히 필요합니다. 더 잘할 수 있을까요? 예, typescript 어설션 기능을 사용합니다.if 문 없애기
엔드포인트에서 요청을 수신하는 백엔드에 권한 부여가 필요하지만 요청에 자격 증명이 없다고 가정해 보십시오. "401: 인증되지 않음, 신임장 없음, 통과하지 못할 것입니다."라고 말하고 싶은 것 같습니다. 그렇다면 리졸버에서 가장 쉬운 방법은 무엇입니까? 다음과 같이 가정합니다.
// get an auth token somehow
const authToken string | null = req.headers.get("Authorization")
assert(
authToken,
"401: There are no creds, you shall not pass"
)
커스텀 어설션
그러나 그것은 유일한 문자열입니다. 객체와 같은 것을 assert 호출에 전달할 수 없으므로 assert 구현을 작성해 보겠습니다.
export function assertWithApiError<T>(
statement: T | null | undefined,
errorObject: ApiError
): asserts statement is T {
if (!statement) {
throw newApiError(errorObject)
}
}
Typescript assert 함수를 사용하면 데이터가 오류로 묶인 상태에서 직접 생성한 모든 throwable을 던질 수 있는 typesafe assertion을 사용할 수 있습니다.
// get an auth token somehow
const authToken: string | null = req.headers.get("Authorization")
assertWithApiError(
authToken,
{ message: 'Auth token is not presented', code: 401 }
)
// there is typescript knows that token is a string
프런트엔드
프런트 엔드 부분은 어떻습니까? 위에서 말했듯이 @svelte/urql 패키지를 사용하여 svelte 앱에서 GraphQL을 처리합니다. 코드를 살펴봅시다!
일반적인 @svelte/urql 사용 사례로 시작하십시오.
// mutation function is from @svelte/urql package
const editUserMutation = mutation<{ me: User }>({
query: EDIT_USER,
})
const { data, error } = await editMeMutation({ intro })
따라서 GraphQL 원래 오류의 배열을 포함하는 @svelte/urql의 오류
CombinedError
유형이 있습니다.
type OriginalError = {
message: string
stack: string
}
export const parseGraphqlApiErrors = (error: CombinedError): ApiError[] => error.graphQLErrors.map((e) => {
const rawOriginalError = (e.extensions?.originalError as OriginalError).message
return parseApiError(rawOriginalError)
})
export const parseApiError = (jsonString: string): ApiError => {
try {
const parsed: unknown = JSON.parse(jsonString)
if (apiErrorTypeGuard(parsed)) {
return parsed
} else {
throw new Error('got invalid api error')
}
} catch (e) {
console.error(e)
throw Error("Can't parse api error from json string")
}
}
const apiErrorTypeGuard = (possiblyError: any): possiblyError is ApiError =>
typeof possiblyError === 'object' && 'code' in possiblyError && 'message' in possiblyError
마지막에는 원하는 데이터로 채워진 오류를 발생시키는 사용자 지정 어설션과 해당 데이터를 추출할 수 있는 프런트엔드 코드가 있습니다. 그게 다야.
저는 GraphQL, Svelte 또는 Urql의 숙련된 사용자가 아닙니다. 위에서 설명한 것보다 더 나은 기존 솔루션을 알려주시고 제 아이디어가 누군가에게 도움이 되기를 바랍니다 :)
사진 제공 Mario Mendez
Reference
이 문제에 관하여(종단 간 GraphQL 오류 처리?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gf_developer/end-to-end-graphql-error-handling-4cbh텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)