diff --git a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte index a0de8a5ef3..85f608d032 100644 --- a/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/HeaderCell.svelte @@ -13,7 +13,7 @@ import { getColumnIcon } from "../lib/utils" import MigrationModal from "../controls/MigrationModal.svelte" import { debounce } from "../../../utils/utils" - import { FieldType, FormulaTypes } from "@budibase/types" + import { FieldType, FormulaType } from "@budibase/types" import { TableNames } from "../../../constants" export let column @@ -96,7 +96,7 @@ const { type, formulaType } = col.schema return ( searchableTypes.includes(type) || - (type === FieldType.FORMULA && formulaType === FormulaTypes.STATIC) + (type === FieldType.FORMULA && formulaType === FormulaType.STATIC) ) } diff --git a/packages/server/specs/resources/table.ts b/packages/server/specs/resources/table.ts index 3a6a77e3e2..7f90769b07 100644 --- a/packages/server/specs/resources/table.ts +++ b/packages/server/specs/resources/table.ts @@ -1,4 +1,4 @@ -import { FieldTypes, RelationshipType, FormulaTypes } from "../../src/constants" +import { FieldType, FormulaType, RelationshipType } from "@budibase/types" import { object } from "./utils" import Resource from "./utils/Resource" @@ -27,7 +27,7 @@ const table = { const baseColumnDef = { type: { type: "string", - enum: Object.values(FieldTypes), + enum: Object.values(FieldType), description: "Defines the type of the column, most explain themselves, a link column is a relationship.", }, @@ -81,7 +81,7 @@ const tableSchema = { ...baseColumnDef, type: { type: "string", - enum: [FieldTypes.LINK], + enum: [FieldType.LINK], description: "A relationship column.", }, fieldName: { @@ -128,7 +128,7 @@ const tableSchema = { ...baseColumnDef, type: { type: "string", - enum: [FieldTypes.FORMULA], + enum: [FieldType.FORMULA], description: "A formula column.", }, formula: { @@ -138,7 +138,7 @@ const tableSchema = { }, formulaType: { type: "string", - enum: Object.values(FormulaTypes), + enum: Object.values(FormulaType), description: "Defines whether this is a static or dynamic formula.", }, diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index 7c98fecb9b..b7dc02c0db 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -1,4 +1,5 @@ import { + AutoFieldSubType, AutoReason, Datasource, FieldSchema, @@ -27,7 +28,6 @@ import { isSQL, } from "../../../integrations/utils" import { getDatasourceAndQuery } from "../../../sdk/app/rows/utils" -import { AutoFieldSubTypes, FieldTypes } from "../../../constants" import { processObjectSync } from "@budibase/string-templates" import { cloneDeep } from "lodash/fp" import { processDates, processFormulas } from "../../../utilities/rowProcessor" @@ -111,10 +111,10 @@ function buildFilters( */ function cleanupConfig(config: RunConfig, table: Table): RunConfig { const primaryOptions = [ - FieldTypes.STRING, - FieldTypes.LONGFORM, - FieldTypes.OPTIONS, - FieldTypes.NUMBER, + FieldType.STRING, + FieldType.LONGFORM, + FieldType.OPTIONS, + FieldType.NUMBER, ] // filter out fields which cannot be keys const fieldNames = Object.entries(table.schema) @@ -241,10 +241,7 @@ function basicProcessing({ function fixArrayTypes(row: Row, table: Table) { for (let [fieldName, schema] of Object.entries(table.schema)) { - if ( - schema.type === FieldTypes.ARRAY && - typeof row[fieldName] === "string" - ) { + if (schema.type === FieldType.ARRAY && typeof row[fieldName] === "string") { try { row[fieldName] = JSON.parse(row[fieldName]) } catch (err) { @@ -274,8 +271,8 @@ function isEditableColumn(column: FieldSchema) { const isExternalAutoColumn = column.autocolumn && column.autoReason !== AutoReason.FOREIGN_KEY && - column.subtype !== AutoFieldSubTypes.AUTO_ID - const isFormula = column.type === FieldTypes.FORMULA + column.subtype !== AutoFieldSubType.AUTO_ID + const isFormula = column.type === FieldType.FORMULA return !(isExternalAutoColumn || isFormula) } @@ -322,11 +319,11 @@ export class ExternalRequest { continue } // 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]) } // if its not a link then just copy it over - if (field.type !== FieldTypes.LINK) { + if (field.type !== FieldType.LINK) { newRow[key] = row[key] continue } @@ -532,7 +529,7 @@ export class ExternalRequest { buildRelationships(table: Table): RelationshipsJson[] { const relationships = [] for (let [fieldName, field] of Object.entries(table.schema)) { - if (field.type !== FieldTypes.LINK) { + if (field.type !== FieldType.LINK) { continue } const { tableName: linkTableName } = breakExternalTableId(field.tableId) @@ -586,7 +583,7 @@ export class ExternalRequest { // we need this to work out if any relationships need removed for (const field of Object.values(table.schema)) { if ( - field.type !== FieldTypes.LINK || + field.type !== FieldType.LINK || !field.fieldName || isOneSide(field) ) { @@ -730,15 +727,15 @@ export class ExternalRequest { return Object.entries(table.schema) .filter( column => - column[1].type !== FieldTypes.LINK && - column[1].type !== FieldTypes.FORMULA && + column[1].type !== FieldType.LINK && + column[1].type !== FieldType.FORMULA && !existing.find((field: string) => field === column[0]) ) .map(column => `${table.name}.${column[0]}`) } let fields = extractRealFields(table) for (let field of Object.values(table.schema)) { - if (field.type !== FieldTypes.LINK || !includeRelations) { + if (field.type !== FieldType.LINK || !includeRelations) { continue } const { tableName: linkTableName } = breakExternalTableId(field.tableId) diff --git a/packages/server/src/api/controllers/row/external.ts b/packages/server/src/api/controllers/row/external.ts index d741247687..dc3b556c54 100644 --- a/packages/server/src/api/controllers/row/external.ts +++ b/packages/server/src/api/controllers/row/external.ts @@ -1,4 +1,3 @@ -import { FieldTypes } from "../../../constants" import { breakExternalTableId, breakRowIdField, @@ -9,6 +8,7 @@ import { RunConfig, } from "./ExternalRequest" import { + FieldType, Datasource, IncludeRelationship, 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 (let [fieldName, field] of Object.entries(table.schema)) { if ( - field.type !== FieldTypes.LINK || + field.type !== FieldType.LINK || !row[fieldName] || row[fieldName].length === 0 ) { diff --git a/packages/server/src/api/controllers/row/internal.ts b/packages/server/src/api/controllers/row/internal.ts index 5c714c098a..3ee08fff2e 100644 --- a/packages/server/src/api/controllers/row/internal.ts +++ b/packages/server/src/api/controllers/row/internal.ts @@ -6,12 +6,12 @@ import { inputProcessing, outputProcessing, } from "../../../utilities/rowProcessor" -import { FieldTypes } from "../../../constants" import * as utils from "./utils" import { cloneDeep } from "lodash/fp" import { context } from "@budibase/backend-core" import { finaliseRow, updateRelatedFormula } from "./staticFormula" import { + FieldType, LinkDocumentValue, PatchRowRequest, PatchRowResponse, @@ -225,7 +225,7 @@ export async function fetchEnrichedRow(ctx: UserCtx) { // insert the link rows in the correct place throughout the main row for (let fieldName of Object.keys(table.schema)) { let field = table.schema[fieldName] - if (field.type === FieldTypes.LINK) { + if (field.type === FieldType.LINK) { // find the links that pertain to this field const links = linkVals.filter(link => link.fieldName === fieldName) // find the rows that the links state are linked to this field diff --git a/packages/server/src/api/controllers/row/staticFormula.ts b/packages/server/src/api/controllers/row/staticFormula.ts index 3cb7348ee3..0ea8b3560e 100644 --- a/packages/server/src/api/controllers/row/staticFormula.ts +++ b/packages/server/src/api/controllers/row/staticFormula.ts @@ -4,9 +4,15 @@ import { processAutoColumn, processFormulas, } from "../../../utilities/rowProcessor" -import { FieldTypes, FormulaTypes } from "../../../constants" 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 sdk from "../../../sdk" import isEqual from "lodash/isEqual" @@ -35,7 +41,7 @@ export async function updateRelatedFormula( let relatedRows: Record = {} for (let [key, field] of Object.entries(enrichedRow)) { const columnDefinition = table.schema[key] - if (columnDefinition && columnDefinition.type === FieldTypes.LINK) { + if (columnDefinition && columnDefinition.type === FieldType.LINK) { const relatedTableId = columnDefinition.tableId! if (!relatedRows[relatedTableId]) { relatedRows[relatedTableId] = [] @@ -63,8 +69,8 @@ export async function updateRelatedFormula( for (let column of Object.values(relatedTable!.schema)) { // needs updated in related rows if ( - column.type === FieldTypes.FORMULA && - column.formulaType === FormulaTypes.STATIC + column.type === FieldType.FORMULA && + column.formulaType === FormulaType.STATIC ) { // re-enrich rows for all the related, don't update the related formula for them promises = promises.concat( diff --git a/packages/server/src/api/controllers/table/bulkFormula.ts b/packages/server/src/api/controllers/table/bulkFormula.ts index 638a87ebea..060b67e8ce 100644 --- a/packages/server/src/api/controllers/table/bulkFormula.ts +++ b/packages/server/src/api/controllers/table/bulkFormula.ts @@ -1,4 +1,3 @@ -import { FormulaTypes } from "../../../constants" import { clearColumns } from "./utils" import { doesContainStrings } from "@budibase/string-templates" import { cloneDeep } from "lodash/fp" @@ -7,6 +6,7 @@ import uniq from "lodash/uniq" import { updateAllFormulasInTable } from "../row/staticFormula" import { context } from "@budibase/backend-core" import { + FormulaType, FieldSchema, FieldType, FormulaFieldMetadata, @@ -17,10 +17,10 @@ import { isRelationshipColumn } from "../../../db/utils" function isStaticFormula( column: FieldSchema -): column is FormulaFieldMetadata & { formulaType: FormulaTypes.STATIC } { +): column is FormulaFieldMetadata & { formulaType: FormulaType.STATIC } { return ( column.type === FieldType.FORMULA && - column.formulaType === FormulaTypes.STATIC + column.formulaType === FormulaType.STATIC ) } diff --git a/packages/server/src/api/controllers/table/tests/utils.spec.ts b/packages/server/src/api/controllers/table/tests/utils.spec.ts index 931a1cd90f..dad0146696 100644 --- a/packages/server/src/api/controllers/table/tests/utils.spec.ts +++ b/packages/server/src/api/controllers/table/tests/utils.spec.ts @@ -1,5 +1,4 @@ -import { FieldType } from "@budibase/types" -import { AutoFieldSubTypes } from "../../../../constants" +import { AutoFieldSubType, FieldType } from "@budibase/types" import TestConfiguration from "../../../../tests/utilities/TestConfiguration" import { importToRows } from "../utils" @@ -22,7 +21,7 @@ describe("utils", () => { autoId: { name: "autoId", type: FieldType.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, autocolumn: true, constraints: { type: FieldType.NUMBER, @@ -69,7 +68,7 @@ describe("utils", () => { autoId: { name: "autoId", type: FieldType.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, autocolumn: true, constraints: { type: FieldType.NUMBER, diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts index f821801d20..9e1bb59e9d 100644 --- a/packages/server/src/api/controllers/table/utils.ts +++ b/packages/server/src/api/controllers/table/utils.ts @@ -2,8 +2,6 @@ import { parse, isSchema, isRows } from "../../../utilities/schema" import { getRowParams, generateRowID, InternalTables } from "../../../db/utils" import isEqual from "lodash/isEqual" import { - AutoFieldSubTypes, - FieldTypes, GOOGLE_SHEETS_PRIMARY_KEY, USERS_TABLE_SCHEMA, SwitchableTypes, @@ -19,6 +17,7 @@ import { cloneDeep } from "lodash/fp" import { quotas } from "@budibase/pro" import { events, context } from "@budibase/backend-core" import { + AutoFieldSubType, ContextUser, Datasource, Row, @@ -106,7 +105,7 @@ export function makeSureTableUpToDate(table: Table, tableToSave: Table) { for ([field, column] of Object.entries(table.schema)) { if ( column.autocolumn && - column.subtype === AutoFieldSubTypes.AUTO_ID && + column.subtype === AutoFieldSubType.AUTO_ID && tableToSave.schema[field] ) { const tableCol = tableToSave.schema[field] as NumberFieldMetadata @@ -144,8 +143,8 @@ export async function importToRows( ? row[fieldName] : [row[fieldName]] if ( - (schema.type === FieldTypes.OPTIONS || - schema.type === FieldTypes.ARRAY) && + (schema.type === FieldType.OPTIONS || + schema.type === FieldType.ARRAY) && row[fieldName] ) { let merged = [...schema.constraints!.inclusion!, ...rowVal] @@ -403,7 +402,7 @@ export async function checkForViewUpdates( ) const newViewTemplate = viewTemplate( viewMetadata, - groupByField?.type === FieldTypes.ARRAY + groupByField?.type === FieldType.ARRAY ) const viewName = view.name! await saveView(null, viewName, newViewTemplate) @@ -434,7 +433,7 @@ export function generateJunctionTableName( export function foreignKeyStructure(keyName: string, meta?: any) { const structure: any = { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, constraints: {}, name: keyName, } diff --git a/packages/server/src/api/controllers/view/views.ts b/packages/server/src/api/controllers/view/views.ts index 36b89e084d..7eb67f98fc 100644 --- a/packages/server/src/api/controllers/view/views.ts +++ b/packages/server/src/api/controllers/view/views.ts @@ -6,8 +6,8 @@ import { fetchView } from "../row" import { context, events } from "@budibase/backend-core" import { DocumentType } from "../../../db/utils" import sdk from "../../../sdk" -import { FieldTypes } from "../../../constants" import { + FieldType, Ctx, Row, Table, @@ -37,7 +37,7 @@ export async function save(ctx: Ctx) { (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 if (!viewName) { diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 5b39652976..37ff599557 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -6,11 +6,11 @@ import * as setup from "./utilities" import { context, InternalTable, roles, tenancy } from "@budibase/backend-core" import { quotas } from "@budibase/pro" import { - AutoFieldSubTypes, + AutoFieldSubType, FieldSchema, FieldType, FieldTypeSubtypes, - FormulaTypes, + FormulaType, INTERNAL_TABLE_SOURCE_ID, MonthlyQuotaName, PermissionLevel, @@ -192,7 +192,7 @@ describe.each([ "Row ID": { name: "Row ID", type: FieldType.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, icon: "ri-magic-line", autocolumn: true, constraints: { @@ -2032,7 +2032,7 @@ describe.each([ name: "formula", type: FieldType.FORMULA, formula: "{{ links.0.name }}", - formulaType: FormulaTypes.DYNAMIC, + formulaType: FormulaType.DYNAMIC, }, }, } @@ -2086,7 +2086,7 @@ describe.each([ name: "formula", type: FieldType.FORMULA, formula: `{{ js "${js}"}}`, - formulaType: FormulaTypes.DYNAMIC, + formulaType: FormulaType.DYNAMIC, }, }, }) @@ -2129,7 +2129,7 @@ describe.each([ name: "formula", type: FieldType.FORMULA, formula: `{{ js "${js}"}}`, - formulaType: FormulaTypes.DYNAMIC, + formulaType: FormulaType.DYNAMIC, }, }, }) diff --git a/packages/server/src/api/routes/tests/table.spec.ts b/packages/server/src/api/routes/tests/table.spec.ts index 4743bca814..e2bd4c7517 100644 --- a/packages/server/src/api/routes/tests/table.spec.ts +++ b/packages/server/src/api/routes/tests/table.spec.ts @@ -1,6 +1,6 @@ import { context, events } from "@budibase/backend-core" import { - AutoFieldSubTypes, + AutoFieldSubType, FieldSubtype, FieldType, INTERNAL_TABLE_SOURCE_ID, @@ -205,7 +205,7 @@ describe("/tables", () => { autoId: { name: "id", type: FieldType.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, autocolumn: true, constraints: { type: "number", diff --git a/packages/server/src/automations/steps/queryRows.ts b/packages/server/src/automations/steps/queryRows.ts index cde2d8fd5d..f3db410d8c 100644 --- a/packages/server/src/automations/steps/queryRows.ts +++ b/packages/server/src/automations/steps/queryRows.ts @@ -1,9 +1,9 @@ import * as rowController from "../../api/controllers/row" import * as tableController from "../../api/controllers/table" -import { FieldTypes } from "../../constants" import { buildCtx } from "./utils" import * as automationUtils from "../automationUtils" import { + FieldType, AutomationActionStepId, AutomationCustomIOType, AutomationFeature, @@ -115,7 +115,7 @@ function typeCoercion(filters: SearchFilters, table: Table) { if (!column || typeof value !== "string") { continue } - if (column.type === FieldTypes.NUMBER) { + if (column.type === FieldType.NUMBER) { if (key === "oneOf") { searchParam[property] = value .split(",") @@ -148,11 +148,11 @@ export async function run({ inputs, appId }: AutomationStepInput) { } } const table = await getTable(appId, tableId) - let sortType = FieldTypes.STRING + let sortType = FieldType.STRING if (table && table.schema && table.schema[sortColumn] && sortColumn) { const fieldType = table.schema[sortColumn].type sortType = - fieldType === FieldTypes.NUMBER ? FieldTypes.NUMBER : FieldTypes.STRING + fieldType === FieldType.NUMBER ? FieldType.NUMBER : FieldType.STRING } const ctx: any = buildCtx(appId, null, { params: { diff --git a/packages/server/src/constants/index.ts b/packages/server/src/constants/index.ts index fb5c42e7b8..49f1d01afb 100644 --- a/packages/server/src/constants/index.ts +++ b/packages/server/src/constants/index.ts @@ -1,18 +1,11 @@ import { constants, objectStore, roles } from "@budibase/backend-core" import { - FieldType as FieldTypes, + FieldType, INTERNAL_TABLE_SOURCE_ID, Table, TableSourceType, } from "@budibase/types" -export { - FieldType as FieldTypes, - RelationshipType, - AutoFieldSubTypes, - FormulaTypes, -} from "@budibase/types" - export enum FilterTypes { STRING = "string", FUZZY = "fuzzy", @@ -36,14 +29,14 @@ export const NoEmptyFilterStrings = [ ] export const CanSwitchTypes = [ - [FieldTypes.JSON, FieldTypes.ARRAY], + [FieldType.JSON, FieldType.ARRAY], [ - FieldTypes.STRING, - FieldTypes.OPTIONS, - FieldTypes.LONGFORM, - FieldTypes.BARCODEQR, + FieldType.STRING, + FieldType.OPTIONS, + FieldType.LONGFORM, + FieldType.BARCODEQR, ], - [FieldTypes.BOOLEAN, FieldTypes.NUMBER], + [FieldType.BOOLEAN, FieldType.NUMBER], ] export const SwitchableTypes = CanSwitchTypes.reduce((prev, current) => @@ -86,9 +79,9 @@ export const USERS_TABLE_SCHEMA: Table = { // TODO: ADMIN PANEL - when implemented this doesn't need to be carried out schema: { email: { - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, email: true, length: { maximum: "", @@ -99,34 +92,34 @@ export const USERS_TABLE_SCHEMA: Table = { }, firstName: { name: "firstName", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, presence: false, }, }, lastName: { name: "lastName", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, presence: false, }, }, roleId: { name: "roleId", - type: FieldTypes.OPTIONS, + type: FieldType.OPTIONS, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, presence: false, inclusion: Object.values(roles.BUILTIN_ROLE_IDS), }, }, status: { name: "status", - type: FieldTypes.OPTIONS, + type: FieldType.OPTIONS, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, presence: false, inclusion: Object.values(constants.UserStatus), }, diff --git a/packages/server/src/db/defaultData/datasource_bb_default.ts b/packages/server/src/db/defaultData/datasource_bb_default.ts index b430f9ffb6..ac540cd8fc 100644 --- a/packages/server/src/db/defaultData/datasource_bb_default.ts +++ b/packages/server/src/db/defaultData/datasource_bb_default.ts @@ -1,6 +1,4 @@ import { - AutoFieldSubTypes, - FieldTypes, DEFAULT_BB_DATASOURCE_ID, DEFAULT_INVENTORY_TABLE_ID, DEFAULT_EMPLOYEE_TABLE_ID, @@ -16,6 +14,7 @@ import { jobsImport } from "./jobsImport" import { expensesImport } from "./expensesImport" import { db as dbCore } from "@budibase/backend-core" import { + AutoFieldSubType, FieldType, RelationshipType, Row, @@ -40,7 +39,7 @@ function syncLastIds(table: Table, rowCount: number) { if ( entry.autocolumn && entry.type === FieldType.NUMBER && - entry.subtype == AutoFieldSubTypes.AUTO_ID + entry.subtype == AutoFieldSubType.AUTO_ID ) { entry.lastID = rowCount } @@ -58,12 +57,12 @@ async function tableImport(table: Table, data: Row[]) { const AUTO_COLUMNS: TableSchema = { "Created At": { name: "Created At", - type: FieldTypes.DATETIME, - subtype: AutoFieldSubTypes.CREATED_AT, + type: FieldType.DATETIME, + subtype: AutoFieldSubType.CREATED_AT, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -74,12 +73,12 @@ const AUTO_COLUMNS: TableSchema = { }, "Updated At": { name: "Updated At", - type: FieldTypes.DATETIME, - subtype: AutoFieldSubTypes.UPDATED_AT, + type: FieldType.DATETIME, + subtype: AutoFieldSubType.UPDATED_AT, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -101,12 +100,12 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { schema: { "Item ID": { name: "Item ID", - type: FieldTypes.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: false, numericality: { greaterThanOrEqualTo: "", @@ -115,9 +114,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { }, }, "Item Name": { - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: { maximum: null, }, @@ -128,9 +127,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { name: "Item Name", }, "Item Tags": { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: { allowEmpty: false, }, @@ -140,9 +139,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { sortable: false, }, Notes: { - type: FieldTypes.LONGFORM, + type: FieldType.LONGFORM, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, @@ -150,9 +149,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { useRichText: null, }, Status: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: { allowEmpty: false, }, @@ -162,18 +161,18 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { sortable: false, }, SKU: { - type: FieldTypes.BARCODEQR, + type: FieldType.BARCODEQR, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, name: "SKU", }, "Purchase Date": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -185,9 +184,9 @@ export const DEFAULT_INVENTORY_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, "Purchase Price": { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: false, numericality: { greaterThanOrEqualTo: null, @@ -211,75 +210,75 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = { schema: { "First Name": { name: "First Name", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, "Last Name": { name: "Last Name", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, Email: { name: "Email", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, Address: { name: "Address", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, City: { name: "City", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, Postcode: { name: "Postcode", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, Phone: { name: "Phone", - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, }, "EMPLOYEE ID": { name: "EMPLOYEE ID", - type: FieldTypes.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: false, numericality: { greaterThanOrEqualTo: "", @@ -288,9 +287,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = { }, }, "Employee Level": { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: false, inclusion: ["Manager", "Junior", "Senior", "Apprentice", "Contractor"], }, @@ -298,18 +297,18 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = { sortable: false, }, "Badge Photo": { - type: FieldTypes.ATTACHMENT, + type: FieldType.ATTACHMENT, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: false, }, name: "Badge Photo", sortable: false, }, Jobs: { - type: FieldTypes.LINK, + type: FieldType.LINK, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: false, }, fieldName: "Assigned", @@ -318,9 +317,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = { tableId: DEFAULT_JOBS_TABLE_ID, }, "Start Date": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -332,9 +331,9 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, "End Date": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -359,12 +358,12 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { schema: { "Job ID": { name: "Job ID", - type: FieldTypes.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: false, numericality: { greaterThanOrEqualTo: "", @@ -373,9 +372,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { }, }, "Quote Date": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: { allowEmpty: false, @@ -389,9 +388,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, "Quote Price": { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: { allowEmpty: false, }, @@ -403,9 +402,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { name: "Quote Price", }, "Works Start": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -417,9 +416,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, Address: { - type: FieldTypes.LONGFORM, + type: FieldType.LONGFORM, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, @@ -427,9 +426,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { useRichText: null, }, "Customer Name": { - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: { maximum: null, }, @@ -438,9 +437,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { name: "Customer Name", }, Notes: { - type: FieldTypes.LONGFORM, + type: FieldType.LONGFORM, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, @@ -448,9 +447,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { useRichText: null, }, "Customer Phone": { - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: { maximum: null, }, @@ -459,9 +458,9 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { name: "Customer Phone", }, "Customer Email": { - type: FieldTypes.STRING, + type: FieldType.STRING, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: { maximum: null, }, @@ -471,14 +470,14 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { }, Assigned: { name: "Assigned", - type: FieldTypes.LINK, + type: FieldType.LINK, tableId: DEFAULT_EMPLOYEE_TABLE_ID, fieldName: "Jobs", relationshipType: RelationshipType.MANY_TO_MANY, // sortable: true, }, "Works End": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { type: "string", length: {}, @@ -492,7 +491,7 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, "Updated Price": { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, constraints: { type: "number", presence: false, @@ -518,12 +517,12 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { schema: { "Expense ID": { name: "Expense ID", - type: FieldTypes.NUMBER, - subtype: AutoFieldSubTypes.AUTO_ID, + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, icon: "ri-magic-line", autocolumn: true, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: false, numericality: { greaterThanOrEqualTo: "", @@ -532,9 +531,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { }, }, "Expense Tags": { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: { allowEmpty: false, }, @@ -554,9 +553,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { sortable: false, }, Cost: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, constraints: { - type: FieldTypes.NUMBER, + type: FieldType.NUMBER, presence: { allowEmpty: false, }, @@ -568,9 +567,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { name: "Cost", }, Notes: { - type: FieldTypes.LONGFORM, + type: FieldType.LONGFORM, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, }, @@ -578,9 +577,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { useRichText: null, }, "Payment Due": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -592,9 +591,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, "Date Paid": { - type: FieldTypes.DATETIME, + type: FieldType.DATETIME, constraints: { - type: FieldTypes.STRING, + type: FieldType.STRING, length: {}, presence: false, datetime: { @@ -606,9 +605,9 @@ export const DEFAULT_EXPENSES_TABLE_SCHEMA: Table = { ignoreTimezones: true, }, Attachment: { - type: FieldTypes.ATTACHMENT, + type: FieldType.ATTACHMENT, constraints: { - type: FieldTypes.ARRAY, + type: FieldType.ARRAY, presence: false, }, name: "Attachment", diff --git a/packages/server/src/db/linkedRows/LinkController.ts b/packages/server/src/db/linkedRows/LinkController.ts index a7de3ff8d8..ffc9e32fde 100644 --- a/packages/server/src/db/linkedRows/LinkController.ts +++ b/packages/server/src/db/linkedRows/LinkController.ts @@ -1,6 +1,5 @@ import { IncludeDocs, getLinkDocuments } from "./linkUtils" import { InternalTables, getUserMetadataParams } from "../utils" -import { FieldTypes } from "../../constants" import { context, logging } from "@budibase/backend-core" import LinkDocument from "./LinkDocument" import { @@ -62,7 +61,7 @@ class LinkController { } for (let fieldName of Object.keys(table.schema)) { const { type } = table.schema[fieldName] - if (type === FieldTypes.LINK) { + if (type === FieldType.LINK) { return true } } @@ -96,7 +95,7 @@ class LinkController { validateTable(table: Table) { const usedAlready = [] for (let schema of Object.values(table.schema)) { - if (schema.type !== FieldTypes.LINK) { + if (schema.type !== FieldType.LINK) { continue } const unique = schema.tableId! + schema?.fieldName @@ -172,7 +171,7 @@ class LinkController { // get the links this row wants to make const rowField = row[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 const thisFieldLinkDocs = linkDocs.filter( linkDoc => @@ -353,7 +352,7 @@ class LinkController { const schema = table.schema for (let fieldName of Object.keys(schema)) { 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 // the put to bubble up as an error, if can't update // table for some reason @@ -366,7 +365,7 @@ class LinkController { } const fields = this.handleRelationshipType(field, { name: field.fieldName, - type: FieldTypes.LINK, + type: FieldType.LINK, // these are the props of the table that initiated the link tableId: table._id!, fieldName: fieldName, @@ -413,10 +412,7 @@ class LinkController { for (let fieldName of Object.keys(oldTable?.schema || {})) { const field = oldTable?.schema[fieldName] as FieldSchema // this field has been removed from the table schema - if ( - field.type === FieldTypes.LINK && - newTable.schema[fieldName] == null - ) { + if (field.type === FieldType.LINK && newTable.schema[fieldName] == null) { await this.removeFieldFromTable(fieldName) } } @@ -437,7 +433,7 @@ class LinkController { for (let fieldName of Object.keys(schema)) { const field = schema[fieldName] try { - if (field.type === FieldTypes.LINK && field.fieldName) { + if (field.type === FieldType.LINK && field.fieldName) { const linkedTable = await this._db.get(field.tableId) delete linkedTable.schema[field.fieldName] field.tableRev = (await this._db.put(linkedTable)).rev diff --git a/packages/server/src/db/linkedRows/LinkDocument.ts b/packages/server/src/db/linkedRows/LinkDocument.ts index 234f43cb48..59dc758c4c 100644 --- a/packages/server/src/db/linkedRows/LinkDocument.ts +++ b/packages/server/src/db/linkedRows/LinkDocument.ts @@ -1,6 +1,5 @@ import { generateLinkID } from "../utils" -import { FieldTypes } from "../../constants" -import { LinkDocument } from "@budibase/types" +import { FieldType, LinkDocument } from "@budibase/types" /** * 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, fieldName2 ) - this.type = FieldTypes.LINK + this.type = FieldType.LINK this.doc1 = { tableId: tableId1, fieldName: fieldName1, diff --git a/packages/server/src/db/linkedRows/linkUtils.ts b/packages/server/src/db/linkedRows/linkUtils.ts index 20f752407f..a999871939 100644 --- a/packages/server/src/db/linkedRows/linkUtils.ts +++ b/packages/server/src/db/linkedRows/linkUtils.ts @@ -1,8 +1,8 @@ import { ViewName, getQueryIndex, isRelationshipColumn } from "../utils" -import { FieldTypes } from "../../constants" import { createLinkView } from "../views/staticViews" import { context, logging } from "@budibase/backend-core" import { + FieldType, DatabaseQueryOpts, LinkDocument, LinkDocumentValue, @@ -131,11 +131,11 @@ export async function getLinkedTable(id: string, tables: Table[]) { export function getRelatedTableForField(table: Table, fieldName: string) { // look to see if its on the table, straight in the schema const field = table.schema[fieldName] - if (field?.type === FieldTypes.LINK) { + if (field?.type === FieldType.LINK) { return field.tableId } 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 } } diff --git a/packages/server/src/db/tests/linkController.spec.js b/packages/server/src/db/tests/linkController.spec.ts similarity index 72% rename from packages/server/src/db/tests/linkController.spec.js rename to packages/server/src/db/tests/linkController.spec.ts index 313cfee837..7f575c7974 100644 --- a/packages/server/src/db/tests/linkController.spec.js +++ b/packages/server/src/db/tests/linkController.spec.ts @@ -1,17 +1,57 @@ -const TestConfig = require("../../tests/utilities/TestConfiguration") -const { - basicRow, +import TestConfig from "../../tests/utilities/TestConfiguration" +import { basicLinkedRow, + basicRow, basicTable, -} = require("../../tests/utilities/structures") -const LinkController = require("../linkedRows/LinkController").default -const { context } = require("@budibase/backend-core") -const { RelationshipType } = require("../../constants") -const { cloneDeep } = require("lodash/fp") +} from "../../tests/utilities/structures" +import LinkController from "../linkedRows/LinkController" +import { context } from "@budibase/backend-core" +import { + FieldType, + ManyToManyRelationshipFieldMetadata, + ManyToOneRelationshipFieldMetadata, + OneToManyRelationshipFieldMetadata, + RelationshipFieldMetadata, + RelationshipType, + Row, + Table, +} from "@budibase/types" +import { cloneDeep } from "lodash" + +const baseColumn = { + type: FieldType.LINK, + fieldName: "", + tableId: "", + name: "", +} + +function mockManyToManyColumn(): ManyToManyRelationshipFieldMetadata { + return { + ...baseColumn, + through: "", + throughFrom: "", + throughTo: "", + relationshipType: RelationshipType.MANY_TO_MANY, + } +} + +function mockManyToOneColumn(): ManyToOneRelationshipFieldMetadata { + return { + ...baseColumn, + relationshipType: RelationshipType.MANY_TO_ONE, + } +} + +function mockOneToManyColumn(): OneToManyRelationshipFieldMetadata { + return { + ...baseColumn, + relationshipType: RelationshipType.ONE_TO_MANY, + } +} describe("test the link controller", () => { let config = new TestConfig() - let table1, table2, appId + let table1: Table, table2: Table, appId: string beforeAll(async () => { const app = await config.init() @@ -30,9 +70,18 @@ describe("test the link controller", () => { afterAll(config.end) - async function createLinkController(table, row = null, oldTable = null) { + async function createLinkController( + table: Table, + row?: Row, + oldTable?: Table + ) { return context.doInAppContext(appId, () => { - const linkConfig = { + const linkConfig: { + tableId?: string + table: Table + row?: Row + oldTable?: Table + } = { tableId: table._id, table, } @@ -47,11 +96,11 @@ describe("test the link controller", () => { } async function createLinkedRow(linkField = "link", t1 = table1, t2 = table2) { - const row = await config.createRow(basicRow(t2._id)) + const row = await config.createRow(basicRow(t2._id!)) const { _id } = await config.createRow( - basicLinkedRow(t1._id, row._id, linkField) + basicLinkedRow(t1._id!, row._id!, linkField) ) - return config.getRow(t1._id, _id) + return config.getRow(t1._id!, _id!) } it("should be able to confirm if two table schemas are equal", async () => { @@ -71,6 +120,7 @@ describe("test the link controller", () => { it("should be able to check the relationship types across two fields", async () => { const controller = await createLinkController(table1) // empty case + //@ts-ignore let output = controller.handleRelationshipType({}, {}) expect(output.linkedField.relationshipType).toEqual( RelationshipType.MANY_TO_MANY @@ -79,8 +129,8 @@ describe("test the link controller", () => { RelationshipType.MANY_TO_MANY ) output = controller.handleRelationshipType( - { relationshipType: RelationshipType.MANY_TO_MANY }, - {} + mockManyToManyColumn(), + {} as any ) expect(output.linkedField.relationshipType).toEqual( RelationshipType.MANY_TO_MANY @@ -88,20 +138,14 @@ describe("test the link controller", () => { expect(output.linkerField.relationshipType).toEqual( RelationshipType.MANY_TO_MANY ) - output = controller.handleRelationshipType( - { relationshipType: RelationshipType.MANY_TO_ONE }, - {} - ) + output = controller.handleRelationshipType(mockManyToOneColumn(), {} as any) expect(output.linkedField.relationshipType).toEqual( RelationshipType.ONE_TO_MANY ) expect(output.linkerField.relationshipType).toEqual( RelationshipType.MANY_TO_ONE ) - output = controller.handleRelationshipType( - { relationshipType: RelationshipType.ONE_TO_MANY }, - {} - ) + output = controller.handleRelationshipType(mockOneToManyColumn(), {} as any) expect(output.linkedField.relationshipType).toEqual( RelationshipType.MANY_TO_ONE ) @@ -115,16 +159,16 @@ describe("test the link controller", () => { const controller = await createLinkController(table1, row) await context.doInAppContext(appId, async () => { // get initial count - const beforeLinks = await controller.getRowLinkDocs(row._id) + const beforeLinks = await controller.getRowLinkDocs(row._id!) await controller.rowDeleted() - let afterLinks = await controller.getRowLinkDocs(row._id) + let afterLinks = await controller.getRowLinkDocs(row._id!) expect(beforeLinks.length).toEqual(1) expect(afterLinks.length).toEqual(0) }) }) it("shouldn't throw an error when deleting a row with no links", async () => { - const row = await config.createRow(basicRow(table1._id)) + const row = await config.createRow(basicRow(table1._id!)) const controller = await createLinkController(table1, row) await context.doInAppContext(appId, async () => { let error @@ -142,12 +186,13 @@ describe("test the link controller", () => { const copyTable = { ...table1, } + //@ts-ignore copyTable.schema.otherTableLink = { - type: "link", + type: FieldType.LINK, fieldName: "link", - tableId: table2._id, + tableId: table2._id!, } - let error + let error: any try { controller.validateTable(copyTable) } catch (err) { @@ -166,7 +211,7 @@ describe("test the link controller", () => { const controller = await createLinkController(table1, row) await context.doInAppContext(appId, async () => { await controller.rowSaved() - let links = await controller.getRowLinkDocs(row._id) + let links = await controller.getRowLinkDocs(row._id!) expect(links.length).toEqual(0) }) }) @@ -186,7 +231,7 @@ describe("test the link controller", () => { it("should be able to remove a linked field from a table", async () => { await createLinkedRow() await createLinkedRow("link2") - const controller = await createLinkController(table1, null, table1) + const controller = await createLinkController(table1, undefined, table1) await context.doInAppContext(appId, async () => { let before = await controller.getTableLinkDocs() await controller.removeFieldFromTable("link") @@ -199,7 +244,8 @@ describe("test the link controller", () => { it("should throw an error when overwriting a link column", async () => { const update = cloneDeep(table1) - update.schema.link.relationshipType = RelationshipType.MANY_TO_ONE + const linkSchema = update.schema.link as ManyToOneRelationshipFieldMetadata + linkSchema.relationshipType = RelationshipType.MANY_TO_ONE let error try { const controller = await createLinkController(update) @@ -215,7 +261,7 @@ describe("test the link controller", () => { await createLinkedRow() const newTable = cloneDeep(table1) delete newTable.schema.link - const controller = await createLinkController(newTable, null, table1) + const controller = await createLinkController(newTable, undefined, table1) await context.doInAppContext(appId, async () => { await controller.tableUpdated() const links = await controller.getTableLinkDocs() @@ -235,7 +281,7 @@ describe("test the link controller", () => { let error try { // create another row to initiate the error - await config.createRow(basicLinkedRow(row.tableId, row.link[0])) + await config.createRow(basicLinkedRow(row.tableId!, row.link[0])) } catch (err) { error = err } @@ -245,7 +291,7 @@ describe("test the link controller", () => { it("should not error if a link being created doesn't exist", async () => { let error try { - await config.createRow(basicLinkedRow(table1._id, "invalid")) + await config.createRow(basicLinkedRow(table1._id!, "invalid")) } catch (err) { error = err } @@ -255,10 +301,11 @@ describe("test the link controller", () => { it("make sure auto column goes onto other row too", async () => { const table = await config.createTable() const tableCfg = basicTable() + //@ts-ignore tableCfg.schema.link = { - type: "link", + type: FieldType.LINK, fieldName: "link", - tableId: table._id, + tableId: table._id!, name: "link", autocolumn: true, } @@ -269,10 +316,11 @@ describe("test the link controller", () => { it("should be able to link to self", async () => { const table = await config.createTable() + //@ts-ignore table.schema.link = { - type: "link", + type: FieldType.LINK, fieldName: "link", - tableId: table._id, + tableId: table._id!, name: "link", autocolumn: true, } @@ -282,8 +330,9 @@ describe("test the link controller", () => { it("should be able to remove a linked field from a table, even if the linked table does not exist", async () => { await createLinkedRow() await createLinkedRow("link2") - table1.schema["link"].tableId = "not_found" - const controller = await createLinkController(table1, null, table1) + const linkSchema = table1.schema["link"] as RelationshipFieldMetadata + linkSchema.tableId = "not_found" + const controller = await createLinkController(table1, undefined, table1) await context.doInAppContext(appId, async () => { let before = await controller.getTableLinkDocs() await controller.removeFieldFromTable("link") diff --git a/packages/server/src/db/tests/linkTests.spec.js b/packages/server/src/db/tests/linkTests.spec.ts similarity index 77% rename from packages/server/src/db/tests/linkTests.spec.js rename to packages/server/src/db/tests/linkTests.spec.ts index 7b3fedb5a9..3dbcb32011 100644 --- a/packages/server/src/db/tests/linkTests.spec.js +++ b/packages/server/src/db/tests/linkTests.spec.ts @@ -1,14 +1,15 @@ -const TestConfig = require("../../tests/utilities/TestConfiguration") -const { basicTable } = require("../../tests/utilities/structures") -const linkUtils = require("../linkedRows/linkUtils") -const { context } = require("@budibase/backend-core") +import TestConfig from "../../tests/utilities/TestConfiguration" +import { basicTable } from "../../tests/utilities/structures" +import * as linkUtils from "../linkedRows/linkUtils" +import { context } from "@budibase/backend-core" +import { FieldType, RelationshipType, Table } from "@budibase/types" describe("test link functionality", () => { const config = new TestConfig() - let appId + let appId: string describe("getLinkedTable", () => { - let table + let table: Table beforeAll(async () => { const app = await config.init() appId = app.appId @@ -17,15 +18,15 @@ describe("test link functionality", () => { it("should be able to retrieve a linked table from a list", async () => { await context.doInAppContext(appId, async () => { - const retrieved = await linkUtils.getLinkedTable(table._id, [table]) + const retrieved = await linkUtils.getLinkedTable(table._id!, [table]) expect(retrieved._id).toBe(table._id) }) }) it("should be able to retrieve a table from DB and update list", async () => { - const tables = [] + const tables: Table[] = [] await context.doInAppContext(appId, async () => { - const retrieved = await linkUtils.getLinkedTable(table._id, tables) + const retrieved = await linkUtils.getLinkedTable(table._id!, tables) expect(retrieved._id).toBe(table._id) expect(tables[0]).toBeDefined() }) @@ -35,9 +36,11 @@ describe("test link functionality", () => { describe("getRelatedTableForField", () => { let link = basicTable() link.schema.link = { + name: "link", + relationshipType: RelationshipType.ONE_TO_MANY, fieldName: "otherLink", tableId: "tableID", - type: "link", + type: FieldType.LINK, } it("should get the field from the table directly", () => { diff --git a/packages/server/src/db/utils.ts b/packages/server/src/db/utils.ts index 1712563085..35d9b69e96 100644 --- a/packages/server/src/db/utils.ts +++ b/packages/server/src/db/utils.ts @@ -1,6 +1,7 @@ import newid from "./newid" import { db as dbCore } from "@budibase/backend-core" import { + FieldType, DocumentType, FieldSchema, RelationshipFieldMetadata, @@ -8,7 +9,6 @@ import { INTERNAL_TABLE_SOURCE_ID, DatabaseQueryOpts, } from "@budibase/types" -import { FieldTypes } from "../constants" export { DocumentType, VirtualDocumentType } from "@budibase/types" @@ -315,5 +315,5 @@ export function extractViewInfoFromID(viewId: string) { export function isRelationshipColumn( column: FieldSchema ): column is RelationshipFieldMetadata { - return column.type === FieldTypes.LINK + return column.type === FieldType.LINK } diff --git a/packages/server/src/integrations/base/sqlTable.ts b/packages/server/src/integrations/base/sqlTable.ts index 1d3f542a10..f553690b23 100644 --- a/packages/server/src/integrations/base/sqlTable.ts +++ b/packages/server/src/integrations/base/sqlTable.ts @@ -1,5 +1,6 @@ import { Knex, knex } from "knex" import { + RelationshipType, FieldSubtype, NumberFieldMetadata, Operation, @@ -11,7 +12,6 @@ import { import { breakExternalTableId } from "../utils" import SchemaBuilder = Knex.SchemaBuilder import CreateTableBuilder = Knex.CreateTableBuilder -import { RelationshipType } from "../../constants" import { utils } from "@budibase/shared-core" function isIgnoredType(type: FieldType) { diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index e9a2dc7998..cf76622581 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -1,4 +1,5 @@ import { + FieldType, DatasourceFieldType, Integration, Operation, @@ -21,7 +22,6 @@ import { SqlClient, } from "./utils" import Sql from "./base/sql" -import { FieldTypes } from "../constants" import { BindParameters, Connection, @@ -302,7 +302,7 @@ class OracleIntegration extends Sql implements DatasourcePlus { }) if (this.isBooleanType(oracleColumn)) { - fieldSchema.type = FieldTypes.BOOLEAN + fieldSchema.type = FieldType.BOOLEAN } table.schema[columnName] = fieldSchema diff --git a/packages/server/src/sdk/app/rows/attachments.ts b/packages/server/src/sdk/app/rows/attachments.ts index bd04f64146..2ab9e83c47 100644 --- a/packages/server/src/sdk/app/rows/attachments.ts +++ b/packages/server/src/sdk/app/rows/attachments.ts @@ -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 { DocumentType, SEPARATOR } from "../../../db/utils" -import { FieldTypes } from "../../../constants" // default limit - seems to work well for performance export const FIND_LIMIT = 25 @@ -31,7 +30,7 @@ export async function getRowsWithAttachments(appId: string, table: Table) { const db = dbCore.getDB(appId) const attachmentCols: string[] = [] for (let [key, column] of Object.entries(table.schema)) { - if (column.type === FieldTypes.ATTACHMENT) { + if (column.type === FieldType.ATTACHMENT) { attachmentCols.push(key) } } diff --git a/packages/server/src/sdk/app/rows/tests/internal.spec.ts b/packages/server/src/sdk/app/rows/tests/internal.spec.ts index b60d31b226..f472608ca0 100644 --- a/packages/server/src/sdk/app/rows/tests/internal.spec.ts +++ b/packages/server/src/sdk/app/rows/tests/internal.spec.ts @@ -7,7 +7,7 @@ import { TableSourceType, FieldType, Table, - AutoFieldSubTypes, + AutoFieldSubType, } from "@budibase/types" import TestConfiguration from "../../../../tests/utilities/TestConfiguration" @@ -117,7 +117,7 @@ describe("sdk >> rows >> internal", () => { id: { name: "id", type: FieldType.AUTO, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, autocolumn: true, lastID: 0, }, @@ -181,7 +181,7 @@ describe("sdk >> rows >> internal", () => { id: { name: "id", type: FieldType.AUTO, - subtype: AutoFieldSubTypes.AUTO_ID, + subtype: AutoFieldSubType.AUTO_ID, autocolumn: true, lastID: 0, }, diff --git a/packages/server/src/sdk/app/rows/utils.ts b/packages/server/src/sdk/app/rows/utils.ts index d0227c7c6b..14868a4013 100644 --- a/packages/server/src/sdk/app/rows/utils.ts +++ b/packages/server/src/sdk/app/rows/utils.ts @@ -1,7 +1,6 @@ import cloneDeep from "lodash/cloneDeep" import validateJs from "validate.js" -import { Row, Table, TableSchema } from "@budibase/types" -import { FieldTypes } from "../../../constants" +import { FieldType, Row, Table, TableSchema } from "@budibase/types" import { makeExternalQuery } from "../../../integrations/base/query" import { Format } from "../../../api/controllers/view/exporters" import sdk from "../.." @@ -22,7 +21,7 @@ export function cleanExportRows( let cleanRows = [...rows] 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]) relationships.forEach(column => { @@ -88,17 +87,17 @@ export async function validate({ continue } // formulas shouldn't validated, data will be deleted anyway - if (type === FieldTypes.FORMULA || column.autocolumn) { + if (type === FieldType.FORMULA || column.autocolumn) { continue } // 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, "") } let res // 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 (!Array.isArray(row[fieldName])) { row[fieldName] = row[fieldName].split(",") @@ -116,13 +115,13 @@ export async function validate({ errors[fieldName] = [`${fieldName} is required`] } } else if ( - (type === FieldTypes.ATTACHMENT || type === FieldTypes.JSON) && + (type === FieldType.ATTACHMENT || type === FieldType.JSON) && typeof row[fieldName] === "string" ) { // this should only happen if there is an error try { const json = JSON.parse(row[fieldName]) - if (type === FieldTypes.ATTACHMENT) { + if (type === FieldType.ATTACHMENT) { if (Array.isArray(json)) { row[fieldName] = json } else { diff --git a/packages/server/src/sdk/app/tables/external/index.ts b/packages/server/src/sdk/app/tables/external/index.ts index 157a683ad0..9a2bed0da2 100644 --- a/packages/server/src/sdk/app/tables/external/index.ts +++ b/packages/server/src/sdk/app/tables/external/index.ts @@ -1,4 +1,5 @@ import { + FieldType, Operation, RelationshipType, RenameColumn, @@ -14,7 +15,6 @@ import { setStaticSchemas, } from "../../../../api/controllers/table/utils" import { cloneDeep } from "lodash/fp" -import { FieldTypes } from "../../../../constants" import { makeTableRequest } from "../../../../api/controllers/table/ExternalRequest" import { isRelationshipSetup, @@ -78,7 +78,7 @@ export async function save( // check if relations need setup for (let schema of Object.values(tableToSave.schema)) { - if (schema.type !== FieldTypes.LINK || isRelationshipSetup(schema)) { + if (schema.type !== FieldType.LINK || isRelationshipSetup(schema)) { continue } const schemaTableId = schema.tableId diff --git a/packages/server/src/sdk/app/tables/external/utils.ts b/packages/server/src/sdk/app/tables/external/utils.ts index 50ea98eb39..321bd990f5 100644 --- a/packages/server/src/sdk/app/tables/external/utils.ts +++ b/packages/server/src/sdk/app/tables/external/utils.ts @@ -9,7 +9,6 @@ import { Table, TableSourceType, } from "@budibase/types" -import { FieldTypes } from "../../../../constants" import { foreignKeyStructure, generateForeignKey, @@ -27,7 +26,7 @@ export function cleanupRelationships( // clean up relationships in couch table schemas for (let [key, schema] of Object.entries(tableToIterate.schema)) { if ( - schema.type === FieldTypes.LINK && + schema.type === FieldType.LINK && (!oldTable || table.schema[key] == null) ) { const schemaTableId = schema.tableId diff --git a/packages/server/src/sdk/app/tables/internal/index.ts b/packages/server/src/sdk/app/tables/internal/index.ts index 4da90e211d..25fe145484 100644 --- a/packages/server/src/sdk/app/tables/internal/index.ts +++ b/packages/server/src/sdk/app/tables/internal/index.ts @@ -1,4 +1,5 @@ import { + FieldType, RenameColumn, Table, ViewStatisticsSchema, @@ -10,7 +11,6 @@ import { hasTypeChanged, TableSaveFunctions, } from "../../../../api/controllers/table/utils" -import { FieldTypes } from "../../../../constants" import { EventType, updateLinks } from "../../../../db/linkedRows" import { cloneDeep } from "lodash/fp" import isEqual from "lodash/isEqual" @@ -63,7 +63,7 @@ export async function save( } // 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.") } diff --git a/packages/server/src/utilities/rowProcessor/attachments.ts b/packages/server/src/utilities/rowProcessor/attachments.ts index 3b670cbc05..799eab1d3a 100644 --- a/packages/server/src/utilities/rowProcessor/attachments.ts +++ b/packages/server/src/utilities/rowProcessor/attachments.ts @@ -1,6 +1,12 @@ -import { FieldTypes, ObjectStoreBuckets } from "../../constants" +import { ObjectStoreBuckets } from "../../constants" 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 { static async coreCleanup(fileListFn: () => string[]): Promise { @@ -28,7 +34,7 @@ export class AttachmentCleanup { let files: string[] = [] const tableSchema = opts.oldTable?.schema || table.schema for (let [key, schema] of Object.entries(tableSchema)) { - if (schema.type !== FieldTypes.ATTACHMENT) { + if (schema.type !== FieldType.ATTACHMENT) { continue } const columnRemoved = opts.oldTable && !table.schema[key] @@ -62,7 +68,7 @@ export class AttachmentCleanup { return AttachmentCleanup.coreCleanup(() => { let files: string[] = [] for (let [key, schema] of Object.entries(table.schema)) { - if (schema.type !== FieldTypes.ATTACHMENT) { + if (schema.type !== FieldType.ATTACHMENT) { continue } rows.forEach(row => { @@ -79,7 +85,7 @@ export class AttachmentCleanup { return AttachmentCleanup.coreCleanup(() => { let files: string[] = [] for (let [key, schema] of Object.entries(table.schema)) { - if (schema.type !== FieldTypes.ATTACHMENT) { + if (schema.type !== FieldType.ATTACHMENT) { continue } const oldKeys = diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 65012d64e1..e3ca576fb7 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -1,10 +1,16 @@ import * as linkRows from "../../db/linkedRows" -import { FieldTypes, AutoFieldSubTypes } from "../../constants" import { processFormulas, fixAutoColumnSubType } from "./utils" import { objectStore, utils } from "@budibase/backend-core" import { InternalTables } from "../../db/utils" 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 { processInputBBReferences, @@ -54,25 +60,25 @@ export function processAutoColumn( schema = fixAutoColumnSubType(schema) } switch (schema.subtype) { - case AutoFieldSubTypes.CREATED_BY: + case AutoFieldSubType.CREATED_BY: if (creating && shouldUpdateUserFields && userId) { row[key] = [userId] } break - case AutoFieldSubTypes.CREATED_AT: + case AutoFieldSubType.CREATED_AT: if (creating) { row[key] = now } break - case AutoFieldSubTypes.UPDATED_BY: + case AutoFieldSubType.UPDATED_BY: if (shouldUpdateUserFields && userId) { row[key] = [userId] } break - case AutoFieldSubTypes.UPDATED_AT: + case AutoFieldSubType.UPDATED_AT: row[key] = now break - case AutoFieldSubTypes.AUTO_ID: + case AutoFieldSubType.AUTO_ID: if (creating) { schema.lastID = !schema.lastID ? BASE_AUTO_ID : schema.lastID + 1 row[key] = schema.lastID @@ -134,7 +140,7 @@ export async function inputProcessing( continue } // remove any formula values, they are to be generated - if (field.type === FieldTypes.FORMULA) { + if (field.type === FieldType.FORMULA) { delete clonedRow[key] } // 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 - if (field.type === FieldTypes.ATTACHMENT) { + if (field.type === FieldType.ATTACHMENT) { const attachments = clonedRow[key] if (attachments?.length) { 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( value, field.subtype as FieldSubtype @@ -214,7 +220,7 @@ export async function outputProcessing( // process complex types: attachements, bb references... for (let [property, column] of Object.entries(table.schema)) { - if (column.type === FieldTypes.ATTACHMENT) { + if (column.type === FieldType.ATTACHMENT) { for (let row of enriched) { if (row[property] == null || !Array.isArray(row[property])) { continue @@ -227,7 +233,7 @@ export async function outputProcessing( } } else if ( !opts.skipBBReferences && - column.type == FieldTypes.BB_REFERENCE + column.type == FieldType.BB_REFERENCE ) { for (let row of enriched) { row[property] = await processOutputBBReferences( diff --git a/packages/server/src/utilities/rowProcessor/map.ts b/packages/server/src/utilities/rowProcessor/map.ts index cbddcaf427..60fe5a001b 100644 --- a/packages/server/src/utilities/rowProcessor/map.ts +++ b/packages/server/src/utilities/rowProcessor/map.ts @@ -1,7 +1,6 @@ -// @ts-nocheck -import { FieldTypes } from "../../constants" +import { FieldType } from "@budibase/types" -const parseArrayString = value => { +const parseArrayString = (value: any) => { if (typeof value === "string") { if (value === "") { 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. */ export const TYPE_TRANSFORM_MAP: any = { - [FieldTypes.LINK]: { + [FieldType.LINK]: { "": [], + //@ts-ignore [null]: [], + //@ts-ignore [undefined]: undefined, - parse: link => { + parse: (link: any) => { if (Array.isArray(link) && typeof link[0] === "object") { return link.map(el => (el && el._id ? el._id : el)) } @@ -35,75 +36,97 @@ export const TYPE_TRANSFORM_MAP: any = { return link }, }, - [FieldTypes.OPTIONS]: { + [FieldType.OPTIONS]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.ARRAY]: { + [FieldType.ARRAY]: { + //@ts-ignore [null]: [], + //@ts-ignore [undefined]: undefined, parse: parseArrayString, }, - [FieldTypes.STRING]: { + [FieldType.STRING]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.BARCODEQR]: { + [FieldType.BARCODEQR]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.FORMULA]: { + [FieldType.FORMULA]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.LONGFORM]: { + [FieldType.LONGFORM]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.NUMBER]: { + [FieldType.NUMBER]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, - parse: n => parseFloat(n), + parse: (n: any) => parseFloat(n), }, - [FieldTypes.BIGINT]: { + [FieldType.BIGINT]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, }, - [FieldTypes.DATETIME]: { + [FieldType.DATETIME]: { "": null, - [undefined]: undefined, + //@ts-ignore [null]: null, - parse: date => { + //@ts-ignore + [undefined]: undefined, + parse: (date: any) => { if (date instanceof Date) { return date.toISOString() } return date }, }, - [FieldTypes.ATTACHMENT]: { + [FieldType.ATTACHMENT]: { + //@ts-ignore [null]: [], + //@ts-ignore [undefined]: undefined, parse: parseArrayString, }, - [FieldTypes.BOOLEAN]: { + [FieldType.BOOLEAN]: { "": null, + //@ts-ignore [null]: null, + //@ts-ignore [undefined]: undefined, true: true, false: false, }, - [FieldTypes.AUTO]: { + [FieldType.AUTO]: { parse: () => undefined, }, - [FieldTypes.JSON]: { - parse: input => { + [FieldType.JSON]: { + parse: (input: any) => { try { if (input === "") { return undefined diff --git a/packages/server/src/utilities/rowProcessor/tests/utils.spec.ts b/packages/server/src/utilities/rowProcessor/tests/utils.spec.ts index 2437fa8864..49dd05910d 100644 --- a/packages/server/src/utilities/rowProcessor/tests/utils.spec.ts +++ b/packages/server/src/utilities/rowProcessor/tests/utils.spec.ts @@ -1,6 +1,11 @@ import { fixAutoColumnSubType } from "../utils" -import { AutoFieldDefaultNames, AutoFieldSubTypes } from "../../../constants" -import { FieldSchema, FieldType, RelationshipType } from "@budibase/types" +import { AutoFieldDefaultNames } from "../../../constants" +import { + AutoFieldSubType, + FieldSchema, + FieldType, + RelationshipType, +} from "@budibase/types" describe("rowProcessor utility", () => { describe("fixAutoColumnSubType", () => { @@ -20,37 +25,37 @@ describe("rowProcessor utility", () => { it("updates the schema with the correct subtype", async () => { schema.name = AutoFieldDefaultNames.CREATED_BY expect(fixAutoColumnSubType(schema).subtype).toEqual( - AutoFieldSubTypes.CREATED_BY + AutoFieldSubType.CREATED_BY ) schema.subtype = undefined schema.name = AutoFieldDefaultNames.UPDATED_BY expect(fixAutoColumnSubType(schema).subtype).toEqual( - AutoFieldSubTypes.UPDATED_BY + AutoFieldSubType.UPDATED_BY ) schema.subtype = undefined schema.name = AutoFieldDefaultNames.CREATED_AT expect(fixAutoColumnSubType(schema).subtype).toEqual( - AutoFieldSubTypes.CREATED_AT + AutoFieldSubType.CREATED_AT ) schema.subtype = undefined schema.name = AutoFieldDefaultNames.UPDATED_AT expect(fixAutoColumnSubType(schema).subtype).toEqual( - AutoFieldSubTypes.UPDATED_AT + AutoFieldSubType.UPDATED_AT ) schema.subtype = undefined schema.name = AutoFieldDefaultNames.AUTO_ID expect(fixAutoColumnSubType(schema).subtype).toEqual( - AutoFieldSubTypes.AUTO_ID + AutoFieldSubType.AUTO_ID ) schema.subtype = undefined }) it("returns the column if subtype exists", async () => { - schema.subtype = AutoFieldSubTypes.CREATED_BY + schema.subtype = AutoFieldSubType.CREATED_BY schema.name = AutoFieldDefaultNames.CREATED_AT expect(fixAutoColumnSubType(schema)).toEqual(schema) }) diff --git a/packages/server/src/utilities/rowProcessor/utils.ts b/packages/server/src/utilities/rowProcessor/utils.ts index cafd366cae..d0fc82b3ee 100644 --- a/packages/server/src/utilities/rowProcessor/utils.ts +++ b/packages/server/src/utilities/rowProcessor/utils.ts @@ -1,15 +1,13 @@ -import { - AutoFieldDefaultNames, - AutoFieldSubTypes, - FieldTypes, - FormulaTypes, -} from "../../constants" +import { AutoFieldDefaultNames } from "../../constants" import { processStringSync } from "@budibase/string-templates" import { AutoColumnFieldMetadata, FieldSchema, Row, Table, + FormulaType, + AutoFieldSubType, + FieldType, } from "@budibase/types" import tracer from "dd-trace" @@ -30,15 +28,15 @@ export function fixAutoColumnSubType( } // the columns which get auto generated 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)) { - column.subtype = AutoFieldSubTypes.UPDATED_BY + column.subtype = AutoFieldSubType.UPDATED_BY } 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)) { - column.subtype = AutoFieldSubTypes.UPDATED_AT + column.subtype = AutoFieldSubType.UPDATED_AT } else if (column.name.endsWith(AutoFieldDefaultNames.AUTO_ID)) { - column.subtype = AutoFieldSubTypes.AUTO_ID + column.subtype = AutoFieldSubType.AUTO_ID } return column } @@ -57,11 +55,11 @@ export function processFormulas( const rows = Array.isArray(inputRows) ? inputRows : [inputRows] if (rows) { for (let [column, schema] of Object.entries(table.schema)) { - if (schema.type !== FieldTypes.FORMULA) { + if (schema.type !== FieldType.FORMULA) { continue } - const isStatic = schema.formulaType === FormulaTypes.STATIC + const isStatic = schema.formulaType === FormulaType.STATIC if ( schema.formula == null || @@ -100,7 +98,7 @@ export function processDates( let rows = Array.isArray(inputRows) ? inputRows : [inputRows] let datesWithTZ: string[] = [] for (let [column, schema] of Object.entries(table.schema)) { - if (schema.type !== FieldTypes.DATETIME) { + if (schema.type !== FieldType.DATETIME) { continue } if (!schema.timeOnly && !schema.ignoreTimezones) { diff --git a/packages/server/src/utilities/schema.ts b/packages/server/src/utilities/schema.ts index 40e4152b63..500e922d65 100644 --- a/packages/server/src/utilities/schema.ts +++ b/packages/server/src/utilities/schema.ts @@ -1,12 +1,11 @@ -import { FieldSubtype } from "@budibase/types" -import { FieldTypes } from "../constants" +import { FieldType, FieldSubtype } from "@budibase/types" import { ValidColumnNameRegex, utils } from "@budibase/shared-core" import { db } from "@budibase/backend-core" import { parseCsvExport } from "../api/controllers/view/exporters" interface SchemaColumn { readonly name: string - readonly type: FieldTypes + readonly type: FieldType readonly subtype: FieldSubtype readonly autocolumn?: boolean readonly constraints?: { @@ -36,13 +35,13 @@ interface ValidationResults { } const PARSERS: any = { - [FieldTypes.NUMBER]: (attribute?: string) => { + [FieldType.NUMBER]: (attribute?: string) => { if (!attribute) { return attribute } return Number(attribute) }, - [FieldTypes.DATETIME]: (attribute?: string) => { + [FieldType.DATETIME]: (attribute?: string) => { if (!attribute) { return attribute } @@ -60,7 +59,7 @@ export function isSchema(schema: any): schema is Schema { column !== null && typeof column === "object" && 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 ) { return - } else if ( - columnType === FieldTypes.NUMBER && - isNaN(Number(columnData)) - ) { + } else if (columnType === FieldType.NUMBER && isNaN(Number(columnData))) { // If provided must be a valid number results.schemaValidation[columnName] = false } else if ( // If provided must be a valid date - columnType === FieldTypes.DATETIME && + columnType === FieldType.DATETIME && isNaN(new Date(columnData).getTime()) ) { results.schemaValidation[columnName] = false } else if ( - columnType === FieldTypes.BB_REFERENCE && + columnType === FieldType.BB_REFERENCE && !isValidBBReference(columnData, columnSubtype) ) { results.schemaValidation[columnName] = false @@ -155,15 +151,15 @@ export function parse(rows: Rows, schema: Schema): Rows { const columnType = schema[columnName].type const columnSubtype = schema[columnName].subtype - if (columnType === FieldTypes.NUMBER) { + if (columnType === FieldType.NUMBER) { // If provided must be a valid number parsedRow[columnName] = columnData ? Number(columnData) : columnData - } else if (columnType === FieldTypes.DATETIME) { + } else if (columnType === FieldType.DATETIME) { // If provided must be a valid date parsedRow[columnName] = columnData ? new Date(columnData).toISOString() : columnData - } else if (columnType === FieldTypes.BB_REFERENCE) { + } else if (columnType === FieldType.BB_REFERENCE) { const parsedValues = !!columnData && parseCsvExport<{ _id: string }[]>(columnData) if (!parsedValues) { diff --git a/packages/types/src/documents/app/table/constants.ts b/packages/types/src/documents/app/table/constants.ts index 783eae0671..fc831e7e7c 100644 --- a/packages/types/src/documents/app/table/constants.ts +++ b/packages/types/src/documents/app/table/constants.ts @@ -8,7 +8,7 @@ export enum AutoReason { FOREIGN_KEY = "foreign_key", } -export enum AutoFieldSubTypes { +export enum AutoFieldSubType { CREATED_BY = "createdBy", CREATED_AT = "createdAt", UPDATED_BY = "updatedBy", @@ -16,7 +16,7 @@ export enum AutoFieldSubTypes { AUTO_ID = "autoID", } -export enum FormulaTypes { +export enum FormulaType { STATIC = "static", DYNAMIC = "dynamic", } diff --git a/packages/types/src/documents/app/table/schema.ts b/packages/types/src/documents/app/table/schema.ts index e9eb139ebc..47ec303b66 100644 --- a/packages/types/src/documents/app/table/schema.ts +++ b/packages/types/src/documents/app/table/schema.ts @@ -2,9 +2,9 @@ // column size, position and whether it can be viewed import { FieldSubtype, FieldType } from "../row" import { - AutoFieldSubTypes, + AutoFieldSubType, AutoReason, - FormulaTypes, + FormulaType, RelationshipType, } from "./constants" @@ -22,7 +22,7 @@ interface BaseRelationshipFieldMetadata fieldName: string tableId: string tableRev?: string - subtype?: AutoFieldSubTypes.CREATED_BY | AutoFieldSubTypes.UPDATED_BY + subtype?: AutoFieldSubType.CREATED_BY | AutoFieldSubType.UPDATED_BY } // External tables use junction tables, internal tables don't require them @@ -62,7 +62,7 @@ export interface AutoColumnFieldMetadata extends Omit { type: FieldType.AUTO autocolumn: true - subtype?: AutoFieldSubTypes + subtype?: AutoFieldSubType lastID?: number // if the column was turned to an auto-column for SQL, explains why (primary, foreign etc) autoReason?: AutoReason @@ -70,7 +70,7 @@ export interface AutoColumnFieldMetadata export interface NumberFieldMetadata extends Omit { type: FieldType.NUMBER - subtype?: AutoFieldSubTypes.AUTO_ID + subtype?: AutoFieldSubType.AUTO_ID lastID?: number autoReason?: AutoReason.FOREIGN_KEY // used specifically when Budibase generates external tables, this denotes if a number field @@ -85,7 +85,7 @@ export interface DateFieldMetadata extends Omit { type: FieldType.DATETIME ignoreTimezones?: boolean timeOnly?: boolean - subtype?: AutoFieldSubTypes.CREATED_AT | AutoFieldSubTypes.UPDATED_AT + subtype?: AutoFieldSubType.CREATED_AT | AutoFieldSubType.UPDATED_AT } export interface LongFormFieldMetadata extends BaseFieldSchema { @@ -96,7 +96,7 @@ export interface LongFormFieldMetadata extends BaseFieldSchema { export interface FormulaFieldMetadata extends BaseFieldSchema { type: FieldType.FORMULA formula: string - formulaType?: FormulaTypes + formulaType?: FormulaType } export interface BBReferenceFieldMetadata