diff --git a/.env.template b/.env.template index 1f0fe0536..b24458b80 100644 --- a/.env.template +++ b/.env.template @@ -1,4 +1,4 @@ -# Available providers: bigcommerce, shopify, swell +# Available providers: local, bigcommerce, shopify, swell, saleor COMMERCE_PROVIDER= BIGCOMMERCE_STOREFRONT_API_URL= diff --git a/framework/bigcommerce/index.tsx b/framework/bigcommerce/index.tsx index 024e54b56..3259836b9 100644 --- a/framework/bigcommerce/index.tsx +++ b/framework/bigcommerce/index.tsx @@ -1,36 +1,9 @@ -import type { ReactNode } from 'react' -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' -import { bigcommerceProvider } from './provider' -import type { BigcommerceProvider } from './provider' +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' +import { bigcommerceProvider, BigcommerceProvider } from './provider' export { bigcommerceProvider } export type { BigcommerceProvider } -export const bigcommerceConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: 'bc_cartId', -} - -export type BigcommerceConfig = Partial - -export type BigcommerceProps = { - children?: ReactNode - locale: string -} & BigcommerceConfig - -export function CommerceProvider({ children, ...config }: BigcommerceProps) { - return ( - - {children} - - ) -} +export const CommerceProvider = getCommerceProvider(bigcommerceProvider) export const useCommerce = () => useCoreCommerce() diff --git a/framework/commerce/config.js b/framework/commerce/config.js index 28502a04e..019c59a51 100644 --- a/framework/commerce/config.js +++ b/framework/commerce/config.js @@ -8,12 +8,12 @@ const merge = require('deepmerge') const prettier = require('prettier') const PROVIDERS = [ + 'local', 'bigcommerce', 'saleor', 'shopify', 'swell', 'vendure', - 'local', ] function getProviderName() { diff --git a/framework/commerce/index.tsx b/framework/commerce/index.tsx index 7ecb44dc1..dd740809f 100644 --- a/framework/commerce/index.tsx +++ b/framework/commerce/index.tsx @@ -47,51 +47,60 @@ export type Provider = CommerceConfig & { } } -export type CommerceProps

= { - children?: ReactNode - provider: P - config: CommerceConfig -} - -export type CommerceConfig = Omit< - CommerceContextValue, - 'providerRef' | 'fetcherRef' -> - -export type CommerceContextValue

