mirror of
https://github.com/vercel/commerce.git
synced 2025-05-16 14:36:59 +00:00
Cart API
This commit is contained in:
parent
d1d9e8c434
commit
5ceb134d33
@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema": {
|
||||
"https://${NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/2022-07/graphql.json": {
|
||||
"https://${NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/2023-01/graphql.json": {
|
||||
"headers": {
|
||||
"X-Shopify-Storefront-Access-Token": "${NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN}"
|
||||
}
|
||||
|
1244
packages/shopify/schema.d.ts
vendored
1244
packages/shopify/schema.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@ directive @accessRestricted(
|
||||
) on FIELD_DEFINITION | OBJECT
|
||||
|
||||
"""
|
||||
Contextualizes data based on the additional information provided by the directive. For example, you can use the `@inContext(country: CA)` directive to [query a product's price](https://shopify.dev/api/examples/international-pricing#query-product-prices) in a storefront within the context of Canada.
|
||||
Contextualizes data based on the additional information provided by the directive. For example, you can use the `@inContext(country: CA)` directive to [query a product's price](https://shopify.dev/custom-storefronts/internationalization/international-pricing) in a storefront within the context of Canada.
|
||||
"""
|
||||
directive @inContext(
|
||||
"""
|
||||
@ -58,22 +58,22 @@ type AppliedGiftCard implements Node {
|
||||
"""
|
||||
The amount that was taken from the gift card by applying it.
|
||||
"""
|
||||
amountUsed: Money! @deprecated(reason: "Use `amountUsedV2` instead.")
|
||||
amountUsed: MoneyV2!
|
||||
|
||||
"""
|
||||
The amount that was taken from the gift card by applying it.
|
||||
"""
|
||||
amountUsedV2: MoneyV2!
|
||||
amountUsedV2: MoneyV2! @deprecated(reason: "Use `amountUsed` instead.")
|
||||
|
||||
"""
|
||||
The amount left on the gift card.
|
||||
"""
|
||||
balance: Money! @deprecated(reason: "Use `balanceV2` instead.")
|
||||
balance: MoneyV2!
|
||||
|
||||
"""
|
||||
The amount left on the gift card.
|
||||
"""
|
||||
balanceV2: MoneyV2!
|
||||
balanceV2: MoneyV2! @deprecated(reason: "Use `balance` instead.")
|
||||
|
||||
"""
|
||||
A globally-unique identifier.
|
||||
@ -560,6 +560,65 @@ enum BlogSortKeys {
|
||||
TITLE
|
||||
}
|
||||
|
||||
"The store's branding configuration.\n"
|
||||
type Brand {
|
||||
"""
|
||||
The colors of the store's brand.
|
||||
"""
|
||||
colors: BrandColors!
|
||||
|
||||
"""
|
||||
The store's cover image.
|
||||
"""
|
||||
coverImage: MediaImage
|
||||
|
||||
"""
|
||||
The store's default logo.
|
||||
"""
|
||||
logo: MediaImage
|
||||
|
||||
"""
|
||||
The store's short description.
|
||||
"""
|
||||
shortDescription: String
|
||||
|
||||
"""
|
||||
The store's slogan.
|
||||
"""
|
||||
slogan: String
|
||||
|
||||
"""
|
||||
The store's preferred logo for square UI elements.
|
||||
"""
|
||||
squareLogo: MediaImage
|
||||
}
|
||||
|
||||
"A group of related colors for the shop's brand.\n"
|
||||
type BrandColorGroup {
|
||||
"""
|
||||
The background color.
|
||||
"""
|
||||
background: Color
|
||||
|
||||
"""
|
||||
The foreground color.
|
||||
"""
|
||||
foreground: Color
|
||||
}
|
||||
|
||||
"The colors of the shop's brand.\n"
|
||||
type BrandColors {
|
||||
"""
|
||||
The shop's primary brand colors.
|
||||
"""
|
||||
primary: [BrandColorGroup!]!
|
||||
|
||||
"""
|
||||
The shop's secondary brand colors.
|
||||
"""
|
||||
secondary: [BrandColorGroup!]!
|
||||
}
|
||||
|
||||
"""
|
||||
Card brand, such as Visa or Mastercard, which can be used for payments.
|
||||
"""
|
||||
@ -595,9 +654,7 @@ enum CardBrand {
|
||||
VISA
|
||||
}
|
||||
|
||||
"""
|
||||
A cart represents the merchandise that a buyer intends to purchase, and the estimated cost associated with the cart. To learn how to interact with a cart during a customer's session, refer to [Manage a cart with the Storefront API](https://shopify.dev/api/examples/cart).
|
||||
"""
|
||||
"A cart represents the merchandise that a buyer intends to purchase,\nand the estimated cost associated with the cart. Learn how to\n[interact with a cart](https://shopify.dev/custom-storefronts/internationalization/international-pricing)\nduring a customer's session.\n"
|
||||
type Cart implements Node {
|
||||
"""
|
||||
An attribute associated with the cart.
|
||||
@ -625,7 +682,7 @@ type Cart implements Node {
|
||||
checkoutUrl: URL!
|
||||
|
||||
"""
|
||||
The estimated costs that the buyer will pay at checkout. The costs are subject to change and changes will be reflected at checkout. The `cost` field uses the `buyerIdentity` field to determine [international pricing](https://shopify.dev/api/examples/international-pricing#create-a-cart).
|
||||
The estimated costs that the buyer will pay at checkout. The costs are subject to change and changes will be reflected at checkout. The `cost` field uses the `buyerIdentity` field to determine [international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing).
|
||||
"""
|
||||
cost: CartCost!
|
||||
|
||||
@ -634,9 +691,7 @@ type Cart implements Node {
|
||||
"""
|
||||
createdAt: DateTime!
|
||||
|
||||
"""
|
||||
The delivery groups available for the cart, based on the default address of the logged-in customer.
|
||||
"""
|
||||
"The delivery groups available for the cart, based on the buyer identity default\ndelivery address preference or the default address of the logged-in customer.\n"
|
||||
deliveryGroups(
|
||||
"""
|
||||
Returns the elements that come after the specified cursor.
|
||||
@ -672,9 +727,7 @@ type Cart implements Node {
|
||||
"The case-insensitive discount codes that the customer added at checkout.\n"
|
||||
discountCodes: [CartDiscountCode!]!
|
||||
|
||||
"""
|
||||
The estimated costs that the buyer will pay at checkout. The estimated costs are subject to change and changes will be reflected at checkout. The `estimatedCost` field uses the `buyerIdentity` field to determine [international pricing](https://shopify.dev/api/examples/international-pricing#create-a-cart).
|
||||
"""
|
||||
"The estimated costs that the buyer will pay at checkout.\nThe estimated costs are subject to change and changes will be reflected at checkout.\nThe `estimatedCost` field uses the `buyerIdentity` field to determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing).\n"
|
||||
estimatedCost: CartEstimatedCost! @deprecated(reason: "Use `cost` instead.")
|
||||
|
||||
"""
|
||||
@ -772,6 +825,9 @@ type CartBuyerIdentity {
|
||||
"""
|
||||
customer: Customer
|
||||
|
||||
"An ordered set of delivery addresses tied to the buyer that is interacting with the cart.\nThe rank of the preferences is determined by the order of the addresses in the array. Preferences\ncan be used to populate relevant fields in the checkout flow.\n"
|
||||
deliveryAddressPreferences: [DeliveryAddress!]!
|
||||
|
||||
"""
|
||||
The email address of the buyer that is interacting with the cart.
|
||||
"""
|
||||
@ -783,7 +839,7 @@ type CartBuyerIdentity {
|
||||
phone: String
|
||||
}
|
||||
|
||||
"Specifies the input fields to update the buyer information associated with a cart.\nBuyer identity is used to determine\n[international pricing](https://shopify.dev/api/examples/international-pricing#create-a-checkout)\nand should match the customer's shipping address.\n"
|
||||
"Specifies the input fields to update the buyer information associated with a cart.\nBuyer identity is used to determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing)\nand should match the customer's shipping address.\n"
|
||||
input CartBuyerIdentityInput {
|
||||
"""
|
||||
The country where the buyer is located.
|
||||
@ -795,6 +851,9 @@ input CartBuyerIdentityInput {
|
||||
"""
|
||||
customerAccessToken: String
|
||||
|
||||
"An ordered set of delivery addresses tied to the buyer that is interacting with the cart.\nThe rank of the preferences is determined by the order of the addresses in the array. Preferences\ncan be used to populate relevant fields in the checkout flow.\n"
|
||||
deliveryAddressPreferences: [DeliveryAddressInput!]
|
||||
|
||||
"""
|
||||
The email address of the buyer that is interacting with the cart.
|
||||
"""
|
||||
@ -836,7 +895,7 @@ type CartCodeDiscountAllocation implements CartDiscountAllocation {
|
||||
discountedAmount: MoneyV2!
|
||||
}
|
||||
|
||||
"The costs that the buyer will pay at checkout.\nIt uses [`CartBuyerIdentity`](https://shopify.dev/api/storefront/reference/cart/cartbuyeridentity) to determine\n[international pricing](https://shopify.dev/api/examples/international-pricing#create-a-cart).\n"
|
||||
"The costs that the buyer will pay at checkout.\nThe cart cost uses [`CartBuyerIdentity`](https://shopify.dev/api/storefront/reference/cart/cartbuyeridentity) to determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing).\n"
|
||||
type CartCost {
|
||||
"""
|
||||
The estimated amount, before taxes and discounts, for the customer to pay at checkout. The checkout charge amount doesn't include any deferred payments that'll be paid at a later date. If the cart has no deferred payments, then the checkout charge amount is equivalent to `subtotalAmount`.
|
||||
@ -962,6 +1021,11 @@ type CartDeliveryGroup {
|
||||
The ID for the delivery group.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
The selected delivery option for the delivery group.
|
||||
"""
|
||||
selectedDeliveryOption: CartDeliveryOption
|
||||
}
|
||||
|
||||
"An auto-generated type for paginating through multiple CartDeliveryGroups.\n"
|
||||
@ -1019,6 +1083,11 @@ type CartDeliveryOption {
|
||||
"""
|
||||
estimatedCost: MoneyV2!
|
||||
|
||||
"""
|
||||
The unique identifier of the delivery option.
|
||||
"""
|
||||
handle: String!
|
||||
|
||||
"""
|
||||
The title of the delivery option.
|
||||
"""
|
||||
@ -1095,7 +1164,7 @@ enum CartErrorCode {
|
||||
MISSING_NOTE
|
||||
}
|
||||
|
||||
"The estimated costs that the buyer will pay at checkout.\nIt uses [`CartBuyerIdentity`](https://shopify.dev/api/storefront/reference/cart/cartbuyeridentity) to determine\n[international pricing](https://shopify.dev/api/examples/international-pricing#create-a-cart).\n"
|
||||
"The estimated costs that the buyer will pay at checkout.\nThe estimated cost uses\n[`CartBuyerIdentity`](https://shopify.dev/api/storefront/reference/cart/cartbuyeridentity)\nto determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing).\n"
|
||||
type CartEstimatedCost {
|
||||
"""
|
||||
The estimated amount, before taxes and discounts, for the customer to pay at checkout. The checkout charge amount doesn't include any deferred payments that'll be paid at a later date. If the cart has no deferred payments, then the checkout charge amount is equivalent to`subtotal_amount`.
|
||||
@ -1132,9 +1201,7 @@ input CartInput {
|
||||
"""
|
||||
attributes: [AttributeInput!]
|
||||
|
||||
"""
|
||||
The customer associated with the cart. Used to determine [international pricing](https://shopify.dev/api/examples/international-pricing#create-a-checkout). Buyer identity should match the customer's shipping address.
|
||||
"""
|
||||
"The customer associated with the cart. Used to determine [international pricing]\n(https://shopify.dev/custom-storefronts/internationalization/international-pricing).\nBuyer identity should match the customer's shipping address.\n"
|
||||
buyerIdentity: CartBuyerIdentityInput
|
||||
|
||||
"The case-insensitive discount codes that the customer added at checkout.\n"
|
||||
@ -1403,6 +1470,34 @@ type CartNoteUpdatePayload {
|
||||
userErrors: [CartUserError!]!
|
||||
}
|
||||
|
||||
"The input fields for updating the selected delivery options for a delivery group.\n"
|
||||
input CartSelectedDeliveryOptionInput {
|
||||
"""
|
||||
The ID of the cart delivery group.
|
||||
"""
|
||||
deliveryGroupId: ID!
|
||||
|
||||
"""
|
||||
The handle of the selected delivery option.
|
||||
"""
|
||||
deliveryOptionHandle: String!
|
||||
}
|
||||
|
||||
"""
|
||||
Return type for `cartSelectedDeliveryOptionsUpdate` mutation.
|
||||
"""
|
||||
type CartSelectedDeliveryOptionsUpdatePayload {
|
||||
"""
|
||||
The updated cart.
|
||||
"""
|
||||
cart: Cart
|
||||
|
||||
"""
|
||||
The list of errors that occurred from executing the mutation.
|
||||
"""
|
||||
userErrors: [CartUserError!]!
|
||||
}
|
||||
|
||||
"""
|
||||
Represents an error that happens during execution of a cart mutation.
|
||||
"""
|
||||
@ -1551,14 +1646,14 @@ type Checkout implements Node {
|
||||
orderStatusUrl: URL
|
||||
|
||||
"""
|
||||
The amount left to be paid. This is equal to the cost of the line items, taxes and shipping minus discounts and gift cards.
|
||||
The amount left to be paid. This is equal to the cost of the line items, taxes, and shipping, minus discounts and gift cards.
|
||||
"""
|
||||
paymentDue: Money! @deprecated(reason: "Use `paymentDueV2` instead.")
|
||||
paymentDue: MoneyV2!
|
||||
|
||||
"""
|
||||
The amount left to be paid. This is equal to the cost of the line items, duties, taxes, and shipping, minus discounts and gift cards.
|
||||
"""
|
||||
paymentDueV2: MoneyV2!
|
||||
paymentDueV2: MoneyV2! @deprecated(reason: "Use `paymentDue` instead.")
|
||||
|
||||
"Whether or not the Checkout is ready and can be completed. Checkouts may\nhave asynchronous operations that can take time to finish. If you want\nto complete a checkout or ensure all the fields are populated and up to\ndate, polling is required until the value is true.\n"
|
||||
ready: Boolean!
|
||||
@ -1582,14 +1677,14 @@ type Checkout implements Node {
|
||||
shippingLine: ShippingRate
|
||||
|
||||
"""
|
||||
Price of the checkout before shipping and taxes.
|
||||
The price at checkout before shipping and taxes.
|
||||
"""
|
||||
subtotalPrice: Money! @deprecated(reason: "Use `subtotalPriceV2` instead.")
|
||||
subtotalPrice: MoneyV2!
|
||||
|
||||
"""
|
||||
The price at checkout before duties, shipping, and taxes.
|
||||
"""
|
||||
subtotalPriceV2: MoneyV2!
|
||||
subtotalPriceV2: MoneyV2! @deprecated(reason: "Use `subtotalPrice` instead.")
|
||||
|
||||
"""
|
||||
Whether the checkout is tax exempt.
|
||||
@ -1607,24 +1702,24 @@ type Checkout implements Node {
|
||||
totalDuties: MoneyV2
|
||||
|
||||
"""
|
||||
The sum of all the prices of all the items in the checkout, taxes and discounts included.
|
||||
The sum of all the prices of all the items in the checkout, including taxes and duties.
|
||||
"""
|
||||
totalPrice: Money! @deprecated(reason: "Use `totalPriceV2` instead.")
|
||||
totalPrice: MoneyV2!
|
||||
|
||||
"""
|
||||
The sum of all the prices of all the items in the checkout, including duties, taxes, and discounts.
|
||||
The sum of all the prices of all the items in the checkout, including taxes and duties.
|
||||
"""
|
||||
totalPriceV2: MoneyV2!
|
||||
totalPriceV2: MoneyV2! @deprecated(reason: "Use `totalPrice` instead.")
|
||||
|
||||
"""
|
||||
The sum of all the taxes applied to the line items and shipping lines in the checkout.
|
||||
"""
|
||||
totalTax: Money! @deprecated(reason: "Use `totalTaxV2` instead.")
|
||||
totalTax: MoneyV2!
|
||||
|
||||
"""
|
||||
The sum of all the taxes applied to the line items and shipping lines in the checkout.
|
||||
"""
|
||||
totalTaxV2: MoneyV2!
|
||||
totalTaxV2: MoneyV2! @deprecated(reason: "Use `totalTax` instead.")
|
||||
|
||||
"""
|
||||
The date and time when the checkout was last updated.
|
||||
@ -1975,6 +2070,11 @@ enum CheckoutErrorCode {
|
||||
"""
|
||||
DISCOUNT_ALREADY_APPLIED
|
||||
|
||||
"""
|
||||
Discount code isn't working right now. Please contact us for help.
|
||||
"""
|
||||
DISCOUNT_CODE_APPLICATION_FAILED
|
||||
|
||||
"""
|
||||
Discount disabled.
|
||||
"""
|
||||
@ -2634,6 +2734,9 @@ enum CollectionSortKeys {
|
||||
UPDATED_AT
|
||||
}
|
||||
|
||||
"A string containing a hexadecimal representation of a color.\n\nFor example, \"#6A8D48\".\n"
|
||||
scalar Color
|
||||
|
||||
"""
|
||||
A comment on an article.
|
||||
"""
|
||||
@ -5010,6 +5113,11 @@ type Customer implements HasMetafields {
|
||||
identifiers: [HasMetafieldsIdentifier!]!
|
||||
): [Metafield]!
|
||||
|
||||
"""
|
||||
The number of orders that the customer has made at the store in their lifetime.
|
||||
"""
|
||||
numberOfOrders: UnsignedInt64!
|
||||
|
||||
"""
|
||||
The orders associated with the customer.
|
||||
"""
|
||||
@ -5608,6 +5716,19 @@ scalar DateTime
|
||||
"A signed decimal number, which supports arbitrary precision and is serialized as a string.\n\nExample values: `\"29.99\"`, `\"29.999\"`.\n"
|
||||
scalar Decimal
|
||||
|
||||
"""
|
||||
A delivery address of the buyer that is interacting with the cart.
|
||||
"""
|
||||
union DeliveryAddress = MailingAddress
|
||||
|
||||
"The input fields for delivery address preferences.\n"
|
||||
input DeliveryAddressInput {
|
||||
"""
|
||||
A delivery address preference of a buyer that is interacting with the cart.
|
||||
"""
|
||||
deliveryAddress: MailingAddressInput
|
||||
}
|
||||
|
||||
"""
|
||||
List of different delivery method types.
|
||||
"""
|
||||
@ -5924,7 +6045,7 @@ type Filter {
|
||||
values: [FilterValue!]!
|
||||
}
|
||||
|
||||
"The type of data that the filter group represents.\n\nFor more information, refer to [Filter products in a collection with the Storefront API]\n(https://shopify.dev/api/examples/filter-products).\n"
|
||||
"The type of data that the filter group represents.\n\nFor more information, refer to [Filter products in a collection with the Storefront API]\n(https://shopify.dev/custom-storefronts/products-collections/filter-products).\n"
|
||||
enum FilterType {
|
||||
"""
|
||||
A boolean value.
|
||||
@ -6124,7 +6245,7 @@ input GeoCoordinateInput {
|
||||
longitude: Float!
|
||||
}
|
||||
|
||||
"A string containing HTML code. Refer to the [HTML spec](https://html.spec.whatwg.org/#elements-3) for a\ncomplete list of HTML elements.\n\nExample value: `\"<p>Grey cotton knit sweater.</p>\"`.\n"
|
||||
"A string containing HTML code. Refer to the [HTML spec](https://html.spec.whatwg.org/#elements-3) for a\ncomplete list of HTML elements.\n\nExample value: `\"<p>Grey cotton knit sweater.</p>\"`\n"
|
||||
scalar HTML
|
||||
|
||||
"""
|
||||
@ -7673,6 +7794,31 @@ type Metafield implements Node {
|
||||
"""
|
||||
reference: MetafieldReference
|
||||
|
||||
"""
|
||||
A list of reference objects if the metafield's type is a resource reference list.
|
||||
"""
|
||||
references(
|
||||
"""
|
||||
Returns the elements that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns up to the first `n` elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns up to the last `n` elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
): MetafieldReferenceConnection
|
||||
|
||||
"The type name of the metafield.\nSee the list of [supported types](https://shopify.dev/apps/metafields/definitions/types).\n"
|
||||
type: String!
|
||||
|
||||
@ -7721,13 +7867,178 @@ union MetafieldParentResource =
|
||||
|
||||
"Returns the resource which is being referred to by a metafield.\n"
|
||||
union MetafieldReference =
|
||||
GenericFile
|
||||
Collection
|
||||
| GenericFile
|
||||
| MediaImage
|
||||
| Metaobject
|
||||
| Page
|
||||
| Product
|
||||
| ProductVariant
|
||||
| Video
|
||||
|
||||
"An auto-generated type for paginating through multiple MetafieldReferences.\n"
|
||||
type MetafieldReferenceConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [MetafieldReferenceEdge!]!
|
||||
|
||||
"""
|
||||
A list of the nodes contained in MetafieldReferenceEdge.
|
||||
"""
|
||||
nodes: [MetafieldReference!]!
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
"An auto-generated type which holds one MetafieldReference and a cursor during pagination.\n"
|
||||
type MetafieldReferenceEdge {
|
||||
"""
|
||||
A cursor for use in pagination.
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of MetafieldReferenceEdge.
|
||||
"""
|
||||
node: MetafieldReference!
|
||||
}
|
||||
|
||||
"""
|
||||
An instance of a user-defined model based on a MetaobjectDefinition.
|
||||
"""
|
||||
type Metaobject implements Node {
|
||||
"""
|
||||
Accesses a field of the object by key.
|
||||
"""
|
||||
field(
|
||||
"""
|
||||
The key of the field.
|
||||
"""
|
||||
key: String!
|
||||
): MetaobjectField
|
||||
|
||||
"All object fields with defined values.\nOmitted object keys can be assumed null, and no guarantees are made about field order.\n"
|
||||
fields: [MetaobjectField!]!
|
||||
|
||||
"""
|
||||
The unique handle of the metaobject. Useful as a custom ID.
|
||||
"""
|
||||
handle: String!
|
||||
|
||||
"""
|
||||
A globally-unique identifier.
|
||||
"""
|
||||
id: ID!
|
||||
|
||||
"""
|
||||
The type of the metaobject. Defines the namespace of its associated metafields.
|
||||
"""
|
||||
type: String!
|
||||
|
||||
"""
|
||||
The date and time when the metaobject was last updated.
|
||||
"""
|
||||
updatedAt: DateTime!
|
||||
}
|
||||
|
||||
"An auto-generated type for paginating through multiple Metaobjects.\n"
|
||||
type MetaobjectConnection {
|
||||
"""
|
||||
A list of edges.
|
||||
"""
|
||||
edges: [MetaobjectEdge!]!
|
||||
|
||||
"""
|
||||
A list of the nodes contained in MetaobjectEdge.
|
||||
"""
|
||||
nodes: [Metaobject!]!
|
||||
|
||||
"""
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
"An auto-generated type which holds one Metaobject and a cursor during pagination.\n"
|
||||
type MetaobjectEdge {
|
||||
"""
|
||||
A cursor for use in pagination.
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
The item at the end of MetaobjectEdge.
|
||||
"""
|
||||
node: Metaobject!
|
||||
}
|
||||
|
||||
"""
|
||||
Provides the value of a Metaobject field.
|
||||
"""
|
||||
type MetaobjectField {
|
||||
"""
|
||||
The field key.
|
||||
"""
|
||||
key: String!
|
||||
|
||||
"""
|
||||
A referenced object if the field type is a resource reference.
|
||||
"""
|
||||
reference: MetafieldReference
|
||||
|
||||
"""
|
||||
A list of referenced objects if the field type is a resource reference list.
|
||||
"""
|
||||
references(
|
||||
"""
|
||||
Returns the elements that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns up to the first `n` elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns up to the last `n` elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
): MetafieldReferenceConnection
|
||||
|
||||
"The type name of the field.\nSee the list of [supported types](https://shopify.dev/apps/metafields/definitions/types).\n"
|
||||
type: String!
|
||||
|
||||
"""
|
||||
The field value.
|
||||
"""
|
||||
value: String
|
||||
}
|
||||
|
||||
"""
|
||||
The input fields used to retrieve a metaobject by handle.
|
||||
"""
|
||||
input MetaobjectHandleInput {
|
||||
"""
|
||||
The handle of the metaobject.
|
||||
"""
|
||||
handle: String!
|
||||
|
||||
"""
|
||||
The type of the metaobject.
|
||||
"""
|
||||
type: String!
|
||||
}
|
||||
|
||||
"""
|
||||
Represents a Shopify hosted 3D model.
|
||||
"""
|
||||
@ -7783,11 +8094,6 @@ type Model3dSource {
|
||||
url: String!
|
||||
}
|
||||
|
||||
"""
|
||||
A monetary value string without a currency symbol or code. Example value: `"100.57"`.
|
||||
"""
|
||||
scalar Money
|
||||
|
||||
"""
|
||||
Specifies the fields for a monetary value with currency.
|
||||
"""
|
||||
@ -7835,11 +8141,9 @@ type Mutation {
|
||||
cartId: ID!
|
||||
): CartAttributesUpdatePayload
|
||||
|
||||
"Updates customer information associated with a cart.\nBuyer identity is used to determine\n[international pricing](https://shopify.dev/api/examples/international-pricing#create-a-checkout)\nand should match the customer's shipping address.\n"
|
||||
"Updates customer information associated with a cart.\nBuyer identity is used to determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing)\nand should match the customer's shipping address.\n"
|
||||
cartBuyerIdentityUpdate(
|
||||
"""
|
||||
The customer associated with the cart. Used to determine [international pricing](https://shopify.dev/api/examples/international-pricing#create-a-checkout). Buyer identity should match the customer's shipping address.
|
||||
"""
|
||||
"The customer associated with the cart. Used to determine\n[international pricing](https://shopify.dev/custom-storefronts/internationalization/international-pricing).\nBuyer identity should match the customer's shipping address.\n"
|
||||
buyerIdentity: CartBuyerIdentityInput!
|
||||
|
||||
"""
|
||||
@ -7931,6 +8235,21 @@ type Mutation {
|
||||
note: String
|
||||
): CartNoteUpdatePayload
|
||||
|
||||
"""
|
||||
Update the selected delivery options for a delivery group.
|
||||
"""
|
||||
cartSelectedDeliveryOptionsUpdate(
|
||||
"""
|
||||
The ID of the cart.
|
||||
"""
|
||||
cartId: ID!
|
||||
|
||||
"""
|
||||
The selected delivery options.
|
||||
"""
|
||||
selectedDeliveryOptions: [CartSelectedDeliveryOptionInput!]!
|
||||
): CartSelectedDeliveryOptionsUpdatePayload
|
||||
|
||||
"""
|
||||
Updates the attributes of a checkout if `allowPartialAddresses` is `true`.
|
||||
"""
|
||||
@ -8325,7 +8644,7 @@ type Mutation {
|
||||
customerAccessToken: String!
|
||||
): CustomerDefaultAddressUpdatePayload
|
||||
|
||||
"\"Sends a reset password email to the customer. The reset password email contains a reset password URL and token that you can pass to the [`customerResetByUrl`](https://shopify.dev/api/storefront/latest/mutations/customerResetByUrl) or [`customerReset`](https://shopify.dev/api/storefront/latest/mutations/customerReset) mutation to reset the customer password.\"\n"
|
||||
"Sends a reset password email to the customer. The reset password\nemail contains a reset password URL and token that you can pass to\nthe [`customerResetByUrl`](https://shopify.dev/api/storefront/latest/mutations/customerResetByUrl) or\n[`customerReset`](https://shopify.dev/api/storefront/latest/mutations/customerReset) mutation to reset the\ncustomer password.\n\nThis mutation is throttled by IP. With authenticated access,\nyou can provide a [`Shopify-Storefront-Buyer-IP`](https://shopify.dev/api/usage/authentication#optional-ip-header) instead of the request IP.\n\nMake sure that the value provided to `Shopify-Storefront-Buyer-IP` is trusted. Unthrottled access to this\nmutation presents a security risk.\n"
|
||||
customerRecover(
|
||||
"""
|
||||
The email address of the customer to recover.
|
||||
@ -8432,6 +8751,11 @@ type Order implements HasMetafields & Node {
|
||||
"""
|
||||
currentTotalTax: MoneyV2!
|
||||
|
||||
"""
|
||||
A list of the custom attributes added to the order.
|
||||
"""
|
||||
customAttributes: [Attribute!]!
|
||||
|
||||
"""
|
||||
The locale code in which this specific order happened.
|
||||
"""
|
||||
@ -8592,12 +8916,12 @@ type Order implements HasMetafields & Node {
|
||||
"""
|
||||
Price of the order before shipping and taxes.
|
||||
"""
|
||||
subtotalPrice: Money @deprecated(reason: "Use `subtotalPriceV2` instead.")
|
||||
subtotalPrice: MoneyV2
|
||||
|
||||
"""
|
||||
Price of the order before duties, shipping and taxes.
|
||||
"""
|
||||
subtotalPriceV2: MoneyV2
|
||||
subtotalPriceV2: MoneyV2 @deprecated(reason: "Use `subtotalPrice` instead.")
|
||||
|
||||
"""
|
||||
List of the order’s successful fulfillments.
|
||||
@ -8610,45 +8934,45 @@ type Order implements HasMetafields & Node {
|
||||
): [Fulfillment!]
|
||||
|
||||
"""
|
||||
The sum of all the prices of all the items in the order, taxes and discounts included (must be positive).
|
||||
The sum of all the prices of all the items in the order, duties, taxes and discounts included (must be positive).
|
||||
"""
|
||||
totalPrice: Money! @deprecated(reason: "Use `totalPriceV2` instead.")
|
||||
totalPrice: MoneyV2!
|
||||
|
||||
"""
|
||||
The sum of all the prices of all the items in the order, duties, taxes and discounts included (must be positive).
|
||||
"""
|
||||
totalPriceV2: MoneyV2!
|
||||
totalPriceV2: MoneyV2! @deprecated(reason: "Use `totalPrice` instead.")
|
||||
|
||||
"""
|
||||
The total amount that has been refunded.
|
||||
"""
|
||||
totalRefunded: Money! @deprecated(reason: "Use `totalRefundedV2` instead.")
|
||||
totalRefunded: MoneyV2!
|
||||
|
||||
"""
|
||||
The total amount that has been refunded.
|
||||
"""
|
||||
totalRefundedV2: MoneyV2!
|
||||
totalRefundedV2: MoneyV2! @deprecated(reason: "Use `totalRefunded` instead.")
|
||||
|
||||
"""
|
||||
The total cost of shipping.
|
||||
"""
|
||||
totalShippingPrice: Money!
|
||||
@deprecated(reason: "Use `totalShippingPriceV2` instead.")
|
||||
totalShippingPrice: MoneyV2!
|
||||
|
||||
"""
|
||||
The total cost of shipping.
|
||||
"""
|
||||
totalShippingPriceV2: MoneyV2!
|
||||
@deprecated(reason: "Use `totalShippingPrice` instead.")
|
||||
|
||||
"""
|
||||
The total cost of taxes.
|
||||
"""
|
||||
totalTax: Money @deprecated(reason: "Use `totalTaxV2` instead.")
|
||||
totalTax: MoneyV2
|
||||
|
||||
"""
|
||||
The total cost of taxes.
|
||||
"""
|
||||
totalTaxV2: MoneyV2
|
||||
totalTaxV2: MoneyV2 @deprecated(reason: "Use `totalTax` instead.")
|
||||
}
|
||||
|
||||
"""
|
||||
@ -8697,6 +9021,11 @@ type OrderConnection {
|
||||
Information to aid in pagination.
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
|
||||
"""
|
||||
The total count of Orders.
|
||||
"""
|
||||
totalCount: UnsignedInt64!
|
||||
}
|
||||
|
||||
"An auto-generated type which holds one Order and a cursor during pagination.\n"
|
||||
@ -9058,12 +9387,12 @@ type Payment implements Node {
|
||||
"""
|
||||
The amount of the payment.
|
||||
"""
|
||||
amount: Money! @deprecated(reason: "Use `amountV2` instead.")
|
||||
amount: MoneyV2!
|
||||
|
||||
"""
|
||||
The amount of the payment.
|
||||
"""
|
||||
amountV2: MoneyV2!
|
||||
amountV2: MoneyV2! @deprecated(reason: "Use `amount` instead.")
|
||||
|
||||
"""
|
||||
The billing address for the payment.
|
||||
@ -9325,6 +9654,11 @@ type Product implements HasMetafields & Node & OnlineStorePublishable {
|
||||
sortKey: ProductImageSortKeys = POSITION
|
||||
): ImageConnection!
|
||||
|
||||
"""
|
||||
Whether the product is a gift card.
|
||||
"""
|
||||
isGiftCard: Boolean!
|
||||
|
||||
"""
|
||||
The media associated with the product.
|
||||
"""
|
||||
@ -9626,6 +9960,11 @@ input ProductFilter {
|
||||
"""
|
||||
productVendor: String
|
||||
|
||||
"""
|
||||
A product tag to filter on.
|
||||
"""
|
||||
tag: String
|
||||
|
||||
"""
|
||||
A variant metafield to filter on.
|
||||
"""
|
||||
@ -9776,12 +10115,12 @@ type ProductVariant implements HasMetafields & Node {
|
||||
"""
|
||||
The compare at price of the variant. This can be used to mark a variant as on sale, when `compareAtPrice` is higher than `price`.
|
||||
"""
|
||||
compareAtPrice: Money @deprecated(reason: "Use `compareAtPriceV2` instead.")
|
||||
compareAtPrice: MoneyV2
|
||||
|
||||
"""
|
||||
The compare at price of the variant. This can be used to mark a variant as on sale, when `compareAtPriceV2` is higher than `priceV2`.
|
||||
"""
|
||||
compareAtPriceV2: MoneyV2
|
||||
compareAtPriceV2: MoneyV2 @deprecated(reason: "Use `compareAtPrice` instead.")
|
||||
|
||||
"""
|
||||
Whether a product is out of stock but still available for purchase (used for backorders).
|
||||
@ -9822,12 +10161,12 @@ type ProductVariant implements HasMetafields & Node {
|
||||
"""
|
||||
The product variant’s price.
|
||||
"""
|
||||
price: Money! @deprecated(reason: "Use `priceV2` instead.")
|
||||
price: MoneyV2!
|
||||
|
||||
"""
|
||||
The product variant’s price.
|
||||
"""
|
||||
priceV2: MoneyV2!
|
||||
priceV2: MoneyV2! @deprecated(reason: "Use `price` instead.")
|
||||
|
||||
"""
|
||||
The product object that the product variant belongs to.
|
||||
@ -9908,6 +10247,11 @@ type ProductVariant implements HasMetafields & Node {
|
||||
"""
|
||||
last: Int
|
||||
|
||||
"""
|
||||
Used to sort results based on proximity to the provided location.
|
||||
"""
|
||||
near: GeoCoordinateInput
|
||||
|
||||
"""
|
||||
Reverse the order of the underlying list.
|
||||
"""
|
||||
@ -10104,9 +10448,7 @@ type QueryRoot {
|
||||
sortKey: BlogSortKeys = ID
|
||||
): BlogConnection!
|
||||
|
||||
"""
|
||||
Retrieve a cart by its ID. For more information, refer to [Manage a cart with the Storefront API](https://shopify.dev/api/examples/cart).
|
||||
"""
|
||||
"Retrieve a cart by its ID. For more information, refer to\n[Manage a cart with the Storefront API](https://shopify.dev/custom-storefronts/cart/manage).\n"
|
||||
cart(
|
||||
"""
|
||||
The ID of the cart.
|
||||
@ -10240,6 +10582,61 @@ type QueryRoot {
|
||||
handle: String!
|
||||
): Menu
|
||||
|
||||
"""
|
||||
Fetch a specific Metaobject by one of its unique identifiers.
|
||||
"""
|
||||
metaobject(
|
||||
"""
|
||||
The handle and type of the metaobject.
|
||||
"""
|
||||
handle: MetaobjectHandleInput
|
||||
|
||||
"""
|
||||
The ID of the metaobject.
|
||||
"""
|
||||
id: ID
|
||||
): Metaobject
|
||||
|
||||
"""
|
||||
All active metaobjects for the shop.
|
||||
"""
|
||||
metaobjects(
|
||||
"""
|
||||
Returns the elements that come after the specified cursor.
|
||||
"""
|
||||
after: String
|
||||
|
||||
"""
|
||||
Returns the elements that come before the specified cursor.
|
||||
"""
|
||||
before: String
|
||||
|
||||
"""
|
||||
Returns up to the first `n` elements from the list.
|
||||
"""
|
||||
first: Int
|
||||
|
||||
"""
|
||||
Returns up to the last `n` elements from the list.
|
||||
"""
|
||||
last: Int
|
||||
|
||||
"""
|
||||
Reverse the order of the underlying list.
|
||||
"""
|
||||
reverse: Boolean = false
|
||||
|
||||
"""
|
||||
The key of a field to sort with. Supports "id" and "updated_at".
|
||||
"""
|
||||
sortKey: String
|
||||
|
||||
"""
|
||||
The type of metaobject to retrieve.
|
||||
"""
|
||||
type: String!
|
||||
): MetaobjectConnection!
|
||||
|
||||
"""
|
||||
Returns a specific node by ID.
|
||||
"""
|
||||
@ -10446,6 +10843,9 @@ type QueryRoot {
|
||||
"""
|
||||
last: Int
|
||||
|
||||
"Supported filter parameters:\n - `created_at`\n - `path`\n - `target`\n\nSee the detailed [search syntax](https://shopify.dev/api/usage/search-syntax)\nfor more information about using filters.\n"
|
||||
query: String
|
||||
|
||||
"""
|
||||
Reverse the order of the underlying list.
|
||||
"""
|
||||
@ -10901,12 +11301,12 @@ type ShippingRate {
|
||||
"""
|
||||
Price of this shipping rate.
|
||||
"""
|
||||
price: Money! @deprecated(reason: "Use `priceV2` instead.")
|
||||
price: MoneyV2!
|
||||
|
||||
"""
|
||||
Price of this shipping rate.
|
||||
"""
|
||||
priceV2: MoneyV2!
|
||||
priceV2: MoneyV2! @deprecated(reason: "Use `price` instead.")
|
||||
|
||||
"""
|
||||
Title of this shipping rate.
|
||||
@ -10918,6 +11318,11 @@ type ShippingRate {
|
||||
Shop represents a collection of the general settings and information about the shop.
|
||||
"""
|
||||
type Shop implements HasMetafields & Node {
|
||||
"""
|
||||
The shop's branding configuration.
|
||||
"""
|
||||
brand: Brand
|
||||
|
||||
"""
|
||||
A description of the shop.
|
||||
"""
|
||||
@ -11180,12 +11585,12 @@ type Transaction {
|
||||
"""
|
||||
The amount of money that the transaction was for.
|
||||
"""
|
||||
amount: Money! @deprecated(reason: "Use `amountV2` instead.")
|
||||
amount: MoneyV2!
|
||||
|
||||
"""
|
||||
The amount of money that the transaction was for.
|
||||
"""
|
||||
amountV2: MoneyV2!
|
||||
amountV2: MoneyV2! @deprecated(reason: "Use `amount` instead.")
|
||||
|
||||
"""
|
||||
The kind of the transaction.
|
||||
@ -11392,6 +11797,9 @@ enum UnitSystem {
|
||||
METRIC_SYSTEM
|
||||
}
|
||||
|
||||
"An unsigned 64-bit integer. Represents whole numeric values between 0 and 2^64 - 1 encoded as a string of base-10 digits.\n\nExample value: `\"50\"`.\n"
|
||||
scalar UnsignedInt64
|
||||
|
||||
"""
|
||||
A redirect on the online store.
|
||||
"""
|
||||
|
@ -1,34 +1,15 @@
|
||||
import {
|
||||
SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
SHOPIFY_CHECKOUT_URL_COOKIE,
|
||||
SHOPIFY_CUSTOMER_TOKEN_COOKIE,
|
||||
} from '../../../const'
|
||||
import associateCustomerWithCheckoutMutation from '../../../utils/mutations/associate-customer-with-checkout'
|
||||
import { SHOPIFY_CART_URL_COOKIE } from '../../../const'
|
||||
import type { CheckoutEndpoint } from '.'
|
||||
|
||||
const getCheckout: CheckoutEndpoint['handlers']['getCheckout'] = async ({
|
||||
req,
|
||||
config,
|
||||
}) => {
|
||||
const { cookies } = req
|
||||
const checkoutUrl = cookies.get(SHOPIFY_CHECKOUT_URL_COOKIE)?.value
|
||||
const customerCookie = cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE)?.value
|
||||
const cartUrl = cookies.get(SHOPIFY_CART_URL_COOKIE)?.value
|
||||
|
||||
if (customerCookie) {
|
||||
try {
|
||||
await config.fetch(associateCustomerWithCheckoutMutation, {
|
||||
variables: {
|
||||
checkoutId: cookies.get(SHOPIFY_CHECKOUT_ID_COOKIE)?.value,
|
||||
customerAccessToken: cookies.get(SHOPIFY_CUSTOMER_TOKEN_COOKIE)
|
||||
?.value,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
return {
|
||||
redirectTo: cartUrl || '/cart',
|
||||
}
|
||||
|
||||
return { redirectTo: checkoutUrl ?? '/cart' }
|
||||
}
|
||||
|
||||
export default getCheckout
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
API_URL,
|
||||
API_TOKEN,
|
||||
SHOPIFY_CUSTOMER_TOKEN_COOKIE,
|
||||
SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
SHOPIFY_CART_ID_COOKIE,
|
||||
} from '../const'
|
||||
|
||||
import fetchGraphqlApi from './utils/fetch-graphql-api'
|
||||
@ -40,7 +40,7 @@ const config: ShopifyConfig = {
|
||||
commerceUrl: API_URL,
|
||||
apiToken: API_TOKEN,
|
||||
customerCookie: SHOPIFY_CUSTOMER_TOKEN_COOKIE,
|
||||
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
cartCookie: SHOPIFY_CART_ID_COOKIE,
|
||||
cartCookieMaxAge: ONE_DAY * 30,
|
||||
fetch: fetchGraphqlApi,
|
||||
}
|
||||
|
@ -1,23 +1,28 @@
|
||||
import { useCallback } from 'react'
|
||||
import type { AddItemHook } from '@vercel/commerce/types/cart'
|
||||
import type { MutationHook } from '@vercel/commerce/utils/types'
|
||||
|
||||
import type {
|
||||
CartLinesAddMutation,
|
||||
CartLinesAddMutationVariables,
|
||||
} from '../../schema'
|
||||
|
||||
import { useCallback } from 'react'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
import useAddItem, { UseAddItem } from '@vercel/commerce/cart/use-add-item'
|
||||
import type { AddItemHook } from '@vercel/commerce/types/cart'
|
||||
|
||||
import useCart from './use-cart'
|
||||
|
||||
import {
|
||||
checkoutLineItemAddMutation,
|
||||
getCheckoutId,
|
||||
checkoutToCart,
|
||||
checkoutCreate,
|
||||
} from '../utils'
|
||||
import { Mutation, MutationCheckoutLineItemsAddArgs } from '../../schema'
|
||||
import { normalizeCart } from '../utils/normalize'
|
||||
import { getCartId, cartCreate } from '../utils/cart'
|
||||
import throwUserErrors from '../utils/throw-user-errors'
|
||||
|
||||
import { cartLinesAddMutation } from '../utils/mutations/cart-mutations'
|
||||
|
||||
export default useAddItem as UseAddItem<typeof handler>
|
||||
|
||||
export const handler: MutationHook<AddItemHook> = {
|
||||
fetchOptions: {
|
||||
query: checkoutLineItemAddMutation,
|
||||
query: cartLinesAddMutation,
|
||||
},
|
||||
async fetcher({ input: item, options, fetch }) {
|
||||
if (
|
||||
@ -29,29 +34,33 @@ export const handler: MutationHook<AddItemHook> = {
|
||||
})
|
||||
}
|
||||
|
||||
const lineItems = [
|
||||
const lines = [
|
||||
{
|
||||
variantId: item.variantId,
|
||||
merchandiseId: item.variantId,
|
||||
quantity: item.quantity ?? 1,
|
||||
},
|
||||
]
|
||||
|
||||
let checkoutId = getCheckoutId()
|
||||
let cartId = getCartId()
|
||||
|
||||
if (!checkoutId) {
|
||||
return checkoutToCart(await checkoutCreate(fetch, lineItems))
|
||||
if (!cartId) {
|
||||
const cart = await cartCreate(fetch, lines)
|
||||
return normalizeCart(cart)
|
||||
} else {
|
||||
const { checkoutLineItemsAdd } = await fetch<
|
||||
Mutation,
|
||||
MutationCheckoutLineItemsAddArgs
|
||||
const { cartLinesAdd } = await fetch<
|
||||
CartLinesAddMutation,
|
||||
CartLinesAddMutationVariables
|
||||
>({
|
||||
...options,
|
||||
variables: {
|
||||
checkoutId,
|
||||
lineItems,
|
||||
cartId,
|
||||
lines,
|
||||
},
|
||||
})
|
||||
return checkoutToCart(checkoutLineItemsAdd)
|
||||
|
||||
throwUserErrors(cartLinesAdd?.userErrors)
|
||||
|
||||
return normalizeCart(cartLinesAdd?.cart)
|
||||
}
|
||||
},
|
||||
useHook:
|
||||
|
@ -1,40 +1,33 @@
|
||||
import type { SWRHook } from '@vercel/commerce/utils/types'
|
||||
import type { GetCartHook } from '@vercel/commerce/types/cart'
|
||||
import type { GetCartQueryVariables, QueryRoot } from '../../schema'
|
||||
|
||||
import { useMemo } from 'react'
|
||||
import useCommerceCart, { type UseCart } from '@vercel/commerce/cart/use-cart'
|
||||
|
||||
import { checkoutToCart } from '../utils'
|
||||
import getCheckoutQuery from '../utils/queries/get-checkout-query'
|
||||
import Cookies from 'js-cookie'
|
||||
import useCommerceCart, { UseCart } from '@vercel/commerce/cart/use-cart'
|
||||
|
||||
import {
|
||||
SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
SHOPIFY_CHECKOUT_URL_COOKIE,
|
||||
} from '../const'
|
||||
import { SHOPIFY_CART_ID_COOKIE } from '../const'
|
||||
|
||||
import { setCartUrlCookie } from '../utils/cart'
|
||||
import { normalizeCart } from '../utils/normalize'
|
||||
import { getCartQuery } from '../utils/queries/get-cart-query'
|
||||
|
||||
export default useCommerceCart as UseCart<typeof handler>
|
||||
|
||||
export const handler: SWRHook<GetCartHook> = {
|
||||
fetchOptions: {
|
||||
query: getCheckoutQuery,
|
||||
query: getCartQuery,
|
||||
},
|
||||
async fetcher({ input: { cartId }, options, fetch }) {
|
||||
if (cartId) {
|
||||
const { node: checkout } = await fetch({
|
||||
let { cart } = await fetch<QueryRoot, GetCartQueryVariables>({
|
||||
...options,
|
||||
variables: {
|
||||
checkoutId: cartId,
|
||||
},
|
||||
variables: { cartId },
|
||||
})
|
||||
if (checkout?.completedAt) {
|
||||
Cookies.remove(SHOPIFY_CHECKOUT_ID_COOKIE)
|
||||
Cookies.remove(SHOPIFY_CHECKOUT_URL_COOKIE)
|
||||
return null
|
||||
if (cart) {
|
||||
setCartUrlCookie(cart.checkoutUrl)
|
||||
return normalizeCart(cart)
|
||||
} else {
|
||||
return checkoutToCart({
|
||||
checkout,
|
||||
})
|
||||
Cookies.remove(SHOPIFY_CART_ID_COOKIE)
|
||||
}
|
||||
}
|
||||
return null
|
||||
@ -50,7 +43,7 @@ export const handler: SWRHook<GetCartHook> = {
|
||||
Object.create(response, {
|
||||
isEmpty: {
|
||||
get() {
|
||||
return (response.data?.lineItems.length ?? 0) <= 0
|
||||
return (response.data?.lineItems?.length ?? 0) <= 0
|
||||
},
|
||||
enumerable: true,
|
||||
},
|
||||
|
@ -1,19 +1,33 @@
|
||||
import { useCallback } from 'react'
|
||||
import type {
|
||||
MutationHookContext,
|
||||
HookFetcherContext,
|
||||
} from '@vercel/commerce/utils/types'
|
||||
import { ValidationError } from '@vercel/commerce/utils/errors'
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
} from '@vercel/commerce/cart/use-remove-item'
|
||||
|
||||
import type {
|
||||
CartLinesRemoveMutation,
|
||||
CartLinesRemoveMutationVariables,
|
||||
} from '../../schema'
|
||||
|
||||
import type {
|
||||
Cart,
|
||||
LineItem,
|
||||
RemoveItemHook,
|
||||
} from '@vercel/commerce/types/cart'
|
||||
|
||||
import { useCallback } from 'react'
|
||||
import { ValidationError } from '@vercel/commerce/utils/errors'
|
||||
|
||||
import useRemoveItem, {
|
||||
UseRemoveItem,
|
||||
} from '@vercel/commerce/cart/use-remove-item'
|
||||
|
||||
import useCart from './use-cart'
|
||||
|
||||
import { getCartId } from '../utils/cart'
|
||||
import { normalizeCart } from '../utils/normalize'
|
||||
import { cartLinesRemoveMutation } from '../utils/mutations/cart-mutations'
|
||||
import throwUserErrors from '../utils/throw-user-errors'
|
||||
|
||||
export type RemoveItemFn<T = any> = T extends LineItem
|
||||
? (input?: RemoveItemActionInput<T>) => Promise<Cart | null | undefined>
|
||||
: (input: RemoveItemActionInput<T>) => Promise<Cart | null>
|
||||
@ -24,28 +38,26 @@ export type RemoveItemActionInput<T = any> = T extends LineItem
|
||||
|
||||
export default useRemoveItem as UseRemoveItem<typeof handler>
|
||||
|
||||
import {
|
||||
checkoutLineItemRemoveMutation,
|
||||
getCheckoutId,
|
||||
checkoutToCart,
|
||||
} from '../utils'
|
||||
|
||||
import { Mutation, MutationCheckoutLineItemsRemoveArgs } from '../../schema'
|
||||
|
||||
export const handler = {
|
||||
fetchOptions: {
|
||||
query: checkoutLineItemRemoveMutation,
|
||||
query: cartLinesRemoveMutation,
|
||||
},
|
||||
async fetcher({
|
||||
input: { itemId },
|
||||
options,
|
||||
fetch,
|
||||
}: HookFetcherContext<RemoveItemHook>) {
|
||||
const data = await fetch<Mutation, MutationCheckoutLineItemsRemoveArgs>({
|
||||
const data = await fetch<
|
||||
CartLinesRemoveMutation,
|
||||
CartLinesRemoveMutationVariables
|
||||
>({
|
||||
...options,
|
||||
variables: { checkoutId: getCheckoutId(), lineItemIds: [itemId] },
|
||||
variables: { cartId: getCartId(), lineIds: [itemId] },
|
||||
})
|
||||
return checkoutToCart(data.checkoutLineItemsRemove)
|
||||
|
||||
throwUserErrors(data.cartLinesRemove?.userErrors)
|
||||
|
||||
return normalizeCart(data.cartLinesRemove?.cart)
|
||||
},
|
||||
useHook:
|
||||
({ fetch }: MutationHookContext<RemoveItemHook>) =>
|
||||
|
@ -1,26 +1,29 @@
|
||||
import type { UpdateItemHook, LineItem } from '@vercel/commerce/types/cart'
|
||||
import type {
|
||||
Mutation,
|
||||
MutationCheckoutLineItemsUpdateArgs,
|
||||
CartLinesUpdateMutation,
|
||||
CartLinesUpdateMutationVariables,
|
||||
} from '../../schema'
|
||||
|
||||
import type {
|
||||
HookFetcherContext,
|
||||
MutationHookContext,
|
||||
} from '@vercel/commerce/utils/types'
|
||||
|
||||
import type { UpdateItemHook, LineItem } from '@vercel/commerce/types/cart'
|
||||
|
||||
import { useCallback } from 'react'
|
||||
import debounce from 'lodash.debounce'
|
||||
import { ValidationError } from '@vercel/commerce/utils/errors'
|
||||
import useUpdateItem, {
|
||||
type UseUpdateItem,
|
||||
UseUpdateItem,
|
||||
} from '@vercel/commerce/cart/use-update-item'
|
||||
|
||||
import useCart from './use-cart'
|
||||
|
||||
import { handler as removeItemHandler } from './use-remove-item'
|
||||
import {
|
||||
getCheckoutId,
|
||||
checkoutLineItemUpdateMutation,
|
||||
checkoutToCart,
|
||||
} from '../utils'
|
||||
|
||||
import { getCartId } from '../utils/cart'
|
||||
import { normalizeCart } from '../utils/normalize'
|
||||
import { cartLinesUpdateMutation } from '../utils/mutations/cart-mutations'
|
||||
|
||||
export type UpdateItemActionInput<T = any> = T extends LineItem
|
||||
? Partial<UpdateItemHook['actionInput']>
|
||||
@ -30,7 +33,7 @@ export default useUpdateItem as UseUpdateItem<typeof handler>
|
||||
|
||||
export const handler = {
|
||||
fetchOptions: {
|
||||
query: checkoutLineItemUpdateMutation,
|
||||
query: cartLinesUpdateMutation,
|
||||
},
|
||||
async fetcher({
|
||||
input: { itemId, item },
|
||||
@ -51,14 +54,14 @@ export const handler = {
|
||||
message: 'The item quantity has to be a valid integer',
|
||||
})
|
||||
}
|
||||
const { checkoutLineItemsUpdate } = await fetch<
|
||||
Mutation,
|
||||
MutationCheckoutLineItemsUpdateArgs
|
||||
const { cartLinesUpdate } = await fetch<
|
||||
CartLinesUpdateMutation,
|
||||
CartLinesUpdateMutationVariables
|
||||
>({
|
||||
...options,
|
||||
variables: {
|
||||
checkoutId: getCheckoutId(),
|
||||
lineItems: [
|
||||
cartId: getCartId(),
|
||||
lines: [
|
||||
{
|
||||
id: itemId,
|
||||
quantity: item.quantity,
|
||||
@ -67,7 +70,7 @@ export const handler = {
|
||||
},
|
||||
})
|
||||
|
||||
return checkoutToCart(checkoutLineItemsUpdate)
|
||||
return normalizeCart(cartLinesUpdate?.cart)
|
||||
},
|
||||
useHook:
|
||||
({ fetch }: MutationHookContext<UpdateItemHook>) =>
|
||||
|
@ -1,6 +1,6 @@
|
||||
export const SHOPIFY_CHECKOUT_ID_COOKIE = 'shopify_checkoutId'
|
||||
export const SHOPIFY_CART_ID_COOKIE = 'shopify_cartId'
|
||||
|
||||
export const SHOPIFY_CHECKOUT_URL_COOKIE = 'shopify_checkoutUrl'
|
||||
export const SHOPIFY_CART_URL_COOKIE = 'shopify_cartUrl'
|
||||
|
||||
export const SHOPIFY_CUSTOMER_TOKEN_COOKIE = 'shopify_customerToken'
|
||||
|
||||
@ -8,6 +8,6 @@ export const STORE_DOMAIN = process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN
|
||||
|
||||
export const SHOPIFY_COOKIE_EXPIRE = 30
|
||||
|
||||
export const API_URL = `https://${STORE_DOMAIN}/api/2022-07/graphql.json`
|
||||
export const API_URL = `https://${STORE_DOMAIN}/api/2023-01/graphql.json`
|
||||
|
||||
export const API_TOKEN = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { SHOPIFY_CHECKOUT_ID_COOKIE } from './const'
|
||||
import { SHOPIFY_CART_ID_COOKIE } from './const'
|
||||
|
||||
import { handler as useCart } from './cart/use-cart'
|
||||
import { handler as useAddItem } from './cart/use-add-item'
|
||||
@ -16,7 +16,7 @@ import fetcher from './fetcher'
|
||||
|
||||
export const shopifyProvider = {
|
||||
locale: 'en-us',
|
||||
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
cartCookie: SHOPIFY_CART_ID_COOKIE,
|
||||
fetcher,
|
||||
cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
|
||||
customer: { useCustomer },
|
||||
|
65
packages/shopify/src/utils/cart.ts
Normal file
65
packages/shopify/src/utils/cart.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import type { FetcherOptions } from '@vercel/commerce/utils/types'
|
||||
|
||||
import type {
|
||||
CartLineInput,
|
||||
CartCreateMutation,
|
||||
CartDetailsFragment,
|
||||
CartCreateMutationVariables,
|
||||
} from '../../schema'
|
||||
|
||||
import Cookies from 'js-cookie'
|
||||
import { cartCreateMutation } from './mutations/cart-mutations'
|
||||
import throwUserErrors from './throw-user-errors'
|
||||
|
||||
import {
|
||||
SHOPIFY_CART_ID_COOKIE,
|
||||
SHOPIFY_CART_URL_COOKIE,
|
||||
SHOPIFY_COOKIE_EXPIRE,
|
||||
} from '../const'
|
||||
|
||||
export const setCartUrlCookie = (cartUrl: string) => {
|
||||
if (cartUrl) {
|
||||
const oldCookie = Cookies.get(SHOPIFY_CART_URL_COOKIE)
|
||||
if (oldCookie !== cartUrl) {
|
||||
Cookies.set(SHOPIFY_CART_URL_COOKIE, cartUrl, {
|
||||
expires: SHOPIFY_COOKIE_EXPIRE,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const getCartId = (id?: string) => {
|
||||
return id || Cookies.get(SHOPIFY_CART_ID_COOKIE)
|
||||
}
|
||||
|
||||
export const cartCreate = async (
|
||||
fetch: <T = any, B = Body>(options: FetcherOptions<B>) => Promise<T>,
|
||||
lines?: Array<CartLineInput> | CartLineInput
|
||||
): Promise<CartDetailsFragment | null | undefined> => {
|
||||
const { cartCreate } = await fetch<
|
||||
CartCreateMutation,
|
||||
CartCreateMutationVariables
|
||||
>({
|
||||
query: cartCreateMutation,
|
||||
variables: {
|
||||
input: {
|
||||
lines,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const cart = cartCreate?.cart
|
||||
|
||||
throwUserErrors(cartCreate?.userErrors)
|
||||
|
||||
if (cart?.id) {
|
||||
const options = {
|
||||
expires: SHOPIFY_COOKIE_EXPIRE,
|
||||
}
|
||||
Cookies.set(SHOPIFY_CART_ID_COOKIE, cart.id, options)
|
||||
}
|
||||
|
||||
setCartUrlCookie(cart?.checkoutUrl)
|
||||
|
||||
return cart
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
import {
|
||||
SHOPIFY_CHECKOUT_ID_COOKIE,
|
||||
SHOPIFY_CHECKOUT_URL_COOKIE,
|
||||
SHOPIFY_COOKIE_EXPIRE,
|
||||
} from '../const'
|
||||
|
||||
import checkoutCreateMutation from './mutations/checkout-create'
|
||||
import {
|
||||
CheckoutCreatePayload,
|
||||
CheckoutLineItemInput,
|
||||
Mutation,
|
||||
MutationCheckoutCreateArgs,
|
||||
} from '../../schema'
|
||||
import { FetcherOptions } from '@vercel/commerce/utils/types'
|
||||
|
||||
export const checkoutCreate = async (
|
||||
fetch: <T = any, B = Body>(options: FetcherOptions<B>) => Promise<T>,
|
||||
lineItems: CheckoutLineItemInput[]
|
||||
): Promise<CheckoutCreatePayload> => {
|
||||
const { checkoutCreate } = await fetch<Mutation, MutationCheckoutCreateArgs>({
|
||||
query: checkoutCreateMutation,
|
||||
variables: {
|
||||
input: { lineItems },
|
||||
},
|
||||
})
|
||||
|
||||
const checkout = checkoutCreate?.checkout
|
||||
|
||||
if (checkout) {
|
||||
const checkoutId = checkout?.id
|
||||
const options = {
|
||||
expires: SHOPIFY_COOKIE_EXPIRE,
|
||||
}
|
||||
Cookies.set(SHOPIFY_CHECKOUT_ID_COOKIE, checkoutId, options)
|
||||
if (checkout?.webUrl) {
|
||||
Cookies.set(SHOPIFY_CHECKOUT_URL_COOKIE, checkout.webUrl, options)
|
||||
}
|
||||
}
|
||||
|
||||
return checkoutCreate!
|
||||
}
|
||||
|
||||
export default checkoutCreate
|
@ -1,41 +0,0 @@
|
||||
import type { Cart } from '@vercel/commerce/types/cart'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
|
||||
import {
|
||||
CheckoutLineItemsAddPayload,
|
||||
CheckoutLineItemsRemovePayload,
|
||||
CheckoutLineItemsUpdatePayload,
|
||||
CheckoutCreatePayload,
|
||||
CheckoutUserError,
|
||||
Checkout,
|
||||
Maybe,
|
||||
} from '../../schema'
|
||||
|
||||
import { normalizeCart } from './normalize'
|
||||
import throwUserErrors from './throw-user-errors'
|
||||
|
||||
export type CheckoutQuery = {
|
||||
checkout: Checkout
|
||||
checkoutUserErrors?: Array<CheckoutUserError>
|
||||
}
|
||||
|
||||
export type CheckoutPayload =
|
||||
| CheckoutLineItemsAddPayload
|
||||
| CheckoutLineItemsUpdatePayload
|
||||
| CheckoutLineItemsRemovePayload
|
||||
| CheckoutCreatePayload
|
||||
| CheckoutQuery
|
||||
|
||||
const checkoutToCart = (checkoutPayload?: Maybe<CheckoutPayload>): Cart => {
|
||||
throwUserErrors(checkoutPayload?.checkoutUserErrors)
|
||||
|
||||
if (!checkoutPayload?.checkout) {
|
||||
throw new CommerceError({
|
||||
message: 'Missing checkout object from response',
|
||||
})
|
||||
}
|
||||
|
||||
return normalizeCart(checkoutPayload?.checkout)
|
||||
}
|
||||
|
||||
export default checkoutToCart
|
@ -0,0 +1,82 @@
|
||||
export const cartDetailsFragment = /* GraphQL */ `
|
||||
fragment CartDetails on Cart {
|
||||
id
|
||||
checkoutUrl
|
||||
createdAt
|
||||
updatedAt
|
||||
lines(first: 10) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
quantity
|
||||
merchandise {
|
||||
... on ProductVariant {
|
||||
id
|
||||
id
|
||||
sku
|
||||
title
|
||||
selectedOptions {
|
||||
name
|
||||
value
|
||||
}
|
||||
image {
|
||||
url
|
||||
altText
|
||||
width
|
||||
height
|
||||
}
|
||||
price {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
compareAtPrice {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
product {
|
||||
title
|
||||
handle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
attributes {
|
||||
key
|
||||
value
|
||||
}
|
||||
buyerIdentity {
|
||||
email
|
||||
customer {
|
||||
id
|
||||
}
|
||||
}
|
||||
estimatedCost {
|
||||
totalAmount {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
subtotalAmount {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
totalTaxAmount {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
totalDutyAmount {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const userErrorsFragment = /* GraphQL */ `
|
||||
fragment UserErrors on CartUserError {
|
||||
code
|
||||
field
|
||||
message
|
||||
}
|
||||
`
|
@ -1,8 +0,0 @@
|
||||
import Cookies from 'js-cookie'
|
||||
import { SHOPIFY_CHECKOUT_ID_COOKIE } from '../const'
|
||||
|
||||
const getCheckoutId = (id?: string) => {
|
||||
return id ?? Cookies.get(SHOPIFY_CHECKOUT_ID_COOKIE)
|
||||
}
|
||||
|
||||
export default getCheckoutId
|
@ -3,9 +3,6 @@ export { default as getSearchVariables } from './get-search-variables'
|
||||
export { default as getSortVariables } from './get-sort-variables'
|
||||
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'
|
||||
export { default as checkoutToCart } from './checkout-to-cart'
|
||||
export { default as handleLogin, handleAutomaticLogin } from './handle-login'
|
||||
export { default as handleAccountActivation } from './handle-account-activation'
|
||||
export { default as throwUserErrors } from './throw-user-errors'
|
||||
|
64
packages/shopify/src/utils/mutations/cart-mutations.ts
Normal file
64
packages/shopify/src/utils/mutations/cart-mutations.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import {
|
||||
cartDetailsFragment,
|
||||
userErrorsFragment,
|
||||
} from '../fragments/cart-details-fragment'
|
||||
|
||||
export const cartCreateMutation = /* GraphQL */ `
|
||||
mutation cartCreate($input: CartInput = {}) {
|
||||
cartCreate(input: $input) {
|
||||
cart {
|
||||
...CartDetails
|
||||
}
|
||||
userErrors {
|
||||
...UserErrors
|
||||
}
|
||||
}
|
||||
}
|
||||
${cartDetailsFragment}
|
||||
${userErrorsFragment}
|
||||
`
|
||||
|
||||
export const cartLinesAddMutation = /* GraphQL */ `
|
||||
mutation cartLinesAdd($lines: [CartLineInput!]!, $cartId: ID!) {
|
||||
cartLinesAdd(lines: $lines, cartId: $cartId) {
|
||||
cart {
|
||||
...CartDetails
|
||||
}
|
||||
userErrors {
|
||||
...UserErrors
|
||||
}
|
||||
}
|
||||
}
|
||||
${cartDetailsFragment}
|
||||
${userErrorsFragment}
|
||||
`
|
||||
|
||||
export const cartLinesRemoveMutation = /* GraphQL */ `
|
||||
mutation cartLinesRemove($cartId: ID!, $lineIds: [ID!]!) {
|
||||
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
|
||||
cart {
|
||||
...CartDetails
|
||||
}
|
||||
userErrors {
|
||||
...UserErrors
|
||||
}
|
||||
}
|
||||
}
|
||||
${cartDetailsFragment}
|
||||
${userErrorsFragment}
|
||||
`
|
||||
|
||||
export const cartLinesUpdateMutation = /* GraphQL */ `
|
||||
mutation cartLinesUpdate($cartId: ID!, $lines: [CartLineUpdateInput!]!) {
|
||||
cartLinesUpdate(cartId: $cartId, lines: $lines) {
|
||||
cart {
|
||||
...CartDetails
|
||||
}
|
||||
userErrors {
|
||||
...UserErrors
|
||||
}
|
||||
}
|
||||
}
|
||||
${cartDetailsFragment}
|
||||
${userErrorsFragment}
|
||||
`
|
@ -1,19 +0,0 @@
|
||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
||||
|
||||
const checkoutCreateMutation = /* GraphQL */ `
|
||||
mutation checkoutCreate($input: CheckoutCreateInput = {}) {
|
||||
checkoutCreate(input: $input) {
|
||||
checkoutUserErrors {
|
||||
code
|
||||
field
|
||||
message
|
||||
}
|
||||
checkout {
|
||||
...checkoutDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${checkoutDetailsFragment}
|
||||
`
|
||||
export default checkoutCreateMutation
|
@ -1,22 +0,0 @@
|
||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
||||
|
||||
const checkoutLineItemAddMutation = /* GraphQL */ `
|
||||
mutation checkoutLineItemAdd(
|
||||
$checkoutId: ID!
|
||||
$lineItems: [CheckoutLineItemInput!]!
|
||||
) {
|
||||
checkoutLineItemsAdd(checkoutId: $checkoutId, lineItems: $lineItems) {
|
||||
checkoutUserErrors {
|
||||
code
|
||||
field
|
||||
message
|
||||
}
|
||||
checkout {
|
||||
...checkoutDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${checkoutDetailsFragment}
|
||||
`
|
||||
export default checkoutLineItemAddMutation
|
@ -1,21 +0,0 @@
|
||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
||||
|
||||
const checkoutLineItemRemoveMutation = /* GraphQL */ `
|
||||
mutation checkoutLineItemRemove($checkoutId: ID!, $lineItemIds: [ID!]!) {
|
||||
checkoutLineItemsRemove(
|
||||
checkoutId: $checkoutId
|
||||
lineItemIds: $lineItemIds
|
||||
) {
|
||||
checkoutUserErrors {
|
||||
code
|
||||
field
|
||||
message
|
||||
}
|
||||
checkout {
|
||||
...checkoutDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
${checkoutDetailsFragment}
|
||||
`
|
||||
export default checkoutLineItemRemoveMutation
|
@ -1,22 +0,0 @@
|
||||
import { checkoutDetailsFragment } from '../queries/get-checkout-query'
|
||||
|
||||
const checkoutLineItemUpdateMutation = /* GraphQL */ `
|
||||
mutation checkoutLineItemUpdate(
|
||||
$checkoutId: ID!
|
||||
$lineItems: [CheckoutLineItemUpdateInput!]!
|
||||
) {
|
||||
checkoutLineItemsUpdate(checkoutId: $checkoutId, lineItems: $lineItems) {
|
||||
checkoutUserErrors {
|
||||
code
|
||||
field
|
||||
message
|
||||
}
|
||||
checkout {
|
||||
...checkoutDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${checkoutDetailsFragment}
|
||||
`
|
||||
export default checkoutLineItemUpdateMutation
|
@ -1,8 +1,4 @@
|
||||
export { default as customerCreateMutation } from './customer-create'
|
||||
export { default as checkoutCreateMutation } from './checkout-create'
|
||||
export { default as checkoutLineItemAddMutation } from './checkout-line-item-add'
|
||||
export { default as checkoutLineItemUpdateMutation } from './checkout-line-item-update'
|
||||
export { default as checkoutLineItemRemoveMutation } from './checkout-line-item-remove'
|
||||
export { default as customerAccessTokenCreateMutation } from './customer-access-token-create'
|
||||
export { default as customerAccessTokenDeleteMutation } from './customer-access-token-delete'
|
||||
export { default as customerActivateMutation } from './customer-activate'
|
||||
|
@ -5,8 +5,6 @@ import type { Category } from '@vercel/commerce/types/site'
|
||||
|
||||
import type {
|
||||
Product as ShopifyProduct,
|
||||
Checkout,
|
||||
CheckoutLineItemEdge,
|
||||
SelectedOption,
|
||||
ImageConnection,
|
||||
ProductVariantConnection,
|
||||
@ -15,9 +13,11 @@ import type {
|
||||
Page as ShopifyPage,
|
||||
PageEdge,
|
||||
Collection,
|
||||
CartDetailsFragment,
|
||||
} from '../../schema'
|
||||
|
||||
import { colorMap } from './colors'
|
||||
import { CommerceError } from '@vercel/commerce/utils/errors'
|
||||
|
||||
const money = ({ amount, currencyCode }: MoneyV2) => {
|
||||
return {
|
||||
@ -67,8 +67,8 @@ const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
|
||||
selectedOptions,
|
||||
sku,
|
||||
title,
|
||||
priceV2,
|
||||
compareAtPriceV2,
|
||||
price,
|
||||
compareAtPrice,
|
||||
requiresShipping,
|
||||
availableForSale,
|
||||
},
|
||||
@ -77,8 +77,8 @@ const normalizeProductVariants = ({ edges }: ProductVariantConnection) => {
|
||||
id,
|
||||
name: title,
|
||||
sku,
|
||||
price: +priceV2.amount,
|
||||
listPrice: +compareAtPriceV2?.amount,
|
||||
price: +price.amount,
|
||||
listPrice: +compareAtPrice?.amount,
|
||||
requiresShipping,
|
||||
availableForSale,
|
||||
options: selectedOptions.map(({ name, value }: SelectedOption) => {
|
||||
@ -129,51 +129,57 @@ export function normalizeProduct({
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeCart(checkout: Checkout): Cart {
|
||||
return {
|
||||
id: checkout.id,
|
||||
url: checkout.webUrl,
|
||||
customerId: '',
|
||||
email: '',
|
||||
createdAt: checkout.createdAt,
|
||||
currency: {
|
||||
code: checkout.totalPriceV2?.currencyCode,
|
||||
},
|
||||
taxesIncluded: checkout.taxesIncluded,
|
||||
lineItems: checkout.lineItems?.edges.map(normalizeLineItem),
|
||||
lineItemsSubtotalPrice: +checkout.subtotalPriceV2?.amount,
|
||||
subtotalPrice: +checkout.subtotalPriceV2?.amount,
|
||||
totalPrice: checkout.totalPriceV2?.amount,
|
||||
discounts: [],
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLineItem({
|
||||
node: { id, title, variant, quantity },
|
||||
}: CheckoutLineItemEdge): LineItem {
|
||||
node: { id, merchandise: variant, quantity },
|
||||
}: {
|
||||
node: any
|
||||
}): LineItem {
|
||||
return {
|
||||
id,
|
||||
variantId: String(variant?.id),
|
||||
productId: String(variant?.id),
|
||||
name: `${title}`,
|
||||
quantity,
|
||||
variantId: variant?.id,
|
||||
productId: variant?.id,
|
||||
name: variant?.product?.title || variant?.title,
|
||||
quantity: quantity ?? 0,
|
||||
variant: {
|
||||
id: String(variant?.id),
|
||||
id: variant?.id,
|
||||
sku: variant?.sku ?? '',
|
||||
name: variant?.title!,
|
||||
image: {
|
||||
url: variant?.image?.url || '/product-img-placeholder.svg',
|
||||
},
|
||||
requiresShipping: variant?.requiresShipping ?? false,
|
||||
price: variant?.priceV2?.amount,
|
||||
listPrice: variant?.compareAtPriceV2?.amount,
|
||||
price: +variant?.price?.amount,
|
||||
listPrice: +variant?.compareAtPrice?.amount,
|
||||
},
|
||||
path: String(variant?.product?.handle),
|
||||
path: variant?.product?.handle,
|
||||
discounts: [],
|
||||
options: variant?.title == 'Default Title' ? [] : variant?.selectedOptions,
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeCart(
|
||||
cart: CartDetailsFragment | undefined | null
|
||||
): Cart {
|
||||
if (!cart) {
|
||||
throw new CommerceError({ message: 'Missing cart details' })
|
||||
}
|
||||
return {
|
||||
id: cart.id,
|
||||
customerId: cart.buyerIdentity?.customer?.id,
|
||||
email: cart.buyerIdentity?.email ?? '',
|
||||
createdAt: cart.createdAt,
|
||||
currency: {
|
||||
code: cart.estimatedCost?.totalAmount?.currencyCode,
|
||||
},
|
||||
taxesIncluded: !!cart.estimatedCost?.totalTaxAmount?.amount,
|
||||
lineItems: cart.lines?.edges?.map(normalizeLineItem) ?? [],
|
||||
lineItemsSubtotalPrice: +cart.estimatedCost?.subtotalAmount?.amount,
|
||||
subtotalPrice: +cart.estimatedCost?.subtotalAmount?.amount,
|
||||
totalPrice: +cart.estimatedCost?.totalAmount?.amount,
|
||||
discounts: [],
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizePage = (
|
||||
{ title: name, handle, ...page }: ShopifyPage,
|
||||
locale: string = 'en-US'
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const getAllPagesQuery = /* GraphQL */ `
|
||||
const getAllPagesQuery = /* GraphQL */ `
|
||||
query getAllPages($first: Int = 250) {
|
||||
pages(first: $first) {
|
||||
edges {
|
||||
|
10
packages/shopify/src/utils/queries/get-cart-query.ts
Normal file
10
packages/shopify/src/utils/queries/get-cart-query.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { cartDetailsFragment } from '../fragments/cart-details-fragment'
|
||||
|
||||
export const getCartQuery = /* GraphQL */ `
|
||||
query getCart($cartId: ID!) {
|
||||
cart(id: $cartId) {
|
||||
...CartDetails
|
||||
}
|
||||
}
|
||||
${cartDetailsFragment}
|
||||
`
|
@ -1,70 +0,0 @@
|
||||
export const checkoutDetailsFragment = /* GraphQL */ `
|
||||
fragment checkoutDetails on Checkout {
|
||||
id
|
||||
webUrl
|
||||
subtotalPriceV2 {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
totalTaxV2 {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
totalPriceV2 {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
completedAt
|
||||
createdAt
|
||||
taxesIncluded
|
||||
lineItems(first: 250) {
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
}
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
variant {
|
||||
id
|
||||
sku
|
||||
title
|
||||
selectedOptions {
|
||||
name
|
||||
value
|
||||
}
|
||||
image {
|
||||
url
|
||||
altText
|
||||
width
|
||||
height
|
||||
}
|
||||
priceV2 {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
compareAtPriceV2 {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
product {
|
||||
handle
|
||||
}
|
||||
}
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const getCheckoutQuery = /* GraphQL */ `
|
||||
query getCheckout($checkoutId: ID!) {
|
||||
node(id: $checkoutId) {
|
||||
...checkoutDetails
|
||||
}
|
||||
}
|
||||
${checkoutDetailsFragment}
|
||||
`
|
||||
export default getCheckoutQuery
|
@ -1,4 +1,4 @@
|
||||
export const getCustomerQuery = /* GraphQL */ `
|
||||
const getCustomerQuery = /* GraphQL */ `
|
||||
query getCustomerId($customerAccessToken: String!) {
|
||||
customer(customerAccessToken: $customerAccessToken) {
|
||||
id
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const getCustomerQuery = /* GraphQL */ `
|
||||
const getCustomerQuery = /* GraphQL */ `
|
||||
query getCustomer($customerAccessToken: String!) {
|
||||
customer(customerAccessToken: $customerAccessToken) {
|
||||
id
|
||||
|
@ -1,4 +1,4 @@
|
||||
export const getPageQuery = /* GraphQL */ `
|
||||
const getPageQuery = /* GraphQL */ `
|
||||
query getPage($id: ID!) {
|
||||
node(id: $id) {
|
||||
id
|
||||
|
@ -40,11 +40,11 @@ const getProductQuery = /* GraphQL */ `
|
||||
name
|
||||
value
|
||||
}
|
||||
priceV2 {
|
||||
price {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
compareAtPriceV2 {
|
||||
compareAtPrice {
|
||||
amount
|
||||
currencyCode
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ export { default as getAllProductsQuery } from './get-all-products-query'
|
||||
export { default as getAllProductsPathtsQuery } from './get-all-products-paths-query'
|
||||
export { default as getAllProductVendors } from './get-all-product-vendors-query'
|
||||
export { default as getCollectionProductsQuery } from './get-collection-products-query'
|
||||
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'
|
||||
|
@ -5,13 +5,18 @@ import {
|
||||
CheckoutUserError,
|
||||
CustomerErrorCode,
|
||||
CustomerUserError,
|
||||
CartUserError,
|
||||
CartErrorCode,
|
||||
} from '../../schema'
|
||||
|
||||
export type UserErrors = Array<CheckoutUserError | CustomerUserError>
|
||||
export type UserErrors = Array<
|
||||
CheckoutUserError | CustomerUserError | CartUserError
|
||||
>
|
||||
|
||||
export type UserErrorCode =
|
||||
| CustomerErrorCode
|
||||
| CheckoutErrorCode
|
||||
| CartErrorCode
|
||||
| null
|
||||
| undefined
|
||||
|
||||
@ -24,7 +29,7 @@ const getCustomMessage = (code: UserErrorCode, message: string) => {
|
||||
return message
|
||||
}
|
||||
|
||||
export const throwUserErrors = (errors?: UserErrors) => {
|
||||
const throwUserErrors = (errors?: UserErrors) => {
|
||||
if (errors && errors.length) {
|
||||
throw new ValidationError({
|
||||
errors: errors.map(({ code, message }) => ({
|
||||
|
Loading…
x
Reference in New Issue
Block a user