@budibase/server 1.0.49-alpha.0 → 1.0.49-alpha.12

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 (357) hide show
  1. package/__mocks__/arangojs.ts +1 -1
  2. package/__mocks__/aws-sdk.ts +4 -4
  3. package/__mocks__/mongodb.ts +4 -5
  4. package/__mocks__/mssql.ts +3 -3
  5. package/__mocks__/node-fetch.ts +2 -1
  6. package/__mocks__/pg.ts +3 -5
  7. package/builder/assets/{index.8184eed9.js → index.0bdf1cad.js} +195 -194
  8. package/builder/assets/{index.dd9e386f.css → index.83c0944f.css} +1 -1
  9. package/builder/assets/{vendor.3bd2f661.js → vendor.d526bfe8.js} +1 -1
  10. package/builder/index.html +3 -3
  11. package/coverage/clover.xml +2927 -2819
  12. package/coverage/coverage-final.json +104 -103
  13. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/application.js.html +157 -136
  16. package/coverage/lcov-report/api/controllers/auth.js.html +11 -14
  17. package/coverage/lcov-report/api/controllers/automation.js.html +39 -69
  18. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/cloud.js.html +8 -11
  20. package/coverage/lcov-report/api/controllers/component.js.html +10 -13
  21. package/coverage/lcov-report/api/controllers/datasource.js.html +31 -37
  22. package/coverage/lcov-report/api/controllers/dev.js.html +6 -6
  23. package/coverage/lcov-report/api/controllers/index.html +69 -54
  24. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/layout.js.html +9 -9
  26. package/coverage/lcov-report/api/controllers/metadata.js.html +6 -21
  27. package/coverage/lcov-report/{migrations/usageQuotas/syncApps.js.html → api/controllers/migrations.js.html} +30 -45
  28. package/coverage/lcov-report/api/controllers/permission.js.html +19 -19
  29. package/coverage/lcov-report/api/controllers/query/index.html +10 -10
  30. package/coverage/lcov-report/api/controllers/query/index.js.html +38 -35
  31. package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -6
  32. package/coverage/lcov-report/api/controllers/role.js.html +16 -16
  33. package/coverage/lcov-report/api/controllers/routing.js.html +7 -10
  34. package/coverage/lcov-report/api/controllers/row/external.js.html +48 -141
  35. package/coverage/lcov-report/api/controllers/row/index.html +52 -37
  36. package/coverage/lcov-report/api/controllers/row/index.js.html +13 -13
  37. package/coverage/lcov-report/api/controllers/row/internal.js.html +108 -216
  38. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +52 -34
  39. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +548 -0
  40. package/coverage/lcov-report/api/controllers/row/utils.js.html +27 -24
  41. package/coverage/lcov-report/api/controllers/screen.js.html +15 -21
  42. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  43. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +599 -0
  44. package/coverage/lcov-report/api/controllers/table/external.js.html +25 -34
  45. package/coverage/lcov-report/api/controllers/table/index.html +57 -42
  46. package/coverage/lcov-report/api/controllers/table/index.js.html +28 -70
  47. package/coverage/lcov-report/api/controllers/table/internal.js.html +56 -47
  48. package/coverage/lcov-report/api/controllers/table/utils.js.html +169 -85
  49. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/user.js.html +43 -52
  51. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  52. package/coverage/lcov-report/api/controllers/view/index.html +16 -16
  53. package/coverage/lcov-report/api/controllers/view/index.js.html +27 -33
  54. package/coverage/lcov-report/api/controllers/view/utils.js.html +35 -20
  55. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  56. package/coverage/lcov-report/api/controllers/webhook.js.html +34 -28
  57. package/coverage/lcov-report/api/index.html +1 -1
  58. package/coverage/lcov-report/api/index.js.html +3 -3
  59. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/index.html +22 -7
  71. package/coverage/lcov-report/api/routes/index.js.html +10 -4
  72. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  75. package/coverage/lcov-report/{migrations/usageQuotas/index.js.html → api/routes/migrations.js.html} +25 -55
  76. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  84. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  85. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  86. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  87. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  88. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/actions.js.html +24 -24
  90. package/coverage/lcov-report/automations/automationUtils.js.html +7 -10
  91. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  92. package/coverage/lcov-report/automations/index.html +18 -18
  93. package/coverage/lcov-report/automations/index.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  95. package/coverage/lcov-report/automations/steps/createRow.js.html +7 -10
  96. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  97. package/coverage/lcov-report/automations/steps/deleteRow.js.html +7 -7
  98. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  99. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  100. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  101. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  102. package/coverage/lcov-report/automations/steps/index.html +1 -1
  103. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  104. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  105. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  106. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  107. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  108. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  109. package/coverage/lcov-report/automations/steps/updateRow.js.html +7 -7
  110. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  111. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  112. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  115. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  116. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  118. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  119. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  120. package/coverage/lcov-report/automations/triggers.js.html +61 -55
  121. package/coverage/lcov-report/automations/utils.js.html +54 -42
  122. package/coverage/lcov-report/constants/index.html +5 -5
  123. package/coverage/lcov-report/constants/index.js.html +42 -27
  124. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  125. package/coverage/lcov-report/constants/screens.js.html +4 -4
  126. package/coverage/lcov-report/db/client.js.html +18 -18
  127. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  128. package/coverage/lcov-report/db/index.html +1 -1
  129. package/coverage/lcov-report/db/index.js.html +3 -3
  130. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +15 -27
  131. package/coverage/lcov-report/db/linkedRows/index.html +27 -27
  132. package/coverage/lcov-report/db/linkedRows/index.js.html +40 -85
  133. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +40 -40
  134. package/coverage/lcov-report/db/newid.js.html +4 -4
  135. package/coverage/lcov-report/db/utils.js.html +75 -75
  136. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  137. package/coverage/lcov-report/events/index.html +1 -1
  138. package/coverage/lcov-report/events/index.js.html +5 -5
  139. package/coverage/lcov-report/events/utils.js.html +3 -3
  140. package/coverage/lcov-report/index.html +107 -122
  141. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  142. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  143. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  144. package/coverage/lcov-report/middleware/authorized.js.html +21 -15
  145. package/coverage/lcov-report/middleware/builder.js.html +3 -3
  146. package/coverage/lcov-report/middleware/currentapp.js.html +72 -60
  147. package/coverage/lcov-report/middleware/index.html +28 -28
  148. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  149. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  150. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  151. package/coverage/lcov-report/middleware/usageQuota.js.html +29 -35
  152. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  153. package/coverage/lcov-report/threads/automation.js.html +30 -24
  154. package/coverage/lcov-report/threads/index.html +25 -25
  155. package/coverage/lcov-report/threads/index.js.html +10 -10
  156. package/coverage/lcov-report/threads/query.js.html +26 -47
  157. package/coverage/lcov-report/threads/utils.js.html +14 -14
  158. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  159. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  160. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  161. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  162. package/coverage/lcov-report/utilities/global.js.html +57 -48
  163. package/coverage/lcov-report/utilities/index.html +27 -27
  164. package/coverage/lcov-report/utilities/index.js.html +42 -72
  165. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  166. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  167. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  168. package/coverage/lcov-report/utilities/routing/index.js.html +7 -7
  169. package/coverage/lcov-report/utilities/rowProcessor/index.html +27 -27
  170. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +65 -71
  171. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
  172. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  173. package/coverage/lcov-report/utilities/security.js.html +8 -8
  174. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  175. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  176. package/coverage/lcov-report/utilities/usageQuota/index.js.html +13 -10
  177. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +5 -2
  178. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  179. package/coverage/lcov-report/utilities/users.js.html +9 -9
  180. package/coverage/lcov-report/utilities/workerRequests.js.html +16 -16
  181. package/coverage/lcov.info +4620 -4358
  182. package/dist/api/controllers/application.js +49 -48
  183. package/dist/api/controllers/auth.js +4 -5
  184. package/dist/api/controllers/automation.js +14 -19
  185. package/dist/api/controllers/cloud.js +2 -3
  186. package/dist/api/controllers/component.js +3 -4
  187. package/dist/api/controllers/datasource.js +9 -10
  188. package/dist/api/controllers/deploy/Deployment.js +3 -6
  189. package/dist/api/controllers/deploy/index.js +12 -13
  190. package/dist/api/controllers/dev.js +5 -5
  191. package/dist/api/controllers/layout.js +3 -3
  192. package/dist/api/controllers/metadata.js +4 -4
  193. package/dist/api/controllers/migrations.js +21 -0
  194. package/dist/api/controllers/permission.js +4 -4
  195. package/dist/api/controllers/query/import/index.js +4 -6
  196. package/dist/api/controllers/query/index.js +11 -10
  197. package/dist/api/controllers/role.js +5 -5
  198. package/dist/api/controllers/routing.js +5 -6
  199. package/dist/api/controllers/row/ExternalRequest.js +90 -67
  200. package/dist/api/controllers/row/external.js +14 -22
  201. package/dist/api/controllers/row/internal.js +55 -93
  202. package/dist/api/controllers/row/internalSearch.js +23 -17
  203. package/dist/api/controllers/row/staticFormula.js +147 -0
  204. package/dist/api/controllers/row/utils.js +7 -6
  205. package/dist/api/controllers/screen.js +5 -7
  206. package/dist/api/controllers/static/index.js +4 -4
  207. package/dist/api/controllers/table/bulkFormula.js +159 -0
  208. package/dist/api/controllers/table/external.js +7 -10
  209. package/dist/api/controllers/table/index.js +7 -10
  210. package/dist/api/controllers/table/internal.js +20 -16
  211. package/dist/api/controllers/table/utils.js +54 -34
  212. package/dist/api/controllers/user.js +16 -20
  213. package/dist/api/controllers/view/index.js +8 -10
  214. package/dist/api/controllers/view/utils.js +9 -4
  215. package/dist/api/controllers/webhook.js +10 -8
  216. package/dist/api/routes/index.js +2 -0
  217. package/dist/api/routes/migrations.js +9 -0
  218. package/dist/api/routes/tests/utilities/TestFunctions.js +37 -17
  219. package/dist/app.js +35 -5
  220. package/dist/automations/automationUtils.js +2 -3
  221. package/dist/automations/steps/createRow.js +1 -1
  222. package/dist/automations/steps/updateRow.js +1 -1
  223. package/dist/automations/triggers.js +27 -25
  224. package/dist/automations/utils.js +10 -5
  225. package/dist/constants/index.js +4 -0
  226. package/dist/db/linkedRows/LinkController.js +3 -7
  227. package/dist/db/linkedRows/index.js +16 -27
  228. package/dist/db/linkedRows/linkUtils.js +6 -6
  229. package/dist/db/views/staticViews.js +9 -10
  230. package/dist/environment.js +3 -1
  231. package/dist/integrations/base/sql.js +43 -8
  232. package/dist/integrations/utils.js +3 -0
  233. package/dist/middleware/authorized.js +5 -3
  234. package/dist/middleware/builder.js +2 -2
  235. package/dist/middleware/currentapp.js +41 -37
  236. package/dist/middleware/usageQuota.js +2 -4
  237. package/dist/migrations/functions/appUrls.js +46 -0
  238. package/dist/migrations/functions/quotas1.js +50 -0
  239. package/dist/migrations/{usageQuotas → functions/usageQuotas}/index.js +6 -10
  240. package/dist/migrations/{usageQuotas → functions/usageQuotas}/syncApps.js +12 -9
  241. package/dist/migrations/{usageQuotas → functions/usageQuotas}/syncRows.js +16 -12
  242. package/dist/migrations/functions/userEmailViewCasing.js +24 -0
  243. package/dist/migrations/index.js +62 -0
  244. package/dist/package.json +4 -4
  245. package/dist/tests/utilities/TestConfiguration.js +70 -44
  246. package/dist/threads/automation.js +13 -11
  247. package/dist/threads/query.js +13 -19
  248. package/dist/tsconfig.tsbuildinfo +1 -1
  249. package/dist/utilities/fileSystem/index.js +4 -3
  250. package/dist/utilities/global.js +15 -12
  251. package/dist/utilities/index.js +7 -17
  252. package/dist/utilities/routing/index.js +5 -5
  253. package/dist/utilities/rowProcessor/index.js +23 -17
  254. package/dist/utilities/rowProcessor/utils.js +14 -4
  255. package/dist/utilities/usageQuota/index.js +1 -0
  256. package/dist/utilities/usageQuota/rows.js +1 -0
  257. package/dist/utilities/users.js +3 -3
  258. package/dist/utilities/workerRequests.js +4 -4
  259. package/package.json +5 -5
  260. package/scripts/integrations/postgres/init.sql +11 -6
  261. package/scripts/likeCypress.ts +1 -1
  262. package/src/api/controllers/application.js +38 -31
  263. package/src/api/controllers/auth.js +4 -5
  264. package/src/api/controllers/automation.js +13 -23
  265. package/src/api/controllers/cloud.js +2 -3
  266. package/src/api/controllers/component.js +3 -4
  267. package/src/api/controllers/datasource.js +9 -11
  268. package/src/api/controllers/deploy/Deployment.js +3 -7
  269. package/src/api/controllers/deploy/index.js +20 -13
  270. package/src/api/controllers/dev.js +5 -5
  271. package/src/api/controllers/layout.js +3 -3
  272. package/src/api/controllers/metadata.js +4 -9
  273. package/src/api/controllers/migrations.js +13 -0
  274. package/src/api/controllers/permission.js +4 -4
  275. package/src/api/controllers/query/import/index.ts +4 -6
  276. package/src/api/controllers/query/import/tests/index.spec.js +2 -1
  277. package/src/api/controllers/query/index.js +11 -10
  278. package/src/api/controllers/role.js +5 -5
  279. package/src/api/controllers/routing.js +5 -6
  280. package/src/api/controllers/row/ExternalRequest.ts +67 -43
  281. package/src/api/controllers/row/external.js +27 -58
  282. package/src/api/controllers/row/internal.js +54 -90
  283. package/src/api/controllers/row/internalSearch.js +23 -17
  284. package/src/api/controllers/row/staticFormula.js +156 -0
  285. package/src/api/controllers/row/utils.js +7 -6
  286. package/src/api/controllers/screen.js +5 -7
  287. package/src/api/controllers/static/index.js +4 -4
  288. package/src/api/controllers/table/bulkFormula.js +173 -0
  289. package/src/api/controllers/table/external.js +7 -10
  290. package/src/api/controllers/table/index.js +7 -21
  291. package/src/api/controllers/table/internal.js +22 -19
  292. package/src/api/controllers/table/utils.js +70 -42
  293. package/src/api/controllers/user.js +17 -20
  294. package/src/api/controllers/view/index.js +8 -10
  295. package/src/api/controllers/view/utils.js +9 -4
  296. package/src/api/controllers/webhook.js +10 -8
  297. package/src/api/routes/index.js +2 -0
  298. package/src/api/routes/migrations.js +14 -0
  299. package/src/api/routes/tests/automation.spec.js +1 -0
  300. package/src/api/routes/tests/misc.spec.js +0 -1
  301. package/src/api/routes/tests/routing.spec.js +21 -12
  302. package/src/api/routes/tests/row.spec.js +7 -4
  303. package/src/api/routes/tests/utilities/TestFunctions.js +39 -17
  304. package/src/app.ts +18 -5
  305. package/src/automations/automationUtils.js +2 -3
  306. package/src/automations/steps/createRow.js +0 -1
  307. package/src/automations/steps/updateRow.js +1 -1
  308. package/src/automations/triggers.js +33 -31
  309. package/src/automations/utils.js +9 -5
  310. package/src/constants/index.js +5 -0
  311. package/src/db/linkedRows/LinkController.js +3 -7
  312. package/src/db/linkedRows/index.js +16 -31
  313. package/src/db/linkedRows/linkUtils.js +6 -6
  314. package/src/db/tests/linkController.spec.js +0 -1
  315. package/src/db/tests/linkTests.spec.js +5 -6
  316. package/src/db/views/staticViews.js +8 -10
  317. package/src/definitions/common.ts +3 -0
  318. package/src/environment.js +3 -1
  319. package/src/integrations/base/sql.ts +55 -14
  320. package/src/integrations/utils.ts +4 -1
  321. package/src/middleware/authorized.js +5 -3
  322. package/src/middleware/builder.js +2 -2
  323. package/src/middleware/currentapp.js +50 -46
  324. package/src/middleware/tests/authorized.spec.js +7 -2
  325. package/src/middleware/tests/currentapp.spec.js +6 -0
  326. package/src/middleware/usageQuota.js +2 -4
  327. package/src/migrations/functions/appUrls.ts +34 -0
  328. package/src/migrations/functions/quotas1.ts +20 -0
  329. package/src/migrations/functions/tests/appUrls.spec.js +29 -0
  330. package/src/migrations/{tests/usageQuotas/index.spec.js → functions/tests/quotas1.spec.js} +5 -5
  331. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +25 -0
  332. package/src/migrations/functions/usageQuotas/index.ts +8 -0
  333. package/src/migrations/{usageQuotas/syncApps.js → functions/usageQuotas/syncApps.ts} +6 -6
  334. package/src/migrations/functions/usageQuotas/syncRows.ts +22 -0
  335. package/src/migrations/{tests/usageQuotas → functions/usageQuotas/tests}/syncApps.spec.js +4 -4
  336. package/src/migrations/{tests/usageQuotas → functions/usageQuotas/tests}/syncRows.spec.js +4 -4
  337. package/src/migrations/functions/userEmailViewCasing.ts +13 -0
  338. package/src/migrations/index.ts +56 -0
  339. package/src/module.d.ts +3 -0
  340. package/src/tests/utilities/TestConfiguration.js +73 -50
  341. package/src/threads/automation.js +17 -15
  342. package/src/threads/query.js +14 -21
  343. package/src/utilities/fileSystem/index.js +4 -3
  344. package/src/utilities/global.js +15 -12
  345. package/src/utilities/index.js +7 -17
  346. package/src/utilities/routing/index.js +5 -5
  347. package/src/utilities/rowProcessor/index.js +25 -27
  348. package/src/utilities/rowProcessor/utils.js +23 -7
  349. package/src/utilities/usageQuota/index.js +1 -0
  350. package/src/utilities/usageQuota/rows.js +1 -0
  351. package/src/utilities/users.js +3 -3
  352. package/src/utilities/workerRequests.js +4 -4
  353. package/tsconfig.json +2 -1
  354. package/coverage/lcov-report/migrations/usageQuotas/index.html +0 -141
  355. package/coverage/lcov-report/migrations/usageQuotas/syncRows.js.html +0 -143
  356. package/src/migrations/usageQuotas/index.js +0 -24
  357. package/src/migrations/usageQuotas/syncRows.js +0 -21
