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", () => {
|
describe("POST /admin/products", () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import { createFindParams } from "../../utils/validators"
|
import { createFindParams } from "../../utils/validators"
|
||||||
|
|
||||||
export type AdminFulfillmentProvidersParamsType = z.infer<
|
export type AdminFulfillmentProvidersParamsType = z.infer<
|
||||||
@@ -13,7 +13,7 @@ export const AdminFulfillmentProvidersParams = createFindParams({
|
|||||||
z.object({
|
z.object({
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
stock_location_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(),
|
q: z.string().optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -27,7 +27,7 @@ export const AdminGetInventoryItemsParams = createFindParams({
|
|||||||
mid_code: z.union([z.string(), z.array(z.string())]).optional(),
|
mid_code: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
hs_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(),
|
material: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
requires_shipping: OptionalBooleanValidator,
|
requires_shipping: booleanString().optional(),
|
||||||
weight: createOperatorMap(z.number(), parseFloat).optional(),
|
weight: createOperatorMap(z.number(), parseFloat).optional(),
|
||||||
length: createOperatorMap(z.number(), parseFloat).optional(),
|
length: createOperatorMap(z.number(), parseFloat).optional(),
|
||||||
height: createOperatorMap(z.number(), parseFloat).optional(),
|
height: createOperatorMap(z.number(), parseFloat).optional(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -34,7 +35,7 @@ export const AdminGetPaymentProvidersParams = createFindParams({
|
|||||||
}).merge(
|
}).merge(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
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(),
|
$and: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
|
||||||
$or: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
|
$or: z.lazy(() => AdminGetPaymentProvidersParams.array()).optional(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -11,8 +11,8 @@ export type AdminProductCategoryParamsType = z.infer<
|
|||||||
>
|
>
|
||||||
export const AdminProductCategoryParams = createSelectParams().merge(
|
export const AdminProductCategoryParams = createSelectParams().merge(
|
||||||
z.object({
|
z.object({
|
||||||
include_ancestors_tree: OptionalBooleanValidator,
|
include_ancestors_tree: booleanString().optional(),
|
||||||
include_descendants_tree: OptionalBooleanValidator,
|
include_descendants_tree: booleanString().optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,10 +29,10 @@ export const AdminProductCategoriesParams = createFindParams({
|
|||||||
description: z.union([z.string(), z.array(z.string())]).optional(),
|
description: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
handle: 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(),
|
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
include_ancestors_tree: OptionalBooleanValidator,
|
include_ancestors_tree: booleanString().optional(),
|
||||||
include_descendants_tree: OptionalBooleanValidator,
|
include_descendants_tree: booleanString().optional(),
|
||||||
is_internal: OptionalBooleanValidator,
|
is_internal: booleanString().optional(),
|
||||||
is_active: OptionalBooleanValidator,
|
is_active: booleanString().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import { createFindParams, createOperatorMap } from "../../utils/validators"
|
import { createFindParams, createOperatorMap } from "../../utils/validators"
|
||||||
|
|
||||||
export type AdminGetProductVariantsParamsType = z.infer<
|
export type AdminGetProductVariantsParamsType = z.infer<
|
||||||
@@ -11,8 +12,8 @@ export const AdminGetProductVariantsParams = createFindParams({
|
|||||||
z.object({
|
z.object({
|
||||||
q: z.string().optional(),
|
q: z.string().optional(),
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
manage_inventory: z.boolean().optional(),
|
manage_inventory: booleanString().optional(),
|
||||||
allow_backorder: z.boolean().optional(),
|
allow_backorder: booleanString().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { BatchMethodRequest } from "@medusajs/types"
|
import { BatchMethodRequest } from "@medusajs/types"
|
||||||
import { ProductStatus } from "@medusajs/utils"
|
import { ProductStatus } from "@medusajs/utils"
|
||||||
|
import { z } from "zod"
|
||||||
import {
|
import {
|
||||||
|
booleanString,
|
||||||
GetProductsParams,
|
GetProductsParams,
|
||||||
transformProductParams,
|
transformProductParams,
|
||||||
} from "../../utils/common-validators"
|
} from "../../utils/common-validators"
|
||||||
import { z } from "zod"
|
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -28,8 +29,8 @@ export const AdminGetProductVariantsParams = createFindParams({
|
|||||||
z.object({
|
z.object({
|
||||||
q: z.string().optional(),
|
q: z.string().optional(),
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
manage_inventory: z.boolean().optional(),
|
manage_inventory: booleanString().optional(),
|
||||||
allow_backorder: z.boolean().optional(),
|
allow_backorder: booleanString().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
@@ -140,8 +141,8 @@ export const CreateProductVariant = z
|
|||||||
barcode: z.string().nullish(),
|
barcode: z.string().nullish(),
|
||||||
hs_code: z.string().nullish(),
|
hs_code: z.string().nullish(),
|
||||||
mid_code: z.string().nullish(),
|
mid_code: z.string().nullish(),
|
||||||
allow_backorder: z.boolean().optional().default(false),
|
allow_backorder: booleanString().optional().default(false),
|
||||||
manage_inventory: z.boolean().optional().default(true),
|
manage_inventory: booleanString().optional().default(true),
|
||||||
variant_rank: z.number().optional(),
|
variant_rank: z.number().optional(),
|
||||||
weight: z.number().nullish(),
|
weight: z.number().nullish(),
|
||||||
length: z.number().nullish(),
|
length: z.number().nullish(),
|
||||||
@@ -177,8 +178,8 @@ export const UpdateProductVariant = z
|
|||||||
barcode: z.string().nullish(),
|
barcode: z.string().nullish(),
|
||||||
hs_code: z.string().nullish(),
|
hs_code: z.string().nullish(),
|
||||||
mid_code: z.string().nullish(),
|
mid_code: z.string().nullish(),
|
||||||
allow_backorder: z.boolean().optional(),
|
allow_backorder: booleanString().optional(),
|
||||||
manage_inventory: z.boolean().optional(),
|
manage_inventory: booleanString().optional(),
|
||||||
variant_rank: z.number().optional(),
|
variant_rank: z.number().optional(),
|
||||||
weight: z.number().nullish(),
|
weight: z.number().nullish(),
|
||||||
length: z.number().nullish(),
|
length: z.number().nullish(),
|
||||||
@@ -211,8 +212,8 @@ export const CreateProduct = z
|
|||||||
title: z.string(),
|
title: z.string(),
|
||||||
subtitle: z.string().nullish(),
|
subtitle: z.string().nullish(),
|
||||||
description: z.string().nullish(),
|
description: z.string().nullish(),
|
||||||
is_giftcard: z.boolean().optional().default(false),
|
is_giftcard: booleanString().optional().default(false),
|
||||||
discountable: z.boolean().optional().default(true),
|
discountable: booleanString().optional().default(true),
|
||||||
images: z.array(z.object({ url: z.string() })).optional(),
|
images: z.array(z.object({ url: z.string() })).optional(),
|
||||||
thumbnail: z.string().nullish(),
|
thumbnail: z.string().nullish(),
|
||||||
handle: z.string().optional(),
|
handle: z.string().optional(),
|
||||||
@@ -242,8 +243,8 @@ export type AdminUpdateProductType = z.infer<typeof UpdateProduct>
|
|||||||
export const UpdateProduct = z
|
export const UpdateProduct = z
|
||||||
.object({
|
.object({
|
||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
discountable: z.boolean().optional(),
|
discountable: booleanString().optional(),
|
||||||
is_giftcard: z.boolean().optional(),
|
is_giftcard: booleanString().optional(),
|
||||||
options: z.array(UpdateProductOption).optional(),
|
options: z.array(UpdateProductOption).optional(),
|
||||||
variants: z.array(UpdateProductVariant).optional(),
|
variants: z.array(UpdateProductVariant).optional(),
|
||||||
status: statusEnum.optional(),
|
status: statusEnum.optional(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -23,7 +23,7 @@ export const AdminGetSalesChannelsParams = createFindParams({
|
|||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
name: z.union([z.string(), z.array(z.string())]).optional(),
|
name: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
is_disabled: OptionalBooleanValidator,
|
is_disabled: booleanString().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import { createFindParams } from "../../utils/validators"
|
import { createFindParams } from "../../utils/validators"
|
||||||
|
|
||||||
export type StoreGetPaymentProvidersParamsType = z.infer<
|
export type StoreGetPaymentProvidersParamsType = z.infer<
|
||||||
@@ -11,7 +12,7 @@ export const StoreGetPaymentProvidersParams = createFindParams({
|
|||||||
z.object({
|
z.object({
|
||||||
region_id: z.string(),
|
region_id: z.string(),
|
||||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
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(),
|
$and: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
|
||||||
$or: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
|
$or: z.lazy(() => StoreGetPaymentProvidersParams.array()).optional(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { OptionalBooleanValidator } from "../../utils/common-validators"
|
import { booleanString } from "../../utils/common-validators"
|
||||||
import {
|
import {
|
||||||
createFindParams,
|
createFindParams,
|
||||||
createOperatorMap,
|
createOperatorMap,
|
||||||
@@ -11,8 +11,8 @@ export type StoreProductCategoryParamsType = z.infer<
|
|||||||
>
|
>
|
||||||
export const StoreProductCategoryParams = createSelectParams().merge(
|
export const StoreProductCategoryParams = createSelectParams().merge(
|
||||||
z.object({
|
z.object({
|
||||||
include_ancestors_tree: OptionalBooleanValidator,
|
include_ancestors_tree: booleanString().optional(),
|
||||||
include_descendants_tree: OptionalBooleanValidator,
|
include_descendants_tree: booleanString().optional(),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,8 +29,8 @@ export const StoreProductCategoriesParams = createFindParams({
|
|||||||
description: z.union([z.string(), z.array(z.string())]).optional(),
|
description: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
handle: 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(),
|
parent_category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
include_ancestors_tree: OptionalBooleanValidator,
|
include_ancestors_tree: booleanString().optional(),
|
||||||
include_descendants_tree: OptionalBooleanValidator,
|
include_descendants_tree: booleanString().optional(),
|
||||||
created_at: createOperatorMap().optional(),
|
created_at: createOperatorMap().optional(),
|
||||||
updated_at: createOperatorMap().optional(),
|
updated_at: createOperatorMap().optional(),
|
||||||
deleted_at: createOperatorMap().optional(),
|
deleted_at: createOperatorMap().optional(),
|
||||||
|
|||||||
@@ -32,7 +32,24 @@ const optionalBooleanMapper = new Map([
|
|||||||
["false", false],
|
["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(
|
export const OptionalBooleanValidator = z.preprocess(
|
||||||
(val: any) => optionalBooleanMapper.get(val?.toLowerCase()),
|
(val: any) => optionalBooleanMapper.get(val?.toLowerCase()),
|
||||||
z.boolean().optional()
|
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 { ProductStatus } from "@medusajs/utils"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { createOperatorMap } from "../../validators"
|
import { createOperatorMap } from "../../validators"
|
||||||
import { OptionalBooleanValidator } from "../common"
|
import { booleanString } from "../common"
|
||||||
import { FilterableProductProps } from "@medusajs/types"
|
|
||||||
|
|
||||||
export const ProductStatusEnum = z.nativeEnum(ProductStatus)
|
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(),
|
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
title: z.string().optional(),
|
title: z.string().optional(),
|
||||||
handle: 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(),
|
category_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
sales_channel_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(),
|
collection_id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||||
|
|||||||
Reference in New Issue
Block a user