@budibase/server 0.9.184 → 0.9.185-alpha.11

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 (290) hide show
  1. package/Dockerfile +1 -1
  2. package/__mocks__/mssql.ts +1 -1
  3. package/__mocks__/pg.ts +3 -0
  4. package/builder/assets/bb-space-man.5be51a45.svg +290 -0
  5. package/builder/assets/index.053c6f7a.js +1321 -0
  6. package/builder/assets/index.4a7c5636.css +1 -0
  7. package/builder/assets/vendor.470042a4.js +152 -0
  8. package/builder/assets/vendor.5e1fe644.css +1 -0
  9. package/builder/index.html +4 -4
  10. package/coverage/clover.xml +1357 -959
  11. package/coverage/coverage-final.json +91 -87
  12. package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
  13. package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
  14. package/coverage/lcov-report/api/controllers/application.js.html +65 -14
  15. package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
  16. package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
  17. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  20. package/coverage/lcov-report/api/controllers/datasource.js.html +147 -27
  21. package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
  22. package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
  23. package/coverage/lcov-report/api/controllers/index.html +90 -90
  24. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
  26. package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
  27. package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
  28. package/coverage/lcov-report/api/controllers/query.js.html +53 -209
  29. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  30. package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
  31. package/coverage/lcov-report/api/controllers/row/external.js.html +12 -6
  32. package/coverage/lcov-report/api/controllers/row/index.html +26 -26
  33. package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
  34. package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
  35. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
  36. package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
  37. package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
  38. package/coverage/lcov-report/api/controllers/script.js.html +3 -3
  39. package/coverage/lcov-report/api/controllers/table/external.js.html +980 -0
  40. package/coverage/lcov-report/api/controllers/table/index.html +56 -26
  41. package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
  42. package/coverage/lcov-report/api/controllers/table/internal.js.html +545 -0
  43. package/coverage/lcov-report/api/controllers/table/utils.js.html +172 -49
  44. package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
  45. package/coverage/lcov-report/api/controllers/user.js.html +390 -33
  46. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.html +9 -9
  48. package/coverage/lcov-report/api/controllers/view/index.js.html +5 -5
  49. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  50. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
  51. package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
  52. package/coverage/lcov-report/api/index.html +1 -1
  53. package/coverage/lcov-report/api/index.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/dev.js.html +2 -2
  65. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/index.html +4 -4
  67. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/query.js.html +5 -2
  73. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/static.js.html +2 -2
  79. package/coverage/lcov-report/api/routes/table.js.html +35 -2
  80. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/user.js.html +17 -2
  82. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  84. package/coverage/lcov-report/automations/actions.js.html +2 -2
  85. package/coverage/lcov-report/automations/automationUtils.js.html +3 -3
  86. package/coverage/lcov-report/automations/bullboard.js.html +71 -20
  87. package/coverage/lcov-report/automations/index.html +33 -48
  88. package/coverage/lcov-report/automations/index.js.html +2 -2
  89. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
  94. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
  96. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/index.html +14 -14
  98. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
  100. package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
  101. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
  106. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  108. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  109. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  111. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  115. package/coverage/lcov-report/automations/triggers.js.html +22 -10
  116. package/coverage/lcov-report/automations/utils.js.html +42 -12
  117. package/coverage/lcov-report/constants/index.html +5 -5
  118. package/coverage/lcov-report/constants/index.js.html +49 -4
  119. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  120. package/coverage/lcov-report/constants/screens.js.html +1 -1
  121. package/coverage/lcov-report/db/client.js.html +2 -2
  122. package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
  123. package/coverage/lcov-report/db/index.html +2 -2
  124. package/coverage/lcov-report/db/index.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
  126. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  127. package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
  128. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
  129. package/coverage/lcov-report/db/newid.js.html +1 -1
  130. package/coverage/lcov-report/db/utils.js.html +1 -1
  131. package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
  132. package/coverage/lcov-report/events/index.html +6 -6
  133. package/coverage/lcov-report/events/index.js.html +1 -1
  134. package/coverage/lcov-report/events/utils.js.html +5 -5
  135. package/coverage/lcov-report/index.html +98 -83
  136. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  137. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  138. package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
  139. package/coverage/lcov-report/middleware/authorized.js.html +11 -8
  140. package/coverage/lcov-report/middleware/builder.js.html +16 -7
  141. package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
  142. package/coverage/lcov-report/middleware/index.html +23 -23
  143. package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
  144. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  145. package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
  146. package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
  147. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  148. package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +83 -32
  149. package/coverage/lcov-report/threads/index.html +141 -0
  150. package/coverage/lcov-report/threads/index.js.html +260 -0
  151. package/coverage/lcov-report/threads/query.js.html +269 -0
  152. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  153. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  154. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  155. package/coverage/lcov-report/utilities/csvParser.js.html +144 -15
  156. package/coverage/lcov-report/utilities/global.js.html +26 -11
  157. package/coverage/lcov-report/utilities/index.html +49 -49
  158. package/coverage/lcov-report/utilities/index.js.html +65 -17
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
  160. package/coverage/lcov-report/utilities/queue/index.html +14 -14
  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 +4 -4
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
  167. package/coverage/lcov-report/utilities/security.js.html +3 -3
  168. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  169. package/coverage/lcov-report/utilities/users.js.html +1 -1
  170. package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
  171. package/coverage/lcov.info +2301 -1599
  172. package/dist/api/controllers/application.js +16 -2
  173. package/dist/api/controllers/auth.js +3 -3
  174. package/dist/api/controllers/datasource.js +47 -16
  175. package/dist/api/controllers/deploy/index.js +2 -0
  176. package/dist/api/controllers/dev.js +4 -1
  177. package/dist/api/controllers/query.js +30 -58
  178. package/dist/api/controllers/row/ExternalRequest.js +37 -14
  179. package/dist/api/controllers/row/external.js +1 -0
  180. package/dist/api/controllers/row/utils.js +6 -12
  181. package/dist/api/controllers/static/index.js +1 -1
  182. package/dist/api/controllers/table/external.js +242 -0
  183. package/dist/api/controllers/table/index.js +49 -123
  184. package/dist/api/controllers/table/internal.js +150 -0
  185. package/dist/api/controllers/table/utils.js +62 -28
  186. package/dist/api/controllers/user.js +123 -11
  187. package/dist/api/routes/query.js +1 -1
  188. package/dist/api/routes/table.js +7 -1
  189. package/dist/api/routes/user.js +2 -1
  190. package/dist/app.js +2 -11
  191. package/dist/automations/bullboard.js +37 -10
  192. package/dist/automations/triggers.js +7 -3
  193. package/dist/automations/utils.js +11 -2
  194. package/dist/constants/index.js +13 -0
  195. package/dist/definitions/datasource.js +4 -0
  196. package/dist/integrations/base/IntegrationBase.js +2 -0
  197. package/dist/integrations/base/datasourcePlus.js +2 -0
  198. package/dist/integrations/base/sql.js +334 -180
  199. package/dist/integrations/base/sqlTable.js +143 -0
  200. package/dist/integrations/base/utils.js +30 -0
  201. package/dist/integrations/microsoftSqlServer.js +117 -9
  202. package/dist/integrations/mysql.js +14 -84
  203. package/dist/integrations/postgres.js +35 -28
  204. package/dist/integrations/utils.js +56 -9
  205. package/dist/middleware/authorized.js +2 -1
  206. package/dist/middleware/builder.js +4 -1
  207. package/dist/package.json +7 -6
  208. package/dist/tests/utilities/TestConfiguration.js +2 -1
  209. package/dist/{automations/thread.js → threads/automation.js} +23 -7
  210. package/dist/threads/index.js +58 -0
  211. package/dist/threads/query.js +61 -0
  212. package/dist/tsconfig.tsbuildinfo +1 -1
  213. package/dist/utilities/csvParser.js +46 -5
  214. package/dist/utilities/global.js +6 -2
  215. package/dist/utilities/index.js +18 -2
  216. package/dist/utilities/queue/inMemoryQueue.js +8 -0
  217. package/dist/utilities/scriptRunner.js +4 -1
  218. package/package.json +8 -7
  219. package/scripts/integrations/mssql/data/Dockerfile +9 -0
  220. package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
  221. package/scripts/integrations/mssql/data/setup.sql +54 -0
  222. package/scripts/integrations/mssql/docker-compose.yaml +12 -0
  223. package/scripts/integrations/mssql/reset.sh +3 -0
  224. package/scripts/likeCypress.ts +33 -0
  225. package/src/api/controllers/application.js +19 -2
  226. package/src/api/controllers/auth.js +3 -0
  227. package/src/api/controllers/datasource.js +56 -16
  228. package/src/api/controllers/deploy/index.js +2 -0
  229. package/src/api/controllers/dev.js +4 -1
  230. package/src/api/controllers/query.js +29 -81
  231. package/src/api/controllers/row/ExternalRequest.ts +47 -16
  232. package/src/api/controllers/row/external.js +2 -0
  233. package/src/api/controllers/row/utils.js +8 -11
  234. package/src/api/controllers/static/index.js +1 -1
  235. package/src/api/controllers/table/external.js +300 -0
  236. package/src/api/controllers/table/index.js +47 -137
  237. package/src/api/controllers/table/internal.js +155 -0
  238. package/src/api/controllers/table/utils.js +74 -33
  239. package/src/api/controllers/user.js +132 -13
  240. package/src/api/routes/query.js +1 -0
  241. package/src/api/routes/table.js +11 -0
  242. package/src/api/routes/tests/datasource.spec.js +2 -2
  243. package/src/api/routes/tests/misc.spec.js +5 -1
  244. package/src/api/routes/tests/query.spec.js +0 -1
  245. package/src/api/routes/user.js +5 -0
  246. package/src/app.ts +2 -10
  247. package/src/automations/bullboard.js +28 -11
  248. package/src/automations/tests/automation.spec.js +3 -4
  249. package/src/automations/triggers.js +7 -3
  250. package/src/automations/utils.js +12 -2
  251. package/src/constants/index.js +15 -0
  252. package/src/definitions/common.ts +7 -1
  253. package/src/definitions/datasource.ts +9 -3
  254. package/src/integrations/airtable.ts +2 -1
  255. package/src/integrations/arangodb.ts +2 -1
  256. package/src/integrations/base/IntegrationBase.ts +6 -0
  257. package/src/integrations/base/datasourcePlus.ts +9 -0
  258. package/src/integrations/base/sql.ts +359 -222
  259. package/src/integrations/base/sqlTable.ts +180 -0
  260. package/src/integrations/base/utils.ts +22 -0
  261. package/src/integrations/couchdb.ts +2 -1
  262. package/src/integrations/dynamodb.ts +2 -1
  263. package/src/integrations/elasticsearch.ts +2 -1
  264. package/src/integrations/microsoftSqlServer.ts +145 -13
  265. package/src/integrations/mongodb.ts +2 -1
  266. package/src/integrations/mysql.ts +20 -94
  267. package/src/integrations/postgres.ts +45 -35
  268. package/src/integrations/rest.ts +2 -1
  269. package/src/integrations/s3.ts +2 -1
  270. package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
  271. package/src/integrations/tests/postgres.spec.js +4 -0
  272. package/src/integrations/utils.ts +60 -8
  273. package/src/middleware/authorized.js +2 -1
  274. package/src/middleware/builder.js +4 -1
  275. package/src/tests/utilities/TestConfiguration.js +2 -1
  276. package/src/{automations/thread.js → threads/automation.js} +24 -7
  277. package/src/threads/index.js +60 -0
  278. package/src/threads/query.js +63 -0
  279. package/src/utilities/csvParser.js +48 -5
  280. package/src/utilities/global.js +7 -2
  281. package/src/utilities/index.js +18 -2
  282. package/src/utilities/queue/inMemoryQueue.js +7 -0
  283. package/src/utilities/scriptRunner.js +4 -1
  284. package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
  285. package/src/utilities/tests/csvParser.spec.js +3 -0
  286. package/tsconfig.json +1 -1
  287. package/builder/assets/index.34964222.js +0 -201
  288. package/builder/assets/index.7469e1e4.css +0 -29
  289. package/builder/assets/vendor.278a305c.js +0 -9
  290. package/builder/assets/vendor.d75d5eb7.css +0 -1
