diff --git a/packages/server/src/api/controllers/datasource.ts b/packages/server/src/api/controllers/datasource.ts index 76cc63bfb7..6961011b0d 100644 --- a/packages/server/src/api/controllers/datasource.ts +++ b/packages/server/src/api/controllers/datasource.ts @@ -1,9 +1,4 @@ -import { - DocumentType, - generateDatasourceID, - getQueryParams, - getTableParams, -} from "../../db/utils" +import { getQueryParams, getTableParams } from "../../db/utils" import { getIntegration } from "../../integrations" import { invalidateDynamicVariables } from "../../threads/utils" import { context, db as dbCore, events } from "@budibase/backend-core" @@ -24,7 +19,6 @@ import { } from "@budibase/types" import sdk from "../../sdk" import { builderSocket } from "../../websockets" -import { setupCreationAuth as googleSetupCreationAuth } from "../../integrations/googlesheets" import { isEqual } from "lodash" export async function fetch(ctx: UserCtx) { @@ -209,54 +203,18 @@ export async function update(ctx: UserCtx) { } } -const preSaveAction: Partial> = { - [SourceName.GOOGLE_SHEETS]: async (datasource: Datasource) => { - await googleSetupCreationAuth(datasource.config as any) - }, -} - export async function save( ctx: UserCtx ) { - const db = context.getAppDB() - const plus = ctx.request.body.datasource.plus - const fetchSchema = ctx.request.body.fetchSchema - const tablesFilter = ctx.request.body.tablesFilter - - const datasource = { - _id: generateDatasourceID({ plus }), - ...ctx.request.body.datasource, - type: plus ? DocumentType.DATASOURCE_PLUS : DocumentType.DATASOURCE, - } - - let errors: Record = {} - if (fetchSchema) { - const schema = await sdk.datasources.buildFilteredSchema( - datasource, - tablesFilter - ) - datasource.entities = schema.tables - setDefaultDisplayColumns(datasource) - errors = schema.errors - } - - if (preSaveAction[datasource.source]) { - await preSaveAction[datasource.source](datasource) - } - - const dbResp = await db.put( - sdk.tables.populateExternalTableSchemas(datasource) - ) - await events.datasource.created(datasource) - datasource._rev = dbResp.rev - - // Drain connection pools when configuration is changed - if (datasource.source) { - const source = await getIntegration(datasource.source) - if (source && source.pool) { - await source.pool.end() - } - } + const { + datasource: datasourceData, + fetchSchema, + tablesFilter, + } = ctx.request.body + const { datasource, errors } = await sdk.datasources.save(datasourceData, { + fetchSchema, + tablesFilter, + }) ctx.body = { datasource: await sdk.datasources.removeSecretSingle(datasource), diff --git a/packages/server/src/sdk/app/datasources/datasources.ts b/packages/server/src/sdk/app/datasources/datasources.ts index 51cceeab94..bb0d8bcb13 100644 --- a/packages/server/src/sdk/app/datasources/datasources.ts +++ b/packages/server/src/sdk/app/datasources/datasources.ts @@ -1,4 +1,4 @@ -import { context, db as dbCore } from "@budibase/backend-core" +import { context, db as dbCore, events } from "@budibase/backend-core" import { findHBSBlocks, processObjectSync } from "@budibase/string-templates" import { Datasource, @@ -14,16 +14,22 @@ import { } from "@budibase/types" import { cloneDeep } from "lodash/fp" import { getEnvironmentVariables } from "../../utils" -import { getDefinitions, getDefinition } from "../../../integrations" +import { + getDefinitions, + getDefinition, + getIntegration, +} from "../../../integrations" import merge from "lodash/merge" import { BudibaseInternalDB, + generateDatasourceID, getDatasourceParams, getDatasourcePlusParams, getTableParams, + DocumentType, } from "../../../db/utils" import sdk from "../../index" -import datasource from "../../../api/routes/datasource" +import { setupCreationAuth as googleSetupCreationAuth } from "../../../integrations/googlesheets" const ENV_VAR_PREFIX = "env." @@ -273,3 +279,75 @@ export async function getExternalDatasources(): Promise { return externalDatasources.rows.map(r => r.doc!) } + +export async function save( + datasource: Datasource, + opts?: { fetchSchema?: boolean; tablesFilter?: string[] } +): Promise<{ datasource: Datasource; errors: Record }> { + const db = context.getAppDB() + const plus = datasource.plus + + const fetchSchema = opts?.fetchSchema || false + const tablesFilter = opts?.tablesFilter || [] + + datasource = { + _id: generateDatasourceID({ plus }), + ...datasource, + type: plus ? DocumentType.DATASOURCE_PLUS : DocumentType.DATASOURCE, + } + + let errors: Record = {} + if (fetchSchema) { + const schema = await sdk.datasources.buildFilteredSchema( + datasource, + tablesFilter + ) + datasource.entities = schema.tables + setDefaultDisplayColumns(datasource) + errors = schema.errors + } + + if (preSaveAction[datasource.source]) { + await preSaveAction[datasource.source](datasource) + } + + const dbResp = await db.put( + sdk.tables.populateExternalTableSchemas(datasource) + ) + await events.datasource.created(datasource) + datasource._rev = dbResp.rev + + // Drain connection pools when configuration is changed + if (datasource.source) { + const source = await getIntegration(datasource.source) + if (source && source.pool) { + await source.pool.end() + } + } + + return { datasource, errors } +} + +const preSaveAction: Partial> = { + [SourceName.GOOGLE_SHEETS]: async (datasource: Datasource) => { + await googleSetupCreationAuth(datasource.config as any) + }, +} + +/** + * Make sure all datasource entities have a display name selected + */ +function setDefaultDisplayColumns(datasource: Datasource) { + // + for (let entity of Object.values(datasource.entities || {})) { + if (entity.primaryDisplay) { + continue + } + const notAutoColumn = Object.values(entity.schema).find( + schema => !schema.autocolumn + ) + if (notAutoColumn) { + entity.primaryDisplay = notAutoColumn.name + } + } +}