@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.
Files changed (182) hide show
  1. package/builder/assets/index.c6df2367.css +6 -0
  2. package/builder/assets/index.ec376520.js +1313 -0
  3. package/builder/index.html +2 -2
  4. package/coverage/clover.xml +123 -121
  5. package/coverage/coverage-final.json +5 -5
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/backup.js.html +9 -6
  10. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/index.html +7 -7
  15. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +8 -23
  25. package/coverage/lcov-report/api/controllers/row/index.html +16 -16
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
  30. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  44. package/coverage/lcov-report/api/index.html +1 -1
  45. package/coverage/lcov-report/api/index.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/index.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  74. package/coverage/lcov-report/automations/actions.js.html +1 -1
  75. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  76. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  77. package/coverage/lcov-report/automations/index.html +5 -5
  78. package/coverage/lcov-report/automations/index.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/index.html +1 -1
  86. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggers.js.html +4 -4
  105. package/coverage/lcov-report/constants/index.html +1 -1
  106. package/coverage/lcov-report/constants/index.js.html +1 -1
  107. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  108. package/coverage/lcov-report/constants/screens.js.html +1 -1
  109. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  110. package/coverage/lcov-report/db/index.html +10 -10
  111. package/coverage/lcov-report/db/index.js.html +1 -1
  112. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  116. package/coverage/lcov-report/db/newid.js.html +1 -1
  117. package/coverage/lcov-report/db/utils.js.html +9 -6
  118. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  119. package/coverage/lcov-report/events/index.html +1 -1
  120. package/coverage/lcov-report/events/index.js.html +1 -1
  121. package/coverage/lcov-report/events/utils.js.html +1 -1
  122. package/coverage/lcov-report/index.html +22 -22
  123. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  124. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  125. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  126. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  127. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  128. package/coverage/lcov-report/middleware/index.html +1 -1
  129. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  130. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  131. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  132. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  133. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  134. package/coverage/lcov-report/threads/automation.js.html +1 -1
  135. package/coverage/lcov-report/threads/index.html +1 -1
  136. package/coverage/lcov-report/threads/query.js.html +1 -1
  137. package/coverage/lcov-report/threads/utils.js.html +1 -1
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  139. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  140. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  141. package/coverage/lcov-report/utilities/global.js.html +1 -1
  142. package/coverage/lcov-report/utilities/index.html +1 -1
  143. package/coverage/lcov-report/utilities/index.js.html +1 -1
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  151. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  152. package/coverage/lcov-report/utilities/security.js.html +1 -1
  153. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  157. package/coverage/lcov-report/utilities/users.js.html +1 -1
  158. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  159. package/coverage/lcov.info +221 -215
  160. package/dist/api/controllers/backup.js +3 -2
  161. package/dist/api/controllers/row/external.js +2 -4
  162. package/dist/api/controllers/row/utils.js +3 -0
  163. package/dist/automations/triggers.js +1 -1
  164. package/dist/db/utils.js +1 -0
  165. package/dist/definitions/datasource.js +1 -0
  166. package/dist/integrations/index.js +4 -0
  167. package/dist/integrations/snowflake.js +101 -0
  168. package/dist/package.json +7 -6
  169. package/dist/tsconfig.build.tsbuildinfo +1 -1
  170. package/dist/utilities/fileSystem/index.js +16 -6
  171. package/package.json +8 -7
  172. package/src/api/controllers/backup.js +3 -2
  173. package/src/api/controllers/row/external.js +2 -7
  174. package/src/api/controllers/row/utils.js +3 -0
  175. package/src/automations/triggers.js +1 -1
  176. package/src/db/utils.js +1 -0
  177. package/src/definitions/datasource.ts +1 -0
  178. package/src/integrations/index.ts +4 -0
  179. package/src/integrations/snowflake.ts +98 -0
  180. package/src/utilities/fileSystem/index.js +22 -8
  181. package/builder/assets/index.24307ca0.css +0 -6
  182. 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: doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
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.206",
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.206",
81
- "@budibase/client": "^1.0.206",
82
- "@budibase/pro": "1.0.205",
83
- "@budibase/string-templates": "^1.0.206",
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.206",
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": "a27b4685d0ca57de403182477b2712c7f1b3e65f"
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
- const { appId } = ctx.query
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, tableName } = breakExternalTableId(ctx.params.tableId)
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
- [table.primaryDisplay]: ctx.request.body.rows.map(
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
@@ -50,6 +50,7 @@ export enum SourceNames {
50
50
  GOOGLE_SHEETS = "GOOGLE_SHEETS",
51
51
  FIRESTORE = "FIRESTORE",
52
52
  REDIS = "REDIS",
53
+ SNOWFLAKE = "SNOWFLAKE",
53
54
  }
54
55
 
55
56
  export enum IncludeRelationships {
@@ -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: doc =>
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
  /**