Update product types

This commit is contained in:
cond0r 2022-09-05 21:09:12 +03:00 committed by Catalin Pinte
parent 8398a96215
commit 110977424d
4 changed files with 195 additions and 90 deletions

View File

@ -5,7 +5,7 @@ import type { SearchProductsHook } from '../types/product'
import type { Provider } from '..' import type { Provider } from '..'
export type UseSearch< export type UseSearch<
H extends SWRHook<SearchProductsHook<any>> = SWRHook<SearchProductsHook> H extends SWRHook<SearchProductsHook> = SWRHook<SearchProductsHook>
> = ReturnType<H['useHook']> > = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<SearchProductsHook> = SWRFetcher export const fetcher: HookFetcherFn<SearchProductsHook> = SWRFetcher

View File

@ -1,14 +1,68 @@
import type { Discount, Measurement, Image } from './common' import type { Discount, Measurement, Image } from './common'
export type SelectedOption = { export type SelectedOption = {
// The option's id. /**
* The selected option's id
*/
id?: string id?: string
// The product options name. /**
* The product options name. */
name: string name: string
/// The product options value. /**
* The product options value. */
value: string value: string
} }
export type ProductVariant = {
/**
* The variant's id. */
id: string
/**
* The SKU (stock keeping unit) associated with the product variant. */
sku: string
/**
* The product variants title, or the product's name. */
name: string
/**
* Whether a customer needs to provide a shipping address when placing
* an order for the product variant. */
requiresShipping: boolean
/**
* The product variants price after all discounts are applied. */
price: number
/**
* Product variants price, as quoted by the manufacturer/distributor. */
listPrice: number
/**
* Image associated with the product variant. Falls back to the product image
* if no image is available. */
image?: Image
/**
* Indicates whether this product variant is in stock. */
isInStock?: boolean
/**
* Indicates if the product variant is available for sale. */
availableForSale?: boolean
/**
* The variant's weight. If a weight was not explicitly specified on the */
/**
* variant this will be the product's weight. */
weight?: Measurement
/**
* The variant's height. If a height was not explicitly specified on the
* variant, this will be the product's height. */
height?: Measurement
/**
* The variant's width. If a width was not explicitly specified on the
* variant, this will be the product's width. */
width?: Measurement
/**
* The variant's depth. If a depth was not explicitly specified on the
* variant, this will be the product's depth. */
depth?: Measurement
}
export type LineItem = { export type LineItem = {
id: string id: string
variantId: string variantId: string
@ -16,69 +70,50 @@ export type LineItem = {
name: string name: string
quantity: number quantity: number
discounts: Discount[] discounts: Discount[]
// A human-friendly unique string automatically generated from the products name /**
* A human-friendly unique string automatically generated from the products name. */
path: string path: string
variant: ProductVariant variant: ProductVariant
options?: SelectedOption[] options?: SelectedOption[]
} }
export type ProductVariant = {
id: string
// The SKU (stock keeping unit) associated with the product variant.
sku: string
// The product variants title, or the product's name.
name: string
// Whether a customer needs to provide a shipping address when placing
// an order for the product variant.
requiresShipping: boolean
// The product variants price after all discounts are applied.
price: number
// Product variants price, as quoted by the manufacturer/distributor.
listPrice: number
// Image associated with the product variant. Falls back to the product image
// if no image is available.
image?: Image
// Indicates whether this product variant is in stock.
isInStock?: boolean
// Indicates if the product variant is available for sale.
availableForSale?: boolean
// The variant's weight. If a weight was not explicitly specified on the
// variant this will be the product's weight.
weight?: Measurement
// The variant's height. If a height was not explicitly specified on the
// variant, this will be the product's height.
height?: Measurement
// The variant's width. If a width was not explicitly specified on the
// variant, this will be the product's width.
width?: Measurement
// The variant's depth. If a depth was not explicitly specified on the
// variant, this will be the product's depth.
depth?: Measurement
}
// Shopping cart, a.k.a Checkout // Shopping cart, a.k.a Checkout
export type Cart = { export type Cart = {
/**
* The cart's id. */
id: string id: string
// ID of the customer to which the cart belongs. /**
* ID of the customer to which the cart belongs. */
customerId?: string customerId?: string
// The email assigned to this cart /**
* The email assigned to this cart. */
email?: string email?: string
// The date and time when the cart was created. /**
* The date and time when the cart was created. */
createdAt: string createdAt: string
// The currency used for this cart /**
* The currency used for this cart */
currency: { code: string } currency: { code: string }
// Specifies if taxes are included in the line items. /**
* Specifies if taxes are included in the line items. */
taxesIncluded: boolean taxesIncluded: boolean
lineItems: LineItem[] lineItems: LineItem[]
// The sum of all the prices of all the items in the cart. /**
// Duties, taxes, shipping and discounts excluded. * The sum of all the prices of all the items in the cart. */
/**
* Duties, taxes, shipping and discounts excluded. */
lineItemsSubtotalPrice: number lineItemsSubtotalPrice: number
// Price of the cart before duties, shipping and taxes. /**
* Price of the cart before duties, shipping and taxes.*/
subtotalPrice: number subtotalPrice: number
// The sum of all the prices of all the items in the cart. /**
// Duties, taxes and discounts included. * The sum of all the prices of all the items in the cart.*/
/**
* Duties, taxes and discounts included.*/
totalPrice: number totalPrice: number
// Discounts that have been applied on the cart. /**
* Discounts that have been applied on the cart.*/
discounts?: Discount[] discounts?: Discount[]
} }

View File

@ -1,91 +1,157 @@
export type ProductImage = { export interface ProductImage {
/**
* The URL of the product image.
*/
url: string url: string
/**
* A word or phrase that describes the content of an image.
*/
alt?: string alt?: string
} }
export type ProductPrice = { export interface ProductPrice {
/**
* Decimal price amount. */
value: number value: number
/**
* Currency of the product price. */
currencyCode?: 'USD' | 'EUR' | 'ARS' | 'GBP' | string currencyCode?: 'USD' | 'EUR' | 'ARS' | 'GBP' | string
/**
* The retail price of the product. This can be used to mark a product as on sale, when `retailPrice` is higher than the price a.k.a `value`. */
retailPrice?: number retailPrice?: number
salePrice?: number
listPrice?: number
extendedSalePrice?: number extendedSalePrice?: number
extendedListPrice?: number extendedListPrice?: number
} }
export type ProductOption = { export interface ProductOption {
__typename?: 'MultipleChoiceOption' __typename?: 'MultipleChoiceOption'
/**
* The option's id. */
id: string id: string
/**
* The option's name. */
displayName: string displayName: string
/**
* List of option values. */
values: ProductOptionValues[] values: ProductOptionValues[]
} }
export type ProductOptionValues = { export interface ProductOptionValues {
/**
* A string that uniquely identifies the option value. */
label: string label: string
/**
* List of hex colors used to display the actual colors in the swatches instead of the name. */
hexColors?: string[] hexColors?: string[]
} }
export interface ProductVariant {
export type ProductVariant = { /**
* The variant's id. */
id: string | number id: string | number
/**
* List of product options. */
options: ProductOption[] options: ProductOption[]
/**
* Indicates if the variant is available for sale. */
availableForSale?: boolean availableForSale?: boolean
} }
export type Product = { export interface Product {
/**
* The product's id. */
id: string id: string
/**
* The product's name. */
name: string name: string
/**
* Stripped description of the product, single line. */
description: string description: string
/**
* The description of the product, complete with HTML formatting. */
descriptionHtml?: string descriptionHtml?: string
/**
* The SKU (stock keeping unit) associated with the product.
*/
sku?: string sku?: string
/**
* A human-friendly unique string for the product, automatically generated from its title. */
slug?: string slug?: string
/**
* A human-friendly string for the product, containing U. */
path?: string path?: string
/**
* List of images associated with the product. */
images: ProductImage[] images: ProductImage[]
/**
* List of the products variants. */
variants: ProductVariant[] variants: ProductVariant[]
/**
* The product's base price. Could be the minimum value, or default variant price. */
price: ProductPrice price: ProductPrice
/**
* The product's price. */
options: ProductOption[] options: ProductOption[]
/**
* The products vendor name. */
vendor?: string vendor?: string
} }
export type SearchProductsBody = { export interface SearchProductsBody {
/**
* The search query string to filter the products by.
*/
search?: string search?: string
/**
* The category ID to filter the products by.
*/
categoryId?: string | number categoryId?: string | number
/**
* The brand ID to filter the products by.
*/
brandId?: string | number brandId?: string | number
/**
* The sort order to sort the products by.
*/
sort?: string sort?: string
/**
* The locale code, used to localize the product data (if the provider supports it).
*/
locale?: string locale?: string
} }
export type ProductTypes = { export interface SearchProductsHook {
product: Product
searchBody: SearchProductsBody
}
export type SearchProductsHook<T extends ProductTypes = ProductTypes> = {
data: { data: {
products: T['product'][] /**
* List of products matching the query. */
products: Product[]
/**
* Indicates if there are any products matching the query. */
found: boolean found: boolean
} }
body: T['searchBody'] body: SearchProductsBody
input: T['searchBody'] /**
fetcherInput: T['searchBody'] * Indicates if the request is loading. */
input: SearchProductsBody
fetcherInput: SearchProductsBody
} }
export type ProductsSchema<T extends ProductTypes = ProductTypes> = { export interface ProductsSchema {
endpoint: { endpoint: {
options: {} options: {}
handlers: { handlers: {
getProducts: SearchProductsHook<T> getProducts: SearchProductsHook
} }
} }
} }
export type GetAllProductPathsOperation<T extends ProductTypes = ProductTypes> = export interface GetAllProductPathsOperation {
{ data: { products: Pick<Product, 'path'>[] }
data: { products: Pick<T['product'], 'path'>[] } variables: { first?: number }
variables: { first?: number } }
}
export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = { export interface GetAllProductsOperation {
data: { products: T['product'][] } data: { products: Product[] }
variables: { variables: {
relevance?: 'featured' | 'best_selling' | 'newest' relevance?: 'featured' | 'best_selling' | 'newest'
ids?: string[] ids?: string[]
@ -93,7 +159,11 @@ export type GetAllProductsOperation<T extends ProductTypes = ProductTypes> = {
} }
} }
export type GetProductOperation<T extends ProductTypes = ProductTypes> = { export interface GetProductOperation {
data: { product?: T['product'] } /**
* Returned data from the operation. */
data: { product?: Product }
/**
* The variables to pass to the operation.*/
variables: { path: string; slug?: never } | { path?: never; slug: string } variables: { path: string; slug?: never } | { path?: never; slug: string }
} }

View File

@ -13,30 +13,30 @@ import {
export default function getProductOperation({ export default function getProductOperation({
commerce, commerce,
}: OperationContext<Provider>) { }: OperationContext<Provider>) {
async function getProduct<T extends GetProductOperation>(opts: { async function getProduct(opts: {
variables: T['variables'] variables: GetProductOperation['variables']
config?: Partial<ShopifyConfig> config?: Partial<ShopifyConfig>
preview?: boolean preview?: boolean
}): Promise<T['data']> }): Promise<GetProductOperation['data']>
async function getProduct<T extends GetProductOperation>( async function getProduct(
opts: { opts: {
variables: T['variables'] variables: GetProductOperation['variables']
config?: Partial<ShopifyConfig> config?: Partial<ShopifyConfig>
preview?: boolean preview?: boolean
} & OperationOptions } & OperationOptions
): Promise<T['data']> ): Promise<GetProductOperation['data']>
async function getProduct<T extends GetProductOperation>({ async function getProduct({
query = getProductQuery, query = getProductQuery,
variables, variables,
config: cfg, config: cfg,
}: { }: {
query?: string query?: string
variables: T['variables'] variables: GetProductOperation['variables']
config?: Partial<ShopifyConfig> config?: Partial<ShopifyConfig>
preview?: boolean preview?: boolean
}): Promise<T['data']> { }): Promise<GetProductOperation['data']> {
const { fetch, locale } = commerce.getConfig(cfg) const { fetch, locale } = commerce.getConfig(cfg)
const { const {