@budibase/server 1.0.113 → 1.0.116

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 (238) hide show
  1. package/builder/assets/{index.e3e5909b.js → index.28d8c64f.js} +4 -4
  2. package/builder/index.html +1 -1
  3. package/coverage/clover.xml +1212 -1269
  4. package/coverage/coverage-final.json +86 -87
  5. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/application.js.html +126 -120
  8. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
  10. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
  14. package/coverage/lcov-report/api/controllers/dev.js.html +23 -14
  15. package/coverage/lcov-report/api/controllers/index.html +17 -17
  16. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
  21. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  22. package/coverage/lcov-report/api/controllers/query/index.js.html +19 -19
  23. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  25. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/external.js.html +19 -19
  27. package/coverage/lcov-report/api/controllers/row/index.html +10 -10
  28. package/coverage/lcov-report/api/controllers/row/index.js.html +14 -14
  29. package/coverage/lcov-report/api/controllers/row/internal.js.html +37 -34
  30. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +9 -9
  31. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +10 -10
  32. package/coverage/lcov-report/api/controllers/row/utils.js.html +12 -12
  33. package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
  34. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  35. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +9 -9
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
  37. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +14 -14
  39. package/coverage/lcov-report/api/controllers/table/internal.js.html +13 -13
  40. package/coverage/lcov-report/api/controllers/table/utils.js.html +30 -30
  41. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/user.js.html +19 -19
  43. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  44. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
  46. package/coverage/lcov-report/api/controllers/view/utils.js.html +12 -12
  47. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  48. package/coverage/lcov-report/api/controllers/webhook.js.html +17 -17
  49. package/coverage/lcov-report/api/index.html +1 -1
  50. package/coverage/lcov-report/api/index.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/index.html +1 -1
  63. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  80. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  83. package/coverage/lcov-report/automations/actions.js.html +24 -24
  84. package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
  85. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  86. package/coverage/lcov-report/automations/index.html +5 -5
  87. package/coverage/lcov-report/automations/index.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/bash.js.html +7 -7
  89. package/coverage/lcov-report/automations/steps/createRow.js.html +7 -7
  90. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  91. package/coverage/lcov-report/automations/steps/deleteRow.js.html +7 -7
  92. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  93. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  94. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  95. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  96. package/coverage/lcov-report/automations/steps/index.html +1 -1
  97. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  98. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  99. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  100. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  101. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  102. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  103. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  104. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  105. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  106. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  107. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  108. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  110. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  115. package/coverage/lcov-report/automations/utils.js.html +43 -40
  116. package/coverage/lcov-report/constants/index.html +1 -1
  117. package/coverage/lcov-report/constants/index.js.html +27 -27
  118. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  119. package/coverage/lcov-report/constants/screens.js.html +4 -4
  120. package/coverage/lcov-report/db/inMemoryView.js.html +52 -49
  121. package/coverage/lcov-report/db/index.html +21 -36
  122. package/coverage/lcov-report/db/index.js.html +49 -10
  123. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +7 -7
  124. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/index.js.html +18 -18
  126. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +13 -13
  127. package/coverage/lcov-report/db/newid.js.html +2 -2
  128. package/coverage/lcov-report/db/utils.js.html +13 -13
  129. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  130. package/coverage/lcov-report/events/index.html +1 -1
  131. package/coverage/lcov-report/events/index.js.html +5 -5
  132. package/coverage/lcov-report/events/utils.js.html +3 -3
  133. package/coverage/lcov-report/index.html +52 -52
  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 +1 -1
  137. package/coverage/lcov-report/middleware/authorized.js.html +1 -1
  138. package/coverage/lcov-report/middleware/builder.js.html +15 -12
  139. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  140. package/coverage/lcov-report/middleware/index.html +4 -4
  141. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  142. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  143. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  144. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  145. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  146. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  147. package/coverage/lcov-report/threads/automation.js.html +1 -1
  148. package/coverage/lcov-report/threads/index.html +34 -34
  149. package/coverage/lcov-report/threads/index.js.html +35 -17
  150. package/coverage/lcov-report/threads/query.js.html +20 -356
  151. package/coverage/lcov-report/threads/utils.js.html +19 -22
  152. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  153. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  154. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  155. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  156. package/coverage/lcov-report/utilities/global.js.html +15 -15
  157. package/coverage/lcov-report/utilities/index.html +1 -1
  158. package/coverage/lcov-report/utilities/index.js.html +26 -26
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  160. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  161. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  162. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +18 -18
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +4 -4
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  167. package/coverage/lcov-report/utilities/security.js.html +8 -8
  168. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  169. package/coverage/lcov-report/utilities/usageQuota/index.html +13 -13
  170. package/coverage/lcov-report/utilities/usageQuota/index.js.html +8 -8
  171. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +38 -26
  172. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  173. package/coverage/lcov-report/utilities/users.js.html +5 -5
  174. package/coverage/lcov-report/utilities/workerRequests.js.html +28 -28
  175. package/coverage/lcov.info +1570 -1660
  176. package/dist/api/controllers/application.js +4 -1
  177. package/dist/api/controllers/deploy/index.js +5 -1
  178. package/dist/api/controllers/dev.js +9 -5
  179. package/dist/api/controllers/row/internal.js +2 -1
  180. package/dist/api/controllers/webhook.js +2 -2
  181. package/dist/api/routes/tests/utilities/TestFunctions.js +1 -4
  182. package/dist/app.js +5 -2
  183. package/dist/automations/utils.js +6 -5
  184. package/dist/db/inMemoryView.js +33 -31
  185. package/dist/db/index.js +13 -2
  186. package/dist/integrations/couchdb.js +19 -25
  187. package/dist/integrations/queries/sql.js +108 -0
  188. package/dist/middleware/builder.js +10 -9
  189. package/dist/migrations/index.js +1 -5
  190. package/dist/package.json +5 -5
  191. package/dist/tests/utilities/TestConfiguration.js +66 -59
  192. package/dist/threads/index.js +6 -1
  193. package/dist/threads/query.js +4 -103
  194. package/dist/threads/utils.js +2 -3
  195. package/dist/tsconfig.tsbuildinfo +1 -1
  196. package/dist/utilities/fileSystem/index.js +27 -26
  197. package/dist/utilities/usageQuota/rows.js +16 -16
  198. package/package.json +6 -6
  199. package/scripts/exportAppTemplate.js +10 -8
  200. package/scripts/integrations/mysql/init.sql +1 -0
  201. package/src/api/controllers/application.js +3 -1
  202. package/src/api/controllers/deploy/index.js +4 -4
  203. package/src/api/controllers/dev.js +9 -6
  204. package/src/api/controllers/query/import/tests/index.spec.js +7 -11
  205. package/src/api/controllers/row/internal.js +2 -1
  206. package/src/api/controllers/webhook.js +2 -2
  207. package/src/api/routes/tests/row.spec.js +15 -11
  208. package/src/api/routes/tests/table.spec.js +3 -2
  209. package/src/api/routes/tests/utilities/TestFunctions.js +1 -5
  210. package/src/app.ts +2 -2
  211. package/src/automations/tests/deleteRow.spec.js +1 -1
  212. package/src/automations/utils.js +6 -5
  213. package/src/db/inMemoryView.js +37 -36
  214. package/src/db/index.js +15 -2
  215. package/src/db/tests/linkTests.spec.js +8 -7
  216. package/src/integrations/couchdb.ts +28 -24
  217. package/src/integrations/queries/sql.ts +125 -0
  218. package/src/integrations/tests/airtable.spec.js +3 -1
  219. package/src/integrations/tests/couchdb.spec.js +4 -1
  220. package/src/middleware/builder.js +10 -9
  221. package/src/middleware/tests/authorized.spec.js +0 -1
  222. package/src/middleware/tests/usageQuota.spec.js +6 -20
  223. package/src/migrations/functions/tests/appUrls.spec.js +8 -11
  224. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +13 -10
  225. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +25 -21
  226. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +26 -24
  227. package/src/migrations/index.ts +1 -2
  228. package/src/module.d.ts +8 -0
  229. package/src/tests/utilities/TestConfiguration.js +62 -55
  230. package/src/threads/index.js +7 -1
  231. package/src/threads/query.js +7 -119
  232. package/src/threads/utils.js +2 -3
  233. package/src/utilities/fileSystem/index.js +30 -30
  234. package/src/utilities/usageQuota/rows.js +22 -18
  235. package/coverage/lcov-report/db/client.js.html +0 -173
  236. package/dist/db/client.js +0 -25
  237. package/scripts/replicateApp.js +0 -50
  238. package/src/db/client.js +0 -31
