diff --git a/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts b/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts index a9a4e5fddf..10b81f9788 100644 --- a/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts +++ b/packages/server/src/utilities/rowProcessor/bbReferenceProcessor.ts @@ -1,6 +1,6 @@ import { cache } from "@budibase/backend-core" import { utils } from "@budibase/shared-core" -import { Document, FieldSubtype } from "@budibase/types" +import { FieldSubtype } from "@budibase/types" import { InvalidBBRefError } from "./errors" export async function processInputBBReferences( @@ -39,3 +39,31 @@ export async function processInputBBReferences( return result.join(",") } + +export async function processOutputBBReferences( + value: string, + subtype: FieldSubtype +) { + const result = [] + + switch (subtype) { + case FieldSubtype.USER: + for (const id of value.split(",")) { + try { + const user = await cache.user.getUser(id) + if (user) { + result.push(user) + } + } catch {} + } + break + default: + throw utils.unreachable(subtype) + } + + if (result.length > 1) { + return result + } + + return result[0] +} diff --git a/packages/server/src/utilities/rowProcessor/tests/inputProcessing.spec.ts b/packages/server/src/utilities/rowProcessor/tests/inputProcessing.spec.ts index 65630da2b9..18d5128986 100644 --- a/packages/server/src/utilities/rowProcessor/tests/inputProcessing.spec.ts +++ b/packages/server/src/utilities/rowProcessor/tests/inputProcessing.spec.ts @@ -5,6 +5,7 @@ import * as bbReferenceProcessor from "../bbReferenceProcessor" jest.mock("../bbReferenceProcessor", (): typeof bbReferenceProcessor => ({ processInputBBReferences: jest.fn(), + processOutputBBReferences: jest.fn(), })) describe("rowProcessor - inputProcessing", () => { diff --git a/packages/server/src/utilities/rowProcessor/tests/outputProcessing.spec.ts b/packages/server/src/utilities/rowProcessor/tests/outputProcessing.spec.ts new file mode 100644 index 0000000000..1b780bed54 --- /dev/null +++ b/packages/server/src/utilities/rowProcessor/tests/outputProcessing.spec.ts @@ -0,0 +1,142 @@ +import { + FieldSubtype, + FieldType, + FieldTypeSubtypes, + Table, +} from "@budibase/types" +import { outputProcessing } from ".." +import { generator, structures } from "@budibase/backend-core/tests" +import * as bbReferenceProcessor from "../bbReferenceProcessor" + +jest.mock("../bbReferenceProcessor", (): typeof bbReferenceProcessor => ({ + processInputBBReferences: jest.fn(), + processOutputBBReferences: jest.fn(), +})) + +describe("rowProcessor - outputProcessing", () => { + beforeEach(() => { + jest.resetAllMocks() + }) + + const processOutputBBReferencesMock = + bbReferenceProcessor.processOutputBBReferences as jest.Mock + + it("fetches bb user references given a populated field", async () => { + const table: Table = { + _id: generator.guid(), + name: "TestTable", + type: "table", + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + presence: true, + type: "string", + }, + }, + user: { + type: FieldType.BB_REFERENCE, + subtype: FieldTypeSubtypes.BB_REFERENCE.USER, + name: "user", + constraints: { + presence: false, + type: "string", + }, + }, + }, + } + + const row = { + name: "Jack", + user: "123", + } + + const user = structures.users.user() + processOutputBBReferencesMock.mockResolvedValue(user) + + const result = await outputProcessing(table, row, { squash: false }) + + expect(result).toEqual({ name: "Jack", user }) + + expect(bbReferenceProcessor.processOutputBBReferences).toBeCalledTimes(1) + expect(bbReferenceProcessor.processOutputBBReferences).toBeCalledWith( + "123", + FieldSubtype.USER + ) + }) + + it("does not fetch bb references when fields are empty", async () => { + const table: Table = { + _id: generator.guid(), + name: "TestTable", + type: "table", + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + presence: true, + type: "string", + }, + }, + user: { + type: FieldType.BB_REFERENCE, + subtype: FieldTypeSubtypes.BB_REFERENCE.USER, + name: "user", + constraints: { + presence: false, + type: "string", + }, + }, + }, + } + + const row = { + name: "Jack", + } + + const result = await outputProcessing(table, row, { squash: false }) + + expect(result).toEqual({ name: "Jack" }) + + expect(bbReferenceProcessor.processOutputBBReferences).not.toBeCalled() + }) + + it("does not fetch bb references when not in the schema", async () => { + const table: Table = { + _id: generator.guid(), + name: "TestTable", + type: "table", + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + presence: true, + type: "string", + }, + }, + user: { + type: FieldType.NUMBER, + name: "user", + constraints: { + presence: false, + type: "string", + }, + }, + }, + } + + const row = { + name: "Jack", + user: "123", + } + + const result = await outputProcessing(table, row, { squash: false }) + + expect(result).toEqual({ name: "Jack", user: "123" }) + + expect(bbReferenceProcessor.processOutputBBReferences).not.toBeCalled() + }) +})