diff --git a/packages/server/src/api/controllers/table/tests/utils.spec.ts b/packages/server/src/api/controllers/table/tests/utils.spec.ts new file mode 100644 index 0000000000..957cf51ecd --- /dev/null +++ b/packages/server/src/api/controllers/table/tests/utils.spec.ts @@ -0,0 +1,97 @@ +import { FieldType } from "@budibase/types" +import { AutoFieldSubTypes } from "../../../../constants" +import TestConfiguration from "../../../../tests/utilities/TestConfiguration" +import { importToRows } from "../utils" + +describe("utils", () => { + const config = new TestConfiguration() + + beforeEach(async () => { + await config.init() + }) + + afterAll(config.end) + + describe("importToRows", () => { + it("consecutive row have consecutive auto ids", async () => { + await config.doInContext(config.appId, async () => { + const table = await config.createTable({ + name: "table", + type: "table", + schema: { + autoId: { + name: "autoId", + type: FieldType.NUMBER, + subtype: AutoFieldSubTypes.AUTO_ID, + autocolumn: true, + constraints: { + type: FieldType.NUMBER, + presence: true, + }, + }, + name: { + name: "name", + type: FieldType.STRING, + constraints: { + type: FieldType.STRING, + presence: true, + }, + }, + }, + }) + + const data = [{ name: "Alice" }, { name: "Bob" }, { name: "Claire" }] + + const result = importToRows(data, table, config.user) + expect(result).toEqual([ + expect.objectContaining({ + autoId: 1, + name: "Alice", + }), + expect.objectContaining({ + autoId: 2, + name: "Bob", + }), + expect.objectContaining({ + autoId: 3, + name: "Claire", + }), + ]) + }) + }) + + it("can import data without a specific user performing the action", async () => { + await config.doInContext(config.appId, async () => { + const table = await config.createTable({ + name: "table", + type: "table", + schema: { + autoId: { + name: "autoId", + type: FieldType.NUMBER, + subtype: AutoFieldSubTypes.AUTO_ID, + autocolumn: true, + constraints: { + type: FieldType.NUMBER, + presence: true, + }, + }, + name: { + name: "name", + type: FieldType.STRING, + constraints: { + type: FieldType.STRING, + presence: true, + }, + }, + }, + }) + + const data = [{ name: "Alice" }, { name: "Bob" }, { name: "Claire" }] + + const result = importToRows(data, table) + expect(result).toHaveLength(3) + }) + }) + }) +}) diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts index 7c5c81939a..cf1883c083 100644 --- a/packages/server/src/api/controllers/table/utils.ts +++ b/packages/server/src/api/controllers/table/utils.ts @@ -20,7 +20,13 @@ import viewTemplate from "../view/viewBuilder" import { cloneDeep } from "lodash/fp" import { quotas } from "@budibase/pro" import { events, context } from "@budibase/backend-core" -import { Database, Datasource, SourceName, Table } from "@budibase/types" +import { + ContextUser, + Database, + Datasource, + SourceName, + Table, +} from "@budibase/types" export async function clearColumns(table: any, columnNames: any) { const db: Database = context.getAppDB() @@ -99,32 +105,35 @@ export function makeSureTableUpToDate(table: any, tableToSave: any) { return tableToSave } -export function importToRows(data: any, table: any, user: any = {}) { +export function importToRows( + data: any[], + table: Table, + user: ContextUser | null = null +) { let finalData: any = [] for (let i = 0; i < data.length; i++) { let row = data[i] - row._id = generateRowID(table._id) + row._id = generateRowID(table._id!) row.tableId = table._id - const processed: any = inputProcessing(user, table, row, { + const processed = inputProcessing(user, table, row, { noAutoRelationships: true, }) row = processed.row + table = processed.table - let fieldName: any - let schema: any - for ([fieldName, schema] of Object.entries(table.schema)) { + for (const [fieldName, schema] of Object.entries(table.schema)) { // check whether the options need to be updated for inclusion as part of the data import if ( schema.type === FieldTypes.OPTIONS && row[fieldName] && - (!schema.constraints.inclusion || - schema.constraints.inclusion.indexOf(row[fieldName]) === -1) + (!schema.constraints!.inclusion || + schema.constraints!.inclusion.indexOf(row[fieldName]) === -1) ) { - schema.constraints.inclusion = [ - ...schema.constraints.inclusion, + schema.constraints!.inclusion = [ + ...schema.constraints!.inclusion!, row[fieldName], ] - schema.constraints.inclusion.sort() + schema.constraints!.inclusion.sort() } } diff --git a/packages/server/src/db/defaultData/datasource_bb_default.ts b/packages/server/src/db/defaultData/datasource_bb_default.ts index 516783ed31..6ffbf601c8 100644 --- a/packages/server/src/db/defaultData/datasource_bb_default.ts +++ b/packages/server/src/db/defaultData/datasource_bb_default.ts @@ -34,7 +34,7 @@ function syncLastIds(table: Table, rowCount: number) { }) } -function tableImport(table: Table, data: Row) { +function tableImport(table: Table, data: Row[]) { const cloneTable = cloneDeep(table) const rowDocs = importToRows(data, cloneTable) syncLastIds(cloneTable, rowDocs.length) diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 9e1029fa1a..a5bb352eeb 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -131,7 +131,7 @@ export function coerce(row: any, type: string) { * @returns {object} the row which has been prepared to be written to the DB. */ export function inputProcessing( - user: ContextUser, + user: ContextUser | null, table: Table, row: Row, opts?: AutoColumnProcessingOpts