Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"@zenstackhq/testtools": "workspace:*",
"@zenstackhq/typescript-config": "workspace:*",
"@zenstackhq/vitest-config": "workspace:*",
"tsx": "^4.19.2"
"tsx": "^4.19.2",
"zod": "~3.25.0"
}
}
4 changes: 2 additions & 2 deletions packages/runtime/src/client/crud-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ type EnumFilter<Schema extends SchemaDef, T extends GetEnums<Schema>, Nullable e
};

type ArrayFilter<Schema extends SchemaDef, T extends string> = {
equals?: MapScalarType<Schema, T>[];
has?: MapScalarType<Schema, T>;
equals?: MapScalarType<Schema, T>[] | null;
has?: MapScalarType<Schema, T> | null;
hasEvery?: MapScalarType<Schema, T>[];
hasSome?: MapScalarType<Schema, T>[];
isEmpty?: boolean;
Expand Down
50 changes: 26 additions & 24 deletions packages/runtime/src/client/crud/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,10 @@ export class InputValidator<Schema extends SchemaDef> {
} else {
return match(type)
.with('String', () => z.string())
.with('Int', () => z.int())
.with('Int', () => z.number().int())
.with('Float', () => z.number())
.with('Boolean', () => z.boolean())
.with('BigInt', () => z.union([z.int(), z.bigint()]))
.with('BigInt', () => z.union([z.number().int(), z.bigint()]))
.with('Decimal', () => z.union([z.number(), z.instanceof(Decimal), z.string()]))
.with('DateTime', () => z.union([z.date(), z.string().datetime()]))
.with('Bytes', () => z.instanceof(Uint8Array))
Expand All @@ -252,20 +252,22 @@ export class InputValidator<Schema extends SchemaDef> {
}
const typeDef = this.schema.typeDefs?.[type];
invariant(typeDef, `Type definition "${type}" not found in schema`);
schema = z.looseObject(
Object.fromEntries(
Object.entries(typeDef.fields).map(([field, def]) => {
let fieldSchema = this.makePrimitiveSchema(def.type);
if (def.array) {
fieldSchema = fieldSchema.array();
}
if (def.optional) {
fieldSchema = fieldSchema.optional();
}
return [field, fieldSchema];
}),
),
);
schema = z
.object(
Object.fromEntries(
Object.entries(typeDef.fields).map(([field, def]) => {
let fieldSchema = this.makePrimitiveSchema(def.type);
if (def.array) {
fieldSchema = fieldSchema.array();
}
if (def.optional) {
fieldSchema = fieldSchema.optional();
}
return [field, fieldSchema];
}),
),
)
.passthrough();
this.schemaCache.set(key, schema);
return schema;
}
Expand Down Expand Up @@ -469,7 +471,7 @@ export class InputValidator<Schema extends SchemaDef> {

private makeDateTimeFilterSchema(optional: boolean, withAggregations: boolean): ZodType {
return this.makeCommonPrimitiveFilterSchema(
z.union([z.iso.datetime(), z.date()]),
z.union([z.string().datetime(), z.date()]),
optional,
() => z.lazy(() => this.makeDateTimeFilterSchema(optional, withAggregations)),
withAggregations ? ['_count', '_min', '_max'] : undefined,
Expand Down Expand Up @@ -519,7 +521,7 @@ export class InputValidator<Schema extends SchemaDef> {
gte: baseSchema.optional(),
not: makeThis().optional(),
...(withAggregations?.includes('_count')
? { _count: this.makeNumberFilterSchema(z.int(), false, false).optional() }
? { _count: this.makeNumberFilterSchema(z.number().int(), false, false).optional() }
: {}),
...(withAggregations?.includes('_avg') ? { _avg: commonAggSchema() } : {}),
...(withAggregations?.includes('_sum') ? { _sum: commonAggSchema() } : {}),
Expand Down Expand Up @@ -1020,7 +1022,7 @@ export class InputValidator<Schema extends SchemaDef> {
return z.strictObject({
where: this.makeWhereSchema(model, false).optional(),
data: this.makeUpdateDataSchema(model, [], true),
limit: z.int().nonnegative().optional(),
limit: z.number().int().nonnegative().optional(),
});
}

Expand Down Expand Up @@ -1158,7 +1160,7 @@ export class InputValidator<Schema extends SchemaDef> {
return z
.object({
where: this.makeWhereSchema(model, false).optional(),
limit: z.int().nonnegative().optional(),
limit: z.number().int().nonnegative().optional(),
})

.optional();
Expand Down Expand Up @@ -1255,10 +1257,10 @@ export class InputValidator<Schema extends SchemaDef> {
const modelDef = requireModel(this.schema, model);
const nonRelationFields = Object.keys(modelDef.fields).filter((field) => !modelDef.fields[field]?.relation);

let schema = z.strictObject({
let schema: z.ZodSchema = z.strictObject({
where: this.makeWhereSchema(model, false).optional(),
orderBy: this.orArray(this.makeOrderBySchema(model, false, true), true).optional(),
by: this.orArray(z.enum(nonRelationFields), true),
by: this.orArray(z.enum(nonRelationFields as [string, ...string[]]), true),
having: this.makeHavingSchema(model).optional(),
skip: this.makeSkipSchema().optional(),
take: this.makeTakeSchema().optional(),
Expand Down Expand Up @@ -1340,11 +1342,11 @@ export class InputValidator<Schema extends SchemaDef> {
// #region Helpers

private makeSkipSchema() {
return z.int().nonnegative();
return z.number().int().nonnegative();
}

private makeTakeSchema() {
return z.int();
return z.number().int();
}

private refineForSelectIncludeMutuallyExclusive(schema: ZodType) {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/test/client-api/mixin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ model Bar with CommonFields {
description: 'Bar',
},
}),
).rejects.toThrow('Invalid input');
).rejects.toThrow(/invalid/i);

await expect(
client.bar.create({
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/test/client-api/typed-json-fields.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ model User {
},
},
}),
).rejects.toThrow('Invalid input');
).rejects.toThrow(/invalid/i);
});

it('works with find', async () => {
Expand Down Expand Up @@ -215,7 +215,7 @@ model User {
},
},
}),
).rejects.toThrow('Invalid input');
).rejects.toThrow(/invalid/i);
});
},
);
3 changes: 2 additions & 1 deletion packages/zod/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
},
"devDependencies": {
"@zenstackhq/eslint-config": "workspace:*",
"@zenstackhq/typescript-config": "workspace:*"
"@zenstackhq/typescript-config": "workspace:*",
"zod": "~3.25.0"
},
"peerDependencies": {
"zod": "catalog:"
Expand Down
21 changes: 9 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ packages:
- tests/**
catalog:
kysely: ^0.27.6
zod: ^4.0.0
zod: ^3.25.0 || ^4.0.0
prisma: ^6.10.0
langium: 3.5.0
langium-cli: 3.5.0
Expand Down
Loading