A quick refactor to get rid of the old 'FieldTypes' enumeration, considering how core it is to all data handling in Budibase, the fact we had both 'FieldType' and 'FieldTypes' was confusing - righting this fully.

This commit is contained in:
mike12345567 2024-01-24 16:58:13 +00:00
parent 34d7fe4372
commit ccc751d09c
31 changed files with 306 additions and 285 deletions

View File

@ -1,4 +1,4 @@
import { FieldTypes, RelationshipType, FormulaTypes } from "../../src/constants" import { FieldType, FormulaType, RelationshipType } from "@budibase/types"
import { object } from "./utils" import { object } from "./utils"
import Resource from "./utils/Resource" import Resource from "./utils/Resource"
@ -27,7 +27,7 @@ const table = {
const baseColumnDef = { const baseColumnDef = {
type: { type: {
type: "string", type: "string",
enum: Object.values(FieldTypes), enum: Object.values(FieldType),
description: description:
"Defines the type of the column, most explain themselves, a link column is a relationship.", "Defines the type of the column, most explain themselves, a link column is a relationship.",
}, },
@ -81,7 +81,7 @@ const tableSchema = {
...baseColumnDef, ...baseColumnDef,
type: { type: {
type: "string", type: "string",
enum: [FieldTypes.LINK], enum: [FieldType.LINK],
description: "A relationship column.", description: "A relationship column.",
}, },
fieldName: { fieldName: {
@ -128,7 +128,7 @@ const tableSchema = {
...baseColumnDef, ...baseColumnDef,
type: { type: {
type: "string", type: "string",
enum: [FieldTypes.FORMULA], enum: [FieldType.FORMULA],
description: "A formula column.", description: "A formula column.",
}, },
formula: { formula: {
@ -138,7 +138,7 @@ const tableSchema = {
}, },
formulaType: { formulaType: {
type: "string", type: "string",
enum: Object.values(FormulaTypes), enum: Object.values(FormulaType),
description: description:
"Defines whether this is a static or dynamic formula.", "Defines whether this is a static or dynamic formula.",
}, },

View File

@ -1,4 +1,5 @@
import { import {
AutoFieldSubType,
AutoReason, AutoReason,
Datasource, Datasource,
FieldSchema, FieldSchema,
@ -27,7 +28,6 @@ import {
isSQL, isSQL,
} from "../../../integrations/utils" } from "../../../integrations/utils"
import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils" import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils"
import { AutoFieldSubTypes, FieldTypes } from "../../../constants"
import { processObjectSync } from "@budibase/string-templates" import { processObjectSync } from "@budibase/string-templates"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { processDates, processFormulas } from "../../../utilities/rowProcessor" import { processDates, processFormulas } from "../../../utilities/rowProcessor"
@ -111,10 +111,10 @@ function buildFilters(
*/ */
function cleanupConfig(config: RunConfig, table: Table): RunConfig { function cleanupConfig(config: RunConfig, table: Table): RunConfig {
const primaryOptions = [ const primaryOptions = [
FieldTypes.STRING, FieldType.STRING,
FieldTypes.LONGFORM, FieldType.LONGFORM,
FieldTypes.OPTIONS, FieldType.OPTIONS,
FieldTypes.NUMBER, FieldType.NUMBER,
] ]
// filter out fields which cannot be keys // filter out fields which cannot be keys
const fieldNames = Object.entries(table.schema) const fieldNames = Object.entries(table.schema)
@ -241,10 +241,7 @@ function basicProcessing({
function fixArrayTypes(row: Row, table: Table) { function fixArrayTypes(row: Row, table: Table) {
for (let [fieldName, schema] of Object.entries(table.schema)) { for (let [fieldName, schema] of Object.entries(table.schema)) {
if ( if (schema.type === FieldType.ARRAY && typeof row[fieldName] === "string") {
schema.type === FieldTypes.ARRAY &&
typeof row[fieldName] === "string"
) {
try { try {
row[fieldName] = JSON.parse(row[fieldName]) row[fieldName] = JSON.parse(row[fieldName])
} catch (err) { } catch (err) {
@ -274,8 +271,8 @@ function isEditableColumn(column: FieldSchema) {
const isExternalAutoColumn = const isExternalAutoColumn =
column.autocolumn && column.autocolumn &&
column.autoReason !== AutoReason.FOREIGN_KEY && column.autoReason !== AutoReason.FOREIGN_KEY &&
column.subtype !== AutoFieldSubTypes.AUTO_ID column.subtype !== AutoFieldSubType.AUTO_ID
const isFormula = column.type === FieldTypes.FORMULA const isFormula = column.type === FieldType.FORMULA
return !(isExternalAutoColumn || isFormula) return !(isExternalAutoColumn || isFormula)
} }
@ -322,11 +319,11 @@ export class ExternalRequest<T extends Operation> {
continue continue
} }
// parse floats/numbers // parse floats/numbers
if (field.type === FieldTypes.NUMBER && !isNaN(parseFloat(row[key]))) { if (field.type === FieldType.NUMBER && !isNaN(parseFloat(row[key]))) {
newRow[key] = parseFloat(row[key]) newRow[key] = parseFloat(row[key])
} }
// if its not a link then just copy it over // if its not a link then just copy it over
if (field.type !== FieldTypes.LINK) { if (field.type !== FieldType.LINK) {
newRow[key] = row[key] newRow[key] = row[key]
continue continue
} }
@ -532,7 +529,7 @@ export class ExternalRequest<T extends Operation> {
buildRelationships(table: Table): RelationshipsJson[] { buildRelationships(table: Table): RelationshipsJson[] {
const relationships = [] const relationships = []
for (let [fieldName, field] of Object.entries(table.schema)) { for (let [fieldName, field] of Object.entries(table.schema)) {
if (field.type !== FieldTypes.LINK) { if (field.type !== FieldType.LINK) {
continue continue
} }
const { tableName: linkTableName } = breakExternalTableId(field.tableId) const { tableName: linkTableName } = breakExternalTableId(field.tableId)
@ -586,7 +583,7 @@ export class ExternalRequest<T extends Operation> {
// we need this to work out if any relationships need removed // we need this to work out if any relationships need removed
for (const field of Object.values(table.schema)) { for (const field of Object.values(table.schema)) {
if ( if (
field.type !== FieldTypes.LINK || field.type !== FieldType.LINK ||
!field.fieldName || !field.fieldName ||
isOneSide(field) isOneSide(field)
) { ) {
@ -730,15 +727,15 @@ export class ExternalRequest<T extends Operation> {
return Object.entries(table.schema) return Object.entries(table.schema)
.filter( .filter(
column => column =>
column[1].type !== FieldTypes.LINK && column[1].type !== FieldType.LINK &&
column[1].type !== FieldTypes.FORMULA && column[1].type !== FieldType.FORMULA &&
!existing.find((field: string) => field === column[0]) !existing.find((field: string) => field === column[0])
) )
.map(column => `${table.name}.${column[0]}`) .map(column => `${table.name}.${column[0]}`)
} }
let fields = extractRealFields(table) let fields = extractRealFields(table)
for (let field of Object.values(table.schema)) { for (let field of Object.values(table.schema)) {
if (field.type !== FieldTypes.LINK || !includeRelations) { if (field.type !== FieldType.LINK || !includeRelations) {
continue continue
} }
const { tableName: linkTableName } = breakExternalTableId(field.tableId) const { tableName: linkTableName } = breakExternalTableId(field.tableId)

View File

@ -1,4 +1,3 @@
import { FieldTypes } from "../../../constants"
import { import {
breakExternalTableId, breakExternalTableId,
breakRowIdField, breakRowIdField,
@ -9,6 +8,7 @@ import {
RunConfig, RunConfig,
} from "./ExternalRequest" } from "./ExternalRequest"
import { import {
FieldType,
Datasource, Datasource,
IncludeRelationship, IncludeRelationship,
Operation, Operation,
@ -154,7 +154,7 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
// for a single row, there is probably a better way to do this with some smart multi-layer joins // for a single row, there is probably a better way to do this with some smart multi-layer joins
for (let [fieldName, field] of Object.entries(table.schema)) { for (let [fieldName, field] of Object.entries(table.schema)) {
if ( if (
field.type !== FieldTypes.LINK || field.type !== FieldType.LINK ||
!row[fieldName] || !row[fieldName] ||
row[fieldName].length === 0 row[fieldName].length === 0
) { ) {

View File

@ -6,12 +6,12 @@ import {
inputProcessing, inputProcessing,
outputProcessing, outputProcessing,
} from "../../../utilities/rowProcessor" } from "../../../utilities/rowProcessor"
import { FieldTypes } from "../../../constants"
import * as utils from "./utils" import * as utils from "./utils"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { context } from "@budibase/backend-core" import { context } from "@budibase/backend-core"
import { finaliseRow, updateRelatedFormula } from "./staticFormula" import { finaliseRow, updateRelatedFormula } from "./staticFormula"
import { import {
FieldType,
LinkDocumentValue, LinkDocumentValue,
PatchRowRequest, PatchRowRequest,
PatchRowResponse, PatchRowResponse,
@ -225,7 +225,7 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
// insert the link rows in the correct place throughout the main row // insert the link rows in the correct place throughout the main row
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
let field = table.schema[fieldName] let field = table.schema[fieldName]
if (field.type === FieldTypes.LINK) { if (field.type === FieldType.LINK) {
// find the links that pertain to this field // find the links that pertain to this field
const links = linkVals.filter(link => link.fieldName === fieldName) const links = linkVals.filter(link => link.fieldName === fieldName)
// find the rows that the links state are linked to this field // find the rows that the links state are linked to this field

View File

@ -4,9 +4,15 @@ import {
processAutoColumn, processAutoColumn,
processFormulas, processFormulas,
} from "../../../utilities/rowProcessor" } from "../../../utilities/rowProcessor"
import { FieldTypes, FormulaTypes } from "../../../constants"
import { context, locks } from "@budibase/backend-core" import { context, locks } from "@budibase/backend-core"
import { Table, Row, LockType, LockName } from "@budibase/types" import {
Table,
Row,
LockType,
LockName,
FormulaType,
FieldType,
} from "@budibase/types"
import * as linkRows from "../../../db/linkedRows" import * as linkRows from "../../../db/linkedRows"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
@ -35,7 +41,7 @@ export async function updateRelatedFormula(
let relatedRows: Record<string, Row[]> = {} let relatedRows: Record<string, Row[]> = {}
for (let [key, field] of Object.entries(enrichedRow)) { for (let [key, field] of Object.entries(enrichedRow)) {
const columnDefinition = table.schema[key] const columnDefinition = table.schema[key]
if (columnDefinition && columnDefinition.type === FieldTypes.LINK) { if (columnDefinition && columnDefinition.type === FieldType.LINK) {
const relatedTableId = columnDefinition.tableId! const relatedTableId = columnDefinition.tableId!
if (!relatedRows[relatedTableId]) { if (!relatedRows[relatedTableId]) {
relatedRows[relatedTableId] = [] relatedRows[relatedTableId] = []
@ -63,8 +69,8 @@ export async function updateRelatedFormula(
for (let column of Object.values(relatedTable!.schema)) { for (let column of Object.values(relatedTable!.schema)) {
// needs updated in related rows // needs updated in related rows
if ( if (
column.type === FieldTypes.FORMULA && column.type === FieldType.FORMULA &&
column.formulaType === FormulaTypes.STATIC column.formulaType === FormulaType.STATIC
) { ) {
// re-enrich rows for all the related, don't update the related formula for them // re-enrich rows for all the related, don't update the related formula for them
promises = promises.concat( promises = promises.concat(

View File

@ -1,4 +1,4 @@
import { FormulaTypes } from "../../../constants" import { FormulaType } from "../../../constants"
import { clearColumns } from "./utils" import { clearColumns } from "./utils"
import { doesContainStrings } from "@budibase/string-templates" import { doesContainStrings } from "@budibase/string-templates"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
@ -17,10 +17,10 @@ import { isRelationshipColumn } from "../../../db/utils"
function isStaticFormula( function isStaticFormula(
column: FieldSchema column: FieldSchema
): column is FormulaFieldMetadata & { formulaType: FormulaTypes.STATIC } { ): column is FormulaFieldMetadata & { formulaType: FormulaType.STATIC } {
return ( return (
column.type === FieldType.FORMULA && column.type === FieldType.FORMULA &&
column.formulaType === FormulaTypes.STATIC column.formulaType === FormulaType.STATIC
) )
} }

View File

@ -1,5 +1,5 @@
import { FieldType } from "@budibase/types" import { FieldType } from "@budibase/types"
import { AutoFieldSubTypes } from "../../../../constants" import { AutoFieldSubType } from "../../../../constants"
import TestConfiguration from "../../../../tests/utilities/TestConfiguration" import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
import { importToRows } from "../utils" import { importToRows } from "../utils"
@ -22,7 +22,7 @@ describe("utils", () => {
autoId: { autoId: {
name: "autoId", name: "autoId",
type: FieldType.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldType.NUMBER, type: FieldType.NUMBER,
@ -69,7 +69,7 @@ describe("utils", () => {
autoId: { autoId: {
name: "autoId", name: "autoId",
type: FieldType.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldType.NUMBER, type: FieldType.NUMBER,

View File

@ -2,8 +2,6 @@ import { parse, isSchema, isRows } from "../../../utilities/schema"
import { getRowParams, generateRowID, InternalTables } from "../../../db/utils" import { getRowParams, generateRowID, InternalTables } from "../../../db/utils"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
import { import {
AutoFieldSubTypes,
FieldTypes,
GOOGLE_SHEETS_PRIMARY_KEY, GOOGLE_SHEETS_PRIMARY_KEY,
USERS_TABLE_SCHEMA, USERS_TABLE_SCHEMA,
SwitchableTypes, SwitchableTypes,
@ -19,6 +17,7 @@ import { cloneDeep } from "lodash/fp"
import { quotas } from "@budibase/pro" import { quotas } from "@budibase/pro"
import { events, context } from "@budibase/backend-core" import { events, context } from "@budibase/backend-core"
import { import {
AutoFieldSubType,
ContextUser, ContextUser,
Datasource, Datasource,
Row, Row,
@ -106,7 +105,7 @@ export function makeSureTableUpToDate(table: Table, tableToSave: Table) {
for ([field, column] of Object.entries(table.schema)) { for ([field, column] of Object.entries(table.schema)) {
if ( if (
column.autocolumn && column.autocolumn &&
column.subtype === AutoFieldSubTypes.AUTO_ID && column.subtype === AutoFieldSubType.AUTO_ID &&
tableToSave.schema[field] tableToSave.schema[field]
) { ) {
const tableCol = tableToSave.schema[field] as NumberFieldMetadata const tableCol = tableToSave.schema[field] as NumberFieldMetadata
@ -144,8 +143,8 @@ export async function importToRows(
? row[fieldName] ? row[fieldName]
: [row[fieldName]] : [row[fieldName]]
if ( if (
(schema.type === FieldTypes.OPTIONS || (schema.type === FieldType.OPTIONS ||
schema.type === FieldTypes.ARRAY) && schema.type === FieldType.ARRAY) &&
row[fieldName] row[fieldName]
) { ) {
let merged = [...schema.constraints!.inclusion!, ...rowVal] let merged = [...schema.constraints!.inclusion!, ...rowVal]
@ -403,7 +402,7 @@ export async function checkForViewUpdates(
) )
const newViewTemplate = viewTemplate( const newViewTemplate = viewTemplate(
viewMetadata, viewMetadata,
groupByField?.type === FieldTypes.ARRAY groupByField?.type === FieldType.ARRAY
) )
const viewName = view.name! const viewName = view.name!
await saveView(null, viewName, newViewTemplate) await saveView(null, viewName, newViewTemplate)
@ -434,7 +433,7 @@ export function generateJunctionTableName(
export function foreignKeyStructure(keyName: string, meta?: any) { export function foreignKeyStructure(keyName: string, meta?: any) {
const structure: any = { const structure: any = {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
constraints: {}, constraints: {},
name: keyName, name: keyName,
} }

View File

@ -6,8 +6,8 @@ import { fetchView } from "../row"
import { context, events } from "@budibase/backend-core" import { context, events } from "@budibase/backend-core"
import { DocumentType } from "../../../db/utils" import { DocumentType } from "../../../db/utils"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import { FieldTypes } from "../../../constants"
import { import {
FieldType,
Ctx, Ctx,
Row, Row,
Table, Table,
@ -37,7 +37,7 @@ export async function save(ctx: Ctx) {
(field: any) => field.name == viewToSave.groupBy (field: any) => field.name == viewToSave.groupBy
) )
const view = viewTemplate(viewToSave, groupByField?.type === FieldTypes.ARRAY) const view = viewTemplate(viewToSave, groupByField?.type === FieldType.ARRAY)
const viewName = viewToSave.name const viewName = viewToSave.name
if (!viewName) { if (!viewName) {

View File

@ -6,11 +6,11 @@ import * as setup from "./utilities"
import { context, InternalTable, roles, tenancy } from "@budibase/backend-core" import { context, InternalTable, roles, tenancy } from "@budibase/backend-core"
import { quotas } from "@budibase/pro" import { quotas } from "@budibase/pro"
import { import {
AutoFieldSubTypes, AutoFieldSubType,
FieldSchema, FieldSchema,
FieldType, FieldType,
FieldTypeSubtypes, FieldTypeSubtypes,
FormulaTypes, FormulaType,
INTERNAL_TABLE_SOURCE_ID, INTERNAL_TABLE_SOURCE_ID,
MonthlyQuotaName, MonthlyQuotaName,
PermissionLevel, PermissionLevel,
@ -192,7 +192,7 @@ describe.each([
"Row ID": { "Row ID": {
name: "Row ID", name: "Row ID",
type: FieldType.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
@ -2032,7 +2032,7 @@ describe.each([
name: "formula", name: "formula",
type: FieldType.FORMULA, type: FieldType.FORMULA,
formula: "{{ links.0.name }}", formula: "{{ links.0.name }}",
formulaType: FormulaTypes.DYNAMIC, formulaType: FormulaType.DYNAMIC,
}, },
}, },
} }
@ -2086,7 +2086,7 @@ describe.each([
name: "formula", name: "formula",
type: FieldType.FORMULA, type: FieldType.FORMULA,
formula: `{{ js "${js}"}}`, formula: `{{ js "${js}"}}`,
formulaType: FormulaTypes.DYNAMIC, formulaType: FormulaType.DYNAMIC,
}, },
}, },
}) })
@ -2129,7 +2129,7 @@ describe.each([
name: "formula", name: "formula",
type: FieldType.FORMULA, type: FieldType.FORMULA,
formula: `{{ js "${js}"}}`, formula: `{{ js "${js}"}}`,
formulaType: FormulaTypes.DYNAMIC, formulaType: FormulaType.DYNAMIC,
}, },
}, },
}) })

View File

@ -1,6 +1,6 @@
import { context, events } from "@budibase/backend-core" import { context, events } from "@budibase/backend-core"
import { import {
AutoFieldSubTypes, AutoFieldSubType,
FieldSubtype, FieldSubtype,
FieldType, FieldType,
INTERNAL_TABLE_SOURCE_ID, INTERNAL_TABLE_SOURCE_ID,
@ -205,7 +205,7 @@ describe("/tables", () => {
autoId: { autoId: {
name: "id", name: "id",
type: FieldType.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: "number", type: "number",

View File

@ -1,9 +1,9 @@
import * as rowController from "../../api/controllers/row" import * as rowController from "../../api/controllers/row"
import * as tableController from "../../api/controllers/table" import * as tableController from "../../api/controllers/table"
import { FieldTypes } from "../../constants"
import { buildCtx } from "./utils" import { buildCtx } from "./utils"
import * as automationUtils from "../automationUtils" import * as automationUtils from "../automationUtils"
import { import {
FieldType,
AutomationActionStepId, AutomationActionStepId,
AutomationCustomIOType, AutomationCustomIOType,
AutomationFeature, AutomationFeature,
@ -115,7 +115,7 @@ function typeCoercion(filters: SearchFilters, table: Table) {
if (!column || typeof value !== "string") { if (!column || typeof value !== "string") {
continue continue
} }
if (column.type === FieldTypes.NUMBER) { if (column.type === FieldType.NUMBER) {
if (key === "oneOf") { if (key === "oneOf") {
searchParam[property] = value searchParam[property] = value
.split(",") .split(",")
@ -148,11 +148,11 @@ export async function run({ inputs, appId }: AutomationStepInput) {
} }
} }
const table = await getTable(appId, tableId) const table = await getTable(appId, tableId)
let sortType = FieldTypes.STRING let sortType = FieldType.STRING
if (table && table.schema && table.schema[sortColumn] && sortColumn) { if (table && table.schema && table.schema[sortColumn] && sortColumn) {
const fieldType = table.schema[sortColumn].type const fieldType = table.schema[sortColumn].type
sortType = sortType =
fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING fieldType === FieldType.NUMBER ? FieldType.NUMBER : FieldType.STRING
} }
const ctx: any = buildCtx(appId, null, { const ctx: any = buildCtx(appId, null, {
params: { params: {

View File

@ -1,16 +1,15 @@
import { constants, objectStore, roles } from "@budibase/backend-core" import { constants, objectStore, roles } from "@budibase/backend-core"
import { import {
FieldType as FieldTypes, FieldType,
INTERNAL_TABLE_SOURCE_ID, INTERNAL_TABLE_SOURCE_ID,
Table, Table,
TableSourceType, TableSourceType,
} from "@budibase/types" } from "@budibase/types"
export { export {
FieldType as FieldTypes,
RelationshipType, RelationshipType,
AutoFieldSubTypes, AutoFieldSubType,
FormulaTypes, FormulaType,
} from "@budibase/types" } from "@budibase/types"
export enum FilterTypes { export enum FilterTypes {
@ -36,14 +35,14 @@ export const NoEmptyFilterStrings = [
] ]
export const CanSwitchTypes = [ export const CanSwitchTypes = [
[FieldTypes.JSON, FieldTypes.ARRAY], [FieldType.JSON, FieldType.ARRAY],
[ [
FieldTypes.STRING, FieldType.STRING,
FieldTypes.OPTIONS, FieldType.OPTIONS,
FieldTypes.LONGFORM, FieldType.LONGFORM,
FieldTypes.BARCODEQR, FieldType.BARCODEQR,
], ],
[FieldTypes.BOOLEAN, FieldTypes.NUMBER], [FieldType.BOOLEAN, FieldType.NUMBER],
] ]
export const SwitchableTypes = CanSwitchTypes.reduce((prev, current) => export const SwitchableTypes = CanSwitchTypes.reduce((prev, current) =>
@ -86,9 +85,9 @@ export const USERS_TABLE_SCHEMA: Table = {
// TODO: ADMIN PANEL - when implemented this doesn't need to be carried out // TODO: ADMIN PANEL - when implemented this doesn't need to be carried out
schema: { schema: {
email: { email: {
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
email: true, email: true,
length: { length: {
maximum: "", maximum: "",
@ -99,34 +98,34 @@ export const USERS_TABLE_SCHEMA: Table = {
}, },
firstName: { firstName: {
name: "firstName", name: "firstName",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
presence: false, presence: false,
}, },
}, },
lastName: { lastName: {
name: "lastName", name: "lastName",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
presence: false, presence: false,
}, },
}, },
roleId: { roleId: {
name: "roleId", name: "roleId",
type: FieldTypes.OPTIONS, type: FieldType.OPTIONS,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
presence: false, presence: false,
inclusion: Object.values(roles.BUILTIN_ROLE_IDS), inclusion: Object.values(roles.BUILTIN_ROLE_IDS),
}, },
}, },
status: { status: {
name: "status", name: "status",
type: FieldTypes.OPTIONS, type: FieldType.OPTIONS,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
presence: false, presence: false,
inclusion: Object.values(constants.UserStatus), inclusion: Object.values(constants.UserStatus),
}, },

View File

@ -1,6 +1,4 @@
import { import {
AutoFieldSubTypes,
FieldTypes,
DEFAULT_BB_DATASOURCE_ID, DEFAULT_BB_DATASOURCE_ID,
DEFAULT_INVENTORY_TABLE_ID, DEFAULT_INVENTORY_TABLE_ID,
DEFAULT_EMPLOYEE_TABLE_ID, DEFAULT_EMPLOYEE_TABLE_ID,
@ -16,6 +14,7 @@ import { jobsImport } from "./jobsImport"
import { expensesImport } from "./expensesImport" import { expensesImport } from "./expensesImport"
import { db as dbCore } from "@budibase/backend-core" import { db as dbCore } from "@budibase/backend-core"
import { import {
AutoFieldSubType,
FieldType, FieldType,
RelationshipType, RelationshipType,
Row, Row,
@ -40,7 +39,7 @@ function syncLastIds(table: Table, rowCount: number) {
if ( if (
entry.autocolumn && entry.autocolumn &&
entry.type === FieldType.NUMBER && entry.type === FieldType.NUMBER &&
entry.subtype == AutoFieldSubTypes.AUTO_ID entry.subtype == AutoFieldSubType.AUTO_ID
) { ) {
entry.lastID = rowCount entry.lastID = rowCount
} }
@ -58,12 +57,12 @@ async function tableImport(table: Table, data: Row[]) {
const AUTO_COLUMNS: TableSchema = { const AUTO_COLUMNS: TableSchema = {
"Created At": { "Created At": {
name: "Created At", name: "Created At",
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
subtype: AutoFieldSubTypes.CREATED_AT, subtype: AutoFieldSubType.CREATED_AT,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -74,12 +73,12 @@ const AUTO_COLUMNS: TableSchema = {
}, },
"Updated At": { "Updated At": {
name: "Updated At", name: "Updated At",
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
subtype: AutoFieldSubTypes.UPDATED_AT, subtype: AutoFieldSubType.UPDATED_AT,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -101,12 +100,12 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
schema: { schema: {
"Item ID": { "Item ID": {
name: "Item ID", name: "Item ID",
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: false, presence: false,
numericality: { numericality: {
greaterThanOrEqualTo: "", greaterThanOrEqualTo: "",
@ -115,9 +114,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
}, },
}, },
"Item Name": { "Item Name": {
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: { length: {
maximum: null, maximum: null,
}, },
@ -128,9 +127,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
name: "Item Name", name: "Item Name",
}, },
"Item Tags": { "Item Tags": {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: { presence: {
allowEmpty: false, allowEmpty: false,
}, },
@ -140,9 +139,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
sortable: false, sortable: false,
}, },
Notes: { Notes: {
type: FieldTypes.LONGFORM, type: FieldType.LONGFORM,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
@ -150,9 +149,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
useRichText: null, useRichText: null,
}, },
Status: { Status: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: { presence: {
allowEmpty: false, allowEmpty: false,
}, },
@ -162,18 +161,18 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
sortable: false, sortable: false,
}, },
SKU: { SKU: {
type: FieldTypes.BARCODEQR, type: FieldType.BARCODEQR,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
name: "SKU", name: "SKU",
}, },
"Purchase Date": { "Purchase Date": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -185,9 +184,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
"Purchase Price": { "Purchase Price": {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: false, presence: false,
numericality: { numericality: {
greaterThanOrEqualTo: null, greaterThanOrEqualTo: null,
@ -211,75 +210,75 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
schema: { schema: {
"First Name": { "First Name": {
name: "First Name", name: "First Name",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
"Last Name": { "Last Name": {
name: "Last Name", name: "Last Name",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
Email: { Email: {
name: "Email", name: "Email",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
Address: { Address: {
name: "Address", name: "Address",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
City: { City: {
name: "City", name: "City",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
Postcode: { Postcode: {
name: "Postcode", name: "Postcode",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
Phone: { Phone: {
name: "Phone", name: "Phone",
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
}, },
"EMPLOYEE ID": { "EMPLOYEE ID": {
name: "EMPLOYEE ID", name: "EMPLOYEE ID",
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: false, presence: false,
numericality: { numericality: {
greaterThanOrEqualTo: "", greaterThanOrEqualTo: "",
@ -288,9 +287,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
}, },
}, },
"Employee Level": { "Employee Level": {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: false, presence: false,
inclusion: ["Manager", "Junior", "Senior", "Apprentice", "Contractor"], inclusion: ["Manager", "Junior", "Senior", "Apprentice", "Contractor"],
}, },
@ -298,18 +297,18 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
sortable: false, sortable: false,
}, },
"Badge Photo": { "Badge Photo": {
type: FieldTypes.ATTACHMENT, type: FieldType.ATTACHMENT,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: false, presence: false,
}, },
name: "Badge Photo", name: "Badge Photo",
sortable: false, sortable: false,
}, },
Jobs: { Jobs: {
type: FieldTypes.LINK, type: FieldType.LINK,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: false, presence: false,
}, },
fieldName: "Assigned", fieldName: "Assigned",
@ -318,9 +317,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
tableId: DEFAULT_JOBS_TABLE_ID, tableId: DEFAULT_JOBS_TABLE_ID,
}, },
"Start Date": { "Start Date": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -332,9 +331,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
"End Date": { "End Date": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -359,12 +358,12 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
schema: { schema: {
"Job ID": { "Job ID": {
name: "Job ID", name: "Job ID",
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: false, presence: false,
numericality: { numericality: {
greaterThanOrEqualTo: "", greaterThanOrEqualTo: "",
@ -373,9 +372,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
}, },
}, },
"Quote Date": { "Quote Date": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: { presence: {
allowEmpty: false, allowEmpty: false,
@ -389,9 +388,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
"Quote Price": { "Quote Price": {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: { presence: {
allowEmpty: false, allowEmpty: false,
}, },
@ -403,9 +402,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
name: "Quote Price", name: "Quote Price",
}, },
"Works Start": { "Works Start": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -417,9 +416,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
Address: { Address: {
type: FieldTypes.LONGFORM, type: FieldType.LONGFORM,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
@ -427,9 +426,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
useRichText: null, useRichText: null,
}, },
"Customer Name": { "Customer Name": {
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: { length: {
maximum: null, maximum: null,
}, },
@ -438,9 +437,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
name: "Customer Name", name: "Customer Name",
}, },
Notes: { Notes: {
type: FieldTypes.LONGFORM, type: FieldType.LONGFORM,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
@ -448,9 +447,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
useRichText: null, useRichText: null,
}, },
"Customer Phone": { "Customer Phone": {
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: { length: {
maximum: null, maximum: null,
}, },
@ -459,9 +458,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
name: "Customer Phone", name: "Customer Phone",
}, },
"Customer Email": { "Customer Email": {
type: FieldTypes.STRING, type: FieldType.STRING,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: { length: {
maximum: null, maximum: null,
}, },
@ -471,14 +470,14 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
}, },
Assigned: { Assigned: {
name: "Assigned", name: "Assigned",
type: FieldTypes.LINK, type: FieldType.LINK,
tableId: DEFAULT_EMPLOYEE_TABLE_ID, tableId: DEFAULT_EMPLOYEE_TABLE_ID,
fieldName: "Jobs", fieldName: "Jobs",
relationshipType: RelationshipType.MANY_TO_MANY, relationshipType: RelationshipType.MANY_TO_MANY,
// sortable: true, // sortable: true,
}, },
"Works End": { "Works End": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: "string", type: "string",
length: {}, length: {},
@ -492,7 +491,7 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
"Updated Price": { "Updated Price": {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
constraints: { constraints: {
type: "number", type: "number",
presence: false, presence: false,
@ -518,12 +517,12 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
schema: { schema: {
"Expense ID": { "Expense ID": {
name: "Expense ID", name: "Expense ID",
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
icon: "ri-magic-line", icon: "ri-magic-line",
autocolumn: true, autocolumn: true,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: false, presence: false,
numericality: { numericality: {
greaterThanOrEqualTo: "", greaterThanOrEqualTo: "",
@ -532,9 +531,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
}, },
}, },
"Expense Tags": { "Expense Tags": {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: { presence: {
allowEmpty: false, allowEmpty: false,
}, },
@ -554,9 +553,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
sortable: false, sortable: false,
}, },
Cost: { Cost: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
constraints: { constraints: {
type: FieldTypes.NUMBER, type: FieldType.NUMBER,
presence: { presence: {
allowEmpty: false, allowEmpty: false,
}, },
@ -568,9 +567,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
name: "Cost", name: "Cost",
}, },
Notes: { Notes: {
type: FieldTypes.LONGFORM, type: FieldType.LONGFORM,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
}, },
@ -578,9 +577,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
useRichText: null, useRichText: null,
}, },
"Payment Due": { "Payment Due": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -592,9 +591,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
"Date Paid": { "Date Paid": {
type: FieldTypes.DATETIME, type: FieldType.DATETIME,
constraints: { constraints: {
type: FieldTypes.STRING, type: FieldType.STRING,
length: {}, length: {},
presence: false, presence: false,
datetime: { datetime: {
@ -606,9 +605,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = {
ignoreTimezones: true, ignoreTimezones: true,
}, },
Attachment: { Attachment: {
type: FieldTypes.ATTACHMENT, type: FieldType.ATTACHMENT,
constraints: { constraints: {
type: FieldTypes.ARRAY, type: FieldType.ARRAY,
presence: false, presence: false,
}, },
name: "Attachment", name: "Attachment",

View File

@ -1,6 +1,5 @@
import { IncludeDocs, getLinkDocuments } from "./linkUtils" import { IncludeDocs, getLinkDocuments } from "./linkUtils"
import { InternalTables, getUserMetadataParams } from "../utils" import { InternalTables, getUserMetadataParams } from "../utils"
import { FieldTypes } from "../../constants"
import { context, logging } from "@budibase/backend-core" import { context, logging } from "@budibase/backend-core"
import LinkDocument from "./LinkDocument" import LinkDocument from "./LinkDocument"
import { import {
@ -62,7 +61,7 @@ class LinkController {
} }
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
const { type } = table.schema[fieldName] const { type } = table.schema[fieldName]
if (type === FieldTypes.LINK) { if (type === FieldType.LINK) {
return true return true
} }
} }
@ -96,7 +95,7 @@ class LinkController {
validateTable(table: Table) { validateTable(table: Table) {
const usedAlready = [] const usedAlready = []
for (let schema of Object.values(table.schema)) { for (let schema of Object.values(table.schema)) {
if (schema.type !== FieldTypes.LINK) { if (schema.type !== FieldType.LINK) {
continue continue
} }
const unique = schema.tableId! + schema?.fieldName const unique = schema.tableId! + schema?.fieldName
@ -172,7 +171,7 @@ class LinkController {
// get the links this row wants to make // get the links this row wants to make
const rowField = row[fieldName] const rowField = row[fieldName]
const field = table.schema[fieldName] const field = table.schema[fieldName]
if (field.type === FieldTypes.LINK && rowField != null) { if (field.type === FieldType.LINK && rowField != null) {
// check which links actual pertain to the update in this row // check which links actual pertain to the update in this row
const thisFieldLinkDocs = linkDocs.filter( const thisFieldLinkDocs = linkDocs.filter(
linkDoc => linkDoc =>
@ -353,7 +352,7 @@ class LinkController {
const schema = table.schema const schema = table.schema
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
const field = schema[fieldName] const field = schema[fieldName]
if (field.type === FieldTypes.LINK && field.fieldName) { if (field.type === FieldType.LINK && field.fieldName) {
// handle this in a separate try catch, want // handle this in a separate try catch, want
// the put to bubble up as an error, if can't update // the put to bubble up as an error, if can't update
// table for some reason // table for some reason
@ -366,7 +365,7 @@ class LinkController {
} }
const fields = this.handleRelationshipType(field, { const fields = this.handleRelationshipType(field, {
name: field.fieldName, name: field.fieldName,
type: FieldTypes.LINK, type: FieldType.LINK,
// these are the props of the table that initiated the link // these are the props of the table that initiated the link
tableId: table._id!, tableId: table._id!,
fieldName: fieldName, fieldName: fieldName,
@ -413,10 +412,7 @@ class LinkController {
for (let fieldName of Object.keys(oldTable?.schema || {})) { for (let fieldName of Object.keys(oldTable?.schema || {})) {
const field = oldTable?.schema[fieldName] as FieldSchema const field = oldTable?.schema[fieldName] as FieldSchema
// this field has been removed from the table schema // this field has been removed from the table schema
if ( if (field.type === FieldType.LINK && newTable.schema[fieldName] == null) {
field.type === FieldTypes.LINK &&
newTable.schema[fieldName] == null
) {
await this.removeFieldFromTable(fieldName) await this.removeFieldFromTable(fieldName)
} }
} }
@ -437,7 +433,7 @@ class LinkController {
for (let fieldName of Object.keys(schema)) { for (let fieldName of Object.keys(schema)) {
const field = schema[fieldName] const field = schema[fieldName]
try { try {
if (field.type === FieldTypes.LINK && field.fieldName) { if (field.type === FieldType.LINK && field.fieldName) {
const linkedTable = await this._db.get<Table>(field.tableId) const linkedTable = await this._db.get<Table>(field.tableId)
delete linkedTable.schema[field.fieldName] delete linkedTable.schema[field.fieldName]
field.tableRev = (await this._db.put(linkedTable)).rev field.tableRev = (await this._db.put(linkedTable)).rev

View File

@ -1,6 +1,5 @@
import { generateLinkID } from "../utils" import { generateLinkID } from "../utils"
import { FieldTypes } from "../../constants" import { FieldType, LinkDocument } from "@budibase/types"
import { LinkDocument } from "@budibase/types"
/** /**
* Creates a new link document structure which can be put to the database. It is important to * Creates a new link document structure which can be put to the database. It is important to
@ -43,7 +42,7 @@ class LinkDocumentImpl implements LinkDocument {
fieldName1, fieldName1,
fieldName2 fieldName2
) )
this.type = FieldTypes.LINK this.type = FieldType.LINK
this.doc1 = { this.doc1 = {
tableId: tableId1, tableId: tableId1,
fieldName: fieldName1, fieldName: fieldName1,

View File

@ -1,8 +1,8 @@
import { ViewName, getQueryIndex, isRelationshipColumn } from "../utils" import { ViewName, getQueryIndex, isRelationshipColumn } from "../utils"
import { FieldTypes } from "../../constants"
import { createLinkView } from "../views/staticViews" import { createLinkView } from "../views/staticViews"
import { context, logging } from "@budibase/backend-core" import { context, logging } from "@budibase/backend-core"
import { import {
FieldType,
DatabaseQueryOpts, DatabaseQueryOpts,
LinkDocument, LinkDocument,
LinkDocumentValue, LinkDocumentValue,
@ -131,11 +131,11 @@ export async function getLinkedTable(id: string, tables: Table[]) {
export function getRelatedTableForField(table: Table, fieldName: string) { export function getRelatedTableForField(table: Table, fieldName: string) {
// look to see if its on the table, straight in the schema // look to see if its on the table, straight in the schema
const field = table.schema[fieldName] const field = table.schema[fieldName]
if (field?.type === FieldTypes.LINK) { if (field?.type === FieldType.LINK) {
return field.tableId return field.tableId
} }
for (let column of Object.values(table.schema)) { for (let column of Object.values(table.schema)) {
if (column.type === FieldTypes.LINK && column.fieldName === fieldName) { if (column.type === FieldType.LINK && column.fieldName === fieldName) {
return column.tableId return column.tableId
} }
} }

View File

@ -1,6 +1,7 @@
import newid from "./newid" import newid from "./newid"
import { db as dbCore } from "@budibase/backend-core" import { db as dbCore } from "@budibase/backend-core"
import { import {
FieldType,
DocumentType, DocumentType,
FieldSchema, FieldSchema,
RelationshipFieldMetadata, RelationshipFieldMetadata,
@ -8,7 +9,6 @@ import {
INTERNAL_TABLE_SOURCE_ID, INTERNAL_TABLE_SOURCE_ID,
DatabaseQueryOpts, DatabaseQueryOpts,
} from "@budibase/types" } from "@budibase/types"
import { FieldTypes } from "../constants"
export { DocumentType, VirtualDocumentType } from "@budibase/types" export { DocumentType, VirtualDocumentType } from "@budibase/types"
@ -315,5 +315,5 @@ export function extractViewInfoFromID(viewId: string) {
export function isRelationshipColumn( export function isRelationshipColumn(
column: FieldSchema column: FieldSchema
): column is RelationshipFieldMetadata { ): column is RelationshipFieldMetadata {
return column.type === FieldTypes.LINK return column.type === FieldType.LINK
} }

View File

@ -1,4 +1,5 @@
import { import {
FieldType,
DatasourceFieldType, DatasourceFieldType,
Integration, Integration,
Operation, Operation,
@ -21,7 +22,6 @@ import {
SqlClient, SqlClient,
} from "./utils" } from "./utils"
import Sql from "./base/sql" import Sql from "./base/sql"
import { FieldTypes } from "../constants"
import { import {
BindParameters, BindParameters,
Connection, Connection,
@ -302,7 +302,7 @@ class OracleIntegration extends Sql implements DatasourcePlus {
}) })
if (this.isBooleanType(oracleColumn)) { if (this.isBooleanType(oracleColumn)) {
fieldSchema.type = FieldTypes.BOOLEAN fieldSchema.type = FieldType.BOOLEAN
} }
table.schema[columnName] = fieldSchema table.schema[columnName] = fieldSchema

View File

@ -1,7 +1,6 @@
import { CouchFindOptions, Table, Row } from "@budibase/types" import { FieldType, CouchFindOptions, Table, Row } from "@budibase/types"
import { db as dbCore } from "@budibase/backend-core" import { db as dbCore } from "@budibase/backend-core"
import { DocumentType, SEPARATOR } from "../../../db/utils" import { DocumentType, SEPARATOR } from "../../../db/utils"
import { FieldTypes } from "../../../constants"
// default limit - seems to work well for performance // default limit - seems to work well for performance
export const FIND_LIMIT = 25 export const FIND_LIMIT = 25
@ -31,7 +30,7 @@ export async function getRowsWithAttachments(appId: string, table: Table) {
const db = dbCore.getDB(appId) const db = dbCore.getDB(appId)
const attachmentCols: string[] = [] const attachmentCols: string[] = []
for (let [key, column] of Object.entries(table.schema)) { for (let [key, column] of Object.entries(table.schema)) {
if (column.type === FieldTypes.ATTACHMENT) { if (column.type === FieldType.ATTACHMENT) {
attachmentCols.push(key) attachmentCols.push(key)
} }
} }

View File

@ -7,7 +7,7 @@ import {
TableSourceType, TableSourceType,
FieldType, FieldType,
Table, Table,
AutoFieldSubTypes, AutoFieldSubType,
} from "@budibase/types" } from "@budibase/types"
import TestConfiguration from "../../../../tests/utilities/TestConfiguration" import TestConfiguration from "../../../../tests/utilities/TestConfiguration"
@ -117,7 +117,7 @@ describe("sdk >> rows >> internal", () => {
id: { id: {
name: "id", name: "id",
type: FieldType.AUTO, type: FieldType.AUTO,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
autocolumn: true, autocolumn: true,
lastID: 0, lastID: 0,
}, },
@ -181,7 +181,7 @@ describe("sdk >> rows >> internal", () => {
id: { id: {
name: "id", name: "id",
type: FieldType.AUTO, type: FieldType.AUTO,
subtype: AutoFieldSubTypes.AUTO_ID, subtype: AutoFieldSubType.AUTO_ID,
autocolumn: true, autocolumn: true,
lastID: 0, lastID: 0,
}, },

View File

@ -1,7 +1,6 @@
import cloneDeep from "lodash/cloneDeep" import cloneDeep from "lodash/cloneDeep"
import validateJs from "validate.js" import validateJs from "validate.js"
import { Row, Table, TableSchema } from "@budibase/types" import { FieldType, Row, Table, TableSchema } from "@budibase/types"
import { FieldTypes } from "../../../constants"
import { makeExternalQuery } from "../../../integrations/base/query" import { makeExternalQuery } from "../../../integrations/base/query"
import { Format } from "../../../api/controllers/view/exporters" import { Format } from "../../../api/controllers/view/exporters"
import sdk from "../.." import sdk from "../.."
@ -22,7 +21,7 @@ export function cleanExportRows(
let cleanRows = [...rows] let cleanRows = [...rows]
const relationships = Object.entries(schema) const relationships = Object.entries(schema)
.filter((entry: any[]) => entry[1].type === FieldTypes.LINK) .filter((entry: any[]) => entry[1].type === FieldType.LINK)
.map(entry => entry[0]) .map(entry => entry[0])
relationships.forEach(column => { relationships.forEach(column => {
@ -88,17 +87,17 @@ export async function validate({
continue continue
} }
// formulas shouldn't validated, data will be deleted anyway // formulas shouldn't validated, data will be deleted anyway
if (type === FieldTypes.FORMULA || column.autocolumn) { if (type === FieldType.FORMULA || column.autocolumn) {
continue continue
} }
// special case for options, need to always allow unselected (empty) // special case for options, need to always allow unselected (empty)
if (type === FieldTypes.OPTIONS && constraints?.inclusion) { if (type === FieldType.OPTIONS && constraints?.inclusion) {
constraints.inclusion.push(null as any, "") constraints.inclusion.push(null as any, "")
} }
let res let res
// Validate.js doesn't seem to handle array // Validate.js doesn't seem to handle array
if (type === FieldTypes.ARRAY && row[fieldName]) { if (type === FieldType.ARRAY && row[fieldName]) {
if (row[fieldName].length) { if (row[fieldName].length) {
if (!Array.isArray(row[fieldName])) { if (!Array.isArray(row[fieldName])) {
row[fieldName] = row[fieldName].split(",") row[fieldName] = row[fieldName].split(",")
@ -116,13 +115,13 @@ export async function validate({
errors[fieldName] = [`${fieldName} is required`] errors[fieldName] = [`${fieldName} is required`]
} }
} else if ( } else if (
(type === FieldTypes.ATTACHMENT || type === FieldTypes.JSON) && (type === FieldType.ATTACHMENT || type === FieldType.JSON) &&
typeof row[fieldName] === "string" typeof row[fieldName] === "string"
) { ) {
// this should only happen if there is an error // this should only happen if there is an error
try { try {
const json = JSON.parse(row[fieldName]) const json = JSON.parse(row[fieldName])
if (type === FieldTypes.ATTACHMENT) { if (type === FieldType.ATTACHMENT) {
if (Array.isArray(json)) { if (Array.isArray(json)) {
row[fieldName] = json row[fieldName] = json
} else { } else {

View File

@ -1,4 +1,5 @@
import { import {
FieldType,
Operation, Operation,
RelationshipType, RelationshipType,
RenameColumn, RenameColumn,
@ -14,7 +15,6 @@ import {
setStaticSchemas, setStaticSchemas,
} from "../../../../api/controllers/table/utils" } from "../../../../api/controllers/table/utils"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { FieldTypes } from "../../../../constants"
import { makeTableRequest } from "../../../../api/controllers/table/ExternalRequest" import { makeTableRequest } from "../../../../api/controllers/table/ExternalRequest"
import { import {
isRelationshipSetup, isRelationshipSetup,
@ -78,7 +78,7 @@ export async function save(
// check if relations need setup // check if relations need setup
for (let schema of Object.values(tableToSave.schema)) { for (let schema of Object.values(tableToSave.schema)) {
if (schema.type !== FieldTypes.LINK || isRelationshipSetup(schema)) { if (schema.type !== FieldType.LINK || isRelationshipSetup(schema)) {
continue continue
} }
const schemaTableId = schema.tableId const schemaTableId = schema.tableId

View File

@ -9,7 +9,6 @@ import {
Table, Table,
TableSourceType, TableSourceType,
} from "@budibase/types" } from "@budibase/types"
import { FieldTypes } from "../../../../constants"
import { import {
foreignKeyStructure, foreignKeyStructure,
generateForeignKey, generateForeignKey,
@ -27,7 +26,7 @@ export function cleanupRelationships(
// clean up relationships in couch table schemas // clean up relationships in couch table schemas
for (let [key, schema] of Object.entries(tableToIterate.schema)) { for (let [key, schema] of Object.entries(tableToIterate.schema)) {
if ( if (
schema.type === FieldTypes.LINK && schema.type === FieldType.LINK &&
(!oldTable || table.schema[key] == null) (!oldTable || table.schema[key] == null)
) { ) {
const schemaTableId = schema.tableId const schemaTableId = schema.tableId

View File

@ -1,4 +1,5 @@
import { import {
FieldType,
RenameColumn, RenameColumn,
Table, Table,
ViewStatisticsSchema, ViewStatisticsSchema,
@ -10,7 +11,6 @@ import {
hasTypeChanged, hasTypeChanged,
TableSaveFunctions, TableSaveFunctions,
} from "../../../../api/controllers/table/utils" } from "../../../../api/controllers/table/utils"
import { FieldTypes } from "../../../../constants"
import { EventType, updateLinks } from "../../../../db/linkedRows" import { EventType, updateLinks } from "../../../../db/linkedRows"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import isEqual from "lodash/isEqual" import isEqual from "lodash/isEqual"
@ -63,7 +63,7 @@ export async function save(
} }
// rename row fields when table column is renamed // rename row fields when table column is renamed
if (renaming && table.schema[renaming.updated].type === FieldTypes.LINK) { if (renaming && table.schema[renaming.updated].type === FieldType.LINK) {
throw new Error("Cannot rename a linked column.") throw new Error("Cannot rename a linked column.")
} }

View File

@ -1,6 +1,12 @@
import { FieldTypes, ObjectStoreBuckets } from "../../constants" import { ObjectStoreBuckets } from "../../constants"
import { context, db as dbCore, objectStore } from "@budibase/backend-core" import { context, db as dbCore, objectStore } from "@budibase/backend-core"
import { RenameColumn, Row, RowAttachment, Table } from "@budibase/types" import {
FieldType,
RenameColumn,
Row,
RowAttachment,
Table,
} from "@budibase/types"
export class AttachmentCleanup { export class AttachmentCleanup {
static async coreCleanup(fileListFn: () => string[]): Promise<void> { static async coreCleanup(fileListFn: () => string[]): Promise<void> {
@ -28,7 +34,7 @@ export class AttachmentCleanup {
let files: string[] = [] let files: string[] = []
const tableSchema = opts.oldTable?.schema || table.schema const tableSchema = opts.oldTable?.schema || table.schema
for (let [key, schema] of Object.entries(tableSchema)) { for (let [key, schema] of Object.entries(tableSchema)) {
if (schema.type !== FieldTypes.ATTACHMENT) { if (schema.type !== FieldType.ATTACHMENT) {
continue continue
} }
const columnRemoved = opts.oldTable && !table.schema[key] const columnRemoved = opts.oldTable && !table.schema[key]
@ -62,7 +68,7 @@ export class AttachmentCleanup {
return AttachmentCleanup.coreCleanup(() => { return AttachmentCleanup.coreCleanup(() => {
let files: string[] = [] let files: string[] = []
for (let [key, schema] of Object.entries(table.schema)) { for (let [key, schema] of Object.entries(table.schema)) {
if (schema.type !== FieldTypes.ATTACHMENT) { if (schema.type !== FieldType.ATTACHMENT) {
continue continue
} }
rows.forEach(row => { rows.forEach(row => {
@ -79,7 +85,7 @@ export class AttachmentCleanup {
return AttachmentCleanup.coreCleanup(() => { return AttachmentCleanup.coreCleanup(() => {
let files: string[] = [] let files: string[] = []
for (let [key, schema] of Object.entries(table.schema)) { for (let [key, schema] of Object.entries(table.schema)) {
if (schema.type !== FieldTypes.ATTACHMENT) { if (schema.type !== FieldType.ATTACHMENT) {
continue continue
} }
const oldKeys = const oldKeys =

View File

@ -1,10 +1,16 @@
import * as linkRows from "../../db/linkedRows" import * as linkRows from "../../db/linkedRows"
import { FieldTypes, AutoFieldSubTypes } from "../../constants"
import { processFormulas, fixAutoColumnSubType } from "./utils" import { processFormulas, fixAutoColumnSubType } from "./utils"
import { objectStore, utils } from "@budibase/backend-core" import { objectStore, utils } from "@budibase/backend-core"
import { InternalTables } from "../../db/utils" import { InternalTables } from "../../db/utils"
import { TYPE_TRANSFORM_MAP } from "./map" import { TYPE_TRANSFORM_MAP } from "./map"
import { FieldSubtype, Row, RowAttachment, Table } from "@budibase/types" import {
FieldType,
AutoFieldSubType,
FieldSubtype,
Row,
RowAttachment,
Table,
} from "@budibase/types"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import { import {
processInputBBReferences, processInputBBReferences,
@ -54,25 +60,25 @@ export function processAutoColumn(
schema = fixAutoColumnSubType(schema) schema = fixAutoColumnSubType(schema)
} }
switch (schema.subtype) { switch (schema.subtype) {
case AutoFieldSubTypes.CREATED_BY: case AutoFieldSubType.CREATED_BY:
if (creating && shouldUpdateUserFields && userId) { if (creating && shouldUpdateUserFields && userId) {
row[key] = [userId] row[key] = [userId]
} }
break break
case AutoFieldSubTypes.CREATED_AT: case AutoFieldSubType.CREATED_AT:
if (creating) { if (creating) {
row[key] = now row[key] = now
} }
break break
case AutoFieldSubTypes.UPDATED_BY: case AutoFieldSubType.UPDATED_BY:
if (shouldUpdateUserFields && userId) { if (shouldUpdateUserFields && userId) {
row[key] = [userId] row[key] = [userId]
} }
break break
case AutoFieldSubTypes.UPDATED_AT: case AutoFieldSubType.UPDATED_AT:
row[key] = now row[key] = now
break break
case AutoFieldSubTypes.AUTO_ID: case AutoFieldSubType.AUTO_ID:
if (creating) { if (creating) {
schema.lastID = !schema.lastID ? BASE_AUTO_ID : schema.lastID + 1 schema.lastID = !schema.lastID ? BASE_AUTO_ID : schema.lastID + 1
row[key] = schema.lastID row[key] = schema.lastID
@ -134,7 +140,7 @@ export async function inputProcessing(
continue continue
} }
// remove any formula values, they are to be generated // remove any formula values, they are to be generated
if (field.type === FieldTypes.FORMULA) { if (field.type === FieldType.FORMULA) {
delete clonedRow[key] delete clonedRow[key]
} }
// otherwise coerce what is there to correct types // otherwise coerce what is there to correct types
@ -143,7 +149,7 @@ export async function inputProcessing(
} }
// remove any attachment urls, they are generated on read // remove any attachment urls, they are generated on read
if (field.type === FieldTypes.ATTACHMENT) { if (field.type === FieldType.ATTACHMENT) {
const attachments = clonedRow[key] const attachments = clonedRow[key]
if (attachments?.length) { if (attachments?.length) {
attachments.forEach((attachment: RowAttachment) => { attachments.forEach((attachment: RowAttachment) => {
@ -152,7 +158,7 @@ export async function inputProcessing(
} }
} }
if (field.type === FieldTypes.BB_REFERENCE && value) { if (field.type === FieldType.BB_REFERENCE && value) {
clonedRow[key] = await processInputBBReferences( clonedRow[key] = await processInputBBReferences(
value, value,
field.subtype as FieldSubtype field.subtype as FieldSubtype
@ -214,7 +220,7 @@ export async function outputProcessing<T extends Row[] | Row>(
// process complex types: attachements, bb references... // process complex types: attachements, bb references...
for (let [property, column] of Object.entries(table.schema)) { for (let [property, column] of Object.entries(table.schema)) {
if (column.type === FieldTypes.ATTACHMENT) { if (column.type === FieldType.ATTACHMENT) {
for (let row of enriched) { for (let row of enriched) {
if (row[property] == null || !Array.isArray(row[property])) { if (row[property] == null || !Array.isArray(row[property])) {
continue continue
@ -227,7 +233,7 @@ export async function outputProcessing<T extends Row[] | Row>(
} }
} else if ( } else if (
!opts.skipBBReferences && !opts.skipBBReferences &&
column.type == FieldTypes.BB_REFERENCE column.type == FieldType.BB_REFERENCE
) { ) {
for (let row of enriched) { for (let row of enriched) {
row[property] = await processOutputBBReferences( row[property] = await processOutputBBReferences(

View File

@ -1,7 +1,6 @@
// @ts-nocheck import { FieldType } from "@budibase/types"
import { FieldTypes } from "../../constants"
const parseArrayString = value => { const parseArrayString = (value: any) => {
if (typeof value === "string") { if (typeof value === "string") {
if (value === "") { if (value === "") {
return [] return []
@ -21,11 +20,13 @@ const parseArrayString = value => {
* A map of how we convert various properties in rows to each other based on the row type. * A map of how we convert various properties in rows to each other based on the row type.
*/ */
export const TYPE_TRANSFORM_MAP: any = { export const TYPE_TRANSFORM_MAP: any = {
[FieldTypes.LINK]: { [FieldType.LINK]: {
"": [], "": [],
//@ts-ignore
[null]: [], [null]: [],
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
parse: link => { parse: (link: any) => {
if (Array.isArray(link) && typeof link[0] === "object") { if (Array.isArray(link) && typeof link[0] === "object") {
return link.map(el => (el && el._id ? el._id : el)) return link.map(el => (el && el._id ? el._id : el))
} }
@ -35,75 +36,97 @@ export const TYPE_TRANSFORM_MAP: any = {
return link return link
}, },
}, },
[FieldTypes.OPTIONS]: { [FieldType.OPTIONS]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.ARRAY]: { [FieldType.ARRAY]: {
//@ts-ignore
[null]: [], [null]: [],
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
parse: parseArrayString, parse: parseArrayString,
}, },
[FieldTypes.STRING]: { [FieldType.STRING]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.BARCODEQR]: { [FieldType.BARCODEQR]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.FORMULA]: { [FieldType.FORMULA]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.LONGFORM]: { [FieldType.LONGFORM]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.NUMBER]: { [FieldType.NUMBER]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
parse: n => parseFloat(n), parse: (n: any) => parseFloat(n),
}, },
[FieldTypes.BIGINT]: { [FieldType.BIGINT]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
}, },
[FieldTypes.DATETIME]: { [FieldType.DATETIME]: {
"": null, "": null,
[undefined]: undefined, //@ts-ignore
[null]: null, [null]: null,
parse: date => { //@ts-ignore
[undefined]: undefined,
parse: (date: any) => {
if (date instanceof Date) { if (date instanceof Date) {
return date.toISOString() return date.toISOString()
} }
return date return date
}, },
}, },
[FieldTypes.ATTACHMENT]: { [FieldType.ATTACHMENT]: {
//@ts-ignore
[null]: [], [null]: [],
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
parse: parseArrayString, parse: parseArrayString,
}, },
[FieldTypes.BOOLEAN]: { [FieldType.BOOLEAN]: {
"": null, "": null,
//@ts-ignore
[null]: null, [null]: null,
//@ts-ignore
[undefined]: undefined, [undefined]: undefined,
true: true, true: true,
false: false, false: false,
}, },
[FieldTypes.AUTO]: { [FieldType.AUTO]: {
parse: () => undefined, parse: () => undefined,
}, },
[FieldTypes.JSON]: { [FieldType.JSON]: {
parse: input => { parse: (input: any) => {
try { try {
if (input === "") { if (input === "") {
return undefined return undefined

View File

@ -1,5 +1,5 @@
import { fixAutoColumnSubType } from "../utils" import { fixAutoColumnSubType } from "../utils"
import { AutoFieldDefaultNames, AutoFieldSubTypes } from "../../../constants" import { AutoFieldDefaultNames, AutoFieldSubType } from "../../../constants"
import { FieldSchema, FieldType, RelationshipType } from "@budibase/types" import { FieldSchema, FieldType, RelationshipType } from "@budibase/types"
describe("rowProcessor utility", () => { describe("rowProcessor utility", () => {
@ -20,37 +20,37 @@ describe("rowProcessor utility", () => {
it("updates the schema with the correct subtype", async () => { it("updates the schema with the correct subtype", async () => {
schema.name = AutoFieldDefaultNames.CREATED_BY schema.name = AutoFieldDefaultNames.CREATED_BY
expect(fixAutoColumnSubType(schema).subtype).toEqual( expect(fixAutoColumnSubType(schema).subtype).toEqual(
AutoFieldSubTypes.CREATED_BY AutoFieldSubType.CREATED_BY
) )
schema.subtype = undefined schema.subtype = undefined
schema.name = AutoFieldDefaultNames.UPDATED_BY schema.name = AutoFieldDefaultNames.UPDATED_BY
expect(fixAutoColumnSubType(schema).subtype).toEqual( expect(fixAutoColumnSubType(schema).subtype).toEqual(
AutoFieldSubTypes.UPDATED_BY AutoFieldSubType.UPDATED_BY
) )
schema.subtype = undefined schema.subtype = undefined
schema.name = AutoFieldDefaultNames.CREATED_AT schema.name = AutoFieldDefaultNames.CREATED_AT
expect(fixAutoColumnSubType(schema).subtype).toEqual( expect(fixAutoColumnSubType(schema).subtype).toEqual(
AutoFieldSubTypes.CREATED_AT AutoFieldSubType.CREATED_AT
) )
schema.subtype = undefined schema.subtype = undefined
schema.name = AutoFieldDefaultNames.UPDATED_AT schema.name = AutoFieldDefaultNames.UPDATED_AT
expect(fixAutoColumnSubType(schema).subtype).toEqual( expect(fixAutoColumnSubType(schema).subtype).toEqual(
AutoFieldSubTypes.UPDATED_AT AutoFieldSubType.UPDATED_AT
) )
schema.subtype = undefined schema.subtype = undefined
schema.name = AutoFieldDefaultNames.AUTO_ID schema.name = AutoFieldDefaultNames.AUTO_ID
expect(fixAutoColumnSubType(schema).subtype).toEqual( expect(fixAutoColumnSubType(schema).subtype).toEqual(
AutoFieldSubTypes.AUTO_ID AutoFieldSubType.AUTO_ID
) )
schema.subtype = undefined schema.subtype = undefined
}) })
it("returns the column if subtype exists", async () => { it("returns the column if subtype exists", async () => {
schema.subtype = AutoFieldSubTypes.CREATED_BY schema.subtype = AutoFieldSubType.CREATED_BY
schema.name = AutoFieldDefaultNames.CREATED_AT schema.name = AutoFieldDefaultNames.CREATED_AT
expect(fixAutoColumnSubType(schema)).toEqual(schema) expect(fixAutoColumnSubType(schema)).toEqual(schema)
}) })

View File

@ -1,15 +1,13 @@
import { import { AutoFieldDefaultNames } from "../../constants"
AutoFieldDefaultNames,
AutoFieldSubTypes,
FieldTypes,
FormulaTypes,
} from "../../constants"
import { processStringSync } from "@budibase/string-templates" import { processStringSync } from "@budibase/string-templates"
import { import {
AutoColumnFieldMetadata, AutoColumnFieldMetadata,
FieldSchema, FieldSchema,
Row, Row,
Table, Table,
FormulaType,
AutoFieldSubType,
FieldType,
} from "@budibase/types" } from "@budibase/types"
import tracer from "dd-trace" import tracer from "dd-trace"
@ -30,15 +28,15 @@ export function fixAutoColumnSubType(
} }
// the columns which get auto generated // the columns which get auto generated
if (column.name.endsWith(AutoFieldDefaultNames.CREATED_BY)) { if (column.name.endsWith(AutoFieldDefaultNames.CREATED_BY)) {
column.subtype = AutoFieldSubTypes.CREATED_BY column.subtype = AutoFieldSubType.CREATED_BY
} else if (column.name.endsWith(AutoFieldDefaultNames.UPDATED_BY)) { } else if (column.name.endsWith(AutoFieldDefaultNames.UPDATED_BY)) {
column.subtype = AutoFieldSubTypes.UPDATED_BY column.subtype = AutoFieldSubType.UPDATED_BY
} else if (column.name.endsWith(AutoFieldDefaultNames.CREATED_AT)) { } else if (column.name.endsWith(AutoFieldDefaultNames.CREATED_AT)) {
column.subtype = AutoFieldSubTypes.CREATED_AT column.subtype = AutoFieldSubType.CREATED_AT
} else if (column.name.endsWith(AutoFieldDefaultNames.UPDATED_AT)) { } else if (column.name.endsWith(AutoFieldDefaultNames.UPDATED_AT)) {
column.subtype = AutoFieldSubTypes.UPDATED_AT column.subtype = AutoFieldSubType.UPDATED_AT
} else if (column.name.endsWith(AutoFieldDefaultNames.AUTO_ID)) { } else if (column.name.endsWith(AutoFieldDefaultNames.AUTO_ID)) {
column.subtype = AutoFieldSubTypes.AUTO_ID column.subtype = AutoFieldSubType.AUTO_ID
} }
return column return column
} }
@ -57,11 +55,11 @@ export function processFormulas<T extends Row | Row[]>(
const rows = Array.isArray(inputRows) ? inputRows : [inputRows] const rows = Array.isArray(inputRows) ? inputRows : [inputRows]
if (rows) { if (rows) {
for (let [column, schema] of Object.entries(table.schema)) { for (let [column, schema] of Object.entries(table.schema)) {
if (schema.type !== FieldTypes.FORMULA) { if (schema.type !== FieldType.FORMULA) {
continue continue
} }
const isStatic = schema.formulaType === FormulaTypes.STATIC const isStatic = schema.formulaType === FormulaType.STATIC
if ( if (
schema.formula == null || schema.formula == null ||
@ -100,7 +98,7 @@ export function processDates<T extends Row | Row[]>(
let rows = Array.isArray(inputRows) ? inputRows : [inputRows] let rows = Array.isArray(inputRows) ? inputRows : [inputRows]
let datesWithTZ: string[] = [] let datesWithTZ: string[] = []
for (let [column, schema] of Object.entries(table.schema)) { for (let [column, schema] of Object.entries(table.schema)) {
if (schema.type !== FieldTypes.DATETIME) { if (schema.type !== FieldType.DATETIME) {
continue continue
} }
if (!schema.timeOnly && !schema.ignoreTimezones) { if (!schema.timeOnly && !schema.ignoreTimezones) {

View File

@ -1,12 +1,11 @@
import { FieldSubtype } from "@budibase/types" import { FieldType, FieldSubtype } from "@budibase/types"
import { FieldTypes } from "../constants"
import { ValidColumnNameRegex, utils } from "@budibase/shared-core" import { ValidColumnNameRegex, utils } from "@budibase/shared-core"
import { db } from "@budibase/backend-core" import { db } from "@budibase/backend-core"
import { parseCsvExport } from "../api/controllers/view/exporters" import { parseCsvExport } from "../api/controllers/view/exporters"
interface SchemaColumn { interface SchemaColumn {
readonly name: string readonly name: string
readonly type: FieldTypes readonly type: FieldType
readonly subtype: FieldSubtype readonly subtype: FieldSubtype
readonly autocolumn?: boolean readonly autocolumn?: boolean
readonly constraints?: { readonly constraints?: {
@ -36,13 +35,13 @@ interface ValidationResults {
} }
const PARSERS: any = { const PARSERS: any = {
[FieldTypes.NUMBER]: (attribute?: string) => { [FieldType.NUMBER]: (attribute?: string) => {
if (!attribute) { if (!attribute) {
return attribute return attribute
} }
return Number(attribute) return Number(attribute)
}, },
[FieldTypes.DATETIME]: (attribute?: string) => { [FieldType.DATETIME]: (attribute?: string) => {
if (!attribute) { if (!attribute) {
return attribute return attribute
} }
@ -60,7 +59,7 @@ export function isSchema(schema: any): schema is Schema {
column !== null && column !== null &&
typeof column === "object" && typeof column === "object" &&
typeof column.type === "string" && typeof column.type === "string" &&
Object.values(FieldTypes).includes(column.type as FieldTypes) Object.values(FieldType).includes(column.type as FieldType)
) )
}) })
) )
@ -110,20 +109,17 @@ export function validate(rows: Rows, schema: Schema): ValidationResults {
isAutoColumn isAutoColumn
) { ) {
return return
} else if ( } else if (columnType === FieldType.NUMBER && isNaN(Number(columnData))) {
columnType === FieldTypes.NUMBER &&
isNaN(Number(columnData))
) {
// If provided must be a valid number // If provided must be a valid number
results.schemaValidation[columnName] = false results.schemaValidation[columnName] = false
} else if ( } else if (
// If provided must be a valid date // If provided must be a valid date
columnType === FieldTypes.DATETIME && columnType === FieldType.DATETIME &&
isNaN(new Date(columnData).getTime()) isNaN(new Date(columnData).getTime())
) { ) {
results.schemaValidation[columnName] = false results.schemaValidation[columnName] = false
} else if ( } else if (
columnType === FieldTypes.BB_REFERENCE && columnType === FieldType.BB_REFERENCE &&
!isValidBBReference(columnData, columnSubtype) !isValidBBReference(columnData, columnSubtype)
) { ) {
results.schemaValidation[columnName] = false results.schemaValidation[columnName] = false
@ -155,15 +151,15 @@ export function parse(rows: Rows, schema: Schema): Rows {
const columnType = schema[columnName].type const columnType = schema[columnName].type
const columnSubtype = schema[columnName].subtype const columnSubtype = schema[columnName].subtype
if (columnType === FieldTypes.NUMBER) { if (columnType === FieldType.NUMBER) {
// If provided must be a valid number // If provided must be a valid number
parsedRow[columnName] = columnData ? Number(columnData) : columnData parsedRow[columnName] = columnData ? Number(columnData) : columnData
} else if (columnType === FieldTypes.DATETIME) { } else if (columnType === FieldType.DATETIME) {
// If provided must be a valid date // If provided must be a valid date
parsedRow[columnName] = columnData parsedRow[columnName] = columnData
? new Date(columnData).toISOString() ? new Date(columnData).toISOString()
: columnData : columnData
} else if (columnType === FieldTypes.BB_REFERENCE) { } else if (columnType === FieldType.BB_REFERENCE) {
const parsedValues = const parsedValues =
!!columnData && parseCsvExport<{ _id: string }[]>(columnData) !!columnData && parseCsvExport<{ _id: string }[]>(columnData)
if (!parsedValues) { if (!parsedValues) {