Improving the typing around the ExternalRequest object, which has implications throughout the row API and SDK, cleaning up where possible based on it.

This commit is contained in:
mike12345567 2023-10-18 10:57:04 +01:00
parent 3abb2fef04
commit 68e8630d85
6 changed files with 44 additions and 47 deletions

View File

@ -280,17 +280,8 @@ function isEditableColumn(column: FieldSchema) {
return !(isExternalAutoColumn || isFormula) return !(isExternalAutoColumn || isFormula)
} }
export type ExternalRequestReturnType<T> = T extends Operation.READ export type ExternalRequestReturnType<T extends Operation> =
? T extends Operation.READ ? Row[] : { row: Row; table: Table }
| Row[]
| {
row: Row
table: Table
}
: {
row: Row
table: Table
}
export class ExternalRequest<T extends Operation> { export class ExternalRequest<T extends Operation> {
private readonly operation: T private readonly operation: T
@ -857,11 +848,12 @@ export class ExternalRequest<T extends Operation> {
} }
const output = this.outputProcessing(response, table, relationships) const output = this.outputProcessing(response, table, relationships)
// if reading it'll just be an array of rows, return whole thing // if reading it'll just be an array of rows, return whole thing
const result = ( if (operation === Operation.READ) {
operation === Operation.READ && Array.isArray(response) return (
? output Array.isArray(output) ? output : [output]
: { row: output[0], table } ) as ExternalRequestReturnType<T>
) as ExternalRequestReturnType<T> } else {
return result return { row: output[0], table } as ExternalRequestReturnType<T>
}
} }
} }

View File

@ -44,7 +44,7 @@ export async function handleRequest<T extends Operation>(
return [] as any return [] as any
} }
return new ExternalRequest(operation, tableId, opts?.datasource).run( return new ExternalRequest<T>(operation, tableId, opts?.datasource).run(
opts || {} opts || {}
) )
} }
@ -148,17 +148,17 @@ export async function find(ctx: UserCtx): Promise<Row> {
export async function destroy(ctx: UserCtx) { export async function destroy(ctx: UserCtx) {
const tableId = utils.getTableId(ctx) const tableId = utils.getTableId(ctx)
const _id = ctx.request.body._id const _id = ctx.request.body._id
const { row } = (await handleRequest(Operation.DELETE, tableId, { const { row } = await handleRequest(Operation.DELETE, tableId, {
id: breakRowIdField(_id), id: breakRowIdField(_id),
includeSqlRelationships: IncludeRelationship.EXCLUDE, includeSqlRelationships: IncludeRelationship.EXCLUDE,
})) as { row: Row } })
return { response: { ok: true, id: _id }, row } return { response: { ok: true, id: _id }, row }
} }
export async function bulkDestroy(ctx: UserCtx) { export async function bulkDestroy(ctx: UserCtx) {
const { rows } = ctx.request.body const { rows } = ctx.request.body
const tableId = utils.getTableId(ctx) const tableId = utils.getTableId(ctx)
let promises: Promise<Row[] | { row: Row; table: Table }>[] = [] let promises: Promise<{ row: Row; table: Table }>[] = []
for (let row of rows) { for (let row of rows) {
promises.push( promises.push(
handleRequest(Operation.DELETE, tableId, { handleRequest(Operation.DELETE, tableId, {
@ -167,7 +167,7 @@ export async function bulkDestroy(ctx: UserCtx) {
}) })
) )
} }
const responses = (await Promise.all(promises)) as { row: Row }[] const responses = await Promise.all(promises)
return { response: { ok: true }, rows: responses.map(resp => resp.row) } return { response: { ok: true }, rows: responses.map(resp => resp.row) }
} }
@ -183,11 +183,11 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
ctx.throw(400, "Datasource has not been configured for plus API.") ctx.throw(400, "Datasource has not been configured for plus API.")
} }
const tables = datasource.entities const tables = datasource.entities
const response = (await handleRequest(Operation.READ, tableId, { const response = await handleRequest(Operation.READ, tableId, {
id, id,
datasource, datasource,
includeSqlRelationships: IncludeRelationship.INCLUDE, includeSqlRelationships: IncludeRelationship.INCLUDE,
})) as Row[] })
const table: Table = tables[tableName] const table: Table = tables[tableName]
const row = response[0] const row = response[0]
// this seems like a lot of work, but basically we need to dig deeper for the enrich // this seems like a lot of work, but basically we need to dig deeper for the enrich

View File

@ -7,11 +7,11 @@ export async function getRow(
rowId: string, rowId: string,
opts?: { relationships?: boolean } opts?: { relationships?: boolean }
) { ) {
const response = (await handleRequest(Operation.READ, tableId, { const response = await handleRequest(Operation.READ, tableId, {
id: breakRowIdField(rowId), id: breakRowIdField(rowId),
includeSqlRelationships: opts?.relationships includeSqlRelationships: opts?.relationships
? IncludeRelationship.INCLUDE ? IncludeRelationship.INCLUDE
: IncludeRelationship.EXCLUDE, : IncludeRelationship.EXCLUDE,
})) as Row[] })
return response ? response[0] : response return response ? response[0] : response
} }

View File

