diff --git a/commerce.config.json b/commerce.config.json index 08ea78814..06b985504 100644 --- a/commerce.config.json +++ b/commerce.config.json @@ -1,6 +1,6 @@ { "features": { - "wishlist": true, + "wishlist": false, "customCheckout": false } } diff --git a/framework/shopify/api/index.ts b/framework/shopify/api/index.ts index 897007348..ad32577a4 100644 --- a/framework/shopify/api/index.ts +++ b/framework/shopify/api/index.ts @@ -8,10 +8,7 @@ import { API_URL, API_TOKEN, SHOPIFY_CUSTOMER_TOKEN_COOKIE } from '../const' import fetchGraphqlApi from './utils/fetch-graphql-api' -import login from './operations/login' -import getAllPages from './operations/get-all-pages' -import getPage from './operations/get-page' -import getSiteInfo from './operations/get-site-info' +import * as operations from './operations' if (!API_URL) { throw new Error( @@ -24,46 +21,22 @@ if (!API_TOKEN) { `The environment variable NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN is missing and it's required to access your store` ) } -export interface ShopifyConfig extends CommerceAPIConfig { - applyLocale?: boolean -} - -export class Config { - private config: ShopifyConfig - - constructor(config: ShopifyConfig) { - this.config = config - } - - getConfig(userConfig: Partial = {}) { - return Object.entries(userConfig).reduce( - (cfg, [key, value]) => Object.assign(cfg, { [key]: value }), - { ...this.config } - ) - } - - setConfig(newConfig: Partial) { - Object.assign(this.config, newConfig) - } -} +export interface ShopifyConfig extends CommerceAPIConfig {} const ONE_DAY = 60 * 60 * 24 -const configJson: ShopifyConfig = { +const config: ShopifyConfig = { commerceUrl: API_URL, apiToken: API_TOKEN, customerCookie: SHOPIFY_CUSTOMER_TOKEN_COOKIE, cartCookie: process.env.SHOPIFY_CART_COOKIE ?? 'shopify_checkoutId', cartCookieMaxAge: ONE_DAY * 30, fetch: fetchGraphqlApi, - applyLocale: true, } -const config = new Config(configJson) - export const provider = { - config: configJson, - operations: { getSiteInfo, getPage, getAllPages, login }, + config, + operations, } export type Provider = typeof provider @@ -73,13 +46,6 @@ export type ShopifyAPI

= CommerceAPI

export function getCommerceApi

( customProvider: P = provider as any ): ShopifyAPI

{ + console.log(customProvider) return commerceApi(customProvider) } - -export function getConfig(userConfig?: Partial) { - return config.getConfig(userConfig) -} - -export function setConfig(newConfig: Partial) { - return config.setConfig(newConfig) -} diff --git a/framework/shopify/api/operations/get-all-pages.ts b/framework/shopify/api/operations/get-all-pages.ts index 353a3dda5..50f2bfd1b 100644 --- a/framework/shopify/api/operations/get-all-pages.ts +++ b/framework/shopify/api/operations/get-all-pages.ts @@ -1,23 +1,39 @@ -import type { OperationContext } from '@commerce/api/operations' +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' import { GetAllPagesQuery, GetAllPagesQueryVariables } from '@framework/schema' import type { ShopifyConfig, Provider } from '..' import { GetAllPagesOperation } from '../../types/page' import getAllPagesQuery from '../../utils/queries/get-all-pages-query' -export default function getSiteInfoOperation({ +export default function getAllPagesOperation({ commerce, }: OperationContext) { - async function getPage({ + async function getAllPages(opts?: { + config?: Partial + preview?: boolean + }): Promise + + async function getAllPages( + opts: { + config?: Partial + preview?: boolean + } & OperationOptions + ): Promise + + async function getAllPages({ query = getAllPagesQuery, config, }: { - query?: string - config?: ShopifyConfig + url?: string + config?: Partial preview?: boolean + query?: string } = {}): Promise { - config = commerce.getConfig(config) + const cfg = commerce.getConfig(config) - const { data } = await config.fetch< + const { data } = await cfg.fetch< GetAllPagesQuery, GetAllPagesQueryVariables >(query) @@ -27,5 +43,5 @@ export default function getSiteInfoOperation({ } } - return getPage + return getAllPages } diff --git a/framework/shopify/api/operations/get-all-product-paths.ts b/framework/shopify/api/operations/get-all-product-paths.ts new file mode 100644 index 000000000..c84f8c90a --- /dev/null +++ b/framework/shopify/api/operations/get-all-product-paths.ts @@ -0,0 +1,55 @@ +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' +import { GetAllProductPathsOperation } from '../../types/product' +import { + GetAllProductPathsQuery, + GetAllProductPathsQueryVariables, + ProductEdge, +} from '../../schema' +import type { ShopifyConfig, Provider } from '..' +import { getAllProductsQuery } from '../../utils' + +export default function getAllProductPathsOperation({ + commerce, +}: OperationContext) { + async function getAllProductPaths< + T extends GetAllProductPathsOperation + >(opts?: { + variables?: T['variables'] + config?: ShopifyConfig + }): Promise + + async function getAllProductPaths( + opts: { + variables?: T['variables'] + config?: ShopifyConfig + } & OperationOptions + ): Promise + + async function getAllProductPaths({ + query = getAllProductsQuery, + config, + variables, + }: { + query?: string + config?: ShopifyConfig + variables?: T['variables'] + } = {}): Promise { + config = commerce.getConfig(config) + + const { data } = await config.fetch< + GetAllProductPathsQuery, + GetAllProductPathsQueryVariables + >(query, { variables }) + + return { + products: data.products.edges.map(({ node: { handle } }) => ({ + path: `/${handle}`, + })), + } + } + + return getAllProductPaths +} diff --git a/framework/shopify/api/operations/get-all-products.ts b/framework/shopify/api/operations/get-all-products.ts new file mode 100644 index 000000000..71114c948 --- /dev/null +++ b/framework/shopify/api/operations/get-all-products.ts @@ -0,0 +1,57 @@ +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' +import { GetAllProductsOperation } from '../../types/product' +import { + GetAllProductsQuery, + GetAllProductsQueryVariables, + Product as ShopifyProduct, +} from '../../schema' +import type { ShopifyConfig, Provider } from '..' +import getAllProductsQuery from '../../utils/queries/get-all-products-query' +import { normalizeProduct } from '@framework/utils' + +export default function getAllProductsOperation({ + commerce, +}: OperationContext) { + async function getAllProducts(opts?: { + variables?: T['variables'] + config?: Partial + preview?: boolean + }): Promise + + async function getAllProducts( + opts: { + variables?: T['variables'] + config?: Partial + preview?: boolean + } & OperationOptions + ): Promise + + async function getAllProducts({ + query = getAllProductsQuery, + variables, + config, + }: { + query?: string + variables?: T['variables'] + config?: Partial + preview?: boolean + } = {}): Promise { + const cfg = commerce.getConfig(config) + + const { data } = await cfg.fetch< + GetAllProductsQuery, + GetAllProductsQueryVariables + >(query, { variables }) + + return { + products: data.products.edges.map(({ node }) => + normalizeProduct(node as ShopifyProduct) + ), + } + } + + return getAllProducts +} diff --git a/framework/shopify/api/operations/get-page.ts b/framework/shopify/api/operations/get-page.ts index 527b6930a..eef8ff88d 100644 --- a/framework/shopify/api/operations/get-page.ts +++ b/framework/shopify/api/operations/get-page.ts @@ -1,32 +1,47 @@ -import type { OperationContext } from '@commerce/api/operations' +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' import type { ShopifyConfig, Provider } from '..' import { GetPageQuery, GetPageQueryVariables, Page } from '../../schema' import { GetPageOperation } from '../../types/page' - import getPageQuery from '../../utils/queries/get-page-query' -export default function getSiteInfoOperation({ +export default function getPageOperation({ commerce, }: OperationContext) { + async function getPage(opts: { + variables: T['variables'] + config?: Partial + preview?: boolean + }): Promise + + async function getPage( + opts: { + variables: T['variables'] + config?: Partial + preview?: boolean + } & OperationOptions + ): Promise + async function getPage({ query = getPageQuery, + variables, config, + preview, }: { query?: string - config?: ShopifyConfig + variables: T['variables'] + config?: Partial preview?: boolean - } = {}): Promise { - config = commerce.getConfig(config) + }): Promise { + const cfg = commerce.getConfig(config) - const { data } = await config.fetch( - query - ) + const { + data: { node: page }, + } = await cfg.fetch(query) - if (data.node) { - return {} - } - - return {} + return page ? { page } : {} } return getPage diff --git a/framework/shopify/api/operations/get-product.ts b/framework/shopify/api/operations/get-product.ts new file mode 100644 index 000000000..c628696f7 --- /dev/null +++ b/framework/shopify/api/operations/get-product.ts @@ -0,0 +1,39 @@ +import type { OperationContext } from '@commerce/api/operations' +import { GetProductOperation } from '../../types/product' +import { normalizeProduct, getProductQuery } from '../../utils' +import type { ShopifyConfig, Provider } from '..' +import { + GetProductBySlugQuery, + GetProductBySlugQueryVariables, + Product as ShopifyProduct, +} from '../../schema' + +export default function getProductOperation({ + commerce, +}: OperationContext) { + async function getProduct({ + query = getProductQuery, + config, + variables, + }: { + query?: string + config?: ShopifyConfig + variables?: GetProductBySlugQueryVariables + } = {}): Promise { + config = commerce.getConfig(config) + + const { + data: { productByHandle }, + } = await config.fetch(query, { + variables, + }) + + return { + ...(productByHandle && { + product: normalizeProduct(productByHandle as ShopifyProduct), + }), + } + } + + return getProduct +} diff --git a/framework/shopify/api/operations/get-site-info.ts b/framework/shopify/api/operations/get-site-info.ts index 14238220c..f7a626c94 100644 --- a/framework/shopify/api/operations/get-site-info.ts +++ b/framework/shopify/api/operations/get-site-info.ts @@ -1,28 +1,45 @@ -import type { OperationContext } from '@commerce/api/operations' -import type { GetSiteInfoQuery } from '../../schema' +import type { + OperationContext, + OperationOptions, +} from '@commerce/api/operations' +import { GetSiteInfoQuery, GetSiteInfoQueryVariables } from '@framework/schema' import type { ShopifyConfig, Provider } from '..' import { GetSiteInfoOperation } from '../../types/site' -import getSiteInfoQuery from '../../utils/queries/get-site-info-query' -import { getCategories, getVendors } from '@framework/utils' +import { getCategories, getBrands, getSiteInfoQuery } from '../../utils' export default function getSiteInfoOperation({ commerce, }: OperationContext) { + async function getSiteInfo(opts?: { + config?: Partial + preview?: boolean + }): Promise + + async function getSiteInfo( + opts: { + config?: Partial + preview?: boolean + } & OperationOptions + ): Promise + async function getSiteInfo({ query = getSiteInfoQuery, config, }: { query?: string - config?: ShopifyConfig + config?: Partial preview?: boolean } = {}): Promise { - config = commerce.getConfig(config) + const cfg = commerce.getConfig(config) - const categories = await getCategories(config) - const brands = await getVendors(config) + const categories = await getCategories(cfg) + const brands = await getBrands(cfg) - // const { data } = await config.fetch(query) + const { data } = await cfg.fetch< + GetSiteInfoQuery, + GetSiteInfoQueryVariables + >(query) return { categories, diff --git a/framework/shopify/api/operations/index.ts b/framework/shopify/api/operations/index.ts new file mode 100644 index 000000000..7872a20b6 --- /dev/null +++ b/framework/shopify/api/operations/index.ts @@ -0,0 +1,7 @@ +export { default as getAllPages } from './get-all-pages' +export { default as getPage } from './get-page' +export { default as getAllProducts } from './get-all-products' +export { default as getAllProductPaths } from './get-all-product-paths' +export { default as getProduct } from './get-product' +export { default as getSiteInfo } from './get-site-info' +export { default as login } from './login' diff --git a/framework/shopify/api/utils/fetch-all-products.ts b/framework/shopify/api/utils/fetch-all-products.ts deleted file mode 100644 index b4eadc67a..000000000 --- a/framework/shopify/api/utils/fetch-all-products.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - GetAllProductPathsQuery, - GetAllProductVendorsQuery, - ProductEdge, -} from '../../schema' -import { ShopifyConfig } from '..' - -type FetchAllProductsQuery = GetAllProductPathsQuery | GetAllProductVendorsQuery - -const fetchAllProducts = async ({ - config, - query, - variables, - acc = [], - cursor, -}: { - config: ShopifyConfig - query: string - acc?: any[] - variables?: any - cursor?: string -}): Promise => { - const { data } = await config.fetch(query, { - variables: { ...variables, cursor }, - }) - - const edges = data.products.edges - acc = acc.concat(edges) - - if (data.products.pageInfo.hasNextPage) { - const cursor = edges.pop()?.cursor - if (cursor) { - return fetchAllProducts({ - config, - query, - variables, - acc, - cursor, - }) - } - } - - return acc -} - -export default fetchAllProducts diff --git a/framework/shopify/product/get-all-collections.ts b/framework/shopify/product/get-all-collections.ts deleted file mode 100644 index 3369f9e51..000000000 --- a/framework/shopify/product/get-all-collections.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { GetSiteCollectionsQuery } from '../schema' -import { getConfig, ShopifyConfig } from '../api' -import getAllCollectionsQuery from '../utils/queries/get-all-collections-query' - -const getAllCollections = async (options?: { - variables?: any - config: ShopifyConfig - preview?: boolean -}) => { - let { config, variables = { first: 250 } } = options ?? {} - config = getConfig(config) - - const { data } = await config.fetch( - getAllCollectionsQuery, - { variables } - ) - - const categories = data.collections.edges.map( - ({ node: { id: entityId, title: name, handle } }) => ({ - entityId, - name, - path: `/${handle}`, - }) - ) - - return { - categories, - } -} - -export default getAllCollections diff --git a/framework/shopify/product/get-all-product-paths.ts b/framework/shopify/product/get-all-product-paths.ts deleted file mode 100644 index e8ee04065..000000000 --- a/framework/shopify/product/get-all-product-paths.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { getConfig, ShopifyConfig } from '../api' -import { ProductEdge } from '../schema' -import getAllProductsPathsQuery from '../utils/queries/get-all-products-paths-query' - -type ProductPath = { - path: string -} - -export type ProductPathNode = { - node: ProductPath -} - -type ReturnType = { - products: ProductPathNode[] -} - -const getAllProductPaths = async (options?: { - variables?: any - config?: ShopifyConfig - preview?: boolean -}): Promise => { - let { config, variables = { first: 100, sortKey: 'BEST_SELLING' } } = - options ?? {} - config = getConfig(config) - - const { data } = await config.fetch(getAllProductsPathsQuery, { - variables, - }) - - return { - products: data.products?.edges?.map( - ({ node: { handle } }: ProductEdge) => ({ - node: { - path: `/${handle}`, - }, - }) - ), - } -} - -export default getAllProductPaths diff --git a/framework/shopify/product/get-all-products.ts b/framework/shopify/product/get-all-products.ts deleted file mode 100644 index d7e811dbc..000000000 --- a/framework/shopify/product/get-all-products.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { getConfig, ShopifyConfig } from '../api' -import { GetAllProductsQuery, Product as ShopifyProduct } from '../schema' -import { getAllProductsQuery } from '../utils/queries' -import { normalizeProduct } from '../utils/normalize' -import { Product } from '../types/product' - -type Variables = { - first?: number - field?: string -} - -const getAllProducts = async (options: { - variables?: Variables - config?: ShopifyConfig - preview?: boolean -}): Promise<{ - products: Product[] -}> => { - let { config, variables = { first: 250 } } = options ?? {} - config = getConfig(config) - - const { data } = await config.fetch( - getAllProductsQuery, - { variables } - ) - - return { - products: data.products.edges.map(({ node }) => - normalizeProduct(node as ShopifyProduct) - ), - } -} - -export default getAllProducts diff --git a/framework/shopify/product/get-product.ts b/framework/shopify/product/get-product.ts deleted file mode 100644 index a3b634fcd..000000000 --- a/framework/shopify/product/get-product.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { GetProductBySlugQuery, Product as ShopifyProduct } from '../schema' -import { getConfig, ShopifyConfig } from '../api' -import { normalizeProduct, getProductQuery } from '../utils' -import { Product } from '@commerce/types' - -type Variables = { - slug: string -} - -const getProduct = async (options: { - variables: Variables - config: ShopifyConfig - preview?: boolean -}): Promise<{ - product?: Product -}> => { - let { config, variables } = options ?? {} - config = getConfig(config) - - const { - data: { productByHandle }, - } = await config.fetch(getProductQuery, { - variables, - }) - - return { - ...(productByHandle && { - product: normalizeProduct(productByHandle as ShopifyProduct), - }), - } -} - -export default getProduct diff --git a/framework/shopify/utils/get-vendors.ts b/framework/shopify/utils/get-brands.ts similarity index 56% rename from framework/shopify/utils/get-vendors.ts rename to framework/shopify/utils/get-brands.ts index 24843f177..afd015dbe 100644 --- a/framework/shopify/utils/get-vendors.ts +++ b/framework/shopify/utils/get-brands.ts @@ -1,5 +1,8 @@ +import { + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables, +} from '@framework/schema' import { ShopifyConfig } from '../api' -import fetchAllProducts from '../api/utils/fetch-all-products' import getAllProductVendors from './queries/get-all-product-vendors-query' export type Brand = { @@ -14,16 +17,17 @@ export type BrandEdge = { export type Brands = BrandEdge[] -const getVendors = async (config: ShopifyConfig): Promise => { - const vendors = await fetchAllProducts({ - config, - query: getAllProductVendors, +const getBrands = async (config: ShopifyConfig): Promise => { + const { data } = await config.fetch< + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables + >(getAllProductVendors, { variables: { first: 250, }, }) - let vendorsStrings = vendors.map(({ node: { vendor } }) => vendor) + let vendorsStrings = data.products.edges.map(({ node: { vendor } }) => vendor) return [...new Set(vendorsStrings)].map((v) => { const id = v.replace(/\s+/g, '-').toLowerCase() @@ -37,4 +41,4 @@ const getVendors = async (config: ShopifyConfig): Promise => { }) } -export default getVendors +export default getBrands diff --git a/framework/shopify/utils/index.ts b/framework/shopify/utils/index.ts index 61e5975d7..a8454ffca 100644 --- a/framework/shopify/utils/index.ts +++ b/framework/shopify/utils/index.ts @@ -1,7 +1,7 @@ export { default as handleFetchResponse } from './handle-fetch-response' 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 getBrands } from './get-brands' export { default as getCategories } from './get-categories' export { default as getCheckoutId } from './get-checkout-id' export { default as checkoutCreate } from './checkout-create' diff --git a/framework/shopify/utils/queries/index.ts b/framework/shopify/utils/queries/index.ts index e19be9c8c..953113491 100644 --- a/framework/shopify/utils/queries/index.ts +++ b/framework/shopify/utils/queries/index.ts @@ -8,3 +8,4 @@ export { default as getCheckoutQuery } from './get-checkout-query' export { default as getAllPagesQuery } from './get-all-pages-query' export { default as getPageQuery } from './get-page-query' export { default as getCustomerQuery } from './get-customer-query' +export { default as getSiteInfoQuery } from './get-site-info-query' diff --git a/pages/index.tsx b/pages/index.tsx index e8c342449..785da555f 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -15,7 +15,6 @@ export async function getStaticProps({ config, preview, }) - console.log(commerce) const { categories, brands } = await commerce.getSiteInfo({ config, preview }) const { pages } = await commerce.getAllPages({ config, preview })