Input processing

This commit is contained in:
Adria Navarro 2024-04-22 17:27:26 +02:00
parent d63c5830e5
commit 808aba0c34
2 changed files with 130 additions and 33 deletions

View File

@ -1,13 +1,43 @@
import { cache, db as dbCore } from "@budibase/backend-core" import { cache, db as dbCore } from "@budibase/backend-core"
import { utils } from "@budibase/shared-core" import { utils } from "@budibase/shared-core"
import { FieldSubtype, DocumentType, SEPARATOR } from "@budibase/types" import {
FieldType,
FieldSubtype,
DocumentType,
SEPARATOR,
User,
} from "@budibase/types"
import { InvalidBBRefError } from "./errors" import { InvalidBBRefError } from "./errors"
const ROW_PREFIX = DocumentType.ROW + SEPARATOR const ROW_PREFIX = DocumentType.ROW + SEPARATOR
export async function processInputBBReferences( export async function processInputBBReferences<
T = FieldType.BB_REFERENCE_SINGLE
>(value: string, type: T): Promise<string | null>
export async function processInputBBReferences<
T = FieldType.BB_REFERENCE,
TS = FieldSubtype.USER
>(
value: string | string[] | { _id: string } | { _id: string }[], value: string | string[] | { _id: string } | { _id: string }[],
subtype: FieldSubtype.USER | FieldSubtype.USERS type: T,
subtype: TS
): Promise<string | null>
export async function processInputBBReferences<
T = FieldType.BB_REFERENCE,
TS = FieldSubtype.USERS
>(
value: string | string[] | { _id: string } | { _id: string }[],
type: T,
subtype: TS
): Promise<string[] | null>
export async function processInputBBReferences<
T extends FieldType.BB_REFERENCE | FieldType.BB_REFERENCE_SINGLE,
TS extends FieldSubtype.USER | FieldSubtype.USERS
>(
value: string | string[] | { _id: string } | { _id: string }[],
type: T,
subtype?: TS
): Promise<string | string[] | null> { ): Promise<string | string[] | null> {
let referenceIds: string[] = [] let referenceIds: string[] = []
@ -39,55 +69,113 @@ export async function processInputBBReferences(
} }
}) })
switch (subtype) { switch (type) {
case FieldSubtype.USER: case FieldType.BB_REFERENCE:
case FieldSubtype.USERS: { switch (subtype) {
const { notFoundIds } = await cache.user.getUsers(referenceIds) case undefined:
throw "Subtype must be defined"
case FieldSubtype.USER:
case FieldSubtype.USERS:
const { notFoundIds } = await cache.user.getUsers(referenceIds)
if (notFoundIds?.length) { if (notFoundIds?.length) {
throw new InvalidBBRefError(notFoundIds[0], FieldSubtype.USER) throw new InvalidBBRefError(notFoundIds[0], FieldSubtype.USER)
}
if (subtype === FieldSubtype.USERS) {
return referenceIds
}
return referenceIds.join(",") || null
default:
throw utils.unreachable(subtype)
} }
if (subtype === FieldSubtype.USERS) { case FieldType.BB_REFERENCE_SINGLE:
return referenceIds const user = await cache.user.getUser(referenceIds[0])
if (!user) {
throw new InvalidBBRefError(referenceIds[0], FieldSubtype.USER)
} }
return referenceIds.join(",") || null return referenceIds[0] || null
}
default: default:
throw utils.unreachable(subtype) throw utils.unreachable(type)
} }
} }
interface UserReferenceInfo {
_id: string
primaryDisplay: string
email: string
firstName: string
lastName: string
}
export async function processOutputBBReferences<
T = FieldType.BB_REFERENCE_SINGLE
>(value: string, type: T): Promise<UserReferenceInfo>
export async function processOutputBBReferences<
T = FieldType.BB_REFERENCE,
TS = FieldSubtype.USER
>(value: string, type: T, subtype: TS): Promise<UserReferenceInfo[]>
export async function processOutputBBReferences<
T = FieldType.BB_REFERENCE,
TS = FieldSubtype.USERS
>(value: string[], type: T, subtype: TS): Promise<UserReferenceInfo[]>
export async function processOutputBBReferences( export async function processOutputBBReferences(
value: string | string[], value: string | string[],
subtype: FieldSubtype.USER | FieldSubtype.USERS type: FieldType.BB_REFERENCE | FieldType.BB_REFERENCE_SINGLE,
subtype?: FieldSubtype.USER | FieldSubtype.USERS
) { ) {
if (value === null || value === undefined) { if (value === null || value === undefined) {
// Already processed or nothing to process // Already processed or nothing to process
return value || undefined return value || undefined
} }
const ids = switch (type) {
typeof value === "string" ? value.split(",").filter(id => !!id) : value case FieldType.BB_REFERENCE:
const ids =
typeof value === "string" ? value.split(",").filter(id => !!id) : value
switch (subtype) { switch (subtype) {
case FieldSubtype.USER: case undefined:
case FieldSubtype.USERS: { throw "Subtype must be defined"
const { users } = await cache.user.getUsers(ids) case FieldSubtype.USER:
if (!users.length) { case FieldSubtype.USERS:
const { users } = await cache.user.getUsers(ids)
if (!users.length) {
return undefined
}
return users.map(u => ({
_id: u._id,
primaryDisplay: u.email,
email: u.email,
firstName: u.firstName,
lastName: u.lastName,
}))
default:
throw utils.unreachable(subtype)
}
case FieldType.BB_REFERENCE_SINGLE:
const user = await cache.user.getUser(value as string)
if (!user) {
return undefined return undefined
} }
return users.map(u => ({ return {
_id: u._id, _id: user._id,
primaryDisplay: u.email, primaryDisplay: user.email,
email: u.email, email: user.email,
firstName: u.firstName, firstName: user.firstName,
lastName: u.lastName, lastName: user.lastName,
})) }
}
default: default:
throw utils.unreachable(subtype) throw utils.unreachable(type)
} }
} }

View File

@ -162,8 +162,16 @@ export async function inputProcessing(
} }
} }
if (field.type === FieldType.BB_REFERENCE && value) { if (
clonedRow[key] = await processInputBBReferences(value, field.subtype) (field.type === FieldType.BB_REFERENCE ||
field.type === FieldType.BB_REFERENCE_SINGLE) &&
value
) {
clonedRow[key] = await processInputBBReferences(
value,
field.type,
field.subtype
)
} }
} }
@ -250,6 +258,7 @@ export async function outputProcessing<T extends Row[] | Row>(
for (let row of enriched) { for (let row of enriched) {
row[property] = await processOutputBBReferences( row[property] = await processOutputBBReferences(
row[property], row[property],
column.type,
column.subtype column.subtype
) )
} }