Skip to content

Commit 2ae00f5

Browse files
fix(codegen): make select required in FindManyArgs/FindFirstArgs type params
The ORM's findMany/findFirst methods require select to be present (via intersection & { select: SelectType }). parseFindManyArgs always sets select at runtime, but the generic type parameter only had FindManyArgs<...> where select is optional. Fix: generate FindManyArgs<...> & { select: SelectType } as the type parameter, making the type match what the ORM expects.
1 parent 76d56cb commit 2ae00f5

2 files changed

Lines changed: 67 additions & 14 deletions

File tree

graphql/codegen/src/__tests__/codegen/__snapshots__/cli-generator.test.ts.snap

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,9 @@ async function handleList(argv: Partial<Record<string, unknown>>, _prompter: Inq
757757
isElectric: true,
758758
createdAt: true
759759
};
760-
const findManyArgs = parseFindManyArgs<FindManyArgs<CarSelect, CarFilter, never, CarsOrderBy>>(argv, defaultSelect);
760+
const findManyArgs = parseFindManyArgs<FindManyArgs<CarSelect, CarFilter, never, CarsOrderBy> & {
761+
select: CarSelect;
762+
}>(argv, defaultSelect);
761763
const client = getClient();
762764
const result = await client.car.findMany(findManyArgs).execute();
763765
console.log(JSON.stringify(result, null, 2));
@@ -779,7 +781,9 @@ async function handleFindFirst(argv: Partial<Record<string, unknown>>, _prompter
779781
isElectric: true,
780782
createdAt: true
781783
};
782-
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<CarSelect, CarFilter, never>>(argv, defaultSelect);
784+
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<CarSelect, CarFilter, never> & {
785+
select: CarSelect;
786+
}>(argv, defaultSelect);
783787
const client = getClient();
784788
const result = await client.car.findFirst(findFirstArgs).execute();
785789
console.log(JSON.stringify(result, null, 2));
@@ -1215,7 +1219,9 @@ async function handleList(argv: Partial<Record<string, unknown>>, _prompter: Inq
12151219
name: true,
12161220
licenseNumber: true
12171221
};
1218-
const findManyArgs = parseFindManyArgs<FindManyArgs<DriverSelect, DriverFilter, never, DriversOrderBy>>(argv, defaultSelect);
1222+
const findManyArgs = parseFindManyArgs<FindManyArgs<DriverSelect, DriverFilter, never, DriversOrderBy> & {
1223+
select: DriverSelect;
1224+
}>(argv, defaultSelect);
12191225
const client = getClient();
12201226
const result = await client.driver.findMany(findManyArgs).execute();
12211227
console.log(JSON.stringify(result, null, 2));
@@ -1234,7 +1240,9 @@ async function handleFindFirst(argv: Partial<Record<string, unknown>>, _prompter
12341240
name: true,
12351241
licenseNumber: true
12361242
};
1237-
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<DriverSelect, DriverFilter, never>>(argv, defaultSelect);
1243+
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<DriverSelect, DriverFilter, never> & {
1244+
select: DriverSelect;
1245+
}>(argv, defaultSelect);
12381246
const client = getClient();
12391247
const result = await client.driver.findFirst(findFirstArgs).execute();
12401248
console.log(JSON.stringify(result, null, 2));
@@ -3247,7 +3255,9 @@ async function handleList(argv: Partial<Record<string, unknown>>, _prompter: Inq
32473255
email: true,
32483256
name: true
32493257
};
3250-
const findManyArgs = parseFindManyArgs<FindManyArgs<UserSelect, UserFilter, never, UsersOrderBy>>(argv, defaultSelect);
3258+
const findManyArgs = parseFindManyArgs<FindManyArgs<UserSelect, UserFilter, never, UsersOrderBy> & {
3259+
select: UserSelect;
3260+
}>(argv, defaultSelect);
32513261
const client = getClient("auth");
32523262
const result = await client.user.findMany(findManyArgs).execute();
32533263
console.log(JSON.stringify(result, null, 2));
@@ -3266,7 +3276,9 @@ async function handleFindFirst(argv: Partial<Record<string, unknown>>, _prompter
32663276
email: true,
32673277
name: true
32683278
};
3269-
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<UserSelect, UserFilter, never>>(argv, defaultSelect);
3279+
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<UserSelect, UserFilter, never> & {
3280+
select: UserSelect;
3281+
}>(argv, defaultSelect);
32703282
const client = getClient("auth");
32713283
const result = await client.user.findFirst(findFirstArgs).execute();
32723284
console.log(JSON.stringify(result, null, 2));
@@ -3475,7 +3487,9 @@ async function handleList(argv: Partial<Record<string, unknown>>, _prompter: Inq
34753487
id: true,
34763488
role: true
34773489
};
3478-
const findManyArgs = parseFindManyArgs<FindManyArgs<MemberSelect, MemberFilter, never, MembersOrderBy>>(argv, defaultSelect);
3490+
const findManyArgs = parseFindManyArgs<FindManyArgs<MemberSelect, MemberFilter, never, MembersOrderBy> & {
3491+
select: MemberSelect;
3492+
}>(argv, defaultSelect);
34793493
const client = getClient("members");
34803494
const result = await client.member.findMany(findManyArgs).execute();
34813495
console.log(JSON.stringify(result, null, 2));
@@ -3493,7 +3507,9 @@ async function handleFindFirst(argv: Partial<Record<string, unknown>>, _prompter
34933507
id: true,
34943508
role: true
34953509
};
3496-
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<MemberSelect, MemberFilter, never>>(argv, defaultSelect);
3510+
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<MemberSelect, MemberFilter, never> & {
3511+
select: MemberSelect;
3512+
}>(argv, defaultSelect);
34973513
const client = getClient("members");
34983514
const result = await client.member.findFirst(findFirstArgs).execute();
34993515
console.log(JSON.stringify(result, null, 2));
@@ -3695,7 +3711,9 @@ async function handleList(argv: Partial<Record<string, unknown>>, _prompter: Inq
36953711
isElectric: true,
36963712
createdAt: true
36973713
};
3698-
const findManyArgs = parseFindManyArgs<FindManyArgs<CarSelect, CarFilter, never, CarsOrderBy>>(argv, defaultSelect);
3714+
const findManyArgs = parseFindManyArgs<FindManyArgs<CarSelect, CarFilter, never, CarsOrderBy> & {
3715+
select: CarSelect;
3716+
}>(argv, defaultSelect);
36993717
const client = getClient("app");
37003718
const result = await client.car.findMany(findManyArgs).execute();
37013719
console.log(JSON.stringify(result, null, 2));
@@ -3717,7 +3735,9 @@ async function handleFindFirst(argv: Partial<Record<string, unknown>>, _prompter
37173735
isElectric: true,
37183736
createdAt: true
37193737
};
3720-
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<CarSelect, CarFilter, never>>(argv, defaultSelect);
3738+
const findFirstArgs = parseFindFirstArgs<FindFirstArgs<CarSelect, CarFilter, never> & {
3739+
select: CarSelect;
3740+
}>(argv, defaultSelect);
37213741
const client = getClient("app");
37223742
const result = await client.car.findFirst(findFirstArgs).execute();
37233743
console.log(JSON.stringify(result, null, 2));

