Merge pull request #1015 from Budibase/mysql-connector

MySQL integration and self hosted deploy event
This commit is contained in:
Martin McKeaveney 2021-01-26 16:17:09 +00:00 committed by GitHub
commit 4cd85e2c94
13 changed files with 225 additions and 911 deletions

View File

@ -0,0 +1,83 @@
<script>
export let width = "100"
export let height = "100"
</script>
<svg
{width}
{height}
viewBox="0 0 147 147"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<path
d="M128.244 27.5625H83.3444L74.1569
45.9375H22.9688V124.031H137.812V27.5625H128.244ZM128.625
45.9375H92.7478L97.5621 36.75H128.625V45.9375Z"
fill="#2A4B59" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M73.5827 67.597C72.6671 67.5874 71.7543 67.6986 70.8678
67.9278V68.061H70.9964C71.6302 69.0199 72.3383 69.9277 73.1141
70.7759C73.647 71.837 74.111 72.889 74.6393 73.9502L74.7679 73.8169C75.2581
73.4258 75.6415 72.917 75.8825 72.3379C76.1234 71.7589 76.2141 71.1283
76.146 70.5048C75.8564 70.0602 75.5911 69.6001 75.3513 69.1267C74.9562
68.4652 74.0926 68.1345 73.5597 67.6062"
fill="white" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M139.319 125.345C134.95 125.032 130.564 125.658 126.457 127.183C125.464
127.578 123.875 127.578 123.742 128.836C124.275 129.365 124.339 130.214
124.808 130.959C125.714 132.492 126.878 133.858 128.248 134.997C129.626
136.058 131.028 137.11 132.488 138.038C135.07 139.632 138.001 140.555
140.495 142.144C141.956 143.063 143.408 144.262 144.873 145.259C145.599
145.787 146.058 146.637 146.986 146.977V146.775C146.712 146.039 146.374
145.329 145.976 144.653C145.314 143.996 144.653 143.394 143.986
142.737C142.043 140.171 139.72 137.917 137.096 136.053C134.974 134.592
130.338 132.608 129.479 130.164L129.346 130.031C130.906 129.811 132.443
129.454 133.94 128.965C136.186 128.372 138.24 128.506 140.56 127.913C141.621
127.647 143.541 126.994 143.541 126.994V125.961C142.356 124.785 141.51
123.204 140.266 122.097C136.876 119.139 133.264 116.447 129.461
114.045C127.426 112.735 124.808 111.885 122.649 110.769C121.868 110.374
120.558 110.181 120.099 109.524C119.022 107.943 118.121 106.248 117.412
104.471C115.475 100.744 113.684 96.944 112.042 93.0786C111.076 90.527
109.961 88.0344 108.702 85.6138C102.629 75.3049 93.8692 66.8402 83.3582
61.1245C80.7056 59.8389 77.8847 58.9342 74.9792 58.4372C73.3392 58.3683
71.7038 58.2396 70.0685 58.1753C69.0107 57.4823 68.0036 56.7147 67.055
55.8784C63.3202 53.5218 53.7009 48.4136 50.9493 55.1572C49.1807 59.4156
53.5677 63.6051 55.0836 65.7688C56.3514 67.2941 57.4683 68.9387 58.4187
70.6795C58.8781 71.7912 59.0067 72.9764 59.4707 74.1524C60.4281 77.1443
61.5648 80.0758 62.8746 82.931C63.5769 84.3429 64.3863 85.699 65.2956
86.9873C65.8238 87.7131 66.738 88.0347 66.9355 89.2199C66.2106 90.78 65.7036
92.4324 65.4288 94.1306C64.2846 97.7426 63.8637 101.545 64.19 105.32C64.5163
109.094 65.5835 112.768 67.3306 116.13C68.378 117.765 70.8678 121.372
74.2212 119.993C77.1658 118.817 76.5181 115.083 77.3633 111.812C77.5609
111.022 77.4276 110.503 77.8227 109.974V110.618C77.8227 110.618 79.4948
114.293 80.3217 116.171C82.5698 119.591 85.3631 122.618 88.5905
125.134C89.8767 126.245 90.9145 127.614 91.6361
129.153V130.339H93.1153C93.0837 129.805 92.9362 129.285 92.6832
128.815C92.4301 128.344 92.0775 127.935 91.6499 127.614C90.4391 126.367
89.33 125.024 88.3332 123.6C85.6231 119.742 83.234 115.669 81.1899
111.421C80.1655 109.34 79.2743 107.071 78.4337 104.99C78.0524 104.191
78.0524 102.983 77.4139 102.583C76.2312 103.981 75.2053 105.505 74.3544
107.126C73.3203 110.403 72.7195 113.8 72.5675 117.233C72.3148 117.301
72.4388 117.233 72.3148 117.366C70.2752 116.833 69.5586 114.61 68.8052
112.772C66.8219 107.009 66.6218 100.781 68.231 94.9023C68.6903 93.5242
70.5967 89.0821 69.825 87.7453C69.4391 86.4682 68.1666 85.7378 67.4638
84.7318C66.5711 83.3765 65.8024 81.9436 65.1669 80.4504C63.6372 76.7065
62.8701 72.5538 61.2117 68.8098C60.2956 67.0053 59.2292 65.2811 58.0236
63.6557C56.6915 62.031 55.5163 60.2837 54.514 58.4372C54.2707 58.0251
54.1215 57.5643 54.077 57.0878C54.0326 56.6113 54.0939 56.1309 54.2568
55.6809C54.2928 55.4547 54.4023 55.2467 54.5684 55.0889C54.7344 54.9312
54.9478 54.8325 55.1755 54.8081C56.0024 54.0731 58.3636 55.0056 59.1905
55.4099C61.4133 56.2841 63.5306 57.4059 65.5023 58.7541C66.421 59.4248
68.4974 61.1245 68.4974 61.1245H69.1176C71.2353 61.5839 73.624 61.2531
75.6085 61.8503C78.9646 62.967 82.1671 64.5011 85.1406 66.4165C93.9149
72.002 101.049 79.8174 105.812 89.0637C106.607 90.5842 106.942 91.9761
107.65 93.561C109.028 96.8133 110.764 100.125 112.152 103.3C113.372 106.43
114.951 109.408 116.856 112.175C117.848 113.553 121.822 114.293 123.609
115.023C125.17 115.557 126.703 116.17 128.202 116.86C130.453 118.239 132.7
119.842 134.822 121.367C135.879 122.162 139.191 123.815 139.388 125.143"
fill="#F3FDFF" />
</svg>

