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 @@ -249,7 +249,7 @@ export interface Post {
content?: string | null;
authorId?: string | null;
publishedAt?: string | null;
tags?: string | null;
tags?: string[] | null;
}
export interface Comment {
id: string;
Expand Down Expand Up @@ -358,7 +358,7 @@ export interface PostFilter {
content?: StringFilter;
authorId?: UUIDFilter;
publishedAt?: DatetimeFilter;
tags?: StringFilter;
tags?: StringListFilter;
and?: PostFilter[];
or?: PostFilter[];
not?: PostFilter;
Expand Down Expand Up @@ -436,15 +436,15 @@ export interface CreatePostInput {
content?: string;
authorId: string;
publishedAt?: string;
tags?: string;
tags?: string[];
};
}
export interface PostPatch {
title?: string | null;
content?: string | null;
authorId?: string | null;
publishedAt?: string | null;
tags?: string | null;
tags?: string[] | null;
}
export interface UpdatePostInput {
clientMutationId?: string;
Expand Down Expand Up @@ -2131,7 +2131,7 @@ export interface Post {
content?: string | null;
authorId?: string | null;
publishedAt?: string | null;
tags?: string | null;
tags?: string[] | null;
}
export interface Category {
id: string;
Expand Down Expand Up @@ -2197,7 +2197,7 @@ export interface PostFilter {
content?: StringFilter;
authorId?: UUIDFilter;
publishedAt?: DatetimeFilter;
tags?: StringFilter;
tags?: StringListFilter;
and?: PostFilter[];
or?: PostFilter[];
not?: PostFilter;
Expand Down Expand Up @@ -2235,15 +2235,15 @@ export interface CreatePostInput {
content?: string;
authorId: string;
publishedAt?: string;
tags?: string;
tags?: string[];
};
}
export interface PostPatch {
title?: string | null;
content?: string | null;
authorId?: string | null;
publishedAt?: string | null;
tags?: string | null;
tags?: string[] | null;
}
export interface UpdatePostInput {
clientMutationId?: string;
Expand Down
92 changes: 68 additions & 24 deletions graphql/codegen/src/core/codegen/orm/input-types-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getFilterTypeName,
getGeneratedFileHeader,
getOrderByTypeName,
getPatchTypeName,
getPrimaryKeyInfo,
getTableNames,
isRelationField,
Expand Down Expand Up @@ -604,7 +605,10 @@ function buildEntityProperties(table: CleanTable): InterfaceProperty[] {

const fieldType =
typeof field.type === 'string' ? field.type : field.type.gqlType;
const tsType = scalarToInputTs(fieldType);
const isArray =
typeof field.type !== 'string' && field.type.isArray;
const baseTsType = scalarToInputTs(fieldType);
const tsType = isArray ? `${baseTsType}[]` : baseTsType;
const isNullable = field.name !== 'id' && field.name !== 'nodeId';

properties.push({
Expand Down Expand Up @@ -1068,8 +1072,8 @@ function generateEntitySelectTypes(
/**
* Map field type to filter type
*/
function getFilterTypeForField(fieldType: string): string {
return scalarToFilterType(fieldType) ?? 'StringFilter';
function getFilterTypeForField(fieldType: string, isArray = false): string {
return scalarToFilterType(fieldType, isArray) ?? 'StringFilter';
}

/**
Expand All @@ -1082,9 +1086,11 @@ function buildTableFilterProperties(table: CleanTable): InterfaceProperty[] {
for (const field of table.fields) {
const fieldType =
typeof field.type === 'string' ? field.type : field.type.gqlType;
const isArray =
typeof field.type !== 'string' && field.type.isArray;
if (isRelationField(field.name, table)) continue;

const filterType = getFilterTypeForField(fieldType);
const filterType = getFilterTypeForField(fieldType, isArray);
properties.push({ name: field.name, type: filterType, optional: true });
}

Expand Down Expand Up @@ -1215,6 +1221,17 @@ function buildOrderByValues(
table: CleanTable,
typeRegistry?: TypeRegistry,
): string[] {
// When the schema's orderBy enum is available, use it as the source of truth
// instead of naively generating values for every field.
if (typeRegistry) {
const orderByTypeName = getOrderByTypeName(table);
const orderByType = typeRegistry.get(orderByTypeName);
if (orderByType?.kind === 'ENUM' && orderByType.enumValues) {
return [...orderByType.enumValues];
}
}

// Fallback: derive from table fields when schema enum is not available
const values: string[] = ['PRIMARY_KEY_ASC', 'PRIMARY_KEY_DESC', 'NATURAL'];

for (const field of table.fields) {
Expand All @@ -1224,21 +1241,6 @@ function buildOrderByValues(
values.push(`${upperSnake}_DESC`);
}

// Merge any additional values from the schema's orderBy enum type
// (e.g., plugin-added values like EMBEDDING_DISTANCE_ASC/DESC)
if (typeRegistry) {
const orderByTypeName = getOrderByTypeName(table);
const orderByType = typeRegistry.get(orderByTypeName);
if (orderByType?.kind === 'ENUM' && orderByType.enumValues) {
const existingValues = new Set(values);
for (const value of orderByType.enumValues) {
if (!existingValues.has(value)) {
values.push(value);
}
}
}
}

return values;
}

Expand Down Expand Up @@ -1292,7 +1294,10 @@ function buildCreateDataFieldsFromTable(

const fieldType =
typeof field.type === 'string' ? field.type : field.type.gqlType;
const tsType = scalarToInputTs(fieldType);
const isArray =
typeof field.type !== 'string' && field.type.isArray;
const baseTsType = scalarToInputTs(fieldType);
const tsType = isArray ? `${baseTsType}[]` : baseTsType;
const isOptional = !field.name.endsWith('Id');

fields.push({ name: field.name, type: tsType, optional: isOptional });
Expand Down Expand Up @@ -1423,9 +1428,45 @@ function buildCreateInputInterface(
}

/**
* Build Patch type properties
* Build Patch type properties.
*
* Prefers reading from the GraphQL schema's Patch input type when available
* (via typeRegistry), which correctly excludes computed/virtual fields.
* Falls back to deriving from table fields if the schema type is not found.
*/
function buildPatchProperties(table: CleanTable): InterfaceProperty[] {
function buildPatchProperties(
table: CleanTable,
typeRegistry?: TypeRegistry,
): InterfaceProperty[] {
// Try to read from the schema's Patch input type first
if (typeRegistry) {
const patchTypeName = getPatchTypeName(table);
const patchType = typeRegistry.get(patchTypeName);
if (
patchType?.kind === 'INPUT_OBJECT' &&
patchType.inputFields
) {
const properties: InterfaceProperty[] = [];
for (const field of patchType.inputFields) {
if (
EXCLUDED_MUTATION_FIELDS.includes(
field.name as (typeof EXCLUDED_MUTATION_FIELDS)[number],
)
)
continue;

const tsType = typeRefToTs(field.type);
properties.push({
name: field.name,
type: `${tsType} | null`,
optional: true,
});
}
return properties;
}
}

// Fallback: derive from table fields
const properties: InterfaceProperty[] = [];

for (const field of table.fields) {
Expand All @@ -1439,7 +1480,10 @@ function buildPatchProperties(table: CleanTable): InterfaceProperty[] {

const fieldType =
typeof field.type === 'string' ? field.type : field.type.gqlType;
const tsType = scalarToInputTs(fieldType);
const isArray =
typeof field.type !== 'string' && field.type.isArray;
const baseTsType = scalarToInputTs(fieldType);
const tsType = isArray ? `${baseTsType}[]` : baseTsType;

properties.push({
name: field.name,
Expand Down Expand Up @@ -1472,7 +1516,7 @@ function generateCrudInputTypes(

// Patch interface
statements.push(
createExportedInterface(patchName, buildPatchProperties(table)),
createExportedInterface(patchName, buildPatchProperties(table, typeRegistry)),
);

// Update input - v5 uses entity-specific patch field names (e.g., "userPatch")
Expand Down
Loading
Loading