Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
23a31e5
feat: wire tablesMeta through pipeline, enrich M:N relations, add ORM…
pyramation Mar 21, 2026
e8277db
fix: remove dead toPascalCase import, drop async on add/remove method…
pyramation Mar 21, 2026
de47501
fix: use inflekt singularize for M:N method names (handles irregular …
pyramation Mar 21, 2026
b7eaca5
fix: use existing utils for junction naming + resolve actual PK types…
pyramation Mar 21, 2026
e38e468
feat: add orm-test package — M:N integration tests against real Postg…
pyramation Mar 21, 2026
e6e5553
Merge remote-tracking branch 'origin/main' into devin/1774056352-orm-…
devin-ai-integration[bot] Mar 21, 2026
b0aba03
feat: add mega query test — all 7 ConstructivePreset plugins + BM25
pyramation Mar 21, 2026
421b4dc
Merge remote-tracking branch 'origin/main' into devin/1774056352-orm-…
devin-ai-integration[bot] Mar 21, 2026
3be2036
feat: rewrite orm-test to use codegen pipeline + ORM models
pyramation Mar 21, 2026
2787eba
feat: improve mega-query test with concrete score assertions and bett…
pyramation Mar 21, 2026
0bda790
fix: composite PK detection + filter type-safety from schema source o…
pyramation Mar 21, 2026
5b88c18
Merge remote-tracking branch 'origin/devin/1774052099-orm-m2m-methods…
pyramation Mar 21, 2026
ae2c27f
Merge remote-tracking branch 'origin/devin/1774056352-orm-test' into …
pyramation Mar 21, 2026
d497aa5
Merge remote-tracking branch 'origin/devin/1774087459-fix-filter-type…
pyramation Mar 21, 2026
e251073
fix: switch orm-m2n tests to ConstructivePreset (clean M:N field names)
pyramation Mar 21, 2026
367d2c2
fix: remove unnecessary setup.sql, use gen_random_uuid(), grant PUBLI…
pyramation Mar 21, 2026
067c902
fix: move CREATE EXTENSION from mega-seed.sql to db.extensions config…
pyramation Mar 21, 2026
01f22e3
feat: composite PK delete support — junction tables use (post_id, tag…
pyramation Mar 21, 2026
4d1930d
refactor: consolidate input type name derivation into shared helpers
pyramation Mar 21, 2026
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 @@ -136,7 +136,9 @@ export class UserModel {
const {
document,
variables
} = buildDeleteByPkDocument("User", "deleteUser", "user", args.where.id, "DeleteUserInput", "id", args.select, connectionFieldsMap);
} = buildDeleteByPkDocument("User", "deleteUser", "user", {
id: args.where.id
}, "DeleteUserInput", args.select, connectionFieldsMap);
return new QueryBuilder({
client: this.client,
operation: "mutation",
Expand Down Expand Up @@ -390,7 +392,9 @@ export class OrganizationModel {
const {
document,
variables
} = buildDeleteByPkDocument("Organization", "removeOrganization", "organization", args.where.id, "DeleteOrganizationInput", "id", args.select, connectionFieldsMap);
} = buildDeleteByPkDocument("Organization", "removeOrganization", "organization", {
id: args.where.id
}, "RemoveOrganizationInput", args.select, connectionFieldsMap);
return new QueryBuilder({
client: this.client,
operation: "mutation",
Expand Down
105 changes: 99 additions & 6 deletions graphql/codegen/src/core/codegen/orm/input-types-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1077,10 +1077,38 @@ function getFilterTypeForField(fieldType: string, isArray = false): string {
}

/**
* Build properties for a table filter interface
* Build properties for a table filter interface.
*
* When typeRegistry is available, uses the schema's filter input type as
* the sole source of truth — this captures plugin-injected filter fields
* (e.g., bm25Body, tsvTsv, trgmName, vectorEmbedding, geom) that are not
* present on the entity type itself. Same pattern as buildOrderByValues().
*/
function buildTableFilterProperties(table: Table): InterfaceProperty[] {
function buildTableFilterProperties(
table: Table,
typeRegistry?: TypeRegistry,
): InterfaceProperty[] {
const filterName = getFilterTypeName(table);

// When the schema's filter type is available, use it as the source of truth
if (typeRegistry) {
const filterType = typeRegistry.get(filterName);
if (filterType?.kind === 'INPUT_OBJECT' && filterType.inputFields) {
const properties: InterfaceProperty[] = [];
for (const field of filterType.inputFields) {
const tsType = typeRefToTs(field.type);
properties.push({
name: field.name,
type: tsType,
optional: true,
description: stripSmartComments(field.description, true),
});
}
return properties;
}
}

// Fallback: derive from table fields when schema filter type is not available
const properties: InterfaceProperty[] = [];

for (const field of table.fields) {
Expand All @@ -1105,13 +1133,19 @@ function buildTableFilterProperties(table: Table): InterfaceProperty[] {
/**
* Generate table filter type statements
*/
function generateTableFilterTypes(tables: Table[]): t.Statement[] {
function generateTableFilterTypes(
tables: Table[],
typeRegistry?: TypeRegistry,
): t.Statement[] {
const statements: t.Statement[] = [];

for (const table of tables) {
const filterName = getFilterTypeName(table);
statements.push(
createExportedInterface(filterName, buildTableFilterProperties(table)),
createExportedInterface(
filterName,
buildTableFilterProperties(table, typeRegistry),
),
);
}

Expand Down Expand Up @@ -1956,6 +1990,54 @@ function generateConnectionFieldsMap(
// Plugin-Injected Type Collector
// ============================================================================

/**
* Collect extra input type names referenced by plugin-injected filter fields.
*
* When the schema's filter type is used as source of truth, plugin-injected
* fields reference custom filter types (e.g., Bm25BodyFilter, TsvectorFilter,
* GeometryFilter) that also need to be generated. This function discovers
* those types by comparing the schema's filter type fields against the
* standard scalar filter types.
*/
function collectFilterExtraInputTypes(
tables: Table[],
typeRegistry: TypeRegistry,
): Set<string> {
const extraTypes = new Set<string>();

for (const table of tables) {
const filterTypeName = getFilterTypeName(table);
const filterType = typeRegistry.get(filterTypeName);
if (
!filterType ||
filterType.kind !== 'INPUT_OBJECT' ||
!filterType.inputFields
) {
continue;
}

const tableFieldNames = new Set(
table.fields
.filter((f) => !isRelationField(f.name, table))
.map((f) => f.name),
);

for (const field of filterType.inputFields) {
// Skip standard column-derived fields and logical operators
if (tableFieldNames.has(field.name)) continue;
if (['and', 'or', 'not'].includes(field.name)) continue;

// Collect the base type name of this extra field
const baseName = getTypeBaseName(field.type);
if (baseName && !SCALAR_NAMES.has(baseName)) {
extraTypes.add(baseName);
}
}
}

return extraTypes;
}

/**
* Collect extra input type names referenced by plugin-injected condition fields.
*
Expand Down Expand Up @@ -2048,7 +2130,9 @@ export function generateInputTypesFile(
statements.push(...generateEntitySelectTypes(tablesList, tableByName));

// 4. Table filter types
statements.push(...generateTableFilterTypes(tablesList));
// Pass typeRegistry to use schema's filter type as source of truth,
// capturing plugin-injected filter fields (e.g., bm25, tsvector, trgm, vector, geom)
statements.push(...generateTableFilterTypes(tablesList, typeRegistry));

// 4b. Table condition types (simple equality filter)
// Pass typeRegistry to merge plugin-injected condition fields
Expand All @@ -2071,8 +2155,17 @@ export function generateInputTypesFile(
statements.push(...generateConnectionFieldsMap(tablesList, tableByName));

// 7. Custom input types from TypeRegistry
// Also include any extra types referenced by plugin-injected condition fields
// Also include any extra types referenced by plugin-injected filter/condition fields
const mergedUsedInputTypes = new Set(usedInputTypes);
if (hasTables) {
const filterExtraTypes = collectFilterExtraInputTypes(
tablesList,
typeRegistry,
);
for (const typeName of filterExtraTypes) {
mergedUsedInputTypes.add(typeName);
}
}
if (hasTables && conditionEnabled) {
const conditionExtraTypes = collectConditionExtraInputTypes(
tablesList,
Expand Down
Loading
Loading