Merge pull request #11315 from Budibase/types/improve-field-schema
Table types improvement - split up FieldSchema
This commit is contained in:
commit
fe8c92be79
19 changed files with 230 additions and 193 deletions
|
@ -18,7 +18,7 @@
|
||||||
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
import { TableNames, UNEDITABLE_USER_FIELDS } from "constants"
|
||||||
import {
|
import {
|
||||||
FIELDS,
|
FIELDS,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
ALLOWABLE_STRING_OPTIONS,
|
ALLOWABLE_STRING_OPTIONS,
|
||||||
ALLOWABLE_NUMBER_OPTIONS,
|
ALLOWABLE_NUMBER_OPTIONS,
|
||||||
ALLOWABLE_STRING_TYPES,
|
ALLOWABLE_STRING_TYPES,
|
||||||
|
@ -183,7 +183,7 @@
|
||||||
dispatch("updatecolumns")
|
dispatch("updatecolumns")
|
||||||
if (
|
if (
|
||||||
saveColumn.type === LINK_TYPE &&
|
saveColumn.type === LINK_TYPE &&
|
||||||
saveColumn.relationshipType === RelationshipTypes.MANY_TO_MANY
|
saveColumn.relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
) {
|
) {
|
||||||
// Fetching the new tables
|
// Fetching the new tables
|
||||||
tables.fetch()
|
tables.fetch()
|
||||||
|
@ -237,7 +237,7 @@
|
||||||
|
|
||||||
// Default relationships many to many
|
// Default relationships many to many
|
||||||
if (editableColumn.type === LINK_TYPE) {
|
if (editableColumn.type === LINK_TYPE) {
|
||||||
editableColumn.relationshipType = RelationshipTypes.MANY_TO_MANY
|
editableColumn.relationshipType = RelationshipType.MANY_TO_MANY
|
||||||
}
|
}
|
||||||
if (editableColumn.type === FORMULA_TYPE) {
|
if (editableColumn.type === FORMULA_TYPE) {
|
||||||
editableColumn.formulaType = "dynamic"
|
editableColumn.formulaType = "dynamic"
|
||||||
|
@ -285,17 +285,17 @@
|
||||||
{
|
{
|
||||||
name: `Many ${thisName} rows → many ${linkName} rows`,
|
name: `Many ${thisName} rows → many ${linkName} rows`,
|
||||||
alt: `Many ${table.name} rows → many ${linkTable.name} rows`,
|
alt: `Many ${table.name} rows → many ${linkTable.name} rows`,
|
||||||
value: RelationshipTypes.MANY_TO_MANY,
|
value: RelationshipType.MANY_TO_MANY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `One ${linkName} row → many ${thisName} rows`,
|
name: `One ${linkName} row → many ${thisName} rows`,
|
||||||
alt: `One ${linkTable.name} rows → many ${table.name} rows`,
|
alt: `One ${linkTable.name} rows → many ${table.name} rows`,
|
||||||
value: RelationshipTypes.ONE_TO_MANY,
|
value: RelationshipType.ONE_TO_MANY,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: `One ${thisName} row → many ${linkName} rows`,
|
name: `One ${thisName} row → many ${linkName} rows`,
|
||||||
alt: `One ${table.name} rows → many ${linkTable.name} rows`,
|
alt: `One ${table.name} rows → many ${linkTable.name} rows`,
|
||||||
value: RelationshipTypes.MANY_TO_ONE,
|
value: RelationshipType.MANY_TO_ONE,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { RelationshipTypes } from "constants/backend"
|
import { RelationshipType } from "constants/backend"
|
||||||
import {
|
import {
|
||||||
keepOpen,
|
keepOpen,
|
||||||
Button,
|
Button,
|
||||||
|
@ -25,11 +25,11 @@
|
||||||
const relationshipTypes = [
|
const relationshipTypes = [
|
||||||
{
|
{
|
||||||
label: "One to Many",
|
label: "One to Many",
|
||||||
value: RelationshipTypes.MANY_TO_ONE,
|
value: RelationshipType.MANY_TO_ONE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Many to Many",
|
label: "Many to Many",
|
||||||
value: RelationshipTypes.MANY_TO_MANY,
|
value: RelationshipType.MANY_TO_MANY,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -58,8 +58,8 @@
|
||||||
value: table._id,
|
value: table._id,
|
||||||
}))
|
}))
|
||||||
$: valid = getErrorCount(errors) === 0 && allRequiredAttributesSet()
|
$: valid = getErrorCount(errors) === 0 && allRequiredAttributesSet()
|
||||||
$: isManyToMany = relationshipType === RelationshipTypes.MANY_TO_MANY
|
$: isManyToMany = relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
$: isManyToOne = relationshipType === RelationshipTypes.MANY_TO_ONE
|
$: isManyToOne = relationshipType === RelationshipType.MANY_TO_ONE
|
||||||
|
|
||||||
function getTable(id) {
|
function getTable(id) {
|
||||||
return plusTables.find(table => table._id === id)
|
return plusTables.find(table => table._id === id)
|
||||||
|
@ -116,7 +116,7 @@
|
||||||
|
|
||||||
function allRequiredAttributesSet() {
|
function allRequiredAttributesSet() {
|
||||||
const base = getTable(fromId) && getTable(toId) && fromColumn && toColumn
|
const base = getTable(fromId) && getTable(toId) && fromColumn && toColumn
|
||||||
if (relationshipType === RelationshipTypes.MANY_TO_ONE) {
|
if (relationshipType === RelationshipType.MANY_TO_ONE) {
|
||||||
return base && fromPrimary && fromForeign
|
return base && fromPrimary && fromForeign
|
||||||
} else {
|
} else {
|
||||||
return base && getTable(throughId) && throughFromKey && throughToKey
|
return base && getTable(throughId) && throughFromKey && throughToKey
|
||||||
|
@ -181,12 +181,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function otherRelationshipType(type) {
|
function otherRelationshipType(type) {
|
||||||
if (type === RelationshipTypes.MANY_TO_ONE) {
|
if (type === RelationshipType.MANY_TO_ONE) {
|
||||||
return RelationshipTypes.ONE_TO_MANY
|
return RelationshipType.ONE_TO_MANY
|
||||||
} else if (type === RelationshipTypes.ONE_TO_MANY) {
|
} else if (type === RelationshipType.ONE_TO_MANY) {
|
||||||
return RelationshipTypes.MANY_TO_ONE
|
return RelationshipType.MANY_TO_ONE
|
||||||
} else if (type === RelationshipTypes.MANY_TO_MANY) {
|
} else if (type === RelationshipType.MANY_TO_MANY) {
|
||||||
return RelationshipTypes.MANY_TO_MANY
|
return RelationshipType.MANY_TO_MANY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@
|
||||||
|
|
||||||
// if any to many only need to check from
|
// if any to many only need to check from
|
||||||
const manyToMany =
|
const manyToMany =
|
||||||
relateFrom.relationshipType === RelationshipTypes.MANY_TO_MANY
|
relateFrom.relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
|
|
||||||
if (!manyToMany) {
|
if (!manyToMany) {
|
||||||
delete relateFrom.through
|
delete relateFrom.through
|
||||||
|
@ -253,7 +253,7 @@
|
||||||
}
|
}
|
||||||
relateTo = {
|
relateTo = {
|
||||||
...relateTo,
|
...relateTo,
|
||||||
relationshipType: RelationshipTypes.ONE_TO_MANY,
|
relationshipType: RelationshipType.ONE_TO_MANY,
|
||||||
foreignKey: relateFrom.fieldName,
|
foreignKey: relateFrom.fieldName,
|
||||||
fieldName: fromPrimary,
|
fieldName: fromPrimary,
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@
|
||||||
fromColumn = toRelationship.name
|
fromColumn = toRelationship.name
|
||||||
}
|
}
|
||||||
relationshipType =
|
relationshipType =
|
||||||
fromRelationship.relationshipType || RelationshipTypes.MANY_TO_ONE
|
fromRelationship.relationshipType || RelationshipType.MANY_TO_ONE
|
||||||
if (selectedFromTable) {
|
if (selectedFromTable) {
|
||||||
fromId = selectedFromTable._id
|
fromId = selectedFromTable._id
|
||||||
fromColumn = selectedFromTable.name
|
fromColumn = selectedFromTable.name
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { RelationshipTypes } from "constants/backend"
|
import { RelationshipType } from "constants/backend"
|
||||||
|
|
||||||
const typeMismatch = "Column type of the foreign key must match the primary key"
|
const typeMismatch = "Column type of the foreign key must match the primary key"
|
||||||
const columnBeingUsed = "Column name cannot be an existing column"
|
const columnBeingUsed = "Column name cannot be an existing column"
|
||||||
|
@ -40,7 +40,7 @@ export class RelationshipErrorChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
isMany() {
|
isMany() {
|
||||||
return this.type === RelationshipTypes.MANY_TO_MANY
|
return this.type === RelationshipType.MANY_TO_MANY
|
||||||
}
|
}
|
||||||
|
|
||||||
relationshipTypeSet(type) {
|
relationshipTypeSet(type) {
|
||||||
|
|
|
@ -151,7 +151,7 @@ export function isAutoColumnUserRelationship(subtype) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RelationshipTypes = {
|
export const RelationshipType = {
|
||||||
MANY_TO_MANY: "many-to-many",
|
MANY_TO_MANY: "many-to-many",
|
||||||
ONE_TO_MANY: "one-to-many",
|
ONE_TO_MANY: "one-to-many",
|
||||||
MANY_TO_ONE: "many-to-one",
|
MANY_TO_ONE: "many-to-one",
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
import {
|
import { FieldTypes, RelationshipType, FormulaTypes } from "../../src/constants"
|
||||||
FieldTypes,
|
|
||||||
RelationshipTypes,
|
|
||||||
FormulaTypes,
|
|
||||||
} from "../../src/constants"
|
|
||||||
import { object } from "./utils"
|
import { object } from "./utils"
|
||||||
import Resource from "./utils/Resource"
|
import Resource from "./utils/Resource"
|
||||||
|
|
||||||
|
@ -100,7 +96,7 @@ const tableSchema = {
|
||||||
},
|
},
|
||||||
relationshipType: {
|
relationshipType: {
|
||||||
type: "string",
|
type: "string",
|
||||||
enum: Object.values(RelationshipTypes),
|
enum: Object.values(RelationshipType),
|
||||||
description:
|
description:
|
||||||
"Defines the type of relationship that this column will be used for.",
|
"Defines the type of relationship that this column will be used for.",
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
Operation,
|
Operation,
|
||||||
PaginationJson,
|
PaginationJson,
|
||||||
RelationshipsJson,
|
RelationshipsJson,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
Row,
|
Row,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
SortJson,
|
SortJson,
|
||||||
|
@ -577,7 +577,7 @@ export class ExternalRequest {
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY
|
const isMany = field.relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
const tableId = isMany ? field.through : field.tableId
|
const tableId = isMany ? field.through : field.tableId
|
||||||
const { tableName: relatedTableName } = breakExternalTableId(tableId)
|
const { tableName: relatedTableName } = breakExternalTableId(tableId)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
FieldSchema,
|
FieldSchema,
|
||||||
Operation,
|
Operation,
|
||||||
QueryJson,
|
QueryJson,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
RenameColumn,
|
RenameColumn,
|
||||||
Table,
|
Table,
|
||||||
TableRequest,
|
TableRequest,
|
||||||
|
@ -103,12 +103,12 @@ function getDatasourceId(table: Table) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function otherRelationshipType(type?: string) {
|
function otherRelationshipType(type?: string) {
|
||||||
if (type === RelationshipTypes.MANY_TO_MANY) {
|
if (type === RelationshipType.MANY_TO_MANY) {
|
||||||
return RelationshipTypes.MANY_TO_MANY
|
return RelationshipType.MANY_TO_MANY
|
||||||
}
|
}
|
||||||
return type === RelationshipTypes.ONE_TO_MANY
|
return type === RelationshipType.ONE_TO_MANY
|
||||||
? RelationshipTypes.MANY_TO_ONE
|
? RelationshipType.MANY_TO_ONE
|
||||||
: RelationshipTypes.ONE_TO_MANY
|
: RelationshipType.ONE_TO_MANY
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateManyLinkSchema(
|
function generateManyLinkSchema(
|
||||||
|
@ -151,12 +151,12 @@ function generateLinkSchema(
|
||||||
column: FieldSchema,
|
column: FieldSchema,
|
||||||
table: Table,
|
table: Table,
|
||||||
relatedTable: Table,
|
relatedTable: Table,
|
||||||
type: RelationshipTypes
|
type: RelationshipType
|
||||||
) {
|
) {
|
||||||
if (!table.primary || !relatedTable.primary) {
|
if (!table.primary || !relatedTable.primary) {
|
||||||
throw new Error("Unable to generate link schema, no primary keys")
|
throw new Error("Unable to generate link schema, no primary keys")
|
||||||
}
|
}
|
||||||
const isOneSide = type === RelationshipTypes.ONE_TO_MANY
|
const isOneSide = type === RelationshipType.ONE_TO_MANY
|
||||||
const primary = isOneSide ? relatedTable.primary[0] : table.primary[0]
|
const primary = isOneSide ? relatedTable.primary[0] : table.primary[0]
|
||||||
// generate a foreign key
|
// generate a foreign key
|
||||||
const foreignKey = generateForeignKey(column, relatedTable)
|
const foreignKey = generateForeignKey(column, relatedTable)
|
||||||
|
@ -251,7 +251,7 @@ export async function save(ctx: UserCtx) {
|
||||||
}
|
}
|
||||||
const relatedColumnName = schema.fieldName!
|
const relatedColumnName = schema.fieldName!
|
||||||
const relationType = schema.relationshipType!
|
const relationType = schema.relationshipType!
|
||||||
if (relationType === RelationshipTypes.MANY_TO_MANY) {
|
if (relationType === RelationshipType.MANY_TO_MANY) {
|
||||||
const junctionTable = generateManyLinkSchema(
|
const junctionTable = generateManyLinkSchema(
|
||||||
datasource,
|
datasource,
|
||||||
schema,
|
schema,
|
||||||
|
@ -265,7 +265,7 @@ export async function save(ctx: UserCtx) {
|
||||||
extraTablesToUpdate.push(junctionTable)
|
extraTablesToUpdate.push(junctionTable)
|
||||||
} else {
|
} else {
|
||||||
const fkTable =
|
const fkTable =
|
||||||
relationType === RelationshipTypes.ONE_TO_MANY
|
relationType === RelationshipType.ONE_TO_MANY
|
||||||
? tableToSave
|
? tableToSave
|
||||||
: relatedTable
|
: relatedTable
|
||||||
const foreignKey = generateLinkSchema(
|
const foreignKey = generateLinkSchema(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { objectStore, roles, constants } from "@budibase/backend-core"
|
import { objectStore, roles, constants } from "@budibase/backend-core"
|
||||||
import { FieldType as FieldTypes } from "@budibase/types"
|
import { FieldType as FieldTypes } from "@budibase/types"
|
||||||
export { FieldType as FieldTypes, RelationshipTypes } from "@budibase/types"
|
export { FieldType as FieldTypes, RelationshipType } from "@budibase/types"
|
||||||
|
|
||||||
export enum FilterTypes {
|
export enum FilterTypes {
|
||||||
STRING = "string",
|
STRING = "string",
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { employeeImport } from "./employeeImport"
|
||||||
import { jobsImport } from "./jobsImport"
|
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 { Table, Row, RelationshipTypes } from "@budibase/types"
|
import { Table, Row, RelationshipType } from "@budibase/types"
|
||||||
|
|
||||||
export const DEFAULT_JOBS_TABLE_ID = "ta_bb_jobs"
|
export const DEFAULT_JOBS_TABLE_ID = "ta_bb_jobs"
|
||||||
export const DEFAULT_INVENTORY_TABLE_ID = "ta_bb_inventory"
|
export const DEFAULT_INVENTORY_TABLE_ID = "ta_bb_inventory"
|
||||||
|
@ -299,7 +299,7 @@ export const DEFAULT_EMPLOYEE_TABLE_SCHEMA: Table = {
|
||||||
},
|
},
|
||||||
fieldName: "Assigned",
|
fieldName: "Assigned",
|
||||||
name: "Jobs",
|
name: "Jobs",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_MANY,
|
relationshipType: RelationshipType.MANY_TO_MANY,
|
||||||
tableId: DEFAULT_JOBS_TABLE_ID,
|
tableId: DEFAULT_JOBS_TABLE_ID,
|
||||||
},
|
},
|
||||||
"Start Date": {
|
"Start Date": {
|
||||||
|
@ -458,7 +458,7 @@ export const DEFAULT_JOBS_TABLE_SCHEMA: Table = {
|
||||||
type: FieldTypes.LINK,
|
type: FieldTypes.LINK,
|
||||||
tableId: DEFAULT_EMPLOYEE_TABLE_ID,
|
tableId: DEFAULT_EMPLOYEE_TABLE_ID,
|
||||||
fieldName: "Jobs",
|
fieldName: "Jobs",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_MANY,
|
relationshipType: RelationshipType.MANY_TO_MANY,
|
||||||
// sortable: true,
|
// sortable: true,
|
||||||
},
|
},
|
||||||
"Works End": {
|
"Works End": {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
Database,
|
Database,
|
||||||
FieldSchema,
|
FieldSchema,
|
||||||
LinkDocumentValue,
|
LinkDocumentValue,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
Row,
|
Row,
|
||||||
Table,
|
Table,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -136,16 +136,16 @@ class LinkController {
|
||||||
handleRelationshipType(linkerField: FieldSchema, linkedField: FieldSchema) {
|
handleRelationshipType(linkerField: FieldSchema, linkedField: FieldSchema) {
|
||||||
if (
|
if (
|
||||||
!linkerField.relationshipType ||
|
!linkerField.relationshipType ||
|
||||||
linkerField.relationshipType === RelationshipTypes.MANY_TO_MANY
|
linkerField.relationshipType === RelationshipType.MANY_TO_MANY
|
||||||
) {
|
) {
|
||||||
linkedField.relationshipType = RelationshipTypes.MANY_TO_MANY
|
linkedField.relationshipType = RelationshipType.MANY_TO_MANY
|
||||||
// make sure by default all are many to many (if not specified)
|
// make sure by default all are many to many (if not specified)
|
||||||
linkerField.relationshipType = RelationshipTypes.MANY_TO_MANY
|
linkerField.relationshipType = RelationshipType.MANY_TO_MANY
|
||||||
} else if (linkerField.relationshipType === RelationshipTypes.MANY_TO_ONE) {
|
} else if (linkerField.relationshipType === RelationshipType.MANY_TO_ONE) {
|
||||||
// Ensure that the other side of the relationship is locked to one record
|
// Ensure that the other side of the relationship is locked to one record
|
||||||
linkedField.relationshipType = RelationshipTypes.ONE_TO_MANY
|
linkedField.relationshipType = RelationshipType.ONE_TO_MANY
|
||||||
} else if (linkerField.relationshipType === RelationshipTypes.ONE_TO_MANY) {
|
} else if (linkerField.relationshipType === RelationshipType.ONE_TO_MANY) {
|
||||||
linkedField.relationshipType = RelationshipTypes.MANY_TO_ONE
|
linkedField.relationshipType = RelationshipType.MANY_TO_ONE
|
||||||
}
|
}
|
||||||
return { linkerField, linkedField }
|
return { linkerField, linkedField }
|
||||||
}
|
}
|
||||||
|
@ -200,9 +200,7 @@ class LinkController {
|
||||||
|
|
||||||
// iterate through the link IDs in the row field, see if any don't exist already
|
// iterate through the link IDs in the row field, see if any don't exist already
|
||||||
for (let linkId of rowField) {
|
for (let linkId of rowField) {
|
||||||
if (
|
if (linkedSchema?.relationshipType === RelationshipType.ONE_TO_MANY) {
|
||||||
linkedSchema?.relationshipType === RelationshipTypes.ONE_TO_MANY
|
|
||||||
) {
|
|
||||||
let links = (
|
let links = (
|
||||||
(await getLinkDocuments({
|
(await getLinkDocuments({
|
||||||
tableId: field.tableId,
|
tableId: field.tableId,
|
||||||
|
|
|
@ -2,7 +2,7 @@ const TestConfig = require("../../tests/utilities/TestConfiguration")
|
||||||
const { basicRow, basicLinkedRow, basicTable } = require("../../tests/utilities/structures")
|
const { basicRow, basicLinkedRow, basicTable } = require("../../tests/utilities/structures")
|
||||||
const LinkController = require("../linkedRows/LinkController").default
|
const LinkController = require("../linkedRows/LinkController").default
|
||||||
const { context } = require("@budibase/backend-core")
|
const { context } = require("@budibase/backend-core")
|
||||||
const { RelationshipTypes } = require("../../constants")
|
const { RelationshipType } = require("../../constants")
|
||||||
const { cloneDeep } = require("lodash/fp")
|
const { cloneDeep } = require("lodash/fp")
|
||||||
|
|
||||||
describe("test the link controller", () => {
|
describe("test the link controller", () => {
|
||||||
|
@ -16,7 +16,7 @@ describe("test the link controller", () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const { _id } = await config.createTable()
|
const { _id } = await config.createTable()
|
||||||
table2 = await config.createLinkedTable(RelationshipTypes.MANY_TO_MANY, ["link", "link2"])
|
table2 = await config.createLinkedTable(RelationshipType.MANY_TO_MANY, ["link", "link2"])
|
||||||
// update table after creating link
|
// update table after creating link
|
||||||
table1 = await config.getTable(_id)
|
table1 = await config.getTable(_id)
|
||||||
})
|
})
|
||||||
|
@ -57,17 +57,17 @@ describe("test the link controller", () => {
|
||||||
const controller = await createLinkController(table1)
|
const controller = await createLinkController(table1)
|
||||||
// empty case
|
// empty case
|
||||||
let output = controller.handleRelationshipType({}, {})
|
let output = controller.handleRelationshipType({}, {})
|
||||||
expect(output.linkedField.relationshipType).toEqual(RelationshipTypes.MANY_TO_MANY)
|
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
|
||||||
expect(output.linkerField.relationshipType).toEqual(RelationshipTypes.MANY_TO_MANY)
|
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
|
||||||
output = controller.handleRelationshipType({ relationshipType: RelationshipTypes.MANY_TO_MANY }, {})
|
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_MANY }, {})
|
||||||
expect(output.linkedField.relationshipType).toEqual(RelationshipTypes.MANY_TO_MANY)
|
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
|
||||||
expect(output.linkerField.relationshipType).toEqual(RelationshipTypes.MANY_TO_MANY)
|
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
|
||||||
output = controller.handleRelationshipType({ relationshipType: RelationshipTypes.MANY_TO_ONE }, {})
|
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_ONE }, {})
|
||||||
expect(output.linkedField.relationshipType).toEqual(RelationshipTypes.ONE_TO_MANY)
|
expect(output.linkedField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
|
||||||
expect(output.linkerField.relationshipType).toEqual(RelationshipTypes.MANY_TO_ONE)
|
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
|
||||||
output = controller.handleRelationshipType({ relationshipType: RelationshipTypes.ONE_TO_MANY }, {})
|
output = controller.handleRelationshipType({ relationshipType: RelationshipType.ONE_TO_MANY }, {})
|
||||||
expect(output.linkedField.relationshipType).toEqual(RelationshipTypes.MANY_TO_ONE)
|
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
|
||||||
expect(output.linkerField.relationshipType).toEqual(RelationshipTypes.ONE_TO_MANY)
|
expect(output.linkerField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should be able to delete a row", async () => {
|
it("should be able to delete a row", async () => {
|
||||||
|
@ -157,7 +157,7 @@ describe("test the link controller", () => {
|
||||||
|
|
||||||
it("should throw an error when overwriting a link column", async () => {
|
it("should throw an error when overwriting a link column", async () => {
|
||||||
const update = cloneDeep(table1)
|
const update = cloneDeep(table1)
|
||||||
update.schema.link.relationshipType = RelationshipTypes.MANY_TO_ONE
|
update.schema.link.relationshipType = RelationshipType.MANY_TO_ONE
|
||||||
let error
|
let error
|
||||||
try {
|
try {
|
||||||
const controller = await createLinkController(update)
|
const controller = await createLinkController(update)
|
||||||
|
@ -183,7 +183,7 @@ describe("test the link controller", () => {
|
||||||
|
|
||||||
it("shouldn't allow one to many having many relationships against it", async () => {
|
it("shouldn't allow one to many having many relationships against it", async () => {
|
||||||
const firstTable = await config.createTable()
|
const firstTable = await config.createTable()
|
||||||
const { _id } = await config.createLinkedTable(RelationshipTypes.MANY_TO_ONE, ["link"])
|
const { _id } = await config.createLinkedTable(RelationshipType.MANY_TO_ONE, ["link"])
|
||||||
const linkTable = await config.getTable(_id)
|
const linkTable = await config.getTable(_id)
|
||||||
// an initial row to link around
|
// an initial row to link around
|
||||||
const row = await createLinkedRow("link", linkTable, firstTable)
|
const row = await createLinkedRow("link", linkTable, firstTable)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import * as setup from "../api/routes/tests/utilities"
|
||||||
import {
|
import {
|
||||||
Datasource,
|
Datasource,
|
||||||
FieldType,
|
FieldType,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
Row,
|
Row,
|
||||||
SourceName,
|
SourceName,
|
||||||
Table,
|
Table,
|
||||||
|
@ -101,17 +101,17 @@ describe("postgres integrations", () => {
|
||||||
oneToManyRelationshipInfo = {
|
oneToManyRelationshipInfo = {
|
||||||
table: await createAuxTable("o2m"),
|
table: await createAuxTable("o2m"),
|
||||||
fieldName: "oneToManyRelation",
|
fieldName: "oneToManyRelation",
|
||||||
relationshipType: RelationshipTypes.ONE_TO_MANY,
|
relationshipType: RelationshipType.ONE_TO_MANY,
|
||||||
}
|
}
|
||||||
manyToOneRelationshipInfo = {
|
manyToOneRelationshipInfo = {
|
||||||
table: await createAuxTable("m2o"),
|
table: await createAuxTable("m2o"),
|
||||||
fieldName: "manyToOneRelation",
|
fieldName: "manyToOneRelation",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_ONE,
|
relationshipType: RelationshipType.MANY_TO_ONE,
|
||||||
}
|
}
|
||||||
manyToManyRelationshipInfo = {
|
manyToManyRelationshipInfo = {
|
||||||
table: await createAuxTable("m2m"),
|
table: await createAuxTable("m2m"),
|
||||||
fieldName: "manyToManyRelation",
|
fieldName: "manyToManyRelation",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_MANY,
|
relationshipType: RelationshipType.MANY_TO_MANY,
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryPostgresTable = await config.createTable({
|
primaryPostgresTable = await config.createTable({
|
||||||
|
@ -143,7 +143,7 @@ describe("postgres integrations", () => {
|
||||||
},
|
},
|
||||||
fieldName: oneToManyRelationshipInfo.fieldName,
|
fieldName: oneToManyRelationshipInfo.fieldName,
|
||||||
name: "oneToManyRelation",
|
name: "oneToManyRelation",
|
||||||
relationshipType: RelationshipTypes.ONE_TO_MANY,
|
relationshipType: RelationshipType.ONE_TO_MANY,
|
||||||
tableId: oneToManyRelationshipInfo.table._id,
|
tableId: oneToManyRelationshipInfo.table._id,
|
||||||
main: true,
|
main: true,
|
||||||
},
|
},
|
||||||
|
@ -154,7 +154,7 @@ describe("postgres integrations", () => {
|
||||||
},
|
},
|
||||||
fieldName: manyToOneRelationshipInfo.fieldName,
|
fieldName: manyToOneRelationshipInfo.fieldName,
|
||||||
name: "manyToOneRelation",
|
name: "manyToOneRelation",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_ONE,
|
relationshipType: RelationshipType.MANY_TO_ONE,
|
||||||
tableId: manyToOneRelationshipInfo.table._id,
|
tableId: manyToOneRelationshipInfo.table._id,
|
||||||
main: true,
|
main: true,
|
||||||
},
|
},
|
||||||
|
@ -165,7 +165,7 @@ describe("postgres integrations", () => {
|
||||||
},
|
},
|
||||||
fieldName: manyToManyRelationshipInfo.fieldName,
|
fieldName: manyToManyRelationshipInfo.fieldName,
|
||||||
name: "manyToManyRelation",
|
name: "manyToManyRelation",
|
||||||
relationshipType: RelationshipTypes.MANY_TO_MANY,
|
relationshipType: RelationshipType.MANY_TO_MANY,
|
||||||
tableId: manyToManyRelationshipInfo.table._id,
|
tableId: manyToManyRelationshipInfo.table._id,
|
||||||
main: true,
|
main: true,
|
||||||
},
|
},
|
||||||
|
@ -193,12 +193,12 @@ describe("postgres integrations", () => {
|
||||||
type ForeignTableInfo = {
|
type ForeignTableInfo = {
|
||||||
table: Table
|
table: Table
|
||||||
fieldName: string
|
fieldName: string
|
||||||
relationshipType: RelationshipTypes
|
relationshipType: RelationshipType
|
||||||
}
|
}
|
||||||
|
|
||||||
type ForeignRowsInfo = {
|
type ForeignRowsInfo = {
|
||||||
row: Row
|
row: Row
|
||||||
relationshipType: RelationshipTypes
|
relationshipType: RelationshipType
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createPrimaryRow(opts: {
|
async function createPrimaryRow(opts: {
|
||||||
|
@ -263,7 +263,7 @@ describe("postgres integrations", () => {
|
||||||
rowData[manyToOneRelationshipInfo.fieldName].push(foreignRow._id)
|
rowData[manyToOneRelationshipInfo.fieldName].push(foreignRow._id)
|
||||||
foreignRows.push({
|
foreignRows.push({
|
||||||
row: foreignRow,
|
row: foreignRow,
|
||||||
relationshipType: RelationshipTypes.MANY_TO_ONE,
|
relationshipType: RelationshipType.MANY_TO_ONE,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,7 +281,7 @@ describe("postgres integrations", () => {
|
||||||
rowData[manyToManyRelationshipInfo.fieldName].push(foreignRow._id)
|
rowData[manyToManyRelationshipInfo.fieldName].push(foreignRow._id)
|
||||||
foreignRows.push({
|
foreignRows.push({
|
||||||
row: foreignRow,
|
row: foreignRow,
|
||||||
relationshipType: RelationshipTypes.MANY_TO_MANY,
|
relationshipType: RelationshipType.MANY_TO_MANY,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ describe("postgres integrations", () => {
|
||||||
expect(res.status).toBe(200)
|
expect(res.status).toBe(200)
|
||||||
|
|
||||||
const one2ManyForeignRows = foreignRows.filter(
|
const one2ManyForeignRows = foreignRows.filter(
|
||||||
x => x.relationshipType === RelationshipTypes.ONE_TO_MANY
|
x => x.relationshipType === RelationshipType.ONE_TO_MANY
|
||||||
)
|
)
|
||||||
expect(one2ManyForeignRows).toHaveLength(1)
|
expect(one2ManyForeignRows).toHaveLength(1)
|
||||||
|
|
||||||
|
@ -921,7 +921,7 @@ describe("postgres integrations", () => {
|
||||||
(row: Row) => row.id === 2
|
(row: Row) => row.id === 2
|
||||||
)
|
)
|
||||||
expect(m2mRow1).toEqual({
|
expect(m2mRow1).toEqual({
|
||||||
...foreignRowsByType[RelationshipTypes.MANY_TO_MANY][0].row,
|
...foreignRowsByType[RelationshipType.MANY_TO_MANY][0].row,
|
||||||
[m2mFieldName]: [
|
[m2mFieldName]: [
|
||||||
{
|
{
|
||||||
_id: row._id,
|
_id: row._id,
|
||||||
|
@ -930,7 +930,7 @@ describe("postgres integrations", () => {
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
expect(m2mRow2).toEqual({
|
expect(m2mRow2).toEqual({
|
||||||
...foreignRowsByType[RelationshipTypes.MANY_TO_MANY][1].row,
|
...foreignRowsByType[RelationshipType.MANY_TO_MANY][1].row,
|
||||||
[m2mFieldName]: [
|
[m2mFieldName]: [
|
||||||
{
|
{
|
||||||
_id: row._id,
|
_id: row._id,
|
||||||
|
@ -940,24 +940,24 @@ describe("postgres integrations", () => {
|
||||||
})
|
})
|
||||||
expect(res.body[m2oFieldName]).toEqual([
|
expect(res.body[m2oFieldName]).toEqual([
|
||||||
{
|
{
|
||||||
...foreignRowsByType[RelationshipTypes.MANY_TO_ONE][0].row,
|
...foreignRowsByType[RelationshipType.MANY_TO_ONE][0].row,
|
||||||
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
||||||
row.id,
|
row.id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...foreignRowsByType[RelationshipTypes.MANY_TO_ONE][1].row,
|
...foreignRowsByType[RelationshipType.MANY_TO_ONE][1].row,
|
||||||
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
||||||
row.id,
|
row.id,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...foreignRowsByType[RelationshipTypes.MANY_TO_ONE][2].row,
|
...foreignRowsByType[RelationshipType.MANY_TO_ONE][2].row,
|
||||||
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
[`fk_${manyToOneRelationshipInfo.table.name}_${manyToOneRelationshipInfo.fieldName}`]:
|
||||||
row.id,
|
row.id,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
expect(res.body[o2mFieldName]).toEqual([
|
expect(res.body[o2mFieldName]).toEqual([
|
||||||
{
|
{
|
||||||
...foreignRowsByType[RelationshipTypes.ONE_TO_MANY][0].row,
|
...foreignRowsByType[RelationshipType.ONE_TO_MANY][0].row,
|
||||||
_id: expect.any(String),
|
_id: expect.any(String),
|
||||||
_rev: expect.any(String),
|
_rev: expect.any(String),
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Operation, QueryJson, RenameColumn, Table } from "@budibase/types"
|
||||||
import { breakExternalTableId } from "../utils"
|
import { breakExternalTableId } from "../utils"
|
||||||
import SchemaBuilder = Knex.SchemaBuilder
|
import SchemaBuilder = Knex.SchemaBuilder
|
||||||
import CreateTableBuilder = Knex.CreateTableBuilder
|
import CreateTableBuilder = Knex.CreateTableBuilder
|
||||||
import { FieldTypes, RelationshipTypes } from "../../constants"
|
import { FieldTypes, RelationshipType } from "../../constants"
|
||||||
|
|
||||||
function generateSchema(
|
function generateSchema(
|
||||||
schema: CreateTableBuilder,
|
schema: CreateTableBuilder,
|
||||||
|
@ -70,8 +70,8 @@ function generateSchema(
|
||||||
case FieldTypes.LINK:
|
case FieldTypes.LINK:
|
||||||
// this side of the relationship doesn't need any SQL work
|
// this side of the relationship doesn't need any SQL work
|
||||||
if (
|
if (
|
||||||
column.relationshipType !== RelationshipTypes.MANY_TO_ONE &&
|
column.relationshipType !== RelationshipType.MANY_TO_ONE &&
|
||||||
column.relationshipType !== RelationshipTypes.MANY_TO_MANY
|
column.relationshipType !== RelationshipType.MANY_TO_MANY
|
||||||
) {
|
) {
|
||||||
if (!column.foreignKey || !column.tableId) {
|
if (!column.foreignKey || !column.tableId) {
|
||||||
throw "Invalid relationship schema"
|
throw "Invalid relationship schema"
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {
|
||||||
Datasource,
|
Datasource,
|
||||||
FieldSchema,
|
FieldSchema,
|
||||||
FieldType,
|
FieldType,
|
||||||
RelationshipTypes,
|
RelationshipType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { FieldTypes } from "../../../constants"
|
import { FieldTypes } from "../../../constants"
|
||||||
|
|
||||||
|
@ -19,14 +19,14 @@ function checkForeignKeysAreAutoColumns(datasource: Datasource) {
|
||||||
column => column.type === FieldType.LINK
|
column => column.type === FieldType.LINK
|
||||||
)
|
)
|
||||||
relationships.forEach(relationship => {
|
relationships.forEach(relationship => {
|
||||||
if (relationship.relationshipType === RelationshipTypes.MANY_TO_MANY) {
|
if (relationship.relationshipType === RelationshipType.MANY_TO_MANY) {
|
||||||
const tableId = relationship.through!
|
const tableId = relationship.through!
|
||||||
foreignKeys.push({ key: relationship.throughTo!, tableId })
|
foreignKeys.push({ key: relationship.throughTo!, tableId })
|
||||||
foreignKeys.push({ key: relationship.throughFrom!, tableId })
|
foreignKeys.push({ key: relationship.throughFrom!, tableId })
|
||||||
} else {
|
} else {
|
||||||
const fk = relationship.foreignKey!
|
const fk = relationship.foreignKey!
|
||||||
const oneSide =
|
const oneSide =
|
||||||
relationship.relationshipType === RelationshipTypes.ONE_TO_MANY
|
relationship.relationshipType === RelationshipType.ONE_TO_MANY
|
||||||
foreignKeys.push({
|
foreignKeys.push({
|
||||||
tableId: oneSide ? table._id! : relationship.tableId!,
|
tableId: oneSide ? table._id! : relationship.tableId!,
|
||||||
key: fk,
|
key: fk,
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
import { Document } from "../document"
|
|
||||||
import { View } from "./view"
|
|
||||||
import { RenameColumn } from "../../sdk"
|
|
||||||
import { FieldType } from "./row"
|
|
||||||
|
|
||||||
export enum RelationshipTypes {
|
|
||||||
ONE_TO_MANY = "one-to-many",
|
|
||||||
MANY_TO_ONE = "many-to-one",
|
|
||||||
MANY_TO_MANY = "many-to-many",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum AutoReason {
|
|
||||||
FOREIGN_KEY = "foreign_key",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FieldSchema {
|
|
||||||
type: FieldType
|
|
||||||
externalType?: string
|
|
||||||
fieldName?: string
|
|
||||||
name: string
|
|
||||||
sortable?: boolean
|
|
||||||
tableId?: string
|
|
||||||
relationshipType?: RelationshipTypes
|
|
||||||
through?: string
|
|
||||||
foreignKey?: string
|
|
||||||
icon?: string
|
|
||||||
autocolumn?: boolean
|
|
||||||
autoReason?: AutoReason
|
|
||||||
subtype?: string
|
|
||||||
throughFrom?: string
|
|
||||||
throughTo?: string
|
|
||||||
formula?: string
|
|
||||||
formulaType?: string
|
|
||||||
main?: boolean
|
|
||||||
ignoreTimezones?: boolean
|
|
||||||
timeOnly?: boolean
|
|
||||||
lastID?: number
|
|
||||||
useRichText?: boolean | null
|
|
||||||
order?: number
|
|
||||||
width?: number
|
|
||||||
meta?: {
|
|
||||||
toTable: string
|
|
||||||
toKey: string
|
|
||||||
}
|
|
||||||
constraints?: {
|
|
||||||
type?: string
|
|
||||||
email?: boolean
|
|
||||||
inclusion?: string[]
|
|
||||||
length?: {
|
|
||||||
minimum?: string | number | null
|
|
||||||
maximum?: string | number | null
|
|
||||||
}
|
|
||||||
numericality?: {
|
|
||||||
greaterThanOrEqualTo: string | null
|
|
||||||
lessThanOrEqualTo: string | null
|
|
||||||
}
|
|
||||||
presence?:
|
|
||||||
| boolean
|
|
||||||
| {
|
|
||||||
allowEmpty?: boolean
|
|
||||||
}
|
|
||||||
datetime?: {
|
|
||||||
latest: string
|
|
||||||
earliest: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TableSchema {
|
|
||||||
[key: string]: FieldSchema
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Table extends Document {
|
|
||||||
type?: string
|
|
||||||
views?: { [key: string]: View }
|
|
||||||
name: string
|
|
||||||
primary?: string[]
|
|
||||||
schema: TableSchema
|
|
||||||
primaryDisplay?: string
|
|
||||||
sourceId?: string
|
|
||||||
relatedFormula?: string[]
|
|
||||||
constrained?: string[]
|
|
||||||
sql?: boolean
|
|
||||||
indexes?: { [key: string]: any }
|
|
||||||
rows?: { [key: string]: any }
|
|
||||||
created?: boolean
|
|
||||||
rowHeight?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExternalTable extends Table {
|
|
||||||
sourceId: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TableRequest extends Table {
|
|
||||||
_rename?: RenameColumn
|
|
||||||
created?: boolean
|
|
||||||
}
|
|
9
packages/types/src/documents/app/table/constants.ts
Normal file
9
packages/types/src/documents/app/table/constants.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export enum RelationshipType {
|
||||||
|
ONE_TO_MANY = "one-to-many",
|
||||||
|
MANY_TO_ONE = "many-to-one",
|
||||||
|
MANY_TO_MANY = "many-to-many",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AutoReason {
|
||||||
|
FOREIGN_KEY = "foreign_key",
|
||||||
|
}
|
3
packages/types/src/documents/app/table/index.ts
Normal file
3
packages/types/src/documents/app/table/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export * from "./table"
|
||||||
|
export * from "./schema"
|
||||||
|
export * from "./constants"
|
98
packages/types/src/documents/app/table/schema.ts
Normal file
98
packages/types/src/documents/app/table/schema.ts
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
// all added by grid/table when defining the
|
||||||
|
// column size, position and whether it can be viewed
|
||||||
|
import { FieldType } from "../row"
|
||||||
|
import { AutoReason, RelationshipType } from "./constants"
|
||||||
|
|
||||||
|
export interface UIFieldMetadata {
|
||||||
|
order?: number
|
||||||
|
width?: number
|
||||||
|
visible?: boolean
|
||||||
|
icon?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RelationshipFieldMetadata {
|
||||||
|
main?: boolean
|
||||||
|
fieldName?: string
|
||||||
|
tableId?: string
|
||||||
|
// below is used for SQL relationships, needed to define the foreign keys
|
||||||
|
// or the tables used for many-to-many relationships (through)
|
||||||
|
relationshipType?: RelationshipType
|
||||||
|
through?: string
|
||||||
|
foreignKey?: string
|
||||||
|
throughFrom?: string
|
||||||
|
throughTo?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AutoColumnFieldMetadata {
|
||||||
|
autocolumn?: boolean
|
||||||
|
subtype?: string
|
||||||
|
lastID?: number
|
||||||
|
// if the column was turned to an auto-column for SQL, explains why (primary, foreign etc)
|
||||||
|
autoReason?: AutoReason
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NumberFieldMetadata {
|
||||||
|
// used specifically when Budibase generates external tables, this denotes if a number field
|
||||||
|
// is a foreign key used for a many-to-many relationship
|
||||||
|
meta?: {
|
||||||
|
toTable: string
|
||||||
|
toKey: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DateFieldMetadata {
|
||||||
|
ignoreTimezones?: boolean
|
||||||
|
timeOnly?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface StringFieldMetadata {
|
||||||
|
useRichText?: boolean | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FormulaFieldMetadata {
|
||||||
|
formula?: string
|
||||||
|
formulaType?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FieldConstraints {
|
||||||
|
type?: string
|
||||||
|
email?: boolean
|
||||||
|
inclusion?: string[]
|
||||||
|
length?: {
|
||||||
|
minimum?: string | number | null
|
||||||
|
maximum?: string | number | null
|
||||||
|
}
|
||||||
|
numericality?: {
|
||||||
|
greaterThanOrEqualTo: string | null
|
||||||
|
lessThanOrEqualTo: string | null
|
||||||
|
}
|
||||||
|
presence?:
|
||||||
|
| boolean
|
||||||
|
| {
|
||||||
|
allowEmpty?: boolean
|
||||||
|
}
|
||||||
|
datetime?: {
|
||||||
|
latest: string
|
||||||
|
earliest: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FieldSchema
|
||||||
|
extends UIFieldMetadata,
|
||||||
|
DateFieldMetadata,
|
||||||
|
RelationshipFieldMetadata,
|
||||||
|
AutoColumnFieldMetadata,
|
||||||
|
StringFieldMetadata,
|
||||||
|
FormulaFieldMetadata,
|
||||||
|
NumberFieldMetadata {
|
||||||
|
type: FieldType
|
||||||
|
name: string
|
||||||
|
sortable?: boolean
|
||||||
|
// only used by external databases, to denote the real type
|
||||||
|
externalType?: string
|
||||||
|
constraints?: FieldConstraints
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableSchema {
|
||||||
|
[key: string]: FieldSchema
|
||||||
|
}
|
30
packages/types/src/documents/app/table/table.ts
Normal file
30
packages/types/src/documents/app/table/table.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { Document } from "../../document"
|
||||||
|
import { View } from "../view"
|
||||||
|
import { RenameColumn } from "../../../sdk"
|
||||||
|
import { TableSchema } from "./schema"
|
||||||
|
|
||||||
|
export interface Table extends Document {
|
||||||
|
type?: string
|
||||||
|
views?: { [key: string]: View }
|
||||||
|
name: string
|
||||||
|
primary?: string[]
|
||||||
|
schema: TableSchema
|
||||||
|
primaryDisplay?: string
|
||||||
|
sourceId?: string
|
||||||
|
relatedFormula?: string[]
|
||||||
|
constrained?: string[]
|
||||||
|
sql?: boolean
|
||||||
|
indexes?: { [key: string]: any }
|
||||||
|
rows?: { [key: string]: any }
|
||||||
|
created?: boolean
|
||||||
|
rowHeight?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExternalTable extends Table {
|
||||||
|
sourceId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableRequest extends Table {
|
||||||
|
_rename?: RenameColumn
|
||||||
|
created?: boolean
|
||||||
|
}
|
Loading…
Reference in a new issue