@budibase/server 1.0.219 → 1.0.220-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 (284) hide show
  1. package/.yarnrc +1 -0
  2. package/__mocks__/node-fetch.ts +9 -0
  3. package/builder/assets/index.7786f497.css +6 -0
  4. package/builder/assets/index.e1885c5f.js +974 -0
  5. package/builder/assets/{vendor.9bf2fcb4.js → vendor.001dcf8c.js} +163 -163
  6. package/builder/index.html +3 -3
  7. package/coverage/clover.xml +1018 -950
  8. package/coverage/coverage-final.json +31 -31
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +111 -12
  12. package/coverage/lcov-report/api/controllers/backup.js.html +9 -6
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
  16. package/coverage/lcov-report/api/controllers/dev.js.html +13 -166
  17. package/coverage/lcov-report/api/controllers/index.html +32 -32
  18. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  24. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/external.js.html +47 -17
  28. package/coverage/lcov-report/api/controllers/row/index.html +33 -33
  29. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +159 -21
  31. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
  33. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  47. package/coverage/lcov-report/api/index.html +15 -15
  48. package/coverage/lcov-report/api/index.js.html +22 -13
  49. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/automation.js.html +32 -2
  53. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/dev.js.html +2 -5
  59. package/coverage/lcov-report/api/routes/index.html +1 -1
  60. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  74. package/coverage/lcov-report/api/routes/utils/validators.js.html +5 -2
  75. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  77. package/coverage/lcov-report/automations/actions.js.html +1 -1
  78. package/coverage/lcov-report/automations/automationUtils.js.html +57 -12
  79. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  80. package/coverage/lcov-report/automations/index.html +17 -17
  81. package/coverage/lcov-report/automations/index.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/executeQuery.js.html +2 -2
  86. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/filter.js.html +58 -34
  88. package/coverage/lcov-report/automations/steps/index.html +11 -11
  89. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggers.js.html +4 -4
  108. package/coverage/lcov-report/constants/index.html +1 -1
  109. package/coverage/lcov-report/constants/index.js.html +1 -1
  110. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  111. package/coverage/lcov-report/constants/screens.js.html +1 -1
  112. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  113. package/coverage/lcov-report/db/index.html +14 -14
  114. package/coverage/lcov-report/db/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/index.html +13 -13
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +10 -7
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  119. package/coverage/lcov-report/db/newid.js.html +2 -2
  120. package/coverage/lcov-report/db/utils.js.html +27 -51
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  122. package/coverage/lcov-report/events/index.html +1 -1
  123. package/coverage/lcov-report/events/index.js.html +1 -1
  124. package/coverage/lcov-report/events/utils.js.html +1 -1
  125. package/coverage/lcov-report/index.html +83 -83
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  127. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  128. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  129. package/coverage/lcov-report/middleware/builder.js.html +12 -12
  130. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  131. package/coverage/lcov-report/middleware/index.html +1 -1
  132. package/coverage/lcov-report/middleware/joi-validator.js.html +10 -10
  133. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  134. package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
  135. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  136. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  137. package/coverage/lcov-report/threads/automation.js.html +18 -9
  138. package/coverage/lcov-report/threads/index.html +25 -25
  139. package/coverage/lcov-report/threads/query.js.html +301 -79
  140. package/coverage/lcov-report/threads/utils.js.html +4 -4
  141. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  142. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  143. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  144. package/coverage/lcov-report/utilities/global.js.html +14 -14
  145. package/coverage/lcov-report/utilities/index.html +26 -26
  146. package/coverage/lcov-report/utilities/index.js.html +17 -32
  147. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  148. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  149. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  150. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  151. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  152. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  153. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  154. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  155. package/coverage/lcov-report/utilities/security.js.html +2 -2
  156. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  157. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  158. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  159. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  160. package/coverage/lcov-report/utilities/users.js.html +1 -1
  161. package/coverage/lcov-report/utilities/workerRequests.js.html +57 -9
  162. package/coverage/lcov.info +1789 -1665
  163. package/dist/api/controllers/application.js +19 -16
  164. package/dist/api/controllers/automation.js +28 -2
  165. package/dist/api/controllers/backup.js +3 -2
  166. package/dist/api/controllers/dev.js +2 -40
  167. package/dist/api/controllers/public/applications.js +1 -1
  168. package/dist/api/controllers/public/utils.js +8 -1
  169. package/dist/api/controllers/query/index.js +31 -3
  170. package/dist/api/controllers/row/external.js +19 -7
  171. package/dist/api/controllers/row/internalSearch.js +47 -10
  172. package/dist/api/controllers/row/utils.js +3 -0
  173. package/dist/api/controllers/static/index.js +1 -5
  174. package/dist/api/index.js +4 -1
  175. package/dist/api/routes/automation.js +2 -0
  176. package/dist/api/routes/dev.js +1 -2
  177. package/dist/api/routes/public/rows.js +7 -2
  178. package/dist/api/routes/utils/validators.js +1 -0
  179. package/dist/app.js +20 -0
  180. package/dist/automations/automationUtils.js +16 -4
  181. package/dist/automations/logging/index.js +70 -0
  182. package/dist/automations/steps/executeQuery.js +1 -1
  183. package/dist/automations/steps/filter.js +38 -29
  184. package/dist/automations/triggers.js +1 -1
  185. package/dist/db/linkedRows/index.js +1 -0
  186. package/dist/db/utils.js +4 -31
  187. package/dist/definitions/datasource.js +1 -0
  188. package/dist/environment.js +3 -0
  189. package/dist/integrations/airtable.js +1 -0
  190. package/dist/integrations/arangodb.js +1 -0
  191. package/dist/integrations/base/sql.js +22 -3
  192. package/dist/integrations/couchdb.js +1 -0
  193. package/dist/integrations/dynamodb.js +1 -0
  194. package/dist/integrations/elasticsearch.js +1 -0
  195. package/dist/integrations/firebase.js +1 -0
  196. package/dist/integrations/googlesheets.js +1 -0
  197. package/dist/integrations/index.js +4 -0
  198. package/dist/integrations/microsoftSqlServer.js +2 -1
  199. package/dist/integrations/mongodb.js +1 -0
  200. package/dist/integrations/mysql.js +2 -1
  201. package/dist/integrations/oracle.js +1 -0
  202. package/dist/integrations/postgres.js +2 -1
  203. package/dist/integrations/queries/sql.js +3 -0
  204. package/dist/integrations/redis.js +1 -0
  205. package/dist/integrations/rest.js +2 -1
  206. package/dist/integrations/s3.js +1 -0
  207. package/dist/integrations/snowflake.js +102 -0
  208. package/dist/package.json +7 -6
  209. package/dist/tests/utilities/TestConfiguration.js +19 -6
  210. package/dist/threads/automation.js +6 -3
  211. package/dist/threads/index.js +15 -1
  212. package/dist/threads/query.js +65 -12
  213. package/dist/tsconfig.build.tsbuildinfo +1 -1
  214. package/dist/utilities/fileSystem/index.js +16 -6
  215. package/dist/utilities/index.js +1 -5
  216. package/dist/utilities/workerRequests.js +8 -0
  217. package/package.json +8 -7
  218. package/scripts/dev/manage.js +2 -0
  219. package/scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip +0 -0
  220. package/scripts/integrations/oracle/instantclient/linux/arm64/install.sh +23 -0
  221. package/scripts/integrations/oracle/instantclient/linux/install.sh +10 -0
  222. package/specs/openapi.json +9 -5
  223. package/specs/openapi.yaml +10 -4
  224. package/src/api/controllers/application.ts +19 -19
  225. package/src/api/controllers/automation.js +35 -2
  226. package/src/api/controllers/backup.js +3 -2
  227. package/src/api/controllers/dev.js +2 -53
  228. package/src/api/controllers/public/applications.ts +2 -2
  229. package/src/api/controllers/public/utils.ts +8 -1
  230. package/src/api/controllers/query/index.ts +40 -4
  231. package/src/api/controllers/row/external.js +19 -9
  232. package/src/api/controllers/row/internalSearch.js +55 -9
  233. package/src/api/controllers/row/utils.js +3 -0
  234. package/src/api/controllers/static/index.js +1 -6
  235. package/src/api/index.js +4 -1
  236. package/src/api/routes/automation.js +10 -0
  237. package/src/api/routes/dev.js +0 -1
  238. package/src/api/routes/public/rows.ts +7 -2
  239. package/src/api/routes/tests/query.spec.js +166 -1
  240. package/src/api/routes/utils/validators.js +1 -0
  241. package/src/app.ts +30 -1
  242. package/src/automations/automationUtils.js +19 -4
  243. package/src/automations/logging/index.ts +35 -0
  244. package/src/automations/steps/executeQuery.js +1 -1
  245. package/src/automations/steps/filter.js +36 -28
  246. package/src/automations/tests/filter.spec.js +2 -1
  247. package/src/automations/triggers.js +1 -1
  248. package/src/db/linkedRows/index.js +1 -0
  249. package/src/db/utils.js +5 -13
  250. package/src/definitions/common.ts +1 -0
  251. package/src/definitions/datasource.ts +2 -0
  252. package/src/definitions/openapi.ts +471 -469
  253. package/src/environment.js +3 -0
  254. package/src/integrations/airtable.ts +1 -0
  255. package/src/integrations/arangodb.ts +1 -0
  256. package/src/integrations/base/sql.ts +29 -11
  257. package/src/integrations/couchdb.ts +1 -0
  258. package/src/integrations/dynamodb.ts +1 -0
  259. package/src/integrations/elasticsearch.ts +1 -0
  260. package/src/integrations/firebase.ts +1 -0
  261. package/src/integrations/googlesheets.ts +1 -0
  262. package/src/integrations/index.ts +4 -0
  263. package/src/integrations/microsoftSqlServer.ts +2 -0
  264. package/src/integrations/mongodb.ts +1 -0
  265. package/src/integrations/mysql.ts +2 -0
  266. package/src/integrations/oracle.ts +1 -0
  267. package/src/integrations/postgres.ts +2 -0
  268. package/src/integrations/queries/sql.ts +3 -1
  269. package/src/integrations/redis.ts +1 -0
  270. package/src/integrations/rest.ts +2 -1
  271. package/src/integrations/s3.ts +1 -0
  272. package/src/integrations/snowflake.ts +99 -0
  273. package/src/integrations/tests/rest.spec.js +16 -1
  274. package/src/migrations/tests/index.spec.ts +18 -2
  275. package/src/module.d.ts +2 -0
  276. package/src/tests/utilities/TestConfiguration.js +22 -3
  277. package/src/threads/automation.js +6 -3
  278. package/src/threads/index.ts +5 -1
  279. package/src/threads/query.js +88 -14
  280. package/src/utilities/fileSystem/index.js +22 -8
  281. package/src/utilities/index.js +1 -6
  282. package/src/utilities/workerRequests.js +16 -0
  283. package/builder/assets/index.1c640a53.js +0 -1316
  284. package/builder/assets/index.24307ca0.css +0 -6
