Skip to content

Commit 843dbfe

Browse files
chore(): upgrade zod to latest (#14309)
* chore(): upgrade zod to latest * chore(): upgrade zod to latest * chore(): upgrade zod to latest * chore(): upgrade zod to latest * chore(): upgrade zod to latest * chore(): upgrade zod to latest * chore(): upgrade zod to latest * force trigger cache miss * fix deps * fix deps * fix * fix tests * fix tests * fix tests * fix tests * cleanup * fix tests * remove only * Create fifty-boats-battle.md * reduce nullish coalescing * cleanup * cleanup * cleanup + fixes * ordering import and type * improve error handler + fix tests and add new tests * improve test cases * fix * update import * update yarn.lock * fix --------- Co-authored-by: Shahed Nasser <shahednasser@gmail.com>
1 parent cec755c commit 843dbfe

File tree

61 files changed

+1295
-769
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+1295
-769
lines changed

.changeset/fifty-boats-battle.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@medusajs/medusa": patch
3+
"@medusajs/core-flows": patch
4+
"@medusajs/framework": patch
5+
"@medusajs/utils": patch
6+
"@medusajs/workflows-sdk": patch
7+
"@medusajs/admin-sdk": patch
8+
"@medusajs/dashboard": patch
9+
---
10+
11+
chore(): upgrade zod to latest

integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,10 +1146,9 @@ medusaIntegrationTestRunner({
11461146
issues: [
11471147
{
11481148
code: "invalid_type",
1149-
expected: "object",
1150-
message: "Expected object, received array",
1149+
expected: "record",
1150+
message: "Invalid input: expected record, received array",
11511151
path: [],
1152-
received: "array",
11531152
},
11541153
],
11551154
}),

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@
132132
"vite-plugin-turbosnap": "^1.0.2",
133133
"vitest": "^3.0.5",
134134
"yalc": "^1.0.0-pre.53",
135-
"zod": "3.25.76"
135+
"zod": "4.2.0",
136+
"zod-validation-error": "5.0.0"
136137
},
137138
"lint-staged": {
138139
"*.{js,jsx,ts,tsx}": "yarn run lint",

packages/admin/admin-sdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
},
2121
"dependencies": {
2222
"@medusajs/admin-shared": "2.13.6",
23-
"zod": "3.25.76"
23+
"zod": "4.2.0"
2424
},
2525
"packageManager": "yarn@3.2.1"
2626
}

