Skip to content

Commit d8ccad6

Browse files
committed
fix decimal and record schemas
1 parent 0ee922d commit d8ccad6

File tree

11 files changed

+46
-43
lines changed

11 files changed

+46
-43
lines changed

packages/plugins/trpc/tests/projects/nuxt-trpc-v10/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"trpc-nuxt": "^0.10.22",
1818
"vue": "latest",
1919
"vue-router": "latest",
20-
"zod": "^3.25.0"
20+
"zod": "^4.0.0"
2121
},
2222
"devDependencies": {
2323
"esbuild": "^0.24.0",

packages/plugins/trpc/tests/projects/nuxt-trpc-v11/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"trpc-nuxt": "^0.11.0-beta.1",
1818
"vue": "latest",
1919
"vue-router": "latest",
20-
"zod": "^3.25.0"
20+
"zod": "^4.0.0"
2121
},
2222
"devDependencies": {
2323
"esbuild": "^0.24.0",

packages/plugins/trpc/tests/projects/t3-trpc-v11/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"react-dom": "^18.3.1",
2929
"server-only": "^0.0.1",
3030
"superjson": "^2.2.1",
31-
"zod": "^3.25.0"
31+
"zod": "^4.0.0"
3232
},
3333
"devDependencies": {
3434
"@types/eslint": "^8.56.10",

packages/schema/src/plugins/zod/generator.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,15 @@ export class ZodSchemaGenerator {
222222
path.join(output, 'common', 'index.ts'),
223223
`
224224
import { z } from 'zod';
225-
export const DecimalSchema = z.union([z.number(), z.string(), z.object({d: z.number().array(), e: z.number(), s: z.number()}).passthrough()]);
225+
export const DecimalSchema = z.any().refine((val) => {
226+
if (typeof val === 'string' || typeof val === 'number') {
227+
return val;
228+
}
229+
// Decimal.js shape
230+
if (typeof val === 'object' && val && Array.isArray(val.d) && typeof val.e === 'number' && typeof val.s === 'number') {
231+
return val;
232+
}
233+
});
226234
`,
227235
{ overwrite: true }
228236
)
@@ -553,7 +561,7 @@ export const ${upperCaseFirst(model.name)}PrismaCreateSchema = ${prismaCreateSch
553561
.map((field) => {
554562
let fieldSchema = makeFieldSchema(field, false);
555563
if (field.type.type === 'Int' || field.type.type === 'Float') {
556-
fieldSchema = `z.union([${fieldSchema}, z.record(z.unknown())])`;
564+
fieldSchema = `z.union([${fieldSchema}, z.record(z.string(), z.unknown())])`;
557565
}
558566
return `\t${field.name}: ${fieldSchema}`;
559567
})

packages/schema/src/plugins/zod/transformer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ export const ${this.name}ObjectSchema: SchemaType = ${schema} as SchemaType;`;
486486
jsonSchemaImplementation += `\n`;
487487
jsonSchemaImplementation += `const literalSchema = z.union([z.string(), z.number(), z.boolean()]);\n`;
488488
jsonSchemaImplementation += `const jsonSchema: z.ZodType<Prisma.InputJsonValue> = z.lazy(() =>\n`;
489-
jsonSchemaImplementation += ` z.union([literalSchema, z.array(jsonSchema.nullable()), z.record(jsonSchema.nullable())])\n`;
489+
jsonSchemaImplementation += ` z.union([literalSchema, z.array(jsonSchema.nullable()), z.record(z.string(), jsonSchema.nullable())])\n`;
490490
jsonSchemaImplementation += `);\n\n`;
491491
}
492492

packages/schema/src/plugins/zod/utils/schema-gen.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export function makeFieldSchema(field: DataModelField | TypeDefField, addDefault
2020
// array field is always optional
2121
return `z.array(z.unknown()).optional()`;
2222
} else {
23-
return field.type.optional ? `z.record(z.unknown()).optional()` : `z.record(z.unknown())`;
23+
return field.type.optional
24+
? `z.record(z.string(), z.unknown()).optional()`
25+
: `z.record(z.string(), z.unknown())`;
2426
}
2527
}
2628

tests/integration/test-run/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
"react": "^18.2.0",
1717
"swr": "^1.3.0",
1818
"zenstack": "file:../../../packages/schema/dist",
19-
"zod": "^3.25.0"
19+
"zod": "^4.0.0"
2020
}
2121
}

tests/integration/tests/enhancements/with-password/with-password.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ describe('Password test', () => {
9494
password: 'abc456789',
9595
},
9696
})
97-
).toBeRejectedByPolicy(['String must contain at most 8 character(s) at "password"']);
97+
).toBeRejectedByPolicy(['8 character']);
9898

9999
await expect(
100100
db.user.create({
@@ -103,7 +103,7 @@ describe('Password test', () => {
103103
password: 'abc456789',
104104
},
105105
})
106-
).toBeRejectedByPolicy(['String must contain at most 8 character(s) at "password"']);
106+
).toBeRejectedByPolicy(['8 character']);
107107

108108
await expect(
109109
db.user.create({

tests/integration/tests/enhancements/with-policy/field-validation.test.ts

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe('Field validation', () => {
6565
handle: 'hello world',
6666
},
6767
})
68-
).toBeRejectedByPolicy(['String must contain at least 8 character(s) at "password"', 'Invalid at "handle"']);
68+
).toBeRejectedByPolicy(['8 character', 'handle']);
6969

7070
let err: any;
7171
try {
@@ -98,11 +98,7 @@ describe('Field validation', () => {
9898
handle: 'user1user1user1user1user1',
9999
},
100100
})
101-
).toBeRejectedByPolicy([
102-
'Invalid email at "email"',
103-
'must end with "@myorg.com" at "email"',
104-
'Invalid at "handle"',
105-
]);
101+
).toBeRejectedByPolicy(['email', 'handle']);
106102

107103
await expect(
108104
db.user.create({
@@ -123,10 +119,7 @@ describe('Field validation', () => {
123119
email: 'something',
124120
},
125121
})
126-
).toBeRejectedByPolicy([
127-
'String must contain at least 8 character(s) at "password"',
128-
'must end with "@myorg.com" at "email"',
129-
]);
122+
).toBeRejectedByPolicy(['8 character', 'email']);
130123

131124
await expect(
132125
db.user.update({
@@ -135,7 +128,7 @@ describe('Field validation', () => {
135128
age: { increment: 100 },
136129
},
137130
})
138-
).toBeRejectedByPolicy(['Number must be less than 100 at "age"']);
131+
).toBeRejectedByPolicy(['100']);
139132

140133
await expect(
141134
db.user.update({
@@ -173,15 +166,15 @@ describe('Field validation', () => {
173166
},
174167
})
175168
).toBeRejectedByPolicy([
176-
'Number must be greater than 0 at "a"',
177-
'Number must be greater than or equal to 0 at "b"',
178-
'Number must be less than 0 at "c"',
179-
'Number must be less than or equal to 0 at "d"',
180-
'must start with "abc" at "text1"',
181-
'must end with "def" at "text2"',
182-
'String must contain at least 3 character(s) at "text3"',
183-
'String must contain at most 5 character(s) at "text4"',
184-
'must end with "xyz" at "text5"',
169+
'0 at "a"',
170+
'0 at "b"',
171+
'0 at "c"',
172+
'0 at "d"',
173+
'text1',
174+
'text2',
175+
'text3',
176+
'text4',
177+
'text5',
185178
]);
186179

187180
await expect(
@@ -240,7 +233,7 @@ describe('Field validation', () => {
240233
},
241234
},
242235
})
243-
).toBeRejectedByPolicy(['Number must be greater than 0 at "a"']);
236+
).toBeRejectedByPolicy(['0 at "a"']);
244237

245238
await expect(
246239
db.user.create({
@@ -253,7 +246,7 @@ describe('Field validation', () => {
253246
},
254247
},
255248
})
256-
).toBeRejectedByPolicy(['Invalid at "slug"']);
249+
).toBeRejectedByPolicy(['slug']);
257250

258251
await expect(
259252
db.user.create({
@@ -272,7 +265,7 @@ describe('Field validation', () => {
272265
},
273266
},
274267
})
275-
).toBeRejectedByPolicy(['Number must be greater than 0 at "a"']);
268+
).toBeRejectedByPolicy(['0 at "a"']);
276269

277270
await expect(
278271
db.user.create({
@@ -290,7 +283,7 @@ describe('Field validation', () => {
290283
},
291284
},
292285
})
293-
).toBeRejectedByPolicy(['Invalid at "slug"']);
286+
).toBeRejectedByPolicy(['slug']);
294287

295288
await expect(
296289
db.user.create({
@@ -351,7 +344,7 @@ describe('Field validation', () => {
351344
},
352345
},
353346
})
354-
).toBeRejectedByPolicy(['Number must be greater than 0 at "a"']);
347+
).toBeRejectedByPolicy(['0 at "a"']);
355348

356349
await expect(
357350
db.user.update({
@@ -364,7 +357,7 @@ describe('Field validation', () => {
364357
},
365358
},
366359
})
367-
).toBeRejectedByPolicy(['Invalid at "slug"']);
360+
).toBeRejectedByPolicy(['slug']);
368361

369362
await expect(
370363
db.user.update({
@@ -394,7 +387,7 @@ describe('Field validation', () => {
394387
},
395388
},
396389
})
397-
).toBeRejectedByPolicy(['Number must be greater than 0 at "a"']);
390+
).toBeRejectedByPolicy(['0 at "a"']);
398391

399392
await expect(
400393
db.user.update({
@@ -410,7 +403,7 @@ describe('Field validation', () => {
410403
},
411404
},
412405
})
413-
).toBeRejectedByPolicy(['Invalid at "slug"']);
406+
).toBeRejectedByPolicy(['slug']);
414407

415408
await expect(
416409
db.user.update({
@@ -450,7 +443,7 @@ describe('Field validation', () => {
450443
},
451444
},
452445
})
453-
).toBeRejectedByPolicy(['Number must be greater than 0 at "a"']);
446+
).toBeRejectedByPolicy(['0 at "a"']);
454447

455448
await expect(
456449
db.user.update({
@@ -466,7 +459,7 @@ describe('Field validation', () => {
466459
},
467460
},
468461
})
469-
).toBeRejectedByPolicy(['Invalid at "slug"']);
462+
).toBeRejectedByPolicy(['slug']);
470463

471464
await expect(
472465
db.user.update({
@@ -979,7 +972,7 @@ describe('Policy and validation interaction', () => {
979972
age: 18,
980973
},
981974
})
982-
).toBeRejectedByPolicy(['Invalid email at "email"']);
975+
).toBeRejectedByPolicy(['email']);
983976

984977
await expect(
985978
db.user.create({

tests/integration/tests/frameworks/nextjs/test-project/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"superjson": "^1.13.0",
2020
"swr": "^2.2.0",
2121
"typescript": "5.x",
22-
"zod": "^3.25.0",
22+
"zod": "^4.0.0",
2323
"@zenstackhq/language": "../../../../../../../packages/language/dist",
2424
"@zenstackhq/runtime": "../../../../../../../packages/runtime/dist",
2525
"@zenstackhq/sdk": "../../../../../../../packages/sdk/dist",

0 commit comments

Comments
 (0)