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 { fetchTableData } from "./tables"
|
||||
import { fetchTableData, fetchTableDefinition } from "./tables"
|
||||
import { fetchViewData } from "./views"
|
||||
import { fetchRelationshipData } from "./relationships"
|
||||
import { executeQuery } from "./queries"
|
||||
import { executeQuery, fetchQueryDefinition } from "./queries"
|
||||
|
||||
/**
|
||||
* 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
|
||||
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.
|
||||
*/
|
||||
export const executeQuery = async ({ queryId, parameters }) => {
|
||||
const query = await API.get({ url: `/api/queries/${queryId}` })
|
||||
const query = await fetchQueryDefinition(queryId)
|
||||
if (query?.datasourceId == null) {
|
||||
notificationStore.actions.error("That query couldn't be found")
|
||||
return
|
||||
|
@ -24,3 +24,10 @@ export const executeQuery = async ({ queryId, parameters }) => {
|
|||
}
|
||||
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 => {
|
||||
if (dataSource?.schema) {
|
||||
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 = {}
|
||||
}
|
||||
let newSchema = (await API.fetchDatasourceSchema(dataSource)) || {}
|
||||
|
||||
// Ensure there are "name" properties for all fields and that field schema
|
||||
// are objects
|
||||
let fixedSchema = {}
|
||||
Object.entries(schema || {}).forEach(([fieldName, fieldSchema]) => {
|
||||
Object.entries(newSchema).forEach(([fieldName, fieldSchema]) => {
|
||||
if (typeof fieldSchema === "string") {
|
||||
fixedSchema[fieldName] = {
|
||||
newSchema[fieldName] = {
|
||||
type: fieldSchema,
|
||||
name: fieldName,
|
||||
}
|
||||
} else {
|
||||
fixedSchema[fieldName] = {
|
||||
newSchema[fieldName] = {
|
||||
...fieldSchema,
|
||||
name: fieldName,
|
||||
}
|
||||
}
|
||||
})
|
||||
schema = fixedSchema
|
||||
schema = newSchema
|
||||
schemaLoaded = true
|
||||
}
|
||||
|
||||
|
|
|
@ -34,25 +34,34 @@
|
|||
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 () => {
|
||||
if (!dataSource?.tableId) {
|
||||
if (!dataSource) {
|
||||
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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue