Add support for nested provider, field and jsonarray datasource types in new data fetch model

This commit is contained in:
Andrew Kingston 2022-01-04 15:02:43 +00:00
parent db55074b0a
commit 6e3f217fbb
5 changed files with 120 additions and 67 deletions

View File

@ -0,0 +1,44 @@
import DataFetch from "./DataFetch.js"
export default class FieldFetch extends DataFetch {
static async getDefinition(datasource) {
// Field sources have their schema statically defined
let schema
if (datasource.fieldType === "attachment") {
schema = {
url: {
type: "string",
},
name: {
type: "string",
},
}
} else if (datasource.fieldType === "array") {
schema = {
value: {
type: "string",
},
}
}
return { schema }
}
async getData() {
const { datasource } = this.options
// These sources will be available directly from context
const data = datasource?.value || []
let rows = []
if (Array.isArray(data) && data[0] && typeof data[0] !== "object") {
rows = data.map(value => ({ value }))
} else {
rows = data
}
return {
rows: rows || [],
hasNextPage: false,
cursor: null,
}
}
}

View File

@ -0,0 +1,13 @@
import FieldFetch from "./FieldFetch.js"
import { fetchTableDefinition } from "api"
import { getJSONArrayDatasourceSchema } from "builder/src/builderStore/jsonUtils"
export default class JSONArrayFetch extends FieldFetch {
static async getDefinition(datasource) {
// JSON arrays need their table definitions fetched.
// We can then extract their schema as a subset of the table schema.
const table = await fetchTableDefinition(datasource.tableId)
const schema = getJSONArrayDatasourceSchema(table?.schema, datasource)
return { schema }
}
}

View File

@ -0,0 +1,20 @@
import DataFetch from "./DataFetch.js"
export default class NestedProviderFetch extends DataFetch {
static async getDefinition(datasource) {
// Nested providers should already have exposed their own schema
return {
schema: datasource?.value?.schema,
}
}
async getData() {
const { datasource } = this.options
// Pull the rows from the existing data provider
return {
rows: datasource?.value?.rows || [],
hasNextPage: false,
cursor: null,
}
}
}

View File

@ -2,12 +2,18 @@ import TableFetch from "./TableFetch.js"
import ViewFetch from "./ViewFetch.js" import ViewFetch from "./ViewFetch.js"
import QueryFetch from "./QueryFetch.js" import QueryFetch from "./QueryFetch.js"
import RelationshipFetch from "./RelationshipFetch.js" import RelationshipFetch from "./RelationshipFetch.js"
import NestedProviderFetch from "./NestedProviderFetch.js"
import FieldFetch from "./FieldFetch.js"
import JSONArrayFetch from "./JSONArrayFetch.js"
const DataFetchMap = { const DataFetchMap = {
table: TableFetch, table: TableFetch,
view: ViewFetch, view: ViewFetch,
query: QueryFetch, query: QueryFetch,
link: RelationshipFetch, link: RelationshipFetch,
provider: NestedProviderFetch,
field: FieldFetch,
jsonarray: JSONArrayFetch,
} }
export const fetchData = (datasource, options) => { export const fetchData = (datasource, options) => {

View File

@ -1,83 +1,53 @@
import { import { convertJSONSchemaToTableSchema } from "builder/src/builderStore/jsonUtils"
convertJSONSchemaToTableSchema,
getJSONArrayDatasourceSchema,
} from "builder/src/builderStore/jsonUtils"
import { fetchTableDefinition } from "api"
import TableFetch from "./fetch/TableFetch.js" import TableFetch from "./fetch/TableFetch.js"
import ViewFetch from "./fetch/ViewFetch.js" import ViewFetch from "./fetch/ViewFetch.js"
import QueryFetch from "./fetch/QueryFetch.js" import QueryFetch from "./fetch/QueryFetch.js"
import RelationshipFetch from "./fetch/RelationshipFetch.js"
import NestedProviderFetch from "./fetch/NestedProviderFetch.js"
import FieldFetch from "./fetch/FieldFetch.js"
import JSONArrayFetch from "./fetch/JSONArrayFetch.js"
/** /**
* Fetches the schema of any kind of datasource. * Fetches the schema of any kind of datasource.
* All datasource fetch classes implement their own functionality to get the
* schema of a datasource of their respective types.
*/ */
export const fetchDatasourceSchema = async datasource => { export const fetchDatasourceSchema = async datasource => {
const type = datasource?.type
let schema
// Nested providers should already have exposed their own schema
if (type === "provider") {
schema = datasource.value?.schema
}
// Field sources have their schema statically defined
if (type === "field") {
if (datasource.fieldType === "attachment") {
schema = {
url: {
type: "string",
},
name: {
type: "string",
},
}
} else if (datasource.fieldType === "array") {
schema = {
value: {
type: "string",
},
}
}
}
// JSON arrays need their table definitions fetched.
// We can then extract their schema as a subset of the table schema.
if (type === "jsonarray") {
const table = await fetchTableDefinition(datasource.tableId)
schema = getJSONArrayDatasourceSchema(table?.schema, datasource)
}
// All normal datasource schema can use their corresponding implementations
// in the data fetch classes
const handler = { const handler = {
table: TableFetch, table: TableFetch,
link: TableFetch,
view: ViewFetch, view: ViewFetch,
query: QueryFetch, query: QueryFetch,
}[type] link: RelationshipFetch,
if (handler) { provider: NestedProviderFetch,
const definition = await handler.getDefinition(datasource) field: FieldFetch,
schema = handler.getSchema(datasource, definition) jsonarray: JSONArrayFetch,
}[datasource?.type]
if (!handler) {
return null
}
// Get the datasource definition and then schema
const definition = await handler.getDefinition(datasource)
const schema = handler.getSchema(datasource, definition)
if (!schema) {
return null
} }
// Check for any JSON fields so we can add any top level properties // Check for any JSON fields so we can add any top level properties
if (schema) { let jsonAdditions = {}
let jsonAdditions = {} Object.keys(schema).forEach(fieldKey => {
Object.keys(schema).forEach(fieldKey => { const fieldSchema = schema[fieldKey]
const fieldSchema = schema[fieldKey] if (fieldSchema?.type === "json") {
if (fieldSchema?.type === "json") { const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, {
const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, { squashObjects: true,
squashObjects: true, })
}) Object.keys(jsonSchema).forEach(jsonKey => {
Object.keys(jsonSchema).forEach(jsonKey => { jsonAdditions[`${fieldKey}.${jsonKey}`] = {
jsonAdditions[`${fieldKey}.${jsonKey}`] = { type: jsonSchema[jsonKey].type,
type: jsonSchema[jsonKey].type, nestedJSON: true,
nestedJSON: true, }
} })
}) }
} })
}) return { ...schema, ...jsonAdditions }
return { ...schema, ...jsonAdditions }
}
return null
} }