Update product mutations & queries

This commit is contained in:
cond0r 2021-04-29 19:22:22 +03:00
parent efed2c5e95
commit cdf8005c21
16 changed files with 170 additions and 98 deletions

View File

@ -1,6 +1,12 @@
import { ProductEdge } from '../../schema'
import {
GetAllProductPathsQuery,
GetAllProductVendorsQuery,
ProductEdge,
} from '../../schema'
import { ShopifyConfig } from '..'
type FetchAllProductsQuery = GetAllProductPathsQuery | GetAllProductVendorsQuery
const fetchAllProducts = async ({
config,
query,
@ -10,19 +16,18 @@ const fetchAllProducts = async ({
}: {
config: ShopifyConfig
query: string
acc?: ProductEdge[]
acc?: any[]
variables?: any
cursor?: string
}): Promise<ProductEdge[]> => {
const { data } = await config.fetch(query, {
const { data } = await config.fetch<FetchAllProductsQuery>(query, {
variables: { ...variables, cursor },
})
const edges: ProductEdge[] = data.products?.edges ?? []
const hasNextPage = data.products?.pageInfo?.hasNextPage
const edges = data.products.edges
acc = acc.concat(edges)
if (hasNextPage) {
if (data.products.pageInfo.hasNextPage) {
const cursor = edges.pop()?.cursor
if (cursor) {
return fetchAllProducts({

View File

@ -1,7 +1,5 @@
import { Product } from '@commerce/types'
import { getConfig, ShopifyConfig } from '../api'
import fetchAllProducts from '../api/utils/fetch-all-products'
import { ProductEdge } from '../schema'
import getAllProductsPathsQuery from '../utils/queries/get-all-products-paths-query'
type ProductPath = {
@ -31,7 +29,7 @@ const getAllProductPaths = async (options?: {
})
return {
products: products?.map(({ node: { handle } }: ProductEdge) => ({
products: products?.map(({ node: { handle } }) => ({
node: {
path: `/${handle}`,
},

View File

@ -1,6 +1,5 @@
import { GraphQLFetcherResult } from '@commerce/api'
import { getConfig, ShopifyConfig } from '../api'
import { ProductEdge } from '../schema'
import { GetAllProductsQuery, Product as ShopifyProduct } from '../schema'
import { getAllProductsQuery } from '../utils/queries'
import { normalizeProduct } from '../utils/normalize'
import { Product } from '@commerce/types'
@ -10,30 +9,25 @@ type Variables = {
field?: string
}
type ReturnType = {
products: Product[]
}
const getAllProducts = async (options: {
variables?: Variables
config?: ShopifyConfig
preview?: boolean
}): Promise<ReturnType> => {
}): Promise<{
products: Product[]
}> => {
let { config, variables = { first: 250 } } = options ?? {}
config = getConfig(config)
const { data }: GraphQLFetcherResult = await config.fetch(
const { data } = await config.fetch<GetAllProductsQuery>(
getAllProductsQuery,
{ variables }
)
const products =
data.products?.edges?.map(({ node: p }: ProductEdge) =>
normalizeProduct(p)
) ?? []
return {
products,
products: data.products.edges.map(({ node }) =>
normalizeProduct(node as ShopifyProduct)
),
}
}

View File

@ -1,30 +1,32 @@
import { GraphQLFetcherResult } from '@commerce/api'
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
}
type ReturnType = {
product: any
}
const getProduct = async (options: {
variables: Variables
config: ShopifyConfig
preview?: boolean
}): Promise<ReturnType> => {
}): Promise<{
product?: Product
}> => {
let { config, variables } = options ?? {}
config = getConfig(config)
const { data }: GraphQLFetcherResult = await config.fetch(getProductQuery, {
const {
data: { productByHandle },
} = await config.fetch<GetProductBySlugQuery>(getProductQuery, {
variables,
})
const { productByHandle } = data
return {
product: productByHandle ? normalizeProduct(productByHandle) : null,
...(productByHandle && {
product: normalizeProduct(productByHandle as ShopifyProduct),
}),
}
}

View File

@ -1,7 +1,12 @@
import { SWRHook } from '@commerce/utils/types'
import useSearch, { UseSearch } from '@commerce/product/use-search'
import { ProductEdge } from '../schema'
import {
CollectionEdge,
GetAllProductsQuery,
Product as ShopifyProduct,
ProductEdge,
} from '../schema'
import {
getAllProductsQuery,
getCollectionProductsQuery,
@ -35,30 +40,38 @@ export const handler: SWRHook<
},
async fetcher({ input, options, fetch }) {
const { categoryId, brandId } = input
const method = options?.method
const variables = getSearchVariables(input)
let products
const data = await fetch({
query: categoryId ? getCollectionProductsQuery : options.query,
method: options?.method,
variables: getSearchVariables(input),
})
let edges
// change the query to getCollectionProductsQuery when categoryId is set
if (categoryId) {
edges = data.node?.products?.edges ?? []
if (brandId) {
edges = edges.filter(
const data = await fetch<CollectionEdge>({
query: getCollectionProductsQuery,
method,
variables,
})
// filter on client when brandId & categoryId are set since is not available on collection product query
products = brandId
? data.node.products.edges.filter(
({ node: { vendor } }: ProductEdge) =>
vendor.replace(/\s+/g, '-').toLowerCase() === brandId
)
}
: data.node.products.edges
} else {
edges = data.products?.edges ?? []
const data = await fetch<GetAllProductsQuery>({
query: options.query,
method,
variables,
})
products = data.products.edges
}
return {
products: edges.map(({ node }: ProductEdge) => normalizeProduct(node)),
found: !!edges.length,
products: products?.map(({ node }) =>
normalizeProduct(node as ShopifyProduct)
),
found: !!products?.length,
}
},
useHook: ({ useData }) => (input = {}) => {

View File

@ -37,7 +37,7 @@ export type ApiVersion = {
displayName: Scalars['String']
/** The unique identifier of an ApiVersion. All supported API versions have a date-based (YYYY-MM) or `unstable` handle. */
handle: Scalars['String']
/** Whether the version is supported by Shopify. */
/** Whether the version is actively supported by Shopify. Supported API versions are guaranteed to be stable. Unsupported API versions include unstable, release candidate, and end-of-life versions that are marked as unsupported. For more information, refer to [Versioning](https://shopify.dev/concepts/about-apis/versioning). */
supported: Scalars['Boolean']
}
@ -393,6 +393,8 @@ export type Checkout = Node & {
taxExempt: Scalars['Boolean']
/** Specifies if taxes are included in the line item and shipping line prices. */
taxesIncluded: Scalars['Boolean']
/** The sum of all the duties applied to the line items in the checkout. */
totalDuties?: Maybe<MoneyV2>
/**
* The sum of all the prices of all the items in the checkout, taxes and discounts included.
* @deprecated Use `totalPriceV2` instead
@ -1661,6 +1663,8 @@ export enum CountryCode {
Zm = 'ZM',
/** Zimbabwe. */
Zw = 'ZW',
/** Unknown Region. */
Zz = 'ZZ',
}
/** Credit card information used for a payment. */
@ -2561,6 +2565,8 @@ export type ExternalVideo = Node &
alt?: Maybe<Scalars['String']>
/** The URL. */
embeddedUrl: Scalars['URL']
/** The host of the external video. */
host: MediaHost
/** Globally unique identifier. */
id: Scalars['ID']
/** The media content type. */
@ -2935,6 +2941,14 @@ export type MediaEdge = {
node: Media
}
/** Host for a Media Resource. */
export enum MediaHost {
/** Host for YouTube embedded videos. */
Youtube = 'YOUTUBE',
/** Host for Vimeo embedded videos. */
Vimeo = 'VIMEO',
}
/** Represents a Shopify hosted image. */
export type MediaImage = Node &
Media & {
@ -3503,6 +3517,8 @@ export type Order = Node & {
currencyCode: CurrencyCode
/** The subtotal of line items and their discounts, excluding line items that have been removed. Does not contain order-level discounts, duties, shipping costs, or shipping discounts. Taxes are not included unless the order is a taxes-included order. */
currentSubtotalPrice: MoneyV2
/** The total cost of duties for the order, including refunds. */
currentTotalDuties?: Maybe<MoneyV2>
/** The total amount of the order, including duties, taxes and discounts, minus amounts for line items that have been removed. */
currentTotalPrice: MoneyV2
/** The total of all taxes applied to the order, excluding taxes for returned line items. */
@ -3532,6 +3548,8 @@ export type Order = Node & {
name: Scalars['String']
/** A unique numeric identifier for the order for use by shop owner and customer. */
orderNumber: Scalars['Int']
/** The total cost of duties charged at checkout. */
originalTotalDuties?: Maybe<MoneyV2>
/** The total price of the order before any applied edits. */
originalTotalPrice: MoneyV2
/** The customer's phone number for receiving SMS notifications. */
@ -5013,9 +5031,11 @@ export type AssociateCustomerWithCheckoutMutation = {
>
}
export type Unnamed_1_MutationVariables = Exact<{ [key: string]: never }>
export type CheckoutCreateMutationVariables = Exact<{
input?: Maybe<CheckoutCreateInput>
}>
export type Unnamed_1_Mutation = { __typename?: 'Mutation' } & {
export type CheckoutCreateMutation = { __typename?: 'Mutation' } & {
checkoutCreate?: Maybe<
{ __typename?: 'CheckoutCreatePayload' } & {
checkoutUserErrors: Array<
@ -5029,12 +5049,12 @@ export type Unnamed_1_Mutation = { __typename?: 'Mutation' } & {
>
}
export type Unnamed_2_MutationVariables = Exact<{
export type CheckoutLineItemAddMutationVariables = Exact<{
checkoutId: Scalars['ID']
lineItems: Array<CheckoutLineItemInput> | CheckoutLineItemInput
}>
export type Unnamed_2_Mutation = { __typename?: 'Mutation' } & {
export type CheckoutLineItemAddMutation = { __typename?: 'Mutation' } & {
checkoutLineItemsAdd?: Maybe<
{ __typename?: 'CheckoutLineItemsAddPayload' } & {
checkoutUserErrors: Array<
@ -5048,12 +5068,12 @@ export type Unnamed_2_Mutation = { __typename?: 'Mutation' } & {
>
}
export type Unnamed_3_MutationVariables = Exact<{
export type CheckoutLineItemRemoveMutationVariables = Exact<{
checkoutId: Scalars['ID']
lineItemIds: Array<Scalars['ID']> | Scalars['ID']
}>
export type Unnamed_3_Mutation = { __typename?: 'Mutation' } & {
export type CheckoutLineItemRemoveMutation = { __typename?: 'Mutation' } & {
checkoutLineItemsRemove?: Maybe<
{ __typename?: 'CheckoutLineItemsRemovePayload' } & {
checkoutUserErrors: Array<
@ -5067,12 +5087,12 @@ export type Unnamed_3_Mutation = { __typename?: 'Mutation' } & {
>
}
export type Unnamed_4_MutationVariables = Exact<{
export type CheckoutLineItemUpdateMutationVariables = Exact<{
checkoutId: Scalars['ID']
lineItems: Array<CheckoutLineItemUpdateInput> | CheckoutLineItemUpdateInput
}>
export type Unnamed_4_Mutation = { __typename?: 'Mutation' } & {
export type CheckoutLineItemUpdateMutation = { __typename?: 'Mutation' } & {
checkoutLineItemsUpdate?: Maybe<
{ __typename?: 'CheckoutLineItemsUpdatePayload' } & {
checkoutUserErrors: Array<
@ -5370,11 +5390,11 @@ export type CheckoutDetailsFragment = { __typename?: 'Checkout' } & Pick<
}
}
export type Unnamed_5_QueryVariables = Exact<{
export type GetCheckoutQueryVariables = Exact<{
checkoutId: Scalars['ID']
}>
export type Unnamed_5_Query = { __typename?: 'QueryRoot' } & {
export type GetCheckoutQuery = { __typename?: 'QueryRoot' } & {
node?: Maybe<
| { __typename?: 'AppliedGiftCard' }
| { __typename?: 'Article' }
@ -5464,11 +5484,11 @@ export type GetCustomerQuery = { __typename?: 'QueryRoot' } & {
>
}
export type Unnamed_6_QueryVariables = Exact<{
export type GetPageQueryVariables = Exact<{
id: Scalars['ID']
}>
export type Unnamed_6_Query = { __typename?: 'QueryRoot' } & {
export type GetPageQuery = { __typename?: 'QueryRoot' } & {
node?: Maybe<
| ({ __typename?: 'AppliedGiftCard' } & Pick<AppliedGiftCard, 'id'>)
| ({ __typename?: 'Article' } & Pick<Article, 'id'>)

View File

@ -28,7 +28,7 @@ type ApiVersion {
handle: String!
"""
Whether the version is supported by Shopify.
Whether the version is actively supported by Shopify. Supported API versions are guaranteed to be stable. Unsupported API versions include unstable, release candidate, and end-of-life versions that are marked as unsupported. For more information, refer to [Versioning](https://shopify.dev/concepts/about-apis/versioning).
"""
supported: Boolean!
}
@ -769,6 +769,11 @@ type Checkout implements Node {
"""
taxesIncluded: Boolean!
"""
The sum of all the duties applied to the line items in the checkout.
"""
totalDuties: MoneyV2
"""
The sum of all the prices of all the items in the checkout, taxes and discounts included.
"""
@ -3306,6 +3311,11 @@ enum CountryCode {
Zimbabwe.
"""
ZW
"""
Unknown Region.
"""
ZZ
}
"""
@ -5178,6 +5188,11 @@ type ExternalVideo implements Node & Media {
"""
embeddedUrl: URL!
"""
The host of the external video.
"""
host: MediaHost!
"""
Globally unique identifier.
"""
@ -5803,6 +5818,21 @@ type MediaEdge {
node: Media!
}
"""
Host for a Media Resource.
"""
enum MediaHost {
"""
Host for YouTube embedded videos.
"""
YOUTUBE
"""
Host for Vimeo embedded videos.
"""
VIMEO
}
"""
Represents a Shopify hosted image.
"""
@ -6745,6 +6775,11 @@ type Order implements Node {
"""
currentSubtotalPrice: MoneyV2!
"""
The total cost of duties for the order, including refunds.
"""
currentTotalDuties: MoneyV2
"""
The total amount of the order, including duties, taxes and discounts, minus amounts for line items that have been removed.
"""
@ -6861,6 +6896,11 @@ type Order implements Node {
"""
orderNumber: Int!
"""
The total cost of duties charged at checkout.
"""
originalTotalDuties: MoneyV2
"""
The total price of the order before any applied edits.
"""

View File

@ -9,7 +9,9 @@ export type ShopifyCheckout = {
export type Cart = Core.Cart & {
lineItems: LineItem[]
url?: String
}
export interface LineItem extends Core.LineItem {
options?: any[]
}

View File

@ -27,12 +27,6 @@ export type CheckoutPayload =
| CheckoutQuery
const checkoutToCart = (checkoutPayload?: Maybe<CheckoutPayload>): Cart => {
if (!checkoutPayload) {
throw new CommerceError({
message: 'Missing checkout payload from response',
})
}
const checkout = checkoutPayload?.checkout
throwUserErrors(checkoutPayload?.checkoutUserErrors)

View File

@ -1,8 +1,8 @@
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
const checkoutCreateMutation = /* GraphQL */ `
mutation {
checkoutCreate(input: {}) {
mutation checkoutCreate($input: CheckoutCreateInput = {}) {
checkoutCreate(input: $input) {
checkoutUserErrors {
code
field

View File

@ -1,7 +1,10 @@
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
const checkoutLineItemAddMutation = /* GraphQL */ `
mutation($checkoutId: ID!, $lineItems: [CheckoutLineItemInput!]!) {
mutation checkoutLineItemAdd(
$checkoutId: ID!
$lineItems: [CheckoutLineItemInput!]!
) {
checkoutLineItemsAdd(checkoutId: $checkoutId, lineItems: $lineItems) {
checkoutUserErrors {
code

View File

@ -1,7 +1,7 @@
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
const checkoutLineItemRemoveMutation = /* GraphQL */ `
mutation($checkoutId: ID!, $lineItemIds: [ID!]!) {
mutation checkoutLineItemRemove($checkoutId: ID!, $lineItemIds: [ID!]!) {
checkoutLineItemsRemove(
checkoutId: $checkoutId
lineItemIds: $lineItemIds

View File

@ -1,7 +1,10 @@
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
const checkoutLineItemUpdateMutation = /* GraphQL */ `
mutation($checkoutId: ID!, $lineItems: [CheckoutLineItemUpdateInput!]!) {
mutation checkoutLineItemUpdate(
$checkoutId: ID!
$lineItems: [CheckoutLineItemUpdateInput!]!
) {
checkoutLineItemsUpdate(checkoutId: $checkoutId, lineItems: $lineItems) {
checkoutUserErrors {
code

View File

@ -75,8 +75,7 @@ const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
)
}
export function normalizeProduct(productNode: ShopifyProduct): Product {
const {
export function normalizeProduct({
id,
title: name,
vendor,
@ -87,10 +86,10 @@ export function normalizeProduct(productNode: ShopifyProduct): Product {
handle,
priceRange,
options,
metafields,
...rest
} = productNode
const product = {
}: ShopifyProduct): Product {
return {
id,
name,
vendor,
@ -108,13 +107,12 @@ export function normalizeProduct(productNode: ShopifyProduct): Product {
...(descriptionHtml && { descriptionHtml }),
...rest,
}
return product
}
export function normalizeCart(checkout: Checkout): Cart {
return {
id: checkout.id,
url: checkout.webUrl,
customerId: '',
email: '',
createdAt: checkout.createdAt,
@ -131,7 +129,7 @@ export function normalizeCart(checkout: Checkout): Cart {
}
function normalizeLineItem({
node: { id, title, variant, quantity, ...rest },
node: { id, title, variant, quantity },
}: CheckoutLineItemEdge): LineItem {
return {
id,
@ -144,7 +142,7 @@ function normalizeLineItem({
sku: variant?.sku ?? '',
name: variant?.title!,
image: {
url: variant?.image?.originalSrc ?? '/product-img-placeholder.svg',
url: variant?.image?.originalSrc || '/product-img-placeholder.svg',
},
requiresShipping: variant?.requiresShipping ?? false,
price: variant?.priceV2?.amount,

View File

@ -56,7 +56,7 @@ export const checkoutDetailsFragment = /* GraphQL */ `
`
const getCheckoutQuery = /* GraphQL */ `
query($checkoutId: ID!) {
query getCheckout($checkoutId: ID!) {
node(id: $checkoutId) {
...checkoutDetails
}

View File

@ -1,5 +1,5 @@
export const getPageQuery = /* GraphQL */ `
query($id: ID!) {
query getPage($id: ID!) {
node(id: $id) {
id
... on Page {