Merge pull request #12729 from Budibase/BUDI-7571/refactor-fetching-external-ds

Refactor datasouce code
This commit is contained in:
Adria Navarro 2024-01-08 16:36:58 +01:00 committed by GitHub
commit 5c66e51c5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 72 deletions

View File

@ -14,10 +14,7 @@ import {
DatasourcePlus, DatasourcePlus,
FetchDatasourceInfoRequest, FetchDatasourceInfoRequest,
FetchDatasourceInfoResponse, FetchDatasourceInfoResponse,
IntegrationBase,
Schema,
SourceName, SourceName,
Table,
UpdateDatasourceResponse, UpdateDatasourceResponse,
UserCtx, UserCtx,
VerifyDatasourceRequest, VerifyDatasourceRequest,
@ -28,65 +25,6 @@ import { builderSocket } from "../../websockets"
import { setupCreationAuth as googleSetupCreationAuth } from "../../integrations/googlesheets" import { setupCreationAuth as googleSetupCreationAuth } from "../../integrations/googlesheets"
import { isEqual } from "lodash" import { isEqual } from "lodash"
async function getConnector(
datasource: Datasource
): Promise<IntegrationBase | DatasourcePlus> {
const Connector = await getIntegration(datasource.source)
// can't enrich if it doesn't have an ID yet
if (datasource._id) {
datasource = await sdk.datasources.enrich(datasource)
}
// Connect to the DB and build the schema
return new Connector(datasource.config)
}
async function getAndMergeDatasource(datasource: Datasource) {
let existingDatasource: undefined | Datasource
if (datasource._id) {
existingDatasource = await sdk.datasources.get(datasource._id)
}
let enrichedDatasource = datasource
if (existingDatasource) {
enrichedDatasource = sdk.datasources.mergeConfigs(
datasource,
existingDatasource
)
}
return await sdk.datasources.enrich(enrichedDatasource)
}
async function buildSchemaHelper(datasource: Datasource): Promise<Schema> {
const connector = (await getConnector(datasource)) as DatasourcePlus
return await connector.buildSchema(
datasource._id!,
datasource.entities! as Record<string, Table>
)
}
async function buildFilteredSchema(
datasource: Datasource,
filter?: string[]
): Promise<Schema> {
let schema = await buildSchemaHelper(datasource)
if (!filter) {
return schema
}
let filteredSchema: Schema = { tables: {}, errors: {} }
for (let key in schema.tables) {
if (filter.some(filter => filter.toLowerCase() === key.toLowerCase())) {
filteredSchema.tables[key] = schema.tables[key]
}
}
for (let key in schema.errors) {
if (filter.some(filter => filter.toLowerCase() === key.toLowerCase())) {
filteredSchema.errors[key] = schema.errors[key]
}
}
return filteredSchema
}
export async function fetch(ctx: UserCtx) { export async function fetch(ctx: UserCtx) {
ctx.body = await sdk.datasources.fetch() ctx.body = await sdk.datasources.fetch()
} }
@ -95,8 +33,10 @@ export async function verify(
ctx: UserCtx<VerifyDatasourceRequest, VerifyDatasourceResponse> ctx: UserCtx<VerifyDatasourceRequest, VerifyDatasourceResponse>
) { ) {
const { datasource } = ctx.request.body const { datasource } = ctx.request.body
const enrichedDatasource = await getAndMergeDatasource(datasource) const enrichedDatasource = await sdk.datasources.getAndMergeDatasource(
const connector = await getConnector(enrichedDatasource) datasource
)
const connector = await sdk.datasources.getConnector(enrichedDatasource)
if (!connector.testConnection) { if (!connector.testConnection) {
ctx.throw(400, "Connection information verification not supported") ctx.throw(400, "Connection information verification not supported")
} }
@ -112,8 +52,12 @@ export async function information(
ctx: UserCtx<FetchDatasourceInfoRequest, FetchDatasourceInfoResponse> ctx: UserCtx<FetchDatasourceInfoRequest, FetchDatasourceInfoResponse>
) { ) {
const { datasource } = ctx.request.body const { datasource } = ctx.request.body
const enrichedDatasource = await getAndMergeDatasource(datasource) const enrichedDatasource = await sdk.datasources.getAndMergeDatasource(
const connector = (await getConnector(enrichedDatasource)) as DatasourcePlus datasource
)
const connector = (await sdk.datasources.getConnector(
enrichedDatasource
)) as DatasourcePlus
if (!connector.getTableNames) { if (!connector.getTableNames) {
ctx.throw(400, "Table name fetching not supported by datasource") ctx.throw(400, "Table name fetching not supported by datasource")
} }
@ -128,7 +72,10 @@ export async function buildSchemaFromDb(ctx: UserCtx) {
const tablesFilter = ctx.request.body.tablesFilter const tablesFilter = ctx.request.body.tablesFilter
const datasource = await sdk.datasources.get(ctx.params.datasourceId) const datasource = await sdk.datasources.get(ctx.params.datasourceId)
const { tables, errors } = await buildFilteredSchema(datasource, tablesFilter) const { tables, errors } = await sdk.datasources.buildFilteredSchema(
datasource,
tablesFilter
)
datasource.entities = tables datasource.entities = tables
setDefaultDisplayColumns(datasource) setDefaultDisplayColumns(datasource)
@ -280,7 +227,10 @@ export async function save(
let errors: Record<string, string> = {} let errors: Record<string, string> = {}
if (fetchSchema) { if (fetchSchema) {
const schema = await buildFilteredSchema(datasource, tablesFilter) const schema = await sdk.datasources.buildFilteredSchema(
datasource,
tablesFilter
)
datasource.entities = schema.tables datasource.entities = schema.tables
setDefaultDisplayColumns(datasource) setDefaultDisplayColumns(datasource)
errors = schema.errors errors = schema.errors
@ -384,8 +334,10 @@ export async function query(ctx: UserCtx) {
export async function getExternalSchema(ctx: UserCtx) { export async function getExternalSchema(ctx: UserCtx) {
const datasource = await sdk.datasources.get(ctx.params.datasourceId) const datasource = await sdk.datasources.get(ctx.params.datasourceId)
const enrichedDatasource = await getAndMergeDatasource(datasource) const enrichedDatasource = await sdk.datasources.getAndMergeDatasource(
const connector = await getConnector(enrichedDatasource) datasource
)
const connector = await sdk.datasources.getConnector(enrichedDatasource)
if (!connector.getExternalSchema) { if (!connector.getExternalSchema) {
ctx.throw(400, "Datasource does not support exporting external schema") ctx.throw(400, "Datasource does not support exporting external schema")

View File

@ -362,8 +362,8 @@ class PostgresIntegration extends Sql implements DatasourcePlus {
}) })
} }
let finalizedTables = finaliseExternalTables(tables, entities) const finalizedTables = finaliseExternalTables(tables, entities)
let errors = checkExternalTables(finalizedTables) const errors = checkExternalTables(finalizedTables)
return { tables: finalizedTables, errors } return { tables: finalizedTables, errors }
} catch (err) { } catch (err) {
// @ts-ignore // @ts-ignore

View File

@ -1,5 +1,7 @@
import * as datasources from "./datasources" import * as datasources from "./datasources"
import * as plus from "./plus"
export default { export default {
...datasources, ...datasources,
...plus,
} }

View File

@ -0,0 +1,62 @@
import {
Datasource,
DatasourcePlus,
IntegrationBase,
Schema,
} from "@budibase/types"
import * as datasources from "./datasources"
import { getIntegration } from "../../../integrations"
export async function buildFilteredSchema(
datasource: Datasource,
filter?: string[]
): Promise<Schema> {
const schema = await buildSchemaHelper(datasource)
if (!filter) {
return schema
}
let filteredSchema: Schema = { tables: {}, errors: {} }
for (let key in schema.tables) {
if (filter.some(filter => filter.toLowerCase() === key.toLowerCase())) {
filteredSchema.tables[key] = schema.tables[key]
}
}
for (let key in schema.errors) {
if (filter.some(filter => filter.toLowerCase() === key.toLowerCase())) {
filteredSchema.errors[key] = schema.errors[key]
}
}
return filteredSchema
}
async function buildSchemaHelper(datasource: Datasource): Promise<Schema> {
const connector = (await getConnector(datasource)) as DatasourcePlus
const externalSchema = await connector.buildSchema(
datasource._id!,
datasource.entities!
)
return externalSchema
}
export async function getConnector(
datasource: Datasource
): Promise<IntegrationBase | DatasourcePlus> {
const Connector = await getIntegration(datasource.source)
// can't enrich if it doesn't have an ID yet
if (datasource._id) {
datasource = await datasources.enrich(datasource)
}
// Connect to the DB and build the schema
return new Connector(datasource.config)
}
export async function getAndMergeDatasource(datasource: Datasource) {
if (datasource._id) {
const existingDatasource = await datasources.get(datasource._id)
datasource = datasources.mergeConfigs(datasource, existingDatasource)
}
return await datasources.enrich(datasource)
}