diff --git a/packages/server/src/api/controllers/row/index.ts b/packages/server/src/api/controllers/row/index.ts index cc007e121c..4a9047d2cd 100644 --- a/packages/server/src/api/controllers/row/index.ts +++ b/packages/server/src/api/controllers/row/index.ts @@ -199,12 +199,25 @@ export async function searchView(ctx: Ctx) { ctx.throw(404, `View ${viewId} not found`) } + if (view.version !== 2) { + ctx.throw(400, `This method only supports viewsV2`) + } + + const table = await sdk.tables.getTable(view?.tableId) + + const viewFields = + (view.columns && + Object.entries(view.columns).length && + Object.keys(sdk.views.enrichSchema(view, table.schema).schema)) || + undefined + ctx.status = 200 ctx.body = await quotas.addQuery( () => sdk.rows.search({ tableId: view.tableId, query: view.query || {}, + fields: viewFields, ...getSortOptions(ctx, view), }), { diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index ec55ecd8a7..c872128b08 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -893,5 +893,38 @@ describe("/rows", () => { }) } ) + + it("when schema is defined, no other columns are returned", async () => { + const table = await config.createTable(userTable()) + const rows = [] + for (let i = 0; i < 10; i++) { + rows.push( + await config.createRow({ + tableId: table._id, + name: generator.name(), + age: generator.age(), + }) + ) + } + + const createViewResponse = await config.api.viewV2.create({ + columns: { name: { visible: true } }, + }) + const response = await config.api.viewV2.search(createViewResponse.id) + + expect(response.body.rows).toHaveLength(10) + expect(response.body.rows).toEqual( + expect.arrayContaining(rows.map(r => ({ name: r.name }))) + ) + }) + + it("views without data can be returned", async () => { + const table = await config.createTable(userTable()) + + const createViewResponse = await config.api.viewV2.create() + const response = await config.api.viewV2.search(createViewResponse.id) + + expect(response.body.rows).toHaveLength(0) + }) }) }) diff --git a/packages/server/src/sdk/app/rows/search.ts b/packages/server/src/sdk/app/rows/search.ts index 53f3bbbc43..4937460686 100644 --- a/packages/server/src/sdk/app/rows/search.ts +++ b/packages/server/src/sdk/app/rows/search.ts @@ -3,6 +3,7 @@ import { isExternalTable } from "../../../integrations/utils" import * as internal from "./search/internal" import * as external from "./search/external" import { Format } from "../../../api/controllers/view/exporters" +import _ from "lodash" export interface SearchParams { tableId: string @@ -15,6 +16,7 @@ export interface SearchParams { sortType?: SortType version?: string disableEscaping?: boolean + fields?: string[] } export interface ViewParams { @@ -32,8 +34,15 @@ function pickApi(tableId: any) { export async function search(options: SearchParams): Promise<{ rows: any[] + hasNextPage?: boolean + bookmark?: number | null }> { - return pickApi(options.tableId).search(options) + const result = await pickApi(options.tableId).search(options) + + if (options.fields) { + result.rows = result.rows.map((r: any) => _.pick(r, options.fields!)) + } + return result } export interface ExportRowsParams {