Skip to content

Commit 081bed5

Browse files
Copilotymc9
andcommitted
Exclude Unsupported type fields from ORM client typing and runtime validation
Co-authored-by: ymc9 <104139426+ymc9@users.noreply.github.com>
1 parent 947cb64 commit 081bed5

3 files changed

Lines changed: 88 additions & 11 deletions

File tree

packages/orm/src/client/zod/factory.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ export class ZodSchemaFactory<
889889
if (this.isModelAllowed(fieldDef.type)) {
890890
fields[field] = this.makeRelationSelectIncludeSchema(model, field, options).optional();
891891
}
892-
} else {
892+
} else if (fieldDef.type !== 'Unsupported') {
893893
fields[field] = z.boolean().optional();
894894
}
895895
}
@@ -996,7 +996,7 @@ export class ZodSchemaFactory<
996996
const fields: Record<string, ZodType> = {};
997997
for (const field of Object.keys(modelDef.fields)) {
998998
const fieldDef = requireField(this.schema, model, field);
999-
if (!fieldDef.relation) {
999+
if (!fieldDef.relation && fieldDef.type !== 'Unsupported') {
10001000
if (this.options.allowQueryTimeOmitOverride !== false) {
10011001
// if override is allowed, use boolean
10021002
fields[field] = z.boolean().optional();
@@ -1067,8 +1067,8 @@ export class ZodSchemaFactory<
10671067
return relationOrderBy.optional();
10681068
});
10691069
}
1070-
} else {
1071-
// scalars
1070+
} else if (fieldDef.type !== 'Unsupported') {
1071+
// scalars (excluding Unsupported type fields)
10721072
if (fieldDef.optional) {
10731073
fields[field] = z
10741074
.union([
@@ -1099,7 +1099,9 @@ export class ZodSchemaFactory<
10991099
@cache()
11001100
private makeDistinctSchema(model: string) {
11011101
const modelDef = requireModel(this.schema, model);
1102-
const nonRelationFields = Object.keys(modelDef.fields).filter((field) => !modelDef.fields[field]?.relation);
1102+
const nonRelationFields = Object.keys(modelDef.fields).filter(
1103+
(field) => !modelDef.fields[field]?.relation && modelDef.fields[field]?.type !== 'Unsupported',
1104+
);
11031105
return nonRelationFields.length > 0 ? this.orArray(z.enum(nonRelationFields as any), true) : z.never();
11041106
}
11051107

@@ -1188,6 +1190,11 @@ export class ZodSchemaFactory<
11881190
return;
11891191
}
11901192

1193+
// skip Unsupported type fields, they cannot be set on create
1194+
if (fieldDef.type === 'Unsupported') {
1195+
return;
1196+
}
1197+
11911198
if (fieldDef.relation) {
11921199
if (skipRelations) {
11931200
return;
@@ -1542,6 +1549,11 @@ export class ZodSchemaFactory<
15421549
return;
15431550
}
15441551

1552+
// skip Unsupported type fields, they cannot be updated
1553+
if (fieldDef.type === 'Unsupported') {
1554+
return;
1555+
}
1556+
15451557
if (fieldDef.relation) {
15461558
if (skipRelations) {
15471559
return;

packages/schema/src/schema.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,13 @@ export type ScalarFields<
201201
? never
202202
: GetModelField<Schema, Model, Key>['foreignKeyFor'] extends readonly string[]
203203
? never
204-
: IncludeComputed extends true
205-
? Key
206-
: FieldIsComputed<Schema, Model, Key> extends true
207-
? never
208-
: Key]: Key;
204+
: GetModelField<Schema, Model, Key>['type'] extends 'Unsupported'
205+
? never
206+
: IncludeComputed extends true
207+
? Key
208+
: FieldIsComputed<Schema, Model, Key> extends true
209+
? never
210+
: Key]: Key;
209211
};
210212

211213
export type ForeignKeyFields<Schema extends SchemaDef, Model extends GetModels<Schema>> = keyof {
@@ -221,7 +223,9 @@ export type ForeignKeyFields<Schema extends SchemaDef, Model extends GetModels<S
221223
export type NonRelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>> = keyof {
222224
[Key in GetModelFields<Schema, Model> as GetModelField<Schema, Model, Key>['relation'] extends object
223225
? never
224-
: Key]: Key;
226+
: GetModelField<Schema, Model, Key>['type'] extends 'Unsupported'
227+
? never
228+
: Key]: Key;
225229
};
226230

227231
export type RelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>> = keyof {

tests/e2e/orm/client-api/zod.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,4 +1375,65 @@ describe('Zod schema factory test', () => {
13751375
});
13761376

13771377
// #endregion
1378+
1379+
// #region Unsupported type fields
1380+
1381+
describe('Unsupported type fields', () => {
1382+
const unsupportedSchema = {
1383+
provider: { type: 'sqlite' as const },
1384+
models: {
1385+
Polygon: {
1386+
name: 'Polygon',
1387+
fields: {
1388+
id: { name: 'id', type: 'Int', id: true, default: 0 },
1389+
name: { name: 'name', type: 'String' },
1390+
geometry: { name: 'geometry', type: 'Unsupported' },
1391+
},
1392+
idFields: ['id'],
1393+
uniqueFields: { id: { type: 'Int' } },
1394+
},
1395+
},
1396+
enums: {},
1397+
} as const;
1398+
1399+
it('create schema rejects Unsupported field', () => {
1400+
const factory = createQuerySchemaFactory(unsupportedSchema);
1401+
const s = factory.makeCreateSchema('Polygon');
1402+
// valid create without unsupported field
1403+
expect(s.safeParse({ data: { name: 'poly1' } }).success).toBe(true);
1404+
// create with unsupported field is rejected
1405+
expect(s.safeParse({ data: { name: 'poly1', geometry: 'some value' } }).success).toBe(false);
1406+
});
1407+
1408+
it('update schema rejects Unsupported field', () => {
1409+
const factory = createQuerySchemaFactory(unsupportedSchema);
1410+
const s = factory.makeUpdateSchema('Polygon');
1411+
// valid update without unsupported field
1412+
expect(s.safeParse({ where: { id: 1 }, data: { name: 'poly2' } }).success).toBe(true);
1413+
// update with unsupported field is rejected
1414+
expect(s.safeParse({ where: { id: 1 }, data: { name: 'poly2', geometry: 'some value' } }).success).toBe(
1415+
false,
1416+
);
1417+
});
1418+
1419+
it('select schema rejects Unsupported field', () => {
1420+
const factory = createQuerySchemaFactory(unsupportedSchema);
1421+
const s = factory.makeFindManySchema('Polygon');
1422+
// valid select without unsupported field
1423+
expect(s.safeParse({ select: { id: true, name: true } }).success).toBe(true);
1424+
// selecting unsupported field is rejected
1425+
expect(s.safeParse({ select: { id: true, geometry: true } }).success).toBe(false);
1426+
});
1427+
1428+
it('orderBy schema rejects Unsupported field', () => {
1429+
const factory = createQuerySchemaFactory(unsupportedSchema);
1430+
const s = factory.makeFindManySchema('Polygon');
1431+
// valid orderBy without unsupported field
1432+
expect(s.safeParse({ orderBy: { name: 'asc' } }).success).toBe(true);
1433+
// orderBy unsupported field is rejected
1434+
expect(s.safeParse({ orderBy: { geometry: 'asc' } }).success).toBe(false);
1435+
});
1436+
});
1437+
1438+
// #endregion
13781439
});

0 commit comments

Comments
 (0)