Skip to content

Commit

Permalink
Refactored GraphQL exceptions for error callbacks (#513)
Browse files Browse the repository at this point in the history
  • Loading branch information
indykoning authored Jun 11, 2024
1 parent 7a0e0ea commit 3a21462
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.
3 changes: 3 additions & 0 deletions resources/js/callbacks.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Vue.prototype.getCheckoutStep = (stepName) => {
}

Vue.prototype.updateCart = async function (data, response) {
if (!response?.data) {
return response?.data
}
cart.value = 'cart' in Object.values(response.data)[0] ? Object.values(response.data)[0].cart : Object.values(response.data)[0]

getAttributeValues().then((response) => {
Expand Down
23 changes: 15 additions & 8 deletions resources/js/components/GraphqlMutation.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script>
import { GraphQLError, magentoGraphQL } from '../fetch'
import InteractWithUser from './User/mixins/InteractWithUser'
export default {
Expand Down Expand Up @@ -121,19 +122,25 @@ export default {
;[query, variables, options] = await this.beforeRequest(this.query, this.variables, options)
}
let response = await magentoGraphQL(query, variables, options)
if (response.data.errors) {
let response = await magentoGraphQL(query, variables, options).catch(async (error) => {
if (!GraphQLError.prototype.isPrototypeOf(err)) {
throw error
}
const errorResponse = error.response.json()
if (this.errorCallback) {
await this.errorCallback(this.data, response)
return
await this.errorCallback(this.data, errorResponse)
}
this.error = response.data.errors[0].message
if (this.alert) {
Notify(response.data.errors[0].message, 'error')
error.errors.forEach((error) => {
Notify(error.message, 'error')
})
}
return errorResponse
})
if (response.data.errors) {
return
}
Expand Down
13 changes: 10 additions & 3 deletions resources/js/components/Product/AddToCart.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script>
import { GraphQLError } from '../../fetch'
import { mask, refreshMask } from '../../stores/useMask'
import InteractWithUser from './../User/mixins/InteractWithUser'
Expand Down Expand Up @@ -97,12 +98,13 @@ export default {
},
)
// If there are user errors we may still get a newly updated cart back.
await this.updateCart({}, response)
if (response.data.addProductsToCart.user_errors.length) {
throw new Error(response.data.addProductsToCart.user_errors[0].message)
}
await this.updateCart({}, response)
this.added = true
setTimeout(() => {
this.added = false
Expand All @@ -129,7 +131,12 @@ export default {
Notify(error.message, 'error')
}
error?.response && (await this.checkResponseForExpiredCart(error.response))
if (error?.response) {
if (!(await this.checkResponseForExpiredCart(error.response)) && GraphQLError.prototype.isPrototypeOf(error)) {
// If there are errors we may still get a newly updated cart back.
await this.updateCart({}, await error.response.json())
}
}
}
this.adding = false
Expand Down
52 changes: 34 additions & 18 deletions resources/js/fetch.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { token } from './stores/useUser'

class FetchError extends Error {
export class FetchError extends Error {
constructor(message, response) {
super(message)
this.response = response
Expand All @@ -9,15 +9,23 @@ class FetchError extends Error {
}
window.FetchError = FetchError

class SessionExpired extends FetchError {
export class GraphQLError extends FetchError {
constructor(errors, response) {
super(errors[0].message, response)
this.errors = errors
}
}
window.GraphQLError = GraphQLError

export class SessionExpired extends FetchError {
constructor(message, response) {
super(message, response)
this.name = this.constructor.name
}
}
window.SessionExpired = SessionExpired

window.rapidezFetch = ((originalFetch) => {
export const rapidezFetch = (window.rapidezFetch = ((originalFetch) => {
return (...args) => {
if (window.app.$data) {
window.app.$data.loadingCount++
Expand All @@ -31,9 +39,9 @@ window.rapidezFetch = ((originalFetch) => {
return args
})
}
})(fetch)
})(fetch))

window.rapidezAPI = async (method, endpoint, data = {}, options = {}) => {
export const rapidezAPI = (window.rapidezAPI = async (method, endpoint, data = {}, options = {}) => {
let response = await rapidezFetch(window.url('/api/' + endpoint), {
method: method.toUpperCase(),
headers: Object.assign(
Expand All @@ -52,9 +60,9 @@ window.rapidezAPI = async (method, endpoint, data = {}, options = {}) => {
}

return await response.json()
}
})

window.magentoGraphQL = async (
export const magentoGraphQL = (window.magentoGraphQL = async (
query,
variables = {},
options = {
Expand All @@ -76,19 +84,23 @@ window.magentoGraphQL = async (
variables: variables,
}),
})
// You can't call response.json() twice, in case of errors we pass our clone instead which hasn't been read.
let responseClone = response.clone()

if (!response.ok) {
throw new FetchError(window.config.translations.errors.wrong, response)
if (!response.ok && !response.headers?.get('content-type')?.includes('application/json')) {
throw new FetchError(window.config.translations.errors.wrong, responseClone)
}

// You can't call response.json() twice, in case of errors we pass our clone instead which hasn't been read.
let responseClone = response.clone()
let data = await response.json()

if (data.errors) {
if (data?.errors) {
console.error(data.errors)

if (data.errors[0]?.extensions?.category === 'graphql-authorization') {
data?.errors?.forEach((error) => {
if (error?.extensions?.category !== 'graphql-authorization') {
return
}

if (options?.notifyOnError ?? true) {
Notify(window.config.translations.errors.session_expired)
}
Expand All @@ -98,15 +110,19 @@ window.magentoGraphQL = async (
} else {
throw new SessionExpired(window.config.translations.errors.session_expired, responseClone)
}
}
})

throw new FetchError(data.errors[0].message, responseClone)
throw new GraphQLError(data.errors, responseClone)
}

if (!response.ok) {
throw new FetchError(window.config.translations.errors.wrong, responseClone)
}

return data
}
})

window.magentoAPI = async (
export const magentoAPI = (window.magentoAPI = async (
method,
endpoint,
data = {},
Expand Down Expand Up @@ -149,4 +165,4 @@ window.magentoAPI = async (
let responseData = await response.json()

return responseData
}
})

0 comments on commit 3a21462

Please sign in to comment.