From f698dea69808860b22036eef1aa95ae1b3637d2d Mon Sep 17 00:00:00 2001
From: cond0r <pinte_catalin@yahoo.com>
Date: Tue, 16 Feb 2021 10:15:18 +0200
Subject: [PATCH] Moved handler to each hook

---
 framework/bigcommerce/product/get-product.ts  |   2 +-
 framework/shopify/cart/use-add-item.tsx       |   7 +-
 framework/shopify/cart/use-cart.tsx           |  42 ++++-
 .../shopify/cart/utils/checkout-to-cart.ts    |   2 +-
 framework/shopify/cart/utils/fetcher.ts       |  30 ++++
 framework/shopify/cart/utils/index.ts         |   1 +
 framework/shopify/customer/use-customer.tsx   |  21 +++
 framework/shopify/fetcher.ts                  |  18 ++
 framework/shopify/product/get-all-products.ts |   2 +-
 framework/shopify/product/get-product.ts      |   2 +-
 framework/shopify/product/use-search.tsx      |  51 ++++++
 framework/shopify/provider.ts                 |  18 ++
 framework/shopify/provider.tsx                | 161 ------------------
 .../shopify/utils/get-search-variables.ts     |   2 +-
 framework/shopify/utils/index.ts              |   4 +-
 framework/shopify/utils/mutations/index.ts    |   2 +
 framework/shopify/{lib => utils}/normalize.ts |   0
 17 files changed, 195 insertions(+), 170 deletions(-)
 create mode 100644 framework/shopify/cart/utils/fetcher.ts
 create mode 100644 framework/shopify/fetcher.ts
 create mode 100644 framework/shopify/provider.ts
 delete mode 100644 framework/shopify/provider.tsx
 rename framework/shopify/{lib => utils}/normalize.ts (100%)

diff --git a/framework/bigcommerce/product/get-product.ts b/framework/bigcommerce/product/get-product.ts
index 7d77eb194..794d89bdf 100644
--- a/framework/bigcommerce/product/get-product.ts
+++ b/framework/bigcommerce/product/get-product.ts
@@ -2,7 +2,7 @@ import type { GetProductQuery, GetProductQueryVariables } from '../schema'
 import setProductLocaleMeta from '../api/utils/set-product-locale-meta'
 import { productInfoFragment } from '../api/fragments/product'
 import { BigcommerceConfig, getConfig } from '../api'