= { - providerRef: MutableRefObject

- fetcherRef: MutableRefObject +export type CommerceConfig = { locale: string cartCookie: string } -export function CommerceProvider

({ +export type CommerceContextValue

= { + providerRef: MutableRefObject

+ fetcherRef: MutableRefObject +} & CommerceConfig + +export type CommerceProps

= { + children?: ReactNode + provider: P +} + +/** + * These are the properties every provider should allow when implementing + * the core commerce provider + */ +export type CommerceProviderProps = { + children?: ReactNode +} & Partial + +export function CoreCommerceProvider

({ provider, children, - config, }: CommerceProps

) { - if (!config) { - throw new Error('CommerceProvider requires a valid config object') - } - const providerRef = useRef(provider) // TODO: Remove the fetcherRef const fetcherRef = useRef(provider.fetcher) - // Because the config is an object, if the parent re-renders this provider - // will re-render every consumer unless we memoize the config + // If the parent re-renders this provider will re-render every + // consumer unless we memoize the config + const { locale, cartCookie } = providerRef.current const cfg = useMemo( - () => ({ - providerRef, - fetcherRef, - locale: config.locale, - cartCookie: config.cartCookie, - }), - [config.locale, config.cartCookie] + () => ({ providerRef, fetcherRef, locale, cartCookie }), + [locale, cartCookie] ) return {children} } +export function getCommerceProvider

(provider: P) { + return function CommerceProvider({ + children, + ...props + }: CommerceProviderProps) { + return ( + + {children} + + ) + } +} + export function useCommerce

() { return useContext(Commerce) as CommerceContextValue

} diff --git a/framework/local/index.tsx b/framework/local/index.tsx index 2ec304f63..dcc713e69 100644 --- a/framework/local/index.tsx +++ b/framework/local/index.tsx @@ -1,32 +1,9 @@ -import * as React from 'react' -import { ReactNode } from 'react' -import { localProvider } from './provider' -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' +import { localProvider, LocalProvider } from './provider' -export const localConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: 'session', -} +export { localProvider } +export type { LocalProvider } -export function CommerceProvider({ - children, - ...config -}: { - children?: ReactNode - locale: string -} & Partial) { - return ( - - {children} - - ) -} +export const CommerceProvider = getCommerceProvider(localProvider) -export const useCommerce = () => useCoreCommerce() +export const useCommerce = () => useCoreCommerce() diff --git a/framework/local/provider.ts b/framework/local/provider.ts index e6a2b0a21..53dc7f574 100644 --- a/framework/local/provider.ts +++ b/framework/local/provider.ts @@ -9,7 +9,6 @@ import { handler as useLogin } from './auth/use-login' import { handler as useLogout } from './auth/use-logout' import { handler as useSignup } from './auth/use-signup' -export type Provider = typeof localProvider export const localProvider = { locale: 'en-us', cartCookie: 'session', @@ -19,3 +18,5 @@ export const localProvider = { products: { useSearch }, auth: { useLogin, useLogout, useSignup }, } + +export type LocalProvider = typeof localProvider diff --git a/framework/saleor/api/index.ts b/framework/saleor/api/index.ts index 5ae5f3a8a..074607666 100644 --- a/framework/saleor/api/index.ts +++ b/framework/saleor/api/index.ts @@ -1,5 +1,5 @@ -import type { CommerceAPIConfig } from '@commerce/api' - +import { CommerceAPI, CommerceAPIConfig, getCommerceApi as commerceApi } from '@commerce/api' +import * as operations from './operations' import * as Const from '../const' if (!Const.API_URL) { @@ -27,23 +27,12 @@ const config: SaleorConfig = { storeChannel: Const.API_CHANNEL, } -import { - CommerceAPI, - getCommerceApi as commerceApi, -} from '@commerce/api' - -import * as operations from './operations' - -export interface ShopifyConfig extends CommerceAPIConfig {} - export const provider = { config, operations } export type Provider = typeof provider export type SaleorAPI

= CommerceAPI

-export function getCommerceApi

( - customProvider: P = provider as any -): SaleorAPI

{ +export function getCommerceApi

(customProvider: P = provider as any): SaleorAPI

{ return commerceApi(customProvider) } diff --git a/framework/saleor/api/operations/get-all-product-paths.ts b/framework/saleor/api/operations/get-all-product-paths.ts index 43ce7de94..c04964147 100644 --- a/framework/saleor/api/operations/get-all-product-paths.ts +++ b/framework/saleor/api/operations/get-all-product-paths.ts @@ -1,10 +1,6 @@ import type { OperationContext } from '@commerce/api/operations' -import { - GetAllProductPathsQuery, - GetAllProductPathsQueryVariables, - ProductCountableEdge, -} from '../../schema' -import type { ShopifyConfig, Provider, SaleorConfig } from '..' +import { ProductCountableEdge } from '../../schema' +import type { Provider, SaleorConfig } from '..' import { getAllProductsPathsQuery } from '../../utils/queries' import fetchAllProducts from '../utils/fetch-all-products' @@ -13,10 +9,7 @@ export type GetAllProductPathsResult = { products: Array<{ path: string }> } -export default function getAllProductPathsOperation({ - commerce, -}: OperationContext) { - +export default function getAllProductPathsOperation({ commerce }: OperationContext) { async function getAllProductPaths({ query, config, @@ -24,7 +17,7 @@ export default function getAllProductPathsOperation({ }: { query?: string config?: SaleorConfig - variables?: any + variables?: any } = {}): Promise { config = commerce.getConfig(config) @@ -39,7 +32,6 @@ export default function getAllProductPathsOperation({ path: `/${slug}`, })), } - } return getAllProductPaths diff --git a/framework/saleor/index.tsx b/framework/saleor/index.tsx index 5c9e61ec8..0fa217943 100644 --- a/framework/saleor/index.tsx +++ b/framework/saleor/index.tsx @@ -1,32 +1,9 @@ -import * as React from 'react' -import { ReactNode } from 'react' - -import { CommerceConfig, CommerceProvider as CoreCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' - +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' import { saleorProvider, SaleorProvider } from './provider' -import * as Const from './const' export { saleorProvider } export type { SaleorProvider } -export const saleorConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: Const.CHECKOUT_ID_COOKIE, -} +export const CommerceProvider = getCommerceProvider(saleorProvider) -export type SaleorConfig = Partial - -export type SaleorProps = { - children?: ReactNode - locale: string -} & SaleorConfig - -export function CommerceProvider({ children, ...config }: SaleorProps) { - return ( - - {children} - - ) -} - -export const useCommerce = () => useCoreCommerce() +export const useCommerce = () => useCoreCommerce() diff --git a/framework/saleor/provider.ts b/framework/saleor/provider.ts index 2ca96475a..becf2998f 100644 --- a/framework/saleor/provider.ts +++ b/framework/saleor/provider.ts @@ -1,3 +1,4 @@ +import { CHECKOUT_ID_COOKIE } from './const' import { handler as useCart } from './cart/use-cart' import { handler as useAddItem } from './cart/use-add-item' import { handler as useUpdateItem } from './cart/use-update-item' @@ -14,8 +15,7 @@ import fetcher from './fetcher' export const saleorProvider = { locale: 'en-us', - cartCookie: '', - cartCookieToken: '', + cartCookie: CHECKOUT_ID_COOKIE, fetcher, cart: { useCart, useAddItem, useUpdateItem, useRemoveItem }, customer: { useCustomer }, diff --git a/framework/shopify/index.tsx b/framework/shopify/index.tsx index 46ed106c5..6a8c6aa8b 100644 --- a/framework/shopify/index.tsx +++ b/framework/shopify/index.tsx @@ -1,40 +1,9 @@ -import * as React from 'react' -import { ReactNode } from 'react' - -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' - -import { shopifyProvider } from './provider' -import type { ShopifyProvider } from './provider' -import { SHOPIFY_CHECKOUT_ID_COOKIE } from './const' +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' +import { shopifyProvider, ShopifyProvider } from './provider' export { shopifyProvider } export type { ShopifyProvider } -export const shopifyConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE, -} - -export type ShopifyConfig = Partial - -export type ShopifyProps = { - children?: ReactNode - locale: string -} & ShopifyConfig - -export function CommerceProvider({ children, ...config }: ShopifyProps) { - return ( - - {children} - - ) -} +export const CommerceProvider = getCommerceProvider(shopifyProvider) export const useCommerce = () => useCoreCommerce() diff --git a/framework/swell/api/utils/fetch-swell-api.ts b/framework/swell/api/utils/fetch-swell-api.ts index 65caed763..83055c5c0 100644 --- a/framework/swell/api/utils/fetch-swell-api.ts +++ b/framework/swell/api/utils/fetch-swell-api.ts @@ -1,7 +1,7 @@ -import { swellConfig } from '../..' +import swell from '../../swell' const fetchApi = async (query: string, method: string, variables: [] = []) => { - const { swell } = swellConfig return swell[query][method](...variables) } + export default fetchApi diff --git a/framework/swell/const.ts b/framework/swell/const.ts index 669194298..16d493896 100644 --- a/framework/swell/const.ts +++ b/framework/swell/const.ts @@ -4,8 +4,6 @@ export const SWELL_CHECKOUT_URL_COOKIE = 'swell_checkoutUrl' export const SWELL_CUSTOMER_TOKEN_COOKIE = 'swell_customerToken' -export const STORE_DOMAIN = process.env.NEXT_PUBLIC_SWELL_STORE_DOMAIN - export const SWELL_COOKIE_EXPIRE = 30 export const SWELL_STORE_ID = process.env.NEXT_PUBLIC_SWELL_STORE_ID diff --git a/framework/swell/fetcher.ts b/framework/swell/fetcher.ts index f18dcf667..655e4da25 100644 --- a/framework/swell/fetcher.ts +++ b/framework/swell/fetcher.ts @@ -1,11 +1,9 @@ import { Fetcher } from '@commerce/utils/types' -import { handleFetchResponse } from './utils' -import { swellConfig } from './index' import { CommerceError } from '@commerce/utils/errors' +import { handleFetchResponse } from './utils' +import swell from './swell' const fetcher: Fetcher = async ({ method = 'get', variables, query }) => { - const { swell } = swellConfig - async function callSwell() { if (Array.isArray(variables)) { const arg1 = variables[0] diff --git a/framework/swell/index.tsx b/framework/swell/index.tsx index 28f60b394..b64df6d48 100644 --- a/framework/swell/index.tsx +++ b/framework/swell/index.tsx @@ -1,47 +1,9 @@ -import * as React from 'react' -import swell from 'swell-js' -import { ReactNode } from 'react' - -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' - +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' import { swellProvider, SwellProvider } from './provider' -import { - SWELL_CHECKOUT_ID_COOKIE, - SWELL_STORE_ID, - SWELL_PUBLIC_KEY, -} from './const' -swell.init(SWELL_STORE_ID, SWELL_PUBLIC_KEY) export { swellProvider } export type { SwellProvider } -export const swellConfig: any = { - locale: 'en-us', - cartCookie: SWELL_CHECKOUT_ID_COOKIE, - swell, -} +export const CommerceProvider = getCommerceProvider(swellProvider) -export type SwellConfig = Partial - -export type SwellProps = { - children?: ReactNode - locale: string -} & SwellConfig - -export function CommerceProvider({ children, ...config }: SwellProps) { - return ( - - {children} - - ) -} - -export const useCommerce = () => useCoreCommerce() +export const useCommerce = () => useCoreCommerce() diff --git a/framework/swell/provider.ts b/framework/swell/provider.ts index aa7be31d4..062f1c32c 100644 --- a/framework/swell/provider.ts +++ b/framework/swell/provider.ts @@ -1,6 +1,5 @@ import { Provider } from '@commerce' - -import { SWELL_CHECKOUT_URL_COOKIE, STORE_DOMAIN } from './const' +import { SWELL_CHECKOUT_ID_COOKIE } from './const' import { handler as useCart } from './cart/use-cart' import { handler as useAddItem } from './cart/use-add-item' @@ -15,11 +14,12 @@ import { handler as useLogout } from './auth/use-logout' import { handler as useSignup } from './auth/use-signup' import fetcher from './fetcher' +import swell from './swell' -export const swellProvider: Provider = { +export const swellProvider: Provider & { swell: any } = { locale: 'en-us', - cartCookie: SWELL_CHECKOUT_URL_COOKIE, - // storeDomain: STORE_DOMAIN, + cartCookie: SWELL_CHECKOUT_ID_COOKIE, + swell, fetcher, cart: { useCart, useAddItem, useUpdateItem, useRemoveItem }, customer: { useCustomer }, diff --git a/framework/swell/swell.ts b/framework/swell/swell.ts new file mode 100644 index 000000000..d73bceb72 --- /dev/null +++ b/framework/swell/swell.ts @@ -0,0 +1,6 @@ +import swell from 'swell-js' +import { SWELL_STORE_ID, SWELL_PUBLIC_KEY } from './const' + +swell.init(SWELL_STORE_ID, SWELL_PUBLIC_KEY) + +export default swell diff --git a/framework/vendure/index.tsx b/framework/vendure/index.tsx index 47e60c7df..086940c54 100644 --- a/framework/vendure/index.tsx +++ b/framework/vendure/index.tsx @@ -1,33 +1,9 @@ -import * as React from 'react' -import { ReactNode } from 'react' -import { - CommerceConfig, - CommerceProvider as CoreCommerceProvider, - useCommerce as useCoreCommerce, -} from '@commerce' -import { vendureProvider } from './provider' +import { getCommerceProvider, useCommerce as useCoreCommerce } from '@commerce' +import { vendureProvider, VendureProvider } from './provider' -export const vendureConfig: CommerceConfig = { - locale: 'en-us', - cartCookie: 'session', -} +export { vendureProvider } +export type { VendureProvider } -export type VendureConfig = Partial - -export type VendureProps = { - children?: ReactNode - locale: string -} & VendureConfig - -export function CommerceProvider({ children, ...config }: VendureProps) { - return ( - - {children} - - ) -} +export const CommerceProvider = getCommerceProvider(vendureProvider) export const useCommerce = () => useCoreCommerce() diff --git a/framework/vendure/provider.ts b/framework/vendure/provider.ts index e100c277b..73f7dd5b2 100644 --- a/framework/vendure/provider.ts +++ b/framework/vendure/provider.ts @@ -1,4 +1,3 @@ -import { Provider } from '@commerce' import { handler as useCart } from './cart/use-cart' import { handler as useAddItem } from './cart/use-add-item' import { handler as useUpdateItem } from './cart/use-update-item' @@ -10,7 +9,7 @@ import { handler as useLogout } from './auth/use-logout' import { handler as useSignup } from './auth/use-signup' import { fetcher } from './fetcher' -export const vendureProvider: Provider = { +export const vendureProvider = { locale: 'en-us', cartCookie: 'session', fetcher, @@ -19,3 +18,5 @@ export const vendureProvider: Provider = { products: { useSearch }, auth: { useLogin, useLogout, useSignup }, } + +export type VendureProvider = typeof vendureProvider