Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export interface PageInfo {
endCursor?: string | null;
}

export interface FindManyArgs<TSelect, TWhere, TCondition, TOrderBy> {
export interface FindManyArgs<TSelect, TWhere, TCondition = never, TOrderBy = never> {
select?: TSelect;
where?: TWhere;
condition?: TCondition;
Expand All @@ -288,7 +288,7 @@ export interface FindManyArgs<TSelect, TWhere, TCondition, TOrderBy> {
offset?: number;
}

export interface FindFirstArgs<TSelect, TWhere, TCondition> {
export interface FindFirstArgs<TSelect, TWhere, TCondition = never> {
select?: TSelect;
where?: TWhere;
condition?: TCondition;
Expand Down
4 changes: 3 additions & 1 deletion graphql/codegen/src/core/codegen/orm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface GenerateOrmResult {
export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
const { tables, customOperations, sharedTypesPath } = options;
const commentsEnabled = options.config.codegen?.comments !== false;
const conditionEnabled = options.config.codegen?.condition !== false;
const files: GeneratedFile[] = [];

// Use shared types when a sharedTypesPath is provided (unified output mode)
Expand All @@ -91,7 +92,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
});

// 2. Generate model files
const modelFiles = generateAllModelFiles(tables, useSharedTypes);
const modelFiles = generateAllModelFiles(tables, useSharedTypes, { condition: conditionEnabled });
for (const modelFile of modelFiles) {
files.push({
path: `models/${modelFile.fileName}`,
Expand Down Expand Up @@ -140,6 +141,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
tables,
usedPayloadTypes,
commentsEnabled,
{ condition: conditionEnabled },
);
files.push({
path: inputTypesFile.fileName,
Expand Down
18 changes: 14 additions & 4 deletions graphql/codegen/src/core/codegen/orm/input-types-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1572,9 +1572,10 @@ function generateCustomInputTypes(
usedInputTypes: Set<string>,
tableCrudTypes?: Set<string>,
comments: boolean = true,
alreadyGeneratedTypes?: Set<string>,
): t.Statement[] {
const statements: t.Statement[] = [];
const generatedTypes = new Set<string>();
const generatedTypes = new Set<string>(alreadyGeneratedTypes ?? []);
const typesToGenerate = new Set(Array.from(usedInputTypes));

// Filter out types we've already generated (exact matches for table CRUD types only)
Expand Down Expand Up @@ -1969,7 +1970,9 @@ export function generateInputTypesFile(
tables?: CleanTable[],
usedPayloadTypes?: Set<string>,
comments: boolean = true,
options?: { condition?: boolean },
): GeneratedInputTypesFile {
const conditionEnabled = options?.condition !== false;
const statements: t.Statement[] = [];
const tablesList = tables ?? [];
const hasTables = tablesList.length > 0;
Expand Down Expand Up @@ -2006,7 +2009,9 @@ export function generateInputTypesFile(
// 4b. Table condition types (simple equality filter)
// Pass typeRegistry to merge plugin-injected condition fields
// (e.g., vectorEmbedding from VectorSearchPlugin)
statements.push(...generateTableConditionTypes(tablesList, typeRegistry));
if (conditionEnabled) {
statements.push(...generateTableConditionTypes(tablesList, typeRegistry));
}

// 5. OrderBy types
// Pass typeRegistry to merge plugin-injected orderBy values
Expand All @@ -2024,7 +2029,7 @@ export function generateInputTypesFile(
// 7. Custom input types from TypeRegistry
// Also include any extra types referenced by plugin-injected condition fields
const mergedUsedInputTypes = new Set(usedInputTypes);
if (hasTables) {
if (hasTables && conditionEnabled) {
const conditionExtraTypes = collectConditionExtraInputTypes(
tablesList,
typeRegistry,
Expand All @@ -2034,8 +2039,13 @@ export function generateInputTypesFile(
}
}
const tableCrudTypes = tables ? buildTableCrudTypeNames(tables) : undefined;
// Pass customScalarTypes + enumTypes as already-generated to avoid duplicate declarations
const alreadyGenerated = new Set<string>([
...customScalarTypes,
...enumTypes,
]);
statements.push(
...generateCustomInputTypes(typeRegistry, mergedUsedInputTypes, tableCrudTypes, comments),
...generateCustomInputTypes(typeRegistry, mergedUsedInputTypes, tableCrudTypes, comments, alreadyGenerated),
);

// 8. Payload/return types for custom operations
Expand Down
168 changes: 98 additions & 70 deletions graphql/codegen/src/core/codegen/orm/model-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ function strictSelectGuard(selectTypeName: string): t.TSType {
export function generateModelFile(
table: CleanTable,
_useSharedTypes: boolean,
options?: { condition?: boolean },
): GeneratedModelFile {
const conditionEnabled = options?.condition !== false;
const { typeName, singularName, pluralName } = getTableNames(table);
const modelName = `${typeName}Model`;
const baseFileName = lcFirst(typeName);
Expand All @@ -175,7 +177,7 @@ export function generateModelFile(
const selectTypeName = `${typeName}Select`;
const relationTypeName = `${typeName}WithRelations`;
const whereTypeName = getFilterTypeName(table);
const conditionTypeName = `${typeName}Condition`;
const conditionTypeName = conditionEnabled ? `${typeName}Condition` : undefined;
const orderByTypeName = getOrderByTypeName(table);
const createInputTypeName = `Create${typeName}Input`;
const updateInputTypeName = `Update${typeName}Input`;
Expand Down Expand Up @@ -221,20 +223,21 @@ export function generateModelFile(
true,
),
);
const inputTypeImports = [
typeName,
relationTypeName,
selectTypeName,
whereTypeName,
...(conditionTypeName ? [conditionTypeName] : []),
orderByTypeName,
createInputTypeName,
updateInputTypeName,
patchTypeName,
];
statements.push(
createImportDeclaration(
'../input-types',
[
typeName,
relationTypeName,
selectTypeName,
whereTypeName,
conditionTypeName,
orderByTypeName,
createInputTypeName,
updateInputTypeName,
patchTypeName,
],
inputTypeImports,
true,
),
);
Expand Down Expand Up @@ -266,15 +269,20 @@ export function generateModelFile(

// ── findMany ───────────────────────────────────────────────────────────
{
const findManyTypeArgs: Array<(sel: t.TSType) => t.TSType> = [
(sel: t.TSType) => sel,
() => t.tsTypeReference(t.identifier(whereTypeName)),
...(conditionTypeName
? [() => t.tsTypeReference(t.identifier(conditionTypeName))]
: []),
() => t.tsTypeReference(t.identifier(orderByTypeName)),
];
const argsType = (sel: t.TSType) =>
t.tsTypeReference(
t.identifier('FindManyArgs'),
t.tsTypeParameterInstantiation([
sel,
t.tsTypeReference(t.identifier(whereTypeName)),
t.tsTypeReference(t.identifier(conditionTypeName)),
t.tsTypeReference(t.identifier(orderByTypeName)),
]),
t.tsTypeParameterInstantiation(
findManyTypeArgs.map(fn => fn(sel)),
),
);
const retType = (sel: t.TSType) =>
t.tsTypeAnnotation(
Expand Down Expand Up @@ -316,31 +324,31 @@ export function generateModelFile(
t.identifier('args'),
t.identifier('select'),
);
const bodyArgs = [
t.stringLiteral(typeName),
t.stringLiteral(pluralQueryName),
selectExpr,
t.objectExpression([
t.objectProperty(
const findManyObjProps = [
t.objectProperty(
t.identifier('where'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('where'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('where'),
false,
true,
),
),
t.objectProperty(
t.identifier('condition'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('condition'),
false,
true,
),
false,
true,
),
t.objectProperty(
t.identifier('orderBy'),
),
...(conditionTypeName
? [
t.objectProperty(
t.identifier('condition'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('condition'),
false,
true,
),
),
]
: []),
t.objectProperty(
t.identifier('orderBy'),
t.tsAsExpression(
t.optionalMemberExpression(
t.identifier('args'),
Expand Down Expand Up @@ -399,11 +407,18 @@ export function generateModelFile(
true,
),
),
]),
];
const bodyArgs = [
t.stringLiteral(typeName),
t.stringLiteral(pluralQueryName),
selectExpr,
t.objectExpression(findManyObjProps),
t.stringLiteral(whereTypeName),
t.stringLiteral(orderByTypeName),
t.identifier('connectionFieldsMap'),
t.stringLiteral(conditionTypeName),
...(conditionTypeName
? [t.stringLiteral(conditionTypeName)]
: []),
];
classBody.push(
createClassMethod(
Expand All @@ -424,14 +439,19 @@ export function generateModelFile(

// ── findFirst ──────────────────────────────────────────────────────────
{
const findFirstTypeArgs: Array<(sel: t.TSType) => t.TSType> = [
(sel: t.TSType) => sel,
() => t.tsTypeReference(t.identifier(whereTypeName)),
...(conditionTypeName
? [() => t.tsTypeReference(t.identifier(conditionTypeName))]
: []),
];
const argsType = (sel: t.TSType) =>
t.tsTypeReference(
t.identifier('FindFirstArgs'),
t.tsTypeParameterInstantiation([
sel,
t.tsTypeReference(t.identifier(whereTypeName)),
t.tsTypeReference(t.identifier(conditionTypeName)),
]),
t.tsTypeParameterInstantiation(
findFirstTypeArgs.map(fn => fn(sel)),
),
);
const retType = (sel: t.TSType) =>
t.tsTypeAnnotation(
Expand Down Expand Up @@ -477,33 +497,40 @@ export function generateModelFile(
t.identifier('args'),
t.identifier('select'),
);
const findFirstObjProps = [
t.objectProperty(
t.identifier('where'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('where'),
false,
true,
),
),
...(conditionTypeName
? [
t.objectProperty(
t.identifier('condition'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('condition'),
false,
true,
),
),
]
: []),
];
const bodyArgs = [
t.stringLiteral(typeName),
t.stringLiteral(pluralQueryName),
selectExpr,
t.objectExpression([
t.objectProperty(
t.identifier('where'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('where'),
false,
true,
),
),
t.objectProperty(
t.identifier('condition'),
t.optionalMemberExpression(
t.identifier('args'),
t.identifier('condition'),
false,
true,
),
),
]),
t.objectExpression(findFirstObjProps),
t.stringLiteral(whereTypeName),
t.identifier('connectionFieldsMap'),
t.stringLiteral(conditionTypeName),
...(conditionTypeName
? [t.stringLiteral(conditionTypeName)]
: []),
];
classBody.push(
createClassMethod(
Expand Down Expand Up @@ -976,6 +1003,7 @@ export function generateModelFile(
export function generateAllModelFiles(
tables: CleanTable[],
useSharedTypes: boolean,
options?: { condition?: boolean },
): GeneratedModelFile[] {
return tables.map((table) => generateModelFile(table, useSharedTypes));
return tables.map((table) => generateModelFile(table, useSharedTypes, options));
}
4 changes: 2 additions & 2 deletions graphql/codegen/src/core/codegen/templates/query-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export function buildSelections(
// Document Builders
// ============================================================================

export function buildFindManyDocument<TSelect, TWhere, TCondition>(
export function buildFindManyDocument<TSelect, TWhere, TCondition = never>(
operationName: string,
queryField: string,
select: TSelect,
Expand Down Expand Up @@ -320,7 +320,7 @@ export function buildFindManyDocument<TSelect, TWhere, TCondition>(
return { document: print(document), variables };
}

export function buildFindFirstDocument<TSelect, TWhere, TCondition>(
export function buildFindFirstDocument<TSelect, TWhere, TCondition = never>(
operationName: string,
queryField: string,
select: TSelect,
Expand Down
4 changes: 2 additions & 2 deletions graphql/codegen/src/core/codegen/templates/select-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface PageInfo {
endCursor?: string | null;
}

export interface FindManyArgs<TSelect, TWhere, TCondition, TOrderBy> {
export interface FindManyArgs<TSelect, TWhere, TCondition = never, TOrderBy = never> {
select?: TSelect;
where?: TWhere;
condition?: TCondition;
Expand All @@ -33,7 +33,7 @@ export interface FindManyArgs<TSelect, TWhere, TCondition, TOrderBy> {
offset?: number;
}

export interface FindFirstArgs<TSelect, TWhere, TCondition> {
export interface FindFirstArgs<TSelect, TWhere, TCondition = never> {
select?: TSelect;
where?: TWhere;
condition?: TCondition;
Expand Down
Loading
Loading