@@ -2,11 +2,11 @@ const {
2
2
  EMPTY_LAYOUT,
3
3
  BASE_LAYOUT_PROP_IDS,
4
4
  } = require("../../constants/layouts")
5
- const CouchDB = require("../../db")
6
5
  const { generateLayoutID, getScreenParams } = require("../../db/utils")
6
+ const { getAppDB } = require("@budibase/backend-core/context")
7
7
 
8
8
  exports.save = async function (ctx) {
9
- const db = new CouchDB(ctx.appId)
9
+ const db = getAppDB()
10
10
  let layout = ctx.request.body
11
11
 
12
12
  if (!layout.props) {
@@ -26,7 +26,7 @@ exports.save = async function (ctx) {
26
26
  }
27
27
 
28
28
  exports.destroy = async function (ctx) {
29
- const db = new CouchDB(ctx.appId)
29
+ const db = getAppDB()
30
30
  const layoutId = ctx.params.layoutId,
31
31
  layoutRev = ctx.params.layoutRev
32
32
 
@@ -1,7 +1,7 @@
1
1
  const { MetadataTypes } = require("../../constants")
2
- const CouchDB = require("../../db")
3
2
  const { generateMetadataID } = require("../../db/utils")
4
3
  const { saveEntityMetadata, deleteEntityMetadata } = require("../../utilities")
4
+ const { getAppDB } = require("@budibase/backend-core/context")
5
5
 
6
6
  exports.getTypes = async ctx => {
7
7
  ctx.body = {
@@ -14,17 +14,12 @@ exports.saveMetadata = async ctx => {
14
14
  if (type === MetadataTypes.AUTOMATION_TEST_HISTORY) {
15
15
  ctx.throw(400, "Cannot save automation history type")
16
16
  }
17
- ctx.body = await saveEntityMetadata(
18
- ctx.appId,
19
- type,
20
- entityId,
21
- ctx.request.body
22
- )
17
+ ctx.body = await saveEntityMetadata(type, entityId, ctx.request.body)
23
18
  }
24
19
 
25
20
  exports.deleteMetadata = async ctx => {
26
21
  const { type, entityId } = ctx.params
27
- await deleteEntityMetadata(ctx.appId, type, entityId)
22
+ await deleteEntityMetadata(type, entityId)
28
23
  ctx.body = {
29
24
  message: "Metadata deleted successfully",
30
25
  }
@@ -32,7 +27,7 @@ exports.deleteMetadata = async ctx => {
32
27
 
33
28
  exports.getMetadata = async ctx => {
34
29
  const { type, entityId } = ctx.params
35
- const db = new CouchDB(ctx.appId)
30
+ const db = getAppDB()
36
31
  const id = generateMetadataID(type, entityId)
37
32
  try {
38
33
  ctx.body = await db.get(id)
@@ -0,0 +1,13 @@
1
+ const { migrate, MIGRATIONS } = require("../../migrations")
2
+
3
+ exports.migrate = async ctx => {
4
+ const options = ctx.request.body
5
+ // don't await as can take a while, just return
6
+ migrate(options)
7
+ ctx.status = 200
8
+ }
9
+
10
+ exports.fetchDefinitions = async ctx => {
11
+ ctx.body = MIGRATIONS
12
+ ctx.status = 200
13
+ }
@@ -6,12 +6,12 @@ const {
6
6
  getBuiltinRoles,
7
7
  } = require("@budibase/backend-core/roles")
8
8
  const { getRoleParams } = require("../../db/utils")
9
- const CouchDB = require("../../db")
10
9
  const {
11
10
  CURRENTLY_SUPPORTED_LEVELS,
12
11
  getBasePermissions,
13
12
  } = require("../../utilities/security")
14
13
  const { removeFromArray } = require("../../utilities")
14
+ const { getAppDB } = require("@budibase/backend-core/context")
15
15
 
16
16
  const PermissionUpdateType = {
17
17
  REMOVE: "remove",
@@ -35,7 +35,7 @@ async function updatePermissionOnRole(
35
35
  { roleId, resourceId, level },
36
36
  updateType
37
37
  ) {
38
- const db = new CouchDB(appId)
38
+ const db = getAppDB()
39
39
  const remove = updateType === PermissionUpdateType.REMOVE
40
40
  const isABuiltin = isBuiltin(roleId)
41
41
  const dbRoleId = getDBRoleID(roleId)
@@ -106,7 +106,7 @@ exports.fetchLevels = function (ctx) {
106
106
  }
107
107
 
108
108
  exports.fetch = async function (ctx) {
109
- const db = new CouchDB(ctx.appId)
109
+ const db = getAppDB()
110
110
  const roles = await getAllDBRoles(db)
111
111
  let permissions = {}
112
112
  // create an object with structure role ID -> resource ID -> level
@@ -133,7 +133,7 @@ exports.fetch = async function (ctx) {
133
133
 
134
134
  exports.getResourcePerms = async function (ctx) {
135
135
  const resourceId = ctx.params.resourceId
136
- const db = new CouchDB(ctx.appId)
136
+ const db = getAppDB()
137
137
  const body = await db.allDocs(
138
138
  getRoleParams(null, {
139
139
  include_docs: true,
@@ -1,10 +1,11 @@
1
- import CouchDB from "../../../../db"
2
1
  import { queryValidation } from "../validation"
3
2
  import { generateQueryID } from "../../../../db/utils"
4
3
  import { ImportInfo, ImportSource } from "./sources/base"
5
4
  import { OpenAPI2 } from "./sources/openapi2"
6
5
  import { Query } from "./../../../../definitions/common"
7
6
  import { Curl } from "./sources/curl"
7
+ // @ts-ignore
8
+ import { getAppDB } from "@budibase/backend-core/context"
8
9
  interface ImportResult {
9
10
  errorQueries: Query[]
10
11
  queries: Query[]
@@ -33,10 +34,7 @@ export class RestImporter {
33
34
  return this.source.getInfo()
34
35
  }
35
36
 
36
- importQueries = async (
37
- appId: string,
38
- datasourceId: string
39
- ): Promise<ImportResult> => {
37
+ importQueries = async (datasourceId: string): Promise<ImportResult> => {
40
38
  // constuct the queries
41
39
  let queries = await this.source.getQueries(datasourceId)
42
40
 
@@ -58,7 +56,7 @@ export class RestImporter {
58
56
  })
59
57
 
60
58
  // persist queries
61
- const db = new CouchDB(appId)
59
+ const db = getAppDB()
62
60
  const response = await db.bulkDocs(queries)
63
61
 
64
62
  // create index to seperate queries and errors
@@ -6,6 +6,7 @@ const db = jest.fn(() => {
6
6
  }
7
7
  })
8
8
  jest.mock("../../../../../db", () => db)
9
+ require("@budibase/backend-core").init(require("../../../../../db"))
9
10
 
10
11
  const { RestImporter } = require("../index")
11
12
 
@@ -77,7 +78,7 @@ describe("Rest Importer", () => {
77
78
  const testImportQueries = async (key, data, assertions) => {
78
79
  await init(data)
79
80
  bulkDocs.mockReturnValue([])
80
- const importResult = await restImporter.importQueries("appId", "datasourceId")
81
+ const importResult = await restImporter.importQueries("datasourceId")
81
82
  expect(importResult.errorQueries.length).toBe(0)
82
83
  expect(importResult.queries.length).toBe(assertions[key].count)
83
84
  expect(bulkDocs).toHaveBeenCalledTimes(1)
@@ -1,4 +1,3 @@
1
- const CouchDB = require("../../../db")
2
1
  const {
3
2
  generateQueryID,
4
3
  getQueryParams,
@@ -10,6 +9,7 @@ const { save: saveDatasource } = require("../datasource")
10
9
  const { RestImporter } = require("./import")
11
10
  const { invalidateDynamicVariables } = require("../../../threads/utils")
12
11
  const environment = require("../../../environment")
12
+ const { getAppDB } = require("@budibase/backend-core/context")
13
13
 
14
14
  const Runner = new Thread(ThreadType.QUERY, {
15
15
  timeoutMs: environment.QUERY_THREAD_TIMEOUT || 10000,
@@ -28,7 +28,7 @@ function enrichQueries(input) {
28
28
  }
29
29
 
30
30
  exports.fetch = async function (ctx) {
31
- const db = new CouchDB(ctx.appId)
31
+ const db = getAppDB()
32
32
 
33
33
  const body = await db.allDocs(
34
34
  getQueryParams(null, {
@@ -69,7 +69,7 @@ exports.import = async ctx => {
69
69
  datasourceId = body.datasourceId
70
70
  }
71
71
 
72
- const importResult = await importer.importQueries(ctx.appId, datasourceId)
72
+ const importResult = await importer.importQueries(datasourceId)
73
73
 
74
74
  ctx.body = {
75
75
  ...importResult,
@@ -79,7 +79,7 @@ exports.import = async ctx => {
79
79
  }
80
80
 
81
81
  exports.save = async function (ctx) {
82
- const db = new CouchDB(ctx.appId)
82
+ const db = getAppDB()
83
83
  const query = ctx.request.body
84
84
 
85
85
  if (!query._id) {
@@ -94,7 +94,7 @@ exports.save = async function (ctx) {
94
94
  }
95
95
 
96
96
  exports.find = async function (ctx) {
97
- const db = new CouchDB(ctx.appId)
97
+ const db = getAppDB()
98
98
  const query = enrichQueries(await db.get(ctx.params.queryId))
99
99
  // remove properties that could be dangerous in real app
100
100
  if (isProdAppID(ctx.appId)) {
@@ -105,7 +105,7 @@ exports.find = async function (ctx) {
105
105
  }
106
106
 
107
107
  exports.preview = async function (ctx) {
108
- const db = new CouchDB(ctx.appId)
108
+ const db = getAppDB()
109
109
 
110
110
  const datasource = await db.get(ctx.request.body.datasourceId)
111
111
  // preview may not have a queryId as it hasn't been saved, but if it does
@@ -136,7 +136,7 @@ exports.preview = async function (ctx) {
136
136
  }
137
137
 
138
138
  async function execute(ctx, opts = { rowsOnly: false }) {
139
- const db = new CouchDB(ctx.appId)
139
+ const db = getAppDB()
140
140
 
141
141
  const query = await db.get(ctx.params.queryId)
142
142
  const datasource = await db.get(query.datasourceId)
@@ -181,7 +181,8 @@ exports.executeV2 = async function (ctx) {
181
181
  return execute(ctx, { rowsOnly: false })
182
182
  }
183
183
 
184
- const removeDynamicVariables = async (db, queryId) => {
184
+ const removeDynamicVariables = async queryId => {
185
+ const db = getAppDB()
185
186
  const query = await db.get(queryId)
186
187
  const datasource = await db.get(query.datasourceId)
187
188
  const dynamicVariables = datasource.config.dynamicVariables
@@ -202,8 +203,8 @@ const removeDynamicVariables = async (db, queryId) => {
202
203
  }
203
204
 
204
205
  exports.destroy = async function (ctx) {
205
- const db = new CouchDB(ctx.appId)
206
- await removeDynamicVariables(db, ctx.params.queryId)
206
+ const db = getAppDB()
207
+ await removeDynamicVariables(ctx.params.queryId)
207
208
  await db.remove(ctx.params.queryId, ctx.params.revId)
208
209
  ctx.message = `Query deleted.`
209
210
  ctx.status = 200
@@ -1,4 +1,3 @@
1
- const CouchDB = require("../../db")
2
1
  const {
3
2
  Role,
4
3
  getRole,
@@ -10,6 +9,7 @@ const {
10
9
  getUserMetadataParams,
11
10
  InternalTables,
12
11
  } = require("../../db/utils")
12
+ const { getAppDB } = require("@budibase/backend-core/context")
13
13
 
14
14
  const UpdateRolesOptions = {
15
15
  CREATED: "created",
@@ -40,15 +40,15 @@ async function updateRolesOnUserTable(db, roleId, updateOption) {
40
40
  }
41
41
 
42
42
  exports.fetch = async function (ctx) {
43
- ctx.body = await getAllRoles(ctx.appId)
43
+ ctx.body = await getAllRoles()
44
44
  }
45
45
 
46
46
  exports.find = async function (ctx) {
47
- ctx.body = await getRole(ctx.appId, ctx.params.roleId)
47
+ ctx.body = await getRole(ctx.params.roleId)
48
48
  }
49
49
 
50
50
  exports.save = async function (ctx) {
51
- const db = new CouchDB(ctx.appId)
51
+ const db = getAppDB()
52
52
  let { _id, name, inherits, permissionId } = ctx.request.body
53
53
  if (!_id) {
54
54
  _id = generateRoleID()
@@ -69,7 +69,7 @@ exports.save = async function (ctx) {
69
69
  }
70
70
 
71
71
  exports.destroy = async function (ctx) {
72
- const db = new CouchDB(ctx.appId)
72
+ const db = getAppDB()
73
73
  const roleId = ctx.params.roleId
74
74
  if (isBuiltin(roleId)) {
75
75
  ctx.throw(400, "Cannot delete builtin role.")
@@ -39,12 +39,11 @@ Routing.prototype.addScreenId = function (fullpath, roleId, screenId) {
39
39
 
40
40
  /**
41
41
  * Gets the full routing structure by querying the routing view and processing the result into the tree.
42
- * @param {string} appId The application to produce the routing structure for.
43
42
  * @returns {Promise<object>} The routing structure, this is the full structure designed for use in the builder,
44
43
  * if the client routing is required then the updateRoutingStructureForUserRole should be used.
45
44
  */
46
- async function getRoutingStructure(appId) {
47
- const screenRoutes = await getRoutingInfo(appId)
45
+ async function getRoutingStructure() {
46
+ const screenRoutes = await getRoutingInfo()
48
47
  const routing = new Routing()
49
48
 
50
49
  for (let screenRoute of screenRoutes) {
@@ -57,13 +56,13 @@ async function getRoutingStructure(appId) {
57
56
  }
58
57
 
59
58
  exports.fetch = async ctx => {
60
- ctx.body = await getRoutingStructure(ctx.appId)
59
+ ctx.body = await getRoutingStructure()
61
60
  }
62
61
 
63
62
  exports.clientFetch = async ctx => {
64
- const routing = await getRoutingStructure(ctx.appId)
63
+ const routing = await getRoutingStructure()
65
64
  let roleId = ctx.user.role._id
66
- const roleIds = await getUserRoleHierarchy(ctx.appId, roleId)
65
+ const roleIds = await getUserRoleHierarchy(roleId)
67
66
  for (let topLevel of Object.values(routing.routes)) {
68
67
  for (let subpathKey of Object.keys(topLevel.subpaths)) {
69
68
  let found = false
@@ -19,6 +19,19 @@ import {
19
19
  isRowId,
20
20
  convertRowId,
21
21
  } from "../../../integrations/utils"
22
+ import { getDatasourceAndQuery } from "./utils"
23
+ import {
24
+ DataSourceOperation,
25
+ FieldTypes,
26
+ RelationshipTypes,
27
+ } from "../../../constants"
28
+ import { breakExternalTableId, isSQL } from "../../../integrations/utils"
29
+ import { processObjectSync } from "@budibase/string-templates"
30
+ // @ts-ignore
31
+ import { cloneDeep } from "lodash/fp"
32
+ import { processFormulas } from "../../../utilities/rowProcessor/utils"
33
+ // @ts-ignore
34
+ import { getAppDB } from "@budibase/backend-core/context"
22
35
 
23
36
  interface ManyRelationship {
24
37
  tableId?: string
@@ -38,18 +51,6 @@ interface RunConfig {
38
51
  }
39
52
 
40
53
  module External {
41
- const { getDatasourceAndQuery } = require("./utils")
42
- const {
43
- DataSourceOperation,
44
- FieldTypes,
45
- RelationshipTypes,
46
- } = require("../../../constants")
47
- const { breakExternalTableId, isSQL } = require("../../../integrations/utils")
48
- const { processObjectSync } = require("@budibase/string-templates")
49
- const { cloneDeep } = require("lodash/fp")
50
- const CouchDB = require("../../../db")
51
- const { processFormulas } = require("../../../utilities/rowProcessor/utils")
52
-
53
54
  function buildFilters(
54
55
  id: string | undefined,
55
56
  filters: SearchFilters,
@@ -183,7 +184,7 @@ module External {
183
184
  thisRow._id = generateIdForRow(row, table)
184
185
  thisRow.tableId = table._id
185
186
  thisRow._rev = "rev"
186
- return thisRow
187
+ return processFormulas(table, thisRow)
187
188
  }
188
189
 
189
190
  function fixArrayTypes(row: Row, table: Table) {
@@ -210,19 +211,12 @@ module External {
210
211
  }
211
212
 
212
213
  class ExternalRequest {
213
- private readonly appId: string
214
214
  private operation: Operation
215
215
  private tableId: string
216
216
  private datasource: Datasource
217
217
  private tables: { [key: string]: Table } = {}
218
218
 
219
- constructor(
220
- appId: string,
221
- operation: Operation,
222
- tableId: string,
223
- datasource: Datasource
224
- ) {
225
- this.appId = appId
219
+ constructor(operation: Operation, tableId: string, datasource: Datasource) {
226
220
  this.operation = operation
227
221
  this.tableId = tableId
228
222
  this.datasource = datasource
@@ -231,12 +225,14 @@ module External {
231
225
  }
232
226
  }
233
227
 
234
- getTable(tableId: string | undefined): Table {
228
+ getTable(tableId: string | undefined): Table | undefined {
235
229
  if (!tableId) {
236
230
  throw "Table ID is unknown, cannot find table"
237
231
  }
238
232
  const { tableName } = breakExternalTableId(tableId)
239
- return this.tables[tableName]
233
+ if (tableName) {
234
+ return this.tables[tableName]
235
+ }
240
236
  }
241
237
 
242
238
  inputProcessing(row: Row | undefined, table: Table) {
@@ -272,9 +268,11 @@ module External {
272
268
  newRow[key] = row[key]
273
269
  continue
274
270
  }
275
- const { tableName: linkTableName } = breakExternalTableId(field.tableId)
271
+ const { tableName: linkTableName } = breakExternalTableId(
272
+ field?.tableId
273
+ )
276
274
  // table has to exist for many to many
277
- if (!this.tables[linkTableName]) {
275
+ if (!linkTableName || !this.tables[linkTableName]) {
278
276
  continue
279
277
  }
280
278
  const linkTable = this.tables[linkTableName]
@@ -329,8 +327,12 @@ module External {
329
327
  * This iterates through the returned rows and works out what elements of the rows
330
328
  * actually match up to another row (based on primary keys) - this is pretty specific
331
329
  * to SQL and the way that SQL relationships are returned based on joins.
330
+ * This is complicated, but the idea is that when a SQL query returns all the relations
331
+ * will be separate rows, with all of the data in each row. We have to decipher what comes
332
+ * from where (which tables) and how to convert that into budibase columns.
332
333
  */
333
334
  updateRelationshipColumns(
335
+ table: Table,
334
336
  row: Row,
335
337
  rows: { [key: string]: Row },
336
338
  relationships: RelationshipsJson[]
@@ -341,6 +343,13 @@ module External {
341
343
  if (!linkedTable) {
342
344
  continue
343
345
  }
346
+ const fromColumn = `${table.name}.${relationship.from}`
347
+ const toColumn = `${linkedTable.name}.${relationship.to}`
348
+ // this is important when working with multiple relationships
349
+ // between the same tables, don't want to overlap/multiply the relations
350
+ if (!relationship.through && row[fromColumn] !== row[toColumn]) {
351
+ continue
352
+ }
344
353
  let linked = basicProcessing(row, linkedTable)
345
354
  if (!linked._id) {
346
355
  continue
@@ -388,6 +397,7 @@ module External {
388
397
  // this is a relationship of some sort
389
398
  if (finalRows[rowId]) {
390
399
  finalRows = this.updateRelationshipColumns(
400
+ table,
391
401
  row,
392
402
  finalRows,
393
403
  relationships
@@ -401,6 +411,7 @@ module External {
401
411
  finalRows[thisRow._id] = thisRow
402
412
  // do this at end once its been added to the final rows
403
413
  finalRows = this.updateRelationshipColumns(
414
+ table,
404
415
  row,
405
416
  finalRows,
406
417
  relationships
@@ -422,7 +433,7 @@ module External {
422
433
  }
423
434
  const { tableName: linkTableName } = breakExternalTableId(field.tableId)
424
435
  // no table to link to, this is not a valid relationships
425
- if (!this.tables[linkTableName]) {
436
+ if (!linkTableName || !this.tables[linkTableName]) {
426
437
  continue
427
438
  }
428
439
  const linkTable = this.tables[linkTableName]
@@ -460,6 +471,9 @@ module External {
460
471
  async lookupRelations(tableId: string, row: Row) {
461
472
  const related: { [key: string]: any } = {}
462
473
  const { tableName } = breakExternalTableId(tableId)
474
+ if (!tableName) {
475
+ return related
476
+ }
463
477
  const table = this.tables[tableName]
464
478
  // @ts-ignore
465
479
  const primaryKey = table.primary[0]
@@ -484,7 +498,7 @@ module External {
484
498
  if (!lookupField || !row[lookupField]) {
485
499
  continue
486
500
  }
487
- const response = await getDatasourceAndQuery(this.appId, {
501
+ const response = await getDatasourceAndQuery({
488
502
  endpoint: getEndpoint(tableId, DataSourceOperation.READ),
489
503
  filters: {
490
504
  equal: {
@@ -515,28 +529,30 @@ module External {
515
529
  row: Row,
516
530
  relationships: ManyRelationship[]
517
531
  ) {
518
- const { appId } = this
519
532
  // if we're creating (in a through table) need to wipe the existing ones first
520
533
  const promises = []
521
534
  const related = await this.lookupRelations(mainTableId, row)
522
535
  for (let relationship of relationships) {
523
536
  const { key, tableId, isUpdate, id, ...rest } = relationship
524
- const body = processObjectSync(rest, row)
537
+ const body: { [key: string]: any } = processObjectSync(rest, row, {})
525
538
  const linkTable = this.getTable(tableId)
526
539
  // @ts-ignore
527
- const linkPrimary = linkTable.primary[0]
528
- const rows = related[key]?.rows || []
540
+ const linkPrimary = linkTable?.primary[0]
541
+ if (!linkTable || !linkPrimary) {
542
+ return
543
+ }
544
+ const rows = related[key].rows || []
529
545
  const found = rows.find(
530
546
  (row: { [key: string]: any }) =>
531
547
  row[linkPrimary] === relationship.id ||
532
- row[linkPrimary] === body[linkPrimary]
548
+ row[linkPrimary] === body?.[linkPrimary]
533
549
  )
534
550
  const operation = isUpdate
535
551
  ? DataSourceOperation.UPDATE
536
552
  : DataSourceOperation.CREATE
537
553
  if (!found) {
538
554
  promises.push(
539
- getDatasourceAndQuery(appId, {
555
+ getDatasourceAndQuery({
540
556
  endpoint: getEndpoint(tableId, operation),
541
557
  // if we're doing many relationships then we're writing, only one response
542
558
  body,
@@ -552,9 +568,12 @@ module External {
552
568
  for (let [colName, { isMany, rows, tableId }] of Object.entries(
553
569
  related
554
570
  )) {
555
- const table: Table = this.getTable(tableId)
571
+ const table: Table | undefined = this.getTable(tableId)
556
572
  // if its not the foreign key skip it, nothing to do
557
- if (table.primary && table.primary.indexOf(colName) !== -1) {
573
+ if (
574
+ !table ||
575
+ (table.primary && table.primary.indexOf(colName) !== -1)
576
+ ) {
558
577
  continue
559
578
  }
560
579
  for (let row of rows) {
@@ -566,7 +585,7 @@ module External {
566
585
  : DataSourceOperation.UPDATE
567
586
  const body = isMany ? null : { [colName]: null }
568
587
  promises.push(
569
- getDatasourceAndQuery(this.appId, {
588
+ getDatasourceAndQuery({
570
589
  endpoint: getEndpoint(tableId, op),
571
590
  body,
572
591
  filters,
@@ -605,20 +624,25 @@ module External {
605
624
  continue
606
625
  }
607
626
  const { tableName: linkTableName } = breakExternalTableId(field.tableId)
608
- const linkTable = this.tables[linkTableName]
609
- if (linkTable) {
610
- const linkedFields = extractRealFields(linkTable, fields)
611
- fields = fields.concat(linkedFields)
627
+ if (linkTableName) {
628
+ const linkTable = this.tables[linkTableName]
629
+ if (linkTable) {
630
+ const linkedFields = extractRealFields(linkTable, fields)
631
+ fields = fields.concat(linkedFields)
632
+ }
612
633
  }
613
634
  }
614
635
  return fields
615
636
  }
616
637
 
617
638
  async run(config: RunConfig) {
618
- const { appId, operation, tableId } = this
639
+ const { operation, tableId } = this
619
640
  let { datasourceId, tableName } = breakExternalTableId(tableId)
641
+ if (!tableName) {
642
+ throw "Unable to run without a table name"
643
+ }
620
644
  if (!this.datasource) {
621
- const db = new CouchDB(appId)
645
+ const db = getAppDB()
622
646
  this.datasource = await db.get(datasourceId)
623
647
  if (!this.datasource || !this.datasource.entities) {
624
648
  throw "No tables found, fetch tables before query."
@@ -670,7 +694,7 @@ module External {
670
694
  },
671
695
  }
672
696
  // can't really use response right now
673
- const response = await getDatasourceAndQuery(appId, json)
697
+ const response = await getDatasourceAndQuery(json)
674
698
  // handle many to many relationships now if we know the ID (could be auto increment)
675
699
  if (
676
700
  operation !== DataSourceOperation.READ &&