@budibase/server 0.9.185-alpha.1 → 0.9.185-alpha.13

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 (234) hide show
  1. package/Dockerfile +1 -1
  2. package/builder/assets/bb-space-man.5be51a45.svg +290 -0
  3. package/builder/assets/index.4a7c5636.css +1 -0
  4. package/builder/assets/index.dc495306.js +1317 -0
  5. package/builder/assets/vendor.470042a4.js +152 -0
  6. package/builder/assets/vendor.5e1fe644.css +1 -0
  7. package/builder/index.html +4 -4
  8. package/coverage/clover.xml +689 -598
  9. package/coverage/coverage-final.json +89 -87
  10. package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
  11. package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
  12. package/coverage/lcov-report/api/controllers/application.js.html +43 -13
  13. package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
  14. package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
  15. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  18. package/coverage/lcov-report/api/controllers/datasource.js.html +129 -21
  19. package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
  20. package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
  21. package/coverage/lcov-report/api/controllers/index.html +83 -83
  22. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
  24. package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
  25. package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
  26. package/coverage/lcov-report/api/controllers/query.js.html +48 -210
  27. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
  29. package/coverage/lcov-report/api/controllers/row/external.js.html +2 -2
  30. package/coverage/lcov-report/api/controllers/row/index.html +10 -10
  31. package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
  32. package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
  33. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
  34. package/coverage/lcov-report/api/controllers/row/utils.js.html +2 -2
  35. package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
  36. package/coverage/lcov-report/api/controllers/script.js.html +3 -3
  37. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.html +11 -11
  39. package/coverage/lcov-report/api/controllers/table/index.js.html +3 -3
  40. package/coverage/lcov-report/api/controllers/table/internal.js.html +2 -2
  41. package/coverage/lcov-report/api/controllers/table/utils.js.html +8 -8
  42. package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
  43. package/coverage/lcov-report/api/controllers/user.js.html +33 -18
  44. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/index.html +9 -9
  46. package/coverage/lcov-report/api/controllers/view/index.js.html +5 -5
  47. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  48. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
  49. package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
  50. package/coverage/lcov-report/api/index.html +1 -1
  51. package/coverage/lcov-report/api/index.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/dev.js.html +2 -2
  63. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/index.html +4 -4
  65. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/query.js.html +5 -2
  71. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/static.js.html +2 -2
  77. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  82. package/coverage/lcov-report/automations/actions.js.html +2 -2
  83. package/coverage/lcov-report/automations/automationUtils.js.html +3 -3
  84. package/coverage/lcov-report/automations/bullboard.js.html +71 -20
  85. package/coverage/lcov-report/automations/index.html +33 -48
  86. package/coverage/lcov-report/automations/index.js.html +2 -2
  87. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
  92. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
  94. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/index.html +14 -14
  96. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
  98. package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
  99. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
  104. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  106. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  107. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  109. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  110. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggers.js.html +22 -10
  114. package/coverage/lcov-report/automations/utils.js.html +42 -12
  115. package/coverage/lcov-report/constants/index.html +5 -5
  116. package/coverage/lcov-report/constants/index.js.html +25 -4
  117. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  118. package/coverage/lcov-report/constants/screens.js.html +1 -1
  119. package/coverage/lcov-report/db/client.js.html +2 -2
  120. package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
  121. package/coverage/lcov-report/db/index.html +2 -2
  122. package/coverage/lcov-report/db/index.js.html +1 -1
  123. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
  124. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  125. package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
  126. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
  127. package/coverage/lcov-report/db/newid.js.html +1 -1
  128. package/coverage/lcov-report/db/utils.js.html +1 -1
  129. package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
  130. package/coverage/lcov-report/events/index.html +6 -6
  131. package/coverage/lcov-report/events/index.js.html +1 -1
  132. package/coverage/lcov-report/events/utils.js.html +5 -5
  133. package/coverage/lcov-report/index.html +83 -68
  134. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  135. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  136. package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
  137. package/coverage/lcov-report/middleware/authorized.js.html +4 -4
  138. package/coverage/lcov-report/middleware/builder.js.html +16 -7
  139. package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
  140. package/coverage/lcov-report/middleware/index.html +21 -21
  141. package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
  142. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  143. package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
  144. package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
  145. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  146. package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +83 -32
  147. package/coverage/lcov-report/threads/index.html +141 -0
  148. package/coverage/lcov-report/threads/index.js.html +260 -0
  149. package/coverage/lcov-report/threads/query.js.html +269 -0
  150. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  151. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  152. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  153. package/coverage/lcov-report/utilities/csvParser.js.html +2 -2
  154. package/coverage/lcov-report/utilities/global.js.html +2 -2
  155. package/coverage/lcov-report/utilities/index.html +21 -21
  156. package/coverage/lcov-report/utilities/index.js.html +12 -9
  157. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
  158. package/coverage/lcov-report/utilities/queue/index.html +14 -14
  159. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  160. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  161. package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
  162. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
  163. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
  164. package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
  165. package/coverage/lcov-report/utilities/security.js.html +3 -3
  166. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  167. package/coverage/lcov-report/utilities/users.js.html +1 -1
  168. package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
  169. package/coverage/lcov.info +1136 -972
  170. package/dist/api/controllers/application.js +11 -1
  171. package/dist/api/controllers/datasource.js +31 -7
  172. package/dist/api/controllers/deploy/index.js +2 -0
  173. package/dist/api/controllers/dev.js +4 -1
  174. package/dist/api/controllers/query.js +27 -57
  175. package/dist/api/controllers/user.js +10 -6
  176. package/dist/api/routes/query.js +1 -1
  177. package/dist/app.js +2 -11
  178. package/dist/automations/bullboard.js +37 -10
  179. package/dist/automations/triggers.js +7 -3
  180. package/dist/automations/utils.js +11 -2
  181. package/dist/constants/index.js +6 -0
  182. package/dist/integrations/base/IntegrationBase.js +2 -0
  183. package/dist/integrations/base/sql.js +36 -8
  184. package/dist/integrations/mysql.js +3 -1
  185. package/dist/integrations/utils.js +7 -1
  186. package/dist/middleware/builder.js +4 -1
  187. package/dist/package.json +7 -6
  188. package/dist/{automations/thread.js → threads/automation.js} +23 -7
  189. package/dist/threads/index.js +58 -0
  190. package/dist/threads/query.js +61 -0
  191. package/dist/tsconfig.tsbuildinfo +1 -1
  192. package/dist/utilities/index.js +1 -0
  193. package/dist/utilities/queue/inMemoryQueue.js +8 -0
  194. package/dist/utilities/scriptRunner.js +4 -1
  195. package/package.json +8 -7
  196. package/scripts/likeCypress.ts +33 -0
  197. package/src/api/controllers/application.js +11 -1
  198. package/src/api/controllers/datasource.js +45 -9
  199. package/src/api/controllers/deploy/index.js +2 -0
  200. package/src/api/controllers/dev.js +4 -1
  201. package/src/api/controllers/query.js +26 -80
  202. package/src/api/controllers/user.js +15 -10
  203. package/src/api/routes/query.js +1 -0
  204. package/src/app.ts +2 -10
  205. package/src/automations/bullboard.js +28 -11
  206. package/src/automations/tests/automation.spec.js +3 -4
  207. package/src/automations/triggers.js +7 -3
  208. package/src/automations/utils.js +12 -2
  209. package/src/constants/index.js +7 -0
  210. package/src/integrations/airtable.ts +2 -1
  211. package/src/integrations/arangodb.ts +2 -1
  212. package/src/integrations/base/IntegrationBase.ts +6 -0
  213. package/src/integrations/base/datasourcePlus.ts +2 -1
  214. package/src/integrations/base/sql.ts +38 -9
  215. package/src/integrations/couchdb.ts +2 -1
  216. package/src/integrations/dynamodb.ts +2 -1
  217. package/src/integrations/elasticsearch.ts +2 -1
  218. package/src/integrations/mongodb.ts +2 -1
  219. package/src/integrations/mysql.ts +1 -1
  220. package/src/integrations/rest.ts +2 -1
  221. package/src/integrations/s3.ts +2 -1
  222. package/src/integrations/utils.ts +6 -1
  223. package/src/middleware/builder.js +4 -1
  224. package/src/{automations/thread.js → threads/automation.js} +24 -7
  225. package/src/threads/index.js +60 -0
  226. package/src/threads/query.js +63 -0
  227. package/src/utilities/index.js +1 -0
  228. package/src/utilities/queue/inMemoryQueue.js +7 -0
  229. package/src/utilities/scriptRunner.js +4 -1
  230. package/tsconfig.json +1 -1
  231. package/builder/assets/index.4feb6e69.js +0 -201
  232. package/builder/assets/index.a79ec0ef.css +0 -29
  233. package/builder/assets/vendor.278a305c.js +0 -9
  234. package/builder/assets/vendor.d75d5eb7.css +0 -1
