@budibase/server 1.0.206 → 1.0.207-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/assets/index.c6df2367.css +6 -0
- package/builder/assets/index.ec376520.js +1313 -0
- package/builder/index.html +2 -2
- package/coverage/clover.xml +123 -121
- package/coverage/coverage-final.json +5 -5
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/backup.js.html +9 -6
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +7 -7
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +8 -23
- package/coverage/lcov-report/api/controllers/row/index.html +16 -16
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
- package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/utils/index.html +1 -1
- package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +5 -5
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +4 -4
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +1 -1
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +10 -10
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +9 -6
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +22 -22
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
- package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +1 -1
- package/coverage/lcov-report/threads/query.js.html +1 -1
- package/coverage/lcov-report/threads/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +1 -1
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +1 -1
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +221 -215
- package/dist/api/controllers/backup.js +3 -2
- package/dist/api/controllers/row/external.js +2 -4
- package/dist/api/controllers/row/utils.js +3 -0
- package/dist/automations/triggers.js +1 -1
- package/dist/db/utils.js +1 -0
- package/dist/definitions/datasource.js +1 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/snowflake.js +101 -0
- package/dist/package.json +7 -6
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/index.js +16 -6
- package/package.json +8 -7
- package/src/api/controllers/backup.js +3 -2
- package/src/api/controllers/row/external.js +2 -7
- package/src/api/controllers/row/utils.js +3 -0
- package/src/automations/triggers.js +1 -1
- package/src/db/utils.js +1 -0
- package/src/definitions/datasource.ts +1 -0
- package/src/integrations/index.ts +4 -0
- package/src/integrations/snowflake.ts +98 -0
- package/src/utilities/fileSystem/index.js +22 -8
- package/builder/assets/index.24307ca0.css +0 -6
- package/builder/assets/index.9dd8f7d4.js +0 -1315
|
@@ -17,7 +17,7 @@ const { ObjectStoreBuckets } = require("../../constants");
|
|
|
17
17
|
const { upload, retrieve, retrieveToTmp, streamUpload, deleteFolder, downloadTarball, } = require("./utilities");
|
|
18
18
|
const { updateClientLibrary } = require("./clientLibrary");
|
|
19
19
|
const env = require("../../environment");
|
|
20
|
-
const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, } = require("../../db/utils");
|
|
20
|
+
const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, TABLE_ROW_PREFIX, } = require("../../db/utils");
|
|
21
21
|
const MemoryStream = require("memorystream");
|
|
22
22
|
const { getAppId } = require("@budibase/backend-core/context");
|
|
23
23
|
const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..");
|
|
@@ -98,6 +98,17 @@ exports.apiFileReturn = contents => {
|
|
|
98
98
|
fs.writeFileSync(path, contents);
|
|
99
99
|
return fs.createReadStream(path);
|
|
100
100
|
};
|
|
101
|
+
exports.defineFilter = excludeRows => {
|
|
102
|
+
if (excludeRows) {
|
|
103
|
+
return doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
|
|
104
|
+
doc._id.includes(LINK_USER_METADATA_PREFIX) ||
|
|
105
|
+
doc._id.includes(TABLE_ROW_PREFIX));
|
|
106
|
+
}
|
|
107
|
+
else if (!excludeRows) {
|
|
108
|
+
return doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
|
|
109
|
+
doc._id.includes(LINK_USER_METADATA_PREFIX));
|
|
110
|
+
}
|
|
111
|
+
};
|
|
101
112
|
/**
|
|
102
113
|
* Local utility to back up the database state for an app, excluding global user
|
|
103
114
|
* data or user relationships.
|
|
@@ -105,9 +116,8 @@ exports.apiFileReturn = contents => {
|
|
|
105
116
|
* @param {object} config Config to send to export DB
|
|
106
117
|
* @returns {*} either a string or a stream of the backup
|
|
107
118
|
*/
|
|
108
|
-
const backupAppData = (appId, config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
-
return yield exports.exportDB(appId, Object.assign(Object.assign({}, config), { filter:
|
|
110
|
-
doc._id.includes(LINK_USER_METADATA_PREFIX)) }));
|
|
119
|
+
const backupAppData = (appId, config, includeRows) => __awaiter(void 0, void 0, void 0, function* () {
|
|
120
|
+
return yield exports.exportDB(appId, Object.assign(Object.assign({}, config), { filter: exports.defineFilter(includeRows) }));
|
|
111
121
|
});
|
|
112
122
|
/**
|
|
113
123
|
* Takes a copy of the database state for an app to the object store.
|
|
@@ -123,8 +133,8 @@ exports.performBackup = (appId, backupName) => __awaiter(void 0, void 0, void 0,
|
|
|
123
133
|
* @param {string} appId The ID of the app which is to be backed up.
|
|
124
134
|
* @returns {*} a readable stream of the backup which is written in real time
|
|
125
135
|
*/
|
|
126
|
-
exports.streamBackup = (appId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
127
|
-
return yield backupAppData(appId, { stream: true });
|
|
136
|
+
exports.streamBackup = (appId, includeRows) => __awaiter(void 0, void 0, void 0, function* () {
|
|
137
|
+
return yield backupAppData(appId, { stream: true }, includeRows);
|
|
128
138
|
});
|
|
129
139
|
/**
|
|
130
140
|
* Exports a DB to either file or a variable (memory).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.207-alpha.2",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -77,10 +77,10 @@
|
|
|
77
77
|
"license": "GPL-3.0",
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
80
|
-
"@budibase/backend-core": "^1.0.
|
|
81
|
-
"@budibase/client": "^1.0.
|
|
82
|
-
"@budibase/pro": "1.0.
|
|
83
|
-
"@budibase/string-templates": "^1.0.
|
|
80
|
+
"@budibase/backend-core": "^1.0.207-alpha.2",
|
|
81
|
+
"@budibase/client": "^1.0.207-alpha.2",
|
|
82
|
+
"@budibase/pro": "1.0.207-alpha.1",
|
|
83
|
+
"@budibase/string-templates": "^1.0.207-alpha.2",
|
|
84
84
|
"@bull-board/api": "3.7.0",
|
|
85
85
|
"@bull-board/koa": "3.9.4",
|
|
86
86
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -135,6 +135,7 @@
|
|
|
135
135
|
"pouchdb-replication-stream": "1.2.9",
|
|
136
136
|
"redis": "4",
|
|
137
137
|
"server-destroy": "1.0.1",
|
|
138
|
+
"snowflake-promise": "^4.5.0",
|
|
138
139
|
"svelte": "3.44.1",
|
|
139
140
|
"swagger-parser": "10.0.3",
|
|
140
141
|
"to-json-schema": "0.2.5",
|
|
@@ -150,7 +151,7 @@
|
|
|
150
151
|
"@babel/core": "7.17.4",
|
|
151
152
|
"@babel/preset-env": "7.16.11",
|
|
152
153
|
"@budibase/standard-components": "^0.9.139",
|
|
153
|
-
"@budibase/types": "^1.0.
|
|
154
|
+
"@budibase/types": "^1.0.207-alpha.2",
|
|
154
155
|
"@jest/test-sequencer": "24.9.0",
|
|
155
156
|
"@types/apidoc": "0.50.0",
|
|
156
157
|
"@types/bson": "4.2.0",
|
|
@@ -194,5 +195,5 @@
|
|
|
194
195
|
"optionalDependencies": {
|
|
195
196
|
"oracledb": "5.3.0"
|
|
196
197
|
},
|
|
197
|
-
"gitHead": "
|
|
198
|
+
"gitHead": "2600c8407747ee26a2b3cea60e77651e14ffe5e3"
|
|
198
199
|
}
|
|
@@ -3,11 +3,12 @@ const { events, context } = require("@budibase/backend-core")
|
|
|
3
3
|
const { DocumentTypes } = require("../../db/utils")
|
|
4
4
|
|
|
5
5
|
exports.exportAppDump = async function (ctx) {
|
|
6
|
-
|
|
6
|
+
let { appId, excludeRows } = ctx.query
|
|
7
7
|
const appName = decodeURI(ctx.query.appname)
|
|
8
|
+
excludeRows = excludeRows === "true"
|
|
8
9
|
const backupIdentifier = `${appName}-export-${new Date().getTime()}.txt`
|
|
9
10
|
ctx.attachment(backupIdentifier)
|
|
10
|
-
ctx.body = await streamBackup(appId)
|
|
11
|
+
ctx.body = await streamBackup(appId, excludeRows)
|
|
11
12
|
|
|
12
13
|
await context.doInAppContext(appId, async () => {
|
|
13
14
|
const appDb = context.getAppDB()
|
|
@@ -155,27 +155,22 @@ exports.validate = async () => {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
exports.exportRows = async ctx => {
|
|
158
|
-
const { datasourceId
|
|
158
|
+
const { datasourceId } = breakExternalTableId(ctx.params.tableId)
|
|
159
159
|
const db = getAppDB()
|
|
160
160
|
let format = ctx.query.format
|
|
161
161
|
const datasource = await db.get(datasourceId)
|
|
162
162
|
if (!datasource || !datasource.entities) {
|
|
163
163
|
ctx.throw(400, "Datasource has not been configured for plus API.")
|
|
164
164
|
}
|
|
165
|
-
const tables = datasource.entities
|
|
166
|
-
const table = tables[tableName]
|
|
167
165
|
ctx.request.body = {
|
|
168
166
|
query: {
|
|
169
167
|
oneOf: {
|
|
170
|
-
|
|
171
|
-
id => breakRowIdField(id)[0]
|
|
172
|
-
),
|
|
168
|
+
_id: ctx.request.body.rows.map(row => JSON.parse(decodeURI(row))[0]),
|
|
173
169
|
},
|
|
174
170
|
},
|
|
175
171
|
}
|
|
176
172
|
|
|
177
173
|
let result = await exports.search(ctx)
|
|
178
|
-
|
|
179
174
|
let headers = Object.keys(result.rows[0])
|
|
180
175
|
const exporter = exporters[format]
|
|
181
176
|
const filename = `export.${format}`
|
|
@@ -64,6 +64,9 @@ exports.validate = async ({ tableId, row, table }) => {
|
|
|
64
64
|
// Validate.js doesn't seem to handle array
|
|
65
65
|
if (type === FieldTypes.ARRAY && row[fieldName]) {
|
|
66
66
|
if (row[fieldName].length) {
|
|
67
|
+
if (!Array.isArray(row[fieldName])) {
|
|
68
|
+
row[fieldName] = row[fieldName].split(",")
|
|
69
|
+
}
|
|
67
70
|
row[fieldName].map(val => {
|
|
68
71
|
if (
|
|
69
72
|
!constraints.inclusion.includes(val) &&
|
|
@@ -97,7 +97,7 @@ exports.externalTrigger = async function (
|
|
|
97
97
|
// values are likely to be submitted as strings, so we shall convert to correct type
|
|
98
98
|
const coercedFields = {}
|
|
99
99
|
const fields = automation.definition.trigger.inputs.fields
|
|
100
|
-
for (let key of Object.keys(fields)) {
|
|
100
|
+
for (let key of Object.keys(fields || {})) {
|
|
101
101
|
coercedFields[key] = coerce(params.fields[key], fields[key])
|
|
102
102
|
}
|
|
103
103
|
params.fields = coercedFields
|
package/src/db/utils.js
CHANGED
|
@@ -74,6 +74,7 @@ exports.isDevAppID = isDevAppID
|
|
|
74
74
|
exports.isProdAppID = isProdAppID
|
|
75
75
|
exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
|
76
76
|
exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
|
77
|
+
exports.TABLE_ROW_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${DocumentTypes.TABLE}`
|
|
77
78
|
exports.ViewNames = ViewNames
|
|
78
79
|
exports.InternalTables = InternalTables
|
|
79
80
|
exports.DocumentTypes = DocumentTypes
|
|
@@ -12,6 +12,7 @@ const rest = require("./rest")
|
|
|
12
12
|
const googlesheets = require("./googlesheets")
|
|
13
13
|
const firebase = require("./firebase")
|
|
14
14
|
const redis = require("./redis")
|
|
15
|
+
const snowflake = require("./snowflake")
|
|
15
16
|
const { SourceNames } = require("../definitions/datasource")
|
|
16
17
|
const environment = require("../environment")
|
|
17
18
|
|
|
@@ -29,6 +30,7 @@ const DEFINITIONS = {
|
|
|
29
30
|
[SourceNames.REST]: rest.schema,
|
|
30
31
|
[SourceNames.FIRESTORE]: firebase.schema,
|
|
31
32
|
[SourceNames.REDIS]: redis.schema,
|
|
33
|
+
[SourceNames.SNOWFLAKE]: snowflake.schema,
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
const INTEGRATIONS = {
|
|
@@ -46,6 +48,8 @@ const INTEGRATIONS = {
|
|
|
46
48
|
[SourceNames.FIRESTORE]: firebase.integration,
|
|
47
49
|
[SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
|
|
48
50
|
[SourceNames.REDIS]: redis.integration,
|
|
51
|
+
[SourceNames.FIREBASE]: firebase.integration,
|
|
52
|
+
[SourceNames.SNOWFLAKE]: snowflake.integration,
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
// optionally add oracle integration if the oracle binary can be installed
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Integration, QueryTypes, SqlQuery } from "../definitions/datasource"
|
|
2
|
+
import { Snowflake } from "snowflake-promise"
|
|
3
|
+
|
|
4
|
+
module SnowflakeModule {
|
|
5
|
+
interface SnowflakeConfig {
|
|
6
|
+
account: string
|
|
7
|
+
username: string
|
|
8
|
+
password: string
|
|
9
|
+
warehouse: string
|
|
10
|
+
database: string
|
|
11
|
+
schema: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const SCHEMA: Integration = {
|
|
15
|
+
docs: "https://developers.snowflake.com/",
|
|
16
|
+
description:
|
|
17
|
+
"Snowflake is a solution for data warehousing, data lakes, data engineering, data science, data application development, and securely sharing and consuming shared data.",
|
|
18
|
+
friendlyName: "Snowflake",
|
|
19
|
+
datasource: {
|
|
20
|
+
account: {
|
|
21
|
+
type: "string",
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
username: {
|
|
25
|
+
type: "string",
|
|
26
|
+
required: true,
|
|
27
|
+
},
|
|
28
|
+
password: {
|
|
29
|
+
type: "password",
|
|
30
|
+
required: true,
|
|
31
|
+
},
|
|
32
|
+
warehouse: {
|
|
33
|
+
type: "string",
|
|
34
|
+
required: true,
|
|
35
|
+
},
|
|
36
|
+
database: {
|
|
37
|
+
type: "string",
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
schema: {
|
|
41
|
+
type: "string",
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
query: {
|
|
46
|
+
create: {
|
|
47
|
+
type: QueryTypes.SQL,
|
|
48
|
+
},
|
|
49
|
+
read: {
|
|
50
|
+
type: QueryTypes.SQL,
|
|
51
|
+
},
|
|
52
|
+
update: {
|
|
53
|
+
type: QueryTypes.SQL,
|
|
54
|
+
},
|
|
55
|
+
delete: {
|
|
56
|
+
type: QueryTypes.SQL,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
class SnowflakeIntegration {
|
|
62
|
+
private client: Snowflake
|
|
63
|
+
|
|
64
|
+
constructor(config: SnowflakeConfig) {
|
|
65
|
+
this.client = new Snowflake(config)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async internalQuery(query: SqlQuery) {
|
|
69
|
+
await this.client.connect()
|
|
70
|
+
try {
|
|
71
|
+
return await this.client.execute(query.sql)
|
|
72
|
+
} catch (err: any) {
|
|
73
|
+
throw err?.message.split(":")[1] || err?.message
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async create(query: SqlQuery) {
|
|
78
|
+
return this.internalQuery(query)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async read(query: SqlQuery) {
|
|
82
|
+
return this.internalQuery(query)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async update(query: SqlQuery) {
|
|
86
|
+
return this.internalQuery(query)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async delete(query: SqlQuery) {
|
|
90
|
+
return this.internalQuery(query)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
schema: SCHEMA,
|
|
96
|
+
integration: SnowflakeIntegration,
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -21,6 +21,7 @@ const env = require("../../environment")
|
|
|
21
21
|
const {
|
|
22
22
|
USER_METDATA_PREFIX,
|
|
23
23
|
LINK_USER_METADATA_PREFIX,
|
|
24
|
+
TABLE_ROW_PREFIX,
|
|
24
25
|
} = require("../../db/utils")
|
|
25
26
|
const MemoryStream = require("memorystream")
|
|
26
27
|
const { getAppId } = require("@budibase/backend-core/context")
|
|
@@ -109,6 +110,23 @@ exports.apiFileReturn = contents => {
|
|
|
109
110
|
return fs.createReadStream(path)
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
exports.defineFilter = excludeRows => {
|
|
114
|
+
if (excludeRows) {
|
|
115
|
+
return doc =>
|
|
116
|
+
!(
|
|
117
|
+
doc._id.includes(USER_METDATA_PREFIX) ||
|
|
118
|
+
doc._id.includes(LINK_USER_METADATA_PREFIX) ||
|
|
119
|
+
doc._id.includes(TABLE_ROW_PREFIX)
|
|
120
|
+
)
|
|
121
|
+
} else if (!excludeRows) {
|
|
122
|
+
return doc =>
|
|
123
|
+
!(
|
|
124
|
+
doc._id.includes(USER_METDATA_PREFIX) ||
|
|
125
|
+
doc._id.includes(LINK_USER_METADATA_PREFIX)
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
112
130
|
/**
|
|
113
131
|
* Local utility to back up the database state for an app, excluding global user
|
|
114
132
|
* data or user relationships.
|
|
@@ -116,14 +134,10 @@ exports.apiFileReturn = contents => {
|
|
|
116
134
|
* @param {object} config Config to send to export DB
|
|
117
135
|
* @returns {*} either a string or a stream of the backup
|
|
118
136
|
*/
|
|
119
|
-
const backupAppData = async (appId, config) => {
|
|
137
|
+
const backupAppData = async (appId, config, includeRows) => {
|
|
120
138
|
return await exports.exportDB(appId, {
|
|
121
139
|
...config,
|
|
122
|
-
filter:
|
|
123
|
-
!(
|
|
124
|
-
doc._id.includes(USER_METDATA_PREFIX) ||
|
|
125
|
-
doc._id.includes(LINK_USER_METADATA_PREFIX)
|
|
126
|
-
),
|
|
140
|
+
filter: exports.defineFilter(includeRows),
|
|
127
141
|
})
|
|
128
142
|
}
|
|
129
143
|
|
|
@@ -142,8 +156,8 @@ exports.performBackup = async (appId, backupName) => {
|
|
|
142
156
|
* @param {string} appId The ID of the app which is to be backed up.
|
|
143
157
|
* @returns {*} a readable stream of the backup which is written in real time
|
|
144
158
|
*/
|
|
145
|
-
exports.streamBackup = async appId => {
|
|
146
|
-
return await backupAppData(appId, { stream: true })
|
|
159
|
+
exports.streamBackup = async (appId, includeRows) => {
|
|
160
|
+
return await backupAppData(appId, { stream: true }, includeRows)
|
|
147
161
|
}
|
|
148
162
|
|
|
149
163
|
/**
|