@@ -0,0 +1,242 @@
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
140
+ delete table.dataImport;
141
+ const datasourceId = getDatasourceId(ctx.request.body);
142
+ let tableToSave = Object.assign({ type: "table", _id: buildExternalTableId(datasourceId, table.name) }, table);
143
+ let oldTable;
144
+ if (ctx.request.body && ctx.request.body._id) {
145
+ oldTable = yield getTable(appId, ctx.request.body._id);
146
+ }
147
+ if (hasTypeChanged(tableToSave, oldTable)) {
148
+ ctx.throw(400, "A column type has changed.");
149
+ }
150
+ const db = new CouchDB(appId);
151
+ const datasource = yield db.get(datasourceId);
152
+ const oldTables = cloneDeep(datasource.entities);
153
+ const tables = datasource.entities;
154
+ const extraTablesToUpdate = [];
155
+ // check if relations need setup
156
+ for (let schema of Object.values(tableToSave.schema)) {
157
+ if (schema.type !== FieldTypes.LINK || isRelationshipSetup(schema)) {
158
+ continue;
159
+ }
160
+ const relatedTable = Object.values(tables).find(table => table._id === schema.tableId);
161
+ const relatedColumnName = schema.fieldName;
162
+ const relationType = schema.relationshipType;
163
+ if (relationType === RelationshipTypes.MANY_TO_MANY) {
164
+ const junctionTable = generateManyLinkSchema(datasource, schema, table, relatedTable);
165
+ if (tables[junctionTable.name]) {
166
+ throw "Junction table already exists, cannot create another relationship.";
167
+ }
168
+ tables[junctionTable.name] = junctionTable;
169
+ extraTablesToUpdate.push(junctionTable);
170
+ }
171
+ else {
172
+ const fkTable = relationType === RelationshipTypes.ONE_TO_MANY ? table : relatedTable;
173
+ const foreignKey = generateLinkSchema(schema, table, relatedTable, relationType);
174
+ fkTable.schema[foreignKey] = foreignKeyStructure(foreignKey);
175
+ if (fkTable.constrained == null) {
176
+ fkTable.constrained = [];
177
+ }
178
+ if (fkTable.constrained.indexOf(foreignKey) === -1) {
179
+ fkTable.constrained.push(foreignKey);
180
+ }
181
+ // foreign key is in other table, need to save it to external
182
+ if (fkTable._id !== table._id) {
183
+ extraTablesToUpdate.push(fkTable);
184
+ }
185
+ }
186
+ generateRelatedSchema(schema, relatedTable, table, relatedColumnName);
187
+ schema.main = true;
188
+ }
189
+ cleanupRelationships(tableToSave, tables, oldTable);
190
+ const operation = oldTable
191
+ ? DataSourceOperation.UPDATE_TABLE
192
+ : DataSourceOperation.CREATE_TABLE;
193
+ yield makeTableRequest(datasource, operation, tableToSave, tables, oldTable);
194
+ // update any extra tables (like foreign keys in other tables)
195
+ for (let extraTable of extraTablesToUpdate) {
196
+ const oldExtraTable = oldTables[extraTable.name];
197
+ let op = oldExtraTable
198
+ ? DataSourceOperation.UPDATE_TABLE
199
+ : DataSourceOperation.CREATE_TABLE;
200
+ yield makeTableRequest(datasource, op, extraTable, tables, oldExtraTable);
201
+ }
202
+ // make sure the constrained list, all still exist
203
+ if (Array.isArray(tableToSave.constrained)) {
204
+ tableToSave.constrained = tableToSave.constrained.filter(constraint => Object.keys(tableToSave.schema).includes(constraint));
205
+ }
206
+ // store it into couch now for budibase reference
207
+ datasource.entities[tableToSave.name] = tableToSave;
208
+ yield db.put(datasource);
209
+ return tableToSave;
210
+ });
211
+ };
212
+ exports.destroy = function (ctx) {
213
+ return __awaiter(this, void 0, void 0, function* () {
214
+ const appId = ctx.appId;
215
+ const tableToDelete = yield getTable(appId, ctx.params.tableId);
216
+ const datasourceId = getDatasourceId(tableToDelete);
217
+ const db = new CouchDB(appId);
218
+ const datasource = yield db.get(datasourceId);
219
+ const tables = datasource.entities;
220
+ const operation = DataSourceOperation.DELETE_TABLE;
221
+ yield makeTableRequest(datasource, operation, tableToDelete, tables);
222
+ cleanupRelationships(tableToDelete, tables);
223
+ delete datasource.entities[tableToDelete.name];
224
+ yield db.put(datasource);
225
+ return tableToDelete;
226
+ });
227
+ };
228
+ exports.bulkImport = function (ctx) {
229
+ return __awaiter(this, void 0, void 0, function* () {
230
+ const appId = ctx.appId;
231
+ const table = yield getTable(appId, ctx.params.tableId);
232
+ const { dataImport } = ctx.request.body;
233
+ if (!dataImport || !dataImport.schema || !dataImport.csvString) {
234
+ ctx.throw(400, "Provided data import information is invalid.");
235
+ }
236
+ const rows = yield csvParser.transform(Object.assign(Object.assign({}, dataImport), { existingTable: table }));
237
+ yield handleRequest(appId, DataSourceOperation.BULK_CREATE, table._id, {
238
+ rows,
239
+ });
240
+ return table;
241
+ });
242
+ };
@@ -8,23 +8,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __rest = (this && this.__rest) || function (s, e) {
12
- var t = {};
13
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
- t[p] = s[p];
15
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
- t[p[i]] = s[p[i]];
19
- }
20
- return t;
21
- };
22
11
  const CouchDB = require("../../../db");
