From 9ccb32ce21574e81ad257d0a551ea9cc6e197f63 Mon Sep 17 00:00:00 2001 From: cond0r Date: Thu, 4 Mar 2021 10:37:51 +0200 Subject: [PATCH] Changes, fix Shopify GraphQL deprecations --- commerce.config.json | 4 +- framework/shopify/.env.template | 4 +- framework/shopify/auth/use-login.tsx | 9 +---- framework/shopify/auth/use-signup.tsx | 12 +----- framework/shopify/cart/index.ts | 1 + framework/shopify/cart/use-add-item.tsx | 9 +++-- framework/shopify/cart/use-cart.tsx | 2 +- framework/shopify/cart/use-remove-item.tsx | 13 +++---- framework/shopify/cart/use-update-item.tsx | 2 +- framework/shopify/cart/utils/fetcher.ts | 31 --------------- framework/shopify/cart/utils/index.ts | 2 - framework/shopify/provider.ts | 3 -- .../{cart => }/utils/checkout-create.ts | 11 +++--- .../{cart => }/utils/checkout-to-cart.ts | 28 ++++++-------- framework/shopify/utils/get-sort-variables.ts | 2 +- .../utils/handle-account-activation.ts | 11 ++---- framework/shopify/utils/handle-login.ts | 25 +----------- framework/shopify/utils/index.ts | 3 ++ .../utils/mutations/checkout-create.ts | 5 ++- .../utils/mutations/checkout-line-item-add.ts | 5 ++- .../mutations/checkout-line-item-remove.ts | 5 ++- .../mutations/checkout-line-item-update.ts | 5 ++- .../mutations/customer-access-token-delete.ts | 2 +- framework/shopify/utils/throw-user-errors.ts | 38 +++++++++++++++++++ tsconfig.json | 4 +- 25 files changed, 103 insertions(+), 133 deletions(-) delete mode 100644 framework/shopify/cart/utils/fetcher.ts delete mode 100644 framework/shopify/cart/utils/index.ts rename framework/shopify/{cart => }/utils/checkout-create.ts (72%) rename framework/shopify/{cart => }/utils/checkout-to-cart.ts (56%) create mode 100644 framework/shopify/utils/throw-user-errors.ts diff --git a/commerce.config.json b/commerce.config.json index bef7db222..e8418f296 100644 --- a/commerce.config.json +++ b/commerce.config.json @@ -1,7 +1,7 @@ { - "provider": "bigcommerce", + "provider": "shopify", "features": { - "wishlist": true, + "wishlist": false, "customCheckout": false } } diff --git a/framework/shopify/.env.template b/framework/shopify/.env.template index 24521c2a1..9dc3674b6 100644 --- a/framework/shopify/.env.template +++ b/framework/shopify/.env.template @@ -1,2 +1,2 @@ -SHOPIFY_STORE_DOMAIN= -SHOPIFY_STOREFRONT_ACCESS_TOKEN= +NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN= +NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN= diff --git a/framework/shopify/auth/use-login.tsx b/framework/shopify/auth/use-login.tsx index 188dd54a2..7993822cd 100644 --- a/framework/shopify/auth/use-login.tsx +++ b/framework/shopify/auth/use-login.tsx @@ -10,7 +10,7 @@ import { MutationCheckoutCreateArgs, } from '../schema' import useLogin, { UseLogin } from '@commerce/auth/use-login' -import { setCustomerToken } from '../utils' +import { setCustomerToken, throwUserErrors } from '../utils' export default useLogin as UseLogin @@ -45,13 +45,8 @@ export const handler: MutationHook = { }, }) - const errors = customerAccessTokenCreate?.customerUserErrors + throwUserErrors(customerAccessTokenCreate?.customerUserErrors) - if (errors && errors.length) { - throw new ValidationError({ - message: getErrorMessage(errors[0]), - }) - } const customerAccessToken = customerAccessTokenCreate?.customerAccessToken const accessToken = customerAccessToken?.accessToken diff --git a/framework/shopify/auth/use-signup.tsx b/framework/shopify/auth/use-signup.tsx index 65ed9f71d..9ca5c682f 100644 --- a/framework/shopify/auth/use-signup.tsx +++ b/framework/shopify/auth/use-signup.tsx @@ -10,7 +10,7 @@ import { } from '../schema' import { customerCreateMutation } from '../utils/mutations' -import { handleAutomaticLogin, handleAccountActivation } from '../utils' +import { handleAutomaticLogin, throwUserErrors } from '../utils' export default useSignup as UseSignup @@ -50,15 +50,7 @@ export const handler: MutationHook< }, }) - const errors = customerCreate?.customerUserErrors - - if (errors && errors.length) { - const [error] = errors - throw new ValidationError({ - message: error.message, - }) - } - + throwUserErrors(customerCreate?.customerUserErrors) await handleAutomaticLogin(fetch, { email, password }) return null diff --git a/framework/shopify/cart/index.ts b/framework/shopify/cart/index.ts index 3d288b1df..f6d36b443 100644 --- a/framework/shopify/cart/index.ts +++ b/framework/shopify/cart/index.ts @@ -1,3 +1,4 @@ export { default as useCart } from './use-cart' export { default as useAddItem } from './use-add-item' +export { default as useUpdateItem } from './use-update-item' export { default as useRemoveItem } from './use-remove-item' diff --git a/framework/shopify/cart/use-add-item.tsx b/framework/shopify/cart/use-add-item.tsx index 36f02847b..cce0950e9 100644 --- a/framework/shopify/cart/use-add-item.tsx +++ b/framework/shopify/cart/use-add-item.tsx @@ -1,12 +1,15 @@ +import { useCallback } from 'react' import type { MutationHook } from '@commerce/utils/types' import { CommerceError } from '@commerce/utils/errors' import useAddItem, { UseAddItem } from '@commerce/cart/use-add-item' import useCart from './use-cart' +import { + checkoutLineItemAddMutation, + getCheckoutId, + checkoutToCart, +} from '../utils' import { Cart, CartItemBody } from '../types' -import { checkoutLineItemAddMutation, getCheckoutId } from '../utils' -import { checkoutToCart } from './utils' import { Mutation, MutationCheckoutLineItemsAddArgs } from '../schema' -import { useCallback } from 'react' export default useAddItem as UseAddItem diff --git a/framework/shopify/cart/use-cart.tsx b/framework/shopify/cart/use-cart.tsx index a8be04969..ea1982c2c 100644 --- a/framework/shopify/cart/use-cart.tsx +++ b/framework/shopify/cart/use-cart.tsx @@ -6,7 +6,7 @@ import useCommerceCart, { import { Cart } from '../types' import { SWRHook } from '@commerce/utils/types' -import { checkoutCreate, checkoutToCart } from './utils' +import { checkoutCreate, checkoutToCart } from '../utils' import getCheckoutQuery from '../utils/queries/get-checkout-query' export default useCommerceCart as UseCart diff --git a/framework/shopify/cart/use-remove-item.tsx b/framework/shopify/cart/use-remove-item.tsx index e2aef13d8..8db38eac2 100644 --- a/framework/shopify/cart/use-remove-item.tsx +++ b/framework/shopify/cart/use-remove-item.tsx @@ -1,23 +1,22 @@ import { useCallback } from 'react' - import type { MutationHookContext, HookFetcherContext, } from '@commerce/utils/types' - +import { RemoveCartItemBody } from '@commerce/types' import { ValidationError } from '@commerce/utils/errors' - import useRemoveItem, { RemoveItemInput as RemoveItemInputBase, UseRemoveItem, } from '@commerce/cart/use-remove-item' - import useCart from './use-cart' -import { checkoutLineItemRemoveMutation, getCheckoutId } from '../utils' -import { checkoutToCart } from './utils' +import { + checkoutLineItemRemoveMutation, + getCheckoutId, + checkoutToCart, +} from '../utils' import { Cart, LineItem } from '../types' import { Mutation, MutationCheckoutLineItemsRemoveArgs } from '../schema' -import { RemoveCartItemBody } from '@commerce/types' export type RemoveItemFn = T extends LineItem ? (input?: RemoveItemInput) => Promise diff --git a/framework/shopify/cart/use-update-item.tsx b/framework/shopify/cart/use-update-item.tsx index 666ce3d08..49dd6be14 100644 --- a/framework/shopify/cart/use-update-item.tsx +++ b/framework/shopify/cart/use-update-item.tsx @@ -13,7 +13,7 @@ import useUpdateItem, { import useCart from './use-cart' import { handler as removeItemHandler } from './use-remove-item' import type { Cart, LineItem, UpdateCartItemBody } from '../types' -import { checkoutToCart } from './utils' +import { checkoutToCart } from '../utils' import { getCheckoutId, checkoutLineItemUpdateMutation } from '../utils' import { Mutation, MutationCheckoutLineItemsUpdateArgs } from '../schema' diff --git a/framework/shopify/cart/utils/fetcher.ts b/framework/shopify/cart/utils/fetcher.ts deleted file mode 100644 index 6afb55f18..000000000 --- a/framework/shopify/cart/utils/fetcher.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { HookFetcherFn } from '@commerce/utils/types' -import { Cart } from '@commerce/types' -import { checkoutCreate, checkoutToCart } from '.' -import { FetchCartInput } from '@commerce/cart/use-cart' - -const fetcher: HookFetcherFn = async ({ - options, - input: { cartId: checkoutId }, - fetch, -}) => { - let checkout - - if (checkoutId) { - const data = await fetch({ - ...options, - variables: { - checkoutId, - }, - }) - checkout = data.node - } - - if (checkout?.completedAt || !checkoutId) { - checkout = await checkoutCreate(fetch) - } - - // TODO: Fix this type - return checkoutToCart({ checkout } as any) -} - -export default fetcher diff --git a/framework/shopify/cart/utils/index.ts b/framework/shopify/cart/utils/index.ts deleted file mode 100644 index 20d04955d..000000000 --- a/framework/shopify/cart/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as checkoutToCart } from './checkout-to-cart' -export { default as checkoutCreate } from './checkout-create' diff --git a/framework/shopify/provider.ts b/framework/shopify/provider.ts index 383822baa..5041770c6 100644 --- a/framework/shopify/provider.ts +++ b/framework/shopify/provider.ts @@ -23,9 +23,6 @@ export const shopifyProvider = { customer: { useCustomer }, products: { useSearch }, auth: { useLogin, useLogout, useSignup }, - features: { - wishlist: false, - }, } export type ShopifyProvider = typeof shopifyProvider diff --git a/framework/shopify/cart/utils/checkout-create.ts b/framework/shopify/utils/checkout-create.ts similarity index 72% rename from framework/shopify/cart/utils/checkout-create.ts rename to framework/shopify/utils/checkout-create.ts index 20c23bcd3..359d16315 100644 --- a/framework/shopify/cart/utils/checkout-create.ts +++ b/framework/shopify/utils/checkout-create.ts @@ -1,12 +1,13 @@ +import Cookies from 'js-cookie' + import { SHOPIFY_CHECKOUT_ID_COOKIE, SHOPIFY_CHECKOUT_URL_COOKIE, SHOPIFY_COOKIE_EXPIRE, -} from '../../const' +} from '../const' -import checkoutCreateMutation from '../../utils/mutations/checkout-create' -import Cookies from 'js-cookie' -import { CheckoutCreatePayload } from '../../schema' +import checkoutCreateMutation from './mutations/checkout-create' +import { CheckoutCreatePayload } from '../schema' export const checkoutCreate = async ( fetch: any @@ -23,7 +24,7 @@ export const checkoutCreate = async ( expires: SHOPIFY_COOKIE_EXPIRE, } Cookies.set(SHOPIFY_CHECKOUT_ID_COOKIE, checkoutId, options) - Cookies.set(SHOPIFY_CHECKOUT_URL_COOKIE, checkout?.webUrl, options) + Cookies.set(SHOPIFY_CHECKOUT_URL_COOKIE, checkout.webUrl, options) } return checkout diff --git a/framework/shopify/cart/utils/checkout-to-cart.ts b/framework/shopify/utils/checkout-to-cart.ts similarity index 56% rename from framework/shopify/cart/utils/checkout-to-cart.ts rename to framework/shopify/utils/checkout-to-cart.ts index 5465e511c..b27b619d3 100644 --- a/framework/shopify/cart/utils/checkout-to-cart.ts +++ b/framework/shopify/utils/checkout-to-cart.ts @@ -1,20 +1,22 @@ -import { Cart } from '../../types' -import { CommerceError, ValidationError } from '@commerce/utils/errors' +import { Cart } from '../types' +import { CommerceError } from '@commerce/utils/errors' import { CheckoutLineItemsAddPayload, CheckoutLineItemsRemovePayload, CheckoutLineItemsUpdatePayload, CheckoutCreatePayload, + CheckoutUserError, Checkout, - UserError, -} from '../../schema' -import { normalizeCart } from '../../utils' -import { Maybe } from 'framework/bigcommerce/schema' + Maybe, +} from '../schema' + +import { normalizeCart } from './normalize' +import throwUserErrors from './throw-user-errors' export type CheckoutQuery = { checkout: Checkout - userErrors?: Array + checkoutUserErrors: Array } export type CheckoutPayload = @@ -27,22 +29,16 @@ export type CheckoutPayload = const checkoutToCart = (checkoutPayload?: Maybe): Cart => { if (!checkoutPayload) { throw new CommerceError({ - message: 'Invalid response from Shopify', + message: 'Missing checkout payload from response', }) } const checkout = checkoutPayload?.checkout - const userErrors = checkoutPayload?.userErrors - - if (userErrors && userErrors.length) { - throw new ValidationError({ - message: userErrors[0].message, - }) - } + throwUserErrors(checkoutPayload?.checkoutUserErrors) if (!checkout) { throw new CommerceError({ - message: 'Invalid response from Shopify', + message: 'Missing checkout object from response', }) } diff --git a/framework/shopify/utils/get-sort-variables.ts b/framework/shopify/utils/get-sort-variables.ts index b8cdeec51..141d9a180 100644 --- a/framework/shopify/utils/get-sort-variables.ts +++ b/framework/shopify/utils/get-sort-variables.ts @@ -1,4 +1,4 @@ -const getSortVariables = (sort?: string, isCategory = false) => { +const getSortVariables = (sort?: string, isCategory: boolean = false) => { let output = {} switch (sort) { case 'price-asc': diff --git a/framework/shopify/utils/handle-account-activation.ts b/framework/shopify/utils/handle-account-activation.ts index 3f5aff5b8..d11f80ba1 100644 --- a/framework/shopify/utils/handle-account-activation.ts +++ b/framework/shopify/utils/handle-account-activation.ts @@ -1,5 +1,6 @@ -import { ValidationError } from '@commerce/utils/errors' import { FetcherOptions } from '@commerce/utils/types' +import throwUserErrors from './throw-user-errors' + import { MutationCustomerActivateArgs, MutationCustomerActivateByUrlArgs, @@ -22,13 +23,7 @@ const handleAccountActivation = async ( }, }) - const errors = customerActivateByUrl?.customerUserErrors - if (errors && errors.length) { - const [error] = errors - throw new ValidationError({ - message: error.message, - }) - } + throwUserErrors(customerActivateByUrl?.customerUserErrors) } catch (error) {} } diff --git a/framework/shopify/utils/handle-login.ts b/framework/shopify/utils/handle-login.ts index 0a0a2e8ec..de86fa1d2 100644 --- a/framework/shopify/utils/handle-login.ts +++ b/framework/shopify/utils/handle-login.ts @@ -1,33 +1,12 @@ -import { ValidationError } from '@commerce/utils/errors' import { FetcherOptions } from '@commerce/utils/types' import { CustomerAccessTokenCreateInput } from '../schema' import { setCustomerToken } from './customer-token' import { customerAccessTokenCreateMutation } from './mutations' - -const getErrorMessage = ({ - code, - message, -}: { - code: string - message: string -}) => { - switch (code) { - case 'UNIDENTIFIED_CUSTOMER': - message = 'Cannot find an account that matches the provided credentials' - break - } - return message -} +import throwUserErrors from './throw-user-errors' const handleLogin = (data: any) => { const response = data.customerAccessTokenCreate - const errors = response?.customerUserErrors - - if (errors && errors.length) { - throw new ValidationError({ - message: getErrorMessage(errors[0]), - }) - } + throwUserErrors(response?.customerUserErrors) const customerAccessToken = response?.customerAccessToken const accessToken = customerAccessToken?.accessToken diff --git a/framework/shopify/utils/index.ts b/framework/shopify/utils/index.ts index 01a5743e5..61e5975d7 100644 --- a/framework/shopify/utils/index.ts +++ b/framework/shopify/utils/index.ts @@ -4,8 +4,11 @@ export { default as getSortVariables } from './get-sort-variables' export { default as getVendors } from './get-vendors' export { default as getCategories } from './get-categories' export { default as getCheckoutId } from './get-checkout-id' +export { default as checkoutCreate } from './checkout-create' +export { default as checkoutToCart } from './checkout-to-cart' export { default as handleLogin, handleAutomaticLogin } from './handle-login' export { default as handleAccountActivation } from './handle-account-activation' +export { default as throwUserErrors } from './throw-user-errors' export * from './queries' export * from './mutations' export * from './normalize' diff --git a/framework/shopify/utils/mutations/checkout-create.ts b/framework/shopify/utils/mutations/checkout-create.ts index 912e1cbd2..ffbd555c7 100644 --- a/framework/shopify/utils/mutations/checkout-create.ts +++ b/framework/shopify/utils/mutations/checkout-create.ts @@ -3,9 +3,10 @@ import { checkoutDetailsFragment } from '../queries/get-checkout-query' const checkoutCreateMutation = /* GraphQL */ ` mutation { checkoutCreate(input: {}) { - userErrors { - message + checkoutUserErrors { + code field + message } checkout { ${checkoutDetailsFragment} diff --git a/framework/shopify/utils/mutations/checkout-line-item-add.ts b/framework/shopify/utils/mutations/checkout-line-item-add.ts index 67b9cf250..2282c4e26 100644 --- a/framework/shopify/utils/mutations/checkout-line-item-add.ts +++ b/framework/shopify/utils/mutations/checkout-line-item-add.ts @@ -3,9 +3,10 @@ import { checkoutDetailsFragment } from '../queries/get-checkout-query' const checkoutLineItemAddMutation = /* GraphQL */ ` mutation($checkoutId: ID!, $lineItems: [CheckoutLineItemInput!]!) { checkoutLineItemsAdd(checkoutId: $checkoutId, lineItems: $lineItems) { - userErrors { - message + checkoutUserErrors { + code field + message } checkout { ${checkoutDetailsFragment} diff --git a/framework/shopify/utils/mutations/checkout-line-item-remove.ts b/framework/shopify/utils/mutations/checkout-line-item-remove.ts index d967a5168..8dea4ce08 100644 --- a/framework/shopify/utils/mutations/checkout-line-item-remove.ts +++ b/framework/shopify/utils/mutations/checkout-line-item-remove.ts @@ -6,9 +6,10 @@ const checkoutLineItemRemoveMutation = /* GraphQL */ ` checkoutId: $checkoutId lineItemIds: $lineItemIds ) { - userErrors { - message + checkoutUserErrors { + code field + message } checkout { ${checkoutDetailsFragment} diff --git a/framework/shopify/utils/mutations/checkout-line-item-update.ts b/framework/shopify/utils/mutations/checkout-line-item-update.ts index 8edf17587..76254341e 100644 --- a/framework/shopify/utils/mutations/checkout-line-item-update.ts +++ b/framework/shopify/utils/mutations/checkout-line-item-update.ts @@ -3,9 +3,10 @@ import { checkoutDetailsFragment } from '../queries/get-checkout-query' const checkoutLineItemUpdateMutation = /* GraphQL */ ` mutation($checkoutId: ID!, $lineItems: [CheckoutLineItemUpdateInput!]!) { checkoutLineItemsUpdate(checkoutId: $checkoutId, lineItems: $lineItems) { - userErrors { - message + checkoutUserErrors { + code field + message } checkout { ${checkoutDetailsFragment} diff --git a/framework/shopify/utils/mutations/customer-access-token-delete.ts b/framework/shopify/utils/mutations/customer-access-token-delete.ts index c46eff1e5..208e69c09 100644 --- a/framework/shopify/utils/mutations/customer-access-token-delete.ts +++ b/framework/shopify/utils/mutations/customer-access-token-delete.ts @@ -3,7 +3,7 @@ const customerAccessTokenDeleteMutation = /* GraphQL */ ` customerAccessTokenDelete(customerAccessToken: $customerAccessToken) { deletedAccessToken deletedCustomerAccessTokenId - userErrors { + customerUserErrors { field message } diff --git a/framework/shopify/utils/throw-user-errors.ts b/framework/shopify/utils/throw-user-errors.ts new file mode 100644 index 000000000..5488ba282 --- /dev/null +++ b/framework/shopify/utils/throw-user-errors.ts @@ -0,0 +1,38 @@ +import { ValidationError } from '@commerce/utils/errors' + +import { + CheckoutErrorCode, + CheckoutUserError, + CustomerErrorCode, + CustomerUserError, +} from '../schema' + +export type UserErrors = Array + +export type UserErrorCode = + | CustomerErrorCode + | CheckoutErrorCode + | null + | undefined + +const getCustomMessage = (code: UserErrorCode, message: string) => { + switch (code) { + case 'UNIDENTIFIED_CUSTOMER': + message = 'Cannot find an account that matches the provided credentials' + break + } + return message +} + +export const throwUserErrors = (errors?: UserErrors) => { + if (errors && errors.length) { + throw new ValidationError({ + errors: errors.map(({ code, message }) => ({ + code: code ?? 'validation_error', + message: getCustomMessage(code, message), + })), + }) + } +} + +export default throwUserErrors diff --git a/tsconfig.json b/tsconfig.json index 9e712fb18..e20f37099 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -22,8 +22,8 @@ "@components/*": ["components/*"], "@commerce": ["framework/commerce"], "@commerce/*": ["framework/commerce/*"], - "@framework": ["framework/bigcommerce"], - "@framework/*": ["framework/bigcommerce/*"] + "@framework": ["framework/shopify"], + "@framework/*": ["framework/shopify/*"] } }, "include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],