@ -1,4 +1,4 @@
import { SearchFilters, SearchParams } from "@budibase/types" import { SearchFilters, SearchParams, Row } from "@budibase/types"
import { isExternalTable } from "../../../integrations/utils" import { isExternalTable } from "../../../integrations/utils"
import * as internal from "./search/internal" import * as internal from "./search/internal"
import * as external from "./search/external" import * as external from "./search/external"
@ -45,7 +45,7 @@ export async function exportRows(
return pickApi(options.tableId).exportRows(options) return pickApi(options.tableId).exportRows(options)
} }
export async function fetch(tableId: string) { export async function fetch(tableId: string): Promise<Row[]> {
return pickApi(tableId).fetch(tableId) return pickApi(tableId).fetch(tableId)
} }
@ -53,6 +53,6 @@ export async function fetchView(
tableId: string, tableId: string,
viewName: string, viewName: string,
params: ViewParams params: ViewParams
) { ): Promise<Row[]> {
return pickApi(tableId).fetchView(viewName, params) return pickApi(tableId).fetchView(viewName, params)
} }

View File

@ -55,15 +55,15 @@ export async function search(options: SearchParams) {
try { try {
const table = await sdk.tables.getTable(tableId) const table = await sdk.tables.getTable(tableId)
options = searchInputMapping(table, options) options = searchInputMapping(table, options)
let rows = (await handleRequest(Operation.READ, tableId, { let rows = await handleRequest(Operation.READ, tableId, {
filters: query, filters: query,
sort, sort,
paginate: paginateObj as PaginationJson, paginate: paginateObj as PaginationJson,
includeSqlRelationships: IncludeRelationship.INCLUDE, includeSqlRelationships: IncludeRelationship.INCLUDE,
})) as Row[] })
let hasNextPage = false let hasNextPage = false
if (paginate && rows.length === limit) { if (paginate && rows.length === limit) {
const nextRows = (await handleRequest(Operation.READ, tableId, { const nextRows = await handleRequest(Operation.READ, tableId, {
filters: query, filters: query,
sort, sort,
paginate: { paginate: {
@ -71,7 +71,7 @@ export async function search(options: SearchParams) {
page: bookmark! * limit + 1, page: bookmark! * limit + 1,
}, },
includeSqlRelationships: IncludeRelationship.INCLUDE, includeSqlRelationships: IncludeRelationship.INCLUDE,
})) as Row[] })
hasNextPage = nextRows.length > 0 hasNextPage = nextRows.length > 0
} }
@ -172,12 +172,18 @@ export async function exportRows(
} }
} }
export async function fetch(tableId: string) { export async function fetch(tableId: string): Promise<Row[]> {
const response = await handleRequest(Operation.READ, tableId, { const response = await handleRequest<Operation.READ>(
includeSqlRelationships: IncludeRelationship.INCLUDE, Operation.READ,
}) tableId,
{
includeSqlRelationships: IncludeRelationship.INCLUDE,
}
)
const table = await sdk.tables.getTable(tableId) const table = await sdk.tables.getTable(tableId)
return await outputProcessing(table, response, { preserveLinks: true }) return await outputProcessing<Row[]>(table, response, {
preserveLinks: true,
})
} }
export async function fetchView(viewName: string) { export async function fetchView(viewName: string) {

View File

@ -6,26 +6,26 @@ import {
import env from "../../../../environment" import env from "../../../../environment"
import { fullSearch, paginatedSearch } from "./internalSearch" import { fullSearch, paginatedSearch } from "./internalSearch"
import { import {
InternalTables,
getRowParams,
DocumentType, DocumentType,
getRowParams,
InternalTables,
} from "../../../../db/utils" } from "../../../../db/utils"
import { getGlobalUsersFromMetadata } from "../../../../utilities/global" import { getGlobalUsersFromMetadata } from "../../../../utilities/global"
import { outputProcessing } from "../../../../utilities/rowProcessor" import { outputProcessing } from "../../../../utilities/rowProcessor"
import { Database, Row, Table, SearchParams } from "@budibase/types" import { Database, Row, SearchParams, Table } from "@budibase/types"
import { cleanExportRows } from "../utils" import { cleanExportRows } from "../utils"
import { import {
Format,
csv, csv,
Format,
json, json,
jsonWithSchema, jsonWithSchema,
} from "../../../../api/controllers/view/exporters" } from "../../../../api/controllers/view/exporters"
import * as inMemoryViews from "../../../../db/inMemoryView" import * as inMemoryViews from "../../../../db/inMemoryView"
import { import {
migrateToInMemoryView,
migrateToDesignView,
getFromDesignDoc, getFromDesignDoc,
getFromMemoryDoc, getFromMemoryDoc,
migrateToDesignView,
migrateToInMemoryView,
} from "../../../../api/controllers/view/utils" } from "../../../../api/controllers/view/utils"
import sdk from "../../../../sdk" import sdk from "../../../../sdk"
import { ExportRowsParams, ExportRowsResult } from "../search" import { ExportRowsParams, ExportRowsResult } from "../search"
@ -139,13 +139,12 @@ export async function exportRows(
} }
} }
export async function fetch(tableId: string) { export async function fetch(tableId: string): Promise<Row[]> {
const db = context.getAppDB() const db = context.getAppDB()
const table = await sdk.tables.getTable(tableId) const table = await sdk.tables.getTable(tableId)
const rows = await getRawTableData(db, tableId) const rows = await getRawTableData(db, tableId)
const result = await outputProcessing(table, rows) return await outputProcessing(table, rows)
return result
} }
async function getRawTableData(db: Database, tableId: string) { async function getRawTableData(db: Database, tableId: string) {