graphql/codegen/src/core/codegen/cli/table-command-generator.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -485,15 +485,19 @@ function buildAutoEmbedInputBlock(
485485

486486
/**
487487
* Build the FindManyArgs type instantiation for a table:
488-
* FindManyArgs<SelectType, FilterType, ConditionType, OrderByType>
488+
* FindManyArgs<SelectType, FilterType, ConditionType, OrderByType> & { select: SelectType }
489+
*
490+
* The intersection with { select: SelectType } makes select required,
491+
* matching what the ORM's findMany method expects. parseFindManyArgs
492+
* always sets select at runtime (from defaultSelect or --select flag).
489493
*/
490494
function buildFindManyArgsType(table: Table, conditionEnabled: boolean): t.TSType {
491495
const { typeName } = getTableNames(table);
492496
const selectTypeName = `${typeName}Select`;
493497
const whereTypeName = getFilterTypeName(table);
494498
const conditionTypeName = conditionEnabled ? getConditionTypeName(table) : undefined;
495499
const orderByTypeName = getOrderByTypeName(table);
496-
return t.tsTypeReference(
500+
const findManyType = t.tsTypeReference(
497501
t.identifier('FindManyArgs'),
498502
t.tsTypeParameterInstantiation([
499503
t.tsTypeReference(t.identifier(selectTypeName)),
@@ -504,18 +508,34 @@ function buildFindManyArgsType(table: Table, conditionEnabled: boolean): t.TSTyp
504508
t.tsTypeReference(t.identifier(orderByTypeName)),
505509
]),
506510
);
511+
// Intersect with { select: SelectType } to make select required
512+
return t.tsIntersectionType([
513+
findManyType,
514+
t.tsTypeLiteral([
515+
Object.assign(
516+
t.tsPropertySignature(
517+
t.identifier('select'),
518+
t.tsTypeAnnotation(t.tsTypeReference(t.identifier(selectTypeName))),
519+
),
520+
{ optional: false },
521+
),
522+
]),
523+
]);
507524
}
508525

509526
/**
510527
* Build the FindFirstArgs type instantiation for a table:
511-
* FindFirstArgs<SelectType, FilterType, ConditionType>
528+
* FindFirstArgs<SelectType, FilterType, ConditionType> & { select: SelectType }
529+
*
530+
* The intersection with { select: SelectType } makes select required,
531+
* matching what the ORM's findFirst method expects.
512532
*/
513533
function buildFindFirstArgsType(table: Table, conditionEnabled: boolean): t.TSType {
514534
const { typeName } = getTableNames(table);
515535
const selectTypeName = `${typeName}Select`;
516536
const whereTypeName = getFilterTypeName(table);
517537
const conditionTypeName = conditionEnabled ? getConditionTypeName(table) : undefined;
518-
return t.tsTypeReference(
538+
const findFirstType = t.tsTypeReference(
519539
t.identifier('FindFirstArgs'),
520540
t.tsTypeParameterInstantiation([
521541
t.tsTypeReference(t.identifier(selectTypeName)),
@@ -525,6 +545,19 @@ function buildFindFirstArgsType(table: Table, conditionEnabled: boolean): t.TSTy
525545
: t.tsNeverKeyword(),
526546
]),
527547
);
548+
// Intersect with { select: SelectType } to make select required
549+
return t.tsIntersectionType([
550+
findFirstType,
551+
t.tsTypeLiteral([
552+
Object.assign(
553+
t.tsPropertySignature(
554+
t.identifier('select'),
555+
t.tsTypeAnnotation(t.tsTypeReference(t.identifier(selectTypeName))),
556+
),
557+
{ optional: false },
558+
),
559+
]),
560+
]);
528561
}
529562

530563
function buildListHandler(table: Table, vectorFieldNames: string[], targetName?: string, typeRegistry?: TypeRegistry, conditionEnabled = false): t.FunctionDeclaration {

0 commit comments

Comments
 (0)