diff --git a/packages/server/src/db/linkedRows/index.ts b/packages/server/src/db/linkedRows/index.ts index 54acb1f8d6..8d4c420eac 100644 --- a/packages/server/src/db/linkedRows/index.ts +++ b/packages/server/src/db/linkedRows/index.ts @@ -17,9 +17,10 @@ import { FieldType, LinkDocumentValue, Row, - SquashTableFields, Table, TableSchema, + ViewFieldMetadata, + ViewV2, } from "@budibase/types" import sdk from "../../sdk" @@ -242,6 +243,8 @@ function getPrimaryDisplayValue(row: Row, table?: Table) { } } +export type SquashTableFields = Record + /** * This function will take the given enriched rows and squash the links to only contain the primary display field. * @param table The table from which the rows originated. @@ -252,8 +255,40 @@ function getPrimaryDisplayValue(row: Row, table?: Table) { export async function squashLinks( table: Table, enriched: T, - squashFields?: SquashTableFields + options?: { + fromViewId?: string + } ): Promise { + // export function outputRowOptions( + // table: Table, + // viewId: string + // ): OutputRowOptions { + // const view = Object.values(table.views || {}).find( + // (v): v is ViewV2 => sdk.views.isV2(v) && v.id === viewId + // ) + // const viewSchema = view?.schema || {} + + // const squashFields: SquashTableFields = {} + // for (const key of Object.keys(viewSchema)) { + // if (viewSchema[key].columns) { + // squashFields[key] = { + // visibleFieldNames: Object.entries(viewSchema[key].columns) + // .filter(([_, c]) => c.visible !== false) + // .map(([columnName]) => columnName), + // } + // } + // } + + // return { squashNestedFields: squashFields } + // } + let viewSchema: Record = {} + if (options?.fromViewId) { + const view = Object.values(table.views || {}).find( + (v): v is ViewV2 => sdk.views.isV2(v) && v.id === options?.fromViewId + ) + viewSchema = view?.schema || {} + } + // will populate this as we find them const linkedTables = [table] const isArray = Array.isArray(enriched) @@ -273,8 +308,27 @@ export async function squashLinks( const obj: any = { _id: link._id } obj.primaryDisplay = getPrimaryDisplayValue(link, linkedTable) - if (squashFields && squashFields[column]) { - for (const relField of squashFields[column].visibleFieldNames) { + if (viewSchema[column]?.columns) { + const squashFields = Object.entries(viewSchema[column].columns) + .filter(([columnName, viewColumnConfig]) => { + const tableColumn = linkedTable.schema[columnName] + if (!tableColumn) { + return false + } + if ( + [FieldType.LINK, FieldType.FORMULA].includes(tableColumn.type) + ) { + return false + } + return ( + tableColumn.visible !== false && + viewColumnConfig.visible !== false + ) + }) + + .map(([columnName]) => columnName) + + for (const relField of squashFields) { obj[relField] = link[relField] } } diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index cedad3b16b..482621630c 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -86,21 +86,16 @@ export async function search( options.query = removeInvalidFilters(options.query, queriableFields) } - let outputRowOptions - if (options.viewId) { - outputRowOptions = sdk.views.outputRowOptions(table, options.viewId) - } - let result: SearchResponse if (isExternalTable) { span?.addTags({ searchType: "external" }) - result = await external.search(options, table, outputRowOptions) + result = await external.search(options, table) } else if (dbCore.isSqsEnabledForTenant()) { span?.addTags({ searchType: "sqs" }) - result = await internal.sqs.search(options, table, { outputRowOptions }) + result = await internal.sqs.search(options, table) } else { span?.addTags({ searchType: "lucene" }) - result = await internal.lucene.search(options, table, outputRowOptions) + result = await internal.lucene.search(options, table) } span?.addTags({ diff --git a/packages/server/src/sdk/app/rows/search/external.ts b/packages/server/src/sdk/app/rows/search/external.ts index 2313d4ed1d..0ff25a00e4 100644 --- a/packages/server/src/sdk/app/rows/search/external.ts +++ b/packages/server/src/sdk/app/rows/search/external.ts @@ -1,7 +1,6 @@ import { IncludeRelationship, Operation, - OutputRowOptions, PaginationJson, Row, RowSearchParams, @@ -61,8 +60,7 @@ function getPaginationAndLimitParameters( export async function search( options: RowSearchParams, - table: Table, - outputRowOptions?: OutputRowOptions + table: Table ): Promise> { const { tableId } = options const { countRows, paginate, query, ...params } = options @@ -117,7 +115,7 @@ export async function search( let processed = await outputProcessing(table, rows, { preserveLinks: true, squash: true, - squashNestedFields: outputRowOptions?.squashNestedFields, + fromViewId: options.viewId, }) let hasNextPage = false diff --git a/packages/server/src/sdk/app/rows/search/internal/lucene.ts b/packages/server/src/sdk/app/rows/search/internal/lucene.ts index fd604bea49..6f449a2bcb 100644 --- a/packages/server/src/sdk/app/rows/search/internal/lucene.ts +++ b/packages/server/src/sdk/app/rows/search/internal/lucene.ts @@ -2,7 +2,6 @@ import { PROTECTED_INTERNAL_COLUMNS } from "@budibase/shared-core" import { fullSearch, paginatedSearch } from "../utils" import { InternalTables } from "../../../../../db/utils" import { - OutputRowOptions, Row, RowSearchParams, SearchResponse, @@ -16,8 +15,7 @@ import pick from "lodash/pick" export async function search( options: RowSearchParams, - table: Table, - outputRowOptions?: OutputRowOptions + table: Table ): Promise> { const { tableId } = options @@ -62,7 +60,7 @@ export async function search( } response.rows = await outputProcessing(table, response.rows, { - squashNestedFields: outputRowOptions?.squashNestedFields, + fromViewId: options.viewId, }) } diff --git a/packages/server/src/sdk/app/rows/search/internal/sqs.ts b/packages/server/src/sdk/app/rows/search/internal/sqs.ts index b35d045c51..64489042e5 100644 --- a/packages/server/src/sdk/app/rows/search/internal/sqs.ts +++ b/packages/server/src/sdk/app/rows/search/internal/sqs.ts @@ -4,7 +4,6 @@ import { FieldType, isLogicalSearchOperator, Operation, - OutputRowOptions, QueryJson, RelationshipFieldMetadata, RelationshipsJson, @@ -284,7 +283,7 @@ function resyncDefinitionsRequired(status: number, message: string) { export async function search( options: RowSearchParams, table: Table, - opts?: { retrying?: boolean; outputRowOptions?: OutputRowOptions } + opts?: { retrying?: boolean } ): Promise> { let { paginate, query, ...params } = options @@ -383,7 +382,7 @@ export async function search( let finalRows = await outputProcessing(table, processed, { preserveLinks: true, squash: true, - squashNestedFields: opts?.outputRowOptions?.squashNestedFields, + fromViewId: options.viewId, }) // check if we need to pick specific rows out @@ -411,10 +410,7 @@ export async function search( const msg = typeof err === "string" ? err : err.message if (!opts?.retrying && resyncDefinitionsRequired(err.status, msg)) { await sdk.tables.sqs.syncDefinition() - return search(options, table, { - retrying: true, - outputRowOptions: opts?.outputRowOptions, - }) + return search(options, table, { retrying: true }) } // previously the internal table didn't error when a column didn't exist in search if (err.status === 400 && msg?.match(MISSING_COLUMN_REGEX)) { diff --git a/packages/server/src/sdk/app/views/index.ts b/packages/server/src/sdk/app/views/index.ts index c3cf58f21e..493104d252 100644 --- a/packages/server/src/sdk/app/views/index.ts +++ b/packages/server/src/sdk/app/views/index.ts @@ -1,9 +1,7 @@ import { FieldType, - OutputRowOptions, RelationSchemaField, RenameColumn, - SquashTableFields, Table, TableSchema, View, @@ -252,26 +250,3 @@ export function syncSchema( return view } - -export function outputRowOptions( - table: Table, - viewId: string -): OutputRowOptions { - const view = Object.values(table.views || {}).find( - (v): v is ViewV2 => sdk.views.isV2(v) && v.id === viewId - ) - const viewSchema = view?.schema || {} - - const squashFields: SquashTableFields = {} - for (const key of Object.keys(viewSchema)) { - if (viewSchema[key].columns) { - squashFields[key] = { - visibleFieldNames: Object.entries(viewSchema[key].columns) - .filter(([_, c]) => c.visible !== false) - .map(([columnName]) => columnName), - } - } - } - - return { squashNestedFields: squashFields } -} diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 592c2718c0..cd4832072b 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -16,7 +16,6 @@ import { IdentityType, Row, RowAttachment, - SquashTableFields, Table, User, } from "@budibase/types" @@ -36,6 +35,7 @@ import { import { processString } from "@budibase/string-templates" import { isUserMetadataTable } from "../../api/controllers/row/utils" + export * from "./utils" export * from "./attachments" @@ -248,7 +248,7 @@ export async function outputProcessing( preserveLinks?: boolean fromRow?: Row skipBBReferences?: boolean - squashNestedFields?: SquashTableFields + fromViewId?: string } = { squash: true, preserveLinks: false, @@ -344,12 +344,10 @@ export async function outputProcessing( // process formulas after the complex types had been processed enriched = await processFormulas(table, enriched, { dynamic: true }) - if (opts.squash || opts.squashNestedFields) { - enriched = await linkRows.squashLinks( - table, - enriched, - opts.squashNestedFields - ) + if (opts.squash) { + enriched = await linkRows.squashLinks(table, enriched, { + fromViewId: opts?.fromViewId, + }) } // remove null properties to match internal API const isExternal = isExternalTableID(table._id!) diff --git a/packages/types/src/sdk/row.ts b/packages/types/src/sdk/row.ts index fe51bd850d..af9f1481d1 100644 --- a/packages/types/src/sdk/row.ts +++ b/packages/types/src/sdk/row.ts @@ -37,9 +37,3 @@ export enum RowExportFormat { JSON = "json", JSON_WITH_SCHEMA = "jsonWithSchema", } - -export interface OutputRowOptions { - squashNestedFields: SquashTableFields -} - -export type SquashTableFields = Record