-import { normalizeProduct } from '@framework/lib/normalize'
+import { normalizeProduct } from '@framework/utils/normalize'
 import type { Product } from '@commerce/types'
 
 export const getProductQuery = /* GraphQL */ `
diff --git a/framework/shopify/cart/use-add-item.tsx b/framework/shopify/cart/use-add-item.tsx
index b5b34adc3..162627057 100644
--- a/framework/shopify/cart/use-add-item.tsx
+++ b/framework/shopify/cart/use-add-item.tsx
@@ -1,13 +1,16 @@
 import { useCallback } from 'react'
 import useCart from './use-cart'
+
 import useCartAddItem, {
   AddItemInput as UseAddItemInput,
 } from '@commerce/cart/use-add-item'
+
 import type { HookFetcher } from '@commerce/utils/types'
 import type { Cart } from '@commerce/types'
-import checkoutLineItemAddMutation from '../utils/mutations/checkout-line-item-add'
-import getCheckoutId from '@framework/utils/get-checkout-id'
+
+import { checkoutLineItemAddMutation, getCheckoutId } from '@framework/utils'
 import { checkoutToCart } from './utils'
+
 import { AddCartItemBody, CartItemBody } from '@framework/types'
 import { MutationCheckoutLineItemsAddArgs } from '@framework/schema'
 
diff --git a/framework/shopify/cart/use-cart.tsx b/framework/shopify/cart/use-cart.tsx
index e5ab8cafb..f5749731f 100644
--- a/framework/shopify/cart/use-cart.tsx
+++ b/framework/shopify/cart/use-cart.tsx
@@ -1,4 +1,44 @@
-import useCommerceCart, { UseCart } from '@commerce/cart/use-cart'
+import { useMemo } from 'react'
 import type { ShopifyProvider } from '..'
 
+import useCommerceCart, {
+  FetchCartInput,
+  UseCart,
+} from '@commerce/cart/use-cart'
+
+import { Cart } from '@commerce/types'
+import { HookHandler } from '@commerce/utils/types'
+
+import fetcher from './utils/fetcher'
+import getCheckoutQuery from '@framework/utils/queries/get-checkout-query'
+
 export default useCommerceCart as UseCart<ShopifyProvider>
+
+export const handler: HookHandler<
+  Cart | null,
+  {},
+  FetchCartInput,
+  { isEmpty?: boolean }
+> = {
+  fetchOptions: {
+    query: getCheckoutQuery,
+  },
+  fetcher,
+  useHook({ input, useData }) {
+    const response = useData({
+      swrOptions: { revalidateOnFocus: false, ...input.swrOptions },
+    })
+    return useMemo(
+      () =>
+        Object.create(response, {
+          isEmpty: {
+            get() {
+              return (response.data?.lineItems.length ?? 0) <= 0
+            },
+            enumerable: true,
+          },
+        }),
+      [response]
+    )
+  },
+}
diff --git a/framework/shopify/cart/utils/checkout-to-cart.ts b/framework/shopify/cart/utils/checkout-to-cart.ts
index 4c64d23e6..a8e91fbe1 100644
--- a/framework/shopify/cart/utils/checkout-to-cart.ts
+++ b/framework/shopify/cart/utils/checkout-to-cart.ts
@@ -1,6 +1,6 @@
 import { Cart } from '@commerce/types'
 import { CommerceError, ValidationError } from '@commerce/utils/errors'
-import { normalizeCart } from '@framework/lib/normalize'
+import { normalizeCart } from '@framework/utils/normalize'
 import { Checkout, Maybe, UserError } from '@framework/schema'
 
 const checkoutToCart = (checkoutResponse?: {
diff --git a/framework/shopify/cart/utils/fetcher.ts b/framework/shopify/cart/utils/fetcher.ts
new file mode 100644
index 000000000..6621b7fde
--- /dev/null
+++ b/framework/shopify/cart/utils/fetcher.ts
@@ -0,0 +1,30 @@
+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<Cart | null, FetchCartInput> = async ({
+  options,
+  input: { cartId },
+  fetch,
+}) => {
+  let checkout
+
+  if (cartId) {
+    const data = await fetch({
+      ...options,
+      variables: {
+        cartId,
+      },
+    })
+    checkout = data?.node
+  }
+
+  if (checkout?.completedAt || !cartId) {
+    checkout = await checkoutCreate(fetch)
+  }
+
+  return checkoutToCart({ checkout })
+}
+
+export default fetcher
diff --git a/framework/shopify/cart/utils/index.ts b/framework/shopify/cart/utils/index.ts
index 20d04955d..0f2b4a6ca 100644
--- a/framework/shopify/cart/utils/index.ts
+++ b/framework/shopify/cart/utils/index.ts
@@ -1,2 +1,3 @@
 export { default as checkoutToCart } from './checkout-to-cart'
 export { default as checkoutCreate } from './checkout-create'
+export { default as fetcher } from './fetcher'
diff --git a/framework/shopify/customer/use-customer.tsx b/framework/shopify/customer/use-customer.tsx
index 652188bbe..55151801b 100644
--- a/framework/shopify/customer/use-customer.tsx
+++ b/framework/shopify/customer/use-customer.tsx
@@ -1,4 +1,25 @@
 import useCustomer, { UseCustomer } from '@commerce/customer/use-customer'
+import { Customer } from '@commerce/types'
+import { HookHandler } from '@commerce/utils/types'
+import { getCustomerQuery } from '@framework/utils'
 import type { ShopifyProvider } from '..'
 
 export default useCustomer as UseCustomer<ShopifyProvider>
+
+export const handler: HookHandler<Customer | null> = {
+  fetchOptions: {
+    query: getCustomerQuery,
+  },
+  async fetcher({ options, fetch }) {
+    const data = await fetch<any | null>(options)
+    return data?.customer ?? null
+  },
+  useHook({ input, useData }) {
+    return useData({
+      swrOptions: {
+        revalidateOnFocus: false,
+        ...input.swrOptions,
+      },
+    })
+  },
+}
diff --git a/framework/shopify/fetcher.ts b/framework/shopify/fetcher.ts
new file mode 100644
index 000000000..9c4fe9a9e
--- /dev/null
+++ b/framework/shopify/fetcher.ts
@@ -0,0 +1,18 @@
+import { Fetcher } from '@commerce/utils/types'
+import { API_TOKEN, API_URL } from './const'
+import { handleFetchResponse } from './utils'
+
+const fetcher: Fetcher = async ({ method = 'POST', variables, query }) => {
+  return handleFetchResponse(
+    await fetch(API_URL, {
+      method,
+      body: JSON.stringify({ query, variables }),
+      headers: {
+        'X-Shopify-Storefront-Access-Token': API_TOKEN!,
+        'Content-Type': 'application/json',
+      },
+    })
+  )
+}
+
+export default fetcher
diff --git a/framework/shopify/product/get-all-products.ts b/framework/shopify/product/get-all-products.ts
index a7cc3043c..34480e90a 100644
--- a/framework/shopify/product/get-all-products.ts
+++ b/framework/shopify/product/get-all-products.ts
@@ -2,7 +2,7 @@ import { GraphQLFetcherResult } from '@commerce/api'
 import { getConfig, ShopifyConfig } from '../api'
 import { Product, ProductEdge } from '../schema'
 import { getAllProductsQuery } from '../utils/queries'
-import { normalizeProduct } from '@framework/lib/normalize'
+import { normalizeProduct } from '@framework/utils/normalize'
 
 export type ProductNode = Product
 
diff --git a/framework/shopify/product/get-product.ts b/framework/shopify/product/get-product.ts
index 84e74c611..191706123 100644
--- a/framework/shopify/product/get-product.ts
+++ b/framework/shopify/product/get-product.ts
@@ -3,7 +3,7 @@ import { GraphQLFetcherResult } from '@commerce/api'
 import { getConfig, ShopifyConfig } from '../api'
 import { Product } from '../schema'
 import getProductQuery from '../utils/queries/get-product-query'
-import { normalizeProduct } from '@framework/lib/normalize'
+import { normalizeProduct } from '@framework/utils/normalize'
 
 export type ProductNode = Product
 
diff --git a/framework/shopify/product/use-search.tsx b/framework/shopify/product/use-search.tsx
index 4f83baa63..174466fdb 100644
--- a/framework/shopify/product/use-search.tsx
+++ b/framework/shopify/product/use-search.tsx
@@ -1,4 +1,55 @@
 import useSearch, { UseSearch } from '@commerce/products/use-search'
+import { SearchProductsData } from '@commerce/types'
+import { HookHandler } from '@commerce/utils/types'
+import { ProductEdge } from '@framework/schema'
+import {
+  getAllProductsQuery,
+  getSearchVariables,
+  normalizeProduct,
+} from '@framework/utils'
 import type { ShopifyProvider } from '..'
 
 export default useSearch as UseSearch<ShopifyProvider>
+
+export type SearchProductsInput = {
+  search?: string
+  categoryId?: number
+  brandId?: number
+  sort?: string
+}
+
+export const handler: HookHandler<
+  SearchProductsData,
+  SearchProductsInput,
+  SearchProductsInput
+> = {
+  fetchOptions: {
+    query: getAllProductsQuery,
+  },
+  async fetcher({ input, options, fetch }) {
+    const resp = await fetch({
+      query: options?.query,
+      method: options?.method,
+      variables: getSearchVariables(input),
+    })
+    const edges = resp.products?.edges
+    return {
+      products: edges?.map(({ node: p }: ProductEdge) => normalizeProduct(p)),
+      found: !!edges?.length,
+    }
+  },
+  useHook({ input, useData }) {
+    return useData({
+      input: [
+        ['search', input.search],
+        ['categoryId', input.categoryId],
+        ['brandId', input.brandId],
+        ['sort', input.sort],
+      ],
+      swrOptions: {
+        revalidateOnFocus: false,
+        ...input.swrOptions,
+      },
+    })
+  },
+}
diff --git a/framework/shopify/provider.ts b/framework/shopify/provider.ts
new file mode 100644
index 000000000..6da831e46
--- /dev/null
+++ b/framework/shopify/provider.ts
@@ -0,0 +1,18 @@
+import { SHOPIFY_CHECKOUT_ID_COOKIE, STORE_DOMAIN } from './const'
+
+import { handler as useCart } from '@framework/cart/use-cart'
+import { handler as useSearch } from '@framework/product/use-search'
+import { handler as useCustomer } from '@framework/customer/use-customer'
+import fetcher from './fetcher'
+
+export const shopifyProvider = {
+  locale: 'en-us',
+  cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
+  storeDomain: STORE_DOMAIN,
+  fetcher,
+  cart: { useCart },
+  customer: { useCustomer },
+  products: { useSearch },
+}
+
+export type ShopifyProvider = typeof shopifyProvider
diff --git a/framework/shopify/provider.tsx b/framework/shopify/provider.tsx
deleted file mode 100644
index 4a1f01525..000000000
--- a/framework/shopify/provider.tsx
+++ /dev/null
@@ -1,161 +0,0 @@
-import { useMemo } from 'react'
-import { Fetcher, HookFetcherFn, HookHandler } from '@commerce/utils/types'
-
-import {
-  API_TOKEN,
-  API_URL,
-  SHOPIFY_CHECKOUT_ID_COOKIE,
-  STORE_DOMAIN,
-} from './const'
-
-import { Cart } from './types'
-import { Customer } from '@commerce/types'
-import { normalizeCart, normalizeProduct } from './lib/normalize'
-import { FetchCartInput } from '@commerce/cart/use-cart'
-import { checkoutCreate, checkoutToCart } from './cart/utils'
-
-import {
-  getAllProductsQuery,
-  getCustomerQuery,
-  getCheckoutQuery,
-  handleFetchResponse,
-  getSearchVariables,
-} from './utils'
-
-import { ProductEdge } from './schema'
-import { SearchProductsInput } from 'framework/bigcommerce/provider'
-import { SearchProductsData } from 'framework/bigcommerce/api/catalog/products'
-
-const fetcher: Fetcher = async ({ method = 'POST', variables, query }) => {
-  return handleFetchResponse(
-    await fetch(API_URL, {
-      method,
-      body: JSON.stringify({ query, variables }),
-      headers: {
-        'X-Shopify-Storefront-Access-Token': API_TOKEN!,
-        'Content-Type': 'application/json',
-      },
-    })
-  )
-}
-
-export const cartFetcher: HookFetcherFn<Cart | null, FetchCartInput> = async ({
-  options,
-  input: { cartId },
-  fetch,
-}) => {
-  let checkout
-
-  if (cartId) {
-    const data = await fetch({
-      ...options,
-      variables: {
-        cartId,
-      },
-    })
-    checkout = data?.node
-  }
-
-  if (checkout?.completedAt || !cartId) {
-    checkout = await checkoutCreate(fetch)
-  }
-
-  return checkoutToCart({ checkout })
-}
-
-const useCart: HookHandler<
-  Cart | null,
-  {},
-  FetchCartInput,
-  { isEmpty?: boolean }
-> = {
-  fetchOptions: {
-    query: getCheckoutQuery,
-  },
-  fetcher: cartFetcher,
-  useHook({ input, useData }) {
-    const response = useData({
-      swrOptions: { revalidateOnFocus: false, ...input.swrOptions },
-    })
-
-    return useMemo(
-      () =>
-        Object.create(response, {
-          isEmpty: {
-            get() {
-              return (response.data?.lineItems.length ?? 0) <= 0
-            },
-            enumerable: true,
-          },
-        }),
-      [response]
-    )
-  },
-}
-
-const useSearch: HookHandler<
-  SearchProductsData,
-  SearchProductsInput,
-  SearchProductsInput
-> = {
-  fetchOptions: {
-    query: getAllProductsQuery,
-  },
-  async fetcher({ input, options, fetch }) {
-    const resp = await fetch({
-      query: options?.query,
-      method: options?.method,
-      variables: getSearchVariables(input),
-    })
-    const edges = resp.products?.edges
-    return {
-      products: edges?.map(({ node: p }: ProductEdge) => normalizeProduct(p)),
-      found: !!edges?.length,
-    }
-  },
-  useHook({ input, useData }) {
-    return useData({
-      input: [
-        ['search', input.search],
-        ['categoryId', input.categoryId],
-        ['brandId', input.brandId],
-        ['sort', input.sort],
-      ],
-      swrOptions: {
-        revalidateOnFocus: false,
-        ...input.swrOptions,
-      },
-    })
-  },
-}
-
-const useCustomerHandler: HookHandler<Customer | null> = {
-  fetchOptions: {
-    query: getCustomerQuery,
-  },
-  async fetcher({ options, fetch }) {
-    const data = await fetch<any | null>(options)
-    return data?.customer ?? null
-  },
-  useHook({ input, useData }) {
-    return useData({
-      swrOptions: {
-        revalidateOnFocus: false,
-        ...input.swrOptions,
-      },
-    })
-  },
-}
-
-export const shopifyProvider = {
-  locale: 'en-us',
-  cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
-  storeDomain: STORE_DOMAIN,
-  fetcher,
-  cartNormalizer: normalizeCart,
-  cart: { useCart },
-  customer: { useCustomer: useCustomerHandler },
-  products: { useSearch },
-}
-
-export type ShopifyProvider = typeof shopifyProvider
diff --git a/framework/shopify/utils/get-search-variables.ts b/framework/shopify/utils/get-search-variables.ts
index 9bc91eca3..90d35ba50 100644
--- a/framework/shopify/utils/get-search-variables.ts
+++ b/framework/shopify/utils/get-search-variables.ts
@@ -1,5 +1,5 @@
-import { SearchProductsInput } from '@framework/product/use-search'
 import getSortVariables from './get-sort-variables'
+import type { SearchProductsInput } from '@framework/product/use-search'
 
 export const getSearchVariables = ({
   categoryId,
diff --git a/framework/shopify/utils/index.ts b/framework/shopify/utils/index.ts
index cecf06fd1..99aa9be68 100644
--- a/framework/shopify/utils/index.ts
+++ b/framework/shopify/utils/index.ts
@@ -3,7 +3,9 @@ export { default as getSearchVariables } from './get-search-variables'
 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 * from './customer-token'
 export * from './queries'
 export * from './mutations'
+export * from './normalize'
+export * from './customer-token'
diff --git a/framework/shopify/utils/mutations/index.ts b/framework/shopify/utils/mutations/index.ts
index 5ccf5b1dd..c9c6ee100 100644
--- a/framework/shopify/utils/mutations/index.ts
+++ b/framework/shopify/utils/mutations/index.ts
@@ -1,8 +1,10 @@
 export { default as createCustomerMutation } from './customer-create'
 export { default as checkoutCreateMutation } from './checkout-create'
+
 export { default as checkoutLineItemAddMutation } from './checkout-line-item-add'
 export { default as checkoutLineItemUpdateMutation } from './checkout-create'
 export { default as checkoutLineItemRemoveMutation } from './checkout-line-item-remove'
+
 export { default as customerCreateMutation } from './customer-create'
 export { default as customerAccessTokenCreateMutation } from './customer-access-token-create'
 export { default as customerAccessTokenDeleteMutation } from './customer-access-token-delete'
diff --git a/framework/shopify/lib/normalize.ts b/framework/shopify/utils/normalize.ts
similarity index 100%
rename from framework/shopify/lib/normalize.ts
rename to framework/shopify/utils/normalize.ts