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 '..'
export type UseSearch<
H extends SWRHook<SearchProductsHook<any>> = SWRHook<SearchProductsHook>
H extends SWRHook<SearchProductsHook> = SWRHook<SearchProductsHook>
> = ReturnType<H['useHook']>
export const fetcher: HookFetcherFn<SearchProductsHook> = SWRFetcher

View File

@ -1,14 +1,68 @@
import type { Discount, Measurement, Image } from './common'
export type SelectedOption = {
// The option's id.
/**
* The selected option's id
*/
id?: string
// The product options name.
/**
* The product options name. */
name: string
/// The product options value.
/**
* The product options value. */
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 = {
id: string
variantId: string
@ -16,69 +70,50 @@ export type LineItem = {
name: string
quantity: number
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
variant: ProductVariant
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
export type Cart = {
/**
* The cart's id. */
id: string
// ID of the customer to which the cart belongs.
/**
* ID of the customer to which the cart belongs. */
customerId?: string
// The email assigned to this cart
/**
* The email assigned to this cart. */
email?: string
// The date and time when the cart was created.
/**
* The date and time when the cart was created. */
createdAt: string
// The currency used for this cart
/**
* The currency used for this cart */
currency: { code: string }
// Specifies if taxes are included in the line items.
/**
* Specifies if taxes are included in the line items. */
taxesIncluded: boolean
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
// Price of the cart before duties, shipping and taxes.
/**
* Price of the cart before duties, shipping and taxes.*/
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
// Discounts that have been applied on the cart.
/**
* Discounts that have been applied on the cart.*/
discounts?: Discount[]
}

View File

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

View File

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