packages/admin/dashboard/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
"react-i18next": "13.5.0",
7878
"react-jwt": "^1.2.0",
7979
"react-router-dom": "6.30.3",
80-
"zod": "3.25.76"
80+
"zod": "4.2.0"
8181
},
8282
"devDependencies": {
8383
"@medusajs/admin-shared": "2.13.6",
Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
import {
2-
ZodBoolean,
3-
ZodEffects,
4-
ZodNull,
5-
ZodNullable,
6-
ZodNumber,
7-
ZodOptional,
8-
ZodString,
9-
ZodType,
10-
ZodUndefined,
11-
} from "zod"
1+
import { z } from "zod"
122
import { FormFieldType } from "./types"
133

144
export function getFieldLabel(name: string, label?: string) {
@@ -22,45 +12,42 @@ export function getFieldLabel(name: string, label?: string) {
2212
.join(" ")
2313
}
2414

25-
export function getFieldType(type: ZodType): FormFieldType {
26-
if (type instanceof ZodString) {
15+
export function getFieldType(type: z.ZodType): FormFieldType {
16+
if (type instanceof z.ZodString) {
2717
return "text"
2818
}
2919

30-
if (type instanceof ZodNumber) {
20+
if (type instanceof z.ZodNumber) {
3121
return "number"
3222
}
3323

34-
if (type instanceof ZodBoolean) {
24+
if (type instanceof z.ZodBoolean) {
3525
return "boolean"
3626
}
3727

38-
if (type instanceof ZodNullable) {
39-
const innerType = type.unwrap()
40-
28+
if (type instanceof z.ZodNullable) {
29+
const innerType = type.unwrap() as z.ZodType
4130
return getFieldType(innerType)
4231
}
4332

44-
if (type instanceof ZodOptional) {
45-
const innerType = type.unwrap()
46-
33+
if (type instanceof z.ZodOptional) {
34+
const innerType = type.unwrap() as z.ZodType
4735
return getFieldType(innerType)
4836
}
4937

50-
if (type instanceof ZodEffects) {
51-
const innerType = type.innerType()
52-
38+
if (type instanceof z.ZodPipe) {
39+
const innerType = type.def.in as z.ZodType
5340
return getFieldType(innerType)
5441
}
5542

5643
return "unsupported"
5744
}
5845

59-
export function getIsFieldOptional(type: ZodType) {
46+
export function getIsFieldOptional(type: z.ZodType) {
6047
return (
61-
type instanceof ZodOptional ||
62-
type instanceof ZodNull ||
63-
type instanceof ZodUndefined ||
64-
type instanceof ZodNullable
48+
type instanceof z.ZodOptional ||
49+
type instanceof z.ZodNull ||
50+
type instanceof z.ZodUndefined ||
51+
type instanceof z.ZodNullable
6552
)
6653
}

packages/admin/dashboard/src/dashboard-app/forms/hooks.tsx

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { zodResolver } from "@hookform/resolvers/zod"
22
import { FieldValues, useForm, UseFormProps } from "react-hook-form"
3-
import { z, ZodEffects, ZodObject } from "zod"
3+
import { z, ZodObject } from "zod"
44

55
import { ConfigField } from "../types"
66

77
interface UseExtendableFormProps<
8-
TSchema extends ZodObject<any> | ZodEffects<ZodObject<any>>,
8+
TSchema extends ZodObject<any>,
99
TContext = any,
1010
TData = any
1111
> extends Omit<UseFormProps<z.infer<TSchema>, TContext>, "resolver"> {
12-
schema: TSchema
12+
schema: TSchema | z.ZodPipe<TSchema, z.ZodType>
1313
configs: ConfigField[]
1414
data?: TData
1515
}
@@ -21,26 +21,45 @@ function createAdditionalDataSchema(configs: ConfigField[]) {
2121
}, {} as Record<string, z.ZodTypeAny>)
2222
}
2323

24-
function createExtendedSchema<
25-
TSchema extends ZodObject<any> | ZodEffects<ZodObject<any>>
26-
>(baseSchema: TSchema, additionalDataSchema: Record<string, z.ZodTypeAny>) {
24+
/**
25+
* Extracts the shape from a schema, handling both ZodObject and ZodPipe.
26+
* ZodPipe is created by .transform() and wraps the original schema.
27+
*/
28+
function getSchemaShape(
29+
schema: ZodObject<any> | z.ZodPipe<ZodObject<any>, z.ZodType>
30+
): z.ZodRawShape {
31+
if (schema instanceof z.ZodPipe) {
32+
const innerSchema = schema.def.in
33+
// Guard: ensure inner schema is a ZodObject before accessing shape
34+
if (innerSchema instanceof ZodObject) {
35+
return innerSchema.shape
36+
}
37+
throw new Error(
38+
"Expected ZodPipe to contain a ZodObject. Schema extensions require the base schema to be a ZodObject."
39+
)
40+
}
41+
return schema.shape
42+
}
43+
44+
function createExtendedSchema(
45+
baseSchema: ZodObject<any> | z.ZodPipe<ZodObject<any>, z.ZodType>,
46+
additionalDataSchema: Record<string, z.ZodTypeAny>
47+
) {
48+
const baseShape = getSchemaShape(baseSchema)
49+
2750
const extendedObjectSchema = z.object({
28-
...(baseSchema instanceof ZodEffects
29-
? baseSchema.innerType().shape
30-
: baseSchema.shape),
51+
...baseShape,
3152
additional_data: z.object(additionalDataSchema).optional(),
3253
})
3354

34-
return baseSchema instanceof ZodEffects
35-
? baseSchema
36-
.superRefine((data, ctx) => {
37-
const result = extendedObjectSchema.safeParse(data)
38-
if (!result.success) {
39-
result.error.issues.forEach((issue) => ctx.addIssue(issue))
40-
}
41-
})
42-
.and(extendedObjectSchema)
43-
: extendedObjectSchema
55+
return baseSchema
56+
.superRefine((data, ctx) => {
57+
const result = extendedObjectSchema.safeParse(data)
58+
if (!result.success) {
59+
result.error.issues.forEach((issue) => ctx.addIssue({ ...issue }))
60+
}
61+
})
62+
.and(extendedObjectSchema)
4463
}
4564

4665
function createExtendedDefaultValues<TData>(
@@ -60,7 +79,7 @@ function createExtendedDefaultValues<TData>(
6079
}
6180

6281
export const useExtendableForm = <
63-
TSchema extends ZodObject<any> | ZodEffects<ZodObject<any>>,
82+
TSchema extends ZodObject<any>,
6483
TContext = any,
6584
TTransformedValues extends FieldValues | undefined = undefined
6685
>({

packages/admin/dashboard/src/dashboard-app/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from "@medusajs/admin-shared"
99
import { ComponentType } from "react"
1010
import { LoaderFunction } from "react-router-dom"
11-
import { ZodFirstPartySchemaTypes } from "zod"
11+
import { z } from "zod"
1212
import { INavItem } from "../components/layout/nav-item"
1313

1414
export type RouteExtension = {
@@ -39,7 +39,7 @@ export type DisplayExtension = {
3939
}
4040

4141
export type FormFieldExtension = {
42-
validation: ZodFirstPartySchemaTypes
42+
validation: z.ZodTypeAny
4343
Component?: ComponentType<any>
4444
label?: string
4545
description?: string
@@ -54,7 +54,7 @@ export type FormExtension = {
5454

5555
export type ConfigFieldExtension = {
5656
defaultValue: ((data: any) => any) | any
57-
validation: ZodFirstPartySchemaTypes
57+
validation: z.ZodTypeAny
5858
}
5959

6060
export type ConfigExtension = {

packages/admin/dashboard/src/routes/inventory/inventory-stock/schema.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ const LocationQuantitySchema = z.object({
77
disabledToggle: z.boolean(),
88
})
99

10-
const InventoryLocationsSchema = z.record(LocationQuantitySchema)
10+
const InventoryLocationsSchema = z.record(z.string(), LocationQuantitySchema)
1111

1212
const InventoryItemSchema = z.object({
1313
locations: InventoryLocationsSchema,
1414
})
1515

1616
export const InventoryStockSchema = z.object({
17-
inventory_items: z.record(InventoryItemSchema),
17+
inventory_items: z.record(z.string(), InventoryItemSchema),
1818
})
1919

2020
export type InventoryLocationsSchema = z.infer<typeof InventoryLocationsSchema>

packages/admin/dashboard/src/routes/price-lists/common/schemas.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ export type PriceListCreateRegionPriceSchema = z.infer<
3030
>
3131

3232
const PriceListCreateProductVariantSchema = z.object({
33-
currency_prices: z.record(PriceListCreateCurrencyPriceSchema.optional()),
34-
region_prices: z.record(PriceListCreateRegionPriceSchema.optional()),
33+
currency_prices: z.record(z.string(), PriceListCreateCurrencyPriceSchema.optional()),
34+
region_prices: z.record(z.string(), PriceListCreateRegionPriceSchema.optional()),
3535
})
3636

3737
export type PriceListCreateProductVariantSchema = z.infer<
3838
typeof PriceListCreateProductVariantSchema
3939
>
4040

4141
const PriceListCreateProductVariantsSchema = z.record(
42+
z.string(),
4243
PriceListCreateProductVariantSchema
4344
)
4445

@@ -47,6 +48,7 @@ export type PriceListCreateProductVariantsSchema = z.infer<
4748
>
4849

4950
export const PriceListCreateProductsSchema = z.record(
51+
z.string(),
5052
z.object({
5153
variants: PriceListCreateProductVariantsSchema,
5254
})
@@ -75,9 +77,10 @@ export type PriceListUpdateRegionPrice = z.infer<
7577
>
7678

7779
export const PriceListUpdateProductVariantsSchema = z.record(
80+
z.string(),
7881
z.object({
79-
currency_prices: z.record(PriceListUpdateCurrencyPriceSchema.optional()),
80-
region_prices: z.record(PriceListUpdateRegionPriceSchema.optional()),
82+
currency_prices: z.record(z.string(), PriceListUpdateCurrencyPriceSchema.optional()),
83+
region_prices: z.record(z.string(), PriceListUpdateRegionPriceSchema.optional()),
8184
})
8285
)
8386

@@ -86,6 +89,7 @@ export type PriceListUpdateProductVariantsSchema = z.infer<
8689
>
8790

8891
export const PriceListUpdateProductsSchema = z.record(
92+
z.string(),
8993
z.object({
9094
variants: PriceListUpdateProductVariantsSchema,
9195
})

0 commit comments

Comments
 (0)