@@ -163,8 +163,15 @@ exports.MetadataTypes = {
163
163
  AUTOMATION_TEST_HISTORY: "automationTestHistory",
164
164
  }
165
165
 
166
+ exports.InvalidColumns = {
167
+ ID: "_id",
168
+ REV: "_rev",
169
+ TABLE_ID: "tableId",
170
+ }
171
+
166
172
  exports.BuildSchemaErrors = {
167
173
  NO_KEY: "no_key",
174
+ INVALID_COLUMN: "invalid_column",
168
175
  }
169
176
 
170
177
  // pass through the list from the auth/core lib
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module AirtableModule {
8
9
  const Airtable = require("airtable")
@@ -73,7 +74,7 @@ module AirtableModule {
73
74
  },
74
75
  }
75
76
 
76
- class AirtableIntegration {
77
+ class AirtableIntegration implements IntegrationBase {
77
78
  private config: AirtableConfig
78
79
  private client: any
79
80
 
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module ArangoModule {
8
9
  const { Database, aql } = require("arangojs")
@@ -55,7 +56,7 @@ module ArangoModule {
55
56
  },
56
57
  }
57
58
 
58
- class ArangoDBIntegration {
59
+ class ArangoDBIntegration implements IntegrationBase {
59
60
  private config: ArangodbConfig
60
61
  private client: any
61
62
 
@@ -0,0 +1,6 @@
1
+ export interface IntegrationBase {
2
+ create?(query: any): Promise<[any]>
3
+ read?(query: any): Promise<[any]>
4
+ update?(query: any): Promise<[any]>
5
+ delete?(query: any): Promise<[any]>
6
+ }
@@ -1,6 +1,7 @@
1
1
  import { Table } from "../../definitions/common"
2
+ import { IntegrationBase } from "./IntegrationBase"
2
3
 
3
- export interface DatasourcePlus {
4
+ export interface DatasourcePlus extends IntegrationBase {
4
5
  tables: Record<string, Table>
5
6
  schemaErrors: Record<string, string>
6
7
 
@@ -13,22 +13,50 @@ import SqlTableQueryBuilder from "./sqlTable"
13
13
  const BASE_LIMIT = 5000
14
14
 
15
15
  type KnexQuery = Knex.QueryBuilder | Knex
16
+ // these are invalid dates sent by the client, need to convert them to a real max date
17
+ const MIN_ISO_DATE = "0000-00-00T00:00:00.000Z"
18
+ const MAX_ISO_DATE = "9999-00-00T00:00:00.000Z"
19
+
20
+ function parse(input: any) {
21
+ if (Array.isArray(input)) {
22
+ return JSON.stringify(input)
23
+ }
24
+ if (typeof input !== "string") {
25
+ return input
26
+ }
27
+ if (input === MAX_ISO_DATE) {
28
+ return new Date(8640000000000000)
29
+ }
30
+ if (input === MIN_ISO_DATE) {
31
+ return new Date(-8640000000000000)
32
+ }
33
+ if (isIsoDateString(input)) {
34
+ return new Date(input)
35
+ }
36
+ return input
37
+ }
16
38
 
17
39
  function parseBody(body: any) {
18
40
  for (let [key, value] of Object.entries(body)) {
19
- if (Array.isArray(value)) {
20
- body[key] = JSON.stringify(value)
21
- }
22
- if (typeof value !== "string") {
23
- continue
24
- }
25
- if (isIsoDateString(value)) {
26
- body[key] = new Date(value)
27
- }
41
+ body[key] = parse(value)
28
42
  }
29
43
  return body
30
44
  }
31
45
 
46
+ function parseFilters(filters: SearchFilters): SearchFilters {
47
+ for (let [key, value] of Object.entries(filters)) {
48
+ let parsed
49
+ if (typeof value === "object") {
50
+ parsed = parseFilters(value)
51
+ } else {
52
+ parsed = parse(value)
53
+ }
54
+ // @ts-ignore
55
+ filters[key] = parsed
56
+ }
57
+ return filters
58
+ }
59
+
32
60
  class InternalBuilder {
33
61
  private readonly client: string
34
62
 
@@ -53,6 +81,7 @@ class InternalBuilder {
53
81
  if (!filters) {
54
82
  return query
55
83
  }
84
+ filters = parseFilters(filters)
56
85
  // if all or specified in filters, then everything is an or
57
86
  const allOr = filters.allOr
58
87
  if (filters.oneOf) {
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module CouchDBModule {
8
9
  const PouchDB = require("pouchdb")
@@ -50,7 +51,7 @@ module CouchDBModule {
50
51
  },
51
52
  }
52
53
 
53
- class CouchDBIntegration {
54
+ class CouchDBIntegration implements IntegrationBase {
54
55
  private config: CouchDBConfig
55
56
  private client: any
56
57
 
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module DynamoModule {
8
9
  const AWS = require("aws-sdk")
@@ -113,7 +114,7 @@ module DynamoModule {
113
114
  },
114
115
  }
115
116
 
116
- class DynamoDBIntegration {
117
+ class DynamoDBIntegration implements IntegrationBase {
117
118
  private config: DynamoDBConfig
118
119
  private client: any
119
120
 
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module ElasticsearchModule {
8
9
  const { Client } = require("@elastic/elasticsearch")
@@ -74,7 +75,7 @@ module ElasticsearchModule {
74
75
  },
75
76
  }
76
77
 
77
- class ElasticSearchIntegration {
78
+ class ElasticSearchIntegration implements IntegrationBase {
78
79
  private config: ElasticsearchConfig
79
80
  private client: any
80
81
 
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module MongoDBModule {
8
9
  const { MongoClient } = require("mongodb")
@@ -62,7 +63,7 @@ module MongoDBModule {
62
63
  },
63
64
  }
64
65
 
65
- class MongoIntegration {
66
+ class MongoIntegration implements IntegrationBase {
66
67
  private config: MongoDBConfig
67
68
  private client: any
68
69
 
@@ -184,7 +184,7 @@ module MySQLModule {
184
184
  return results.length ? results : [{ created: true }]
185
185
  }
186
186
 
187
- read(query: SqlQuery | string) {
187
+ async read(query: SqlQuery | string) {
188
188
  return internalQuery(this.client, getSqlQuery(query))
189
189
  }
190
190
 
@@ -3,6 +3,7 @@ import {
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
5
  } from "../definitions/datasource"
6
+ import { IntegrationBase } from "./base/IntegrationBase"
6
7
 
7
8
  module RestModule {
8
9
  const fetch = require("node-fetch")
@@ -131,7 +132,7 @@ module RestModule {
131
132
  },
132
133
  }
133
134
 
134
- class RestIntegration {
135
+ class RestIntegration implements IntegrationBase {
135
136
  private config: RestConfig
136
137
  private headers: {
137
138
  [key: string]: string
@@ -1,4 +1,5 @@
1
1
  import { Integration, QueryTypes } from "../definitions/datasource"
2
+ import { IntegrationBase } from "./base/IntegrationBase"
2
3
 
3
4
  module S3Module {
4
5
  const AWS = require("aws-sdk")
@@ -42,7 +43,7 @@ module S3Module {
42
43
  },
43
44
  }
44
45
 
45
- class S3Integration {
46
+ class S3Integration implements IntegrationBase {
46
47
  private readonly config: S3Config
47
48
  private client: any
48
49
  private connectionPromise: Promise<any>
@@ -2,7 +2,7 @@ import { SqlQuery } from "../definitions/datasource"
2
2
  import { Datasource, Table } from "../definitions/common"
3
3
  import { SourceNames } from "../definitions/datasource"
4
4
  const { DocumentTypes, SEPARATOR } = require("../db/utils")
5
- const { FieldTypes, BuildSchemaErrors } = require("../constants")
5
+ const { FieldTypes, BuildSchemaErrors, InvalidColumns } = require("../constants")
6
6
 
7
7
  const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`
8
8
  const ROW_ID_REGEX = /^\[.*]$/g
@@ -161,13 +161,18 @@ export function finaliseExternalTables(
161
161
  tables: { [key: string]: any },
162
162
  entities: { [key: string]: any }
163
163
  ) {
164
+ const invalidColumns = Object.values(InvalidColumns)
164
165
  const finalTables: { [key: string]: any } = {}
165
166
  const errors: { [key: string]: string } = {}
166
167
  for (let [name, table] of Object.entries(tables)) {
168
+ const schemaFields = Object.keys(table.schema)
167
169
  // make sure every table has a key
168
170
  if (table.primary == null || table.primary.length === 0) {
169
171
  errors[name] = BuildSchemaErrors.NO_KEY
170
172
  continue
173
+ } else if (schemaFields.find(field => invalidColumns.includes(field))) {
174
+ errors[name] = BuildSchemaErrors.INVALID_COLUMN
175
+ continue
171
176
  }
172
177
  // make sure all previous props have been added back
173
178
  finalTables[name] = copyExistingPropsOver(name, table, entities)
@@ -8,6 +8,7 @@ const {
8
8
  const CouchDB = require("../db")
9
9
  const { DocumentTypes } = require("../db/utils")
10
10
  const { PermissionTypes } = require("@budibase/auth/permissions")
11
+ const { app: appCache } = require("@budibase/auth/cache")
11
12
 
12
13
  const DEBOUNCE_TIME_SEC = 30
13
14
 
@@ -50,7 +51,9 @@ async function updateAppUpdatedAt(ctx) {
50
51
  const db = new CouchDB(appId)
51
52
  const metadata = await db.get(DocumentTypes.APP_METADATA)
52
53
  metadata.updatedAt = new Date().toISOString()
53
- await db.put(metadata)
54
+ const response = await db.put(metadata)
55
+ metadata._rev = response.rev
56
+ await appCache.invalidateAppMetadata(appId, metadata)
54
57
  // set a new debounce record with a short TTL
55
58
  await setDebounce(appId, DEBOUNCE_TIME_SEC)
56
59
  }
@@ -1,5 +1,5 @@
1
- const actions = require("./actions")
2
- const automationUtils = require("./automationUtils")
1
+ const actions = require("../automations/actions")
2
+ const automationUtils = require("../automations/automationUtils")
3
3
  const AutomationEmitter = require("../events/AutomationEmitter")
4
4
  const { processObject } = require("@budibase/string-templates")
5
5
  const { DEFAULT_TENANT_ID } = require("@budibase/auth").constants
@@ -8,8 +8,10 @@ const { DocumentTypes, isDevAppID } = require("../db/utils")
8
8
  const { doInTenant } = require("@budibase/auth/tenancy")
9
9
  const env = require("../environment")
10
10
  const usage = require("../utilities/usageQuota")
11
+ const { definitions: triggerDefs } = require("../automations/triggerInfo")
11
12
 
12
13
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
14
+ const CRON_STEP_ID = triggerDefs.CRON.stepId
13
15
  const STOPPED_STATUS = { success: false, status: "STOPPED" }
14
16
 
15
17
  /**
@@ -23,6 +25,8 @@ class Orchestrator {
23
25
  this._chainCount = this._metadata ? this._metadata.automationChainCount : 0
24
26
  this._appId = triggerOutput.appId
25
27
  this._app = null
28
+ const triggerStepId = automation.definition.trigger.stepId
29
+ triggerOutput = this.cleanupTriggerOutputs(triggerStepId, triggerOutput)
26
30
  // remove from context
27
31
  delete triggerOutput.appId
28
32
  delete triggerOutput.metadata
@@ -34,11 +38,17 @@ class Orchestrator {
34
38
  this._emitter = new AutomationEmitter(this._chainCount + 1)
35
39
  this.executionOutput = { trigger: {}, steps: [] }
36
40
  // setup the execution output
37
- const triggerStepId = automation.definition.trigger.stepId
38
41
  const triggerId = automation.definition.trigger.id
39
42
  this.updateExecutionOutput(triggerId, triggerStepId, null, triggerOutput)
40
43
  }
41
44
 
45
+ cleanupTriggerOutputs(stepId, triggerOutput) {
46
+ if (stepId === CRON_STEP_ID) {
47
+ triggerOutput.timestamp = Date.now()
48
+ }
49
+ return triggerOutput
50
+ }
51
+
42
52
  async getStepFunctionality(stepId) {
43
53
  let step = await actions.getAction(stepId)
44
54
  if (step == null) {
@@ -119,10 +129,17 @@ class Orchestrator {
119
129
  }
120
130
  }
121
131
 
122
- module.exports = async job => {
132
+ module.exports = (input, callback) => {
123
133
  const automationOrchestrator = new Orchestrator(
124
- job.data.automation,
125
- job.data.event
134
+ input.data.automation,
135
+ input.data.event
126
136
  )
127
- return automationOrchestrator.execute()
137
+ automationOrchestrator
138
+ .execute()
139
+ .then(response => {
140
+ callback(null, response)
141
+ })
142
+ .catch(err => {
143
+ callback(err)
144
+ })
128
145
  }
@@ -0,0 +1,60 @@
1
+ const workerFarm = require("worker-farm")
2
+ const env = require("../environment")
3
+
4
+ const ThreadType = {
5
+ QUERY: "query",
6
+ AUTOMATION: "automation",
7
+ }
8
+
9
+ function typeToFile(type) {
10
+ let filename = null
11
+ switch (type) {
12
+ case ThreadType.QUERY:
13
+ filename = "./query"
14
+ break
15
+ case ThreadType.AUTOMATION:
16
+ filename = "./automation"
17
+ break
18
+ default:
19
+ throw "Unknown thread type"
20
+ }
21
+ return require.resolve(filename)
22
+ }
23
+
24
+ class Thread {
25
+ constructor(type, opts = { timeoutMs: null, count: 1 }) {
26
+ this.type = type
27
+ if (!env.isTest()) {
28
+ const workerOpts = {
29
+ autoStart: true,
30
+ maxConcurrentWorkers: opts.count ? opts.count : 1,
31
+ }
32
+ if (opts.timeoutMs) {
33
+ workerOpts.maxCallTime = opts.timeoutMs
34
+ }
35
+ this.workers = workerFarm(workerOpts, typeToFile(type))
36
+ }
37
+ }
38
+
39
+ run(data) {
40
+ return new Promise((resolve, reject) => {
41
+ let fncToCall
42
+ // if in test then don't use threading
43
+ if (env.isTest()) {
44
+ fncToCall = require(typeToFile(this.type))
45
+ } else {
46
+ fncToCall = this.workers
47
+ }
48
+ fncToCall(data, (err, response) => {
49
+ if (err) {
50
+ reject(err)
51
+ } else {
52
+ resolve(response)
53
+ }
54
+ })
55
+ })
56
+ }
57
+ }
58
+
59
+ module.exports.Thread = Thread
60
+ module.exports.ThreadType = ThreadType
@@ -0,0 +1,63 @@
1
+ const ScriptRunner = require("../utilities/scriptRunner")
2
+ const { integrations } = require("../integrations")
3
+
4
+ function formatResponse(resp) {
5
+ if (typeof resp === "string") {
6
+ try {
7
+ resp = JSON.parse(resp)
8
+ } catch (err) {
9
+ resp = { response: resp }
10
+ }
11
+ }
12
+ return resp
13
+ }
14
+
15
+ async function runAndTransform(datasource, queryVerb, query, transformer) {
16
+ const Integration = integrations[datasource.source]
17
+ if (!Integration) {
18
+ throw "Integration type does not exist."
19
+ }
20
+ const integration = new Integration(datasource.config)
21
+
22
+ let rows = formatResponse(await integration[queryVerb](query))
23
+
24
+ // transform as required
25
+ if (transformer) {
26
+ const runner = new ScriptRunner(transformer, { data: rows })
27
+ rows = runner.execute()
28
+ }
29
+
30
+ // needs to an array for next step
31
+ if (!Array.isArray(rows)) {
32
+ rows = [rows]
33
+ }
34
+
35
+ // map into JSON if just raw primitive here
36
+ if (rows.find(row => typeof row !== "object")) {
37
+ rows = rows.map(value => ({ value }))
38
+ }
39
+
40
+ // get all the potential fields in the schema
41
+ let keys = rows.flatMap(Object.keys)
42
+
43
+ if (integration.end) {
44
+ integration.end()
45
+ }
46
+
47
+ return { rows, keys }
48
+ }
49
+
50
+ module.exports = (input, callback) => {
51
+ runAndTransform(
52
+ input.datasource,
53
+ input.queryVerb,
54
+ input.query,
55
+ input.transformer
56
+ )
57
+ .then(response => {
58
+ callback(null, response)
59
+ })
60
+ .catch(err => {
61
+ callback(err)
62
+ })
63
+ }
@@ -48,6 +48,7 @@ exports.objectStoreUrl = () => {
48
48
  * via a specific endpoint (under /api/assets/client).
49
49
  * @param {string} appId In production we need the appId to look up the correct bucket, as the
50
50
  * version of the client lib may differ between apps.
51
+ * @param {string} version The version to retrieve.
51
52
  * @return {string} The URL to be inserted into appPackage response or server rendered
52
53
  * app index file.
53
54
  */
@@ -89,6 +89,13 @@ class InMemoryQueue {
89
89
  getRepeatableJobs() {
90
90
  return []
91
91
  }
92
+
93
+ /**
94
+ * Implemented for tests
95
+ */
96
+ async clean() {
97
+ return []
98
+ }
92
99
  }
93
100
 
94
101
  module.exports = InMemoryQueue
@@ -1,10 +1,13 @@
1
1
  const fetch = require("node-fetch")
2
2
  const { VM, VMScript } = require("vm2")
3
+ const JS_TIMEOUT_MS = 1000
3
4
 
4
5
  class ScriptRunner {
5
6
  constructor(script, context) {
6
7
  const code = `let fn = () => {\n${script}\n}; results.out = fn();`
7
- this.vm = new VM()
8
+ this.vm = new VM({
9
+ timeout: JS_TIMEOUT_MS,
10
+ })
8
11
  this.results = { out: "" }
9
12
  this.vm.setGlobals(context)
10
13
  this.vm.setGlobal("fetch", fetch)
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "compilerOptions": {
3
3
  "target": "es6",
4
4
  "module": "commonjs",
5
- "lib": ["es6"],
5
+ "lib": ["es2019"],
6
6
  "allowJs": true,
7
7
  "outDir": "dist",
8
8
  "strict": true,