@@ -1,6 +1,4 @@
1
- const core = require("@budibase/backend-core")
2
- const CouchDB = require("../../db")
3
- core.init(CouchDB)
1
+ require("../../db").init()
4
2
  const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
5
3
  const env = require("../../environment")
6
4
  const {
@@ -20,7 +18,7 @@ const supertest = require("supertest")
20
18
  const { cleanup } = require("../../utilities/fileSystem")
21
19
  const { Cookies, Headers } = require("@budibase/backend-core/constants")
22
20
  const { jwt } = require("@budibase/backend-core/auth")
23
- const { getGlobalDB } = require("@budibase/backend-core/tenancy")
21
+ const { doInTenant, doWithGlobalDB } = require("@budibase/backend-core/tenancy")
24
22
  const { createASession } = require("@budibase/backend-core/sessions")
25
23
  const { user: userCache } = require("@budibase/backend-core/cache")
26
24
  const newid = require("../../db/newid")
@@ -57,8 +55,20 @@ class TestConfiguration {
57
55
  return this.appId
58
56
  }
59
57
 
60
- getCouch() {
61
- return CouchDB
58
+ async doInContext(appId, task) {
59
+ if (!appId) {
60
+ appId = this.appId
61
+ }
62
+ return doInTenant(TENANT_ID, () => {
63
+ // check if already in a context
64
+ if (context.getAppId() == null && appId !== null) {
65
+ return context.doInAppContext(appId, async () => {
66
+ return task()
67
+ })
68
+ } else {
69
+ return task()
70
+ }
71
+ })
62
72
  }
63
73
 
64
74
  async _req(config, params, controlFunc) {
@@ -72,35 +82,28 @@ class TestConfiguration {
72
82
  request.request = {
73
83
  body: config,
74
84
  }
75
- async function run() {
85
+ return this.doInContext(this.appId, async () => {
76
86
  if (params) {
77
87
  request.params = params
78
88
  }
79
89
  await controlFunc(request)
80
90
  return request.body
81
- }
82
- // check if already in a context
83
- if (context.getAppId() == null && this.appId !== null) {
84
- return context.doInAppContext(this.appId, async () => {
85
- return run()
86
- })
87
- } else {
88
- return run()
89
- }
91
+ })
90
92
  }
91
93
 
92
94
  async generateApiKey(userId = GLOBAL_USER_ID) {
93
- const db = getGlobalDB(TENANT_ID)
94
- const id = generateDevInfoID(userId)
95
- let devInfo
96
- try {
97
- devInfo = await db.get(id)
98
- } catch (err) {
99
- devInfo = { _id: id, userId }
100
- }
101
- devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`)
102
- await db.put(devInfo)
103
- return devInfo.apiKey
95
+ return doWithGlobalDB(TENANT_ID, async db => {
96
+ const id = generateDevInfoID(userId)
97
+ let devInfo
98
+ try {
99
+ devInfo = await db.get(id)
100
+ } catch (err) {
101
+ devInfo = { _id: id, userId }
102
+ }
103
+ devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`)
104
+ await db.put(devInfo)
105
+ return devInfo.apiKey
106
+ })
104
107
  }
