From f694a979ac53c76b39d616c5d52ecaaad35d8651 Mon Sep 17 00:00:00 2001 From: DuvCharles Date: Tue, 20 Jun 2023 18:28:28 +0200 Subject: [PATCH 01/11] feat: remove shopify folder --- lib/shopify/fragments/cart.ts | 53 ---- lib/shopify/fragments/image.ts | 10 - lib/shopify/fragments/product.ts | 64 ----- lib/shopify/fragments/seo.ts | 8 - lib/shopify/index.ts | 449 ------------------------------ lib/shopify/mutations/cart.ts | 45 --- lib/shopify/queries/cart.ts | 10 - lib/shopify/queries/collection.ts | 56 ---- lib/shopify/queries/menu.ts | 10 - lib/shopify/queries/page.ts | 41 --- lib/shopify/queries/product.ts | 32 --- lib/shopify/types.ts | 265 ------------------ 12 files changed, 1043 deletions(-) delete mode 100644 lib/shopify/fragments/cart.ts delete mode 100644 lib/shopify/fragments/image.ts delete mode 100644 lib/shopify/fragments/product.ts delete mode 100644 lib/shopify/fragments/seo.ts delete mode 100644 lib/shopify/index.ts delete mode 100644 lib/shopify/mutations/cart.ts delete mode 100644 lib/shopify/queries/cart.ts delete mode 100644 lib/shopify/queries/collection.ts delete mode 100644 lib/shopify/queries/menu.ts delete mode 100644 lib/shopify/queries/page.ts delete mode 100644 lib/shopify/queries/product.ts delete mode 100644 lib/shopify/types.ts diff --git a/lib/shopify/fragments/cart.ts b/lib/shopify/fragments/cart.ts deleted file mode 100644 index fc5c838ddb..0000000000 --- a/lib/shopify/fragments/cart.ts +++ /dev/null @@ -1,53 +0,0 @@ -import productFragment from './product'; - -const cartFragment = /* GraphQL */ ` - fragment cart on Cart { - id - checkoutUrl - cost { - subtotalAmount { - amount - currencyCode - } - totalAmount { - amount - currencyCode - } - totalTaxAmount { - amount - currencyCode - } - } - lines(first: 100) { - edges { - node { - id - quantity - cost { - totalAmount { - amount - currencyCode - } - } - merchandise { - ... on ProductVariant { - id - title - selectedOptions { - name - value - } - product { - ...product - } - } - } - } - } - } - totalQuantity - } - ${productFragment} -`; - -export default cartFragment; diff --git a/lib/shopify/fragments/image.ts b/lib/shopify/fragments/image.ts deleted file mode 100644 index 5d002f1756..0000000000 --- a/lib/shopify/fragments/image.ts +++ /dev/null @@ -1,10 +0,0 @@ -const imageFragment = /* GraphQL */ ` - fragment image on Image { - url - altText - width - height - } -`; - -export default imageFragment; diff --git a/lib/shopify/fragments/product.ts b/lib/shopify/fragments/product.ts deleted file mode 100644 index be14dedca7..0000000000 --- a/lib/shopify/fragments/product.ts +++ /dev/null @@ -1,64 +0,0 @@ -import imageFragment from './image'; -import seoFragment from './seo'; - -const productFragment = /* GraphQL */ ` - fragment product on Product { - id - handle - availableForSale - title - description - descriptionHtml - options { - id - name - values - } - priceRange { - maxVariantPrice { - amount - currencyCode - } - minVariantPrice { - amount - currencyCode - } - } - variants(first: 250) { - edges { - node { - id - title - availableForSale - selectedOptions { - name - value - } - price { - amount - currencyCode - } - } - } - } - featuredImage { - ...image - } - images(first: 20) { - edges { - node { - ...image - } - } - } - seo { - ...seo - } - tags - updatedAt - } - ${imageFragment} - ${seoFragment} -`; - -export default productFragment; diff --git a/lib/shopify/fragments/seo.ts b/lib/shopify/fragments/seo.ts deleted file mode 100644 index 2d4786c4ff..0000000000 --- a/lib/shopify/fragments/seo.ts +++ /dev/null @@ -1,8 +0,0 @@ -const seoFragment = /* GraphQL */ ` - fragment seo on SEO { - description - title - } -`; - -export default seoFragment; diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts deleted file mode 100644 index 0b14212d2e..0000000000 --- a/lib/shopify/index.ts +++ /dev/null @@ -1,449 +0,0 @@ -import { HIDDEN_PRODUCT_TAG, SHOPIFY_GRAPHQL_API_ENDPOINT, TAGS } from 'lib/constants'; -import { isShopifyError } from 'lib/type-guards'; -import { ensureStartsWith } from 'lib/utils'; -import { revalidateTag } from 'next/cache'; -import { headers } from 'next/headers'; -import { NextRequest, NextResponse } from 'next/server'; -import { - addToCartMutation, - createCartMutation, - editCartItemsMutation, - removeFromCartMutation -} from './mutations/cart'; -import { getCartQuery } from './queries/cart'; -import { - getCollectionProductsQuery, - getCollectionQuery, - getCollectionsQuery -} from './queries/collection'; -import { getMenuQuery } from './queries/menu'; -import { getPageQuery, getPagesQuery } from './queries/page'; -import { - getProductQuery, - getProductRecommendationsQuery, - getProductsQuery -} from './queries/product'; -import { - Cart, - Collection, - Connection, - Image, - Menu, - Page, - Product, - ShopifyAddToCartOperation, - ShopifyCart, - ShopifyCartOperation, - ShopifyCollection, - ShopifyCollectionOperation, - ShopifyCollectionProductsOperation, - ShopifyCollectionsOperation, - ShopifyCreateCartOperation, - ShopifyMenuOperation, - ShopifyPageOperation, - ShopifyPagesOperation, - ShopifyProduct, - ShopifyProductOperation, - ShopifyProductRecommendationsOperation, - ShopifyProductsOperation, - ShopifyRemoveFromCartOperation, - ShopifyUpdateCartOperation -} from './types'; - -const domain = process.env.SHOPIFY_STORE_DOMAIN - ? ensureStartsWith(process.env.SHOPIFY_STORE_DOMAIN, 'https://') - : ''; -const endpoint = `${domain}${SHOPIFY_GRAPHQL_API_ENDPOINT}`; -const key = process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN!; - -type ExtractVariables = T extends { variables: object } ? T['variables'] : never; - -export async function shopifyFetch({ - cache = 'force-cache', - headers, - query, - tags, - variables -}: { - cache?: RequestCache; - headers?: HeadersInit; - query: string; - tags?: string[]; - variables?: ExtractVariables; -}): Promise<{ status: number; body: T } | never> { - try { - const result = await fetch(endpoint, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-Shopify-Storefront-Access-Token': key, - ...headers - }, - body: JSON.stringify({ - ...(query && { query }), - ...(variables && { variables }) - }), - cache, - ...(tags && { next: { tags } }) - }); - - const body = await result.json(); - - if (body.errors) { - throw body.errors[0]; - } - - return { - status: result.status, - body - }; - } catch (e) { - if (isShopifyError(e)) { - throw { - cause: e.cause?.toString() || 'unknown', - status: e.status || 500, - message: e.message, - query - }; - } - - throw { - error: e, - query - }; - } -} - -const removeEdgesAndNodes = (array: Connection) => { - return array.edges.map((edge) => edge?.node); -}; - -const reshapeCart = (cart: ShopifyCart): Cart => { - if (!cart.cost?.totalTaxAmount) { - cart.cost.totalTaxAmount = { - amount: '0.0', - currencyCode: 'USD' - }; - } - - return { - ...cart, - lines: removeEdgesAndNodes(cart.lines) - }; -}; - -const reshapeCollection = (collection: ShopifyCollection): Collection | undefined => { - if (!collection) { - return undefined; - } - - return { - ...collection, - path: `/search/${collection.handle}` - }; -}; - -const reshapeCollections = (collections: ShopifyCollection[]) => { - const reshapedCollections = []; - - for (const collection of collections) { - if (collection) { - const reshapedCollection = reshapeCollection(collection); - - if (reshapedCollection) { - reshapedCollections.push(reshapedCollection); - } - } - } - - return reshapedCollections; -}; - -const reshapeImages = (images: Connection, productTitle: string) => { - const flattened = removeEdgesAndNodes(images); - - return flattened.map((image) => { - const filename = image.url.match(/.*\/(.*)\..*/)[1]; - return { - ...image, - altText: image.altText || `${productTitle} - ${filename}` - }; - }); -}; - -const reshapeProduct = (product: ShopifyProduct, filterHiddenProducts: boolean = true) => { - if (!product || (filterHiddenProducts && product.tags.includes(HIDDEN_PRODUCT_TAG))) { - return undefined; - } - - const { images, variants, ...rest } = product; - - return { - ...rest, - images: reshapeImages(images, product.title), - variants: removeEdgesAndNodes(variants) - }; -}; - -const reshapeProducts = (products: ShopifyProduct[]) => { - const reshapedProducts = []; - - for (const product of products) { - if (product) { - const reshapedProduct = reshapeProduct(product); - - if (reshapedProduct) { - reshapedProducts.push(reshapedProduct); - } - } - } - - return reshapedProducts; -}; - -export async function createCart(): Promise { - const res = await shopifyFetch({ - query: createCartMutation, - cache: 'no-store' - }); - - return reshapeCart(res.body.data.cartCreate.cart); -} - -export async function addToCart( - cartId: string, - lines: { merchandiseId: string; quantity: number }[] -): Promise { - const res = await shopifyFetch({ - query: addToCartMutation, - variables: { - cartId, - lines - }, - cache: 'no-store' - }); - return reshapeCart(res.body.data.cartLinesAdd.cart); -} - -export async function removeFromCart(cartId: string, lineIds: string[]): Promise { - const res = await shopifyFetch({ - query: removeFromCartMutation, - variables: { - cartId, - lineIds - }, - cache: 'no-store' - }); - - return reshapeCart(res.body.data.cartLinesRemove.cart); -} - -export async function updateCart( - cartId: string, - lines: { id: string; merchandiseId: string; quantity: number }[] -): Promise { - const res = await shopifyFetch({ - query: editCartItemsMutation, - variables: { - cartId, - lines - }, - cache: 'no-store' - }); - - return reshapeCart(res.body.data.cartLinesUpdate.cart); -} - -export async function getCart(cartId: string): Promise { - const res = await shopifyFetch({ - query: getCartQuery, - variables: { cartId }, - cache: 'no-store' - }); - - // Old carts becomes `null` when you checkout. - if (!res.body.data.cart) { - return undefined; - } - - return reshapeCart(res.body.data.cart); -} - -export async function getCollection(handle: string): Promise { - const res = await shopifyFetch({ - query: getCollectionQuery, - tags: [TAGS.collections], - variables: { - handle - } - }); - - return reshapeCollection(res.body.data.collection); -} - -export async function getCollectionProducts({ - collection, - reverse, - sortKey -}: { - collection: string; - reverse?: boolean; - sortKey?: string; -}): Promise { - const res = await shopifyFetch({ - query: getCollectionProductsQuery, - tags: [TAGS.collections, TAGS.products], - variables: { - handle: collection, - reverse, - sortKey: sortKey === 'CREATED_AT' ? 'CREATED' : sortKey - } - }); - - if (!res.body.data.collection) { - console.log(`No collection found for \`${collection}\``); - return []; - } - - return reshapeProducts(removeEdgesAndNodes(res.body.data.collection.products)); -} - -export async function getCollections(): Promise { - const res = await shopifyFetch({ - query: getCollectionsQuery, - tags: [TAGS.collections] - }); - const shopifyCollections = removeEdgesAndNodes(res.body?.data?.collections); - const collections = [ - { - handle: '', - title: 'All', - description: 'All products', - seo: { - title: 'All', - description: 'All products' - }, - path: '/search', - updatedAt: new Date().toISOString() - }, - // Filter out the `hidden` collections. - // Collections that start with `hidden-*` need to be hidden on the search page. - ...reshapeCollections(shopifyCollections).filter( - (collection) => !collection.handle.startsWith('hidden') - ) - ]; - - return collections; -} - -export async function getMenu(handle: string): Promise { - const res = await shopifyFetch({ - query: getMenuQuery, - tags: [TAGS.collections], - variables: { - handle - } - }); - - return ( - res.body?.data?.menu?.items.map((item: { title: string; url: string }) => ({ - title: item.title, - path: item.url.replace(domain, '').replace('/collections', '/search').replace('/pages', '') - })) || [] - ); -} - -export async function getPage(handle: string): Promise { - const res = await shopifyFetch({ - query: getPageQuery, - variables: { handle } - }); - - return res.body.data.pageByHandle; -} - -export async function getPages(): Promise { - const res = await shopifyFetch({ - query: getPagesQuery - }); - - return removeEdgesAndNodes(res.body.data.pages); -} - -export async function getProduct(handle: string): Promise { - const res = await shopifyFetch({ - query: getProductQuery, - tags: [TAGS.products], - variables: { - handle - } - }); - - return reshapeProduct(res.body.data.product, false); -} - -export async function getProductRecommendations(productId: string): Promise { - const res = await shopifyFetch({ - query: getProductRecommendationsQuery, - tags: [TAGS.products], - variables: { - productId - } - }); - - return reshapeProducts(res.body.data.productRecommendations); -} - -export async function getProducts({ - query, - reverse, - sortKey -}: { - query?: string; - reverse?: boolean; - sortKey?: string; -}): Promise { - const res = await shopifyFetch({ - query: getProductsQuery, - tags: [TAGS.products], - variables: { - query, - reverse, - sortKey - } - }); - - return reshapeProducts(removeEdgesAndNodes(res.body.data.products)); -} - -// This is called from `app/api/revalidate.ts` so providers can control revalidation logic. -export async function revalidate(req: NextRequest): Promise { - // We always need to respond with a 200 status code to Shopify, - // otherwise it will continue to retry the request. - const collectionWebhooks = ['collections/create', 'collections/delete', 'collections/update']; - const productWebhooks = ['products/create', 'products/delete', 'products/update']; - const topic = headers().get('x-shopify-topic') || 'unknown'; - const secret = req.nextUrl.searchParams.get('secret'); - const isCollectionUpdate = collectionWebhooks.includes(topic); - const isProductUpdate = productWebhooks.includes(topic); - - if (!secret || secret !== process.env.SHOPIFY_REVALIDATION_SECRET) { - console.error('Invalid revalidation secret.'); - return NextResponse.json({ status: 200 }); - } - - if (!isCollectionUpdate && !isProductUpdate) { - // We don't need to revalidate anything for any other topics. - return NextResponse.json({ status: 200 }); - } - - if (isCollectionUpdate) { - revalidateTag(TAGS.collections); - } - - if (isProductUpdate) { - revalidateTag(TAGS.products); - } - - return NextResponse.json({ status: 200, revalidated: true, now: Date.now() }); -} diff --git a/lib/shopify/mutations/cart.ts b/lib/shopify/mutations/cart.ts deleted file mode 100644 index 4cc1b5ac68..0000000000 --- a/lib/shopify/mutations/cart.ts +++ /dev/null @@ -1,45 +0,0 @@ -import cartFragment from '../fragments/cart'; - -export const addToCartMutation = /* GraphQL */ ` - mutation addToCart($cartId: ID!, $lines: [CartLineInput!]!) { - cartLinesAdd(cartId: $cartId, lines: $lines) { - cart { - ...cart - } - } - } - ${cartFragment} -`; - -export const createCartMutation = /* GraphQL */ ` - mutation createCart($lineItems: [CartLineInput!]) { - cartCreate(input: { lines: $lineItems }) { - cart { - ...cart - } - } - } - ${cartFragment} -`; - -export const editCartItemsMutation = /* GraphQL */ ` - mutation editCartItems($cartId: ID!, $lines: [CartLineUpdateInput!]!) { - cartLinesUpdate(cartId: $cartId, lines: $lines) { - cart { - ...cart - } - } - } - ${cartFragment} -`; - -export const removeFromCartMutation = /* GraphQL */ ` - mutation removeFromCart($cartId: ID!, $lineIds: [ID!]!) { - cartLinesRemove(cartId: $cartId, lineIds: $lineIds) { - cart { - ...cart - } - } - } - ${cartFragment} -`; diff --git a/lib/shopify/queries/cart.ts b/lib/shopify/queries/cart.ts deleted file mode 100644 index 044e47f668..0000000000 --- a/lib/shopify/queries/cart.ts +++ /dev/null @@ -1,10 +0,0 @@ -import cartFragment from '../fragments/cart'; - -export const getCartQuery = /* GraphQL */ ` - query getCart($cartId: ID!) { - cart(id: $cartId) { - ...cart - } - } - ${cartFragment} -`; diff --git a/lib/shopify/queries/collection.ts b/lib/shopify/queries/collection.ts deleted file mode 100644 index 6396ff8eba..0000000000 --- a/lib/shopify/queries/collection.ts +++ /dev/null @@ -1,56 +0,0 @@ -import productFragment from '../fragments/product'; -import seoFragment from '../fragments/seo'; - -const collectionFragment = /* GraphQL */ ` - fragment collection on Collection { - handle - title - description - seo { - ...seo - } - updatedAt - } - ${seoFragment} -`; - -export const getCollectionQuery = /* GraphQL */ ` - query getCollection($handle: String!) { - collection(handle: $handle) { - ...collection - } - } - ${collectionFragment} -`; - -export const getCollectionsQuery = /* GraphQL */ ` - query getCollections { - collections(first: 100, sortKey: TITLE) { - edges { - node { - ...collection - } - } - } - } - ${collectionFragment} -`; - -export const getCollectionProductsQuery = /* GraphQL */ ` - query getCollectionProducts( - $handle: String! - $sortKey: ProductCollectionSortKeys - $reverse: Boolean - ) { - collection(handle: $handle) { - products(sortKey: $sortKey, reverse: $reverse, first: 100) { - edges { - node { - ...product - } - } - } - } - } - ${productFragment} -`; diff --git a/lib/shopify/queries/menu.ts b/lib/shopify/queries/menu.ts deleted file mode 100644 index d05b099496..0000000000 --- a/lib/shopify/queries/menu.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const getMenuQuery = /* GraphQL */ ` - query getMenu($handle: String!) { - menu(handle: $handle) { - items { - title - url - } - } - } -`; diff --git a/lib/shopify/queries/page.ts b/lib/shopify/queries/page.ts deleted file mode 100644 index ac6f6f986a..0000000000 --- a/lib/shopify/queries/page.ts +++ /dev/null @@ -1,41 +0,0 @@ -import seoFragment from '../fragments/seo'; - -const pageFragment = /* GraphQL */ ` - fragment page on Page { - ... on Page { - id - title - handle - body - bodySummary - seo { - ...seo - } - createdAt - updatedAt - } - } - ${seoFragment} -`; - -export const getPageQuery = /* GraphQL */ ` - query getPage($handle: String!) { - pageByHandle(handle: $handle) { - ...page - } - } - ${pageFragment} -`; - -export const getPagesQuery = /* GraphQL */ ` - query getPages { - pages(first: 100) { - edges { - node { - ...page - } - } - } - } - ${pageFragment} -`; diff --git a/lib/shopify/queries/product.ts b/lib/shopify/queries/product.ts deleted file mode 100644 index d3f12bd0f7..0000000000 --- a/lib/shopify/queries/product.ts +++ /dev/null @@ -1,32 +0,0 @@ -import productFragment from '../fragments/product'; - -export const getProductQuery = /* GraphQL */ ` - query getProduct($handle: String!) { - product(handle: $handle) { - ...product - } - } - ${productFragment} -`; - -export const getProductsQuery = /* GraphQL */ ` - query getProducts($sortKey: ProductSortKeys, $reverse: Boolean, $query: String) { - products(sortKey: $sortKey, reverse: $reverse, query: $query, first: 100) { - edges { - node { - ...product - } - } - } - } - ${productFragment} -`; - -export const getProductRecommendationsQuery = /* GraphQL */ ` - query getProductRecommendations($productId: ID!) { - productRecommendations(productId: $productId) { - ...product - } - } - ${productFragment} -`; diff --git a/lib/shopify/types.ts b/lib/shopify/types.ts deleted file mode 100644 index 23dc02d469..0000000000 --- a/lib/shopify/types.ts +++ /dev/null @@ -1,265 +0,0 @@ -export type Maybe = T | null; - -export type Connection = { - edges: Array>; -}; - -export type Edge = { - node: T; -}; - -export type Cart = Omit & { - lines: CartItem[]; -}; - -export type CartItem = { - id: string; - quantity: number; - cost: { - totalAmount: Money; - }; - merchandise: { - id: string; - title: string; - selectedOptions: { - name: string; - value: string; - }[]; - product: Product; - }; -}; - -export type Collection = ShopifyCollection & { - path: string; -}; - -export type Image = { - url: string; - altText: string; - width: number; - height: number; -}; - -export type Menu = { - title: string; - path: string; -}; - -export type Money = { - amount: string; - currencyCode: string; -}; - -export type Page = { - id: string; - title: string; - handle: string; - body: string; - bodySummary: string; - seo?: SEO; - createdAt: string; - updatedAt: string; -}; - -export type Product = Omit & { - variants: ProductVariant[]; - images: Image[]; -}; - -export type ProductOption = { - id: string; - name: string; - values: string[]; -}; - -export type ProductVariant = { - id: string; - title: string; - availableForSale: boolean; - selectedOptions: { - name: string; - value: string; - }[]; - price: Money; -}; - -export type SEO = { - title: string; - description: string; -}; - -export type ShopifyCart = { - id: string; - checkoutUrl: string; - cost: { - subtotalAmount: Money; - totalAmount: Money; - totalTaxAmount: Money; - }; - lines: Connection; - totalQuantity: number; -}; - -export type ShopifyCollection = { - handle: string; - title: string; - description: string; - seo: SEO; - updatedAt: string; -}; - -export type ShopifyProduct = { - id: string; - handle: string; - availableForSale: boolean; - title: string; - description: string; - descriptionHtml: string; - options: ProductOption[]; - priceRange: { - maxVariantPrice: Money; - minVariantPrice: Money; - }; - variants: Connection; - featuredImage: Image; - images: Connection; - seo: SEO; - tags: string[]; - updatedAt: string; -}; - -export type ShopifyCartOperation = { - data: { - cart: ShopifyCart; - }; - variables: { - cartId: string; - }; -}; - -export type ShopifyCreateCartOperation = { - data: { cartCreate: { cart: ShopifyCart } }; -}; - -export type ShopifyAddToCartOperation = { - data: { - cartLinesAdd: { - cart: ShopifyCart; - }; - }; - variables: { - cartId: string; - lines: { - merchandiseId: string; - quantity: number; - }[]; - }; -}; - -export type ShopifyRemoveFromCartOperation = { - data: { - cartLinesRemove: { - cart: ShopifyCart; - }; - }; - variables: { - cartId: string; - lineIds: string[]; - }; -}; - -export type ShopifyUpdateCartOperation = { - data: { - cartLinesUpdate: { - cart: ShopifyCart; - }; - }; - variables: { - cartId: string; - lines: { - id: string; - merchandiseId: string; - quantity: number; - }[]; - }; -}; - -export type ShopifyCollectionOperation = { - data: { - collection: ShopifyCollection; - }; - variables: { - handle: string; - }; -}; - -export type ShopifyCollectionProductsOperation = { - data: { - collection: { - products: Connection; - }; - }; - variables: { - handle: string; - reverse?: boolean; - sortKey?: string; - }; -}; - -export type ShopifyCollectionsOperation = { - data: { - collections: Connection; - }; -}; - -export type ShopifyMenuOperation = { - data: { - menu?: { - items: { - title: string; - url: string; - }[]; - }; - }; - variables: { - handle: string; - }; -}; - -export type ShopifyPageOperation = { - data: { pageByHandle: Page }; - variables: { handle: string }; -}; - -export type ShopifyPagesOperation = { - data: { - pages: Connection; - }; -}; - -export type ShopifyProductOperation = { - data: { product: ShopifyProduct }; - variables: { - handle: string; - }; -}; - -export type ShopifyProductRecommendationsOperation = { - data: { - productRecommendations: ShopifyProduct[]; - }; - variables: { - productId: string; - }; -}; - -export type ShopifyProductsOperation = { - data: { - products: Connection; - }; - variables: { - query?: string; - reverse?: boolean; - sortKey?: string; - }; -}; From ec0789dcec5af4bfd411ec15af43b336674423bf Mon Sep 17 00:00:00 2001 From: DuvCharles Date: Tue, 20 Jun 2023 18:30:42 +0200 Subject: [PATCH 02/11] feat: create sylius folder --- .env.example | 7 ++----- lib/constants.ts | 4 +--- lib/sylius/index.ts | 25 +++++++++++++++++++++++++ lib/type-guards.ts | 27 --------------------------- 4 files changed, 28 insertions(+), 35 deletions(-) create mode 100644 lib/sylius/index.ts diff --git a/.env.example b/.env.example index 9ff0463db9..c5171847f5 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,4 @@ -COMPANY_NAME="Vercel Inc." -TWITTER_CREATOR="@vercel" +TWITTER_CREATOR="@DuvCharles" TWITTER_SITE="https://nextjs.org/commerce" SITE_NAME="Next.js Commerce" -SHOPIFY_REVALIDATION_SECRET="" -SHOPIFY_STOREFRONT_ACCESS_TOKEN="" -SHOPIFY_STORE_DOMAIN="[your-shopify-store-subdomain].myshopify.com" +SYLIUS_STORE_DOMAIN=localhost:8001 diff --git a/lib/constants.ts b/lib/constants.ts index 99711221aa..454f3cc5a6 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -25,6 +25,4 @@ export const TAGS = { products: 'products' }; -export const HIDDEN_PRODUCT_TAG = 'nextjs-frontend-hidden'; -export const DEFAULT_OPTION = 'Default Title'; -export const SHOPIFY_GRAPHQL_API_ENDPOINT = '/api/2023-01/graphql.json'; +export const SYLIUS_API_ENDPOINT = '/api/v2'; diff --git a/lib/sylius/index.ts b/lib/sylius/index.ts new file mode 100644 index 0000000000..b93e99d8ec --- /dev/null +++ b/lib/sylius/index.ts @@ -0,0 +1,25 @@ +import { SYLIUS_API_ENDPOINT } from 'lib/constants'; + +const domain = `${process.env.SYLIUS_STORE_DOMAIN}`; +const endpoint = `${domain}${SYLIUS_API_ENDPOINT}`; + +// Pages +export const getPages = () => []; +export const getPage = () => {}; + +// Products +export const getProducts = () => []; +export const getProduct = () => {}; +export const getProductRecommendations = () => []; +export const getCollection = () => {}; +export const getCollectionProducts = () => []; + +// Cart +export const createCart = () => {}; +export const getCart = () => {}; +export const addToCart = () => {}; +export const removeFromCart = () => {}; +export const updateCart = () => {}; + +// Site +export const getMenu = () => []; diff --git a/lib/type-guards.ts b/lib/type-guards.ts index 6f920d1f62..e69de29bb2 100644 --- a/lib/type-guards.ts +++ b/lib/type-guards.ts @@ -1,27 +0,0 @@ -export interface ShopifyErrorLike { - status: number; - message: Error; - cause?: Error; -} - -export const isObject = (object: unknown): object is Record => { - return typeof object === 'object' && object !== null && !Array.isArray(object); -}; - -export const isShopifyError = (error: unknown): error is ShopifyErrorLike => { - if (!isObject(error)) return false; - - if (error instanceof Error) return true; - - return findError(error); -}; - -function findError(error: T): boolean { - if (Object.prototype.toString.call(error) === '[object Error]') { - return true; - } - - const prototype = Object.getPrototypeOf(error) as T | null; - - return prototype === null ? false : findError(prototype); -} From ea9d90b8799044cdc4ebc0c93ba12eaecd6d9d5b Mon Sep 17 00:00:00 2001 From: DuvCharles Date: Tue, 20 Jun 2023 18:30:59 +0200 Subject: [PATCH 03/11] feat: import from lib/sylius --- app/[page]/opengraph-image.tsx | 2 +- app/[page]/page.tsx | 2 +- app/product/[handle]/page.tsx | 4 ++-- app/search/[collection]/opengraph-image.tsx | 2 +- app/search/[collection]/page.tsx | 2 +- app/search/page.tsx | 2 +- app/sitemap.ts | 2 +- components/carousel.tsx | 2 +- components/cart/delete-item-button.tsx | 2 +- components/cart/edit-item-quantity-button.tsx | 2 +- components/cart/index.tsx | 2 +- components/cart/modal.tsx | 2 +- components/grid/three-items.tsx | 4 ++-- components/layout/footer.tsx | 4 ++-- components/layout/navbar/index.tsx | 6 +++--- components/layout/navbar/mobile-menu.tsx | 2 +- components/layout/product-grid-items.tsx | 2 +- components/layout/search/collections.tsx | 2 +- components/product/variant-selector.tsx | 2 +- 19 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/[page]/opengraph-image.tsx b/app/[page]/opengraph-image.tsx index 2fd59281e8..7f663ba3d9 100644 --- a/app/[page]/opengraph-image.tsx +++ b/app/[page]/opengraph-image.tsx @@ -1,5 +1,5 @@ import OpengraphImage from 'components/opengraph-image'; -import { getPage } from 'lib/shopify'; +import { getPage } from 'lib/sylius'; export const runtime = 'edge'; diff --git a/app/[page]/page.tsx b/app/[page]/page.tsx index 3dfde9f922..0361282b21 100644 --- a/app/[page]/page.tsx +++ b/app/[page]/page.tsx @@ -1,7 +1,7 @@ import type { Metadata } from 'next'; import Prose from 'components/prose'; -import { getPage } from 'lib/shopify'; +import { getPage } from 'lib/sylius'; import { notFound } from 'next/navigation'; export const runtime = 'edge'; diff --git a/app/product/[handle]/page.tsx b/app/product/[handle]/page.tsx index cf31f00215..a86922242b 100644 --- a/app/product/[handle]/page.tsx +++ b/app/product/[handle]/page.tsx @@ -7,8 +7,8 @@ import Footer from 'components/layout/footer'; import { Gallery } from 'components/product/gallery'; import { ProductDescription } from 'components/product/product-description'; import { HIDDEN_PRODUCT_TAG } from 'lib/constants'; -import { getProduct, getProductRecommendations } from 'lib/shopify'; -import { Image } from 'lib/shopify/types'; +import { getProduct, getProductRecommendations } from 'lib/sylius'; +import { Image } from 'lib/sylius/types'; import Link from 'next/link'; export const runtime = 'edge'; diff --git a/app/search/[collection]/opengraph-image.tsx b/app/search/[collection]/opengraph-image.tsx index 9eb9c47f77..9769d5ddc3 100644 --- a/app/search/[collection]/opengraph-image.tsx +++ b/app/search/[collection]/opengraph-image.tsx @@ -1,5 +1,5 @@ import OpengraphImage from 'components/opengraph-image'; -import { getCollection } from 'lib/shopify'; +import { getCollection } from 'lib/sylius'; export const runtime = 'edge'; diff --git a/app/search/[collection]/page.tsx b/app/search/[collection]/page.tsx index 25416d544d..8e0b7da773 100644 --- a/app/search/[collection]/page.tsx +++ b/app/search/[collection]/page.tsx @@ -1,4 +1,4 @@ -import { getCollection, getCollectionProducts } from 'lib/shopify'; +import { getCollection, getCollectionProducts } from 'lib/sylius'; import { Metadata } from 'next'; import { notFound } from 'next/navigation'; diff --git a/app/search/page.tsx b/app/search/page.tsx index 2f7a53bd4a..7af0310b2b 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -1,7 +1,7 @@ import Grid from 'components/grid'; import ProductGridItems from 'components/layout/product-grid-items'; import { defaultSort, sorting } from 'lib/constants'; -import { getProducts } from 'lib/shopify'; +import { getProducts } from 'lib/sylius'; export const runtime = 'edge'; diff --git a/app/sitemap.ts b/app/sitemap.ts index 46d39669c2..9bbbebd283 100644 --- a/app/sitemap.ts +++ b/app/sitemap.ts @@ -1,4 +1,4 @@ -import { getCollections, getPages, getProducts } from 'lib/shopify'; +import { getCollections, getPages, getProducts } from 'lib/sylius'; import { MetadataRoute } from 'next'; type Route = { diff --git a/components/carousel.tsx b/components/carousel.tsx index 286d4dfea4..5e297f3f6f 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -1,4 +1,4 @@ -import { getCollectionProducts } from 'lib/shopify'; +import { getCollectionProducts } from 'lib/sylius'; import Link from 'next/link'; import { GridTileImage } from './grid/tile'; diff --git a/components/cart/delete-item-button.tsx b/components/cart/delete-item-button.tsx index 605adcf512..cc2b0141cb 100644 --- a/components/cart/delete-item-button.tsx +++ b/components/cart/delete-item-button.tsx @@ -4,7 +4,7 @@ import { useRouter } from 'next/navigation'; import clsx from 'clsx'; import { removeItem } from 'components/cart/actions'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/sylius/types'; import { useTransition } from 'react'; export default function DeleteItemButton({ item }: { item: CartItem }) { diff --git a/components/cart/edit-item-quantity-button.tsx b/components/cart/edit-item-quantity-button.tsx index e846196caa..214e4a568d 100644 --- a/components/cart/edit-item-quantity-button.tsx +++ b/components/cart/edit-item-quantity-button.tsx @@ -5,7 +5,7 @@ import { MinusIcon, PlusIcon } from '@heroicons/react/24/outline'; import clsx from 'clsx'; import { removeItem, updateItemQuantity } from 'components/cart/actions'; import LoadingDots from 'components/loading-dots'; -import type { CartItem } from 'lib/shopify/types'; +import type { CartItem } from 'lib/sylius/types'; export default function EditItemQuantityButton({ item, diff --git a/components/cart/index.tsx b/components/cart/index.tsx index 3e250ba93c..fb53271656 100644 --- a/components/cart/index.tsx +++ b/components/cart/index.tsx @@ -1,4 +1,4 @@ -import { getCart } from 'lib/shopify'; +import { getCart } from 'lib/sylius'; import { cookies } from 'next/headers'; import CartModal from './modal'; diff --git a/components/cart/modal.tsx b/components/cart/modal.tsx index 4fbfcc6adf..fa1c54d73d 100644 --- a/components/cart/modal.tsx +++ b/components/cart/modal.tsx @@ -4,7 +4,7 @@ import { Dialog, Transition } from '@headlessui/react'; import { ShoppingCartIcon } from '@heroicons/react/24/outline'; import Price from 'components/price'; import { DEFAULT_OPTION } from 'lib/constants'; -import type { Cart } from 'lib/shopify/types'; +import type { Cart } from 'lib/sylius/types'; import { createUrl } from 'lib/utils'; import Image from 'next/image'; import Link from 'next/link'; diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index 23b3f89910..75948bdfd5 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -1,6 +1,6 @@ import { GridTileImage } from 'components/grid/tile'; -import { getCollectionProducts } from 'lib/shopify'; -import type { Product } from 'lib/shopify/types'; +import { getCollectionProducts } from 'lib/sylius'; +import type { Product } from 'lib/sylius/types'; import Link from 'next/link'; function ThreeItemGridItem({ diff --git a/components/layout/footer.tsx b/components/layout/footer.tsx index 8627ca28b3..67123ddea2 100644 --- a/components/layout/footer.tsx +++ b/components/layout/footer.tsx @@ -2,7 +2,7 @@ import Link from 'next/link'; import FooterMenu from 'components/layout/footer-menu'; import LogoSquare from 'components/logo-square'; -import { getMenu } from 'lib/shopify'; +import { getMenu } from 'lib/sylius'; import { Suspense } from 'react'; const { COMPANY_NAME, SITE_NAME } = process.env; @@ -11,7 +11,7 @@ export default async function Footer() { const currentYear = new Date().getFullYear(); const copyrightDate = 2023 + (currentYear > 2023 ? `-${currentYear}` : ''); const skeleton = 'w-full h-6 animate-pulse rounded bg-neutral-200 dark:bg-neutral-700'; - const menu = await getMenu('next-js-frontend-footer-menu'); + const menu = await getMenu(); const copyrightName = COMPANY_NAME || SITE_NAME || ''; return ( diff --git a/components/layout/navbar/index.tsx b/components/layout/navbar/index.tsx index 0058d5ec8d..ea6d9bb0c1 100644 --- a/components/layout/navbar/index.tsx +++ b/components/layout/navbar/index.tsx @@ -1,8 +1,8 @@ import Cart from 'components/cart'; import OpenCart from 'components/cart/open-cart'; import LogoSquare from 'components/logo-square'; -import { getMenu } from 'lib/shopify'; -import { Menu } from 'lib/shopify/types'; +import { getMenu } from 'lib/sylius'; +import { Menu } from 'lib/sylius/types'; import Link from 'next/link'; import { Suspense } from 'react'; import MobileMenu from './mobile-menu'; @@ -10,7 +10,7 @@ import Search from './search'; const { SITE_NAME } = process.env; export default async function Navbar() { - const menu = await getMenu('next-js-frontend-header-menu'); + const menu = await getMenu(); return (