From 390b2c33032efb1b4a52fafd940a583fe2b4f49c Mon Sep 17 00:00:00 2001 From: Luis Alvarez Date: Thu, 1 Oct 2020 20:26:32 -0500 Subject: [PATCH] Added products paths to getStaticPaths --- .../api/operations/get-all-product-paths.ts | 54 +++++++++++++++++++ lib/bigcommerce/api/operations/get-product.ts | 16 +++--- lib/bigcommerce/schema.d.ts | 22 +++++++- pages/product/[slug].tsx | 35 +++++++----- 4 files changed, 102 insertions(+), 25 deletions(-) create mode 100644 lib/bigcommerce/api/operations/get-all-product-paths.ts diff --git a/lib/bigcommerce/api/operations/get-all-product-paths.ts b/lib/bigcommerce/api/operations/get-all-product-paths.ts new file mode 100644 index 000000000..6fea2401b --- /dev/null +++ b/lib/bigcommerce/api/operations/get-all-product-paths.ts @@ -0,0 +1,54 @@ +import type { GetAllProductPathsQuery } from 'lib/bigcommerce/schema'; +import type { RecursivePartial, RecursiveRequired } from '../utils/types'; +import { BigcommerceConfig, getConfig } from '..'; + +export const getAllProductPathsQuery = /* GraphQL */ ` + query getAllProductPaths { + site { + products { + edges { + node { + path + } + } + } + } + } +`; + +export interface GetAllProductPathsResult { + products: T extends GetAllProductPathsQuery + ? NonNullable + : unknown; +} + +async function getAllProductPaths(opts?: { + query?: string; + config?: BigcommerceConfig; +}): Promise>; + +async function getAllProductPaths(opts: { + query: string; + config?: BigcommerceConfig; +}): Promise>; + +async function getAllProductPaths({ + query = getAllProductPathsQuery, + config = getConfig(), +}: { + query?: string; + config?: BigcommerceConfig; +} = {}): Promise> { + // RecursivePartial forces the method to check for every prop in the data, which is + // required in case there's a custom `query` + const data = await config.fetch>( + query + ); + const products = data.site?.products?.edges; + + return { + products: (products as RecursiveRequired) ?? [], + }; +} + +export default getAllProductPaths; diff --git a/lib/bigcommerce/api/operations/get-product.ts b/lib/bigcommerce/api/operations/get-product.ts index c548f3873..bbd705242 100644 --- a/lib/bigcommerce/api/operations/get-product.ts +++ b/lib/bigcommerce/api/operations/get-product.ts @@ -4,16 +4,11 @@ import type { } from 'lib/bigcommerce/schema'; import type { RecursivePartial, RecursiveRequired } from '../utils/types'; import { productInfoFragment } from '../fragments/product'; -import { - BigcommerceConfig, - getConfig, - Images, - ProductImageVariables, -} from '..'; +import { BigcommerceConfig, getConfig, Images } from '..'; export const getProductQuery = /* GraphQL */ ` query getProduct( - $slug: String! + $path: String! $imgSmallWidth: Int = 320 $imgSmallHeight: Int $imgMediumWidth: Int = 640 @@ -24,7 +19,7 @@ export const getProductQuery = /* GraphQL */ ` $imgXLHeight: Int ) { site { - route(path: $slug) { + route(path: $path) { node { __typename ... on Product { @@ -45,7 +40,7 @@ export interface GetProductResult { } export type ProductVariables = Images & - Omit; + ({ path: string; slug?: never } | { path?: never; slug: string }); async function getProduct(opts: { query?: string; @@ -61,7 +56,7 @@ async function getProduct(opts: { async function getProduct({ query = getProductQuery, - variables: vars, + variables: { slug, ...vars }, config = getConfig(), }: { query?: string; @@ -71,6 +66,7 @@ async function getProduct({ const variables: GetProductQueryVariables = { ...config.imageVariables, ...vars, + path: slug ? `/${slug}/` : vars.path!, }; const data = await config.fetch>(query, { variables, diff --git a/lib/bigcommerce/schema.d.ts b/lib/bigcommerce/schema.d.ts index 5f25ff205..638e34e44 100644 --- a/lib/bigcommerce/schema.d.ts +++ b/lib/bigcommerce/schema.d.ts @@ -1713,6 +1713,26 @@ export type ProductInfoFragment = ( ) } ); +export type GetAllProductPathsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetAllProductPathsQuery = ( + { __typename?: 'Query' } + & { site: ( + { __typename?: 'Site' } + & { products: ( + { __typename?: 'ProductConnection' } + & { edges?: Maybe + ) } + )>>> } + ) } + ) } +); + export type GetAllProductsQueryVariables = Exact<{ first?: Maybe; imgSmallWidth?: Maybe; @@ -1748,7 +1768,7 @@ export type GetAllProductsQuery = ( ); export type GetProductQueryVariables = Exact<{ - slug: Scalars['String']; + path: Scalars['String']; imgSmallWidth?: Maybe; imgSmallHeight?: Maybe; imgMediumWidth?: Maybe; diff --git a/pages/product/[slug].tsx b/pages/product/[slug].tsx index 3b333ec12..012c43368 100644 --- a/pages/product/[slug].tsx +++ b/pages/product/[slug].tsx @@ -1,18 +1,16 @@ -import { GetStaticPropsContext, InferGetStaticPropsType } from "next"; -import { useRouter } from "next/router"; -import getProduct from "lib/bigcommerce/api/operations/get-product"; -import { Layout } from "@components/core"; -import { ProductView } from "@components/product"; +import { GetStaticPropsContext, InferGetStaticPropsType } from 'next'; +import { useRouter } from 'next/router'; +import getProduct from 'lib/bigcommerce/api/operations/get-product'; +import { Layout } from '@components/core'; +import { ProductView } from '@components/product'; +import getAllProductPaths from '@lib/bigcommerce/api/operations/get-all-product-paths'; export async function getStaticProps({ params, }: GetStaticPropsContext<{ slug: string }>) { const { product } = await getProduct({ variables: { slug: params!.slug } }); - - console.log("PRODUCT", product); - const productData = { - title: "T-Shirt", + title: 'T-Shirt', description: ` Nothing undercover about this tee. Nope. This is the official Bad Boys tee. Printed in white or black ink on Black, Brown, or Oatmeal. @@ -21,12 +19,13 @@ export async function getStaticProps({ run. Printing starts when the drop ends. Reminder: Bad Boys For Life. Shipping may take 10+ days due to COVID-19. `, - price: "$50", - colors: ["black", "white", "pink"], - sizes: ["s", "m", "l", "xl", "xxl"], + price: '$50', + colors: ['black', 'white', 'pink'], + sizes: ['s', 'm', 'l', 'xl', 'xxl'], }; return { props: { + product, productData, }, revalidate: 200, @@ -34,16 +33,24 @@ export async function getStaticProps({ } export async function getStaticPaths() { + const { products } = await getAllProductPaths(); + return { - paths: [], - fallback: "unstable_blocking", + paths: products.map((product) => ({ + params: { slug: product!.node.path }, + })), + fallback: 'unstable_blocking', }; } export default function Home({ + product, productData, }: InferGetStaticPropsType) { + console.log('PRODUCT', product); + const router = useRouter(); + return ( {router.isFallback ? (