fix: Validate boolean query params (#8834)
This commit is contained in:
@@ -1092,6 +1092,58 @@ medusaIntegrationTestRunner({
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("should get product variants filtered by manage_inventory", async () => {
|
||||
const payload = {
|
||||
title: "Test product - 1",
|
||||
handle: "test-1",
|
||||
variants: [
|
||||
{
|
||||
title: "Custom inventory 1",
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
manage_inventory: true,
|
||||
inventory_items: [],
|
||||
},
|
||||
{
|
||||
title: "Custom inventory 2",
|
||||
prices: [{ currency_code: "usd", amount: 100 }],
|
||||
manage_inventory: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const product = (
|
||||
await api.post(`/admin/products`, payload, adminHeaders)
|
||||
).data.product
|
||||
|
||||
let variants = (
|
||||
await api.get(
|
||||
`/admin/products/${product.id}/variants?manage_inventory=true`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.variants
|
||||
|
||||
expect(variants).toEqual([
|
||||
expect.objectContaining({
|
||||
title: "Custom inventory 1",
|
||||
product_id: product.id,
|
||||
}),
|
||||
])
|
||||
|
||||
variants = (
|
||||
await api.get(
|
||||
`/admin/products/${product.id}/variants?manage_inventory=false`,
|
||||
adminHeaders
|
||||
)
|
||||
).data.variants
|
||||
|
||||
expect(variants).toEqual([
|
||||
expect.objectContaining({
|
||||
title: "Custom inventory 2",
|
||||
product_id: product.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/products", () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import { createFindParams } from "../../utils/validators"
|
||||
|
||||
export type AdminFulfillmentProvidersParamsType = z.infer<
|
||||
@@ -13,7 +13,7 @@ export const AdminFulfillmentProvidersParams = createFindParams({
|
||||
z.object({
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
stock_location_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
is_enabled: OptionalBooleanValidator,
|
||||
is_enabled: booleanString().optional(),
|
||||
q: z.string().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -27,7 +27,7 @@ export const AdminGetInventoryItemsParams = createFindParams({
|
||||
mid_code: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
hs_code: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
material: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
requires_shipping: OptionalBooleanValidator,
|
||||
requires_shipping: booleanString().optional(),
|
||||
weight: createOperatorMap(z.number(), parseFloat).optional(),
|
||||
length: createOperatorMap(z.number(), parseFloat).optional(),
|
||||
height: createOperatorMap(z.number(), parseFloat).optional(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -34,7 +35,7 @@ export const AdminGetPaymentProvidersParams = createFindParams({
|
||||
}).merge(
|
||||
z.object({
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
is_enabled: z.boolean().optional(),
|
||||
is_enabled: booleanString().optional(),
|
||||
$and: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
|
||||
$or: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -11,8 +11,8 @@ export type AdminProductCategoryParamsType = z.infer<
|
||||
>
|
||||
export const AdminProductCategoryParams = createSelectParams().merge(
|
||||
z.object({
|
||||
include_ancestors_tree: OptionalBooleanValidator,
|
||||
include_descendants_tree: OptionalBooleanValidator,
|
||||
include_ancestors_tree: booleanString().optional(),
|
||||
include_descendants_tree: booleanString().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -29,10 +29,10 @@ export const AdminProductCategoriesParams = createFindParams({
|
||||
description: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
handle: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
include_ancestors_tree: OptionalBooleanValidator,
|
||||
include_descendants_tree: OptionalBooleanValidator,
|
||||
is_internal: OptionalBooleanValidator,
|
||||
is_active: OptionalBooleanValidator,
|
||||
include_ancestors_tree: booleanString().optional(),
|
||||
include_descendants_tree: booleanString().optional(),
|
||||
is_internal: booleanString().optional(),
|
||||
is_active: booleanString().optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import { createFindParams, createOperatorMap } from "../../utils/validators"
|
||||
|
||||
export type AdminGetProductVariantsParamsType = z.infer<
|
||||
@@ -11,8 +12,8 @@ export const AdminGetProductVariantsParams = createFindParams({
|
||||
z.object({
|
||||
q: z.string().optional(),
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
manage_inventory: z.boolean().optional(),
|
||||
allow_backorder: z.boolean().optional(),
|
||||
manage_inventory: booleanString().optional(),
|
||||
allow_backorder: booleanString().optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { BatchMethodRequest } from "@medusajs/types"
|
||||
import { ProductStatus } from "@medusajs/utils"
|
||||
import { z } from "zod"
|
||||
import {
|
||||
booleanString,
|
||||
GetProductsParams,
|
||||
transformProductParams,
|
||||
} from "../../utils/common-validators"
|
||||
import { z } from "zod"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -28,8 +29,8 @@ export const AdminGetProductVariantsParams = createFindParams({
|
||||
z.object({
|
||||
q: z.string().optional(),
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
manage_inventory: z.boolean().optional(),
|
||||
allow_backorder: z.boolean().optional(),
|
||||
manage_inventory: booleanString().optional(),
|
||||
allow_backorder: booleanString().optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
@@ -140,8 +141,8 @@ export const CreateProductVariant = z
|
||||
barcode: z.string().nullish(),
|
||||
hs_code: z.string().nullish(),
|
||||
mid_code: z.string().nullish(),
|
||||
allow_backorder: z.boolean().optional().default(false),
|
||||
manage_inventory: z.boolean().optional().default(true),
|
||||
allow_backorder: booleanString().optional().default(false),
|
||||
manage_inventory: booleanString().optional().default(true),
|
||||
variant_rank: z.number().optional(),
|
||||
weight: z.number().nullish(),
|
||||
length: z.number().nullish(),
|
||||
@@ -177,8 +178,8 @@ export const UpdateProductVariant = z
|
||||
barcode: z.string().nullish(),
|
||||
hs_code: z.string().nullish(),
|
||||
mid_code: z.string().nullish(),
|
||||
allow_backorder: z.boolean().optional(),
|
||||
manage_inventory: z.boolean().optional(),
|
||||
allow_backorder: booleanString().optional(),
|
||||
manage_inventory: booleanString().optional(),
|
||||
variant_rank: z.number().optional(),
|
||||
weight: z.number().nullish(),
|
||||
length: z.number().nullish(),
|
||||
@@ -211,8 +212,8 @@ export const CreateProduct = z
|
||||
title: z.string(),
|
||||
subtitle: z.string().nullish(),
|
||||
description: z.string().nullish(),
|
||||
is_giftcard: z.boolean().optional().default(false),
|
||||
discountable: z.boolean().optional().default(true),
|
||||
is_giftcard: booleanString().optional().default(false),
|
||||
discountable: booleanString().optional().default(true),
|
||||
images: z.array(z.object({ url: z.string() })).optional(),
|
||||
thumbnail: z.string().nullish(),
|
||||
handle: z.string().optional(),
|
||||
@@ -242,8 +243,8 @@ export type AdminUpdateProductType = z.infer<typeof UpdateProduct>
|
||||
export const UpdateProduct = z
|
||||
.object({
|
||||
title: z.string().optional(),
|
||||
discountable: z.boolean().optional(),
|
||||
is_giftcard: z.boolean().optional(),
|
||||
discountable: booleanString().optional(),
|
||||
is_giftcard: booleanString().optional(),
|
||||
options: z.array(UpdateProductOption).optional(),
|
||||
variants: z.array(UpdateProductVariant).optional(),
|
||||
status: statusEnum.optional(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -23,7 +23,7 @@ export const AdminGetSalesChannelsParams = createFindParams({
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
name: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
description: z.string().optional(),
|
||||
is_disabled: OptionalBooleanValidator,
|
||||
is_disabled: booleanString().optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import { createFindParams } from "../../utils/validators"
|
||||
|
||||
export type StoreGetPaymentProvidersParamsType = z.infer<
|
||||
@@ -11,7 +12,7 @@ export const StoreGetPaymentProvidersParams = createFindParams({
|
||||
z.object({
|
||||
region_id: z.string(),
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
is_enabled: z.boolean().optional(),
|
||||
is_enabled: booleanString().optional(),
|
||||
$and: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
|
||||
$or: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod"
|
||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
||||
import { booleanString } from "../../utils/common-validators"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
@@ -11,8 +11,8 @@ export type StoreProductCategoryParamsType = z.infer<
|
||||
>
|
||||
export const StoreProductCategoryParams = createSelectParams().merge(
|
||||
z.object({
|
||||
include_ancestors_tree: OptionalBooleanValidator,
|
||||
include_descendants_tree: OptionalBooleanValidator,
|
||||
include_ancestors_tree: booleanString().optional(),
|
||||
include_descendants_tree: booleanString().optional(),
|
||||
})
|
||||
)
|
||||
|
||||
@@ -29,8 +29,8 @@ export const StoreProductCategoriesParams = createFindParams({
|
||||
description: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
handle: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
include_ancestors_tree: OptionalBooleanValidator,
|
||||
include_descendants_tree: OptionalBooleanValidator,
|
||||
include_ancestors_tree: booleanString().optional(),
|
||||
include_descendants_tree: booleanString().optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
|
||||
@@ -32,7 +32,24 @@ const optionalBooleanMapper = new Map([
|
||||
["false", false],
|
||||
])
|
||||
|
||||
/**
|
||||
* @deprecated Use `booleanString` instead
|
||||
* It support the chainable API of zod. Please note it does not come with `.optional()` by default
|
||||
*/
|
||||
export const OptionalBooleanValidator = z.preprocess(
|
||||
(val: any) => optionalBooleanMapper.get(val?.toLowerCase()),
|
||||
z.boolean().optional()
|
||||
)
|
||||
|
||||
/**
|
||||
* Validates that a value is a boolean when it is passed as a string.
|
||||
*/
|
||||
export const booleanString = () =>
|
||||
z
|
||||
.union([z.boolean(), z.string()])
|
||||
.refine((value) => {
|
||||
return ["true", "false"].includes(value.toString().toLowerCase())
|
||||
})
|
||||
.transform((value) => {
|
||||
return value.toString().toLowerCase() === "true"
|
||||
})
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FilterableProductProps } from "@medusajs/types"
|
||||
import { ProductStatus } from "@medusajs/utils"
|
||||
import { z } from "zod"
|
||||
import { createOperatorMap } from "../../validators"
|
||||
import { OptionalBooleanValidator } from "../common"
|
||||
import { FilterableProductProps } from "@medusajs/types"
|
||||
import { booleanString } from "../common"
|
||||
|
||||
export const ProductStatusEnum = z.nativeEnum(ProductStatus)
|
||||
|
||||
@@ -11,7 +11,7 @@ export const GetProductsParams = z.object({
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
title: z.string().optional(),
|
||||
handle: z.string().optional(),
|
||||
is_giftcard: OptionalBooleanValidator,
|
||||
is_giftcard: booleanString().optional(),
|
||||
category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
sales_channel_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
collection_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
|
||||
Reference in New Issue
Block a user