@@ -74,10 +74,13 @@ module.exports = {
74
74
  DYNAMO_ENDPOINT: process.env.DYNAMO_ENDPOINT,
75
75
  QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT),
76
76
  SQL_MAX_ROWS: process.env.SQL_MAX_ROWS,
77
+ BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL,
78
+ BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
77
79
  // flags
78
80
  ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS,
79
81
  DISABLE_THREADING: process.env.DISABLE_THREADING,
80
82
  DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE,
83
+ DISABLE_AUTOMATION_LOGS: process.env.DISABLE_AUTOMATION_LOGS,
81
84
  MULTI_TENANCY: process.env.MULTI_TENANCY,
82
85
  ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
83
86
  SELF_HOSTED: process.env.SELF_HOSTED,
@@ -18,6 +18,7 @@ module AirtableModule {
18
18
  description:
19
19
  "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
20
20
  friendlyName: "Airtable",
21
+ type: "Spreadsheet",
21
22
  datasource: {
22
23
  apiKey: {
23
24
  type: DatasourceFieldTypes.PASSWORD,
@@ -19,6 +19,7 @@ module ArangoModule {
19
19
  const SCHEMA: Integration = {
20
20
  docs: "https://github.com/arangodb/arangojs",
21
21
  friendlyName: "ArangoDB",
22
+ type: "Non-relational",
22
23
  description:
23
24
  "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. ",
24
25
  datasource: {
@@ -89,6 +89,32 @@ function parseFilters(filters: SearchFilters | undefined): SearchFilters {
89
89
  return filters
90
90
  }
91
91
 
92
+ function generateSelectStatement(
93
+ json: QueryJson,
94
+ knex: Knex
95
+ ): (string | Knex.Raw)[] {
96
+ const { resource, meta } = json
97
+ const schema = meta?.table?.schema
98
+ return resource.fields.map(field => {
99
+ const fieldNames = field.split(/\./g)
100
+ const tableName = fieldNames[0]
101
+ const columnName = fieldNames[1]
102
+ if (
103
+ columnName &&
104
+ schema?.[columnName] &&
105
+ knex.client.config.client === SqlClients.POSTGRES
106
+ ) {
107
+ const externalType = schema[columnName].externalType
108
+ if (externalType?.includes("money")) {
109
+ return knex.raw(
110
+ `"${tableName}"."${columnName}"::money::numeric as "${field}"`
111
+ )
112
+ }
113
+ }
114
+ return `${field} as ${field}`
115
+ })
116
+ }
117
+
92
118
  class InternalBuilder {
93
119
  private readonly client: string
94
120
 
@@ -216,9 +242,7 @@ class InternalBuilder {
216
242
  }
217
243
 
218
244
  addRelationships(
219
- knex: Knex,
220
245
  query: KnexQuery,
221
- fields: string | string[],
222
246
  fromTable: string,
223
247
  relationships: RelationshipsJson[] | undefined
224
248
  ): KnexQuery {
@@ -323,12 +347,12 @@ class InternalBuilder {
323
347
  if (!resource) {
324
348
  resource = { fields: [] }
325
349
  }
326
- let selectStatement: string | string[] = "*"
350
+ let selectStatement: string | (string | Knex.Raw)[] = "*"
327
351
  // handle select
328
352
  if (resource.fields && resource.fields.length > 0) {
329
353
  // select the resources as the format "table.columnName" - this is what is provided
330
354
  // by the resource builder further up
331
- selectStatement = resource.fields.map(field => `${field} as ${field}`)
355
+ selectStatement = generateSelectStatement(json, knex)
332
356
  }
333
357
  let foundLimit = limit || BASE_LIMIT
334
358
  // handle pagination
@@ -363,13 +387,7 @@ class InternalBuilder {
363
387
  preQuery = this.addSorting(preQuery, json)
364
388
  }
365
389
  // handle joins
366
- query = this.addRelationships(
367
- knex,
368
- preQuery,
369
- selectStatement,
370
- tableName,
371
- relationships
372
- )
390
+ query = this.addRelationships(preQuery, tableName, relationships)
373
391
  return this.addFilters(query, filters, { relationship: true })
374
392
  }
375
393
 
@@ -16,6 +16,7 @@ module CouchDBModule {
16
16
  const SCHEMA: Integration = {
17
17
  docs: "https://docs.couchdb.org/en/stable/",
18
18
  friendlyName: "CouchDB",
19
+ type: "Non-relational",
19
20
  description:
20
21
  "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.",
21
22
  datasource: {
@@ -21,6 +21,7 @@ module DynamoModule {
21
21
  description:
22
22
  "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.",
23
23
  friendlyName: "DynamoDB",
24
+ type: "Non-relational",
24
25
  datasource: {
25
26
  region: {
26
27
  type: DatasourceFieldTypes.STRING,
@@ -17,6 +17,7 @@ module ElasticsearchModule {
17
17
  description:
18
18
  "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.",
19
19
  friendlyName: "ElasticSearch",
20
+ type: "Non-relational",
20
21
  datasource: {
21
22
  url: {
22
23
  type: DatasourceFieldTypes.STRING,
@@ -16,6 +16,7 @@ module Firebase {
16
16
  const SCHEMA: Integration = {
17
17
  docs: "https://firebase.google.com/docs/firestore/quickstart",
18
18
  friendlyName: "Firestore",
19
+ type: "Non-relational",
19
20
  description:
20
21
  "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
21
22
  datasource: {
@@ -49,6 +49,7 @@ module GoogleSheetsModule {
49
49
  description:
50
50
  "Create and collaborate on online spreadsheets in real-time and from any device. ",
51
51
  friendlyName: "Google Sheets",
52
+ type: "Spreadsheet",
52
53
  datasource: {
53
54
  spreadsheetId: {
54
55
  display: "Google Sheet URL",
@@ -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
@@ -44,6 +44,7 @@ module MSSQLModule {
44
44
  description:
45
45
  "Microsoft SQL Server is a relational database management system developed by Microsoft. ",
46
46
  friendlyName: "MS SQL Server",
47
+ type: "Relational",
47
48
  datasource: {
48
49
  user: {
49
50
  type: DatasourceFieldTypes.STRING,
@@ -246,6 +247,7 @@ module MSSQLModule {
246
247
  autocolumn: !!autoColumns.find((col: string) => col === name),
247
248
  name: name,
248
249
  ...convertSqlType(def.DATA_TYPE),
250
+ externalType: def.DATA_TYPE,
249
251
  }
250
252
  }
251
253
  tables[tableName] = {
@@ -24,6 +24,7 @@ module MongoDBModule {
24
24
  const SCHEMA: Integration = {
25
25
  docs: "https://github.com/mongodb/node-mongodb-native",
26
26
  friendlyName: "MongoDB",
27
+ type: "Non-relational",
27
28
  description:
28
29
  "MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.",
29
30
  datasource: {
@@ -36,6 +36,7 @@ module MySQLModule {
36
36
  docs: "https://github.com/sidorares/node-mysql2",
37
37
  plus: true,
38
38
  friendlyName: "MySQL",
39
+ type: "Relational",
39
40
  description:
40
41
  "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ",
41
42
  datasource: {
@@ -232,6 +233,7 @@ module MySQLModule {
232
233
  autocolumn: isAuto,
233
234
  constraints,
234
235
  ...convertSqlType(column.Type),
236
+ externalType: column.Type,
235
237
  }
236
238
  }
237
239
  if (!tables[tableName]) {
@@ -40,6 +40,7 @@ module OracleModule {
40
40
  docs: "https://github.com/oracle/node-oracledb",
41
41
  plus: true,
42
42
  friendlyName: "Oracle",
43
+ type: "Relational",
43
44
  description:
44
45
  "Oracle Database is an object-relational database management system developed by Oracle Corporation",
45
46
  datasource: {
@@ -47,6 +47,7 @@ module PostgresModule {
47
47
  docs: "https://node-postgres.com",
48
48
  plus: true,
49
49
  friendlyName: "PostgreSQL",
50
+ type: "Relational",
50
51
  description:
51
52
  "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.",
52
53
  datasource: {
@@ -271,6 +272,7 @@ module PostgresModule {
271
272
  autocolumn: isAuto,
272
273
  name: columnName,
273
274
  ...convertSqlType(column.data_type),
275
+ externalType: column.data_type,
274
276
  }
275
277
  }
276
278
 
@@ -9,7 +9,9 @@ export function enrichQueryFields(
9
9
  parameters = {}
10
10
  ) {
11
11
  const enrichedQuery: { [key: string]: any } = Array.isArray(fields) ? [] : {}
12
-
12
+ if (!fields || !parameters) {
13
+ return enrichedQuery
14
+ }
13
15
  // enrich the fields with dynamic parameters
14
16
  for (let key of Object.keys(fields)) {
15
17
  if (fields[key] == null) {
@@ -17,6 +17,7 @@ module RedisModule {
17
17
  docs: "https://redis.io/docs/",
18
18
  description: "",
19
19
  friendlyName: "Redis",
20
+ type: "Non-relational",
20
21
  datasource: {
21
22
  host: {
22
23
  type: "string",
@@ -64,6 +64,7 @@ module RestModule {
64
64
  description:
65
65
  "With the REST API datasource, you can connect, query and pull data from multiple REST APIs. You can then use the retrieved data to build apps.",
66
66
  friendlyName: "REST API",
67
+ type: "API",
67
68
  datasource: {
68
69
  url: {
69
70
  type: DatasourceFieldTypes.STRING,
@@ -286,7 +287,7 @@ module RestModule {
286
287
  input.body = form
287
288
  break
288
289
  case BodyTypes.XML:
289
- if (object != null) {
290
+ if (object != null && Object.keys(object).length) {
290
291
  string = new XmlBuilder().buildObject(object)
291
292
  }
292
293
  input.body = string
@@ -17,6 +17,7 @@ module S3Module {
17
17
  description:
18
18
  "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.",
19
19
  friendlyName: "Amazon S3",
20
+ type: "Object store",
20
21
  datasource: {
21
22
  region: {
22
23
  type: "string",
@@ -0,0 +1,99 @@
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
+ type: "Relational",
20
+ datasource: {
21
+ account: {
22
+ type: "string",
23
+ required: true,
24
+ },
25
+ username: {
26
+ type: "string",
27
+ required: true,
28
+ },
29
+ password: {
30
+ type: "password",
31
+ required: true,
32
+ },
33
+ warehouse: {
34
+ type: "string",
35
+ required: true,
36
+ },
37
+ database: {
38
+ type: "string",
39
+ required: true,
40
+ },
41
+ schema: {
42
+ type: "string",
43
+ required: true,
44
+ },
45
+ },
46
+ query: {
47
+ create: {
48
+ type: QueryTypes.SQL,
49
+ },
50
+ read: {
51
+ type: QueryTypes.SQL,
52
+ },
53
+ update: {
54
+ type: QueryTypes.SQL,
55
+ },
56
+ delete: {
57
+ type: QueryTypes.SQL,
58
+ },
59
+ },
60
+ }
61
+
62
+ class SnowflakeIntegration {
63
+ private client: Snowflake
64
+
65
+ constructor(config: SnowflakeConfig) {
66
+ this.client = new Snowflake(config)
67
+ }
68
+
69
+ async internalQuery(query: SqlQuery) {
70
+ await this.client.connect()
71
+ try {
72
+ return await this.client.execute(query.sql)
73
+ } catch (err: any) {
74
+ throw err?.message.split(":")[1] || err?.message
75
+ }
76
+ }
77
+
78
+ async create(query: SqlQuery) {
79
+ return this.internalQuery(query)
80
+ }
81
+
82
+ async read(query: SqlQuery) {
83
+ return this.internalQuery(query)
84
+ }
85
+
86
+ async update(query: SqlQuery) {
87
+ return this.internalQuery(query)
88
+ }
89
+
90
+ async delete(query: SqlQuery) {
91
+ return this.internalQuery(query)
92
+ }
93
+ }
94
+
95
+ module.exports = {
96
+ schema: SCHEMA,
97
+ integration: SnowflakeIntegration,
98
+ }
99
+ }
@@ -155,12 +155,27 @@ describe("REST Integration", () => {
155
155
  expect(output.headers["Content-Type"]).toEqual("application/json")
156
156
  })
157
157
 
158
- it("should allow XML", () => {
158
+ it("should allow raw XML", () => {
159
+ const output = config.integration.addBody("xml", "<a>1</a><b>2</b>", {})
160
+ expect(output.body.includes("<a>1</a>")).toEqual(true)
161
+ expect(output.body.includes("<b>2</b>")).toEqual(true)
162
+ expect(output.headers["Content-Type"]).toEqual("application/xml")
163
+ })
164
+
165
+ it("should allow a valid js object and parse the contents to xml", () => {
159
166
  const output = config.integration.addBody("xml", input, {})
160
167
  expect(output.body.includes("<a>1</a>")).toEqual(true)
161
168
  expect(output.body.includes("<b>2</b>")).toEqual(true)
162
169
  expect(output.headers["Content-Type"]).toEqual("application/xml")
163
170
  })
171
+
172
+ it("should allow a valid json string and parse the contents to xml", () => {
173
+ const output = config.integration.addBody("xml", JSON.stringify(input), {})
174
+ expect(output.body.includes("<a>1</a>")).toEqual(true)
175
+ expect(output.body.includes("<b>2</b>")).toEqual(true)
176
+ expect(output.headers["Content-Type"]).toEqual("application/xml")
177
+ })
178
+
164
179
  })
165
180
 
166
181
  describe("response", () => {
@@ -93,8 +93,24 @@ describe("migrations", () => {
93
93
  await clearMigrations()
94
94
  const appId = config.prodAppId
95
95
  const roles = { [appId]: "role_12345" }
96
- await config.createUser(undefined, undefined, false, true, roles) // admin only
97
- await config.createUser(undefined, undefined, false, false, roles) // non admin non builder
96
+ await config.createUser(
97
+ undefined,
98
+ undefined,
99
+ undefined,
100
+ undefined,
101
+ false,
102
+ true,
103
+ roles
104
+ ) // admin only
105
+ await config.createUser(
106
+ undefined,
107
+ undefined,
108
+ undefined,
109
+ undefined,
110
+ false,
111
+ false,
112
+ roles
113
+ ) // non admin non builder
98
114
  await config.createTable()
99
115
  await config.createRow()
100
116
  await config.createRow()
package/src/module.d.ts CHANGED
@@ -8,3 +8,5 @@ declare module "@budibase/backend-core/constants"
8
8
  declare module "@budibase/backend-core/auth"
9
9
  declare module "@budibase/backend-core/sessions"
10
10
  declare module "@budibase/backend-core/encryption"
11
+ declare module "@budibase/backend-core/utils"
12
+ declare module "@budibase/backend-core/redis"
@@ -28,6 +28,8 @@ const { encrypt } = require("@budibase/backend-core/encryption")
28
28
 
29
29
  const GLOBAL_USER_ID = "us_uuid1"
30
30
  const EMAIL = "babs@babs.com"
31
+ const FIRSTNAME = "Barbara"
32
+ const LASTNAME = "Barbington"
31
33
  const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306"
32
34
 
33
35
  class TestConfiguration {
@@ -59,6 +61,15 @@ class TestConfiguration {
59
61
  return this.prodAppId
60
62
  }
61
63
 
64
+ getUserDetails() {
65
+ return {
66
+ globalId: GLOBAL_USER_ID,
67
+ email: EMAIL,
68
+ firstName: FIRSTNAME,
69
+ lastName: LASTNAME,
70
+ }
71
+ }
72
+
62
73
  async doInContext(appId, task) {
63
74
  if (!appId) {
64
75
  appId = this.appId
@@ -118,6 +129,8 @@ class TestConfiguration {
118
129
  // USER / AUTH
119
130
  async globalUser({
120
131
  id = GLOBAL_USER_ID,
132
+ firstName = FIRSTNAME,
133
+ lastName = LASTNAME,
121
134
  builder = true,
122
135
  admin = false,
123
136
  email = EMAIL,
@@ -135,6 +148,8 @@ class TestConfiguration {
135
148
  ...existing,
136
149
  roles: roles || {},
137
150
  tenantId: TENANT_ID,
151
+ firstName,
152
+ lastName,
138
153
  }
139
154
  await createASession(id, {
140
155
  sessionId: "sessionid",
@@ -161,6 +176,8 @@ class TestConfiguration {
161
176
 
162
177
  async createUser(
163
178
  id = null,
179
+ firstName = FIRSTNAME,
180
+ lastName = LASTNAME,
164
181
  email = EMAIL,
165
182
  builder = true,
166
183
  admin = false,
@@ -169,6 +186,8 @@ class TestConfiguration {
169
186
  const globalId = !id ? `us_${Math.random()}` : `us_${id}`
170
187
  const resp = await this.globalUser({
171
188
  id: globalId,
189
+ firstName,
190
+ lastName,
172
191
  email,
173
192
  builder,
174
193
  admin,
@@ -520,14 +539,14 @@ class TestConfiguration {
520
539
 
521
540
  // QUERY
522
541
 
523
- async previewQuery(request, config, datasource, fields) {
542
+ async previewQuery(request, config, datasource, fields, params, verb) {
524
543
  return request
525
544
  .post(`/api/queries/preview`)
526
545
  .send({
527
546
  datasourceId: datasource._id,
528
- parameters: {},
547
+ parameters: params || {},
529
548
  fields,
530
- queryVerb: "read",
549
+ queryVerb: verb || "read",
531
550
  name: datasource.name,
532
551
  })
533
552
  .set(config.defaultHeaders())
@@ -9,11 +9,12 @@ const { doInTenant } = require("@budibase/backend-core/tenancy")
9
9
  const { definitions: triggerDefs } = require("../automations/triggerInfo")
10
10
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
11
11
  const { AutomationErrors, LoopStepTypes } = require("../constants")
12
+ const { storeLog } = require("../automations/logging")
12
13
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
13
14
  const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
14
15
 
15
16
  const CRON_STEP_ID = triggerDefs.CRON.stepId
16
- const STOPPED_STATUS = { success: false, status: "STOPPED" }
17
+ const STOPPED_STATUS = { success: true, status: "STOPPED" }
17
18
  const { cloneDeep } = require("lodash/fp")
18
19
  const env = require("../environment")
19
20
 
@@ -218,7 +219,7 @@ class Orchestrator {
218
219
  }
219
220
  }
220
221
  if (
221
- index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
222
+ index === env.AUTOMATION_MAX_ITERATION ||
222
223
  index === parseInt(loopStep.inputs.iterations)
223
224
  ) {
224
225
  this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
@@ -275,7 +276,7 @@ class Orchestrator {
275
276
  this._context.steps[stepCount] = outputs
276
277
  // if filter causes us to stop execution don't break the loop, set a var
277
278
  // so that we can finish iterating through the steps and record that it stopped
278
- if (step.stepId === FILTER_STEP_ID && !outputs.success) {
279
+ if (step.stepId === FILTER_STEP_ID && !outputs.result) {
279
280
  stopped = true
280
281
  this.updateExecutionOutput(step.id, step.stepId, step.inputs, {
281
282
  ...outputs,
@@ -325,6 +326,8 @@ class Orchestrator {
325
326
  }
326
327
  }
327
328
 
329
+ // store the logs for the automation run
330
+ await storeLog(this._automation, this.executionOutput)
328
331
  return this.executionOutput
329
332
  }
330
333
  }
@@ -77,7 +77,7 @@ export class Thread {
77
77
  })
78
78
  }
79
79
 
80
- static shutdown() {
80
+ static stopThreads() {
81
81
  return new Promise<void>(resolve => {
82
82
  if (Thread.workerRefs.length === 0) {
83
83
  resolve()
@@ -95,4 +95,8 @@ export class Thread {
95
95
  Thread.workerRefs = []
96
96
  })
97
97
  }
98
+
99
+ static async shutdown() {
100
+ await Thread.stopThreads()
101
+ }
98
102
  }