From 886b726627dd46ed235281c69660049074f9d067 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 15:21:33 +0200 Subject: [PATCH 01/10] Verify datasouce before saving --- .../builder/src/builderStore/datasource.js | 7 +++++ .../modals/DatasourceConfigModal.svelte | 29 +++++++++++++++++-- packages/frontend-core/src/api/datasources.js | 11 +++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/builderStore/datasource.js b/packages/builder/src/builderStore/datasource.js index e12b318e1c..6509216a5b 100644 --- a/packages/builder/src/builderStore/datasource.js +++ b/packages/builder/src/builderStore/datasource.js @@ -2,6 +2,7 @@ import { datasources, tables } from "../stores/backend" import { IntegrationNames } from "../constants/backend" import { get } from "svelte/store" import cloneDeep from "lodash/cloneDeepWith" +import { API } from "api" function prepareData(config) { let datasource = {} @@ -37,3 +38,9 @@ export async function createRestDatasource(integration) { const config = cloneDeep(integration) return saveDatasource(config) } + +export async function validateDatasourceConfig(config) { + const datasource = prepareData(config) + const resp = await API.validateDatasource(datasource) + return resp +} diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index edbe55178f..36b535c2b8 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -4,7 +4,10 @@ import IntegrationConfigForm from "components/backend/DatasourceNavigator/TableIntegrationMenu/IntegrationConfigForm.svelte" import { IntegrationNames } from "constants/backend" import cloneDeep from "lodash/cloneDeepWith" - import { saveDatasource as save } from "builderStore/datasource" + import { + saveDatasource as save, + validateDatasourceConfig, + } from "builderStore/datasource" import { onMount } from "svelte" export let integration @@ -18,6 +21,27 @@ $: name = IntegrationNames[datasource.type] || datasource.name || datasource.type + async function validateConfig() { + function displayError(message) { + notifications.error(message ?? "Error validating datasource") + } + + let connected = false + try { + if (!datasource.name) { + datasource.name = name + } + + const resp = await validateDatasourceConfig(datasource) + if (!resp.connected) { + displayError(resp.error) + } + connected = resp.connected + } catch (err) { + displayError(err?.message) + } + return connected + } async function saveDatasource() { try { if (!datasource.name) { @@ -40,7 +64,8 @@ saveDatasource()} + onConfirm={() => + validateConfig().then(connected => connected && saveDatasource())} onCancel={() => modal.show()} confirmText={datasource.plus ? "Save and fetch tables" diff --git a/packages/frontend-core/src/api/datasources.js b/packages/frontend-core/src/api/datasources.js index eda7b3c860..16d19c512f 100644 --- a/packages/frontend-core/src/api/datasources.js +++ b/packages/frontend-core/src/api/datasources.js @@ -58,4 +58,15 @@ export const buildDatasourceEndpoints = API => ({ url: `/api/datasources/${datasourceId}/${datasourceRev}`, }) }, + + /** + * Validate a datasource configuration + * @param datasource the datasource configuration to validate + */ + validateDatasource: async datasource => { + return await API.post({ + url: `/api/datasources/verify`, + body: { datasource }, + }) + }, }) From d6b00efa908b9646eaf09e20d391df7c7a4c6636 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 15:53:01 +0200 Subject: [PATCH 02/10] Verify datasouce before updating --- .../modals/DatasourceConfigModal.svelte | 15 ++++++------- .../datasource/[datasourceId]/index.svelte | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 36b535c2b8..f5d57285bb 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -22,16 +22,11 @@ IntegrationNames[datasource.type] || datasource.name || datasource.type async function validateConfig() { - function displayError(message) { + const displayError = message => notifications.error(message ?? "Error validating datasource") - } let connected = false try { - if (!datasource.name) { - datasource.name = name - } - const resp = await validateDatasourceConfig(datasource) if (!resp.connected) { displayError(resp.error) @@ -42,7 +37,12 @@ } return connected } + async function saveDatasource() { + const valid = await validateConfig() + if (!valid) { + return false + } try { if (!datasource.name) { datasource.name = name @@ -64,8 +64,7 @@ - validateConfig().then(connected => connected && saveDatasource())} + onConfirm={() => saveDatasource()} onCancel={() => modal.show()} confirmText={datasource.plus ? "Save and fetch tables" diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index 3a3a2495ed..511a7a81c8 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -20,6 +20,7 @@ import { isEqual } from "lodash" import { cloneDeep } from "lodash/fp" import ImportRestQueriesModal from "components/backend/DatasourceNavigator/modals/ImportRestQueriesModal.svelte" + import { API } from "api" const querySchema = { name: {}, @@ -45,7 +46,28 @@ } } + async function validateConfig() { + const displayError = message => + notifications.error(message ?? "Error validating datasource") + + let connected = false + try { + const resp = await API.validateDatasource(datasource) + if (!resp.connected) { + displayError(resp.error) + } + connected = resp.connected + } catch (err) { + displayError(err?.message) + } + return connected + } + const saveDatasource = async () => { + const valid = await validateConfig() + if (!valid) { + return false + } try { // Create datasource await datasources.save(datasource) From 3951788f7ed58931cf45fab2742c2557c44b3015 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 15:55:36 +0200 Subject: [PATCH 03/10] Improve messaging --- .../[application]/data/datasource/[datasourceId]/index.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index 511a7a81c8..850e92c772 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -54,7 +54,7 @@ try { const resp = await API.validateDatasource(datasource) if (!resp.connected) { - displayError(resp.error) + displayError(`Error connecting to the datasource: ` + resp.error) } connected = resp.connected } catch (err) { From 6659a697dec8ab2c8f254f86d33946fb65035588 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 15:58:50 +0200 Subject: [PATCH 04/10] Improve messaging --- .../DatasourceNavigator/modals/DatasourceConfigModal.svelte | 2 +- .../[application]/data/datasource/[datasourceId]/index.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index f5d57285bb..5394510122 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -29,7 +29,7 @@ try { const resp = await validateDatasourceConfig(datasource) if (!resp.connected) { - displayError(resp.error) + displayError(`Unable to connect - ${resp.error}`) } connected = resp.connected } catch (err) { diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index 850e92c772..f33860bb69 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -54,7 +54,7 @@ try { const resp = await API.validateDatasource(datasource) if (!resp.connected) { - displayError(`Error connecting to the datasource: ` + resp.error) + displayError(`Unable to connect - ${resp.error}`) } connected = resp.connected } catch (err) { From 3c3f67c3006194da916a46fb6e9e2756f8e066c5 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 16:19:36 +0200 Subject: [PATCH 05/10] Handle name change on onboarding --- .../apps/onboarding/_components/NamePanel.svelte | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/builder/src/pages/builder/portal/apps/onboarding/_components/NamePanel.svelte b/packages/builder/src/pages/builder/portal/apps/onboarding/_components/NamePanel.svelte index 1264b63531..0641e28766 100644 --- a/packages/builder/src/pages/builder/portal/apps/onboarding/_components/NamePanel.svelte +++ b/packages/builder/src/pages/builder/portal/apps/onboarding/_components/NamePanel.svelte @@ -31,6 +31,18 @@ return "Invalid URL" } } + + $: urlManuallySet = false + + const updateUrl = event => { + const appName = event.detail + if (urlManuallySet) { + return + } + + const parsedUrl = appName.toLowerCase().replace(/\s+/g, "-") + url = encodeURI(parsedUrl) + }
@@ -43,11 +55,13 @@ bind:value={name} bind:error={nameError} validate={validateName} + on:change={updateUrl} label="Name" /> (urlManuallySet = true)} validate={validateUrl} label="URL" /> From 2b2b25290022b1afb273d683360aff47e4a4c6d3 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 16:43:10 +0200 Subject: [PATCH 06/10] Update messages --- .../DatasourceNavigator/modals/DatasourceConfigModal.svelte | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 5394510122..09eb97a497 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -66,12 +66,9 @@ title={`Connect to ${name}`} onConfirm={() => saveDatasource()} onCancel={() => modal.show()} - confirmText={datasource.plus - ? "Save and fetch tables" - : "Save and continue to query"} + confirmText={datasource.plus ? "Connect" : "Save and continue to query"} cancelText="Back" showSecondaryButton={datasource.plus} - secondaryButtonText={datasource.plus ? "Skip table fetch" : undefined} secondaryAction={() => { skipFetch = true saveDatasource() From 7be824b2e6a7ca24ae1ccc1ffeca4aa50d9249f1 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 16:45:30 +0200 Subject: [PATCH 07/10] Remove secondary action --- .../modals/DatasourceConfigModal.svelte | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index 09eb97a497..d9b39e95a3 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -15,7 +15,6 @@ // kill the reference so the input isn't saved let datasource = cloneDeep(integration) - let skipFetch = false let isValid = false $: name = @@ -47,7 +46,7 @@ if (!datasource.name) { datasource.name = name } - const resp = await save(datasource, skipFetch) + const resp = await save(datasource) $goto(`./datasource/${resp._id}`) notifications.success(`Datasource updated successfully.`) } catch (err) { @@ -56,10 +55,6 @@ return false } } - - onMount(() => { - skipFetch = false - }) { - skipFetch = true - saveDatasource() - return true - }} size="L" disabled={!isValid} > From 0c97f61cc890a0a8ecacd4efa5a8ade072385e46 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 23 May 2023 18:23:37 +0200 Subject: [PATCH 08/10] Validate feature toggle --- .../modals/CreateDatasourceModal.svelte | 1 + .../modals/DatasourceConfigModal.svelte | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte index a07829eb58..290f25b941 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/CreateDatasourceModal.svelte @@ -53,6 +53,7 @@ config, schema: selected.datasource, auth: selected.auth, + features: selected.features || [], } if (selected.friendlyName) { integration.name = selected.friendlyName diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index d9b39e95a3..ee1f97bf40 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -8,7 +8,6 @@ saveDatasource as save, validateDatasourceConfig, } from "builderStore/datasource" - import { onMount } from "svelte" export let integration export let modal @@ -37,10 +36,14 @@ return connected } + $: shouldValidate = integration.features?.find(f => f === "connection") + async function saveDatasource() { - const valid = await validateConfig() - if (!valid) { - return false + if (shouldValidate) { + const valid = await validateConfig() + if (!valid) { + return false + } } try { if (!datasource.name) { @@ -48,7 +51,7 @@ } const resp = await save(datasource) $goto(`./datasource/${resp._id}`) - notifications.success(`Datasource updated successfully.`) + notifications.success(`Datasource created successfully.`) } catch (err) { notifications.error(err?.message ?? "Error saving datasource") // prevent the modal from closing @@ -61,7 +64,11 @@ title={`Connect to ${name}`} onConfirm={() => saveDatasource()} onCancel={() => modal.show()} - confirmText={datasource.plus ? "Connect" : "Save and continue to query"} + confirmText={datasource.plus + ? shouldValidate + ? "Connect" + : "Save and continue" + : "Save and continue to query"} cancelText="Back" showSecondaryButton={datasource.plus} size="L" From 237cda064c90ab79ef3f61ca576da2da9a52b496 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 24 May 2023 10:50:51 +0200 Subject: [PATCH 09/10] Simplify integration features --- .../modals/DatasourceConfigModal.svelte | 11 +++-------- .../data/datasource/[datasourceId]/index.svelte | 9 ++++++--- packages/builder/src/stores/portal/features.js | 2 +- packages/server/src/integrations/airtable.ts | 4 +++- packages/server/src/integrations/arangodb.ts | 4 +++- packages/server/src/integrations/couchdb.ts | 4 +++- packages/server/src/integrations/dynamodb.ts | 4 +++- packages/server/src/integrations/elasticsearch.ts | 4 +++- packages/server/src/integrations/firebase.ts | 4 +++- packages/server/src/integrations/googlesheets.ts | 8 ++++---- .../server/src/integrations/microsoftSqlServer.ts | 8 ++++---- packages/server/src/integrations/mongodb.ts | 4 +++- packages/server/src/integrations/mysql.ts | 8 ++++---- packages/server/src/integrations/oracle.ts | 8 ++++---- packages/server/src/integrations/postgres.ts | 8 ++++---- packages/server/src/integrations/redis.ts | 4 +++- packages/server/src/integrations/s3.ts | 4 +++- packages/server/src/integrations/snowflake.ts | 4 +++- packages/types/src/sdk/datasources.ts | 2 +- 19 files changed, 61 insertions(+), 43 deletions(-) diff --git a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte index ee1f97bf40..e75109b1be 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte +++ b/packages/builder/src/components/backend/DatasourceNavigator/modals/DatasourceConfigModal.svelte @@ -8,6 +8,7 @@ saveDatasource as save, validateDatasourceConfig, } from "builderStore/datasource" + import { DatasourceFeature } from "@budibase/types" export let integration export let modal @@ -36,10 +37,8 @@ return connected } - $: shouldValidate = integration.features?.find(f => f === "connection") - async function saveDatasource() { - if (shouldValidate) { + if (integration.features[DatasourceFeature.CONNECTION_CHECKING]) { const valid = await validateConfig() if (!valid) { return false @@ -64,11 +63,7 @@ title={`Connect to ${name}`} onConfirm={() => saveDatasource()} onCancel={() => modal.show()} - confirmText={datasource.plus - ? shouldValidate - ? "Connect" - : "Save and continue" - : "Save and continue to query"} + confirmText={datasource.plus ? "Connect" : "Save and continue to query"} cancelText="Back" showSecondaryButton={datasource.plus} size="L" diff --git a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte index f33860bb69..a853fcea0c 100644 --- a/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/data/datasource/[datasourceId]/index.svelte @@ -21,6 +21,7 @@ import { cloneDeep } from "lodash/fp" import ImportRestQueriesModal from "components/backend/DatasourceNavigator/modals/ImportRestQueriesModal.svelte" import { API } from "api" + import { DatasourceFeature } from "@budibase/types" const querySchema = { name: {}, @@ -64,9 +65,11 @@ } const saveDatasource = async () => { - const valid = await validateConfig() - if (!valid) { - return false + if (integration.features[DatasourceFeature.CONNECTION_CHECKING]) { + const valid = await validateConfig() + if (!valid) { + return false + } } try { // Create datasource diff --git a/packages/builder/src/stores/portal/features.js b/packages/builder/src/stores/portal/features.js index 4334fda3c4..e2ecb4c66a 100644 --- a/packages/builder/src/stores/portal/features.js +++ b/packages/builder/src/stores/portal/features.js @@ -1,7 +1,7 @@ import { writable } from "svelte/store" import { API } from "api" import { licensing } from "./licensing" -import { ConfigType } from "../../../../types/src/documents" +import { ConfigType } from "@budibase/types" export const createFeatureStore = () => { const internalStore = writable({ diff --git a/packages/server/src/integrations/airtable.ts b/packages/server/src/integrations/airtable.ts index a102caab76..a404a84b43 100644 --- a/packages/server/src/integrations/airtable.ts +++ b/packages/server/src/integrations/airtable.ts @@ -20,7 +20,9 @@ const SCHEMA: Integration = { "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.", friendlyName: "Airtable", type: "Spreadsheet", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { apiKey: { type: DatasourceFieldType.PASSWORD, diff --git a/packages/server/src/integrations/arangodb.ts b/packages/server/src/integrations/arangodb.ts index b486748a68..0127d25632 100644 --- a/packages/server/src/integrations/arangodb.ts +++ b/packages/server/src/integrations/arangodb.ts @@ -23,7 +23,9 @@ const SCHEMA: Integration = { type: "Non-relational", description: "ArangoDB is a scalable open-source multi-model database natively supporting graph, document and search. All supported data models & access patterns can be combined in queries allowing for maximal flexibility. ", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { url: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/couchdb.ts b/packages/server/src/integrations/couchdb.ts index 4ccbd5456d..b55468fd93 100644 --- a/packages/server/src/integrations/couchdb.ts +++ b/packages/server/src/integrations/couchdb.ts @@ -20,7 +20,9 @@ const SCHEMA: Integration = { type: "Non-relational", description: "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { url: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts index 28b42c7a54..bede4a7f7c 100644 --- a/packages/server/src/integrations/dynamodb.ts +++ b/packages/server/src/integrations/dynamodb.ts @@ -25,7 +25,9 @@ const SCHEMA: Integration = { "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.", friendlyName: "DynamoDB", type: "Non-relational", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { region: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/elasticsearch.ts b/packages/server/src/integrations/elasticsearch.ts index af52799c51..7ae0295298 100644 --- a/packages/server/src/integrations/elasticsearch.ts +++ b/packages/server/src/integrations/elasticsearch.ts @@ -22,7 +22,9 @@ const SCHEMA: Integration = { "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.", friendlyName: "ElasticSearch", type: "Non-relational", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { url: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/firebase.ts b/packages/server/src/integrations/firebase.ts index 3907275f41..3f03f295a9 100644 --- a/packages/server/src/integrations/firebase.ts +++ b/packages/server/src/integrations/firebase.ts @@ -20,7 +20,9 @@ const SCHEMA: Integration = { type: "Non-relational", description: "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { email: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index d1f3f9e950..aa1c2fb66f 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -66,10 +66,10 @@ const SCHEMA: Integration = { "Create and collaborate on online spreadsheets in real-time and from any device.", friendlyName: "Google Sheets", type: "Spreadsheet", - features: [ - DatasourceFeature.CONNECTION_CHECKING, - DatasourceFeature.FETCH_TABLE_NAMES, - ], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + [DatasourceFeature.FETCH_TABLE_NAMES]: true, + }, datasource: { spreadsheetId: { display: "Google Sheet URL", diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index a83630afbb..291aad8631 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -40,10 +40,10 @@ const SCHEMA: Integration = { "Microsoft SQL Server is a relational database management system developed by Microsoft. ", friendlyName: "MS SQL Server", type: "Relational", - features: [ - DatasourceFeature.CONNECTION_CHECKING, - DatasourceFeature.FETCH_TABLE_NAMES, - ], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + [DatasourceFeature.FETCH_TABLE_NAMES]: true, + }, datasource: { user: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/mongodb.ts b/packages/server/src/integrations/mongodb.ts index ee7302c501..417aa61f41 100644 --- a/packages/server/src/integrations/mongodb.ts +++ b/packages/server/src/integrations/mongodb.ts @@ -40,7 +40,9 @@ const getSchema = () => { type: "Non-relational", description: "MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { connectionString: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/mysql.ts b/packages/server/src/integrations/mysql.ts index d83ce300d3..0dbd628ea3 100644 --- a/packages/server/src/integrations/mysql.ts +++ b/packages/server/src/integrations/mysql.ts @@ -36,10 +36,10 @@ const SCHEMA: Integration = { type: "Relational", description: "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ", - features: [ - DatasourceFeature.CONNECTION_CHECKING, - DatasourceFeature.FETCH_TABLE_NAMES, - ], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + [DatasourceFeature.FETCH_TABLE_NAMES]: true, + }, datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/oracle.ts b/packages/server/src/integrations/oracle.ts index afb7021a74..d8c366814f 100644 --- a/packages/server/src/integrations/oracle.ts +++ b/packages/server/src/integrations/oracle.ts @@ -50,10 +50,10 @@ const SCHEMA: Integration = { type: "Relational", description: "Oracle Database is an object-relational database management system developed by Oracle Corporation", - features: [ - DatasourceFeature.CONNECTION_CHECKING, - DatasourceFeature.FETCH_TABLE_NAMES, - ], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + [DatasourceFeature.FETCH_TABLE_NAMES]: true, + }, datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/postgres.ts b/packages/server/src/integrations/postgres.ts index 8633d78a88..47295716e6 100644 --- a/packages/server/src/integrations/postgres.ts +++ b/packages/server/src/integrations/postgres.ts @@ -52,10 +52,10 @@ const SCHEMA: Integration = { type: "Relational", description: "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.", - features: [ - DatasourceFeature.CONNECTION_CHECKING, - DatasourceFeature.FETCH_TABLE_NAMES, - ], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + [DatasourceFeature.FETCH_TABLE_NAMES]: true, + }, datasource: { host: { type: DatasourceFieldType.STRING, diff --git a/packages/server/src/integrations/redis.ts b/packages/server/src/integrations/redis.ts index d71f66edc1..26666ac800 100644 --- a/packages/server/src/integrations/redis.ts +++ b/packages/server/src/integrations/redis.ts @@ -21,7 +21,9 @@ const SCHEMA: Integration = { "Redis is a caching tool, providing powerful key-value store capabilities.", friendlyName: "Redis", type: "Non-relational", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { host: { type: "string", diff --git a/packages/server/src/integrations/s3.ts b/packages/server/src/integrations/s3.ts index 0f9848ed59..df9d21aab2 100644 --- a/packages/server/src/integrations/s3.ts +++ b/packages/server/src/integrations/s3.ts @@ -24,7 +24,9 @@ const SCHEMA: Integration = { "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.", friendlyName: "Amazon S3", type: "Object store", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { region: { type: "string", diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index 9b743131ae..73d3d4f6af 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -22,7 +22,9 @@ const SCHEMA: Integration = { "Snowflake is a solution for data warehousing, data lakes, data engineering, data science, data application development, and securely sharing and consuming shared data.", friendlyName: "Snowflake", type: "Relational", - features: [DatasourceFeature.CONNECTION_CHECKING], + features: { + [DatasourceFeature.CONNECTION_CHECKING]: true, + }, datasource: { account: { type: "string", diff --git a/packages/types/src/sdk/datasources.ts b/packages/types/src/sdk/datasources.ts index 24ccea7e83..50ea063ca3 100644 --- a/packages/types/src/sdk/datasources.ts +++ b/packages/types/src/sdk/datasources.ts @@ -116,7 +116,7 @@ export interface Integration { docs: string plus?: boolean auth?: { type: string } - features?: DatasourceFeature[] + features?: Partial> relationships?: boolean description: string friendlyName: string From d3eb262bed58a535261017bb83c17a7652f66ccd Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Wed, 24 May 2023 11:07:49 +0200 Subject: [PATCH 10/10] Validate onboarding --- .../portal/apps/onboarding/index.svelte | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte b/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte index 546f5f57ba..18253bb8a2 100644 --- a/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte +++ b/packages/builder/src/pages/builder/portal/apps/onboarding/index.svelte @@ -18,6 +18,8 @@ import { Roles } from "constants/backend" import Spinner from "components/common/Spinner.svelte" import { helpers } from "@budibase/shared-core" + import { validateDatasourceConfig } from "builderStore/datasource" + import { DatasourceFeature } from "@budibase/types" let name = "My first app" let url = "my-first-app" @@ -108,7 +110,24 @@ isGoogle, }) => { let app + try { + if ( + datasourceConfig && + plusIntegrations[stage].features[DatasourceFeature.CONNECTION_CHECKING] + ) { + const resp = await validateDatasourceConfig({ + config: datasourceConfig, + type: stage, + }) + if (!resp.connected) { + notifications.error( + `Unable to connect - ${resp.error ?? "Error validating datasource"}` + ) + return false + } + } + app = await createApp(useSampleData) let datasource