Fix/opencommerce provider (#10)

* sync changes with latest changes

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

* fix typescripts

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

* fix all types issue and checkout process

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

* fix some types

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

* several fixes

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

* remove console log

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>

---------

Signed-off-by: Chloe <pinkcloudvnn@gmail.com>
This commit is contained in:
Chloe 2023-03-09 20:11:53 +07:00 committed by GitHub
parent 1f2634a38c
commit 611a18b07f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
65 changed files with 1727 additions and 729 deletions

View File

@ -1,5 +1,4 @@
COMMERCE_PROVIDER=@vercel/commerce-opencommerce
OPENCOMMERCE_STOREFRONT_API_URL=
OPENCOMMERCE_PRIMARY_SHOP_ID=
OPENCOMMERCE_IMAGE_DOMAIN=
NEXT_PUBLIC_OPENCOMMERCE_API_URL=
NEXT_PUBLIC_OPENCOMMERCE_IMAGE_DOMAIN=

View File

@ -1,6 +1,6 @@
{
"overwrite": true,
"schema": "http://localhost:3000/graphql",
"schema": "http://api.open-commerce.io/graphql",
"documents": [
{
"./src/api/**/*.ts": {

View File

@ -48,32 +48,31 @@
}
},
"dependencies": {
"@vercel/commerce": "^0.0.1",
"@vercel/fetch": "^6.1.1"
"@vercel/commerce": "workspace:*"
},
"peerDependencies": {
"next": "^12",
"react": "^17",
"react-dom": "^17"
"next": "^13",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@graphql-codegen/cli": "2.6.2",
"@graphql-codegen/cli": "2.7.0",
"@graphql-codegen/schema-ast": "^2.4.1",
"@graphql-codegen/typescript": "2.4.8",
"@graphql-codegen/typescript-operations": "2.3.5",
"@graphql-codegen/typescript": "^2.6.0",
"@graphql-codegen/typescript-operations": "^2.4.3",
"@taskr/clear": "^1.1.0",
"@taskr/esnext": "^1.1.0",
"@taskr/watch": "^1.1.0",
"@types/node": "^17.0.8",
"@types/react": "^17.0.38",
"lint-staged": "^12.1.7",
"next": "^12.0.8",
"prettier": "^2.5.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"@types/node": "^18.0.3",
"@types/react": "^18.0.14",
"lint-staged": "^13.0.3",
"next": "^13.0.4",
"prettier": "^2.7.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"taskr": "^1.1.0",
"taskr-swc": "^0.0.1",
"typescript": "^4.5.4"
"taskr-swc": "workspace:*",
"typescript": "^4.7.4"
},
"lint-staged": {
"**/*.{js,jsx,ts,tsx,json}": [

View File

@ -16,27 +16,11 @@ export type Scalars = {
Boolean: boolean
Int: number
Float: number
/**
*
* An opaque string that identifies a particular result within a connection,
* allowing you to request a subset of results before or after that result.
*
*/
ConnectionCursor: any
/**
*
* An integer between 1 and 50, inclusive. Values less than 1 become 1 and
* values greater than 50 become 50.
*
*/
ConnectionLimitInt: any
/** A date string, such as 2007-12-03, compliant with the `full-date` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */
Date: any
/** A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar. */
DateTime: any
/** A string email address */
Email: any
/** An object with any fields */
JSONObject: any
}
@ -685,6 +669,35 @@ export type AuthenticateParamsInput = {
user?: InputMaybe<UserInput>
}
/** Represents a single user partial account */
export type BasicAccount = Node & {
__typename?: 'BasicAccount'
/** The account ID */
_id: Scalars['ID']
/** Flag to indicate if the account accepts marketing emails */
acceptsMarketing?: Maybe<Scalars['Boolean']>
/** List of shop Ids */
adminUIShopIds?: Maybe<Array<Maybe<Scalars['String']>>>
/** The date and time at which this account was created */
createdAt?: Maybe<Scalars['DateTime']>
/** Email record associated with the account */
emails?: Maybe<Array<Maybe<EmailRecord>>>
/** List of group Ids to which the account belongs */
groups?: Maybe<Array<Maybe<Scalars['String']>>>
/** The full name of the person this account represents, if known */
name?: Maybe<Scalars['String']>
/** List of shipping/billing addresses */
profile?: Maybe<Array<Maybe<Profile>>>
/** ID of shop */
shopId?: Maybe<Scalars['String']>
/** Account creation state */
state?: Maybe<Scalars['String']>
/** The date and time at which this account was last updated */
updatedAt?: Maybe<Scalars['DateTime']>
/** ID of user */
userId?: Maybe<Scalars['String']>
}
/** A single calculated tax for a cart, order group, cart item, or order item */
export type CalculatedTax = {
__typename?: 'CalculatedTax'
@ -1459,6 +1472,8 @@ export type CreateAccountGroupPayload = {
export type CreateAccountInput = {
/** Bio to display on profile */
bio?: InputMaybe<Scalars['String']>
/** An optional string identifying the mutation call, which will be returned in the response payload */
clientMutationId?: InputMaybe<Scalars['String']>
/** Email record to create account with */
emails: Array<InputMaybe<EmailRecordInput>>
/** Name to display on profile */
@ -1477,7 +1492,7 @@ export type CreateAccountInput = {
export type CreateAccountPayload = {
__typename?: 'CreateAccountPayload'
/** The added account */
account?: Maybe<Account>
account?: Maybe<BasicAccount>
/** The same string you sent with the mutation params, for matching mutation calls with their responses */
clientMutationId?: Maybe<Scalars['String']>
}
@ -2315,12 +2330,16 @@ export type EmailJob = {
__typename?: 'EmailJob'
/** The ID of the e-mail job */
_id: Scalars['ID']
/** The date and time of the creation of the e-mail job */
createdAt: Scalars['DateTime']
/** The data of the e-mail */
data: EmailJobData
/** The status of the e-mail job */
status: Scalars['String']
/** The date and time of the last update to the e-mail job */
/** To be deprecated. Use updatedAt instead. The date and time of the last update to the e-mail job. */
updated: Scalars['DateTime']
/** The date and time of the last update to the e-mail job */
updatedAt: Scalars['DateTime']
}
/**
@ -4894,6 +4913,26 @@ export type ProductConnection = {
totalCount: Scalars['Int']
}
/** Operators for filtering on a DateTime field */
export type ProductDateOperators = {
/** The value must be greater than or equal to the given value */
after?: InputMaybe<Scalars['DateTime']>
/** The value must be greater than the given value */
before?: InputMaybe<Scalars['DateTime']>
/** The value must be between the given values */
between?: InputMaybe<ProductDateRange>
/** The value must be equal to the given value */
eq?: InputMaybe<Scalars['DateTime']>
}
/** Range operator for DateTime fields */
export type ProductDateRange = {
/** The end of the date range */
end: Scalars['DateTime']
/** The start of the date range */
start: Scalars['DateTime']
}
/** A connection edge in which each node is a `Product` object */
export type ProductEdge = {
__typename?: 'ProductEdge'
@ -5183,6 +5222,11 @@ export type ProductVariantPricesInput = {
price?: InputMaybe<Scalars['Float']>
}
export type Profile = {
__typename?: 'Profile'
addressBook?: Maybe<Array<Maybe<Address>>>
}
/** Input for the `publishNavigationChanges` mutation */
export type PublishNavigationChangesInput = {
/** An optional string identifying the mutation call, which will be returned in the response payload */
@ -5590,8 +5634,10 @@ export type QueryProductArgs = {
export type QueryProductsArgs = {
after?: InputMaybe<Scalars['ConnectionCursor']>
before?: InputMaybe<Scalars['ConnectionCursor']>
createdAt?: InputMaybe<ProductDateOperators>
first?: InputMaybe<Scalars['ConnectionLimitInt']>
isArchived?: InputMaybe<Scalars['Boolean']>
isExactMatch?: InputMaybe<Scalars['Boolean']>
isVisible?: InputMaybe<Scalars['Boolean']>
last?: InputMaybe<Scalars['ConnectionLimitInt']>
metafieldKey?: InputMaybe<Scalars['String']>
@ -5605,6 +5651,7 @@ export type QueryProductsArgs = {
sortBy?: InputMaybe<ProductSortByField>
sortOrder?: InputMaybe<SortOrder>
tagIds?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>
updatedAt?: InputMaybe<ProductDateOperators>
}
/** Queries return all requested data, without any side effects */
@ -5719,6 +5766,7 @@ export type QueryTagArgs = {
export type QueryTagsArgs = {
after?: InputMaybe<Scalars['ConnectionCursor']>
before?: InputMaybe<Scalars['ConnectionCursor']>
createdAt?: InputMaybe<TagDateOperators>
excludedTagIds?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>
filter?: InputMaybe<Scalars['String']>
first?: InputMaybe<Scalars['ConnectionLimitInt']>
@ -5730,6 +5778,7 @@ export type QueryTagsArgs = {
shouldIncludeInvisible?: InputMaybe<Scalars['Boolean']>
sortBy?: InputMaybe<TagSortByField>
sortOrder?: InputMaybe<SortOrder>
updatedAt?: InputMaybe<TagDateOperators>
}
/** Queries return all requested data, without any side effects */
@ -6890,6 +6939,26 @@ export type TagConnection = {
totalCount: Scalars['Int']
}
/** Operators for filtering on a DateTime field */
export type TagDateOperators = {
/** The value must be greater than or equal to the given value */
after?: InputMaybe<Scalars['DateTime']>
/** The value must be greater than the given value */
before?: InputMaybe<Scalars['DateTime']>
/** The value must be between the given values */
between?: InputMaybe<ProductDateRange>
/** The value must be equal to the given value */
eq?: InputMaybe<Scalars['DateTime']>
}
/** Range operator for DateTime fields */
export type TagDateRange = {
/** The end of the date range */
end: Scalars['DateTime']
/** The start of the date range */
start: Scalars['DateTime']
}
/** A connection edge in which each node is a `Tag` object */
export type TagEdge = NodeEdge & {
__typename?: 'TagEdge'
@ -8001,127 +8070,6 @@ export type CatalogItemsQuery = {
} | null
}
export type PrimaryShopQueryVariables = Exact<{
language?: Scalars['String']
}>
export type PrimaryShopQuery = {
__typename?: 'Query'
primaryShop?: {
__typename?: 'Shop'
_id: string
description?: string | null
name: string
currency: { __typename?: 'Currency'; code: string }
defaultNavigationTree?: {
__typename?: 'NavigationTree'
_id: string
shopId: string
name: string
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
} | null> | null
} | null> | null
} | null> | null
} | null
} | null
}
export type NavigationTreeFragmentFragment = {
__typename?: 'NavigationTree'
_id: string
shopId: string
name: string
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
} | null> | null
} | null> | null
} | null> | null
}
export type NavigationItemFieldsFragment = {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
}
export type GetProductBySlugQueryVariables = Exact<{
slug: Scalars['String']
}>
@ -8130,6 +8078,7 @@ export type GetProductBySlugQuery = {
__typename?: 'Query'
catalogItemProduct?: {
__typename?: 'CatalogItemProduct'
_id: string
product?: {
__typename?: 'CatalogProduct'
_id: string
@ -8144,7 +8093,6 @@ export type GetProductBySlugQuery = {
metafields?: Array<{
__typename?: 'Metafield'
description?: string | null
key?: string | null
namespace?: string | null
scope?: string | null
value?: string | null
@ -8324,6 +8272,133 @@ export type GetProductBySlugQuery = {
} | null
}
export type PrimaryShopQueryVariables = Exact<{
language?: Scalars['String']
}>
export type PrimaryShopQuery = {
__typename?: 'Query'
primaryShop?: {
__typename?: 'Shop'
_id: string
description?: string | null
name: string
currency: { __typename?: 'Currency'; code: string }
defaultNavigationTree?: {
__typename?: 'NavigationTree'
_id: string
shopId: string
name: string
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
_id: string
shopId: string
createdAt: any
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
} | null> | null
} | null> | null
} | null> | null
} | null
} | null
}
export type NavigationTreeFragmentFragment = {
__typename?: 'NavigationTree'
_id: string
shopId: string
name: string
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
items?: Array<{
__typename?: 'NavigationTreeItem'
navigationItem: {
__typename?: 'NavigationItem'
_id: string
shopId: string
createdAt: any
data?: {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
} | null
}
} | null> | null
} | null> | null
} | null> | null
}
export type NavigationItemFieldsFragment = {
__typename?: 'NavigationItemData'
contentForLanguage?: string | null
classNames?: string | null
url?: string | null
isUrlRelative?: boolean | null
shouldOpenInNewWindow?: boolean | null
}
export type GetShopCurrencyQueryVariables = Exact<{
id: Scalars['ID']
}>

View File

@ -1190,6 +1190,71 @@ input AuthenticateParamsInput {
user: UserInput
}
"""
Represents a single user partial account
"""
type BasicAccount implements Node {
"""
The account ID
"""
_id: ID!
"""
Flag to indicate if the account accepts marketing emails
"""
acceptsMarketing: Boolean
"""
List of shop Ids
"""
adminUIShopIds: [String]
"""
The date and time at which this account was created
"""
createdAt: DateTime
"""
Email record associated with the account
"""
emails: [EmailRecord]
"""
List of group Ids to which the account belongs
"""
groups: [String]
"""
The full name of the person this account represents, if known
"""
name: String
"""
List of shipping/billing addresses
"""
profile: [Profile]
"""
ID of shop
"""
shopId: String
"""
Account creation state
"""
state: String
"""
The date and time at which this account was last updated
"""
updatedAt: DateTime
"""
ID of user
"""
userId: String
}
"""
A single calculated tax for a cart, order group, cart item, or order item
"""
@ -2641,6 +2706,11 @@ input CreateAccountInput {
"""
bio: String
"""
An optional string identifying the mutation call, which will be returned in the response payload
"""
clientMutationId: String
"""
Email record to create account with
"""
@ -2679,7 +2749,7 @@ type CreateAccountPayload {
"""
The added account
"""
account: Account
account: BasicAccount
"""
The same string you sent with the mutation params, for matching mutation calls with their responses
@ -3172,6 +3242,8 @@ type CreateShopPayload {
Input for the createStripePaymentIntent mutation
"""
input CreateStripePaymentIntentInput {
"""
"""
cartId: String!
"""
@ -3183,6 +3255,9 @@ input CreateStripePaymentIntentInput {
An optional string identifying the mutation call, which will be returned in the response payload
"""
clientMutationId: String
"""
"""
shopId: String!
}
@ -3194,6 +3269,9 @@ type CreateStripePaymentIntentPayload {
The same string you sent with the mutation params, for matching mutation calls with their responses
"""
clientMutationId: String
"""
"""
paymentIntentClientSecret: String
}
@ -4191,6 +4269,11 @@ type EmailJob {
"""
_id: ID!
"""
The date and time of the creation of the e-mail job
"""
createdAt: DateTime!
"""
The data of the e-mail
"""
@ -4202,9 +4285,14 @@ type EmailJob {
status: String!
"""
The date and time of the last update to the e-mail job
To be deprecated. Use updatedAt instead. The date and time of the last update to the e-mail job.
"""
updated: DateTime!
"""
The date and time of the last update to the e-mail job
"""
updatedAt: DateTime!
}
"""
@ -4827,6 +4915,8 @@ input GlobalSettingsUpdates {
doNotUse: String
}
"""
"""
input GrantOrRevokeAdminUIAccessInput {
"""
The account ID to update
@ -4844,6 +4934,8 @@ input GrantOrRevokeAdminUIAccessInput {
shopId: String!
}
"""
"""
type GrantOrRevokeAdminUIAccessPayload {
"""
The up to date account object
@ -8474,6 +8566,46 @@ type ProductConnection {
totalCount: Int!
}
"""
Operators for filtering on a DateTime field
"""
input ProductDateOperators {
"""
The value must be greater than or equal to the given value
"""
after: DateTime
"""
The value must be greater than the given value
"""
before: DateTime
"""
The value must be between the given values
"""
between: ProductDateRange
"""
The value must be equal to the given value
"""
eq: DateTime
}
"""
Range operator for DateTime fields
"""
input ProductDateRange {
"""
The end of the date range
"""
end: DateTime!
"""
The start of the date range
"""
start: DateTime!
}
"""
A connection edge in which each node is a `Product` object
"""
@ -9030,6 +9162,14 @@ input ProductVariantPricesInput {
price: Float
}
"""
"""
type Profile {
"""
"""
addressBook: [Address]
}
"""
Input for the `publishNavigationChanges` mutation
"""
@ -9961,6 +10101,11 @@ type Query {
"""
before: ConnectionCursor
"""
Filter by created timestamp
"""
createdAt: ProductDateOperators
"""
Return at most this many results. This parameter may be used with either `after` or `offset` parameters.
"""
@ -9971,6 +10116,11 @@ type Query {
"""
isArchived: Boolean
"""
Flag to set metafields search method. Default value false, performs a fuzzy search. Explicitly set it to true to perform exact match.
"""
isExactMatch: Boolean = false
"""
Filter by visibility
"""
@ -9982,12 +10132,12 @@ type Query {
last: ConnectionLimitInt
"""
Filter by metafield key
Filter by metafield key using `regex` match. To get specific searches send the argument as a regex pattern
"""
metafieldKey: String
"""
Filter by metafield value
Filter by metafield value using `regex` match. To get specific searches send the argument as a regex pattern
"""
metafieldValue: String
@ -10035,6 +10185,11 @@ type Query {
List of tag ids to filter by
"""
tagIds: [ID]
"""
Filter by updated at timestamp
"""
updatedAt: ProductDateOperators
): ProductConnection
"""
@ -10202,6 +10357,9 @@ type Query {
"""
shopId: ID!
): ShopSettings!
"""
"""
shops(
"""
Return only results that come after this cursor. Use this with `first` to specify the number of results to return.
@ -10379,6 +10537,11 @@ type Query {
"""
before: ConnectionCursor
"""
Filter by created timestamp
"""
createdAt: TagDateOperators
"""
Tags to exclude from results
"""
@ -10433,6 +10596,11 @@ type Query {
Return results sorted in this order
"""
sortOrder: SortOrder = asc
"""
Filter by updated at timestamp
"""
updatedAt: TagDateOperators
): TagConnection
"""
@ -12631,6 +12799,46 @@ type TagConnection {
totalCount: Int!
}
"""
Operators for filtering on a DateTime field
"""
input TagDateOperators {
"""
The value must be greater than or equal to the given value
"""
after: DateTime
"""
The value must be greater than the given value
"""
before: DateTime
"""
The value must be between the given values
"""
between: ProductDateRange
"""
The value must be equal to the given value
"""
eq: DateTime
}
"""
Range operator for DateTime fields
"""
input TagDateRange {
"""
The end of the date range
"""
end: DateTime!
"""
The start of the date range
"""
start: DateTime!
}
"""
A connection edge in which each node is a `Tag` object
"""
@ -13282,6 +13490,8 @@ type UpdateAddressValidationRulePayload {
clientMutationId: String
}
"""
"""
input UpdateAdminUIAccessInput {
"""
The account IDs to update
@ -13299,6 +13509,8 @@ input UpdateAdminUIAccessInput {
shopIds: [String]!
}
"""
"""
type UpdateAdminUIAccessPayload {
"""
The up to date account objects
@ -13581,6 +13793,8 @@ input UpdateGroupInput {
slug: String
}
"""
"""
input UpdateGroupsForAccountsInput {
"""
The account IDs
@ -13598,6 +13812,8 @@ input UpdateGroupsForAccountsInput {
groupIds: [ID]!
}
"""
"""
type UpdateGroupsForAccountsPayload {
"""
The accounts that were modified
@ -14401,6 +14617,8 @@ input UserInput {
username: String
}
"""
"""
type Vendor {
"""
The name of the vendor

View File

@ -1,37 +1,69 @@
import { normalizeCart } from '../../../utils/normalize'
import { normalizeCart, normalizeProduct } from '../../../utils/normalize'
import getCartCookie from '../../utils/get-cart-cookie'
import addCartItemsMutation from '../../mutations/add-cart-item'
import createCartMutation from '../../mutations/create-cart'
import getProductQuery from '../../queries/get-catalog-product-item-query'
import getPrimaryShopQuery from '../../queries/get-primary-shop-query'
import type { CartEndpoint } from '.'
import { PrimaryShopQuery } from '../../../../schema'
const addItem: CartEndpoint['handlers']['addItem'] = async ({
res,
body: { cartId, item },
config,
req: { cookies },
}) => {
if (!item) {
return res.status(400).json({
return {
data: null,
errors: [{ message: 'Missing item' }],
})
}
}
const {
data: { primaryShop },
} = await config.fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (!primaryShop?._id) {
return {
data: null,
}
}
const {
data: { catalogItemProduct },
} = await config.fetch(getProductQuery, {
variables: { slug: item.productId! },
})
const product = normalizeProduct(catalogItemProduct)
const selectedVariant = product.variants.find(
({ id }) => id === item.variantId
)
if (!selectedVariant) {
return {
data: null,
errors: [{ message: 'Invalid product or variant' }],
}
}
if (!item.quantity) item.quantity = 1
const variables = {
input: {
shopId: config.shopId,
shopId: primaryShop._id,
items: [
{
productConfiguration: {
productId: item.productId,
productId: catalogItemProduct.product.productId,
productVariantId: item.variantId,
},
quantity: item.quantity,
price: {
amount: item.variant?.price,
currencyCode: item.currencyCode,
amount: selectedVariant?.price?.value || 0,
currencyCode: product?.price.currencyCode,
},
},
],
@ -42,20 +74,23 @@ const addItem: CartEndpoint['handlers']['addItem'] = async ({
const {
data: { createCart },
} = await config.fetch(createCartMutation, { variables })
res.setHeader('Set-Cookie', [
getCartCookie(
config.cartCookie,
createCart.cart._id,
config.cartCookieMaxAge
),
getCartCookie(
config.anonymousCartTokenCookie,
createCart.token,
config.cartCookieMaxAge
),
])
return res.status(200).json({ data: normalizeCart(createCart.cart) })
return {
data: normalizeCart(createCart.cart),
headers: {
'Set-Cookie': [
getCartCookie(
config.cartCookie,
createCart.cart._id,
config.cartCookieMaxAge
),
getCartCookie(
config.anonymousCartTokenCookie,
createCart.token,
config.cartCookieMaxAge
),
],
},
}
}
const {
@ -65,12 +100,12 @@ const addItem: CartEndpoint['handlers']['addItem'] = async ({
input: {
items: variables.input.items,
cartId,
cartToken: cookies[config.anonymousCartTokenCookie],
cartToken: cookies.get(config.anonymousCartTokenCookie)?.value,
},
},
})
return res.status(200).json({ data: normalizeCart(addCartItems.cart) })
return { data: normalizeCart(addCartItems.cart) }
}
export default addItem

View File

@ -4,29 +4,28 @@ import type { CartEndpoint } from '.'
// Return current cart info
const getCart: CartEndpoint['handlers']['getCart'] = async ({
res,
req: { cookies },
body: { cartId },
config,
}) => {
if (cartId && cookies[config.anonymousCartTokenCookie]) {
if (cartId && cookies.get(config.anonymousCartTokenCookie)?.value) {
const {
data: { cart: rawAnonymousCart },
} = await config.fetch(getAnonymousCartQuery, {
variables: {
cartId,
cartToken: cookies[config.anonymousCartTokenCookie],
cartToken: cookies.get(config.anonymousCartTokenCookie)?.value,
},
})
return res.status(200).json({
return {
data: rawAnonymousCart ? normalizeCart(rawAnonymousCart) : null,
})
}
}
res.status(200).json({
return {
data: null,
})
}
}
export default getCart

View File

@ -4,16 +4,15 @@ import removeCartItemsMutation from '../../mutations/remove-cart-item'
import type { CartEndpoint } from '.'
const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
res,
body: { cartId, itemId },
config,
req: { cookies },
}) => {
if (!cartId || !itemId) {
return res.status(400).json({
return {
data: null,
errors: [{ message: 'Invalid request' }],
})
}
}
const {
@ -23,17 +22,21 @@ const removeItem: CartEndpoint['handlers']['removeItem'] = async ({
input: {
cartId,
cartItemIds: [itemId],
cartToken: cookies[config.anonymousCartTokenCookie],
cartToken: cookies.get(config.anonymousCartTokenCookie)?.value,
},
},
})
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
res.status(200).json({ data: normalizeCart(removeCartItems.cart) })
return {
data: normalizeCart(removeCartItems.cart),
headers: {
'Set-Cookie': getCartCookie(
config.cartCookie,
cartId,
config.cartCookieMaxAge
),
},
}
}
export default removeItem

View File

@ -4,16 +4,15 @@ import updateCartItemsQuantityMutation from '../../mutations/update-cart-item-qu
import type { CartEndpoint } from '.'
const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
res,
body: { cartId, itemId, item },
config,
req: { cookies },
}) => {
if (!cartId || !itemId || !item) {
return res.status(400).json({
data: null,
return {
data: undefined,
errors: [{ message: 'Invalid request' }],
})
}
}
const {
@ -22,18 +21,24 @@ const updateItem: CartEndpoint['handlers']['updateItem'] = async ({
variables: {
updateCartItemsQuantityInput: {
cartId,
cartToken: cookies[config.anonymousCartTokenCookie],
cartToken: cookies.get(config.anonymousCartTokenCookie)?.value,
items: [{ cartItemId: itemId, quantity: item.quantity }],
},
},
})
// Update the cart cookie
res.setHeader(
'Set-Cookie',
getCartCookie(config.cartCookie, cartId, config.cartCookieMaxAge)
)
res.status(200).json({ data: normalizeCart(updateCartItemsQuantity.cart) })
return {
data: normalizeCart(updateCartItemsQuantity.cart),
headers: {
'Set-Cookie': getCartCookie(
config.cartCookie,
cartId,
config.cartCookieMaxAge
),
},
}
}
export default updateItem

View File

@ -1,12 +1,14 @@
import type { ProductsEndpoint } from './products'
import getSearchVariables from '../../utils/get-search-variables'
import getSortVariables from '../../utils/get-sort-variables'
import { CatalogItemsQueryVariables } from '../../../../schema'
import getShopCurrencyQuery from '../../queries/get-shop-currency-query'
import {
CatalogItemsQueryVariables,
PrimaryShopQuery,
} from '../../../../schema'
import getPrimaryShopQuery from '../../queries/get-primary-shop-query'
const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
body: { brandId, search, sort, categoryId },
res,
config,
commerce,
}) => {
@ -15,21 +17,21 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
sortParams = null
}
let currency: string | null = null
const {
data: { primaryShop },
} = await config.fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (sortParams?.sortBy === 'minPrice') {
const {
if (!primaryShop?._id) {
return {
data: {
shop: {
currency: { code },
},
products: [],
found: false
},
} = await config.fetch(getShopCurrencyQuery, {
variables: { id: config.shopId },
})
currency = code
}
}
let currency: string | null = primaryShop.currency.code
const { products } = await commerce.getAllProducts({
variables: {
...getSearchVariables({ brandId, search, categoryId }),
@ -45,12 +47,12 @@ const getProducts: ProductsEndpoint['handlers']['getProducts'] = async ({
config,
})
res.status(200).json({
return {
data: {
products,
found: !!products.length,
},
})
}
}
export default getProducts

View File

@ -1 +1,3 @@
export default function noopApi(...args: any[]): void {}
export default function getCheckout(..._args: any[]) {
return Promise.resolve({ data: null })
}

View File

@ -1,42 +1,67 @@
import { LineItem } from '../../../types/cart'
import placeOrder from '../../mutations/place-order'
import setEmailOnAnonymousCart from '../../mutations/set-email-on-anonymous-cart'
import getAnonymousCartQuery from '../../queries/get-anonymous-cart'
import getCartCookie from '../../utils/get-cart-cookie'
import type { CheckoutEndpoint } from '.'
import { normalizeCheckout, normalizeCart } from '../../../utils/normalize'
import { PrimaryShopQuery } from '../../../../schema'
import getPrimaryShopQuery from '../../queries/get-primary-shop-query'
const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({
res,
body: { item, cartId },
config: { fetch, shopId, anonymousCartTokenCookie, cartCookie },
body: { cartId },
config: { fetch, anonymousCartTokenCookie, cartCookie },
req: { cookies },
}) => {
const {
data: { primaryShop },
} = await fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (!primaryShop?._id) {
return {
data: null,
}
}
await fetch(setEmailOnAnonymousCart, {
variables: {
input: {
cartId,
cartToken: cookies[anonymousCartTokenCookie],
cartToken: cookies.get(anonymousCartTokenCookie)?.value,
email: 'opencommerce@test.com',
},
},
})
const {
data: { cart: rawAnonymousCart },
} = await fetch(getAnonymousCartQuery, {
variables: {
cartId,
cartToken: cookies.get(anonymousCartTokenCookie)?.value,
},
})
const checkout = normalizeCheckout(rawAnonymousCart.checkout)
const cart = normalizeCart(rawAnonymousCart)
const { data } = await fetch(placeOrder, {
variables: {
input: {
payments: {
data: { fullName: 'Open Commerce Demo Site' },
amount: item.checkout.cart.checkout.summary.total.amount,
amount: checkout.summary.total.amount,
method: 'iou_example',
},
order: {
cartId,
currencyCode: item.checkout.cart.currency.code,
currencyCode: cart.currency.code,
email: 'opencommerce@test.com',
shopId,
shopId: primaryShop._id,
fulfillmentGroups: {
shopId,
data: item.checkout.cart.checkout.fulfillmentGroups[0].data,
items: item.checkout.cart.lineItems.map((item: LineItem) => ({
shopId: primaryShop._id,
data: checkout.fulfillmentGroups[0].data,
items: cart.lineItems.map((item: LineItem) => ({
price: item.variant.price,
quantity: item.quantity,
productConfiguration: {
@ -44,22 +69,26 @@ const submitCheckout: CheckoutEndpoint['handlers']['submitCheckout'] = async ({
productVariantId: item.variantId,
},
})),
type: item.checkout.cart.checkout.fulfillmentGroups[0].type,
type: checkout.fulfillmentGroups[0].type,
selectedFulfillmentMethodId:
item.checkout.cart.checkout.fulfillmentGroups[0]
.selectedFulfillmentOption.fulfillmentMethod._id,
checkout.fulfillmentGroups[0].selectedFulfillmentOption
?.fulfillmentMethod?._id,
},
},
},
},
})
res.setHeader('Set-Cookie', [
getCartCookie(cartCookie),
getCartCookie(anonymousCartTokenCookie),
])
res.status(200).json({ data: null, errors: [] })
return {
data: null,
errors: [],
headers: {
'Set-Cookie': [
getCartCookie(cartCookie),
getCartCookie(anonymousCartTokenCookie),
],
},
}
}
export default submitCheckout

View File

@ -4,17 +4,16 @@ import updateFulfillmentOptions from '../../../mutations/update-fulfillment-opti
import selectFulfillmentOptions from '../../../mutations/select-fulfillment-options'
const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
res,
body: { item, cartId },
config: { fetch, anonymousCartTokenCookie },
req: { cookies },
}) => {
// Return an error if no cart is present
if (!cartId) {
return res.status(400).json({
return {
data: null,
errors: [{ message: 'Cookie not found' }],
})
}
}
// Register address
@ -35,7 +34,6 @@ const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
region: item.city || 'LA',
},
cartId,
cartToken: cookies[anonymousCartTokenCookie],
},
},
})
@ -56,7 +54,7 @@ const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
variables: {
input: {
cartId,
cartToken: cookies[anonymousCartTokenCookie],
cartToken: cookies.get(anonymousCartTokenCookie)?.value,
fulfillmentGroupId:
updateFulfillmentOptionsForGroup.cart.checkout.fulfillmentGroups[0]
._id,
@ -67,7 +65,7 @@ const addItem: CustomerAddressEndpoint['handlers']['addItem'] = async ({
},
})
return res.status(200).json({ data: null, errors: [] })
return { data: null, errors: [] }
}
export default addItem

View File

@ -1,9 +1,8 @@
import type { CustomerAddressEndpoint } from '.'
const getCards: CustomerAddressEndpoint['handlers']['getAddresses'] = async ({
res,
}) => {
return res.status(200).json({ data: null, errors: [] })
}
const getCards: CustomerAddressEndpoint['handlers']['getAddresses'] =
async ({}) => {
return { data: null, errors: [] }
}
export default getCards

View File

@ -1,7 +1,4 @@
import type {
CustomerAddressSchema,
CustomerAddressTypes,
} from '../../../../types/customer/address'
import type { CustomerAddressSchema } from '../../../../types/customer/address'
import type { OpenCommerceAPI } from '../../..'
import { GetAPISchema, createEndpoint } from '@vercel/commerce/api'
@ -14,7 +11,7 @@ import removeItem from './remove-item'
export type CustomerAddressAPI = GetAPISchema<
OpenCommerceAPI,
CustomerAddressSchema<CustomerAddressTypes>
CustomerAddressSchema
>
export type CustomerAddressEndpoint = CustomerAddressAPI['endpoint']

View File

@ -1,9 +1,8 @@
import type { CustomerAddressEndpoint } from '.'
const removeItem: CustomerAddressEndpoint['handlers']['removeItem'] = async ({
res,
}) => {
return res.status(200).json({ data: null, errors: [] })
}
const removeItem: CustomerAddressEndpoint['handlers']['removeItem'] =
async ({}) => {
return { data: null, errors: [] }
}
export default removeItem

View File

@ -1,34 +1,7 @@
import selectFulfillmentOptions from '../../../mutations/select-fulfillment-options'
import type { CustomerAddressEndpoint } from '.'
const updateItem: CustomerAddressEndpoint['handlers']['updateItem'] = async ({
res,
body: { item, cartId },
config: { fetch, anonymousCartTokenCookie },
req: { cookies },
}) => {
// Return an error if no cart is present
if (!cartId) {
return res.status(400).json({
data: null,
errors: [{ message: 'Cookie not found' }],
})
}
if (item.shippingMethodId) {
await fetch(selectFulfillmentOptions, {
variables: {
input: {
cartId,
cartToken: cookies[anonymousCartTokenCookie],
fulfillmentGroupId: item.fulfillmentGroupId,
fulfillmentMethodId: item.shippingMethodId,
},
},
})
}
return res.status(200).json({ data: null, errors: [] })
const updateItem: CustomerAddressEndpoint['handlers']['updateItem'] = () => {
return Promise.resolve({ data: null })
}
export default updateItem

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -0,0 +1,19 @@
import { OpenCommerceAPI, Provider } from '../index'
import createEndpoints from '@vercel/commerce/api/endpoints'
import cart from './cart'
import checkout from './checkout'
import customerAddress from './customer/address'
import products from './catalog/products'
const endpoints = {
cart,
checkout,
'customer/address': customerAddress,
'catalog/products': products,
}
export default function opencommerceAPI(commerce: OpenCommerceAPI) {
return createEndpoints<Provider>(commerce, endpoints)
}

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -1 +0,0 @@
export default function noopApi(...args: any[]): void {}

View File

@ -5,10 +5,21 @@ import {
} from '@vercel/commerce/api'
import createFetchGraphqlApi from './utils/fetch-grapql-api'
import * as operations from './operations'
import getAllPages from './operations/get-all-pages'
import getPage from './operations/get-page'
import getSiteInfo from './operations/get-site-info'
import getAllProductPaths from './operations/get-all-product-paths'
import getAllProducts from './operations/get-all-products'
import getProduct from './operations/get-product'
import {
OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE,
OPENCOMMERCE_CART_TOKEN,
API_URL,
} from '../const'
const API_URL = process.env.OPENCOMMERCE_STOREFRONT_API_URL
const SHOP_ID = process.env.OPENCOMMERCE_PRIMARY_SHOP_ID
export interface OpenCommerceConfig extends CommerceAPIConfig {
anonymousCartTokenCookie: string
}
if (!API_URL) {
throw new Error(
@ -16,24 +27,27 @@ if (!API_URL) {
)
}
export interface OpenCommerceConfig extends CommerceAPIConfig {
shopId: string
anonymousCartTokenCookie: string
}
const ONE_DAY = 60 * 60 * 24
const config: OpenCommerceConfig = {
commerceUrl: API_URL,
apiToken: '',
shopId: SHOP_ID ?? '',
customerCookie: 'opencommerce_customerToken',
cartCookie: 'opencommerce_cartId',
cartCookie: OPENCOMMERCE_CART_TOKEN,
cartCookieMaxAge: ONE_DAY * 30,
anonymousCartTokenCookie: 'opencommerce_anonymousCartToken',
anonymousCartTokenCookie: OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE,
fetch: createFetchGraphqlApi(() => getCommerceApi().getConfig()),
}
const operations = {
getAllPages,
getPage,
getSiteInfo,
getAllProductPaths,
getAllProducts,
getProduct,
}
export const provider = { config, operations }
export type Provider = typeof provider

View File

@ -6,12 +6,14 @@ import type {
CatalogItemsQuery,
CatalogItemsQueryVariables,
CatalogItemProduct,
PrimaryShopQuery,
} from '../../../schema'
import type { GetAllProductPathsOperation } from '../../types/product'
import type { RecursivePartial, RecursiveRequired } from '../utils/types'
import filterEdges from '../utils/filter-edges'
import { OpenCommerceConfig, Provider } from '..'
import getAllProductPathsQuery from '../queries/get-all-product-paths-query'
import getPrimaryShopQuery from '../queries/get-primary-shop-query'
export default function getAllProductPathsOperation({
commerce,
@ -39,14 +41,25 @@ export default function getAllProductPathsOperation({
variables?: CatalogItemsQueryVariables
config?: OpenCommerceConfig
} = {}): Promise<T['data']> {
const { fetch, shopId } = commerce.getConfig(config)
const { fetch } = commerce.getConfig(config)
const {
data: { primaryShop },
} = await fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (!primaryShop?._id) {
return {
products: [],
}
}
// RecursivePartial forces the method to check for every prop in the data, which is
// required in case there's a custom `query`
const { data } = await fetch<
RecursivePartial<CatalogItemsQuery>,
CatalogItemsQueryVariables
>(query, {
variables: { ...variables, shopIds: [shopId] },
variables: { ...variables, shopIds: [primaryShop._id] },
})
const products = data.catalogItems?.edges

View File

@ -4,12 +4,14 @@ import {
CatalogItemProduct,
CatalogItemsQuery,
CatalogItemsQueryVariables,
PrimaryShopQuery,
} from '../../../schema'
import catalogItemsQuery from '../queries/get-all-products-query'
import type { OpenCommerceConfig, Provider } from '..'
import { normalizeProduct } from '../../utils/normalize'
import { RecursivePartial, RecursiveRequired } from '../utils/types'
import filterEdges from '../utils/filter-edges'
import getPrimaryShopQuery from '../queries/get-primary-shop-query'
export default function getAllProductsOperation({
commerce,
@ -30,14 +32,23 @@ export default function getAllProductsOperation({
config?: Partial<OpenCommerceConfig>
preview?: boolean
} = {}): Promise<T['data']> {
const { fetch, locale, shopId } = commerce.getConfig(config)
const { fetch, locale } = commerce.getConfig(config)
const {
data: { primaryShop },
} = await fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (!primaryShop?._id) {
return {
products: []
}
}
const { data } = await fetch<
RecursivePartial<CatalogItemsQuery>,
CatalogItemsQueryVariables
>(
query,
{ variables: { ...variables, shopIds: [shopId] } },
{ variables: { ...variables, shopIds: [primaryShop._id] } },
{
...(locale && {
headers: {

View File

@ -10,7 +10,7 @@ import {
GetProductBySlugQuery,
GetProductBySlugQueryVariables,
} from '../../../schema'
import getProductQuery from '../queries/get-product-query'
import getProductQuery from '../queries/get-catalog-product-item-query'
export default function getProductOperation({
commerce,

View File

@ -7,9 +7,11 @@ import {
GetAllProductVendorsQuery,
GetTagsQueryVariables,
GetAllProductVendorsQueryVariables,
PrimaryShopQuery,
NavigationTreeItem,
} from '../../../schema'
import getTagsQuery from '../queries/get-tags-query'
import { GetSiteInfoOperation, OCCategory, SiteTypes } from '../../types/site'
import { GetSiteInfoOperation, OCCategory } from '../../types/site'
import {
normalizeCategory,
normalizeNavigation,
@ -42,19 +44,29 @@ export default function getSiteInfoOperation({
config?: Partial<OpenCommerceConfig>
preview?: boolean
} = {}): Promise<T['data']> {
const { fetch, shopId } = commerce.getConfig(cfg)
const { fetch } = commerce.getConfig(cfg)
const [categoriesResponse, vendorsResponse, primaryShopResponse] =
await Promise.all([
await fetch<GetTagsQuery, GetTagsQueryVariables>(getTagsQuery, {
variables: { first: 250, shopId },
}),
await fetch<
GetAllProductVendorsQuery,
GetAllProductVendorsQueryVariables
>(getAllProductVendors, { variables: { shopIds: [shopId] } }),
await fetch(getPrimaryShopQuery),
])
const {
data: { primaryShop },
} = await fetch<PrimaryShopQuery>(getPrimaryShopQuery)
if (!primaryShop?._id) {
return {
categories: [],
brands: [],
navigation: [],
}
}
const [categoriesResponse, vendorsResponse] = await Promise.all([
await fetch<GetTagsQuery, GetTagsQueryVariables>(getTagsQuery, {
variables: { first: 250, shopId: primaryShop._id },
}),
await fetch<
GetAllProductVendorsQuery,
GetAllProductVendorsQueryVariables
>(getAllProductVendors, { variables: { shopIds: [primaryShop._id] } }),
])
const categories = filterEdges(categoriesResponse.data.tags?.edges).map(
(edge) => normalizeCategory(edge.node! as OCCategory)
@ -64,8 +76,9 @@ export default function getSiteInfoOperation({
...new Set(filterEdges(vendorsResponse.data.vendors?.nodes)),
].map(normalizeVendors)
const navigationItems =
primaryShopResponse.data.primaryShop.defaultNavigationTree.items ?? []
const navigationItems = filterEdges(
primaryShop?.defaultNavigationTree?.items
) as NavigationTreeItem[]
return {
categories,

View File

@ -0,0 +1,181 @@
const getProductQuery = /* GraphQL */ `
query getProductBySlug($slug: String!) {
catalogItemProduct(slugOrId: $slug) {
_id
product {
_id
productId
title
slug
description
vendor
isLowQuantity
isSoldOut
isBackorder
metafields {
description
namespace
scope
value
valueType
}
pricing {
currency {
code
}
displayPrice
minPrice
maxPrice
}
shop {
currency {
code
}
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
tags {
nodes {
name
slug
position
}
}
variants {
_id
variantId
attributeLabel
title
optionTitle
index
pricing {
compareAtPrice {
displayAmount
}
price
currency {
code
}
displayPrice
}
canBackorder
inventoryAvailableToSell
isBackorder
isSoldOut
isLowQuantity
options {
_id
variantId
attributeLabel
title
index
pricing {
compareAtPrice {
displayAmount
}
price
currency {
code
}
displayPrice
}
optionTitle
canBackorder
inventoryAvailableToSell
isBackorder
isSoldOut
isLowQuantity
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
metafields {
description
key
namespace
scope
value
valueType
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
}
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
metafields {
description
key
namespace
scope
value
valueType
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
}
}
}
}
`
export default getProductQuery

View File

@ -30,6 +30,9 @@ const getPrimaryShopQuery = /* GraphQL */ `
}
items {
navigationItem {
_id
shopId
createdAt
data {
...NavigationItemFields
}

View File

@ -1,181 +0,0 @@
const getProductQuery = /* GraphQL */ `
query getProductBySlug($slug: String!) {
catalogItemProduct(slugOrId: $slug) {
product {
_id
productId
title
slug
description
vendor
isLowQuantity
isSoldOut
isBackorder
metafields {
description
key
namespace
scope
value
valueType
}
pricing {
currency {
code
}
displayPrice
minPrice
maxPrice
}
shop {
currency {
code
}
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
tags {
nodes {
name
slug
position
}
}
variants {
_id
variantId
attributeLabel
title
optionTitle
index
pricing {
compareAtPrice {
displayAmount
}
price
currency {
code
}
displayPrice
}
canBackorder
inventoryAvailableToSell
isBackorder
isSoldOut
isLowQuantity
options {
_id
variantId
attributeLabel
title
index
pricing {
compareAtPrice {
displayAmount
}
price
currency {
code
}
displayPrice
}
optionTitle
canBackorder
inventoryAvailableToSell
isBackorder
isSoldOut
isLowQuantity
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
metafields {
description
key
namespace
scope
value
valueType
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
}
media {
priority
productId
variantId
URLs {
thumbnail
small
medium
large
original
}
}
metafields {
description
key
namespace
scope
value
valueType
}
primaryImage {
URLs {
large
medium
original
small
thumbnail
}
priority
productId
variantId
}
}
}
}
}
`
export default getProductQuery

View File

@ -1,11 +0,0 @@
const getShopCurrencyQuery = /* GraphQL */ `
query getShopCurrency($id: ID!) {
shop(id: $id) {
currency {
code
}
}
}
`
export default getShopCurrencyQuery

View File

@ -1,23 +1,27 @@
import { FetcherError } from '@vercel/commerce/utils/errors'
import type { GraphQLFetcher } from '@vercel/commerce/api'
import type { FetchOptions, GraphQLFetcher } from '@vercel/commerce/api'
import type { OpenCommerceConfig } from '../index'
import fetch from './fetch'
const fetchGraphqlApi: (
getConfig: () => OpenCommerceConfig
) => GraphQLFetcher =
(getConfig) =>
async (query: string, { variables, preview } = {}, fetchOptions) => {
async (
query: string,
{ variables } = {},
options?: FetchOptions
): Promise<any> => {
// log.warn(query)
const config = getConfig()
const res = await fetch(config.commerceUrl + (preview ? '/preview' : ''), {
...fetchOptions,
const res = await fetch(config.commerceUrl, {
...options,
method: 'POST',
headers: {
...fetchOptions?.headers,
...options?.headers,
'Content-Type': 'application/json',
},
body: JSON.stringify({
...options?.body,
query,
variables,
}),

View File

@ -3,14 +3,13 @@ import useAddItem, { UseAddItem } from '@vercel/commerce/cart/use-add-item'
import type { AddItemHook } from '@vercel/commerce/types/cart'
import { CommerceError } from '@vercel/commerce/utils/errors'
import { MutationHook } from '@vercel/commerce/utils/types'
import { CartTypes } from '../types/cart'
import useCart from './use-cart'
export default useAddItem as UseAddItem<typeof handler>
export const handler: MutationHook<AddItemHook<CartTypes>> = {
export const handler: MutationHook<AddItemHook> = {
fetchOptions: {
url: '/api/cart',
url: '/api/commerce/cart',
method: 'POST',
},
async fetcher({ input: item, options, fetch }) {
@ -22,7 +21,6 @@ export const handler: MutationHook<AddItemHook<CartTypes>> = {
message: 'The item quantity has to be a valid integer greater than 0',
})
}
const data = await fetch({ ...options, body: { item } })
return data
},

View File

@ -2,13 +2,12 @@ import { useMemo } from 'react'
import { SWRHook } from '@vercel/commerce/utils/types'
import useCart, { UseCart } from '@vercel/commerce/cart/use-cart'
import type { GetCartHook } from '@vercel/commerce/types/cart'
import { CartTypes } from '../types/cart'
export default useCart as UseCart<typeof handler>
export const handler: SWRHook<GetCartHook<CartTypes>> = {
export const handler: SWRHook<GetCartHook> = {
fetchOptions: {
url: '/api/cart',
url: '/api/commerce/cart',
method: 'GET',
},
useHook:

View File

@ -27,7 +27,7 @@ export default useRemoveItem as UseRemoveItem<typeof handler>
export const handler: MutationHook<RemoveItemHook> = {
fetchOptions: {
url: '/api/cart',
url: '/api/commerce/cart',
method: 'DELETE',
},
async fetcher({ input: { itemId }, options, fetch }) {

View File

@ -17,7 +17,7 @@ export default useUpdateItem as UseUpdateItem<typeof handler>
export const handler: MutationHook<UpdateItemHook> = {
fetchOptions: {
url: '/api/cart',
url: '/api/commerce/cart',
method: 'PUT',
},
async fetcher({ input: { itemId, item }, options, fetch }) {

View File

@ -1,6 +1,5 @@
import type { GetCheckoutHook } from '@vercel/commerce/types/checkout'
import { useMemo } from 'react'
import Cookies from 'js-cookie'
import { SWRHook } from '@vercel/commerce/utils/types'
import useCheckout, {
UseCheckout,
@ -8,27 +7,64 @@ import useCheckout, {
import useSubmitCheckout from './use-submit-checkout'
import { useCheckoutContext } from '@components/checkout/context'
import { AddressFields } from '../types/customer/address'
import { useCart } from '../cart'
import { GetCheckoutHook } from '../types/checkout'
import { FulfillmentGroup } from '../types/cart'
import { API_URL, OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE } from '../const'
import getAnonymousCartQuery from '../api/queries/get-anonymous-cart'
import { normalizeCheckout } from '../utils/normalize'
export default useCheckout as UseCheckout<typeof handler>
export const handler: SWRHook<GetCheckoutHook> = {
fetchOptions: {
query: '',
method: '',
query: getAnonymousCartQuery,
url: API_URL,
},
useHook: () =>
function useHook() {
const { data: cart } = useCart()
const shippingTypeMethod =
cart?.checkout?.fulfillmentGroups &&
cart.checkout.fulfillmentGroups.find(
(group) => group?.type === 'shipping'
)
const hasShippingMethods =
!!shippingTypeMethod?.availableFulfillmentOptions?.length
async fetcher({ options, fetch, input: { cartId } }) {
const cartToken = Cookies.get(OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE)
if (cartId && cartToken) {
const { cart: rawAnonymousCart } = await fetch({
...options,
variables: {
cartId,
cartToken: cartToken,
},
})
if (!rawAnonymousCart?.checkout) return null
const checkout = normalizeCheckout(rawAnonymousCart.checkout)
const shippingTypeFulfillment = checkout.fulfillmentGroups.find(
(group) => group.type === 'shipping'
)
const hasShippingMethods =
!!shippingTypeFulfillment?.availableFulfillmentOptions?.length
const shippingGroup = checkout.fulfillmentGroups.find(
(group: FulfillmentGroup) => group?.type === 'shipping'
)
const totalDisplayAmount =
checkout.summary.fulfillmentTotal?.displayAmount || '0'
return {
hasPayment: true,
hasShippingMethods,
shippingGroup,
hasShipping: false,
addressId: 'addressId',
totalDisplayAmount,
}
}
return null
},
useHook: ({ useData }) =>
function useHook(input) {
const submit = useSubmitCheckout()
const { addressFields } = useCheckoutContext()
const { shippingMethodId, ...restAddressFields } =
@ -38,45 +74,38 @@ export const handler: SWRHook<GetCheckoutHook> = {
(fieldValue) => !!fieldValue
)
const totalAmount =
cart?.checkout?.summary.fulfillmentTotal?.displayAmount
const response = useData({
swrOptions: { revalidateOnFocus: false, ...input?.swrOptions },
})
const shippingGroup = cart?.checkout?.fulfillmentGroups.find(
(group: FulfillmentGroup) => group?.type === 'shipping'
)
const response = useMemo(
() => ({
data: {
// example payment plugin does not need payment info
hasPayment: true,
hasShipping: hasEnteredAddress,
hasShippingMethods,
hasSelectedShippingMethod: !!shippingMethodId,
totalAmount,
shippingGroup,
},
}),
[
hasEnteredAddress,
hasShippingMethods,
shippingMethodId,
totalAmount,
shippingGroup,
]
)
return useMemo(
() =>
Object.create(response, {
submit: {
get() {
return useSubmitCheckout
},
enumerable: true,
return useMemo(() => {
if (response.data) {
return {
...response,
data: {
...response.data,
hasShipping: hasEnteredAddress,
hasSelectedShippingMethod: !!shippingMethodId,
},
}),
[response, useSubmitCheckout]
)
submit: () => submit,
isEmpty: response.data.lineItems?.length ?? 0,
}
}
return Object.create(response, {
isEmpty: {
get() {
return response.data?.lineItems?.length ?? 0
},
enumerable: true,
},
submit: {
get() {
return submit
},
enumerable: true,
},
})
}, [response, submit, hasEnteredAddress, shippingMethodId])
},
}

View File

@ -1,6 +1,7 @@
import { useCallback } from 'react'
import type { SubmitCheckoutHook } from '@vercel/commerce/types/checkout'
import { useCheckoutContext } from '@components/checkout/context'
import type { MutationHook } from '@vercel/commerce/utils/types'
import useSubmitCheckout, {
UseSubmitCheckout,
@ -10,7 +11,7 @@ export default useSubmitCheckout as UseSubmitCheckout<typeof handler>
export const handler: MutationHook<SubmitCheckoutHook> = {
fetchOptions: {
url: '/api/checkout',
url: '/api/commerce/checkout',
method: 'POST',
},
async fetcher({ input: item, options, fetch }) {
@ -22,9 +23,21 @@ export const handler: MutationHook<SubmitCheckoutHook> = {
},
useHook: ({ fetch }) =>
function useHook() {
const { addressFields } = useCheckoutContext()
return useCallback(async function onSubmitCheckout(input) {
const data = await fetch({
input,
// dummy data here since OC does not need card data for example payment method
input: {
...input,
card: {
cardHolder: 'Open Commerce',
cardCvc: '123',
cardExpireDate: '03/30',
cardNumber: '123456789',
...addressFields,
},
},
})
return data
}, [])

View File

@ -0,0 +1,4 @@
export const OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE =
'opencommerce_anonymousCartToken'
export const OPENCOMMERCE_CART_TOKEN = 'opencommerce_cartId'
export const API_URL = process.env.NEXT_PUBLIC_OPENCOMMERCE_API_URL

View File

@ -5,13 +5,12 @@ import useAddItem, {
UseAddItem,
} from '@vercel/commerce/customer/address/use-add-item'
import { useCheckoutContext } from '@components/checkout/context'
import { CustomerAddressTypes } from '../../types/customer/address'
export default useAddItem as UseAddItem<typeof handler>
export const handler: MutationHook<AddItemHook<CustomerAddressTypes>> = {
export const handler: MutationHook<AddItemHook> = {
fetchOptions: {
url: '/api/customer/address',
url: '/api/commerce/customer/address',
method: 'POST',
},
async fetcher({ input: item, options, fetch }) {
@ -29,7 +28,7 @@ export const handler: MutationHook<AddItemHook<CustomerAddressTypes>> = {
async function addItem(input) {
await fetch({ input })
setAddressFields({ ...addressFields, ...input })
return undefined
return null
},
[setAddressFields]
)

View File

@ -1,38 +1,51 @@
import type { UpdateItemHook } from '@vercel/commerce/types/customer/address'
import Cookies from 'js-cookie'
import type { MutationHook } from '@vercel/commerce/utils/types'
import { useCallback } from 'react'
import useUpdateItem, {
UseUpdateItem,
} from '@vercel/commerce/customer/address/use-update-item'
import { useCheckoutContext } from '@components/checkout/context'
import { CustomerAddressTypes } from '../../types/customer/address'
import { useCart } from '../../cart'
import selectFulfillmentOptions from '../../api/mutations/select-fulfillment-options'
import { useCheckout } from '../../checkout'
import { UpdateAddressItemHook } from '../../types/customer/address'
import { OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE } from '../../const'
export default useUpdateItem as UseUpdateItem<typeof handler>
export const handler: MutationHook<UpdateItemHook<CustomerAddressTypes>> = {
export const handler: MutationHook<UpdateAddressItemHook> = {
fetchOptions: {
url: '/api/customer/address',
method: 'PUT',
query: selectFulfillmentOptions,
},
async fetcher({ input: { item, itemId }, options, fetch }) {
async fetcher({ input: { item, itemId: cartId }, options, fetch }) {
const cartToken = Cookies.get(OPENCOMMERCE_ANONYMOUS_CART_TOKEN_COOKIE)
if (!cartId) return null
const data = await fetch({
...options,
body: { item, itemId },
variables: {
input: {
cartId,
cartToken,
fulfillmentGroupId: item.fulfillmentGroupId,
fulfillmentMethodId: item.shippingMethodId,
},
},
})
return data
},
useHook: ({ fetch }) =>
function useHook() {
const { data: cart } = useCart()
const { data: checkoutData } = useCheckout()
const { setAddressFields, addressFields } = useCheckoutContext()
return useCallback(
async function updateItem(input) {
const { id, ...rest } = input
const fulfillmentGroupId =
cart?.checkout?.fulfillmentGroups[0]._id || 'groupId'
checkoutData?.shippingGroup?._id || 'groupId'
await fetch({
input: { item: { ...rest, fulfillmentGroupId }, itemId: id },
})
@ -41,7 +54,7 @@ export const handler: MutationHook<UpdateItemHook<CustomerAddressTypes>> = {
shippingMethodId: rest.shippingMethodId,
fulfillmentGroupId,
})
return undefined
return null
},
[setAddressFields]
)

View File

@ -19,7 +19,7 @@ export const handler: MutationHook<AddItemHook> = {
return useCallback(
async function addItem(input) {
setCardFields(input)
return undefined
return null
},
[setCardFields]
)

View File

@ -1,5 +1,6 @@
import type { Fetcher } from '@vercel/commerce/utils/types'
import { FetcherError } from '@vercel/commerce/utils/errors'
import { API_URL } from './const'
async function getText(res: Response) {
try {
@ -18,20 +19,24 @@ async function getError(res: Response) {
}
const fetcher: Fetcher = async ({
url,
method = 'GET',
url = API_URL,
method = 'POST',
variables,
query,
body: bodyObj,
}) => {
const hasBody = Boolean(variables || bodyObj)
const body = hasBody
? JSON.stringify(variables ? { variables } : bodyObj)
? JSON.stringify(variables ? { query, variables } : bodyObj)
: undefined
const headers = hasBody ? { 'Content-Type': 'application/json' } : undefined
const res = await fetch(url!, { method, body, headers })
if (res.ok) {
const { data } = await res.json()
const { data, errors } = await res.json()
if (errors && errors.length) {
throw getError(res)
}
return data
}

View File

@ -3,6 +3,6 @@ const commerce = require('./commerce.config.json')
module.exports = {
commerce,
images: {
domains: [process.env.OPENCOMMERCE_IMAGE_DOMAIN],
domains: [process.env.NEXT_PUBLIC_OPENCOMMERCE_IMAGE_DOMAIN],
},
}

View File

@ -6,7 +6,7 @@ export default useSearch as UseSearch<typeof handler>
export const handler: SWRHook<SearchProductsHook> = {
fetchOptions: {
url: '/api/catalog/products',
url: '/api/commerce/catalog/products',
method: 'GET',
},
async fetcher({

View File

@ -1,10 +1,8 @@
import * as Core from '@vercel/commerce/types/cart'
import {
Checkout as CheckoutSchema,
FulfillmentOption as FulfillmentOptionSchema,
FulfillmentGroup as FulfillmentGroupSchema,
} from '../../schema'
import { ProductVariant } from './product'
export * from '@vercel/commerce/types/cart'
@ -24,19 +22,3 @@ export type Checkout = {
fulfillmentGroups: FulfillmentGroup[]
summary: CheckoutSchema['summary']
}
export type Cart = Core.Cart & {
checkout?: Checkout
}
export type CartItemBody = Core.CartItemBody & {
currencyCode?: string
variant?: ProductVariant
}
export type CartTypes = Core.CartTypes & {
itemBody: CartItemBody
cart?: Cart
}
export type CartSchema = Core.CartSchema<CartTypes>

View File

@ -1 +1,18 @@
export * from '@vercel/commerce/types/checkout'
import {
GetCheckoutHook as CoreGetCheckoutHook,
Checkout,
} from '@vercel/commerce/types/checkout'
import { FulfillmentGroup } from './cart'
export type GetCheckoutHook = Omit<CoreGetCheckoutHook, 'data'> & {
data:
| (Checkout & {
hasShippingMethods?: boolean
hasSelectedShippingMethod?: boolean
totalDisplayAmount?: string
shippingGroup?: FulfillmentGroup
})
| null
}

View File

@ -7,6 +7,18 @@ export type AddressFields = Core.AddressFields & {
fulfillmentGroupId?: string
}
export type CustomerAddressTypes = Core.CustomerAddressTypes & {
fields: AddressFields
export type UpdateAddressItemHook = Omit<
Core.UpdateItemHook,
'input' | 'body' | 'fetcherInput' | 'actionInput'
> & {
input: {
item?: AddressFields
wait?: number
}
body: {
itemId: string
item: AddressFields
}
fetcherInput: { itemId: string; item: AddressFields }
actionInput: AddressFields & { id: string }
}

View File

@ -7,5 +7,5 @@ export type PageTypes = {
page: Page
}
export type GetAllPagesOperation = Core.GetAllPagesOperation<PageTypes>
export type GetPageOperation = Core.GetPageOperation<PageTypes>
export type GetAllPagesOperation = Core.GetAllPagesOperation
export type GetPageOperation = Core.GetPageOperation

View File

@ -1,6 +1,4 @@
import * as Core from '@vercel/commerce/types/product'
export * from '@vercel/commerce/types/product'
export type ProductVariant = Core.ProductVariant & {
price?: number
}
export type ProductVariant = Core.ProductVariant

View File

@ -1,5 +1,5 @@
import { Vendor as QueryVender, TagEdge } from '../../schema'
import { SiteTypes as CoreSiteTypes } from '@vercel/commerce/types/site'
import { Category, Brand } from '@vercel/commerce/types/site'
export * from '@vercel/commerce/types/site'
@ -23,14 +23,10 @@ export type Navigation = {
items?: Navigation[]
}
export type SiteTypes = CoreSiteTypes & {
navigation: Navigation
}
export type GetSiteInfoOperation<T extends SiteTypes = SiteTypes> = {
export type GetSiteInfoOperation = {
data: {
categories: T['category'][]
brands: T['brand'][]
navigation: T['navigation'][]
categories: Category[]
brands: Brand[]
navigation: Navigation[]
}
}

View File

@ -7,7 +7,7 @@ import type {
import {
OCCategory,
Category,
Vendor,
Brand,
OCVendor,
Navigation,
} from '../types/site'
@ -49,18 +49,18 @@ export function normalizeProduct(
} = product
return {
id: productId ?? _id,
id: productNode._id || productId,
name: title ?? '',
description: description ?? '',
slug: slug?.replace(/^\/+|\/+$/g, '') ?? '',
path: slug ?? '',
path: `/${slug}` ?? '/',
sku: sku ?? '',
images: media?.length
? normalizeProductImages(<ImageInfo[]>media, title ?? '')
: [],
...(product.vendor ? { vendor: product.vendor } : {}),
price: {
value: pricing[0]?.minPrice ?? 0,
value: pricing[0]?.price || pricing[0]?.minPrice || 0,
currencyCode: pricing[0]?.currency.code,
},
variants: !!variants
@ -167,7 +167,7 @@ const normalizeProductVariants = (
productVariants.push({
id: variantId ?? '',
price: variantPrice,
price: { value: variantPrice },
options: [normalizeProductOption(variant)],
})
@ -226,13 +226,12 @@ export function normalizeCategory(category: OCCategory): Category {
}
}
export function normalizeVendors({ name }: OCVendor): Vendor {
export function normalizeVendors({ name }: OCVendor): Brand {
return {
node: {
entityId: name ?? '',
name: name ?? '',
path: `brands/${name}`,
},
id: name ?? '',
name: name ?? '',
path: `/${name}`,
slug: `/brands/${name}`,
}
}
@ -246,7 +245,7 @@ export function normalizeCart(cart: OCCart): Cart {
createdAt: cart.createdAt,
currency: {
code: cart.checkout?.summary?.total?.currency.code ?? '',
code: cart.checkout?.summary?.total?.currency.code ?? 'USD',
},
lineItems:
cart.items?.edges?.map((cartItem) =>
@ -257,7 +256,6 @@ export function normalizeCart(cart: OCCart): Cart {
totalPrice: cart.checkout?.summary?.total?.amount ?? 0,
discounts: [],
taxesIncluded: !!cart.checkout?.summary?.taxTotal?.amount,
checkout: cart.checkout ? normalizeCheckout(cart.checkout) : undefined,
}
}
@ -267,7 +265,7 @@ function filterNullValue<T>(
return items?.filter((item: T | null | undefined): item is T => !!item) ?? []
}
function normalizeCheckout(checkout: OCCheckout): Checkout {
export function normalizeCheckout(checkout: OCCheckout): Checkout {
const fulfillmentGroups = filterNullValue(checkout.fulfillmentGroups).map(
(group) => ({
selectedFulfillmentOption: group.selectedFulfillmentOption,
@ -323,7 +321,7 @@ function normalizeLineItem(cartItemEdge: CartItemEdge): LineItem {
price: priceWhenAdded?.amount,
listPrice: compareAtPrice?.amount ?? 0,
},
path: productSlug ?? '',
path: `/${productSlug}` ?? '',
discounts: [],
options: [
{

View File

@ -4,11 +4,7 @@
"module": "esnext",
"outDir": "dist",
"baseUrl": "src",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"declaration": true,
"allowJs": true,
"skipLibCheck": true,
@ -20,12 +16,6 @@
"incremental": true,
"jsx": "react-jsx"
},
"include": [
"src",
"global.d.ts"
],
"exclude": [
"node_modules",
"dist"
]
}
"include": ["src", "global.d.ts"],
"exclude": ["node_modules", "dist"]
}

575
pnpm-lock.yaml generated
View File

@ -257,6 +257,47 @@ importers:
taskr-swc: link:../taskr-swc
typescript: 4.8.3
packages/opencommerce:
specifiers:
'@graphql-codegen/cli': 2.7.0
'@graphql-codegen/schema-ast': ^2.4.1
'@graphql-codegen/typescript': ^2.6.0
'@graphql-codegen/typescript-operations': ^2.4.3
'@taskr/clear': ^1.1.0
'@taskr/esnext': ^1.1.0
'@taskr/watch': ^1.1.0
'@types/node': ^18.0.3
'@types/react': ^18.0.14
'@vercel/commerce': workspace:*
lint-staged: ^13.0.3
next: ^13.0.4
prettier: ^2.7.1
react: ^18.2.0
react-dom: ^18.2.0
taskr: ^1.1.0
taskr-swc: workspace:*
typescript: ^4.7.4
dependencies:
'@vercel/commerce': link:../commerce
devDependencies:
'@graphql-codegen/cli': 2.7.0_bidgzm5cq2du6gnjtweqqjrrn4
'@graphql-codegen/schema-ast': 2.5.1
'@graphql-codegen/typescript': 2.7.3
'@graphql-codegen/typescript-operations': 2.5.3
'@taskr/clear': 1.1.0
'@taskr/esnext': 1.1.0
'@taskr/watch': 1.1.0
'@types/node': 18.7.18
'@types/react': 18.0.20
lint-staged: 13.0.3
next: 13.0.6_biqbaboplfbrettd7655fr4n2y
prettier: 2.7.1
react: 18.2.0
react-dom: 18.2.0_react@18.2.0
taskr: 1.1.0
taskr-swc: link:../taskr-swc
typescript: 4.8.3
packages/ordercloud:
specifiers:
'@taskr/clear': ^1.1.0
@ -615,6 +656,7 @@ importers:
'@vercel/commerce-commercejs': workspace:*
'@vercel/commerce-kibocommerce': workspace:*
'@vercel/commerce-local': workspace:*
'@vercel/commerce-opencommerce': workspace:*
'@vercel/commerce-ordercloud': workspace:*
'@vercel/commerce-saleor': workspace:*
'@vercel/commerce-sfcc': workspace:*
@ -657,6 +699,7 @@ importers:
'@vercel/commerce-commercejs': link:../packages/commercejs
'@vercel/commerce-kibocommerce': link:../packages/kibocommerce
'@vercel/commerce-local': link:../packages/local
'@vercel/commerce-opencommerce': link:../packages/opencommerce
'@vercel/commerce-ordercloud': link:../packages/ordercloud
'@vercel/commerce-saleor': link:../packages/saleor
'@vercel/commerce-sfcc': link:../packages/sfcc
@ -711,6 +754,34 @@ packages:
'@jridgewell/trace-mapping': 0.3.15
dev: true
/@ardatan/relay-compiler/12.0.0:
resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==}
hasBin: true
peerDependencies:
graphql: '*'
dependencies:
'@babel/core': 7.20.5
'@babel/generator': 7.20.5
'@babel/parser': 7.20.5
'@babel/runtime': 7.19.0
'@babel/traverse': 7.20.5
'@babel/types': 7.20.5
babel-preset-fbjs: 3.4.0_@babel+core@7.20.5
chalk: 4.1.2
fb-watchman: 2.0.1
fbjs: 3.0.4
glob: 7.2.3
immutable: 3.7.6
invariant: 2.2.4
nullthrows: 1.1.1
relay-runtime: 12.0.0
signedsource: 1.0.0
yargs: 15.4.1
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@ardatan/relay-compiler/12.0.0_graphql@16.6.0:
resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==}
hasBin: true
@ -1616,6 +1687,59 @@ packages:
- utf-8-validate
dev: true
/@graphql-codegen/cli/2.7.0_bidgzm5cq2du6gnjtweqqjrrn4:
resolution: {integrity: sha512-qlBcS6jGfZ/xWXwqiyRLHGRuLC9gUdF8AwGHN7LdAYEP5MjL7pIXb02W5JuvMn47rrvr2Q22H9ECppZX65oSAg==}
hasBin: true
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/core': 2.5.1
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-tools/apollo-engine-loader': 7.3.13
'@graphql-tools/code-file-loader': 7.3.6
'@graphql-tools/git-loader': 7.2.6
'@graphql-tools/github-loader': 7.3.13
'@graphql-tools/graphql-file-loader': 7.5.5
'@graphql-tools/json-file-loader': 7.4.6
'@graphql-tools/load': 7.7.7
'@graphql-tools/prisma-loader': 7.2.22_@types+node@18.7.18
'@graphql-tools/url-loader': 7.16.2_@types+node@18.7.18
'@graphql-tools/utils': 8.12.0
ansi-escapes: 4.3.2
chalk: 4.1.2
change-case-all: 1.0.14
chokidar: 3.5.3
common-tags: 1.8.2
cosmiconfig: 7.0.1
debounce: 1.2.1
detect-indent: 6.1.0
graphql-config: 4.3.5_bidgzm5cq2du6gnjtweqqjrrn4
inquirer: 8.2.4
is-glob: 4.0.3
json-to-pretty-yaml: 1.2.2
latest-version: 5.1.0
listr: 0.14.3
listr-update-renderer: 0.5.0_listr@0.14.3
log-symbols: 4.1.0
mkdirp: 1.0.4
string-env-interpolation: 1.0.1
ts-log: 2.2.4
wrap-ansi: 7.0.0
yaml: 1.10.2
yargs: 17.5.1
transitivePeerDependencies:
- '@swc/core'
- '@swc/wasm'
- '@types/node'
- bufferutil
- encoding
- supports-color
- typescript
- utf-8-validate
- zen-observable
- zenObservable
dev: true
/@graphql-codegen/cli/2.7.0_fte77dov2vin5jxmf6euzzc57i:
resolution: {integrity: sha512-qlBcS6jGfZ/xWXwqiyRLHGRuLC9gUdF8AwGHN7LdAYEP5MjL7pIXb02W5JuvMn47rrvr2Q22H9ECppZX65oSAg==}
hasBin: true
@ -1724,6 +1848,17 @@ packages:
- zenObservable
dev: true
/@graphql-codegen/core/2.5.1:
resolution: {integrity: sha512-alctBVl2hMnBXDLwkgmnFPrZVIiBDsWJSmxJcM4GKg1PB23+xuov35GE47YAyAhQItE1B1fbYnbb1PtGiDZ4LA==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-tools/schema': 8.5.1
'@graphql-tools/utils': 8.12.0
tslib: 2.3.1
dev: true
/@graphql-codegen/core/2.5.1_graphql@16.6.0:
resolution: {integrity: sha512-alctBVl2hMnBXDLwkgmnFPrZVIiBDsWJSmxJcM4GKg1PB23+xuov35GE47YAyAhQItE1B1fbYnbb1PtGiDZ4LA==}
peerDependencies:
@ -1748,6 +1883,19 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-codegen/plugin-helpers/2.7.0:
resolution: {integrity: sha512-+a2VP/4Ob0fwP8YLrQ/hhYlAA9UZUdDFNqwS543DmyiGFUkNIsa7TnTsE/mBDKJSMsCVWLw78949fCpzjyw/9Q==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-tools/utils': 8.12.0
change-case-all: 1.0.14
common-tags: 1.8.2
import-from: 4.0.0
lodash: 4.17.21
tslib: 2.4.0
dev: true
/@graphql-codegen/plugin-helpers/2.7.0_graphql@16.6.0:
resolution: {integrity: sha512-+a2VP/4Ob0fwP8YLrQ/hhYlAA9UZUdDFNqwS543DmyiGFUkNIsa7TnTsE/mBDKJSMsCVWLw78949fCpzjyw/9Q==}
peerDependencies:
@ -1762,6 +1910,16 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-codegen/schema-ast/2.5.1:
resolution: {integrity: sha512-tewa5DEKbglWn7kYyVBkh3J8YQ5ALqAMVmZwiVFIGOao5u66nd+e4HuFqp0u+Jpz4SJGGi0ap/oFrEvlqLjd2A==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
dev: true
/@graphql-codegen/schema-ast/2.5.1_graphql@16.6.0:
resolution: {integrity: sha512-tewa5DEKbglWn7kYyVBkh3J8YQ5ALqAMVmZwiVFIGOao5u66nd+e4HuFqp0u+Jpz4SJGGi0ap/oFrEvlqLjd2A==}
peerDependencies:
@ -1773,6 +1931,21 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-codegen/typescript-operations/2.5.3:
resolution: {integrity: sha512-s+pA+Erm0HeBb/D5cNrflwRM5KWhkiA5cbz4uA99l3fzFPveoQBPfRCBu0XAlJLP/kBDy64+o4B8Nfc7wdRtmA==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-codegen/typescript': 2.7.3
'@graphql-codegen/visitor-plugin-common': 2.12.1
auto-bind: 4.0.0
tslib: 2.4.0
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@graphql-codegen/typescript-operations/2.5.3_graphql@16.6.0:
resolution: {integrity: sha512-s+pA+Erm0HeBb/D5cNrflwRM5KWhkiA5cbz4uA99l3fzFPveoQBPfRCBu0XAlJLP/kBDy64+o4B8Nfc7wdRtmA==}
peerDependencies:
@ -1789,6 +1962,21 @@ packages:
- supports-color
dev: true
/@graphql-codegen/typescript/2.7.3:
resolution: {integrity: sha512-EzX/acijXtbG/AwPzho2ZZWaNo00+xAbsRDP+vnT2PwQV3AYq3/5bFvjq1XfAGWbTntdmlYlIwC9hf5bI85WVA==}
peerDependencies:
graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-codegen/schema-ast': 2.5.1
'@graphql-codegen/visitor-plugin-common': 2.12.1
auto-bind: 4.0.0
tslib: 2.4.0
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@graphql-codegen/typescript/2.7.3_graphql@16.6.0:
resolution: {integrity: sha512-EzX/acijXtbG/AwPzho2ZZWaNo00+xAbsRDP+vnT2PwQV3AYq3/5bFvjq1XfAGWbTntdmlYlIwC9hf5bI85WVA==}
peerDependencies:
@ -1805,6 +1993,26 @@ packages:
- supports-color
dev: true
/@graphql-codegen/visitor-plugin-common/2.12.1:
resolution: {integrity: sha512-dIUrX4+i/uazyPQqXyQ8cqykgNFe1lknjnfDWFo0gnk2W8+ruuL2JpSrj/7efzFHxbYGMQrCABDCUTVLi3DcVA==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-codegen/plugin-helpers': 2.7.0
'@graphql-tools/optimize': 1.3.1
'@graphql-tools/relay-operation-optimizer': 6.5.6
'@graphql-tools/utils': 8.12.0
auto-bind: 4.0.0
change-case-all: 1.0.14
dependency-graph: 0.11.0
graphql-tag: 2.12.6
parse-filepath: 1.0.2
tslib: 2.4.0
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@graphql-codegen/visitor-plugin-common/2.12.1_graphql@16.6.0:
resolution: {integrity: sha512-dIUrX4+i/uazyPQqXyQ8cqykgNFe1lknjnfDWFo0gnk2W8+ruuL2JpSrj/7efzFHxbYGMQrCABDCUTVLi3DcVA==}
peerDependencies:
@ -1826,6 +2034,19 @@ packages:
- supports-color
dev: true
/@graphql-tools/apollo-engine-loader/7.3.13:
resolution: {integrity: sha512-fr2TcA9fM+H81ymdtyDaocZ/Ua4Vhhf1IvpQoPpuEUwLorREd86N8VORUEIBvEdJ1b7Bz7NqwL3RnM5m9KXftA==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@ardatan/sync-fetch': 0.0.1
'@graphql-tools/utils': 8.12.0
'@whatwg-node/fetch': 0.4.3
tslib: 2.4.0
transitivePeerDependencies:
- encoding
dev: true
/@graphql-tools/apollo-engine-loader/7.3.13_graphql@16.6.0:
resolution: {integrity: sha512-fr2TcA9fM+H81ymdtyDaocZ/Ua4Vhhf1IvpQoPpuEUwLorREd86N8VORUEIBvEdJ1b7Bz7NqwL3RnM5m9KXftA==}
peerDependencies:
@ -1840,6 +2061,17 @@ packages:
- encoding
dev: true
/@graphql-tools/batch-execute/8.5.6:
resolution: {integrity: sha512-33vMvVDLBKsNJVNhcySVXF+zkcRL/GRs1Lt+MxygrYCypcAPpFm+amE2y9vOCFufuaKExIX7Lonnmxu19vPzaQ==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/utils': 8.12.0
dataloader: 2.1.0
tslib: 2.4.0
value-or-promise: 1.0.11
dev: true
/@graphql-tools/batch-execute/8.5.6_graphql@16.6.0:
resolution: {integrity: sha512-33vMvVDLBKsNJVNhcySVXF+zkcRL/GRs1Lt+MxygrYCypcAPpFm+amE2y9vOCFufuaKExIX7Lonnmxu19vPzaQ==}
peerDependencies:
@ -1852,6 +2084,20 @@ packages:
value-or-promise: 1.0.11
dev: true
/@graphql-tools/code-file-loader/7.3.6:
resolution: {integrity: sha512-PNWWSwSuQAqANerDwS0zdQ5FPipirv75TjjzBHnY+6AF/WvKq5sQiUQheA2P7B+MZc/KdQ7h/JAGMQOhKNVA+Q==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/graphql-tag-pluck': 7.3.6
'@graphql-tools/utils': 8.12.0
globby: 11.1.0
tslib: 2.4.0
unixify: 1.0.0
transitivePeerDependencies:
- supports-color
dev: true
/@graphql-tools/code-file-loader/7.3.6_graphql@16.6.0:
resolution: {integrity: sha512-PNWWSwSuQAqANerDwS0zdQ5FPipirv75TjjzBHnY+6AF/WvKq5sQiUQheA2P7B+MZc/KdQ7h/JAGMQOhKNVA+Q==}
peerDependencies:
@ -1867,6 +2113,19 @@ packages:
- supports-color
dev: true
/@graphql-tools/delegate/9.0.6:
resolution: {integrity: sha512-HMA7rcJLQA3dJwWRG2271mRCdh0SLaK5+FPg+F7JIa3aF5fRdN4pVHNDaAjQeyKOQ2afjgjO5FvOyJwv/ve7Bg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/batch-execute': 8.5.6
'@graphql-tools/schema': 9.0.4
'@graphql-tools/utils': 8.12.0
dataloader: 2.1.0
tslib: 2.4.0
value-or-promise: 1.0.11
dev: true
/@graphql-tools/delegate/9.0.6_graphql@16.6.0:
resolution: {integrity: sha512-HMA7rcJLQA3dJwWRG2271mRCdh0SLaK5+FPg+F7JIa3aF5fRdN4pVHNDaAjQeyKOQ2afjgjO5FvOyJwv/ve7Bg==}
peerDependencies:
@ -1881,6 +2140,21 @@ packages:
value-or-promise: 1.0.11
dev: true
/@graphql-tools/git-loader/7.2.6:
resolution: {integrity: sha512-QA94Gjp70xcdIYUbZDIm8fnuDN0IvoIIVVU+lXQemoV+vDeJKIjrP9tfOTjVDPIDXQnCYswvu9HLe8BlEApQYw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/graphql-tag-pluck': 7.3.6
'@graphql-tools/utils': 8.12.0
is-glob: 4.0.3
micromatch: 4.0.5
tslib: 2.4.0
unixify: 1.0.0
transitivePeerDependencies:
- supports-color
dev: true
/@graphql-tools/git-loader/7.2.6_graphql@16.6.0:
resolution: {integrity: sha512-QA94Gjp70xcdIYUbZDIm8fnuDN0IvoIIVVU+lXQemoV+vDeJKIjrP9tfOTjVDPIDXQnCYswvu9HLe8BlEApQYw==}
peerDependencies:
@ -1897,6 +2171,21 @@ packages:
- supports-color
dev: true
/@graphql-tools/github-loader/7.3.13:
resolution: {integrity: sha512-4RTjdtdtQC+n9LJMKpBThQGD3LnpeLVjU2A7BoVuKR+NQPJtcUzzuD6dXeYm5RiOMOQUsPGxQWKhJenW20aLUg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@ardatan/sync-fetch': 0.0.1
'@graphql-tools/graphql-tag-pluck': 7.3.6
'@graphql-tools/utils': 8.12.0
'@whatwg-node/fetch': 0.4.3
tslib: 2.4.0
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@graphql-tools/github-loader/7.3.13_graphql@16.6.0:
resolution: {integrity: sha512-4RTjdtdtQC+n9LJMKpBThQGD3LnpeLVjU2A7BoVuKR+NQPJtcUzzuD6dXeYm5RiOMOQUsPGxQWKhJenW20aLUg==}
peerDependencies:
@ -1913,6 +2202,18 @@ packages:
- supports-color
dev: true
/@graphql-tools/graphql-file-loader/7.5.5:
resolution: {integrity: sha512-OL+7qO1S66TpMK7OGz8Ag2WL08HlxKxrObVSDlxzWbSubWuXM5v959XscYAKRf6daYcVpkfNvO37QjflL9mjhg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/import': 6.7.6
'@graphql-tools/utils': 8.12.0
globby: 11.1.0
tslib: 2.4.0
unixify: 1.0.0
dev: true
/@graphql-tools/graphql-file-loader/7.5.5_graphql@16.6.0:
resolution: {integrity: sha512-OL+7qO1S66TpMK7OGz8Ag2WL08HlxKxrObVSDlxzWbSubWuXM5v959XscYAKRf6daYcVpkfNvO37QjflL9mjhg==}
peerDependencies:
@ -1926,6 +2227,20 @@ packages:
unixify: 1.0.0
dev: true
/@graphql-tools/graphql-tag-pluck/7.3.6:
resolution: {integrity: sha512-qULgqsOGKY1/PBqmP7fJZqbCg/TzPHKB9Wl51HGA9QjGymrzmrH5EjvsC8RtgdubF8yuTTVVFTz1lmSQ7RPssQ==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@babel/parser': 7.20.5
'@babel/traverse': 7.20.5
'@babel/types': 7.20.5
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
transitivePeerDependencies:
- supports-color
dev: true
/@graphql-tools/graphql-tag-pluck/7.3.6_graphql@16.6.0:
resolution: {integrity: sha512-qULgqsOGKY1/PBqmP7fJZqbCg/TzPHKB9Wl51HGA9QjGymrzmrH5EjvsC8RtgdubF8yuTTVVFTz1lmSQ7RPssQ==}
peerDependencies:
@ -1941,6 +2256,16 @@ packages:
- supports-color
dev: true
/@graphql-tools/import/6.7.6:
resolution: {integrity: sha512-WtUyiO2qCaK/H4u81zAw/NbBvCOzwKl4N+Vl+FqrFCzYobscwL6x6roePyoXM1O3+JJIIn3CETv4kg4kwxaBVw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/utils': 8.12.0
resolve-from: 5.0.0
tslib: 2.4.0
dev: true
/@graphql-tools/import/6.7.6_graphql@16.6.0:
resolution: {integrity: sha512-WtUyiO2qCaK/H4u81zAw/NbBvCOzwKl4N+Vl+FqrFCzYobscwL6x6roePyoXM1O3+JJIIn3CETv4kg4kwxaBVw==}
peerDependencies:
@ -1952,6 +2277,17 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/json-file-loader/7.4.6:
resolution: {integrity: sha512-34AfjCitO4NtJ5AcXYLcFF3GDsMVTycrljSaBA2t1d7B4bMPtREDphKXLMc/Uf2zW6IW1i1sZZyrcmArPy1Z8A==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/utils': 8.12.0
globby: 11.1.0
tslib: 2.4.0
unixify: 1.0.0
dev: true
/@graphql-tools/json-file-loader/7.4.6_graphql@16.6.0:
resolution: {integrity: sha512-34AfjCitO4NtJ5AcXYLcFF3GDsMVTycrljSaBA2t1d7B4bMPtREDphKXLMc/Uf2zW6IW1i1sZZyrcmArPy1Z8A==}
peerDependencies:
@ -1964,6 +2300,17 @@ packages:
unixify: 1.0.0
dev: true
/@graphql-tools/load/7.7.7:
resolution: {integrity: sha512-IpI2672zcoAX4FLjcH5kvHc7eqjPyLP1svrIcZKQenv0GRS6dW0HI9E5UCBs0y/yy8yW6s+SvpmNsfIlkMj3Kw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/schema': 9.0.4
'@graphql-tools/utils': 8.12.0
p-limit: 3.1.0
tslib: 2.4.0
dev: true
/@graphql-tools/load/7.7.7_graphql@16.6.0:
resolution: {integrity: sha512-IpI2672zcoAX4FLjcH5kvHc7eqjPyLP1svrIcZKQenv0GRS6dW0HI9E5UCBs0y/yy8yW6s+SvpmNsfIlkMj3Kw==}
peerDependencies:
@ -1976,6 +2323,15 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/merge/8.3.1:
resolution: {integrity: sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/utils': 8.9.0
tslib: 2.4.0
dev: true
/@graphql-tools/merge/8.3.1_graphql@16.6.0:
resolution: {integrity: sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg==}
peerDependencies:
@ -1986,6 +2342,15 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/merge/8.3.6:
resolution: {integrity: sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
dev: true
/@graphql-tools/merge/8.3.6_graphql@16.6.0:
resolution: {integrity: sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==}
peerDependencies:
@ -1996,6 +2361,14 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/optimize/1.3.1:
resolution: {integrity: sha512-5j5CZSRGWVobt4bgRRg7zhjPiSimk+/zIuColih8E8DxuFOaJ+t0qu7eZS5KXWBkjcd4BPNuhUPpNlEmHPqVRQ==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
tslib: 2.4.0
dev: true
/@graphql-tools/optimize/1.3.1_graphql@16.6.0:
resolution: {integrity: sha512-5j5CZSRGWVobt4bgRRg7zhjPiSimk+/zIuColih8E8DxuFOaJ+t0qu7eZS5KXWBkjcd4BPNuhUPpNlEmHPqVRQ==}
peerDependencies:
@ -2005,6 +2378,38 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/prisma-loader/7.2.22_@types+node@18.7.18:
resolution: {integrity: sha512-QafvScyyJ9Nvi1r4dmYUBzk1pe5MDwhMQUlJQLIphIPHYP8so8aRHKttoycuMZgQB43uOP+9RpdK0BIPa84/dw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/url-loader': 7.16.2_@types+node@18.7.18
'@graphql-tools/utils': 8.12.0
'@types/js-yaml': 4.0.5
'@types/json-stable-stringify': 1.0.34
'@types/jsonwebtoken': 8.5.9
chalk: 4.1.2
debug: 4.3.4
dotenv: 16.0.2
graphql-request: 5.0.0
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.1
isomorphic-fetch: 3.0.0
js-yaml: 4.1.0
json-stable-stringify: 1.0.1
jsonwebtoken: 8.5.1
lodash: 4.17.21
scuid: 1.1.0
tslib: 2.4.0
yaml-ast-parser: 0.0.43
transitivePeerDependencies:
- '@types/node'
- bufferutil
- encoding
- supports-color
- utf-8-validate
dev: true
/@graphql-tools/prisma-loader/7.2.22_c3mutv243l2gduwl4hptzcimie:
resolution: {integrity: sha512-QafvScyyJ9Nvi1r4dmYUBzk1pe5MDwhMQUlJQLIphIPHYP8so8aRHKttoycuMZgQB43uOP+9RpdK0BIPa84/dw==}
peerDependencies:
@ -2071,6 +2476,19 @@ packages:
- utf-8-validate
dev: true
/@graphql-tools/relay-operation-optimizer/6.5.6:
resolution: {integrity: sha512-2KjaWYxD/NC6KtckbDEAbN46QO+74d1SBaZQ26qQjWhyoAjon12xlMW4HWxHEN0d0xuz0cnOVUVc+t4wVXePUg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@ardatan/relay-compiler': 12.0.0
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
transitivePeerDependencies:
- encoding
- supports-color
dev: true
/@graphql-tools/relay-operation-optimizer/6.5.6_graphql@16.6.0:
resolution: {integrity: sha512-2KjaWYxD/NC6KtckbDEAbN46QO+74d1SBaZQ26qQjWhyoAjon12xlMW4HWxHEN0d0xuz0cnOVUVc+t4wVXePUg==}
peerDependencies:
@ -2085,6 +2503,17 @@ packages:
- supports-color
dev: true
/@graphql-tools/schema/8.5.1:
resolution: {integrity: sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/merge': 8.3.1
'@graphql-tools/utils': 8.9.0
tslib: 2.4.0
value-or-promise: 1.0.11
dev: true
/@graphql-tools/schema/8.5.1_graphql@16.6.0:
resolution: {integrity: sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg==}
peerDependencies:
@ -2097,6 +2526,17 @@ packages:
value-or-promise: 1.0.11
dev: true
/@graphql-tools/schema/9.0.4:
resolution: {integrity: sha512-B/b8ukjs18fq+/s7p97P8L1VMrwapYc3N2KvdG/uNThSazRRn8GsBK0Nr+FH+mVKiUfb4Dno79e3SumZVoHuOQ==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/merge': 8.3.6
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
value-or-promise: 1.0.11
dev: true
/@graphql-tools/schema/9.0.4_graphql@16.6.0:
resolution: {integrity: sha512-B/b8ukjs18fq+/s7p97P8L1VMrwapYc3N2KvdG/uNThSazRRn8GsBK0Nr+FH+mVKiUfb4Dno79e3SumZVoHuOQ==}
peerDependencies:
@ -2109,6 +2549,32 @@ packages:
value-or-promise: 1.0.11
dev: true
/@graphql-tools/url-loader/7.16.2_@types+node@18.7.18:
resolution: {integrity: sha512-ZVG3kDEJ88zLfqYtVmI36RUzaP/0bPBcJfBH8whMYL620tE6kizEQsON8iKsxcU1bWB5D7m9ZVFqW4eZ5EqVWw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@ardatan/sync-fetch': 0.0.1
'@graphql-tools/delegate': 9.0.6
'@graphql-tools/utils': 8.12.0
'@graphql-tools/wrap': 9.2.1
'@types/ws': 8.5.3
'@whatwg-node/fetch': 0.4.3
dset: 3.1.2
extract-files: 11.0.0
graphql-ws: 5.10.2
isomorphic-ws: 5.0.0_ws@8.8.1
meros: 1.2.0_@types+node@18.7.18
tslib: 2.4.0
value-or-promise: 1.0.11
ws: 8.8.1
transitivePeerDependencies:
- '@types/node'
- bufferutil
- encoding
- utf-8-validate
dev: true
/@graphql-tools/url-loader/7.16.2_c3mutv243l2gduwl4hptzcimie:
resolution: {integrity: sha512-ZVG3kDEJ88zLfqYtVmI36RUzaP/0bPBcJfBH8whMYL620tE6kizEQsON8iKsxcU1bWB5D7m9ZVFqW4eZ5EqVWw==}
peerDependencies:
@ -2163,6 +2629,14 @@ packages:
- utf-8-validate
dev: true
/@graphql-tools/utils/8.12.0:
resolution: {integrity: sha512-TeO+MJWGXjUTS52qfK4R8HiPoF/R7X+qmgtOYd8DTH0l6b+5Y/tlg5aGeUJefqImRq7nvi93Ms40k/Uz4D5CWw==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
tslib: 2.4.0
dev: true
/@graphql-tools/utils/8.12.0_graphql@16.6.0:
resolution: {integrity: sha512-TeO+MJWGXjUTS52qfK4R8HiPoF/R7X+qmgtOYd8DTH0l6b+5Y/tlg5aGeUJefqImRq7nvi93Ms40k/Uz4D5CWw==}
peerDependencies:
@ -2172,6 +2646,14 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/utils/8.9.0:
resolution: {integrity: sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
tslib: 2.4.0
dev: true
/@graphql-tools/utils/8.9.0_graphql@16.6.0:
resolution: {integrity: sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg==}
peerDependencies:
@ -2181,6 +2663,18 @@ packages:
tslib: 2.4.0
dev: true
/@graphql-tools/wrap/9.2.1:
resolution: {integrity: sha512-W8bzJijTZDNi8e1oM2AMG89CtvfTYaJ9lCe0dYMN+a+OPMhRfgR9+eO7ALcUa9y4MTu+YEDVjUq0ZboaSvesyA==}
peerDependencies:
graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
dependencies:
'@graphql-tools/delegate': 9.0.6
'@graphql-tools/schema': 9.0.4
'@graphql-tools/utils': 8.12.0
tslib: 2.4.0
value-or-promise: 1.0.11
dev: true
/@graphql-tools/wrap/9.2.1_graphql@16.6.0:
resolution: {integrity: sha512-W8bzJijTZDNi8e1oM2AMG89CtvfTYaJ9lCe0dYMN+a+OPMhRfgR9+eO7ALcUa9y4MTu+YEDVjUq0ZboaSvesyA==}
peerDependencies:
@ -2194,6 +2688,12 @@ packages:
value-or-promise: 1.0.11
dev: true
/@graphql-typed-document-node/core/3.1.1:
resolution: {integrity: sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dev: true
/@graphql-typed-document-node/core/3.1.1_graphql@16.6.0:
resolution: {integrity: sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==}
peerDependencies:
@ -5005,7 +5505,7 @@ packages:
eslint: 8.23.1
eslint-import-resolver-node: 0.3.6
eslint-import-resolver-typescript: 2.7.1_hdzsmr7kawaomymueo2tso6fjq
eslint-plugin-import: 2.26.0_eslint@8.23.1
eslint-plugin-import: 2.26.0_6r44hdgvdiqbnekattsi42eeia
eslint-plugin-jsx-a11y: 6.6.1_eslint@8.23.1
eslint-plugin-react: 7.31.8_eslint@8.23.1
eslint-plugin-react-hooks: 4.6.0_eslint@8.23.1
@ -5042,7 +5542,7 @@ packages:
dependencies:
debug: 4.3.4
eslint: 8.23.1
eslint-plugin-import: 2.26.0_eslint@8.23.1
eslint-plugin-import: 2.26.0_6r44hdgvdiqbnekattsi42eeia
glob: 7.2.3
is-glob: 4.0.3
resolve: 1.22.1
@ -5051,7 +5551,7 @@ packages:
- supports-color
dev: true
/eslint-module-utils/2.7.4_oxfrjumrtiktpkw7r2zaom7f74:
/eslint-module-utils/2.7.4_ssuof5somrshypivkj4dxrg5tm:
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
engines: {node: '>=4'}
peerDependencies:
@ -5072,14 +5572,16 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.37.0_4brgkhw6cq4me3drk3kxrpb2mm
debug: 3.2.7
eslint: 8.23.1
eslint-import-resolver-node: 0.3.6
eslint-import-resolver-typescript: 2.7.1_hdzsmr7kawaomymueo2tso6fjq
transitivePeerDependencies:
- supports-color
dev: true
/eslint-plugin-import/2.26.0_eslint@8.23.1:
/eslint-plugin-import/2.26.0_6r44hdgvdiqbnekattsi42eeia:
resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==}
engines: {node: '>=4'}
peerDependencies:
@ -5089,13 +5591,14 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.37.0_4brgkhw6cq4me3drk3kxrpb2mm
array-includes: 3.1.5
array.prototype.flat: 1.3.0
debug: 2.6.9
doctrine: 2.1.0
eslint: 8.23.1
eslint-import-resolver-node: 0.3.6
eslint-module-utils: 2.7.4_oxfrjumrtiktpkw7r2zaom7f74
eslint-module-utils: 2.7.4_ssuof5somrshypivkj4dxrg5tm
has: 1.0.3
is-core-module: 2.10.0
is-glob: 4.0.3
@ -5797,6 +6300,35 @@ packages:
resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==}
dev: true
/graphql-config/4.3.5_bidgzm5cq2du6gnjtweqqjrrn4:
resolution: {integrity: sha512-B4jXhHL7j3llCem+ACeo48wvVYhtJxRyt5SfSnvywbRlVYyUzt5ibZV6WJU2Yii2/rcVRIGi7BHDgcAPWdWdJg==}
engines: {node: '>= 10.0.0'}
peerDependencies:
graphql: ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
'@graphql-tools/graphql-file-loader': 7.5.5
'@graphql-tools/json-file-loader': 7.4.6
'@graphql-tools/load': 7.7.7
'@graphql-tools/merge': 8.3.6
'@graphql-tools/url-loader': 7.16.2_@types+node@18.7.18
'@graphql-tools/utils': 8.12.0
cosmiconfig: 7.0.1
cosmiconfig-toml-loader: 1.0.0
cosmiconfig-typescript-loader: 4.0.0_7erwhgajjbydxgvliy6verrdiu
minimatch: 4.2.1
string-env-interpolation: 1.0.1
ts-node: 10.9.1_bidgzm5cq2du6gnjtweqqjrrn4
tslib: 2.4.0
transitivePeerDependencies:
- '@swc/core'
- '@swc/wasm'
- '@types/node'
- bufferutil
- encoding
- typescript
- utf-8-validate
dev: true
/graphql-config/4.3.5_fte77dov2vin5jxmf6euzzc57i:
resolution: {integrity: sha512-B4jXhHL7j3llCem+ACeo48wvVYhtJxRyt5SfSnvywbRlVYyUzt5ibZV6WJU2Yii2/rcVRIGi7BHDgcAPWdWdJg==}
engines: {node: '>= 10.0.0'}
@ -5857,6 +6389,19 @@ packages:
- utf-8-validate
dev: true
/graphql-request/5.0.0:
resolution: {integrity: sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==}
peerDependencies:
graphql: 14 - 16
dependencies:
'@graphql-typed-document-node/core': 3.1.1
cross-fetch: 3.1.5
extract-files: 9.0.0
form-data: 3.0.1
transitivePeerDependencies:
- encoding
dev: true
/graphql-request/5.0.0_graphql@16.6.0:
resolution: {integrity: sha512-SpVEnIo2J5k2+Zf76cUkdvIRaq5FMZvGQYnA4lUWYbc99m+fHh4CZYRRO/Ff4tCLQ613fzCm3SiDT64ubW5Gyw==}
peerDependencies:
@ -5871,6 +6416,15 @@ packages:
- encoding
dev: true
/graphql-tag/2.12.6:
resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==}
engines: {node: '>=10'}
peerDependencies:
graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
dependencies:
tslib: 2.4.0
dev: true
/graphql-tag/2.12.6_graphql@16.6.0:
resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==}
engines: {node: '>=10'}
@ -5881,6 +6435,13 @@ packages:
tslib: 2.4.0
dev: true
/graphql-ws/5.10.2:
resolution: {integrity: sha512-QnLz0hbpTkmp/ATKAA3Tsg9LFZjWtgrLMgxc3W9G+3+rxUtzcYLwQh4YbXELYcpCqo8zdQxmERAtIQSgq75LTw==}
engines: {node: '>=10'}
peerDependencies:
graphql: '>=0.11 <=16'
dev: true
/graphql-ws/5.10.2_graphql@16.6.0:
resolution: {integrity: sha512-QnLz0hbpTkmp/ATKAA3Tsg9LFZjWtgrLMgxc3W9G+3+rxUtzcYLwQh4YbXELYcpCqo8zdQxmERAtIQSgq75LTw==}
engines: {node: '>=10'}
@ -6598,7 +7159,7 @@ packages:
dev: true
/json-buffer/3.0.0:
resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==}
resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=}
dev: true
/json-buffer/3.0.1:
@ -7375,7 +7936,7 @@ packages:
dependencies:
'@next/env': 12.3.0
'@swc/helpers': 0.4.11
caniuse-lite: 1.0.30001399
caniuse-lite: 1.0.30001422
postcss: 8.4.14
react: 18.2.0
react-dom: 18.2.0_react@18.2.0

View File

@ -50,9 +50,8 @@ KIBO_API_HOST=
NEXT_PUBLIC_COMMERCEJS_PUBLIC_KEY=
NEXT_PUBLIC_COMMERCEJS_DEPLOYMENT_URL=
OPENCOMMERCE_STOREFRONT_API_URL=
OPENCOMMERCE_PRIMARY_SHOP_ID=
OPENCOMMERCE_IMAGE_DOMAIN=
NEXT_PUBLIC_OPENCOMMERCE_API_URL=
NEXT_PUBLIC_OPENCOMMERCE_IMAGE_DOMAIN=
SFCC_CLIENT_ID=
SFCC_CLIENT_SECRET=

View File

@ -89,7 +89,7 @@ const CartItem = ({
>
<div className="flex flex-row space-x-4 py-4">
<div className="w-16 h-16 bg-violet relative overflow-hidden cursor-pointer">
<Link href={`/product/${item.path}`}>
<Link href={`/product${item.path}`}>
<Image
onClick={() => closeSidebarIfPresent()}
className={s.productImage}

View File

@ -24,7 +24,6 @@ const CheckoutSidebarView: FC = () => {
const { clearCheckoutFields, cardFields, addressFields } =
useCheckoutContext()
async function handleSubmit(event: React.ChangeEvent<HTMLFormElement>) {
try {
setLoadingSubmit(true)
@ -32,7 +31,6 @@ const CheckoutSidebarView: FC = () => {
await onCheckout({
card: cardFields,
address: addressFields,
checkout: { cart: cartData },
})
clearCheckoutFields()
setLoadingSubmit(false)
@ -111,7 +109,7 @@ const CheckoutSidebarView: FC = () => {
{checkoutData?.hasSelectedShippingMethod ? (
<li className="flex justify-between py-1">
<span>Shipping</span>
<span>{checkoutData?.totalAmount}</span>
<span>{checkoutData?.totalDisplayAmount}</span>
</li>
) : (
<li className="flex justify-between py-1">

View File

@ -37,7 +37,7 @@ const ShippingMethod = () => {
setSidebarView('CHECKOUT_VIEW')
}
return checkoutData.shippingGroup ? (
return checkoutData?.shippingGroup ? (
<form className="h-full" onSubmit={handleSubmit}>
<SidebarLayout handleBack={() => setSidebarView('CHECKOUT_VIEW')}>
<div className="px-4 sm:px-6 flex-1">
@ -58,7 +58,7 @@ const ShippingMethod = () => {
type="radio"
value={option?.fulfillmentMethod?._id}
defaultChecked={
checkoutData.shippingGroup.selectedFulfillmentOption
checkoutData.shippingGroup?.selectedFulfillmentOption
?.fulfillmentMethod?._id ===
option?.fulfillmentMethod?._id
}

View File

@ -16,7 +16,8 @@ import ShippingMethodView from '@components/checkout/ShippingMethodView'
import { CheckoutProvider } from '@components/checkout/context'
import { MenuSidebarView } from '@components/common/UserNav'
import type { Page } from '@commerce/types/page'
import type { Category, Navigation } from '@commerce/types/site'
import type { Category } from '@commerce/types/site'
import type { Navigation } from '@framework/types/site'
import type { Link as LinkProps } from '../UserNav/MenuSidebarView'
const Loading = () => (

View File

@ -20,14 +20,14 @@ const SubItem = ({ subItem, level = 0 }: SubItemProps) => {
return (
<>
{subItem.isUrlRelative ? (
<Link href={subItem.url} key={subItem.url}>
<a
className={`block rounded ml-${
level * 2
} py-[10px] px-4 text-sm text-black`}
>
{subItem.label}
</a>
<Link
href={subItem.url}
key={subItem.url}
className={`block rounded ml-${
level * 2
} py-[10px] px-4 text-sm text-black`}
>
{subItem.label}
</Link>
) : (
<a
@ -61,15 +61,14 @@ const CustomNavbar = ({ links = [] }: CustomNavbarProps) => {
{links.map((item) => (
<div className="group inline-block relative" key={item.url}>
{item.isUrlRelative ? (
<Link href={item.url}>
<a
className={cn(
s.link,
Number(item.items?.length) > 0 && s.customLink
)}
>
{item.label}
</a>
<Link
href={item.url}
className={cn(
s.link,
Number(item.items?.length) > 0 && s.customLink
)}
>
{item.label}
</Link>
) : (
<a

View File

@ -5,7 +5,7 @@ import s from './Navbar.module.css'
import NavbarRoot from './NavbarRoot'
import { Logo, Container } from '@components/ui'
import { Searchbar, UserNav } from '@components/common'
import { Navigation } from '@commerce/types/site'
import type { Navigation } from '@framework/types/site'
import CustomNavbar from './CustomNavbar'
interface Link {
@ -32,11 +32,11 @@ const Navbar: FC<NavbarProps> = ({ links, customNavigation }) => (
) : (
<>
<Link href="/search" className={s.link}>
All
All
</Link>
{links?.map((l) => (
<Link href={l.href} key={l.href} className={s.link}>
{l.label}
{l.label}
</Link>
))}
</>

View File

@ -36,11 +36,6 @@ const ProductSidebar: FC<ProductSidebarProps> = ({ product, className }) => {
await addItem({
productId: String(product.id),
variantId: String(variant ? variant.id : product.variants[0]?.id),
// Open Commerce provider only
...({
variant: variant ?? product.variants[0],
currencyCode: String(product.price.currencyCode),
} as any),
})
setSidebarView('CART_VIEW')
openSidebar()

View File

@ -23,8 +23,8 @@
"@components/*": ["components/*"],
"@commerce": ["../packages/commerce/src"],
"@commerce/*": ["../packages/commerce/src/*"],
"@framework": ["../packages/local/src"],
"@framework/*": ["../packages/local/src/*"]
"@framework": ["../packages/opencommerce/src"],
"@framework/*": ["../packages/opencommerce/src/*"]
}
},
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],