@budibase/server 0.9.188 → 0.9.190-alpha.10

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 (314) hide show
  1. package/Dockerfile +7 -1
  2. package/__mocks__/mssql.ts +1 -1
  3. package/__mocks__/oracledb.ts +31 -0
  4. package/__mocks__/pg.ts +3 -0
  5. package/builder/assets/bb-space-man.5be51a45.svg +290 -0
  6. package/builder/assets/index.2bd3b345.js +1316 -0
  7. package/builder/assets/index.4fb3f887.css +1 -0
  8. package/builder/assets/oracle.66592424.png +0 -0
  9. package/builder/assets/vendor.470042a4.js +152 -0
  10. package/builder/assets/vendor.5e1fe644.css +1 -0
  11. package/builder/index.html +4 -4
  12. package/coverage/clover.xml +1608 -1191
  13. package/coverage/coverage-final.json +97 -93
  14. package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
  15. package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
  16. package/coverage/lcov-report/api/controllers/application.js.html +113 -80
  17. package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
  18. package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
  19. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  22. package/coverage/lcov-report/api/controllers/datasource.js.html +245 -41
  23. package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
  24. package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
  25. package/coverage/lcov-report/api/controllers/index.html +98 -98
  26. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/layout.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
  29. package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
  30. package/coverage/lcov-report/api/controllers/query.js.html +79 -229
  31. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  32. package/coverage/lcov-report/api/controllers/routing.js.html +29 -29
  33. package/coverage/lcov-report/api/controllers/row/external.js.html +17 -8
  34. package/coverage/lcov-report/api/controllers/row/index.html +26 -26
  35. package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
  36. package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
  37. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
  38. package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
  39. package/coverage/lcov-report/api/controllers/screen.js.html +3 -3
  40. package/coverage/lcov-report/api/controllers/script.js.html +3 -3
  41. package/coverage/lcov-report/api/controllers/table/external.js.html +1001 -0
  42. package/coverage/lcov-report/api/controllers/table/index.html +56 -26
  43. package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
  44. package/coverage/lcov-report/api/controllers/table/internal.js.html +533 -0
  45. package/coverage/lcov-report/api/controllers/table/utils.js.html +175 -52
  46. package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
  47. package/coverage/lcov-report/api/controllers/user.js.html +390 -33
  48. package/coverage/lcov-report/api/controllers/view/exporters.js.html +19 -4
  49. package/coverage/lcov-report/api/controllers/view/index.html +22 -22
  50. package/coverage/lcov-report/api/controllers/view/index.js.html +52 -13
  51. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  52. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
  53. package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
  54. package/coverage/lcov-report/api/index.html +1 -1
  55. package/coverage/lcov-report/api/index.js.html +5 -5
  56. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/dev.js.html +2 -2
  67. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/index.html +4 -4
  69. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/query.js.html +5 -2
  75. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/row.js.html +536 -2
  78. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/static.js.html +2 -2
  81. package/coverage/lcov-report/api/routes/table.js.html +464 -2
  82. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/user.js.html +17 -2
  84. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  85. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  86. package/coverage/lcov-report/automations/actions.js.html +2 -2
  87. package/coverage/lcov-report/automations/automationUtils.js.html +4 -4
  88. package/coverage/lcov-report/automations/bullboard.js.html +71 -20
  89. package/coverage/lcov-report/automations/index.html +35 -50
  90. package/coverage/lcov-report/automations/index.js.html +2 -2
  91. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
  96. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
  98. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/index.html +14 -14
  100. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
  102. package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
  103. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  106. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  107. package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
  108. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  110. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  113. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  115. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  116. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggers.js.html +22 -10
  118. package/coverage/lcov-report/automations/utils.js.html +46 -16
  119. package/coverage/lcov-report/constants/index.html +5 -5
  120. package/coverage/lcov-report/constants/index.js.html +87 -21
  121. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  122. package/coverage/lcov-report/constants/screens.js.html +2 -2
  123. package/coverage/lcov-report/db/client.js.html +2 -2
  124. package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
  125. package/coverage/lcov-report/db/index.html +2 -2
  126. package/coverage/lcov-report/db/index.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
  128. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  129. package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
  130. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
  131. package/coverage/lcov-report/db/newid.js.html +4 -4
  132. package/coverage/lcov-report/db/utils.js.html +75 -75
  133. package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
  134. package/coverage/lcov-report/events/index.html +6 -6
  135. package/coverage/lcov-report/events/index.js.html +1 -1
  136. package/coverage/lcov-report/events/utils.js.html +5 -5
  137. package/coverage/lcov-report/index.html +106 -91
  138. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  139. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  140. package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
  141. package/coverage/lcov-report/middleware/authorized.js.html +19 -16
  142. package/coverage/lcov-report/middleware/builder.js.html +22 -13
  143. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  144. package/coverage/lcov-report/middleware/index.html +23 -23
  145. package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
  146. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  147. package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
  148. package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
  149. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  150. package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +90 -33
  151. package/coverage/lcov-report/threads/index.html +141 -0
  152. package/coverage/lcov-report/threads/index.js.html +278 -0
  153. package/coverage/lcov-report/threads/query.js.html +278 -0
  154. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  155. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  156. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  157. package/coverage/lcov-report/utilities/csvParser.js.html +144 -15
  158. package/coverage/lcov-report/utilities/global.js.html +38 -23
  159. package/coverage/lcov-report/utilities/index.html +48 -48
  160. package/coverage/lcov-report/utilities/index.js.html +49 -16
  161. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +31 -10
  162. package/coverage/lcov-report/utilities/queue/index.html +14 -14
  163. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  164. package/coverage/lcov-report/utilities/routing/index.js.html +2 -2
  165. package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
  166. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
  167. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
  168. package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
  169. package/coverage/lcov-report/utilities/security.js.html +3 -3
  170. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  171. package/coverage/lcov-report/utilities/users.js.html +1 -1
  172. package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
  173. package/coverage/lcov.info +2687 -1942
  174. package/dist/api/controllers/application.js +16 -6
  175. package/dist/api/controllers/auth.js +3 -3
  176. package/dist/api/controllers/datasource.js +67 -16
  177. package/dist/api/controllers/deploy/index.js +2 -0
  178. package/dist/api/controllers/dev.js +4 -1
  179. package/dist/api/controllers/query.js +32 -62
  180. package/dist/api/controllers/row/ExternalRequest.js +83 -36
  181. package/dist/api/controllers/row/external.js +3 -1
  182. package/dist/api/controllers/row/utils.js +6 -12
  183. package/dist/api/controllers/table/external.js +249 -0
  184. package/dist/api/controllers/table/index.js +49 -123
  185. package/dist/api/controllers/table/internal.js +146 -0
  186. package/dist/api/controllers/table/utils.js +62 -28
  187. package/dist/api/controllers/user.js +123 -11
  188. package/dist/api/controllers/view/exporters.js +4 -0
  189. package/dist/api/controllers/view/index.js +14 -2
  190. package/dist/api/routes/query.js +1 -1
  191. package/dist/api/routes/row.js +178 -0
  192. package/dist/api/routes/table.js +150 -1
  193. package/dist/api/routes/user.js +2 -1
  194. package/dist/app.js +2 -11
  195. package/dist/automations/bullboard.js +37 -10
  196. package/dist/automations/triggers.js +7 -3
  197. package/dist/automations/utils.js +11 -2
  198. package/dist/constants/index.js +19 -0
  199. package/dist/definitions/datasource.js +17 -1
  200. package/dist/environment.js +13 -0
  201. package/dist/integrations/base/IntegrationBase.js +2 -0
  202. package/dist/integrations/base/datasourcePlus.js +2 -0
  203. package/dist/integrations/base/sql.js +350 -177
  204. package/dist/integrations/base/sqlTable.js +143 -0
  205. package/dist/integrations/base/utils.js +30 -0
  206. package/dist/integrations/index.js +6 -0
  207. package/dist/integrations/microsoftSqlServer.js +117 -9
  208. package/dist/integrations/mysql.js +16 -85
  209. package/dist/integrations/oracle.js +367 -0
  210. package/dist/integrations/postgres.js +35 -28
  211. package/dist/integrations/utils.js +71 -9
  212. package/dist/middleware/authorized.js +2 -1
  213. package/dist/middleware/builder.js +4 -1
  214. package/dist/package.json +18 -9
  215. package/dist/tests/utilities/TestConfiguration.js +2 -1
  216. package/dist/{automations/thread.js → threads/automation.js} +26 -8
  217. package/dist/threads/index.js +64 -0
  218. package/dist/threads/query.js +64 -0
  219. package/dist/tsconfig.tsbuildinfo +1 -1
  220. package/dist/utilities/csvParser.js +46 -5
  221. package/dist/utilities/global.js +6 -2
  222. package/dist/utilities/index.js +11 -0
  223. package/dist/utilities/queue/inMemoryQueue.js +8 -0
  224. package/dist/utilities/scriptRunner.js +4 -1
  225. package/package.json +19 -10
  226. package/scripts/dev/manage.js +1 -0
  227. package/scripts/docs/README.md +31 -0
  228. package/scripts/docs/generate.js +74 -0
  229. package/scripts/docs/toSwagger.js +320 -0
  230. package/scripts/integrations/mssql/data/Dockerfile +9 -0
  231. package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
  232. package/scripts/integrations/mssql/data/setup.sql +54 -0
  233. package/scripts/integrations/mssql/docker-compose.yaml +12 -0
  234. package/scripts/integrations/mssql/reset.sh +3 -0
  235. package/scripts/integrations/oracle/docker-compose.yml +19 -0
  236. package/scripts/integrations/oracle/instantclient/linux/x86-64/basiclite-21.4.zip +0 -0
  237. package/scripts/integrations/oracle/instantclient/linux/x86-64/install.sh +23 -0
  238. package/scripts/integrations/oracle/oracle.md +90 -0
  239. package/scripts/integrations/postgres/docker-compose.yml +3 -3
  240. package/scripts/likeCypress.ts +33 -0
  241. package/src/api/controllers/application.js +18 -7
  242. package/src/api/controllers/auth.js +3 -0
  243. package/src/api/controllers/datasource.js +84 -16
  244. package/src/api/controllers/deploy/index.js +2 -0
  245. package/src/api/controllers/dev.js +4 -1
  246. package/src/api/controllers/query.js +35 -85
  247. package/src/api/controllers/row/ExternalRequest.ts +99 -38
  248. package/src/api/controllers/row/external.js +4 -1
  249. package/src/api/controllers/row/utils.js +8 -11
  250. package/src/api/controllers/table/external.js +307 -0
  251. package/src/api/controllers/table/index.js +47 -137
  252. package/src/api/controllers/table/internal.js +151 -0
  253. package/src/api/controllers/table/utils.js +74 -33
  254. package/src/api/controllers/user.js +132 -13
  255. package/src/api/controllers/view/exporters.js +5 -0
  256. package/src/api/controllers/view/index.js +15 -2
  257. package/src/api/routes/query.js +1 -0
  258. package/src/api/routes/row.js +178 -0
  259. package/src/api/routes/table.js +154 -0
  260. package/src/api/routes/tests/application.spec.js +0 -2
  261. package/src/api/routes/tests/datasource.spec.js +2 -2
  262. package/src/api/routes/tests/misc.spec.js +5 -1
  263. package/src/api/routes/tests/query.spec.js +38 -9
  264. package/src/api/routes/tests/screen.spec.js +1 -1
  265. package/src/api/routes/user.js +5 -0
  266. package/src/app.ts +2 -10
  267. package/src/automations/bullboard.js +28 -11
  268. package/src/automations/tests/automation.spec.js +3 -4
  269. package/src/automations/triggers.js +7 -3
  270. package/src/automations/utils.js +12 -2
  271. package/src/constants/index.js +22 -0
  272. package/src/definitions/common.ts +7 -1
  273. package/src/definitions/datasource.ts +21 -3
  274. package/src/environment.js +15 -0
  275. package/src/integrations/airtable.ts +2 -1
  276. package/src/integrations/arangodb.ts +2 -1
  277. package/src/integrations/base/IntegrationBase.ts +6 -0
  278. package/src/integrations/base/datasourcePlus.ts +9 -0
  279. package/src/integrations/base/sql.ts +375 -218
  280. package/src/integrations/base/sqlTable.ts +180 -0
  281. package/src/integrations/base/utils.ts +22 -0
  282. package/src/integrations/couchdb.ts +2 -1
  283. package/src/integrations/dynamodb.ts +2 -1
  284. package/src/integrations/elasticsearch.ts +2 -1
  285. package/src/integrations/index.ts +7 -0
  286. package/src/integrations/microsoftSqlServer.ts +145 -13
  287. package/src/integrations/mongodb.ts +2 -1
  288. package/src/integrations/mysql.ts +23 -95
  289. package/src/integrations/oracle.ts +464 -0
  290. package/src/integrations/postgres.ts +45 -35
  291. package/src/integrations/rest.ts +2 -1
  292. package/src/integrations/s3.ts +2 -1
  293. package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
  294. package/src/integrations/tests/oracle.spec.js +94 -0
  295. package/src/integrations/tests/postgres.spec.js +4 -0
  296. package/src/integrations/utils.ts +78 -8
  297. package/src/middleware/authorized.js +2 -1
  298. package/src/middleware/builder.js +4 -1
  299. package/src/tests/utilities/TestConfiguration.js +2 -1
  300. package/src/{automations/thread.js → threads/automation.js} +27 -8
  301. package/src/threads/index.js +66 -0
  302. package/src/threads/query.js +66 -0
  303. package/src/utilities/csvParser.js +48 -5
  304. package/src/utilities/global.js +7 -2
  305. package/src/utilities/index.js +11 -0
  306. package/src/utilities/queue/inMemoryQueue.js +7 -0
  307. package/src/utilities/scriptRunner.js +4 -1
  308. package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
  309. package/src/utilities/tests/csvParser.spec.js +3 -0
  310. package/tsconfig.json +1 -1
  311. package/builder/assets/index.550fdba7.js +0 -201
  312. package/builder/assets/index.7469e1e4.css +0 -29
  313. package/builder/assets/vendor.278a305c.js +0 -9
  314. package/builder/assets/vendor.d75d5eb7.css +0 -1
