Merge pull request #14949 from Budibase/chore/refactor-finalizerow

Patch row improvements
This commit is contained in:
Michael Drury 2024-11-29 14:07:42 +00:00 committed by GitHub
commit c372d5e64e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 49 additions and 20 deletions

View File

@ -15,10 +15,21 @@ import {
} from "@budibase/types" } from "@budibase/types"
import * as linkRows from "../../../db/linkedRows" import * as linkRows from "../../../db/linkedRows"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
import { cloneDeep } from "lodash/fp" import { cloneDeep, merge } from "lodash/fp"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import * as pro from "@budibase/pro" import * as pro from "@budibase/pro"
function mergeRows(row1: Row, row2: Row) {
const merged = merge(row1, row2)
// make sure any specifically undefined fields are removed
for (const key of Object.keys(row2)) {
if (row2[key] === undefined) {
delete merged[key]
}
}
return merged
}
/** /**
* This function runs through a list of enriched rows, looks at the rows which * This function runs through a list of enriched rows, looks at the rows which
* are related and then checks if they need the state of their formulas * are related and then checks if they need the state of their formulas
@ -162,9 +173,14 @@ export async function finaliseRow(
}) })
} }
const response = await db.put(row) await db.put(row)
// for response, calculate the formulas for the enriched row const retrieved = await db.tryGet<Row>(row._id)
enrichedRow._rev = response.rev if (!retrieved) {
throw new Error(`Unable to retrieve row ${row._id} after saving.`)
}
delete enrichedRow._rev
enrichedRow = mergeRows(retrieved, enrichedRow)
enrichedRow = await processFormulas(table, enrichedRow, { enrichedRow = await processFormulas(table, enrichedRow, {
dynamic: false, dynamic: false,
}) })

View File

@ -2607,6 +2607,8 @@ if (descriptions.length) {
name: "foo", name: "foo",
description: "bar", description: "bar",
tableId, tableId,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2628,6 +2630,8 @@ if (descriptions.length) {
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
[`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2650,6 +2654,8 @@ if (descriptions.length) {
_rev: expect.any(String), _rev: expect.any(String),
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2729,6 +2735,8 @@ if (descriptions.length) {
id: isInternal ? undefined : expect.any(Number), id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined, type: isInternal ? "row" : undefined,
[`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id,
createdAt: isInternal ? new Date().toISOString() : undefined,
updatedAt: isInternal ? new Date().toISOString() : undefined,
}) })
}) })
@ -2745,15 +2753,8 @@ if (descriptions.length) {
user: null, user: null,
users: null, users: null,
}) })
expect(updatedRow).toEqual({ expect(updatedRow.user).toBeUndefined()
name: "foo", expect(updatedRow.users).toBeUndefined()
description: "bar",
tableId,
_id: row._id,
_rev: expect.any(String),
id: isInternal ? undefined : expect.any(Number),
type: isInternal ? "row" : undefined,
})
}) })
it("fetch all will populate the relationships", async () => { it("fetch all will populate the relationships", async () => {

View File

@ -102,6 +102,9 @@ function createDummyTest() {
} }
export function datasourceDescribe(opts: DatasourceDescribeOpts) { export function datasourceDescribe(opts: DatasourceDescribeOpts) {
// tests that call this need a lot longer timeouts
jest.setTimeout(120000)
if (process.env.DATASOURCE === "none") { if (process.env.DATASOURCE === "none") {
createDummyTest() createDummyTest()
} }

View File

@ -25,7 +25,7 @@ export async function getDatasource(): Promise<Datasource> {
}) })
.withWaitStrategy( .withWaitStrategy(
Wait.forLogMessage("DATABASE IS READY TO USE!").withStartupTimeout( Wait.forLogMessage("DATABASE IS READY TO USE!").withStartupTimeout(
20000 60000
) )
) )
) )

View File

@ -153,10 +153,10 @@ export async function processOutputBBReference(
} }
export async function processOutputBBReferences( export async function processOutputBBReferences(
value: string | null | undefined, value: string | string[] | null | undefined,
subtype: BBReferenceFieldSubType subtype: BBReferenceFieldSubType
): Promise<UserReferenceInfo[] | undefined> { ): Promise<UserReferenceInfo[] | undefined> {
if (!value) { if (!value || (Array.isArray(value) && value.length === 0)) {
return undefined return undefined
} }
const ids = const ids =

View File

@ -29,6 +29,8 @@ import {
import { isExternalTableID } from "../../integrations/utils" import { isExternalTableID } from "../../integrations/utils"
import { import {
helpers, helpers,
isExternalColumnName,
isInternalColumnName,
PROTECTED_EXTERNAL_COLUMNS, PROTECTED_EXTERNAL_COLUMNS,
PROTECTED_INTERNAL_COLUMNS, PROTECTED_INTERNAL_COLUMNS,
} from "@budibase/shared-core" } from "@budibase/shared-core"
@ -200,14 +202,17 @@ export async function inputProcessing(
const clonedRow = cloneDeep(row) const clonedRow = cloneDeep(row)
const table = await getTableFromSource(source) const table = await getTableFromSource(source)
const dontCleanseKeys = ["type", "_id", "_rev", "tableId"]
for (const [key, value] of Object.entries(clonedRow)) { for (const [key, value] of Object.entries(clonedRow)) {
const field = table.schema[key] const field = table.schema[key]
const isBuiltinColumn = isExternalTableID(table._id!)
? isExternalColumnName(key)
: isInternalColumnName(key)
// cleanse fields that aren't in the schema // cleanse fields that aren't in the schema
if (!field && !isBuiltinColumn) {
delete clonedRow[key]
}
// field isn't found - might be a built-in column, skip over it
if (!field) { if (!field) {
if (dontCleanseKeys.indexOf(key) === -1) {
delete clonedRow[key]
}
continue continue
} }
// remove any formula values, they are to be generated // remove any formula values, they are to be generated

View File

@ -12,3 +12,7 @@ export const PROTECTED_EXTERNAL_COLUMNS = ["_id", "_rev", "tableId"] as const
export function isInternalColumnName(name: string): boolean { export function isInternalColumnName(name: string): boolean {
return (PROTECTED_INTERNAL_COLUMNS as readonly string[]).includes(name) return (PROTECTED_INTERNAL_COLUMNS as readonly string[]).includes(name)
} }
export function isExternalColumnName(name: string): boolean {
return (PROTECTED_EXTERNAL_COLUMNS as readonly string[]).includes(name)
}