23
- const linkRows = require("../../../db/linkedRows");
12
+ const internal = require("./internal");
13
+ const external = require("./external");
24
14
  const csvParser = require("../../../utilities/csvParser");
25
- const { getRowParams, getTableParams, generateTableID, getDatasourceParams, BudibaseInternalDB, } = require("../../../db/utils");
26
- const { FieldTypes } = require("../../../constants");
27
- const { TableSaveFunctions, getTable } = require("./utils");
15
+ const { isExternalTable } = require("../../../integrations/utils");
16
+ const { getTableParams, getDatasourceParams, BudibaseInternalDB, } = require("../../../db/utils");
17
+ const { getTable } = require("./utils");
18
+ function pickApi({ tableId, table }) {
19
+ if (table && !tableId) {
20
+ tableId = table._id;
21
+ }
22
+ if (table && table.type === "external") {
23
+ return external;
24
+ }
25
+ else if (tableId && isExternalTable(tableId)) {
26
+ return external;
27
+ }
28
+ return internal;
29
+ }
30
+ // covers both internal and external
28
31
  exports.fetch = function (ctx) {
29
32
  return __awaiter(this, void 0, void 0, function* () {
30
33
  const db = new CouchDB(ctx.appId);
@@ -50,126 +53,49 @@ exports.find = function (ctx) {
50
53
  exports.save = function (ctx) {
51
54
  return __awaiter(this, void 0, void 0, function* () {
52
55
  const appId = ctx.appId;
53
- const db = new CouchDB(appId);
54
- const _a = ctx.request.body, { dataImport } = _a, rest = __rest(_a, ["dataImport"]);
55
- let tableToSave = Object.assign({ type: "table", _id: generateTableID(), views: {} }, rest);
56
- // if the table obj had an _id then it will have been retrieved
57
- let oldTable;
58
- if (ctx.request.body && ctx.request.body._id) {
59
- oldTable = yield db.get(ctx.request.body._id);
60
- }
61
- // saving a table is a complex operation, involving many different steps, this
62
- // has been broken out into a utility to make it more obvious/easier to manipulate
63
- const tableSaveFunctions = new TableSaveFunctions({
64
- db,
65
- ctx,
66
- oldTable,
67
- dataImport,
68
- });
69
- tableToSave = yield tableSaveFunctions.before(tableToSave);
70
- // make sure that types don't change of a column, have to remove
71
- // the column if you want to change the type
72
- if (oldTable && oldTable.schema) {
73
- for (let propKey of Object.keys(tableToSave.schema)) {
74
- let column = tableToSave.schema[propKey];
75
- let oldColumn = oldTable.schema[propKey];
76
- if (oldColumn && oldColumn.type === "internal") {
77
- oldColumn.type = "auto";
78
- }
79
- if (oldColumn && oldColumn.type !== column.type) {
80
- ctx.throw(400, "Cannot change the type of a column");
81
- }
82
- }
83
- }
84
- // Don't rename if the name is the same
85
- let { _rename } = tableToSave;
86
- /* istanbul ignore next */
87
- if (_rename && _rename.old === _rename.updated) {
88
- _rename = null;
89
- delete tableToSave._rename;
90
- }
91
- // rename row fields when table column is renamed
92
- /* istanbul ignore next */
93
- if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
94
- ctx.throw(400, "Cannot rename a linked column.");
95
- }
96
- tableToSave = yield tableSaveFunctions.mid(tableToSave);
97
- // update schema of non-statistics views when new columns are added
98
- for (let view in tableToSave.views) {
99
- const tableView = tableToSave.views[view];
100
- if (!tableView)
101
- continue;
102
- if (tableView.schema.group || tableView.schema.field)
103
- continue;
104
- tableView.schema = tableToSave.schema;
105
- }
106
- // update linked rows
107
- try {
108
- const linkResp = yield linkRows.updateLinks({
109
- appId,
110
- eventType: oldTable
111
- ? linkRows.EventType.TABLE_UPDATED
112
- : linkRows.EventType.TABLE_SAVE,
113
- table: tableToSave,
114
- oldTable: oldTable,
115
- });
116
- if (linkResp != null && linkResp._rev) {
117
- tableToSave._rev = linkResp._rev;
118
- }
119
- }
120
- catch (err) {
121
- ctx.throw(400, err);
122
- }
123
- // don't perform any updates until relationships have been
124
- // checked by the updateLinks function
125
- const updatedRows = tableSaveFunctions.getUpdatedRows();
126
- if (updatedRows && updatedRows.length !== 0) {
127
- yield db.bulkDocs(updatedRows);
128
- }
129
- const result = yield db.put(tableToSave);
130
- tableToSave._rev = result.rev;
131
- tableToSave = yield tableSaveFunctions.after(tableToSave);
132
- ctx.eventEmitter &&
133
- ctx.eventEmitter.emitTable(`table:save`, appId, tableToSave);
56
+ const table = ctx.request.body;
57
+ const savedTable = yield pickApi({ table }).save(ctx);
134
58
  ctx.status = 200;
135
- ctx.message = `Table ${ctx.request.body.name} saved successfully.`;
136
- ctx.body = tableToSave;
59
+ ctx.message = `Table ${table.name} saved successfully.`;
60
+ ctx.eventEmitter &&
61
+ ctx.eventEmitter.emitTable(`table:save`, appId, savedTable);
62
+ ctx.body = savedTable;
137
63
  });
138
64
  };
139
65
  exports.destroy = function (ctx) {
140
66
  return __awaiter(this, void 0, void 0, function* () {
141
67
  const appId = ctx.appId;
142
- const db = new CouchDB(appId);
143
- const tableToDelete = yield db.get(ctx.params.tableId);
144
- // Delete all rows for that table
145
- const rows = yield db.allDocs(getRowParams(ctx.params.tableId, null, {
146
- include_docs: true,
147
- }));
148
- yield db.bulkDocs(rows.rows.map(row => (Object.assign(Object.assign({}, row.doc), { _deleted: true }))));
149
- // update linked rows
150
- yield linkRows.updateLinks({
151
- appId,
152
- eventType: linkRows.EventType.TABLE_DELETE,
153
- table: tableToDelete,
154
- });
155
- // don't remove the table itself until very end
156
- yield db.remove(tableToDelete);
157
- // remove table search index
158
- const currentIndexes = yield db.getIndexes();
159
- const existingIndex = currentIndexes.indexes.find(existing => existing.name === `search:${ctx.params.tableId}`);
160
- if (existingIndex) {
161
- yield db.deleteIndex(existingIndex);
162
- }
68
+ const tableId = ctx.params.tableId;
69
+ const deletedTable = yield pickApi({ tableId }).destroy(ctx);
163
70
  ctx.eventEmitter &&
164
- ctx.eventEmitter.emitTable(`table:delete`, appId, tableToDelete);
71
+ ctx.eventEmitter.emitTable(`table:delete`, appId, deletedTable);
165
72
  ctx.status = 200;
166
- ctx.body = { message: `Table ${ctx.params.tableId} deleted.` };
73
+ ctx.body = { message: `Table ${tableId} deleted.` };
74
+ });
75
+ };
76
+ exports.bulkImport = function (ctx) {
77
+ return __awaiter(this, void 0, void 0, function* () {
78
+ const tableId = ctx.params.tableId;
79
+ yield pickApi({ tableId }).bulkImport(ctx);
80
+ // right now we don't trigger anything for bulk import because it
81
+ // can only be done in the builder, but in the future we may need to
82
+ // think about events for bulk items
83
+ ctx.status = 200;
84
+ ctx.body = { message: `Bulk rows created.` };
167
85
  });
168
86
  };
169
87
  exports.validateCSVSchema = function (ctx) {
170
88
  return __awaiter(this, void 0, void 0, function* () {
171
- const { csvString, schema = {} } = ctx.request.body;
172
- const result = yield csvParser.parse(csvString, schema);
89
+ // tableId being specified means its an import to an existing table
90
+ const { csvString, schema = {}, tableId } = ctx.request.body;
91
+ let existingTable;
92
+ if (tableId) {
93
+ existingTable = yield getTable(ctx.appId, tableId);
94
+ }
95
+ let result = yield csvParser.parse(csvString, schema);
96
+ if (existingTable) {
97
+ result = csvParser.updateSchema({ schema: result, existingTable });
98
+ }
173
99
  ctx.body = { schema: result };
174
100
  });
175
101
  };
@@ -0,0 +1,150 @@
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
+ var __rest = (this && this.__rest) || function (s, e) {
12
+ var t = {};
13
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
14
+ t[p] = s[p];
15
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
16
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
17
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
18
+ t[p[i]] = s[p[i]];
19
+ }
20
+ return t;
21
+ };
22
+ const CouchDB = require("../../../db");
23
+ const linkRows = require("../../../db/linkedRows");
24
+ const { getRowParams, generateTableID } = require("../../../db/utils");
25
+ const { FieldTypes } = require("../../../constants");
26
+ const { TableSaveFunctions, hasTypeChanged, getTable, handleDataImport, } = require("./utils");
27
+ exports.save = function (ctx) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const appId = ctx.appId;
30
+ const db = new CouchDB(appId);
31
+ const _a = ctx.request.body, { dataImport } = _a, rest = __rest(_a, ["dataImport"]);
32
+ let tableToSave = Object.assign({ type: "table", _id: generateTableID(), views: {} }, rest);
33
+ // if the table obj had an _id then it will have been retrieved
34
+ let oldTable;
35
+ if (ctx.request.body && ctx.request.body._id) {
36
+ oldTable = yield db.get(ctx.request.body._id);
37
+ }
38
+ if (hasTypeChanged(tableToSave, oldTable)) {
39
+ ctx.throw(400, "A column type has changed.");
40
+ }
41
+ // saving a table is a complex operation, involving many different steps, this
42
+ // has been broken out into a utility to make it more obvious/easier to manipulate
43
+ const tableSaveFunctions = new TableSaveFunctions({
44
+ db,
45
+ ctx,
46
+ oldTable,
47
+ dataImport,
48
+ });
49
+ tableToSave = yield tableSaveFunctions.before(tableToSave);
50
+ // make sure that types don't change of a column, have to remove
51
+ // the column if you want to change the type
52
+ if (oldTable && oldTable.schema) {
53
+ for (let propKey of Object.keys(tableToSave.schema)) {
54
+ let column = tableToSave.schema[propKey];
55
+ let oldColumn = oldTable.schema[propKey];
56
+ if (oldColumn && oldColumn.type === "internal") {
57
+ oldColumn.type = "auto";
58
+ }
59
+ if (oldColumn && oldColumn.type !== column.type) {
60
+ ctx.throw(400, "Cannot change the type of a column");
61
+ }
62
+ }
63
+ }
64
+ // Don't rename if the name is the same
65
+ let { _rename } = tableToSave;
66
+ /* istanbul ignore next */
67
+ if (_rename && _rename.old === _rename.updated) {
68
+ _rename = null;
69
+ delete tableToSave._rename;
70
+ }
71
+ // rename row fields when table column is renamed
72
+ /* istanbul ignore next */
73
+ if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
74
+ ctx.throw(400, "Cannot rename a linked column.");
75
+ }
76
+ tableToSave = yield tableSaveFunctions.mid(tableToSave);
77
+ // update schema of non-statistics views when new columns are added
78
+ for (let view in tableToSave.views) {
79
+ const tableView = tableToSave.views[view];
80
+ if (!tableView)
81
+ continue;
82
+ if (tableView.schema.group || tableView.schema.field)
83
+ continue;
84
+ tableView.schema = tableToSave.schema;
85
+ }
86
+ // update linked rows
87
+ try {
88
+ const linkResp = yield linkRows.updateLinks({
89
+ appId,
90
+ eventType: oldTable
91
+ ? linkRows.EventType.TABLE_UPDATED
92
+ : linkRows.EventType.TABLE_SAVE,
93
+ table: tableToSave,
94
+ oldTable: oldTable,
95
+ });
96
+ if (linkResp != null && linkResp._rev) {
97
+ tableToSave._rev = linkResp._rev;
98
+ }
99
+ }
100
+ catch (err) {
101
+ ctx.throw(400, err);
102
+ }
103
+ // don't perform any updates until relationships have been
104
+ // checked by the updateLinks function
105
+ const updatedRows = tableSaveFunctions.getUpdatedRows();
106
+ if (updatedRows && updatedRows.length !== 0) {
107
+ yield db.bulkDocs(updatedRows);
108
+ }
109
+ const result = yield db.put(tableToSave);
110
+ tableToSave._rev = result.rev;
111
+ tableToSave = yield tableSaveFunctions.after(tableToSave);
112
+ return tableToSave;
113
+ });
114
+ };
115
+ exports.destroy = function (ctx) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const appId = ctx.appId;
118
+ const db = new CouchDB(appId);
119
+ const tableToDelete = yield db.get(ctx.params.tableId);
120
+ // Delete all rows for that table
121
+ const rows = yield db.allDocs(getRowParams(ctx.params.tableId, null, {
122
+ include_docs: true,
123
+ }));
124
+ yield db.bulkDocs(rows.rows.map(row => (Object.assign(Object.assign({}, row.doc), { _deleted: true }))));
125
+ // update linked rows
126
+ yield linkRows.updateLinks({
127
+ appId,
128
+ eventType: linkRows.EventType.TABLE_DELETE,
129
+ table: tableToDelete,
130
+ });
131
+ // don't remove the table itself until very end
132
+ yield db.remove(tableToDelete);
133
+ // remove table search index
134
+ const currentIndexes = yield db.getIndexes();
135
+ const existingIndex = currentIndexes.indexes.find(existing => existing.name === `search:${ctx.params.tableId}`);
136
+ if (existingIndex) {
137
+ yield db.deleteIndex(existingIndex);
138
+ }
139
+ return tableToDelete;
140
+ });
141
+ };
142
+ exports.bulkImport = function (ctx) {
143
+ return __awaiter(this, void 0, void 0, function* () {
144
+ const appId = ctx.appId;
145
+ const table = yield getTable(appId, ctx.params.tableId);
146
+ const { dataImport } = ctx.request.body;
147
+ yield handleDataImport(appId, ctx.user, table, dataImport);
148
+ return table;
149
+ });
150
+ };