105
108
 
106
109
  async globalUser({
@@ -109,34 +112,35 @@ class TestConfiguration {
109
112
  email = EMAIL,
110
113
  roles,
111
114
  } = {}) {
112
- const db = getGlobalDB(TENANT_ID)
113
- let existing
114
- try {
115
- existing = await db.get(id)
116
- } catch (err) {
117
- existing = { email }
118
- }
119
- const user = {
120
- _id: id,
121
- ...existing,
122
- roles: roles || {},
123
- tenantId: TENANT_ID,
124
- }
125
- await createASession(id, {
126
- sessionId: "sessionid",
127
- tenantId: TENANT_ID,
128
- csrfToken: CSRF_TOKEN,
115
+ return doWithGlobalDB(TENANT_ID, async db => {
116
+ let existing
117
+ try {
118
+ existing = await db.get(id)
119
+ } catch (err) {
120
+ existing = { email }
121
+ }
122
+ const user = {
123
+ _id: id,
124
+ ...existing,
125
+ roles: roles || {},
126
+ tenantId: TENANT_ID,
127
+ }
128
+ await createASession(id, {
129
+ sessionId: "sessionid",
130
+ tenantId: TENANT_ID,
131
+ csrfToken: CSRF_TOKEN,
132
+ })
133
+ if (builder) {
134
+ user.builder = { global: true }
135
+ } else {
136
+ user.builder = { global: false }
137
+ }
138
+ const resp = await db.put(user)
139
+ return {
140
+ _rev: resp._rev,
141
+ ...user,
142
+ }
129
143
  })
130
- if (builder) {
131
- user.builder = { global: true }
132
- } else {
133
- user.builder = { global: false }
134
- }
135
- const resp = await db.put(user)
136
- return {
137
- _rev: resp._rev,
138
- ...user,
139
- }
140
144
  }
141
145
 
142
146
  // use a new id as the name to avoid name collisions
@@ -205,9 +209,12 @@ class TestConfiguration {
205
209
 
206
210
  async createApp(appName) {
207
211
  // create dev app
212
+ // clear any old app
213
+ this.appId = null
214
+ await context.updateAppId(null)
208
215
  this.app = await this._req({ name: appName }, null, controllers.app.create)
209
216
  this.appId = this.app.appId
210
- context.updateAppId(this.appId)
217
+ await context.updateAppId(this.appId)
211
218
 
212
219
  // create production app
213
220
  this.prodApp = await this.deploy()
@@ -36,6 +36,7 @@ class Thread {
36
36
  maxConcurrentWorkers: this.count,
37
37
  }
38
38
  if (opts.timeoutMs) {
39
+ this.timeoutMs = opts.timeoutMs
39
40
  workerOpts.maxCallTime = opts.timeoutMs
40
41
  }
41
42
  this.workers = workerFarm(workerOpts, typeToFile(type))
@@ -43,6 +44,7 @@ class Thread {
43
44
  }
44
45
 
45
46
  run(data) {
47
+ const timeoutMs = this.timeoutMs
46
48
  return new Promise((resolve, reject) => {
47
49
  let fncToCall
48
50
  // if in test then don't use threading
@@ -52,7 +54,11 @@ class Thread {
52
54
  fncToCall = this.workers
53
55
  }
54
56
  fncToCall(data, (err, response) => {
55
- if (err) {
57
+ if (err && err.type === "TimeoutError") {
58
+ reject(
59
+ new Error(`Query response time exceeded ${timeoutMs}ms timeout.`)
60
+ )
61
+ } else if (err) {
56
62
  reject(err)
57
63
  } else {
58
64
  resolve(response)
@@ -2,14 +2,13 @@ const threadUtils = require("./utils")
2
2
  threadUtils.threadSetup()
3
3
  const ScriptRunner = require("../utilities/scriptRunner")
4
4
  const { integrations } = require("../integrations")
5
- const {
6
- processStringSync,
7
- findHBSBlocks,
8
- } = require("@budibase/string-templates")
5
+ const { processStringSync } = require("@budibase/string-templates")
9
6
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
10
7
  const { isSQL } = require("../integrations/utils")
11
-
12
- const CONST_CHAR_REGEX = new RegExp("'[^']*'", "g")
8
+ const {
9
+ enrichQueryFields,
10
+ interpolateSQL,
11
+ } = require("../integrations/queries/sql")
13
12
 
14
13
  class QueryRunner {
15
14
  constructor(input, flags = { noRecursiveQuery: false }) {
@@ -29,76 +28,6 @@ class QueryRunner {
29
28
  this.hasRerun = false
30
29
  }
31
30
 
32
- interpolateSQL(fields, parameters, integration) {
33
- let sql = fields.sql
34
- if (!sql) {
35
- return fields
36
- }
37
- const bindings = findHBSBlocks(sql)
38
- let variables = [],
39
- arrays = []
40
- for (let binding of bindings) {
41
- // look for array/list operations in the SQL statement, which will need handled later
42
- const listRegexMatch = sql.match(
43
- new RegExp(`(in|IN|In|iN)( )+[(]?${binding}[)]?`)
44
- )
45
- // check if the variable was used as part of a string concat e.g. 'Hello {{binding}}'
46
- // start by finding all the instances of const character strings
47
- const charConstMatch = sql.match(CONST_CHAR_REGEX) || []
48
- // now look within them to see if a binding is used
49
- const charConstBindingMatch = charConstMatch.find(string =>
50
- string.match(new RegExp(`'[^']*${binding}[^']*'`))
51
- )
52
- if (charConstBindingMatch) {
53
- let [part1, part2] = charConstBindingMatch.split(binding)
54
- part1 = `'${part1.substring(1)}'`
55
- part2 = `'${part2.substring(0, part2.length - 1)}'`
56
- sql = sql.replace(
57
- charConstBindingMatch,
58
- integration.getStringConcat([
59
- part1,
60
- integration.getBindingIdentifier(),
61
- part2,
62
- ])
63
- )
64
- }
65
- // generate SQL parameterised array
66
- else if (listRegexMatch) {
67
- arrays.push(binding)
68
- // determine the length of the array
69
- const value = this.enrichQueryFields([binding], parameters)[0].split(
70
- ","
71
- )
72
- // build a string like ($1, $2, $3)
73
- let replacement = `${Array.apply(null, Array(value.length))
74
- .map(() => integration.getBindingIdentifier())
75
- .join(",")}`
76
- // check if parentheses are needed
77
- if (!listRegexMatch[0].includes(`(${binding})`)) {
78
- replacement = `(${replacement})`
79
- }
80
- sql = sql.replace(binding, replacement)
81
- } else {
82
- sql = sql.replace(binding, integration.getBindingIdentifier())
83
- }
84
- variables.push(binding)
85
- }
86
- // replicate the knex structure
87
- fields.sql = sql
88
- fields.bindings = this.enrichQueryFields(variables, parameters)
89
- // check for arrays in the data
90
- let updated = []
91
- for (let i = 0; i < variables.length; i++) {
92
- if (arrays.includes(variables[i])) {
93
- updated = updated.concat(fields.bindings[i].split(","))
94
- } else {
95
- updated.push(fields.bindings[i])
96
- }
97
- }
98
- fields.bindings = updated
99
- return fields
100
- }
101
-
102
31
  async execute() {
103
32
  let { datasource, fields, queryVerb, transformer } = this
104
33
  const Integration = integrations[datasource.source]
@@ -112,9 +41,9 @@ class QueryRunner {
112
41
  let query
113
42
  // handle SQL injections by interpolating the variables
114
43
  if (isSQL(datasource)) {
115
- query = this.interpolateSQL(fields, parameters, integration)
44
+ query = interpolateSQL(fields, parameters, integration)
116
45
  } else {
117
- query = this.enrichQueryFields(fields, parameters)
46
+ query = enrichQueryFields(fields, parameters)
118
47
  }
119
48
 
120
49
  // Add pagination values for REST queries
@@ -259,47 +188,6 @@ class QueryRunner {
259
188
  }
260
189
  return parameters
261
190
  }
262
-
263
- enrichQueryFields(fields, parameters = {}) {
264
- const enrichedQuery = Array.isArray(fields) ? [] : {}
265
-
266
- // enrich the fields with dynamic parameters
267
- for (let key of Object.keys(fields)) {
268
- if (fields[key] == null) {
269
- continue
270
- }
271
- if (typeof fields[key] === "object") {
272
- // enrich nested fields object
273
- enrichedQuery[key] = this.enrichQueryFields(fields[key], parameters)
274
- } else if (typeof fields[key] === "string") {
275
- // enrich string value as normal
276
- enrichedQuery[key] = processStringSync(fields[key], parameters, {
277
- noEscaping: true,
278
- noHelpers: true,
279
- escapeNewlines: true,
280
- })
281
- } else {
282
- enrichedQuery[key] = fields[key]
283
- }
284
- }
285
- if (
286
- enrichedQuery.json ||
287
- enrichedQuery.customData ||
288
- enrichedQuery.requestBody
289
- ) {
290
- try {
291
- enrichedQuery.json = JSON.parse(
292
- enrichedQuery.json ||
293
- enrichedQuery.customData ||
294
- enrichedQuery.requestBody
295
- )
296
- } catch (err) {
297
- // no json found, ignore
298
- }
299
- delete enrichedQuery.customData
300
- }
301
- return enrichedQuery
302
- }
303
191
  }
304
192
 
305
193
  module.exports = (input, callback) => {
@@ -1,6 +1,5 @@
1
1
  const env = require("../environment")
2
- const CouchDB = require("../db")
3
- const { init } = require("@budibase/backend-core")
2
+ const db = require("../db")
4
3
  const redis = require("@budibase/backend-core/redis")
5
4
  const { SEPARATOR } = require("@budibase/backend-core/db")
6
5
 
@@ -25,7 +24,7 @@ exports.threadSetup = () => {
25
24
  }
26
25
  // when thread starts, make sure it is recorded
27
26
  env.setInThread()
28
- init(CouchDB)
27
+ db.init()
29
28
  }
30
29
 
31
30
  function makeVariableKey(queryId, variable) {
@@ -2,7 +2,7 @@ const { budibaseTempDir } = require("../budibaseDir")
2
2
  const fs = require("fs")
3
3
  const { join } = require("path")
4
4
  const uuid = require("uuid/v4")
5
- const CouchDB = require("../../db")
5
+ const { doWithDB } = require("@budibase/backend-core/db")
6
6
  const { ObjectStoreBuckets } = require("../../constants")
7
7
  const {
8
8
  upload,
@@ -151,41 +151,41 @@ exports.streamBackup = async appId => {
151
151
  * @return {*} either a readable stream or a string
152
152
  */
153
153
  exports.exportDB = async (dbName, { stream, filter, exportName } = {}) => {
154
- const instanceDb = new CouchDB(dbName)
154
+ return doWithDB(dbName, async db => {
155
+ // Stream the dump if required
156
+ if (stream) {
157
+ const memStream = new MemoryStream()
158
+ db.dump(memStream, { filter })
159
+ return memStream
160
+ }
155
161
 
156
- // Stream the dump if required
157
- if (stream) {
158
- const memStream = new MemoryStream()
159
- instanceDb.dump(memStream, { filter })
160
- return memStream
161
- }
162
+ // Write the dump to file if required
163
+ if (exportName) {
164
+ const path = join(budibaseTempDir(), exportName)
165
+ const writeStream = fs.createWriteStream(path)
166
+ await db.dump(writeStream, { filter })
162
167
 
163
- // Write the dump to file if required
164
- if (exportName) {
165
- const path = join(budibaseTempDir(), exportName)
166
- const writeStream = fs.createWriteStream(path)
167
- await instanceDb.dump(writeStream, { filter })
168
+ // Upload the dump to the object store if self hosted
169
+ if (env.SELF_HOSTED) {
170
+ await streamUpload(
171
+ ObjectStoreBuckets.BACKUPS,
172
+ join(dbName, exportName),
173
+ fs.createReadStream(path)
174
+ )
175
+ }
168
176
 
169
- // Upload the dump to the object store if self hosted
170
- if (env.SELF_HOSTED) {
171
- await streamUpload(
172
- ObjectStoreBuckets.BACKUPS,
173
- join(dbName, exportName),
174
- fs.createReadStream(path)
175
- )
177
+ return fs.createReadStream(path)
176
178
  }
177
179
 
178
- return fs.createReadStream(path)
179
- }
180
-
181
- // Stringify the dump in memory if required
182
- const memStream = new MemoryStream()
183
- let appString = ""
184
- memStream.on("data", chunk => {
185
- appString += chunk.toString()
180
+ // Stringify the dump in memory if required
181
+ const memStream = new MemoryStream()
182
+ let appString = ""
183
+ memStream.on("data", chunk => {
184
+ appString += chunk.toString()
185
+ })
186
+ await db.dump(memStream, { filter })
187
+ return appString
186
188
  })
187
- await instanceDb.dump(memStream, { filter })
188
- return appString
189
189
  }
190
190
 
191
191
  /**
@@ -1,6 +1,9 @@
1
1
  const { getRowParams, USER_METDATA_PREFIX } = require("../../db/utils")
2
- const CouchDB = require("../../db")
3
- const { isDevAppID, getDevelopmentAppID } = require("@budibase/backend-core/db")
2
+ const {
3
+ isDevAppID,
4
+ getDevelopmentAppID,
5
+ doWithDB,
6
+ } = require("@budibase/backend-core/db")
4
7
 
5
8
  const ROW_EXCLUSIONS = [USER_METDATA_PREFIX]
6
9
 
@@ -24,22 +27,23 @@ const getAppPairs = appIds => {
24
27
 
25
28
  const getAppRows = async appId => {
26
29
  // need to specify the app ID, as this is used for different apps in one call
27
- const appDb = new CouchDB(appId)
28
- const response = await appDb.allDocs(
29
- getRowParams(null, null, {
30
- include_docs: false,
31
- })
32
- )
33
- return response.rows
34
- .map(r => r.id)
35
- .filter(id => {
36
- for (let exclusion of ROW_EXCLUSIONS) {
37
- if (id.startsWith(exclusion)) {
38
- return false
30
+ return doWithDB(appId, async db => {
31
+ const response = await db.allDocs(
32
+ getRowParams(null, null, {
33
+ include_docs: false,
34
+ })
35
+ )
36
+ return response.rows
37
+ .map(r => r.id)
38
+ .filter(id => {
39
+ for (let exclusion of ROW_EXCLUSIONS) {
40
+ if (id.startsWith(exclusion)) {
41
+ return false
42
+ }
39
43
  }
40
- }
41
- return true
42
- })
44
+ return true
45
+ })
46
+ })
43
47
  }
44
48
 
45
49
  /**
@@ -58,7 +62,7 @@ exports.getUniqueRows = async appIds => {
58
62
  continue
59
63
  }
60
64
  try {
61
- appRows.push(await getAppRows(appId))
65
+ appRows = appRows.concat(await getAppRows(appId))
62
66
  } catch (e) {
63
67
  console.error(e)
64
68
  // don't error out if we can't count the app rows, just continue
@@ -1,173 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for db/client.js</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../prettify.css" />
9
- <link rel="stylesheet" href="../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../index.html">All files</a> / <a href="index.html">db</a> client.js</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">100% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>17/17</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">75% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>3/4</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">100% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>0/0</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">100% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>17/17</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- </div>
58
- <div class='status-line high'></div>
59
- <pre><table class="coverage">
60
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
61
- <a name='L2'></a><a href='#L2'>2</a>
62
- <a name='L3'></a><a href='#L3'>3</a>
63
- <a name='L4'></a><a href='#L4'>4</a>
64
- <a name='L5'></a><a href='#L5'>5</a>
65
- <a name='L6'></a><a href='#L6'>6</a>
66
- <a name='L7'></a><a href='#L7'>7</a>
67
- <a name='L8'></a><a href='#L8'>8</a>
68
- <a name='L9'></a><a href='#L9'>9</a>
69
- <a name='L10'></a><a href='#L10'>10</a>
70
- <a name='L11'></a><a href='#L11'>11</a>
71
- <a name='L12'></a><a href='#L12'>12</a>
72
- <a name='L13'></a><a href='#L13'>13</a>
73
- <a name='L14'></a><a href='#L14'>14</a>
74
- <a name='L15'></a><a href='#L15'>15</a>
75
- <a name='L16'></a><a href='#L16'>16</a>
76
- <a name='L17'></a><a href='#L17'>17</a>
77
- <a name='L18'></a><a href='#L18'>18</a>
78
- <a name='L19'></a><a href='#L19'>19</a>
79
- <a name='L20'></a><a href='#L20'>20</a>
80
- <a name='L21'></a><a href='#L21'>21</a>
81
- <a name='L22'></a><a href='#L22'>22</a>
82
- <a name='L23'></a><a href='#L23'>23</a>
83
- <a name='L24'></a><a href='#L24'>24</a>
84
- <a name='L25'></a><a href='#L25'>25</a>
85
- <a name='L26'></a><a href='#L26'>26</a>
86
- <a name='L27'></a><a href='#L27'>27</a>
87
- <a name='L28'></a><a href='#L28'>28</a>
88
- <a name='L29'></a><a href='#L29'>29</a>
89
- <a name='L30'></a><a href='#L30'>30</a>
90
- <a name='L31'></a><a href='#L31'>31</a>
91
- <a name='L32'></a><a href='#L32'>32</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">43x</span>
92
- <span class="cline-any cline-yes">43x</span>
93
- <span class="cline-any cline-yes">43x</span>
94
- <span class="cline-any cline-yes">43x</span>
95
- <span class="cline-any cline-yes">43x</span>
96
- <span class="cline-any cline-yes">43x</span>
97
- <span class="cline-any cline-neutral">&nbsp;</span>
98
- <span class="cline-any cline-yes">43x</span>
99
- <span class="cline-any cline-neutral">&nbsp;</span>
100
- <span class="cline-any cline-yes">43x</span>
101
- <span class="cline-any cline-yes">43x</span>
102
- <span class="cline-any cline-yes">43x</span>
103
- <span class="cline-any cline-neutral">&nbsp;</span>
104
- <span class="cline-any cline-yes">43x</span>
105
- <span class="cline-any cline-neutral">&nbsp;</span>
106
- <span class="cline-any cline-neutral">&nbsp;</span>
107
- <span class="cline-any cline-neutral">&nbsp;</span>
108
- <span class="cline-any cline-yes">43x</span>
109
- <span class="cline-any cline-yes">43x</span>
110
- <span class="cline-any cline-yes">43x</span>
111
- <span class="cline-any cline-neutral">&nbsp;</span>
112
- <span class="cline-any cline-neutral">&nbsp;</span>
113
- <span class="cline-any cline-neutral">&nbsp;</span>
114
- <span class="cline-any cline-neutral">&nbsp;</span>
115
- <span class="cline-any cline-neutral">&nbsp;</span>
116
- <span class="cline-any cline-yes">43x</span>
117
- <span class="cline-any cline-neutral">&nbsp;</span>
118
- <span class="cline-any cline-neutral">&nbsp;</span>
119
- <span class="cline-any cline-yes">43x</span>
120
- <span class="cline-any cline-neutral">&nbsp;</span>
121
- <span class="cline-any cline-yes">43x</span>
122
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const PouchDB = require("pouchdb")
123
- const { getCouchUrl } = require("@budibase/backend-core/db")
124
- const replicationStream = require("pouchdb-replication-stream")
125
- const allDbs = require("pouchdb-all-dbs")
126
- const find = require("pouchdb-find")
127
- const env = require("../environment")
128
- &nbsp;
129
- const COUCH_DB_URL = getCouchUrl() || "http://localhost:4005"
130
- &nbsp;
131
- PouchDB.plugin(replicationStream.plugin)
132
- PouchDB.plugin(find)
133
- PouchDB.adapter("writableStream", replicationStream.adapters.writableStream)
134
- &nbsp;
135
- let POUCH_DB_DEFAULTS = {
136
- prefix: COUCH_DB_URL,
137
- }
138
- &nbsp;
139
- if (env.isTest()) {
140
- PouchDB.plugin(require("pouchdb-adapter-memory"))
141
- POUCH_DB_DEFAULTS = {
142
- prefix: undefined,
143
- adapter: "memory",
144
- }
145
- }
146
- &nbsp;
147
- const Pouch = PouchDB.defaults(POUCH_DB_DEFAULTS)
148
- &nbsp;
149
- // have to still have pouch alldbs for testing
150
- allDbs(Pouch)
151
- &nbsp;
152
- module.exports = Pouch
153
- &nbsp;</pre></td></tr></table></pre>
154
-
155
- <div class='push'></div><!-- for sticky footer -->
156
- </div><!-- /wrapper -->
157
- <div class='footer quiet pad2 space-top1 center small'>
158
- Code coverage generated by
159
- <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
160
- at Wed Apr 13 2022 12:20:55 GMT+0000 (Coordinated Universal Time)
161
- </div>
162
- </div>
163
- <script src="../prettify.js"></script>
164
- <script>
165
- window.onload = function () {
166
- prettyPrint();
167
- };
168
- </script>
169
- <script src="../sorter.js"></script>
170
- <script src="../block-navigation.js"></script>
171
- </body>
172
- </html>
173
-