Mostly solving type errors around passing the view all the way down, got a fair few left.
This commit is contained in:
parent
51774b3434
commit
fc9b54cb85
|
@ -42,6 +42,7 @@ export async function handleRequest<T extends Operation>(
|
|||
|
||||
export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) {
|
||||
const source = await utils.getSource(ctx)
|
||||
const table = await utils.getTableFromSource(source)
|
||||
const { _id, ...rowData } = ctx.request.body
|
||||
|
||||
const { row: dataToUpdate } = await inputProcessing(
|
||||
|
@ -58,11 +59,11 @@ export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) {
|
|||
throw { validation: validateResult.errors }
|
||||
}
|
||||
|
||||
const beforeRow = await sdk.rows.external.getRow(tableId, _id, {
|
||||
const beforeRow = await sdk.rows.external.getRow(table._id!, _id, {
|
||||
relationships: true,
|
||||
})
|
||||
|
||||
const response = await handleRequest(Operation.UPDATE, tableId, {
|
||||
const response = await handleRequest(Operation.UPDATE, source, {
|
||||
id: breakRowIdField(_id),
|
||||
row: dataToUpdate,
|
||||
})
|
||||
|
@ -70,7 +71,7 @@ export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) {
|
|||
// The id might have been changed, so the refetching would fail. Recalculating the id just in case
|
||||
const updatedId =
|
||||
generateIdForRow({ ...beforeRow, ...dataToUpdate }, table) || _id
|
||||
const row = await sdk.rows.external.getRow(tableId, updatedId, {
|
||||
const row = await sdk.rows.external.getRow(table._id!, updatedId, {
|
||||
relationships: true,
|
||||
})
|
||||
|
||||
|
@ -78,7 +79,6 @@ export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) {
|
|||
outputProcessing(table, row, {
|
||||
squash: true,
|
||||
preserveLinks: true,
|
||||
fromViewId: viewId,
|
||||
}),
|
||||
outputProcessing(table, beforeRow, {
|
||||
squash: true,
|
||||
|
@ -95,9 +95,9 @@ export async function patch(ctx: UserCtx<PatchRowRequest, PatchRowResponse>) {
|
|||
}
|
||||
|
||||
export async function destroy(ctx: UserCtx) {
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
const source = await utils.getSource(ctx)
|
||||
const _id = ctx.request.body._id
|
||||
const { row } = await handleRequest(Operation.DELETE, tableId, {
|
||||
const { row } = await handleRequest(Operation.DELETE, source, {
|
||||
id: breakRowIdField(_id),
|
||||
includeSqlRelationships: IncludeRelationship.EXCLUDE,
|
||||
})
|
||||
|
@ -106,11 +106,11 @@ export async function destroy(ctx: UserCtx) {
|
|||
|
||||
export async function bulkDestroy(ctx: UserCtx) {
|
||||
const { rows } = ctx.request.body
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
const source = await utils.getSource(ctx)
|
||||
let promises: Promise<{ row: Row; table: Table }>[] = []
|
||||
for (let row of rows) {
|
||||
promises.push(
|
||||
handleRequest(Operation.DELETE, tableId, {
|
||||
handleRequest(Operation.DELETE, source, {
|
||||
id: breakRowIdField(row._id),
|
||||
includeSqlRelationships: IncludeRelationship.EXCLUDE,
|
||||
})
|
||||
|
@ -125,6 +125,7 @@ export async function bulkDestroy(ctx: UserCtx) {
|
|||
|
||||
export async function fetchEnrichedRow(ctx: UserCtx) {
|
||||
const id = ctx.params.rowId
|
||||
const source = await utils.getSource(ctx)
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
const { datasourceId, tableName } = breakExternalTableId(tableId)
|
||||
const datasource: Datasource = await sdk.datasources.get(datasourceId)
|
||||
|
@ -132,7 +133,7 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
|
|||
ctx.throw(400, "Datasource has not been configured for plus API.")
|
||||
}
|
||||
const tables = datasource.entities
|
||||
const response = await handleRequest(Operation.READ, tableId, {
|
||||
const response = await handleRequest(Operation.READ, source, {
|
||||
id,
|
||||
datasource,
|
||||
includeSqlRelationships: IncludeRelationship.INCLUDE,
|
||||
|
@ -156,7 +157,7 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
|
|||
// don't support composite keys right now
|
||||
const linkedIds = links.map((link: Row) => breakRowIdField(link._id!)[0])
|
||||
const primaryLink = linkedTable.primary?.[0] as string
|
||||
const relatedRows = await handleRequest(Operation.READ, linkedTableId!, {
|
||||
const relatedRows = await handleRequest(Operation.READ, linkedTable, {
|
||||
tables,
|
||||
filters: {
|
||||
oneOf: {
|
||||
|
|
|
@ -221,7 +221,7 @@ export async function search(ctx: Ctx<SearchRowRequest, SearchRowResponse>) {
|
|||
const searchParams: RowSearchParams = {
|
||||
...ctx.request.body,
|
||||
query: enrichedQuery,
|
||||
tableId,
|
||||
sourceId: tableId,
|
||||
}
|
||||
|
||||
ctx.status = 200
|
||||
|
@ -229,14 +229,15 @@ export async function search(ctx: Ctx<SearchRowRequest, SearchRowResponse>) {
|
|||
}
|
||||
|
||||
export async function validate(ctx: Ctx<Row, ValidateResponse>) {
|
||||
const { tableId } = utils.getSourceId(ctx)
|
||||
const source = await utils.getSource(ctx)
|
||||
const table = await utils.getTableFromSource(source)
|
||||
// external tables are hard to validate currently
|
||||
if (isExternalTableID(tableId)) {
|
||||
if (isExternalTableID(table._id!)) {
|
||||
ctx.body = { valid: true, errors: {} }
|
||||
} else {
|
||||
ctx.body = await sdk.rows.utils.validate({
|
||||
row: ctx.request.body,
|
||||
tableId,
|
||||
source,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,19 +106,11 @@ export async function getSource(ctx: Ctx): Promise<Table | ViewV2> {
|
|||
return sdk.tables.getTable(tableId)
|
||||
}
|
||||
|
||||
export async function validate(
|
||||
opts: { row: Row } & ({ tableId: string } | { table: Table })
|
||||
) {
|
||||
let fetchedTable: Table
|
||||
if ("tableId" in opts) {
|
||||
fetchedTable = await sdk.tables.getTable(opts.tableId)
|
||||
} else {
|
||||
fetchedTable = opts.table
|
||||
export async function getTableFromSource(source: Table | ViewV2) {
|
||||
if (sdk.views.isView(source)) {
|
||||
return await sdk.views.getTable(source.id)
|
||||
}
|
||||
return sdk.rows.utils.validate({
|
||||
...opts,
|
||||
table: fetchedTable,
|
||||
})
|
||||
return source
|
||||
}
|
||||
|
||||
function fixBooleanFields({ row, table }: { row: Row; table: Table }) {
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
import { IncludeRelationship, Operation, Row } from "@budibase/types"
|
||||
import { HTTPError } from "@budibase/backend-core"
|
||||
import {
|
||||
IncludeRelationship,
|
||||
Operation,
|
||||
Row,
|
||||
Table,
|
||||
ViewV2,
|
||||
} from "@budibase/types"
|
||||
import { docIds, HTTPError } from "@budibase/backend-core"
|
||||
import { handleRequest } from "../../../api/controllers/row/external"
|
||||
import { breakRowIdField } from "../../../integrations/utils"
|
||||
import sdk from "../../../sdk"
|
||||
|
@ -12,11 +18,21 @@ import isEqual from "lodash/fp/isEqual"
|
|||
import { tryExtractingTableAndViewId } from "./utils"
|
||||
|
||||
export async function getRow(
|
||||
tableId: string,
|
||||
sourceId: string | Table | ViewV2,
|
||||
rowId: string,
|
||||
opts?: { relationships?: boolean }
|
||||
) {
|
||||
const response = await handleRequest(Operation.READ, tableId, {
|
||||
let source: Table | ViewV2
|
||||
if (typeof sourceId === "string") {
|
||||
if (docIds.isViewId(sourceId)) {
|
||||
source = await sdk.views.get(sourceId)
|
||||
} else {
|
||||
source = await sdk.tables.getTable(sourceId)
|
||||
}
|
||||
} else {
|
||||
source = sourceId
|
||||
}
|
||||
const response = await handleRequest(Operation.READ, source, {
|
||||
id: breakRowIdField(rowId),
|
||||
includeSqlRelationships: opts?.relationships
|
||||
? IncludeRelationship.INCLUDE
|
||||
|
@ -27,45 +43,50 @@ export async function getRow(
|
|||
}
|
||||
|
||||
export async function save(
|
||||
tableOrViewId: string,
|
||||
sourceId: string,
|
||||
inputs: Row,
|
||||
userId: string | undefined
|
||||
) {
|
||||
const { tableId, viewId } = tryExtractingTableAndViewId(tableOrViewId)
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
const { tableId, viewId } = tryExtractingTableAndViewId(sourceId)
|
||||
let source: Table | ViewV2
|
||||
if (viewId) {
|
||||
source = await sdk.views.get(viewId)
|
||||
} else {
|
||||
source = await sdk.tables.getTable(tableId)
|
||||
}
|
||||
|
||||
const { table: updatedTable, row } = await inputProcessing(
|
||||
userId,
|
||||
cloneDeep(table),
|
||||
cloneDeep(source),
|
||||
inputs
|
||||
)
|
||||
|
||||
const validateResult = await sdk.rows.utils.validate({
|
||||
row,
|
||||
tableId,
|
||||
source,
|
||||
})
|
||||
if (!validateResult.valid) {
|
||||
throw { validation: validateResult.errors }
|
||||
}
|
||||
|
||||
const response = await handleRequest(Operation.CREATE, tableId, {
|
||||
const response = await handleRequest(Operation.CREATE, source, {
|
||||
row,
|
||||
})
|
||||
|
||||
if (!isEqual(table, updatedTable)) {
|
||||
if (sdk.tables.isTable(source) && !isEqual(source, updatedTable)) {
|
||||
await sdk.tables.saveTable(updatedTable)
|
||||
}
|
||||
|
||||
const rowId = response.row._id
|
||||
if (rowId) {
|
||||
const row = await getRow(tableId, rowId, {
|
||||
const row = await getRow(source, rowId, {
|
||||
relationships: true,
|
||||
})
|
||||
return {
|
||||
...response,
|
||||
row: await outputProcessing(table, row, {
|
||||
row: await outputProcessing(source, row, {
|
||||
preserveLinks: true,
|
||||
squash: true,
|
||||
fromViewId: viewId,
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
|
@ -76,7 +97,14 @@ export async function save(
|
|||
export async function find(tableOrViewId: string, rowId: string): Promise<Row> {
|
||||
const { tableId, viewId } = tryExtractingTableAndViewId(tableOrViewId)
|
||||
|
||||
const row = await getRow(tableId, rowId, {
|
||||
let source: Table | ViewV2
|
||||
if (viewId) {
|
||||
source = await sdk.views.get(viewId)
|
||||
} else {
|
||||
source = await sdk.tables.getTable(tableId)
|
||||
}
|
||||
|
||||
const row = await getRow(source, rowId, {
|
||||
relationships: true,
|
||||
})
|
||||
|
||||
|
@ -84,11 +112,10 @@ export async function find(tableOrViewId: string, rowId: string): Promise<Row> {
|
|||
throw new HTTPError("Row not found", 404)
|
||||
}
|
||||
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
// Preserving links, as the outputProcessing does not support external rows yet and we don't need it in this use case
|
||||
return await outputProcessing(table, row, {
|
||||
// Preserving links, as the outputProcessing does not support external rows
|
||||
// yet and we don't need it in this use case
|
||||
return await outputProcessing(source, row, {
|
||||
squash: true,
|
||||
preserveLinks: true,
|
||||
fromViewId: viewId,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import { db as dbCore, context, docIds } from "@budibase/backend-core"
|
||||
import { Database, Row } from "@budibase/types"
|
||||
import {
|
||||
extractViewInfoFromID,
|
||||
getRowParams,
|
||||
} from "../../../db/utils"
|
||||
import { extractViewInfoFromID, getRowParams } from "../../../db/utils"
|
||||
import { isExternalTableID } from "../../../integrations/utils"
|
||||
import * as internal from "./internal"
|
||||
import * as external from "./external"
|
||||
|
@ -36,13 +33,13 @@ function pickApi(tableOrViewId: string) {
|
|||
}
|
||||
|
||||
export async function save(
|
||||
tableOrViewId: string,
|
||||
sourceId: string,
|
||||
row: Row,
|
||||
userId: string | undefined
|
||||
) {
|
||||
return pickApi(tableOrViewId).save(tableOrViewId, row, userId)
|
||||
return pickApi(sourceId).save(sourceId, row, userId)
|
||||
}
|
||||
|
||||
export async function find(tableOrViewId: string, rowId: string) {
|
||||
return pickApi(tableOrViewId).find(tableOrViewId, rowId)
|
||||
export async function find(sourceId: string, rowId: string) {
|
||||
return pickApi(sourceId).find(sourceId, rowId)
|
||||
}
|
||||
|
|
|
@ -106,9 +106,9 @@ export async function search(
|
|||
includeSqlRelationships: IncludeRelationship.INCLUDE,
|
||||
}
|
||||
const [{ rows, rawResponseSize }, totalRows] = await Promise.all([
|
||||
handleRequest(Operation.READ, tableId, parameters),
|
||||
handleRequest(Operation.READ, source, parameters),
|
||||
countRows
|
||||
? handleRequest(Operation.COUNT, tableId, parameters)
|
||||
? handleRequest(Operation.COUNT, source, parameters)
|
||||
: Promise.resolve(undefined),
|
||||
])
|
||||
|
||||
|
@ -200,7 +200,7 @@ export async function exportRows(
|
|||
}
|
||||
|
||||
let result = await search(
|
||||
{ tableId, query: requestQuery, sort, sortOrder },
|
||||
{ sourceId: table._id!, query: requestQuery, sort, sortOrder },
|
||||
table
|
||||
)
|
||||
let rows: Row[] = []
|
||||
|
@ -256,10 +256,10 @@ export async function exportRows(
|
|||
}
|
||||
|
||||
export async function fetch(tableId: string): Promise<Row[]> {
|
||||
const response = await handleRequest(Operation.READ, tableId, {
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
const response = await handleRequest(Operation.READ, table, {
|
||||
includeSqlRelationships: IncludeRelationship.INCLUDE,
|
||||
})
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
return await outputProcessing(table, response.rows, {
|
||||
preserveLinks: true,
|
||||
squash: true,
|
||||
|
@ -267,7 +267,8 @@ export async function fetch(tableId: string): Promise<Row[]> {
|
|||
}
|
||||
|
||||
export async function fetchRaw(tableId: string): Promise<Row[]> {
|
||||
const response = await handleRequest(Operation.READ, tableId, {
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
const response = await handleRequest(Operation.READ, table, {
|
||||
includeSqlRelationships: IncludeRelationship.INCLUDE,
|
||||
})
|
||||
return response.rows
|
||||
|
|
|
@ -9,7 +9,6 @@ import {
|
|||
SearchResponse,
|
||||
Row,
|
||||
RowSearchParams,
|
||||
ViewV2,
|
||||
} from "@budibase/types"
|
||||
import { db as dbCore, context } from "@budibase/backend-core"
|
||||
import { utils } from "@budibase/shared-core"
|
||||
|
|
|
@ -21,6 +21,7 @@ import sdk from "../.."
|
|||
import { extractViewInfoFromID, isRelationshipColumn } from "../../../db/utils"
|
||||
import { isSQL } from "../../../integrations/utils"
|
||||
import { docIds } from "@budibase/backend-core"
|
||||
import { getTableFromSource } from "../../../api/controllers/row/utils"
|
||||
|
||||
const SQL_CLIENT_SOURCE_MAP: Record<SourceName, SqlClient | undefined> = {
|
||||
[SourceName.POSTGRES]: SqlClient.POSTGRES,
|
||||
|
@ -149,12 +150,7 @@ export async function validate({
|
|||
valid: boolean
|
||||
errors: Record<string, any>
|
||||
}> {
|
||||
let table: Table
|
||||
if (sdk.views.isView(source)) {
|
||||
table = await sdk.views.getTable(source.id)
|
||||
} else {
|
||||
table = source
|
||||
}
|
||||
const table = await getTableFromSource(source)
|
||||
const errors: Record<string, any> = {}
|
||||
const disallowArrayTypes = [
|
||||
FieldType.ATTACHMENT_SINGLE,
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
RowAttachment,
|
||||
Table,
|
||||
User,
|
||||
ViewV2,
|
||||
} from "@budibase/types"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import {
|
||||
|
@ -34,7 +35,11 @@ import {
|
|||
PROTECTED_INTERNAL_COLUMNS,
|
||||
} from "@budibase/shared-core"
|
||||
import { processString } from "@budibase/string-templates"
|
||||
import { isUserMetadataTable } from "../../api/controllers/row/utils"
|
||||
import {
|
||||
getTableFromSource,
|
||||
isUserMetadataTable,
|
||||
} from "../../api/controllers/row/utils"
|
||||
import sdk from "../../sdk"
|
||||
|
||||
export * from "./utils"
|
||||
export * from "./attachments"
|
||||
|
@ -170,11 +175,12 @@ export function coerce(row: any, type: string) {
|
|||
*/
|
||||
export async function inputProcessing(
|
||||
userId: string | null | undefined,
|
||||
table: Table,
|
||||
source: Table | ViewV2,
|
||||
row: Row,
|
||||
opts?: AutoColumnProcessingOpts
|
||||
) {
|
||||
const clonedRow = cloneDeep(row)
|
||||
const table = await getTableFromSource(source)
|
||||
|
||||
const dontCleanseKeys = ["type", "_id", "_rev", "tableId"]
|
||||
for (const [key, value] of Object.entries(clonedRow)) {
|
||||
|
@ -243,14 +249,13 @@ export async function inputProcessing(
|
|||
* @returns the enriched rows will be returned.
|
||||
*/
|
||||
export async function outputProcessing<T extends Row[] | Row>(
|
||||
table: Table,
|
||||
source: Table | ViewV2,
|
||||
rows: T,
|
||||
opts: {
|
||||
squash?: boolean
|
||||
preserveLinks?: boolean
|
||||
fromRow?: Row
|
||||
skipBBReferences?: boolean
|
||||
fromViewId?: string
|
||||
aggregations?: Aggregation[]
|
||||
} = {
|
||||
squash: true,
|
||||
|
|
Loading…
Reference in New Issue