forked from tsai/budibase
5 changed files with 119 additions and 66 deletions
@ -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, |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 } |
||||
|
} |
||||
|
} |
||||
@ -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, |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
} |
} |
||||
|
|
||||
// Check for any JSON fields so we can add any top level properties
|
// Get the datasource definition and then schema
|
||||
if (schema) { |
const definition = await handler.getDefinition(datasource) |
||||
let jsonAdditions = {} |
const schema = handler.getSchema(datasource, definition) |
||||
Object.keys(schema).forEach(fieldKey => { |
if (!schema) { |
||||
const fieldSchema = schema[fieldKey] |
return null |
||||
if (fieldSchema?.type === "json") { |
|
||||
const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, { |
|
||||
squashObjects: true, |
|
||||
}) |
|
||||
Object.keys(jsonSchema).forEach(jsonKey => { |
|
||||
jsonAdditions[`${fieldKey}.${jsonKey}`] = { |
|
||||
type: jsonSchema[jsonKey].type, |
|
||||
nestedJSON: true, |
|
||||
} |
|
||||
}) |
|
||||
} |
|
||||
}) |
|
||||
return { ...schema, ...jsonAdditions } |
|
||||
} |
} |
||||
|
|
||||
return null |
// Check for any JSON fields so we can add any top level properties
|
||||
|
let jsonAdditions = {} |
||||
|
Object.keys(schema).forEach(fieldKey => { |
||||
|
const fieldSchema = schema[fieldKey] |
||||
|
if (fieldSchema?.type === "json") { |
||||
|
const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, { |
||||
|
squashObjects: true, |
||||
|
}) |
||||
|
Object.keys(jsonSchema).forEach(jsonKey => { |
||||
|
jsonAdditions[`${fieldKey}.${jsonKey}`] = { |
||||
|
type: jsonSchema[jsonKey].type, |
||||
|
nestedJSON: true, |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
return { ...schema, ...jsonAdditions } |
||||
} |
} |
||||
|
|||||
Loading…
Reference in new issue