mirror of
https://github.com/vuejs/apollo.git
synced 2025-12-08 18:02:09 +00:00
feat: convert errors into ApolloError (#1225)
This commit is contained in:
parent
08b6b0e7d9
commit
334310d5e6
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -4,5 +4,6 @@
|
||||
"javascriptreact",
|
||||
"vue"
|
||||
],
|
||||
"eslint.enable": true
|
||||
"eslint.enable": true,
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { DocumentNode } from 'graphql'
|
||||
import { MutationOptions, OperationVariables, FetchResult, TypedDocumentNode } from '@apollo/client/core'
|
||||
import { MutationOptions, OperationVariables, FetchResult, TypedDocumentNode, ApolloError } from '@apollo/client/core'
|
||||
import { ref, onBeforeUnmount, isRef, Ref, getCurrentInstance } from 'vue-demi'
|
||||
import { useApolloClient } from './useApolloClient'
|
||||
import { ReactiveFunction } from './util/ReactiveFunction'
|
||||
import { useEventHook } from './util/useEventHook'
|
||||
import { trackMutation } from './util/loadingTracking'
|
||||
import { toApolloError } from './util/toApolloError'
|
||||
|
||||
/**
|
||||
* `useMutation` options for mutations that don't require `variables`.
|
||||
@ -27,12 +28,12 @@ export type MutateFunction<TResult, TVariables> = (variables?: TVariables | null
|
||||
export interface UseMutationReturn<TResult, TVariables> {
|
||||
mutate: MutateFunction<TResult, TVariables>
|
||||
loading: Ref<boolean>
|
||||
error: Ref<Error | null>
|
||||
error: Ref<ApolloError | null>
|
||||
called: Ref<boolean>
|
||||
onDone: (fn: (param: FetchResult<TResult, Record<string, any>, Record<string, any>>) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
onError: (fn: (param: Error) => void) => {
|
||||
onError: (fn: (param: ApolloError) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
}
|
||||
@ -47,11 +48,11 @@ export function useMutation<
|
||||
const vm = getCurrentInstance()
|
||||
const loading = ref<boolean>(false)
|
||||
vm && trackMutation(loading)
|
||||
const error = ref<Error | null>(null)
|
||||
const error = ref<ApolloError | null>(null)
|
||||
const called = ref<boolean>(false)
|
||||
|
||||
const doneEvent = useEventHook<FetchResult<TResult, Record<string, any>, Record<string, any>>>()
|
||||
const errorEvent = useEventHook<Error>()
|
||||
const errorEvent = useEventHook<ApolloError>()
|
||||
|
||||
// Apollo Client
|
||||
const { resolveClient } = useApolloClient()
|
||||
@ -94,11 +95,12 @@ export function useMutation<
|
||||
doneEvent.trigger(result)
|
||||
return result
|
||||
} catch (e) {
|
||||
error.value = e
|
||||
const apolloError = toApolloError(e)
|
||||
error.value = apolloError
|
||||
loading.value = false
|
||||
errorEvent.trigger(e)
|
||||
errorEvent.trigger(apolloError)
|
||||
if (currentOptions.throws === 'always' || (currentOptions.throws !== 'never' && !errorEvent.getCount())) {
|
||||
throw e
|
||||
throw apolloError
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
@ -20,6 +20,7 @@ import {
|
||||
FetchMoreOptions,
|
||||
ObservableSubscription,
|
||||
TypedDocumentNode,
|
||||
ApolloError,
|
||||
} from '@apollo/client/core'
|
||||
import { throttle, debounce } from 'throttle-debounce'
|
||||
import { useApolloClient } from './useApolloClient'
|
||||
@ -28,6 +29,7 @@ import { paramToRef } from './util/paramToRef'
|
||||
import { paramToReactive } from './util/paramToReactive'
|
||||
import { useEventHook } from './util/useEventHook'
|
||||
import { trackQuery } from './util/loadingTracking'
|
||||
import { toApolloError } from './util/toApolloError'
|
||||
|
||||
import type { CurrentInstance } from './util/types'
|
||||
|
||||
@ -58,7 +60,7 @@ export interface UseQueryReturn<TResult, TVariables> {
|
||||
result: Ref<TResult | undefined>
|
||||
loading: Ref<boolean>
|
||||
networkStatus: Ref<number | undefined>
|
||||
error: Ref<Error | null>
|
||||
error: Ref<ApolloError | null>
|
||||
start: () => void
|
||||
stop: () => void
|
||||
restart: () => void
|
||||
@ -73,7 +75,7 @@ export interface UseQueryReturn<TResult, TVariables> {
|
||||
onResult: (fn: (param: ApolloQueryResult<TResult>) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
onError: (fn: (param: Error) => void) => {
|
||||
onError: (fn: (param: ApolloError) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
}
|
||||
@ -154,8 +156,8 @@ export function useQueryImpl<
|
||||
*/
|
||||
const result = ref<TResult | undefined>()
|
||||
const resultEvent = useEventHook<ApolloQueryResult<TResult>>()
|
||||
const error = ref<Error | null>(null)
|
||||
const errorEvent = useEventHook<Error>()
|
||||
const error = ref<ApolloError | null>(null)
|
||||
const errorEvent = useEventHook<ApolloError>()
|
||||
|
||||
// Loading
|
||||
|
||||
@ -168,7 +170,7 @@ export function useQueryImpl<
|
||||
|
||||
// SSR
|
||||
let firstResolve: (() => void) | undefined
|
||||
let firstReject: ((error: Error) => void) | undefined
|
||||
let firstReject: ((apolloError: ApolloError) => void) | undefined
|
||||
onServerPrefetch?.(() => {
|
||||
if (!isEnabled.value || (isServer && currentOptions.value?.prefetch === false)) return
|
||||
|
||||
@ -178,8 +180,8 @@ export function useQueryImpl<
|
||||
firstResolve = undefined
|
||||
firstReject = undefined
|
||||
}
|
||||
firstReject = (error: Error) => {
|
||||
reject(error)
|
||||
firstReject = (apolloError: ApolloError) => {
|
||||
reject(apolloError)
|
||||
firstResolve = undefined
|
||||
firstReject = undefined
|
||||
}
|
||||
@ -258,15 +260,10 @@ export function useQueryImpl<
|
||||
|
||||
processNextResult(queryResult)
|
||||
|
||||
// Result errors
|
||||
// This is set when `errorPolicy` is `all`
|
||||
if (queryResult.errors?.length) {
|
||||
const e = new Error(`GraphQL error: ${queryResult.errors.map(e => e.message).join(' | ')}`)
|
||||
Object.assign(e, {
|
||||
graphQLErrors: queryResult.errors,
|
||||
networkError: null,
|
||||
})
|
||||
processError(e)
|
||||
// ApolloQueryResult.error may be set at the same time as we get a result
|
||||
// when `errorPolicy` is `all`
|
||||
if (queryResult.error !== undefined) {
|
||||
processError(queryResult.error)
|
||||
} else {
|
||||
if (firstResolve) {
|
||||
firstResolve()
|
||||
@ -282,22 +279,25 @@ export function useQueryImpl<
|
||||
resultEvent.trigger(queryResult)
|
||||
}
|
||||
|
||||
function onError (queryError: any) {
|
||||
function onError (queryError: unknown) {
|
||||
// any error should already be an ApolloError, but we make sure
|
||||
const apolloError = toApolloError(queryError)
|
||||
|
||||
processNextResult((query.value as ObservableQuery<TResult, TVariables>).getCurrentResult())
|
||||
processError(queryError)
|
||||
processError(apolloError)
|
||||
if (firstReject) {
|
||||
firstReject(queryError)
|
||||
firstReject(apolloError)
|
||||
stop()
|
||||
}
|
||||
// The observable closes the sub if an error occurs
|
||||
resubscribeToQuery()
|
||||
}
|
||||
|
||||
function processError (queryError: any) {
|
||||
error.value = queryError
|
||||
function processError (apolloError: ApolloError) {
|
||||
error.value = apolloError
|
||||
loading.value = false
|
||||
networkStatus.value = 8
|
||||
errorEvent.trigger(queryError)
|
||||
errorEvent.trigger(apolloError)
|
||||
}
|
||||
|
||||
function resubscribeToQuery () {
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
Observable,
|
||||
ObservableSubscription,
|
||||
TypedDocumentNode,
|
||||
ApolloError,
|
||||
} from '@apollo/client/core'
|
||||
import { throttle, debounce } from 'throttle-debounce'
|
||||
import { ReactiveFunction } from './util/ReactiveFunction'
|
||||
@ -26,6 +27,7 @@ import { useEventHook } from './util/useEventHook'
|
||||
import { trackSubscription } from './util/loadingTracking'
|
||||
|
||||
import type { CurrentInstance } from './util/types'
|
||||
import { toApolloError } from './util/toApolloError'
|
||||
|
||||
export interface UseSubscriptionOptions <
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
@ -45,7 +47,7 @@ type OptionsParameter<TResult, TVariables> = UseSubscriptionOptions<TResult, TVa
|
||||
export interface UseSubscriptionReturn<TResult, TVariables> {
|
||||
result: Ref<TResult | null | undefined>
|
||||
loading: Ref<boolean>
|
||||
error: Ref<Error | null>
|
||||
error: Ref<ApolloError | null>
|
||||
start: () => void
|
||||
stop: () => void
|
||||
restart: () => void
|
||||
@ -56,7 +58,7 @@ export interface UseSubscriptionReturn<TResult, TVariables> {
|
||||
onResult: (fn: (param: FetchResult<TResult, Record<string, any>, Record<string, any>>) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
onError: (fn: (param: Error) => void) => {
|
||||
onError: (fn: (param: ApolloError) => void) => {
|
||||
off: () => void
|
||||
}
|
||||
}
|
||||
@ -119,8 +121,8 @@ export function useSubscription <
|
||||
|
||||
const result = ref<TResult | null | undefined>()
|
||||
const resultEvent = useEventHook<FetchResult<TResult>>()
|
||||
const error = ref<Error | null>(null)
|
||||
const errorEvent = useEventHook<Error>()
|
||||
const error = ref<ApolloError | null>(null)
|
||||
const errorEvent = useEventHook<ApolloError>()
|
||||
|
||||
const loading = ref(false)
|
||||
vm && trackSubscription(loading)
|
||||
@ -157,10 +159,12 @@ export function useSubscription <
|
||||
resultEvent.trigger(fetchResult)
|
||||
}
|
||||
|
||||
function onError (fetchError: any) {
|
||||
error.value = fetchError
|
||||
function onError (fetchError: unknown) {
|
||||
const apolloError = toApolloError(fetchError)
|
||||
|
||||
error.value = apolloError
|
||||
loading.value = false
|
||||
errorEvent.trigger(fetchError)
|
||||
errorEvent.trigger(apolloError)
|
||||
}
|
||||
|
||||
function stop () {
|
||||
|
||||
16
packages/vue-apollo-composable/src/util/toApolloError.ts
Normal file
16
packages/vue-apollo-composable/src/util/toApolloError.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { ApolloError, isApolloError } from '@apollo/client'
|
||||
|
||||
export function toApolloError (error: unknown): ApolloError {
|
||||
if (!(error instanceof Error)) {
|
||||
return new ApolloError({
|
||||
networkError: Object.assign(new Error(), { originalError: error }),
|
||||
errorMessage: String(error),
|
||||
})
|
||||
}
|
||||
|
||||
if (isApolloError(error)) {
|
||||
return error
|
||||
}
|
||||
|
||||
return new ApolloError({ networkError: error, errorMessage: error.message })
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user