View File

@ -6,6 +6,7 @@ import CouchDB from "./CouchDB.svelte"
import S3 from "./S3.svelte" import S3 from "./S3.svelte"
import Airtable from "./Airtable.svelte" import Airtable from "./Airtable.svelte"
import SqlServer from "./SQLServer.svelte" import SqlServer from "./SQLServer.svelte"
import MySQL from "./MySQL.svelte"
export default { export default {
POSTGRES: Postgres, POSTGRES: Postgres,
@ -16,4 +17,5 @@ export default {
SQL_SERVER: SqlServer, SQL_SERVER: SqlServer,
S3: S3, S3: S3,
AIRTABLE: Airtable, AIRTABLE: Airtable,
MYSQL: MySQL,
} }

View File

@ -34,7 +34,7 @@
})) }))
return [...acc, ...viewsArr] return [...acc, ...viewsArr]
}, []) }, [])
$: queries = $backendUiStore.queries.map(query => ({ $: queries = $backendUiStore.queries.filter(query => query.queryVerb === "read").map(query => ({
label: query.name, label: query.name,
name: query.name, name: query.name,
tableId: query._id, tableId: query._id,

View File

@ -164,7 +164,7 @@
<div class="viewer-controls"> <div class="viewer-controls">
<Button <Button
blue blue
disabled={data.length === 0} disabled={data.length === 0 || !query.name}
on:click={saveQuery}> on:click={saveQuery}>
Save Query Save Query
</Button> </Button>

View File

@ -1,6 +1,7 @@
<script> <script>
import { notifier } from "builderStore/store/notifications" import { notifier } from "builderStore/store/notifications"
import { hostingStore } from "builderStore" import { hostingStore } from "builderStore"
import { HostingTypes } from "constants/backend"
import { Input, ModalContent, Toggle } from "@budibase/bbui" import { Input, ModalContent, Toggle } from "@budibase/bbui"
import ThemeEditor from "components/settings/ThemeEditor.svelte" import ThemeEditor from "components/settings/ThemeEditor.svelte"
import analytics from "analytics" import analytics from "analytics"
@ -10,7 +11,7 @@
let selfhosted = false let selfhosted = false
async function save() { async function save() {
hostingInfo.type = selfhosted ? "self" : "cloud" hostingInfo.type = selfhosted ? HostingTypes.SELF : HostingTypes.CLOUD
if (!selfhosted && hostingInfo._rev) { if (!selfhosted && hostingInfo._rev) {
hostingInfo = { hostingInfo = {
type: hostingInfo.type, type: hostingInfo.type,
@ -27,7 +28,7 @@
} }
function updateSelfHosting(event) { function updateSelfHosting(event) {
if (hostingInfo.type === "cloud" && event.target.checked) { if (hostingInfo.type === HostingTypes.CLOUD && event.target.checked) {
hostingInfo.hostingUrl = "localhost:10000" hostingInfo.hostingUrl = "localhost:10000"
hostingInfo.useHttps = false hostingInfo.useHttps = false
hostingInfo.selfHostKey = "budibase" hostingInfo.selfHostKey = "budibase"

View File

@ -87,3 +87,8 @@ export const FILE_TYPES = {
CODE: ["js", "rs", "py", "java", "rb", "hs", "yml"], CODE: ["js", "rs", "py", "java", "rb", "hs", "yml"],
DOCUMENT: ["odf", "docx", "doc", "pdf", "csv"], DOCUMENT: ["odf", "docx", "doc", "pdf", "csv"],
} }
export const HostingTypes = {
CLOUD: "cloud",
SELF: "self",
}

View File

@ -51,7 +51,6 @@
<div class="query-list-item" on:click={() => onClickQuery(query)}> <div class="query-list-item" on:click={() => onClickQuery(query)}>
<p class="query-name">{query.name}</p> <p class="query-name">{query.name}</p>
<p>{query.queryVerb}</p> <p>{query.queryVerb}</p>
<p>4000 records</p>
<p></p> <p></p>
</div> </div>
{/each} {/each}
@ -115,7 +114,7 @@
background: var(--background); background: var(--background);
border: var(--border-grey); border: var(--border-grey);
display: grid; display: grid;
grid-template-columns: 2fr 0.75fr 0.75fr 1fr 20px; grid-template-columns: 2fr 0.75fr 20px;
align-items: center; align-items: center;
padding: var(--spacing-m) var(--layout-xs); padding: var(--spacing-m) var(--layout-xs);
gap: var(--layout-xs); gap: var(--layout-xs);

View File

@ -1,7 +1,7 @@
<script> <script>
import { onMount } from "svelte" import { onMount } from "svelte"
import { Button, Spacer, Modal } from "@budibase/bbui" import { Button, Spacer, Modal } from "@budibase/bbui"
import { store } from "builderStore" import { store, hostingStore } from "builderStore"
import { notifier } from "builderStore/store/notifications" import { notifier } from "builderStore/store/notifications"
import api from "builderStore/api" import api from "builderStore/api"
import Spinner from "components/common/Spinner.svelte" import Spinner from "components/common/Spinner.svelte"
@ -29,6 +29,7 @@
analytics.captureEvent("Deployed App", { analytics.captureEvent("Deployed App", {
appId, appId,
hostingType: $hostingStore.hostingInfo?.type,
}) })
if (analytics.requestFeedbackOnDeploy()) { if (analytics.requestFeedbackOnDeploy()) {
@ -37,6 +38,7 @@
} catch (err) { } catch (err) {
analytics.captureEvent("Deploy App Failed", { analytics.captureEvent("Deploy App Failed", {
appId, appId,
hostingType: $hostingStore.hostingInfo?.type,
}) })
analytics.captureException(err) analytics.captureException(err)
notifier.danger("Deployment unsuccessful. Please try again later.") notifier.danger("Deployment unsuccessful. Please try again later.")

View File

@ -49,9 +49,9 @@
"author": "Budibase", "author": "Budibase",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@elastic/elasticsearch": "^7.10.0",
"@budibase/client": "^0.5.3", "@budibase/client": "^0.5.3",
"@budibase/string-templates": "^0.5.3", "@budibase/string-templates": "^0.5.3",
"@elastic/elasticsearch": "^7.10.0",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@sendgrid/mail": "^7.1.1", "@sendgrid/mail": "^7.1.1",
"@sentry/node": "^5.19.2", "@sentry/node": "^5.19.2",
@ -82,6 +82,7 @@
"lodash": "^4.17.13", "lodash": "^4.17.13",
"mongodb": "^3.6.3", "mongodb": "^3.6.3",
"mssql": "^6.2.3", "mssql": "^6.2.3",
"mysql": "^2.18.1",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"open": "^7.3.0", "open": "^7.3.0",
"pg": "^8.5.1", "pg": "^8.5.1",

View File

@ -3,10 +3,10 @@ const dynamodb = require("./dynamodb")
const mongodb = require("./mongodb") const mongodb = require("./mongodb")
const elasticsearch = require("./elasticsearch") const elasticsearch = require("./elasticsearch")
const couchdb = require("./couchdb") const couchdb = require("./couchdb")
// const redis = require("./redis")
const sqlServer = require("./microsoftSqlServer") const sqlServer = require("./microsoftSqlServer")
const s3 = require("./s3") const s3 = require("./s3")
const airtable = require("./airtable") const airtable = require("./airtable")
const mysql = require("./mysql")
const DEFINITIONS = { const DEFINITIONS = {
POSTGRES: postgres.schema, POSTGRES: postgres.schema,
@ -17,6 +17,7 @@ const DEFINITIONS = {
SQL_SERVER: sqlServer.schema, SQL_SERVER: sqlServer.schema,
S3: s3.schema, S3: s3.schema,
AIRTABLE: airtable.schema, AIRTABLE: airtable.schema,
MYSQL: mysql.schema,
} }
const INTEGRATIONS = { const INTEGRATIONS = {
@ -28,6 +29,7 @@ const INTEGRATIONS = {
S3: s3.integration, S3: s3.integration,
SQL_SERVER: sqlServer.integration, SQL_SERVER: sqlServer.integration,
AIRTABLE: airtable.integration, AIRTABLE: airtable.integration,
MYSQL: mysql.integration,
} }
module.exports = { module.exports = {

View File

@ -0,0 +1,80 @@
const mysql = require("mysql")
const SCHEMA = {
docs: "https://github.com/mysqljs/mysql",
datasource: {
host: {
type: "string",
default: "localhost",
required: true,
},
user: {
type: "string",
default: "root",
required: true,
},
password: {
type: "password",
default: "root",
required: true,
},
database: {
type: "string",
required: true,
},
},
query: {
create: {
type: "sql",
},
read: {
type: "sql",
},
update: {
type: "sql",
},
delete: {
type: "sql",
},
},
}
class MySQLIntegration {
constructor(config) {
this.config = config
this.client = mysql.createConnection(config)
}
query(query) {
// Node MySQL is callback based, so we must wrap our call in a promise
return new Promise((resolve, reject) => {
this.client.connect()
return this.client.query(query.sql, (error, results) => {
if (error) return reject(error)
resolve(results)
this.client.end()
})
})
}
create(query) {
return this.query(query)
}
read(query) {
return this.query(query)
}
update(query) {
return this.query(query)
}
delete(query) {
return this.query(query)
}
}
module.exports = {
schema: SCHEMA,
integration: MySQLIntegration,
}

View File

@ -58,7 +58,7 @@ class PostgresIntegration {
async create({ sql }) { async create({ sql }) {
const response = await this.client.query(sql) const response = await this.client.query(sql)
return response.rows return response.rows.length ? response.rows : [{ created: true }]
} }
async read({ sql }) { async read({ sql }) {
@ -68,12 +68,12 @@ class PostgresIntegration {
async update({ sql }) { async update({ sql }) {
const response = await this.client.query(sql) const response = await this.client.query(sql)
return response.rows return response.rows.length ? response.rows : [{ updated: true }]
} }
async delete({ sql }) { async delete({ sql }) {
const response = await this.client.query(sql) const response = await this.client.query(sql)
return response.rows return response.rows.length ? response.rows : [{ deleted: true }]
} }
} }

File diff suppressed because it is too large Load Diff