@@ -24,12 +24,13 @@ const datasource_1 = require("../../../definitions/datasource");
24
24
  const utils_1 = require("../../../integrations/utils");
25
25
  var External;
26
26
  (function (External) {
27
- const { makeExternalQuery } = require("./utils");
27
+ const { getDatasourceAndQuery } = require("./utils");
28
28
  const { DataSourceOperation, FieldTypes, RelationshipTypes, } = require("../../../constants");
29
29
  const { breakExternalTableId, isSQL } = require("../../../integrations/utils");
30
30
  const { processObjectSync } = require("@budibase/string-templates");
31
31
  const { cloneDeep } = require("lodash/fp");
32
32
  const CouchDB = require("../../../db");
33
+ const { processFormulas } = require("../../../utilities/rowProcessor/utils");
33
34
  function buildFilters(id, filters, table) {
34
35
  const primary = table.primary;
35
36
  // if passed in array need to copy for shifting etc
@@ -94,8 +95,11 @@ var External;
94
95
  };
95
96
  // check the row and filters to make sure they aren't a key of some sort
96
97
  if (config.filters) {
97
- for (let filter of Object.values(config.filters)) {
98
- if (typeof filter !== "object" || Object.keys(filter).length === 0) {
98
+ for (let [key, filter] of Object.entries(config.filters)) {
99
+ // oneOf is an array, don't iterate it
100
+ if (typeof filter !== "object" ||
101
+ Object.keys(filter).length === 0 ||
102
+ key === datasource_1.FilterTypes.ONE_OF) {
99
103
  continue;
100
104
  }
101
105
  iterateObject(filter);
@@ -151,8 +155,23 @@ var External;
151
155
  thisRow._rev = "rev";
152
156
  return thisRow;
153
157
  }
154
- function isMany(field) {
155
- return (field.relationshipType && field.relationshipType.split("-")[0] === "many");
158
+ function fixArrayTypes(row, table) {
159
+ for (let [fieldName, schema] of Object.entries(table.schema)) {
160
+ if (schema.type === FieldTypes.ARRAY &&
161
+ typeof row[fieldName] === "string") {
162
+ try {
163
+ row[fieldName] = JSON.parse(row[fieldName]);
164
+ }
165
+ catch (err) {
166
+ // couldn't convert back to array, ignore
167
+ delete row[fieldName];
168
+ }
169
+ }
170
+ }
171
+ return row;
172
+ }
173
+ function isOneSide(field) {
174
+ return (field.relationshipType && field.relationshipType.split("-")[0] === "one");
156
175
  }
157
176
  class ExternalRequest {
158
177
  constructor(appId, operation, tableId, datasource) {
@@ -182,7 +201,10 @@ var External;
182
201
  let newRow = {}, manyRelationships = [];
183
202
  for (let [key, field] of Object.entries(table.schema)) {
184
203
  // if set already, or not set just skip it
185
- if ((!row[key] && row[key] !== "") || newRow[key] || field.autocolumn) {
204
+ if (row[key] == null ||
205
+ newRow[key] ||
206
+ field.autocolumn ||
207
+ field.type === FieldTypes.FORMULA) {
186
208
  continue;
187
209
  }
188
210
  // if its an empty string then it means return the column to null (if possible)
@@ -207,24 +229,35 @@ var External;
207
229
  const linkTable = this.tables[linkTableName];
208
230
  // @ts-ignore
209
231
  const linkTablePrimary = linkTable.primary[0];
210
- if (!isMany(field)) {
232
+ // one to many
233
+ if (isOneSide(field)) {
211
234
  newRow[field.foreignKey || linkTablePrimary] = utils_1.breakRowIdField(row[key][0])[0];
212
235
  }
213
- else {
236
+ // many to many
237
+ else if (field.through) {
214
238
  // we're not inserting a doc, will be a bunch of update calls
215
- const isUpdate = !field.through;
216
- const thisKey = isUpdate
217
- ? "id"
218
- : field.throughTo || linkTablePrimary;
219
- // @ts-ignore
220
- const otherKey = isUpdate
221
- ? field.fieldName
222
- : field.throughFrom || tablePrimary;
239
+ const otherKey = field.throughFrom || linkTablePrimary;
240
+ const thisKey = field.throughTo || tablePrimary;
223
241
  row[key].map((relationship) => {
224
- // we don't really support composite keys for relationships, this is why [0] is used
225
242
  manyRelationships.push({
226
243
  tableId: field.through || field.tableId,
227
- isUpdate,
244
+ isUpdate: false,
245
+ key: otherKey,
246
+ [otherKey]: utils_1.breakRowIdField(relationship)[0],
247
+ // leave the ID for enrichment later
248
+ [thisKey]: `{{ literal ${tablePrimary} }}`,
249
+ });
250
+ });
251
+ }
252
+ // many to one
253
+ else {
254
+ const thisKey = "id";
255
+ // @ts-ignore
256
+ const otherKey = field.fieldName;
257
+ row[key].map((relationship) => {
258
+ manyRelationships.push({
259
+ tableId: field.tableId,
260
+ isUpdate: true,
228
261
  key: otherKey,
229
262
  [thisKey]: utils_1.breakRowIdField(relationship)[0],
230
263
  // leave the ID for enrichment later
@@ -278,7 +311,7 @@ var External;
278
311
  return rows;
279
312
  }
280
313
  outputProcessing(rows = [], table, relationships) {
281
- if (rows[0].read === true) {
314
+ if (!rows || rows.length === 0 || rows[0].read === true) {
282
315
  return [];
283
316
  }
284
317
  let finalRows = {};
@@ -290,12 +323,15 @@ var External;
290
323
  finalRows = this.updateRelationshipColumns(row, finalRows, relationships);
291
324
  continue;
292
325
  }
293
- const thisRow = basicProcessing(row, table);
326
+ const thisRow = fixArrayTypes(basicProcessing(row, table), table);
327
+ if (thisRow._id == null) {
328
+ throw "Unable to generate row ID for SQL rows";
329
+ }
294
330
  finalRows[thisRow._id] = thisRow;
295
331
  // do this at end once its been added to the final rows
296
332
  finalRows = this.updateRelationshipColumns(row, finalRows, relationships);
297
333
  }
298
- return Object.values(finalRows);
334
+ return processFormulas(table, Object.values(finalRows));
299
335
  }
300
336
  /**
301
337
  * Gets the list of relationship JSON structures based on the columns in the table,
@@ -329,8 +365,8 @@ var External;
329
365
  const { tableName: throughTableName } = breakExternalTableId(field.through);
330
366
  definition.through = throughTableName;
331
367
  // don't support composite keys for relationships
332
- definition.from = field.throughFrom || table.primary[0];
333
- definition.to = field.throughTo || linkTable.primary[0];
368
+ definition.from = field.throughTo || table.primary[0];
369
+ definition.to = field.throughFrom || linkTable.primary[0];
334
370
  definition.fromPrimary = table.primary[0];
335
371
  definition.toPrimary = linkTable.primary[0];
336
372
  }
@@ -352,24 +388,34 @@ var External;
352
388
  // make a new request to get the row with all its relationships
353
389
  // we need this to work out if any relationships need removed
354
390
  for (let field of Object.values(table.schema)) {
355
- if (field.type !== FieldTypes.LINK || !field.fieldName) {
391
+ if (field.type !== FieldTypes.LINK ||
392
+ !field.fieldName ||
393
+ isOneSide(field)) {
356
394
  continue;
357
395
  }
358
396
  const isMany = field.relationshipType === RelationshipTypes.MANY_TO_MANY;
359
397
  const tableId = isMany ? field.through : field.tableId;
360
- const manyKey = field.throughFrom || primaryKey;
398
+ const { tableName: relatedTableName } = breakExternalTableId(tableId);
399
+ // @ts-ignore
400
+ const linkPrimaryKey = this.tables[relatedTableName].primary[0];
401
+ const manyKey = field.throughTo || primaryKey;
402
+ const lookupField = isMany ? primaryKey : field.foreignKey;
361
403
  const fieldName = isMany ? manyKey : field.fieldName;
362
- const response = yield makeExternalQuery(this.appId, {
404
+ if (!lookupField || !row[lookupField]) {
405
+ continue;
406
+ }
407
+ const response = yield getDatasourceAndQuery(this.appId, {
363
408
  endpoint: getEndpoint(tableId, DataSourceOperation.READ),
364
409
  filters: {
365
410
  equal: {
366
- [fieldName]: row[primaryKey],
411
+ [fieldName]: row[lookupField],
367
412
  },
368
413
  },
369
414
  });
370
415
  // this is the response from knex if no rows found
371
416
  const rows = !response[0].read ? response : [];
372
- related[fieldName] = { rows, isMany, tableId };
417
+ const storeTo = isMany ? field.throughFrom || linkPrimaryKey : manyKey;
418
+ related[storeTo] = { rows, isMany, tableId };
373
419
  }
374
420
  return related;
375
421
  });
@@ -403,7 +449,7 @@ var External;
403
449
  ? DataSourceOperation.UPDATE
404
450
  : DataSourceOperation.CREATE;
405
451
  if (!found) {
406
- promises.push(makeExternalQuery(appId, {
452
+ promises.push(getDatasourceAndQuery(appId, {
407
453
  endpoint: getEndpoint(tableId, operation),
408
454
  // if we're doing many relationships then we're writing, only one response
409
455
  body,
@@ -430,7 +476,7 @@ var External;
430
476
  ? DataSourceOperation.DELETE
431
477
  : DataSourceOperation.UPDATE;
432
478
  const body = isMany ? null : { [colName]: null };
433
- promises.push(makeExternalQuery(this.appId, {
479
+ promises.push(getDatasourceAndQuery(this.appId, {
434
480
  endpoint: getEndpoint(tableId, op),
435
481
  body,
436
482
  filters,
@@ -449,13 +495,14 @@ var External;
449
495
  * is more performant and has the added benefit of protecting against this scenario.
450
496
  */
451
497
  buildFields(table, includeRelations = datasource_1.IncludeRelationships.INCLUDE) {
452
- function extractNonLinkFieldNames(table, existing = []) {
498
+ function extractRealFields(table, existing = []) {
453
499
  return Object.entries(table.schema)
454
500
  .filter(column => column[1].type !== FieldTypes.LINK &&
501
+ column[1].type !== FieldTypes.FORMULA &&
455
502
  !existing.find((field) => field === column[0]))
456
503
  .map(column => `${table.name}.${column[0]}`);
457
504
  }
458
- let fields = extractNonLinkFieldNames(table);
505
+ let fields = extractRealFields(table);
459
506
  for (let field of Object.values(table.schema)) {
460
507
  if (field.type !== FieldTypes.LINK || !includeRelations) {
461
508
  continue;
@@ -463,7 +510,7 @@ var External;
463
510
  const { tableName: linkTableName } = breakExternalTableId(field.tableId);
464
511
  const linkTable = this.tables[linkTableName];
465
512
  if (linkTable) {
466
- const linkedFields = extractNonLinkFieldNames(linkTable, fields);
513
+ const linkedFields = extractRealFields(linkTable, fields);
467
514
  fields = fields.concat(linkedFields);
468
515
  }
469
516
  }
@@ -487,7 +534,7 @@ var External;
487
534
  throw `Unable to process query, table "${tableName}" not defined.`;
488
535
  }
489
536
  // look for specific components of config which may not be considered acceptable
490
- let { id, row, filters, sort, paginate } = cleanupConfig(config, table);
537
+ let { id, row, filters, sort, paginate, rows } = cleanupConfig(config, table);
491
538
  filters = buildFilters(id, filters || {}, table);
492
539
  const relationships = this.buildRelationships(table);
493
540
  // clean up row on ingress using schema
@@ -511,7 +558,7 @@ var External;
511
558
  sort,
512
559
  paginate,
513
560
  relationships,
514
- body: row,
561
+ body: row || rows,
515
562
  // pass an id filter into extra, purely for mysql/returning
516
563
  extra: {
517
564
  idFilter: buildFilters(id || generateIdForRow(row, table), {}, table),
@@ -521,7 +568,7 @@ var External;
521
568
  },
522
569
  };
523
570
  // can't really use response right now
524
- const response = yield makeExternalQuery(appId, json);
571
+ const response = yield getDatasourceAndQuery(appId, json);
525
572
  // handle many to many relationships now if we know the ID (could be auto increment)
526
573
  if (operation !== DataSourceOperation.READ &&
527
574
  processed.manyRelationships) {
@@ -41,6 +41,7 @@ function handleRequest(appId, operation, tableId, opts = {}) {
41
41
  return new ExternalRequest(appId, operation, tableId, opts.datasource).run(opts);
42
42
  });
43
43
  }
44
+ exports.handleRequest = handleRequest;
44
45
  exports.patch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
45
46
  const appId = ctx.appId;
46
47
  const inputs = ctx.request.body;
@@ -64,7 +65,8 @@ exports.save = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
64
65
  exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
65
66
  // there are no views in external data sources, shouldn't ever be called
66
67
  // for now just fetch
67
- ctx.params.tableId = ctx.params.viewName.split("all_")[1];
68
+ const split = ctx.params.viewName.split("all_");
69
+ ctx.params.tableId = split[1] ? split[1] : split[0];
68
70
  return exports.fetch(ctx);
69
71
  });
70
72
  exports.fetch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
@@ -14,8 +14,8 @@ const CouchDB = require("../../../db");
14
14
  const { InternalTables } = require("../../../db/utils");
15
15
  const userController = require("../user");
16
16
  const { FieldTypes } = require("../../../constants");
17
- const { integrations } = require("../../../integrations");
18
17
  const { processStringSync } = require("@budibase/string-templates");
18
+ const { makeExternalQuery } = require("../../../integrations/base/utils");
19
19
  validateJs.extend(validateJs.validators.datetime, {
20
20
  parse: function (value) {
21
21
  return new Date(value).getTime();
@@ -25,19 +25,11 @@ validateJs.extend(validateJs.validators.datetime, {
25
25
  return new Date(value).toISOString();
26
26
  },
27
27
  });
28
- exports.makeExternalQuery = (appId, json) => __awaiter(void 0, void 0, void 0, function* () {
28
+ exports.getDatasourceAndQuery = (appId, json) => __awaiter(void 0, void 0, void 0, function* () {
29
29
  const datasourceId = json.endpoint.datasourceId;
30
30
  const db = new CouchDB(appId);
31
31
  const datasource = yield db.get(datasourceId);
32
- const Integration = integrations[datasource.source];
33
- // query is the opinionated function
34
- if (Integration.prototype.query) {
35
- const integration = new Integration(datasource.config);
36
- return integration.query(json);
37
- }
38
- else {
39
- throw "Datasource does not support query.";
40
- }
32
+ return makeExternalQuery(datasource, json);
41
33
  });
42
34
  exports.findRow = (ctx, db, tableId, rowId) => __awaiter(void 0, void 0, void 0, function* () {
43
35
  let row;
@@ -73,7 +65,9 @@ exports.validate = ({ appId, tableId, row, table }) => __awaiter(void 0, void 0,
73
65
  }
74
66
  let res;
75
67
  // Validate.js doesn't seem to handle array
76
- if (table.schema[fieldName].type === FieldTypes.ARRAY) {
68
+ if (table.schema[fieldName].type === FieldTypes.ARRAY &&
69
+ row[fieldName] &&
70
+ row[fieldName].length) {
77
71
  row[fieldName].map(val => {
78
72
  if (!constraints.inclusion.includes(val)) {
79
73
  errors[fieldName] = "Field not in list";
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ const CouchDB = require("../../../db");
12
+ const { buildExternalTableId, breakExternalTableId, } = require("../../../integrations/utils");
13
+ const { getTable, generateForeignKey, generateJunctionTableName, foreignKeyStructure, hasTypeChanged, } = require("./utils");
14
+ const { DataSourceOperation, FieldTypes, RelationshipTypes, } = require("../../../constants");
15
+ const { makeExternalQuery } = require("../../../integrations/base/utils");
16
+ const { cloneDeep } = require("lodash/fp");
17
+ const csvParser = require("../../../utilities/csvParser");
18
+ const { handleRequest } = require("../row/external");
19
+ function makeTableRequest(datasource, operation, table, tables, oldTable = null) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ const json = {
22
+ endpoint: {
23
+ datasourceId: datasource._id,
24
+ entityId: table._id,
25
+ operation,
26
+ },
27
+ meta: {
28
+ tables,
29
+ },
30
+ table,
31
+ };
32
+ if (oldTable) {
33
+ json.meta.table = oldTable;
34
+ }
35
+ return makeExternalQuery(datasource, json);
36
+ });
37
+ }
38
+ function cleanupRelationships(table, tables, oldTable = null) {
39
+ const tableToIterate = oldTable ? oldTable : table;
40
+ // clean up relationships in couch table schemas
41
+ for (let [key, schema] of Object.entries(tableToIterate.schema)) {
42
+ if (schema.type === FieldTypes.LINK &&
43
+ (!oldTable || table.schema[key] == null)) {
44
+ const relatedTable = Object.values(tables).find(table => table._id === schema.tableId);
45
+ const foreignKey = schema.foreignKey;
46
+ if (!relatedTable || !foreignKey) {
47
+ continue;
48
+ }
49
+ for (let [relatedKey, relatedSchema] of Object.entries(relatedTable.schema)) {
50
+ if (relatedSchema.type === FieldTypes.LINK &&
51
+ relatedSchema.fieldName === foreignKey) {
52
+ delete relatedTable.schema[relatedKey];
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ function getDatasourceId(table) {
59
+ if (!table) {
60
+ throw "No table supplied";
61
+ }
62
+ if (table.sourceId) {
63
+ return table.sourceId;
64
+ }
65
+ return breakExternalTableId(table._id).datasourceId;
66
+ }
67
+ function otherRelationshipType(type) {
68
+ if (type === RelationshipTypes.MANY_TO_MANY) {
69
+ return RelationshipTypes.MANY_TO_MANY;
70
+ }
71
+ return type === RelationshipTypes.ONE_TO_MANY
72
+ ? RelationshipTypes.MANY_TO_ONE
73
+ : RelationshipTypes.ONE_TO_MANY;
74
+ }
75
+ function generateManyLinkSchema(datasource, column, table, relatedTable) {
76
+ const primary = table.name + table.primary[0];
77
+ const relatedPrimary = relatedTable.name + relatedTable.primary[0];
78
+ const jcTblName = generateJunctionTableName(column, table, relatedTable);
79
+ // first create the new table
80
+ const junctionTable = {
81
+ _id: buildExternalTableId(datasource._id, jcTblName),
82
+ name: jcTblName,
83
+ primary: [primary, relatedPrimary],
84
+ constrained: [primary, relatedPrimary],
85
+ schema: {
86
+ [primary]: foreignKeyStructure(primary, {
87
+ toTable: table.name,
88
+ toKey: table.primary[0],
89
+ }),
90
+ [relatedPrimary]: foreignKeyStructure(relatedPrimary, {
91
+ toTable: relatedTable.name,
92
+ toKey: relatedTable.primary[0],
93
+ }),
94
+ },
95
+ };
96
+ column.through = junctionTable._id;
97
+ column.throughFrom = primary;
98
+ column.throughTo = relatedPrimary;
99
+ column.fieldName = relatedPrimary;
100
+ return junctionTable;
101
+ }
102
+ function generateLinkSchema(column, table, relatedTable, type) {
103
+ const isOneSide = type === RelationshipTypes.ONE_TO_MANY;
104
+ const primary = isOneSide ? relatedTable.primary[0] : table.primary[0];
105
+ // generate a foreign key
106
+ const foreignKey = generateForeignKey(column, relatedTable);
107
+ column.relationshipType = type;
108
+ column.foreignKey = isOneSide ? foreignKey : primary;
109
+ column.fieldName = isOneSide ? primary : foreignKey;
110
+ return foreignKey;
111
+ }
112
+ function generateRelatedSchema(linkColumn, table, relatedTable, columnName) {
113
+ // generate column for other table
114
+ const relatedSchema = cloneDeep(linkColumn);
115
+ // swap them from the main link
116
+ if (linkColumn.foreignKey) {
117
+ relatedSchema.fieldName = linkColumn.foreignKey;
118
+ relatedSchema.foreignKey = linkColumn.fieldName;
119
+ }
120
+ // is many to many
121
+ else {
122
+ // don't need to copy through, already got it
123
+ relatedSchema.fieldName = linkColumn.throughFrom;
124
+ relatedSchema.throughTo = linkColumn.throughFrom;
125
+ relatedSchema.throughFrom = linkColumn.throughTo;
126
+ }
127
+ relatedSchema.relationshipType = otherRelationshipType(linkColumn.relationshipType);
128
+ relatedSchema.tableId = relatedTable._id;
129
+ relatedSchema.name = columnName;
130
+ table.schema[columnName] = relatedSchema;
131
+ }
132
+ function isRelationshipSetup(column) {
133
+ return column.foreignKey || column.through;
134
+ }
135
+ exports.save = function (ctx) {
136
+ return __awaiter(this, void 0, void 0, function* () {
137
+ const appId = ctx.appId;
138
+ const table = ctx.request.body;
139
+ // can't do this right now
140
+ delete table.dataImport;
141
+ const datasourceId = getDatasourceId(ctx.request.body);
142
+ // table doesn't exist already, note that it is created
143
+ if (!table._id) {
144
+ table.created = true;
145
+ }
146
+ let tableToSave = Object.assign({ type: "table", _id: buildExternalTableId(datasourceId, table.name) }, table);
147
+ let oldTable;
148
+ if (ctx.request.body && ctx.request.body._id) {
149
+ oldTable = yield getTable(appId, ctx.request.body._id);
150
+ }
151
+ if (hasTypeChanged(tableToSave, oldTable)) {
152
+ ctx.throw(400, "A column type has changed.");
153
+ }
154
+ const db = new CouchDB(appId);
155
+ const datasource = yield db.get(datasourceId);
156
+ const oldTables = cloneDeep(datasource.entities);
157
+ const tables = datasource.entities;
158
+ const extraTablesToUpdate = [];
159
+ // check if relations need setup
160
+ for (let schema of Object.values(tableToSave.schema)) {
161
+ if (schema.type !== FieldTypes.LINK || isRelationshipSetup(schema)) {
162
+ continue;
163
+ }
164
+ const relatedTable = Object.values(tables).find(table => table._id === schema.tableId);
165
+ const relatedColumnName = schema.fieldName;
166
+ const relationType = schema.relationshipType;
167
+ if (relationType === RelationshipTypes.MANY_TO_MANY) {
168
+ const junctionTable = generateManyLinkSchema(datasource, schema, table, relatedTable);
169
+ if (tables[junctionTable.name]) {
170
+ throw "Junction table already exists, cannot create another relationship.";
171
+ }
172
+ tables[junctionTable.name] = junctionTable;
173
+ extraTablesToUpdate.push(junctionTable);
174
+ }
175
+ else {
176
+ const fkTable = relationType === RelationshipTypes.ONE_TO_MANY ? table : relatedTable;
177
+ const foreignKey = generateLinkSchema(schema, table, relatedTable, relationType);
178
+ fkTable.schema[foreignKey] = foreignKeyStructure(foreignKey);
179
+ if (fkTable.constrained == null) {
180
+ fkTable.constrained = [];
181
+ }
182
+ if (fkTable.constrained.indexOf(foreignKey) === -1) {
183
+ fkTable.constrained.push(foreignKey);
184
+ }
185
+ // foreign key is in other table, need to save it to external
186
+ if (fkTable._id !== table._id) {
187
+ extraTablesToUpdate.push(fkTable);
188
+ }
189
+ }
190
+ generateRelatedSchema(schema, relatedTable, table, relatedColumnName);
191
+ schema.main = true;
192
+ }
193
+ cleanupRelationships(tableToSave, tables, oldTable);
194
+ const operation = oldTable
195
+ ? DataSourceOperation.UPDATE_TABLE
196
+ : DataSourceOperation.CREATE_TABLE;
197
+ yield makeTableRequest(datasource, operation, tableToSave, tables, oldTable);
198
+ // update any extra tables (like foreign keys in other tables)
199
+ for (let extraTable of extraTablesToUpdate) {
200
+ const oldExtraTable = oldTables[extraTable.name];
201
+ let op = oldExtraTable
202
+ ? DataSourceOperation.UPDATE_TABLE
203
+ : DataSourceOperation.CREATE_TABLE;
204
+ yield makeTableRequest(datasource, op, extraTable, tables, oldExtraTable);
205
+ }
206
+ // make sure the constrained list, all still exist
207
+ if (Array.isArray(tableToSave.constrained)) {
208
+ tableToSave.constrained = tableToSave.constrained.filter(constraint => Object.keys(tableToSave.schema).includes(constraint));
209
+ }
210
+ // store it into couch now for budibase reference
211
+ datasource.entities[tableToSave.name] = tableToSave;
212
+ yield db.put(datasource);
213
+ return tableToSave;
214
+ });
215
+ };
216
+ exports.destroy = function (ctx) {
217
+ return __awaiter(this, void 0, void 0, function* () {
218
+ const appId = ctx.appId;
219
+ const tableToDelete = yield getTable(appId, ctx.params.tableId);
220
+ if (!tableToDelete || !tableToDelete.created) {
221
+ ctx.throw(400, "Cannot delete tables which weren't created in Budibase.");
222
+ }
223
+ const datasourceId = getDatasourceId(tableToDelete);
224
+ const db = new CouchDB(appId);
225
+ const datasource = yield db.get(datasourceId);
226
+ const tables = datasource.entities;
227
+ const operation = DataSourceOperation.DELETE_TABLE;
228
+ yield makeTableRequest(datasource, operation, tableToDelete, tables);
229
+ cleanupRelationships(tableToDelete, tables);
230
+ delete datasource.entities[tableToDelete.name];
231
+ yield db.put(datasource);
232
+ return tableToDelete;
233
+ });
234
+ };
235
+ exports.bulkImport = function (ctx) {
236
+ return __awaiter(this, void 0, void 0, function* () {
237
+ const appId = ctx.appId;
238
+ const table = yield getTable(appId, ctx.params.tableId);
239
+ const { dataImport } = ctx.request.body;
240
+ if (!dataImport || !dataImport.schema || !dataImport.csvString) {
241
+ ctx.throw(400, "Provided data import information is invalid.");
242
+ }
243
+ const rows = yield csvParser.transform(Object.assign(Object.assign({}, dataImport), { existingTable: table }));
244
+ yield handleRequest(appId, DataSourceOperation.BULK_CREATE, table._id, {
245
+ rows,
246
+ });
247
+ return table;
248
+ });
249
+ };