Standardise fetching schema from client apps to fix issues with determing schema for certain data sources
This commit is contained in:
parent
08de9c0b45
commit
fcf87956de
|
@ -1,8 +1,8 @@
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { fetchTableData } from "./tables"
|
import { fetchTableData, fetchTableDefinition } from "./tables"
|
||||||
import { fetchViewData } from "./views"
|
import { fetchViewData } from "./views"
|
||||||
import { fetchRelationshipData } from "./relationships"
|
import { fetchRelationshipData } from "./relationships"
|
||||||
import { executeQuery } from "./queries"
|
import { executeQuery, fetchQueryDefinition } from "./queries"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all rows for a particular Budibase data source.
|
* Fetches all rows for a particular Budibase data source.
|
||||||
|
@ -39,3 +39,35 @@ export const fetchDatasource = async dataSource => {
|
||||||
// Enrich the result is always an array
|
// Enrich the result is always an array
|
||||||
return Array.isArray(rows) ? rows : []
|
return Array.isArray(rows) ? rows : []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the schema of any kind of datasource.
|
||||||
|
*/
|
||||||
|
export const fetchDatasourceSchema = async dataSource => {
|
||||||
|
if (!dataSource) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const { type } = dataSource
|
||||||
|
|
||||||
|
// Nested providers should already have exposed their own schema
|
||||||
|
if (type === "provider") {
|
||||||
|
return dataSource.value?.schema
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tables, views and links can be fetched by table ID
|
||||||
|
if (
|
||||||
|
(type === "table" || type === "view" || type === "link") &&
|
||||||
|
dataSource.tableId
|
||||||
|
) {
|
||||||
|
const table = await fetchTableDefinition(dataSource.tableId)
|
||||||
|
return table?.schema
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queries can be fetched by query ID
|
||||||
|
if (type === "query" && dataSource._id) {
|
||||||
|
const definition = await fetchQueryDefinition(dataSource._id)
|
||||||
|
return definition?.schema
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import API from "./api"
|
||||||
* Executes a query against an external data connector.
|
* Executes a query against an external data connector.
|
||||||
*/
|
*/
|
||||||
export const executeQuery = async ({ queryId, parameters }) => {
|
export const executeQuery = async ({ queryId, parameters }) => {
|
||||||
const query = await API.get({ url: `/api/queries/${queryId}` })
|
const query = await fetchQueryDefinition(queryId)
|
||||||
if (query?.datasourceId == null) {
|
if (query?.datasourceId == null) {
|
||||||
notificationStore.actions.error("That query couldn't be found")
|
notificationStore.actions.error("That query couldn't be found")
|
||||||
return
|
return
|
||||||
|
@ -24,3 +24,10 @@ export const executeQuery = async ({ queryId, parameters }) => {
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the definition of an external query.
|
||||||
|
*/
|
||||||
|
export const fetchQueryDefinition = async queryId => {
|
||||||
|
return await API.get({ url: `/api/queries/${queryId}`, cache: true })
|
||||||
|
}
|
||||||
|
|
|
@ -156,34 +156,24 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const getSchema = async dataSource => {
|
const getSchema = async dataSource => {
|
||||||
if (dataSource?.schema) {
|
let newSchema = (await API.fetchDatasourceSchema(dataSource)) || {}
|
||||||
schema = dataSource.schema
|
|
||||||
} else if (dataSource?.tableId) {
|
|
||||||
const definition = await API.fetchTableDefinition(dataSource.tableId)
|
|
||||||
schema = definition?.schema ?? {}
|
|
||||||
} else if (dataSource?.type === "provider") {
|
|
||||||
schema = dataSource.value?.schema ?? {}
|
|
||||||
} else {
|
|
||||||
schema = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure there are "name" properties for all fields and that field schema
|
// Ensure there are "name" properties for all fields and that field schema
|
||||||
// are objects
|
// are objects
|
||||||
let fixedSchema = {}
|
Object.entries(newSchema).forEach(([fieldName, fieldSchema]) => {
|
||||||
Object.entries(schema || {}).forEach(([fieldName, fieldSchema]) => {
|
|
||||||
if (typeof fieldSchema === "string") {
|
if (typeof fieldSchema === "string") {
|
||||||
fixedSchema[fieldName] = {
|
newSchema[fieldName] = {
|
||||||
type: fieldSchema,
|
type: fieldSchema,
|
||||||
name: fieldName,
|
name: fieldName,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fixedSchema[fieldName] = {
|
newSchema[fieldName] = {
|
||||||
...fieldSchema,
|
...fieldSchema,
|
||||||
name: fieldName,
|
name: fieldName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
schema = fixedSchema
|
schema = newSchema
|
||||||
schemaLoaded = true
|
schemaLoaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,25 +34,34 @@
|
||||||
return closestContext || {}
|
return closestContext || {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetches the form schema from this form's dataSource, if one exists
|
// Fetches the form schema from this form's dataSource
|
||||||
const fetchSchema = async () => {
|
const fetchSchema = async () => {
|
||||||
if (!dataSource?.tableId) {
|
if (!dataSource) {
|
||||||
schema = {}
|
schema = {}
|
||||||
table = null
|
|
||||||
} else {
|
|
||||||
table = await API.fetchTableDefinition(dataSource?.tableId)
|
|
||||||
if (table) {
|
|
||||||
if (dataSource?.type === "query") {
|
|
||||||
schema = {}
|
|
||||||
const params = table.parameters || []
|
|
||||||
params.forEach(param => {
|
|
||||||
schema[param.name] = { ...param, type: "string" }
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
schema = table.schema || {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the datasource is a query, then we instead use a schema of the query
|
||||||
|
// parameters rather than the output schema
|
||||||
|
else if (
|
||||||
|
dataSource.type === "query" &&
|
||||||
|
dataSource._id &&
|
||||||
|
actionType === "Create"
|
||||||
|
) {
|
||||||
|
const query = await API.fetchQueryDefinition(dataSource._id)
|
||||||
|
let paramSchema = {}
|
||||||
|
const params = query.parameters || []
|
||||||
|
params.forEach(param => {
|
||||||
|
paramSchema[param.name] = { ...param, type: "string" }
|
||||||
|
})
|
||||||
|
schema = paramSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all other cases, just grab the normal schema
|
||||||
|
else {
|
||||||
|
const dataSourceSchema = await API.fetchDatasourceSchema(dataSource)
|
||||||
|
schema = dataSourceSchema || {}
|
||||||
|
}
|
||||||
|
|
||||||
loaded = true
|
loaded = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue