feat(medusa): migrate store cart endpoints to zod (#7130)

This commit is contained in:
Riqwan Thamir authored and GitHub committed 2024-04-23 13:31:52 +02:00
1 parent cfd765bece
commit 2446151420
13 files changed
+275 -292

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
feat(medusa): migrate store cart endpoints to zod
@@ -4,12 +4,15 @@ import {
} from "@medusajs/core-flows" } from "@medusajs/core-flows"
import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { ICartModuleService } from "@medusajs/types" import { ICartModuleService } from "@medusajs/types"
import { MedusaError, remoteQueryObjectFromString } from "@medusajs/utils" import { MedusaError } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../../../types/routing"
import { defaultStoreCartFields } from "../../../query-config" import { refetchCart } from "../../../helpers"
import { StorePostCartsCartLineItemsItemReq } from "./validators" import { StoreUpdateCartLineItemType } from "../../../validators"
export const POST = async (req: MedusaRequest, res: MedusaResponse) => { export const POST = async (
req: MedusaRequest<StoreUpdateCartLineItemType>,
res: MedusaResponse
) => {
const cartModuleService = req.scope.resolve<ICartModuleService>( const cartModuleService = req.scope.resolve<ICartModuleService>(
ModuleRegistrationName.CART ModuleRegistrationName.CART
) )
@@ -31,7 +34,7 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
const input = { const input = {
cart, cart,
item, item,
update: req.validatedBody as StorePostCartsCartLineItemsItemReq, update: req.validatedBody,
} }
const { errors } = await updateLineItemInCartWorkflow(req.scope).run({ const { errors } = await updateLineItemInCartWorkflow(req.scope).run({
@@ -43,16 +46,11 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
throw errors[0].error throw errors[0].error
} }
const remoteQuery = req.scope.resolve("remoteQuery") const updatedCart = await refetchCart(
req.params.id,
const query = remoteQueryObjectFromString({ req.scope,
entryPoint: "cart", req.remoteQueryConfig.fields
fields: defaultStoreCartFields, )
})
const [updatedCart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
res.status(200).json({ cart: updatedCart }) res.status(200).json({ cart: updatedCart })
} }
@@ -69,16 +67,11 @@ export const DELETE = async (req: MedusaRequest, res: MedusaResponse) => {
throw errors[0].error throw errors[0].error
} }
const remoteQuery = req.scope.resolve("remoteQuery") const cart = await refetchCart(
req.params.id,
const query = remoteQueryObjectFromString({ req.scope,
entryPoint: "cart", req.remoteQueryConfig.fields
fields: defaultStoreCartFields, )
})
const [cart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -1,9 +0,0 @@
import { IsInt, IsOptional } from "class-validator"
export class StorePostCartsCartLineItemsItemReq {
@IsInt()
quantity: number
@IsOptional()
metadata?: Record<string, unknown> | undefined
}
@@ -1,24 +1,20 @@
import { addToCartWorkflow } from "@medusajs/core-flows" import { addToCartWorkflow } from "@medusajs/core-flows"
import { LinkModuleUtils, Modules } from "@medusajs/modules-sdk"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { defaultStoreCartFields } from "../../query-config" import { refetchCart } from "../../helpers"
import { StorePostCartsCartLineItemsReq } from "./validators" import { StoreAddCartLineItemType } from "../../validators"
export const POST = async (req: MedusaRequest, res: MedusaResponse) => { export const POST = async (
const remoteQuery = req.scope.resolve(LinkModuleUtils.REMOTE_QUERY) req: MedusaRequest<StoreAddCartLineItemType>,
res: MedusaResponse
const query = remoteQueryObjectFromString({ ) => {
entryPoint: Modules.CART, const cart = await refetchCart(
fields: defaultStoreCartFields, req.params.id,
}) req.scope,
req.remoteQueryConfig.fields
const [cart] = await remoteQuery(query, { )
cart: { id: req.params.id },
})
const workflowInput = { const workflowInput = {
items: [req.validatedBody as StorePostCartsCartLineItemsReq], items: [req.validatedBody],
cart, cart,
} }
@@ -31,9 +27,11 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
throw errors[0].error throw errors[0].error
} }
const [updatedCart] = await remoteQuery(query, { const updatedCart = await refetchCart(
cart: { id: req.params.id }, req.params.id,
}) req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ cart: updatedCart }) res.status(200).json({ cart: updatedCart })
} }
@@ -1,12 +0,0 @@
import { IsInt, IsOptional, IsString } from "class-validator"
export class StorePostCartsCartLineItemsReq {
@IsString()
variant_id: string
@IsInt()
quantity: number
@IsOptional()
metadata?: Record<string, unknown> | undefined
}
@@ -1,28 +1,19 @@
import { createPaymentCollectionForCartWorkflow } from "@medusajs/core-flows" import { createPaymentCollectionForCartWorkflow } from "@medusajs/core-flows"
import { UpdateCartDataDTO } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { defaultStoreCartFields } from "../../query-config" import { refetchCart } from "../../helpers"
import { StoreUpdateCartType } from "../../validators"
export const POST = async ( export const POST = async (
req: MedusaRequest<UpdateCartDataDTO>, req: MedusaRequest<StoreUpdateCartType>,
res: MedusaResponse res: MedusaResponse
) => { ) => {
const workflow = createPaymentCollectionForCartWorkflow(req.scope) const workflow = createPaymentCollectionForCartWorkflow(req.scope)
let cart = await refetchCart(req.params.id, req.scope, [
const remoteQuery = req.scope.resolve("remoteQuery") "id",
"currency_code",
let [cart] = await remoteQuery( "region_id",
{ "total",
cart: { ])
fields: ["id", "currency_code", "region_id", "total"],
},
},
{
cart: { id: req.params.id },
}
)
const { errors } = await workflow.run({ const { errors } = await workflow.run({
input: { input: {
@@ -38,13 +29,11 @@ export const POST = async (
throw errors[0].error throw errors[0].error
} }
const query = remoteQueryObjectFromString({ cart = await refetchCart(
entryPoint: "cart", req.params.id,
variables: { id: req.params.id }, req.scope,
fields: defaultStoreCartFields, req.remoteQueryConfig.fields
}) )
;[cart] = await remoteQuery(query)
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -1,13 +1,18 @@
import { updateCartPromotionsWorkflow } from "@medusajs/core-flows" import { updateCartPromotionsWorkflow } from "@medusajs/core-flows"
import { PromotionActions, remoteQueryObjectFromString } from "@medusajs/utils" import { PromotionActions } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { defaultStoreCartFields } from "../../query-config" import { refetchCart } from "../../helpers"
import { StorePostCartsCartPromotionsReq } from "../../validators" import {
StoreAddCartPromotionsType,
StoreRemoveCartPromotionsType,
} from "../../validators"
export const POST = async (req: MedusaRequest, res: MedusaResponse) => { export const POST = async (
const remoteQuery = req.scope.resolve("remoteQuery") req: MedusaRequest<StoreAddCartPromotionsType>,
res: MedusaResponse
) => {
const workflow = updateCartPromotionsWorkflow(req.scope) const workflow = updateCartPromotionsWorkflow(req.scope)
const payload = req.validatedBody as StorePostCartsCartPromotionsReq const payload = req.validatedBody
const { errors } = await workflow.run({ const { errors } = await workflow.run({
input: { input: {
@@ -22,22 +27,21 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
throw errors[0].error throw errors[0].error
} }
const query = remoteQueryObjectFromString({ const cart = await refetchCart(
entryPoint: "cart", req.params.id,
fields: defaultStoreCartFields, req.scope,
}) req.remoteQueryConfig.fields
)
const [cart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
export const DELETE = async (req: MedusaRequest, res: MedusaResponse) => { export const DELETE = async (
const remoteQuery = req.scope.resolve("remoteQuery") req: MedusaRequest<StoreRemoveCartPromotionsType>,
res: MedusaResponse
) => {
const workflow = updateCartPromotionsWorkflow(req.scope) const workflow = updateCartPromotionsWorkflow(req.scope)
const payload = req.validatedBody as StorePostCartsCartPromotionsReq const payload = req.validatedBody
const { errors } = await workflow.run({ const { errors } = await workflow.run({
input: { input: {
@@ -52,14 +56,11 @@ export const DELETE = async (req: MedusaRequest, res: MedusaResponse) => {
throw errors[0].error throw errors[0].error
} }
const query = remoteQueryObjectFromString({ const cart = await refetchCart(
entryPoint: "cart", req.params.id,
fields: defaultStoreCartFields, req.scope,
}) req.remoteQueryConfig.fields
)
const [cart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -1,21 +1,15 @@
import { updateCartWorkflow } from "@medusajs/core-flows" import { updateCartWorkflow } from "@medusajs/core-flows"
import { LinkModuleUtils, Modules } from "@medusajs/modules-sdk"
import { UpdateCartDataDTO } from "@medusajs/types" import { UpdateCartDataDTO } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { defaultStoreCartFields } from "../query-config" import { refetchCart } from "../helpers"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => { export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const remoteQuery = req.scope.resolve(LinkModuleUtils.REMOTE_QUERY) const cart = await refetchCart(
const variables = { id: req.params.id } req.params.id,
req.scope,
const query = remoteQueryObjectFromString({ req.remoteQueryConfig.fields
entryPoint: Modules.CART, )
fields: req.remoteQueryConfig.fields,
})
const [cart] = await remoteQuery(query, { cart: variables })
res.json({ cart }) res.json({ cart })
} }
@@ -38,16 +32,11 @@ export const POST = async (
throw errors[0].error throw errors[0].error
} }
const remoteQuery = req.scope.resolve(LinkModuleUtils.REMOTE_QUERY) const cart = await refetchCart(
req.params.id,
const query = remoteQueryObjectFromString({ req.scope,
entryPoint: Modules.CART, req.remoteQueryConfig.fields
fields: defaultStoreCartFields, )
})
const [cart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -1,15 +1,10 @@
import { updateTaxLinesWorkflow } from "@medusajs/core-flows" import { updateTaxLinesWorkflow } from "@medusajs/core-flows"
import { Modules } from "@medusajs/modules-sdk"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing" import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { defaultStoreCartFields } from "../../query-config" import { refetchCart } from "../../helpers"
import { StorePostCartsCartTaxesReq } from "../../validators" import { StoreCalculateCartTaxesType } from "../../validators"
export const POST = async ( export const POST = async (
req: MedusaRequest<StorePostCartsCartTaxesReq>, req: MedusaRequest<StoreCalculateCartTaxesType>,
res: MedusaResponse res: MedusaResponse
) => { ) => {
const workflow = updateTaxLinesWorkflow(req.scope) const workflow = updateTaxLinesWorkflow(req.scope)
@@ -26,18 +21,11 @@ export const POST = async (
throw errors[0].error throw errors[0].error
} }
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY) const cart = await refetchCart(
req.params.id,
const query = remoteQueryObjectFromString({ req.scope,
entryPoint: Modules.CART, req.remoteQueryConfig.fields
fields: defaultStoreCartFields, )
})
const [cart] = await remoteQuery(query, {
cart: { id: req.params.id },
})
// TODO: wrap result with totals when totals calculation is ready
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -0,0 +1,22 @@
import { MedusaContainer } from "@medusajs/types"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
export const refetchCart = async (
id: string,
scope: MedusaContainer,
fields: string[]
) => {
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const queryObject = remoteQueryObjectFromString({
entryPoint: "cart",
variables: { filters: { id } },
fields,
})
const [cart] = await remoteQuery(queryObject)
return cart
}
@@ -1,15 +1,17 @@
import { transformBody, transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types" import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { authenticate } from "../../../utils/authenticate-middleware" import { authenticate } from "../../../utils/authenticate-middleware"
import { StorePostCartsCartLineItemsItemReq } from "./[id]/line-items/[line_id]/validators" import { validateAndTransformBody } from "../../utils/validate-body"
import { StorePostCartsCartLineItemsReq } from "./[id]/line-items/validators" import { validateAndTransformQuery } from "../../utils/validate-query"
import * as QueryConfig from "./query-config" import * as QueryConfig from "./query-config"
import { import {
StoreDeleteCartsCartPromotionsReq, StoreAddCartLineItem,
StoreGetCartsCartParams, StoreAddCartPromotions,
StorePostCartReq, StoreCalculateCartTaxes,
StorePostCartsCartPromotionsReq, StoreCreateCart,
StorePostCartsCartReq, StoreGetCartsCart,
StoreRemoveCartPromotions,
StoreUpdateCart,
StoreUpdateCartLineItem,
} from "./validators" } from "./validators"
export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [ export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [
@@ -26,8 +28,8 @@ export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [
method: ["GET"], method: ["GET"],
matcher: "/store/carts/:id", matcher: "/store/carts/:id",
middlewares: [ middlewares: [
transformQuery( validateAndTransformQuery(
StoreGetCartsCartParams, StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig QueryConfig.retrieveTransformQueryConfig
), ),
], ],
@@ -35,34 +37,99 @@ export const storeCartRoutesMiddlewares: MiddlewareRoute[] = [
{ {
method: ["POST"], method: ["POST"],
matcher: "/store/carts", matcher: "/store/carts",
middlewares: [transformBody(StorePostCartReq)], middlewares: [
validateAndTransformBody(StoreCreateCart),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["POST"], method: ["POST"],
matcher: "/store/carts/:id", matcher: "/store/carts/:id",
middlewares: [transformBody(StorePostCartsCartReq)], middlewares: [
validateAndTransformBody(StoreUpdateCart),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["POST"], method: ["POST"],
matcher: "/store/carts/:id/line-items", matcher: "/store/carts/:id/line-items",
middlewares: [transformBody(StorePostCartsCartLineItemsReq)], middlewares: [
validateAndTransformBody(StoreAddCartLineItem),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["POST"], method: ["POST"],
matcher: "/store/carts/:id/line-items/:line_id", matcher: "/store/carts/:id/line-items/:line_id",
middlewares: [transformBody(StorePostCartsCartLineItemsItemReq)], middlewares: [
validateAndTransformBody(StoreUpdateCartLineItem),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["DELETE"], method: ["DELETE"],
matcher: "/store/carts/:id/line-items/:line_id", matcher: "/store/carts/:id/line-items/:line_id",
middlewares: [
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["POST"],
matcher: "/store/carts/:id/promotions", matcher: "/store/carts/:id/promotions",
middlewares: [transformBody(StorePostCartsCartPromotionsReq)], middlewares: [
validateAndTransformBody(StoreAddCartPromotions),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/store/carts/:id/taxes",
middlewares: [
validateAndTransformBody(StoreCalculateCartTaxes),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/store/carts/:id/payment-collections",
middlewares: [
validateAndTransformBody(StoreUpdateCart),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
{ {
method: ["DELETE"], method: ["DELETE"],
matcher: "/store/carts/:id/promotions", matcher: "/store/carts/:id/promotions",
middlewares: [transformBody(StoreDeleteCartsCartPromotionsReq)], middlewares: [
validateAndTransformBody(StoreRemoveCartPromotions),
validateAndTransformQuery(
StoreGetCartsCart,
QueryConfig.retrieveTransformQueryConfig
),
],
}, },
] ]
@@ -1,12 +1,10 @@
import { createCartWorkflow } from "@medusajs/core-flows" import { createCartWorkflow } from "@medusajs/core-flows"
import { LinkModuleUtils, Modules } from "@medusajs/modules-sdk"
import { CreateCartWorkflowInputDTO } from "@medusajs/types" import { CreateCartWorkflowInputDTO } from "@medusajs/types"
import { remoteQueryObjectFromString } from "@medusajs/utils"
import { import {
AuthenticatedMedusaRequest, AuthenticatedMedusaRequest,
MedusaResponse, MedusaResponse,
} from "../../../types/routing" } from "../../../types/routing"
import { defaultStoreCartFields } from "../carts/query-config" import { refetchCart } from "./helpers"
export const POST = async ( export const POST = async (
req: AuthenticatedMedusaRequest<CreateCartWorkflowInputDTO>, req: AuthenticatedMedusaRequest<CreateCartWorkflowInputDTO>,
@@ -26,13 +24,11 @@ export const POST = async (
throw errors[0].error throw errors[0].error
} }
const remoteQuery = req.scope.resolve(LinkModuleUtils.REMOTE_QUERY) const cart = await refetchCart(
const query = remoteQueryObjectFromString({ result.id,
entryPoint: Modules.CART, req.scope,
fields: defaultStoreCartFields, req.remoteQueryConfig.fields
}) )
const [cart] = await remoteQuery(query, { cart: { id: result.id } })
res.status(200).json({ cart }) res.status(200).json({ cart })
} }
@@ -1,118 +1,74 @@
import { Type } from "class-transformer" import { z } from "zod"
import { import { AddressPayload } from "../../utils/common-validators"
IsArray, import { createSelectParams } from "../../utils/validators"
IsEmail,
IsInt,
IsNotEmpty,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { AddressPayload, FindParams } from "../../../types/common"
import { IsType } from "../../../utils"
export class StoreGetCartsCartParams extends FindParams {} export type StoreGetPromotionType = z.infer<typeof StoreGetCartsCart>
export const StoreGetCartsCart = createSelectParams()
export class Item { const ItemSchema = z.object({
@IsNotEmpty() variant_id: z.string(),
@IsString() quantity: z.number(),
variant_id: string })
@IsNotEmpty() export type StoreCreateCartType = z.infer<typeof StoreCreateCart>
@IsInt() export const StoreCreateCart = z
quantity: number .object({
} region_id: z.string().optional().nullable(),
shipping_address: z.union([AddressPayload, z.string()]).optional(),
billing_address: z.union([AddressPayload, z.string()]).optional(),
email: z.string().email().optional().nullable(),
currency_code: z.string().optional(),
items: z.array(ItemSchema).optional(),
sales_channel_id: z.string().optional().nullable(),
metadata: z.record(z.unknown()).optional().nullable(),
})
.strict()
export class StorePostCartReq { export type StoreAddCartPromotionsType = z.infer<typeof StoreAddCartPromotions>
@IsOptional() export const StoreAddCartPromotions = z
@IsString() .object({
region_id?: string promo_codes: z.array(z.string()),
})
.strict()
@IsOptional() export type StoreRemoveCartPromotionsType = z.infer<
@IsType([AddressPayload, String]) typeof StoreRemoveCartPromotions
shipping_address?: AddressPayload | string >
export const StoreRemoveCartPromotions = z
.object({
promo_codes: z.array(z.string()),
})
.strict()
@IsOptional() export type StoreUpdateCartType = z.infer<typeof StoreUpdateCart>
@IsType([AddressPayload, String]) export const StoreUpdateCart = z
billing_address?: AddressPayload | string .object({
region_id: z.string().optional().nullable(),
email: z.string().email().optional().nullable(),
billing_address: z.union([AddressPayload, z.string()]).optional(),
shipping_address: z.union([AddressPayload, z.string()]).optional(),
sales_channel_id: z.string().optional().nullable(),
metadata: z.record(z.unknown()).optional().nullable(),
promo_codes: z.array(z.string()).optional(),
})
.strict()
@IsOptional() export type StoreCalculateCartTaxesType = z.infer<
@IsString() typeof StoreCalculateCartTaxes
email?: string >
export const StoreCalculateCartTaxes = createSelectParams()
@IsOptional() export type StoreAddCartLineItemType = z.infer<typeof StoreAddCartLineItem>
@IsString() export const StoreAddCartLineItem = z.object({
currency_code?: string variant_id: z.string(),
quantity: z.number(),
metadata: z.record(z.unknown()).optional(),
})
@IsOptional() export type StoreUpdateCartLineItemType = z.infer<
@IsArray() typeof StoreUpdateCartLineItem
@ValidateNested({ each: true }) >
@Type(() => Item) export const StoreUpdateCartLineItem = z.object({
items?: Item[] quantity: z.number(),
metadata: z.record(z.unknown()).optional(),
@IsString() })
@IsOptional()
sales_channel_id?: string
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
}
export class StorePostCartsCartPromotionsReq {
@IsArray()
@Type(() => String)
promo_codes: string[]
}
export class StoreDeleteCartsCartPromotionsReq {
@IsArray()
@Type(() => String)
promo_codes: string[]
}
export class StorePostCartsCartReq {
@IsOptional()
@IsString()
region_id?: string
@IsEmail()
@IsOptional()
email?: string
@IsOptional()
@IsType([AddressPayload, String])
billing_address?: AddressPayload | string
@IsOptional()
@IsType([AddressPayload, String])
shipping_address?: AddressPayload | string
@IsOptional()
@IsString()
sales_channel_id?: string
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
@IsOptional()
@IsArray()
@Type(() => String)
promo_codes?: string[]
// @IsOptional()
// @IsArray()
// @ValidateNested({ each: true })
// @Type(() => GiftCard)
// gift_cards?: GiftCard[]
// @IsOptional()
// @IsArray()
// @ValidateNested({ each: true })
// @Type(() => Discount)
// discounts?: Discount[]
}
export class StorePostCartsCartTaxesReq {}