diff --git a/packages/server/src/sdk/app/rows/queryUtils.ts b/packages/server/src/sdk/app/rows/queryUtils.ts index 78cf64e184..65f400a1d9 100644 --- a/packages/server/src/sdk/app/rows/queryUtils.ts +++ b/packages/server/src/sdk/app/rows/queryUtils.ts @@ -16,32 +16,32 @@ export const removeInvalidFilters = ( validFields = validFields.map(f => f.toLowerCase()) for (const filterKey of Object.keys(result) as (keyof SearchFilters)[]) { - if (typeof result[filterKey] !== "object") { + const filter = result[filterKey] + if (!filter || typeof filter !== "object") { continue } if (isLogicalSearchOperator(filterKey)) { const resultingConditions: SearchFilters[] = [] - for (const condition of result[filterKey].conditions) { + for (const condition of filter.conditions) { const resultingCondition = removeInvalidFilters(condition, validFields) if (Object.keys(resultingCondition).length) { resultingConditions.push(resultingCondition) } } if (resultingConditions.length) { - result[filterKey].conditions = resultingConditions + filter.conditions = resultingConditions } else { delete result[filterKey] } continue } - const filter = result[filterKey] for (const columnKey of Object.keys(filter)) { const possibleKeys = [columnKey, db.removeKeyNumbering(columnKey)].map( c => c.toLowerCase() ) if (!validFields.some(f => possibleKeys.includes(f.toLowerCase()))) { - delete filter[columnKey] + delete filter[columnKey as keyof typeof filter] } } if (!Object.keys(filter).length) { @@ -60,18 +60,22 @@ export const getQueryableFields = async ( table: Table, allowedFields: string[], fromTables: string[], - opts: { allowRelationships?: boolean } = { allowRelationships: true } + opts?: { noRelationships?: boolean } ): Promise => { const result = [] for (const field of Object.keys(table.schema).filter( f => allowedFields.includes(f) && table.schema[f].visible !== false )) { const subSchema = table.schema[field] - if (opts.allowRelationships && subSchema.type === FieldType.LINK) { - if (fromTables.includes(subSchema.tableId)) { - // avoid circular loops - continue - } + const isRelationship = subSchema.type === FieldType.LINK + // avoid relationship loops + if ( + isRelationship && + (opts?.noRelationships || fromTables.includes(subSchema.tableId)) + ) { + continue + } + if (isRelationship) { try { const relatedTable = await sdk.tables.getTable(subSchema.tableId) const relatedFields = await extractTableFields( @@ -79,7 +83,7 @@ export const getQueryableFields = async ( Object.keys(relatedTable.schema), [...fromTables, subSchema.tableId], // don't let it recurse back and forth between relationships - { allowRelationships: false } + { noRelationships: true } ) result.push( diff --git a/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts index c156b2d5ba..aabc359484 100644 --- a/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts +++ b/packages/server/src/sdk/app/rows/tests/queryUtils.spec.ts @@ -386,35 +386,13 @@ describe("query utils", () => { expect(result).toEqual([ "_id", "name", - // deep 1 aux1 primitive props + // aux1 primitive props "aux1.name", "aux1Table.name", - // deep 2 aux1 primitive props - "aux1.aux2_1.title", - "aux1Table.aux2_1.title", - "aux1.aux2Table.title", - "aux1Table.aux2Table.title", - - // deep 2 aux2 primitive props - "aux1.aux2_2.title", - "aux1Table.aux2_2.title", - "aux1.aux2Table.title", - "aux1Table.aux2Table.title", - - // deep 1 aux2 primitive props + // aux2 primitive props "aux2.title", "aux2Table.title", - - // deep 2 aux2 primitive props - "aux2.aux1_1.name", - "aux2Table.aux1_1.name", - "aux2.aux1Table.name", - "aux2Table.aux1Table.name", - "aux2.aux1_2.name", - "aux2Table.aux1_2.name", - "aux2.aux1Table.name", - "aux2Table.aux1Table.name", ]) }) @@ -426,35 +404,17 @@ describe("query utils", () => { "_id", "name", - // deep 1 aux2_1 primitive props + // aux2_1 primitive props "aux2_1.title", "aux2Table.title", - // deep 2 aux2_1 primitive props - "aux2_1.table.name", - "aux2Table.table.name", - "aux2_1.TestTable.name", - "aux2Table.TestTable.name", - - // deep 1 aux2_2 primitive props + // aux2_2 primitive props "aux2_2.title", "aux2Table.title", - // deep 2 aux2_2 primitive props - "aux2_2.table.name", - "aux2Table.table.name", - "aux2_2.TestTable.name", - "aux2Table.TestTable.name", - - // deep 1 table primitive props + // table primitive props "table.name", "TestTable.name", - - // deep 2 table primitive props - "table.aux2.title", - "TestTable.aux2.title", - "table.aux2Table.title", - "TestTable.aux2Table.title", ]) }) @@ -466,35 +426,17 @@ describe("query utils", () => { "_id", "title", - // deep 1 aux1_1 primitive props + // aux1_1 primitive props "aux1_1.name", "aux1Table.name", - // deep 2 aux1_1 primitive props - "aux1_1.table.name", - "aux1Table.table.name", - "aux1_1.TestTable.name", - "aux1Table.TestTable.name", - - // deep 1 aux1_2 primitive props + // aux1_2 primitive props "aux1_2.name", "aux1Table.name", - // deep 2 aux1_2 primitive props - "aux1_2.table.name", - "aux1Table.table.name", - "aux1_2.TestTable.name", - "aux1Table.TestTable.name", - - // deep 1 table primitive props + // table primitive props "table.name", "TestTable.name", - - // deep 2 table primitive props - "table.aux1.name", - "TestTable.aux1.name", - "table.aux1Table.name", - "TestTable.aux1Table.name", ]) }) })