diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/Snowflake.svelte b/packages/builder/src/components/backend/DatasourceNavigator/icons/Snowflake.svelte new file mode 100644 index 0000000000..fed9025126 --- /dev/null +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/Snowflake.svelte @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + diff --git a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js index 1a8df2507e..8003317212 100644 --- a/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js +++ b/packages/builder/src/components/backend/DatasourceNavigator/icons/index.js @@ -14,6 +14,7 @@ import Oracle from "./Oracle.svelte" import GoogleSheets from "./GoogleSheets.svelte" import Firebase from "./Firebase.svelte" import Redis from "./Redis.svelte" +import Snowflake from "./Snowflake.svelte" export default { BUDIBASE: Budibase, @@ -32,4 +33,5 @@ export default { GOOGLE_SHEETS: GoogleSheets, FIREBASE: Firebase, REDIS: Redis, + SNOWFLAKE: Snowflake, } diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 922955591a..8851cba771 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -184,6 +184,7 @@ export const IntegrationTypes = { GOOGLE_SHEETS: "GOOGLE_SHEETS", FIREBASE: "FIREBASE", REDIS: "REDIS", + SNOWFLAKE: "SNOWFLAKE", } export const IntegrationNames = { @@ -203,6 +204,7 @@ export const IntegrationNames = { [IntegrationTypes.GOOGLE_SHEETS]: "Google Sheets", [IntegrationTypes.FIREBASE]: "Firebase", [IntegrationTypes.REDIS]: "Redis", + [IntegrationTypes.SNOWFLAKE]: "Snowflake", } export const SchemaTypeOptions = [ diff --git a/packages/server/src/definitions/datasource.ts b/packages/server/src/definitions/datasource.ts index 23266991ee..f7f98c22e9 100644 --- a/packages/server/src/definitions/datasource.ts +++ b/packages/server/src/definitions/datasource.ts @@ -50,6 +50,7 @@ export enum SourceNames { GOOGLE_SHEETS = "GOOGLE_SHEETS", FIREBASE = "FIREBASE", REDIS = "REDIS", + SNOWFLAKE = "SNOWFLAKE", } export enum IncludeRelationships { diff --git a/packages/server/src/integrations/index.ts b/packages/server/src/integrations/index.ts index f3e7a5fc3a..af45ae5aff 100644 --- a/packages/server/src/integrations/index.ts +++ b/packages/server/src/integrations/index.ts @@ -12,6 +12,7 @@ const rest = require("./rest") const googlesheets = require("./googlesheets") const firebase = require("./firebase") const redis = require("./redis") +const snowflake = require("./snowflake") const { SourceNames } = require("../definitions/datasource") const environment = require("../environment") @@ -29,6 +30,7 @@ const DEFINITIONS = { [SourceNames.REST]: rest.schema, [SourceNames.FIREBASE]: firebase.schema, [SourceNames.REDIS]: redis.schema, + [SourceNames.SNOWFLAKE]: snowflake.schema, } const INTEGRATIONS = { @@ -47,6 +49,7 @@ const INTEGRATIONS = { [SourceNames.GOOGLE_SHEETS]: googlesheets.integration, [SourceNames.REDIS]: redis.integration, [SourceNames.FIREBASE]: firebase.integration, + [SourceNames.SNOWFLAKE]: snowflake.integration, } // optionally add oracle integration if the oracle binary can be installed diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts new file mode 100644 index 0000000000..cdde54e2f2 --- /dev/null +++ b/packages/server/src/integrations/snowflake.ts @@ -0,0 +1,98 @@ +import { Integration, QueryTypes, SqlQuery } from "../definitions/datasource" +const snowflake = require("snowflake-sdk") + +module SnowflakeModule { + interface SnowflakeConfig { + account: string + username: string + password: string + warehouse: string + database: string + schema: string + } + + const SCHEMA: Integration = { + docs: "https://developers.snowflake.com/", + description: + "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", + datasource: { + account: { + type: "string", + required: true, + }, + username: { + type: "string", + required: true, + }, + password: { + type: "password", + required: true, + }, + warehouse: { + type: "string", + required: true, + }, + database: { + type: "string", + required: true, + }, + schema: { + type: "string", + required: true, + }, + }, + query: { + create: { + type: QueryTypes.SQL, + }, + read: { + type: QueryTypes.SQL, + }, + update: { + type: QueryTypes.SQL, + }, + delete: { + type: QueryTypes.SQL, + }, + }, + } + + class SnowflakeIntegration { + private config: SnowflakeConfig + private client: any + + constructor(config: SnowflakeConfig) { + this.config = config + this.client = snowflake.createConnection(config) + } + + async connAsync(connection: any) { + return new Promise((resolve, reject) => { + connection.connect(function (err: any, conn: any) { + if (err) reject(err) + resolve(conn) + }) + }) + } + + async read(query: SqlQuery) { + let connection: any = await this.connAsync(this.client) + let response: any = await new Promise((resolve, reject) => + connection.execute({ + sqlText: query.sql, + streamResult: false, + complete: (err: any, statement: any, rows: any) => { + resolve({ rows }) + }, + }) + ) + return response.rows + } + } + + module.exports = { + schema: SCHEMA, + integration: SnowflakeIntegration, + } +}