From 8eda86ae824eea53aabd2798f9b8fa6a68826a32 Mon Sep 17 00:00:00 2001 From: Chloe Date: Wed, 20 Apr 2022 15:43:05 +0700 Subject: [PATCH] Add get-site-info operator Signed-off-by: Chloe --- .vscode/settings.json | 5 +- packages/opencommerce/schema.d.ts | 33 +++++++ .../src/api/operations/get-site-info.ts | 85 ++++++++++++------- .../src/api/queries/get-tags-query.ts | 14 +++ .../src/api/queries/get-vendors-query.ts | 10 +++ packages/opencommerce/src/types/site.ts | 15 ++++ packages/opencommerce/src/utils/normalize.ts | 20 +++++ 7 files changed, 148 insertions(+), 34 deletions(-) create mode 100644 packages/opencommerce/src/api/queries/get-tags-query.ts create mode 100644 packages/opencommerce/src/api/queries/get-vendors-query.ts create mode 100644 packages/opencommerce/src/types/site.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bf4d12b5..fd83e09f5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,5 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true -} + "editor.formatOnSave": true, + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/packages/opencommerce/schema.d.ts b/packages/opencommerce/schema.d.ts index a8b175848..bc48653e8 100644 --- a/packages/opencommerce/schema.d.ts +++ b/packages/opencommerce/schema.d.ts @@ -8195,3 +8195,36 @@ export type GetProductBySlugQuery = { } | null } | null } + +export type GetTagsQueryVariables = Exact<{ + first: Scalars['ConnectionLimitInt'] + shopId: Scalars['ID'] +}> + +export type GetTagsQuery = { + __typename?: 'Query' + tags: { + __typename?: 'TagConnection' + edges: Array<{ + __typename?: 'TagEdge' + node: { + __typename?: 'Tag' + _id: string + displayTitle: string | null + slug: string | null + } | null + } | null> | null + } | null +} + +export type GetAllProductVendorsQueryVariables = Exact<{ + shopIds: Array> | InputMaybe +}> + +export type GetAllProductVendorsQuery = { + __typename?: 'Query' + vendors: { + __typename?: 'VendorConnection' + nodes: Array<{ __typename?: 'Vendor'; name: string | null } | null> | null + } | null +} diff --git a/packages/opencommerce/src/api/operations/get-site-info.ts b/packages/opencommerce/src/api/operations/get-site-info.ts index 025a283fa..4fecc98c9 100644 --- a/packages/opencommerce/src/api/operations/get-site-info.ts +++ b/packages/opencommerce/src/api/operations/get-site-info.ts @@ -1,42 +1,63 @@ -import { OperationContext } from '@vercel/commerce/api/operations' -import { Category } from '@vercel/commerce/types/site' -import type { OpenCommerceConfig } from '../index' +import { + OperationContext, + OperationOptions, +} from '@vercel/commerce/api/operations' +import { + GetTagsQuery, + GetAllProductVendorsQuery, + GetTagsQueryVariables, + GetAllProductVendorsQueryVariables, +} from '../../../schema' +import getTagsQuery from '../queries/get-tags-query' +import { GetSiteInfoOperation, OCCategory } from '../../types/site' +import { normalizeCategory, normalizeVendors } from '../../utils/normalize' +import type { OpenCommerceConfig, Provider } from '..' +import filterEdges from '../utils/filter-edges' +import getAllProductVendors from '../queries/get-vendors-query' -export type GetSiteInfoResult< - T extends { categories: any[]; brands: any[] } = { - categories: Category[] - brands: any[] - } -> = T +export default function getSiteInfoOperation({ + commerce, +}: OperationContext) { + async function getSiteInfo(opts?: { + config?: Partial + preview?: boolean + }): Promise -export default function getSiteInfoOperation({}: OperationContext) { - function getSiteInfo({ - query, - variables, + async function getSiteInfo( + opts: { + config?: Partial + preview?: boolean + } & OperationOptions + ): Promise + + async function getSiteInfo({ config: cfg, }: { query?: string - variables?: any config?: Partial preview?: boolean - } = {}): Promise { - return Promise.resolve({ - categories: [ - { - id: 'new-arrivals', - name: 'New Arrivals', - slug: 'new-arrivals', - path: '/new-arrivals', - }, - { - id: 'featured', - name: 'Featured', - slug: 'featured', - path: '/featured', - }, - ], - brands: [], - }) + } = {}): Promise { + const { fetch, shopId } = commerce.getConfig(cfg) + + const [categoriesResponse, vendorsResponse] = await Promise.all([ + await fetch(getTagsQuery, { + variables: { first: 250, shopId }, + }), + await fetch< + GetAllProductVendorsQuery, + GetAllProductVendorsQueryVariables + >(getAllProductVendors, { variables: { shopIds: [shopId] } }), + ]) + + const categories = filterEdges(categoriesResponse.data.tags?.edges).map( + (edge) => normalizeCategory(edge.node! as OCCategory) + ) + + const brands = [ + ...new Set(filterEdges(vendorsResponse.data.vendors?.nodes)), + ].map(normalizeVendors) + + return { categories, brands } } return getSiteInfo diff --git a/packages/opencommerce/src/api/queries/get-tags-query.ts b/packages/opencommerce/src/api/queries/get-tags-query.ts new file mode 100644 index 000000000..6644df423 --- /dev/null +++ b/packages/opencommerce/src/api/queries/get-tags-query.ts @@ -0,0 +1,14 @@ +const getTagsQuery = /* GraphQL */ ` + query getTags($first: ConnectionLimitInt!, $shopId: ID!) { + tags(first: $first, shopId: $shopId) { + edges { + node { + _id + displayTitle + slug + } + } + } + } +` +export default getTagsQuery diff --git a/packages/opencommerce/src/api/queries/get-vendors-query.ts b/packages/opencommerce/src/api/queries/get-vendors-query.ts new file mode 100644 index 000000000..ab55b4ea2 --- /dev/null +++ b/packages/opencommerce/src/api/queries/get-vendors-query.ts @@ -0,0 +1,10 @@ +const getAllProductVendors = /* GraphQL */ ` + query getAllProductVendors($shopIds: [ID]!) { + vendors(shopIds: $shopIds) { + nodes { + name + } + } + } +` +export default getAllProductVendors diff --git a/packages/opencommerce/src/types/site.ts b/packages/opencommerce/src/types/site.ts new file mode 100644 index 000000000..159152b99 --- /dev/null +++ b/packages/opencommerce/src/types/site.ts @@ -0,0 +1,15 @@ +import { Vendor as QueryVender, TagEdge } from '../../schema' + +export * from '@vercel/commerce/types/site' + +export type OCCategory = NonNullable['node']> + +export type OCVendor = QueryVender + +export type Vendor = { + node: { + entityId: string + name: string + path: string + } +} diff --git a/packages/opencommerce/src/utils/normalize.ts b/packages/opencommerce/src/utils/normalize.ts index 0d0acd774..a3db9a64e 100644 --- a/packages/opencommerce/src/utils/normalize.ts +++ b/packages/opencommerce/src/utils/normalize.ts @@ -4,6 +4,7 @@ import type { ProductOptionValues, ProductVariant, } from '../types/product' +import { OCCategory, Category, Vendor, OCVendor } from '../types/site' import { CatalogItemProduct, CatalogProduct, @@ -205,3 +206,22 @@ function colorizeProductOptionValue( } return value } + +export function normalizeCategory(category: OCCategory): Category { + return { + id: category._id, + name: category.displayTitle ?? '', + slug: category.slug ?? '', + path: category.slug ? `/${category.slug}` : '', + } +} + +export function normalizeVendors({ name }: OCVendor): Vendor { + return { + node: { + entityId: name ?? '', + name: name ?? '', + path: `brands/${name}`, + }, + } +}