Skip to content

Commit cc8af45

Browse files
authored
merge from svetch/main (#233)
1 parent 1fe1be1 commit cc8af45

File tree

4 files changed

+30
-22
lines changed

4 files changed

+30
-22
lines changed

packages/runtime/src/client/crud/operations/find.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,26 @@ export class FindOperationHandler<Schema extends SchemaDef> extends BaseOperatio
77
// normalize args to strip `undefined` fields
88
const normalizedArgs = this.normalizeArgs(args);
99

10+
const findOne = operation === 'findFirst' || operation === 'findUnique';
11+
1012
// parse args
11-
const parsedArgs = (validateArgs
12-
? this.inputValidator.validateFindArgs(this.model, operation === 'findUnique', normalizedArgs)
13-
: normalizedArgs) as FindArgs<Schema, GetModels<Schema>, true>;
13+
let parsedArgs = validateArgs
14+
? this.inputValidator.validateFindArgs(this.model, normalizedArgs, {
15+
unique: operation === 'findUnique',
16+
findOne,
17+
})
18+
: (normalizedArgs as FindArgs<Schema, GetModels<Schema>, true> | undefined);
1419

15-
if (operation === 'findFirst') {
20+
if (findOne) {
21+
// ensure "limit 1"
22+
parsedArgs = parsedArgs ?? {};
1623
parsedArgs.take = 1;
1724
}
1825

1926
// run query
20-
const result = await this.read(
21-
this.client.$qb,
22-
this.model,
23-
parsedArgs,
24-
);
27+
const result = await this.read(this.client.$qb, this.model, parsedArgs);
2528

26-
const finalResult = operation === 'findMany' ? result : (result[0] ?? null);
29+
const finalResult = findOne ? (result[0] ?? null) : result;
2730
return finalResult;
2831
}
2932
}

packages/runtime/src/client/crud/validator.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,11 @@ export class InputValidator<Schema extends SchemaDef> {
4040

4141
constructor(private readonly schema: Schema) {}
4242

43-
validateFindArgs(model: GetModels<Schema>, unique: boolean, args: unknown) {
44-
return this.validate<FindArgs<Schema, GetModels<Schema>, true>, Parameters<typeof this.makeFindSchema>[1]>(
45-
model,
46-
'find',
47-
{ unique },
48-
(model, options) => this.makeFindSchema(model, options),
49-
args,
50-
);
43+
validateFindArgs(model: GetModels<Schema>, args: unknown, options: { unique: boolean; findOne: boolean }) {
44+
return this.validate<
45+
FindArgs<Schema, GetModels<Schema>, true> | undefined,
46+
Parameters<typeof this.makeFindSchema>[1]
47+
>(model, 'find', options, (model, options) => this.makeFindSchema(model, options), args);
5148
}
5249

5350
validateCreateArgs(model: GetModels<Schema>, args: unknown) {
@@ -196,7 +193,7 @@ export class InputValidator<Schema extends SchemaDef> {
196193

197194
// #region Find
198195

199-
private makeFindSchema(model: string, options: { unique: boolean }) {
196+
private makeFindSchema(model: string, options: { unique: boolean; findOne: boolean }) {
200197
const fields: Record<string, z.ZodSchema> = {};
201198
const where = this.makeWhereSchema(model, options.unique);
202199
if (options.unique) {
@@ -211,7 +208,11 @@ export class InputValidator<Schema extends SchemaDef> {
211208

212209
if (!options.unique) {
213210
fields['skip'] = this.makeSkipSchema().optional();
214-
fields['take'] = this.makeTakeSchema().optional();
211+
if (options.findOne) {
212+
fields['take'] = z.literal(1).optional();
213+
} else {
214+
fields['take'] = this.makeTakeSchema().optional();
215+
}
215216
fields['orderBy'] = this.orArray(this.makeOrderBySchema(model, true, false), true).optional();
216217
fields['cursor'] = this.makeCursorSchema(model).optional();
217218
fields['distinct'] = this.makeDistinctSchema(model).optional();

packages/runtime/test/client-api/computed-fields.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ model User {
7575
await expect(
7676
db.user.findFirst({
7777
orderBy: { upperName: 'desc' },
78-
take: -1,
78+
take: 1,
7979
}),
8080
).resolves.toMatchObject({
8181
upperName: 'ALEX',

packages/runtime/test/client-api/find.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
22
import type { ClientContract } from '../../src/client';
3-
import { NotFoundError } from '../../src/client/errors';
3+
import { InputValidationError, NotFoundError } from '../../src/client/errors';
44
import { schema } from '../schemas/basic';
55
import { createClientSpecs } from './client-specs';
66
import { createPosts, createUser } from './utils';
@@ -54,6 +54,10 @@ describe.each(createClientSpecs(PG_DB_NAME))('Client find tests for $provider',
5454
await expect(client.user.findMany({ take: 2 })).resolves.toHaveLength(2);
5555
await expect(client.user.findMany({ take: 4 })).resolves.toHaveLength(3);
5656

57+
// findFirst's take must be 1
58+
await expect(client.user.findFirst({ take: 2 })).rejects.toThrow(InputValidationError);
59+
await expect(client.user.findFirst({ take: 1 })).toResolveTruthy();
60+
5761
// skip
5862
await expect(client.user.findMany({ skip: 1 })).resolves.toHaveLength(2);
5963
await expect(client.user.findMany({ skip: 2 })).resolves.toHaveLength(1);

0 commit comments

Comments
 (0)