@budibase/server 1.0.26 → 1.0.27-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 (258) hide show
  1. package/__mocks__/node-fetch.ts +21 -0
  2. package/builder/assets/bb-spaceship.8f6e81e1.svg +227 -0
  3. package/builder/assets/{index.4fb3f887.css → index.0dce895b.css} +1 -1
  4. package/builder/assets/index.b98dd7ca.js +1348 -0
  5. package/builder/assets/{vendor.470042a4.js → vendor.f9faf6ab.js} +88 -88
  6. package/builder/index.html +3 -3
  7. package/coverage/clover.xml +1364 -1121
  8. package/coverage/coverage-final.json +37 -36
  9. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/application.js.html +59 -59
  12. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/automation.js.html +22 -10
  14. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  17. package/coverage/lcov-report/api/controllers/datasource.js.html +170 -68
  18. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/index.html +39 -54
  21. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/query/index.html +126 -0
  26. package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +225 -114
  27. package/coverage/lcov-report/api/controllers/query/validation.js.html +206 -0
  28. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/index.html +22 -22
  32. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/internal.js.html +38 -11
  34. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +7 -4
  35. package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -20
  36. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/user.js.html +108 -9
  45. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  49. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/webhook.js.html +18 -6
  51. package/coverage/lcov-report/api/index.html +1 -1
  52. package/coverage/lcov-report/api/index.js.html +5 -5
  53. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/index.html +9 -9
  66. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/query.js.html +19 -85
  72. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/user.js.html +32 -2
  81. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  83. package/coverage/lcov-report/automations/actions.js.html +1 -1
  84. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  85. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  86. package/coverage/lcov-report/automations/index.html +20 -20
  87. package/coverage/lcov-report/automations/index.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/executeQuery.js.html +31 -7
  94. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/index.html +11 -11
  97. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +5 -8
  99. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  113. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  114. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  115. package/coverage/lcov-report/automations/utils.js.html +48 -15
  116. package/coverage/lcov-report/constants/index.html +1 -1
  117. package/coverage/lcov-report/constants/index.js.html +22 -22
  118. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  119. package/coverage/lcov-report/constants/screens.js.html +1 -1
  120. package/coverage/lcov-report/db/client.js.html +18 -18
  121. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  122. package/coverage/lcov-report/db/index.html +15 -15
  123. package/coverage/lcov-report/db/index.js.html +3 -3
  124. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  126. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  128. package/coverage/lcov-report/db/newid.js.html +4 -4
  129. package/coverage/lcov-report/db/utils.js.html +107 -80
  130. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  131. package/coverage/lcov-report/events/index.html +1 -1
  132. package/coverage/lcov-report/events/index.js.html +1 -1
  133. package/coverage/lcov-report/events/utils.js.html +1 -1
  134. package/coverage/lcov-report/index.html +99 -84
  135. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  136. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  137. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  138. package/coverage/lcov-report/middleware/authorized.js.html +10 -10
  139. package/coverage/lcov-report/middleware/builder.js.html +8 -8
  140. package/coverage/lcov-report/middleware/currentapp.js.html +28 -28
  141. package/coverage/lcov-report/middleware/index.html +1 -1
  142. package/coverage/lcov-report/middleware/joi-validator.js.html +11 -11
  143. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  144. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  145. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  146. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  147. package/coverage/lcov-report/threads/automation.js.html +1 -1
  148. package/coverage/lcov-report/threads/index.html +31 -31
  149. package/coverage/lcov-report/threads/index.js.html +12 -12
  150. package/coverage/lcov-report/threads/query.js.html +396 -69
  151. package/coverage/lcov-report/threads/utils.js.html +358 -13
  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 +1 -1
  156. package/coverage/lcov-report/utilities/global.js.html +13 -13
  157. package/coverage/lcov-report/utilities/index.html +19 -19
  158. package/coverage/lcov-report/utilities/index.js.html +69 -36
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  160. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  161. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  162. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.html +19 -19
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +235 -10
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  167. package/coverage/lcov-report/utilities/security.js.html +2 -2
  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 +19 -19
  171. package/coverage/lcov.info +2294 -1874
  172. package/dist/api/controllers/automation.js +7 -5
  173. package/dist/api/controllers/datasource.js +29 -0
  174. package/dist/api/controllers/query/import/index.js +79 -0
  175. package/dist/api/controllers/query/import/sources/base/index.js +64 -0
  176. package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
  177. package/dist/api/controllers/query/import/sources/curl.js +96 -0
  178. package/dist/api/controllers/query/import/sources/openapi2.js +142 -0
  179. package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  180. package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  181. package/dist/api/controllers/{query.js → query/index.js} +86 -52
  182. package/dist/api/controllers/query/validation.js +38 -0
  183. package/dist/api/controllers/row/internal.js +14 -6
  184. package/dist/api/controllers/row/internalSearch.js +2 -1
  185. package/dist/api/controllers/row/utils.js +13 -6
  186. package/dist/api/controllers/user.js +37 -1
  187. package/dist/api/controllers/webhook.js +4 -0
  188. package/dist/api/routes/query.js +5 -33
  189. package/dist/api/routes/user.js +3 -1
  190. package/dist/automations/steps/executeQuery.js +8 -1
  191. package/dist/automations/steps/outgoingWebhook.js +2 -3
  192. package/dist/automations/utils.js +10 -0
  193. package/dist/db/utils.js +8 -0
  194. package/dist/definitions/datasource.js +6 -1
  195. package/dist/integrations/base/sqlTable.js +1 -1
  196. package/dist/integrations/rest.js +207 -117
  197. package/dist/package.json +11 -4
  198. package/dist/tests/utilities/TestConfiguration.js +47 -0
  199. package/dist/threads/query.js +148 -40
  200. package/dist/threads/utils.js +105 -0
  201. package/dist/tsconfig.tsbuildinfo +1 -1
  202. package/dist/utilities/fileSystem/utilities.js +2 -1
  203. package/dist/utilities/index.js +10 -0
  204. package/dist/utilities/rowProcessor/index.js +76 -0
  205. package/package.json +12 -5
  206. package/src/api/controllers/automation.js +8 -4
  207. package/src/api/controllers/datasource.js +34 -0
  208. package/src/api/controllers/query/import/index.ts +85 -0
  209. package/src/api/controllers/query/import/sources/base/index.ts +87 -0
  210. package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
  211. package/src/api/controllers/query/import/sources/curl.ts +102 -0
  212. package/src/api/controllers/query/import/sources/openapi2.ts +163 -0
  213. package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +103 -0
  214. package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
  215. package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
  216. package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
  217. package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
  218. package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
  219. package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
  220. package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
  221. package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
  222. package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
  223. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  224. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
  225. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  226. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
  227. package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +238 -0
  228. package/src/api/controllers/query/import/tests/index.spec.js +109 -0
  229. package/src/api/controllers/query/index.js +195 -0
  230. package/src/api/controllers/query/validation.js +42 -0
  231. package/src/api/controllers/row/internal.js +14 -5
  232. package/src/api/controllers/row/internalSearch.js +2 -1
  233. package/src/api/controllers/row/utils.js +11 -8
  234. package/src/api/controllers/user.js +33 -0
  235. package/src/api/controllers/webhook.js +4 -0
  236. package/src/api/routes/query.js +13 -35
  237. package/src/api/routes/tests/datasource.spec.js +45 -0
  238. package/src/api/routes/tests/query.spec.js +69 -0
  239. package/src/api/routes/user.js +10 -0
  240. package/src/automations/steps/executeQuery.js +9 -1
  241. package/src/automations/steps/outgoingWebhook.js +2 -3
  242. package/src/automations/utils.js +11 -0
  243. package/src/db/utils.js +9 -0
  244. package/src/definitions/common.ts +2 -16
  245. package/src/definitions/datasource.ts +83 -1
  246. package/src/integrations/base/IntegrationBase.ts +4 -4
  247. package/src/integrations/base/sqlTable.ts +1 -1
  248. package/src/integrations/oracle.ts +1 -1
  249. package/src/integrations/rest.ts +230 -137
  250. package/src/integrations/tests/rest.spec.js +167 -19
  251. package/src/tests/utilities/TestConfiguration.js +57 -0
  252. package/src/threads/query.js +149 -40
  253. package/src/threads/utils.js +115 -0
  254. package/src/utilities/fileSystem/utilities.js +2 -0
  255. package/src/utilities/index.js +11 -0
  256. package/src/utilities/rowProcessor/index.js +75 -0
  257. package/builder/assets/index.8adef83f.js +0 -1316
  258. package/src/api/controllers/query.js +0 -158
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- const { ObjectStore, makeSureBucketExists, upload, streamUpload, retrieve, retrieveToTmp, deleteFolder, uploadDirectory, downloadTarball, } = require("@budibase/auth").objectStore;
2
+ const { ObjectStore, makeSureBucketExists, upload, deleteFiles, streamUpload, retrieve, retrieveToTmp, deleteFolder, uploadDirectory, downloadTarball, } = require("@budibase/auth").objectStore;
3
3
  /***********************************
4
4
  * NOTE *
5
5
  * This file purely exists so that *
@@ -17,3 +17,4 @@ exports.retrieveToTmp = retrieveToTmp;
17
17
  exports.deleteFolder = deleteFolder;
18
18
  exports.uploadDirectory = uploadDirectory;
19
19
  exports.downloadTarball = downloadTarball;
20
+ exports.deleteFiles = deleteFiles;
@@ -142,3 +142,13 @@ exports.doesDatabaseExist = (dbName) => __awaiter(void 0, void 0, void 0, functi
142
142
  return false;
143
143
  }
144
144
  });
145
+ exports.formatBytes = bytes => {
146
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
147
+ const byteIncrements = 1024;
148
+ let unit = 0;
149
+ let size = parseInt(bytes, 10) || 0;
150
+ while (size >= byteIncrements && ++unit) {
151
+ size /= byteIncrements;
152
+ }
153
+ return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`;
154
+ };
@@ -13,6 +13,10 @@ const { cloneDeep } = require("lodash/fp");
13
13
  const { FieldTypes, AutoFieldSubTypes } = require("../../constants");
14
14
  const { attachmentsRelativeURL } = require("../index");
15
15
  const { processFormulas } = require("./utils");
16
+ const { deleteFiles } = require("../../utilities/fileSystem/utilities");
17
+ const { ObjectStoreBuckets } = require("../../constants");
18
+ const { isProdAppID, getDeployedAppID, dbExists } = require("@budibase/auth/db");
19
+ const CouchDB = require("../../db");
16
20
  const BASE_AUTO_ID = 1;
17
21
  /**
18
22
  * A map of how we convert various properties in rows to each other based on the row type.
@@ -89,7 +93,36 @@ const TYPE_TRANSFORM_MAP = {
89
93
  [FieldTypes.AUTO]: {
90
94
  parse: () => undefined,
91
95
  },
96
+ [FieldTypes.JSON]: {
97
+ parse: input => {
98
+ try {
99
+ if (input === "") {
100
+ return undefined;
101
+ }
102
+ return JSON.parse(input);
103
+ }
104
+ catch (err) {
105
+ return input;
106
+ }
107
+ },
108
+ },
92
109
  };
110
+ /**
111
+ * Given the old state of the row and the new one after an update, this will
112
+ * find the keys that have been removed in the updated row.
113
+ */
114
+ function getRemovedAttachmentKeys(oldRow, row, attachmentKey) {
115
+ if (!oldRow[attachmentKey]) {
116
+ return [];
117
+ }
118
+ const oldKeys = oldRow[attachmentKey].map(attachment => attachment.key);
119
+ // no attachments in new row, all removed
120
+ if (!row[attachmentKey]) {
121
+ return oldKeys;
122
+ }
123
+ const newKeys = row[attachmentKey].map(attachment => attachment.key);
124
+ return oldKeys.filter(key => newKeys.indexOf(key) === -1);
125
+ }
93
126
  /**
94
127
  * This will update any auto columns that are found on the row/table with the correct information based on
95
128
  * time now and the current logged in user making the request.
@@ -240,3 +273,46 @@ exports.outputProcessing = (ctx, table, rows, opts = { squash: true }) => __awai
240
273
  }
241
274
  return wasArray ? enriched : enriched[0];
242
275
  });
276
+ /**
277
+ * Clean up any attachments that were attached to a row.
278
+ * @param {string} appId The ID of the app from which a row is being deleted.
279
+ * @param {object} table The table from which a row is being removed.
280
+ * @param {any} row optional - the row being removed.
281
+ * @param {any} rows optional - if multiple rows being deleted can do this in bulk.
282
+ * @param {any} oldRow optional - if updating a row this will determine the difference.
283
+ * @return {Promise<void>} When all attachments have been removed this will return.
284
+ */
285
+ exports.cleanupAttachments = (appId, table, { row, rows, oldRow }) => __awaiter(void 0, void 0, void 0, function* () {
286
+ if (!isProdAppID(appId)) {
287
+ const prodAppId = getDeployedAppID(appId);
288
+ // if prod exists, then don't allow deleting
289
+ const exists = yield dbExists(CouchDB, prodAppId);
290
+ if (exists) {
291
+ return;
292
+ }
293
+ }
294
+ let files = [];
295
+ function addFiles(row, key) {
296
+ if (row[key]) {
297
+ files = files.concat(row[key].map(attachment => attachment.key));
298
+ }
299
+ }
300
+ for (let [key, schema] of Object.entries(table.schema)) {
301
+ if (schema.type !== FieldTypes.ATTACHMENT) {
302
+ continue;
303
+ }
304
+ // if updating, need to manage the differences
305
+ if (oldRow && row) {
306
+ files = files.concat(getRemovedAttachmentKeys(oldRow, row, key));
307
+ }
308
+ else if (row) {
309
+ addFiles(row, key);
310
+ }
311
+ else if (rows) {
312
+ rows.forEach(row => addFiles(row, key));
313
+ }
314
+ }
315
+ if (files.length > 0) {
316
+ return deleteFiles(ObjectStoreBuckets.APPS, files);
317
+ }
318
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.0.26",
4
+ "version": "1.0.27-alpha.11",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -69,9 +69,10 @@
69
69
  "author": "Budibase",
70
70
  "license": "GPL-3.0",
71
71
  "dependencies": {
72
- "@budibase/auth": "^1.0.26",
73
- "@budibase/client": "^1.0.26",
74
- "@budibase/string-templates": "^1.0.26",
72
+ "@apidevtools/swagger-parser": "^10.0.3",
73
+ "@budibase/auth": "^1.0.27-alpha.11",
74
+ "@budibase/client": "^1.0.27-alpha.11",
75
+ "@budibase/string-templates": "^1.0.27-alpha.11",
75
76
  "@bull-board/api": "^3.7.0",
76
77
  "@bull-board/koa": "^3.7.0",
77
78
  "@elastic/elasticsearch": "7.10.0",
@@ -85,12 +86,15 @@
85
86
  "bull": "^3.22.4",
86
87
  "chmodr": "1.2.0",
87
88
  "csvtojson": "2.0.10",
89
+ "curlconverter": "^3.21.0",
88
90
  "dotenv": "8.2.0",
89
91
  "download": "8.0.0",
90
92
  "fix-path": "3.0.0",
93
+ "form-data": "^4.0.0",
91
94
  "fs-extra": "8.1.0",
92
95
  "jimp": "0.16.1",
93
96
  "joi": "17.2.1",
97
+ "js-yaml": "^4.1.0",
94
98
  "jsonschema": "1.4.0",
95
99
  "knex": "^0.95.6",
96
100
  "koa": "2.7.0",
@@ -118,11 +122,13 @@
118
122
  "pouchdb-replication-stream": "1.2.9",
119
123
  "server-destroy": "1.0.1",
120
124
  "svelte": "^3.38.2",
125
+ "swagger-parser": "^10.0.3",
121
126
  "to-json-schema": "0.2.5",
122
127
  "uuid": "3.3.2",
123
128
  "validate.js": "0.13.1",
124
129
  "vm2": "^3.9.3",
125
130
  "worker-farm": "^1.7.0",
131
+ "xml2js": "^0.4.23",
126
132
  "yargs": "13.2.4",
127
133
  "zlib": "1.0.5"
128
134
  },
@@ -146,6 +152,7 @@
146
152
  "eslint": "^6.8.0",
147
153
  "jest": "^27.0.5",
148
154
  "nodemon": "^2.0.4",
155
+ "openapi-types": "^9.3.1",
149
156
  "path-to-regexp": "^6.2.0",
150
157
  "prettier": "^2.3.1",
151
158
  "rimraf": "^3.0.2",
@@ -158,5 +165,5 @@
158
165
  "optionalDependencies": {
159
166
  "oracledb": "^5.3.0"
160
167
  },
161
- "gitHead": "6ebc345b6523efdd0ac77ea4c7e392918aff0757"
168
+ "gitHead": "45631b235ddba52942183e312b9154fbdb4ea862"
162
169
  }
@@ -5,11 +5,15 @@ const { getAutomationParams, generateAutomationID } = require("../../db/utils")
5
5
  const {
6
6
  checkForWebhooks,
7
7
  updateTestHistory,
8
+ removeDeprecated,
8
9
  } = require("../../automations/utils")
9
10
  const { deleteEntityMetadata } = require("../../utilities")
10
11
  const { MetadataTypes } = require("../../constants")
11
12
  const { setTestFlag, clearTestFlag } = require("../../utilities/redis")
12
13
 
14
+ const ACTION_DEFS = removeDeprecated(actions.ACTION_DEFINITIONS)
15
+ const TRIGGER_DEFS = removeDeprecated(triggers.TRIGGER_DEFINITIONS)
16
+
13
17
  /*************************
14
18
  * *
15
19
  * BUILDER FUNCTIONS *
@@ -155,17 +159,17 @@ exports.destroy = async function (ctx) {
155
159
  }
156
160
 
157
161
  exports.getActionList = async function (ctx) {
158
- ctx.body = actions.ACTION_DEFINITIONS
162
+ ctx.body = ACTION_DEFS
159
163
  }
160
164
 
161
165
  exports.getTriggerList = async function (ctx) {
162
- ctx.body = triggers.TRIGGER_DEFINITIONS
166
+ ctx.body = TRIGGER_DEFS
163
167
  }
164
168
 
165
169
  module.exports.getDefinitionList = async function (ctx) {
166
170
  ctx.body = {
167
- trigger: triggers.TRIGGER_DEFINITIONS,
168
- action: actions.ACTION_DEFINITIONS,
171
+ trigger: TRIGGER_DEFS,
172
+ action: ACTION_DEFS,
169
173
  }
170
174
  }
171
175
 
@@ -10,6 +10,7 @@ const {
10
10
  const { BuildSchemaErrors, InvalidColumns } = require("../../constants")
11
11
  const { integrations } = require("../../integrations")
12
12
  const { getDatasourceAndQuery } = require("./row/utils")
13
+ const { invalidateDynamicVariables } = require("../../threads/utils")
13
14
 
14
15
  exports.fetch = async function (ctx) {
15
16
  const database = new CouchDB(ctx.appId)
@@ -57,10 +58,43 @@ exports.buildSchemaFromDb = async function (ctx) {
57
58
  ctx.body = response
58
59
  }
59
60
 
61
+ /**
62
+ * Check for variables that have been updated or removed and invalidate them.
63
+ */
64
+ const invalidateVariables = async (existingDatasource, updatedDatasource) => {
65
+ const existingVariables = existingDatasource.config.dynamicVariables
66
+ const updatedVariables = updatedDatasource.config.dynamicVariables
67
+ const toInvalidate = []
68
+
69
+ if (!existingVariables) {
70
+ return
71
+ }
72
+
73
+ if (!updatedVariables) {
74
+ // invalidate all
75
+ toInvalidate.push(...existingVariables)
76
+ } else {
77
+ // invaldate changed / removed
78
+ existingVariables.forEach(existing => {
79
+ const unchanged = updatedVariables.find(
80
+ updated =>
81
+ existing.name === updated.name &&
82
+ existing.queryId === updated.queryId &&
83
+ existing.value === updated.value
84
+ )
85
+ if (!unchanged) {
86
+ toInvalidate.push(existing)
87
+ }
88
+ })
89
+ }
90
+ await invalidateDynamicVariables(toInvalidate)
91
+ }
92
+
60
93
  exports.update = async function (ctx) {
61
94
  const db = new CouchDB(ctx.appId)
62
95
  const datasourceId = ctx.params.datasourceId
63
96
  let datasource = await db.get(datasourceId)
97
+ await invalidateVariables(datasource, ctx.request.body)
64
98
  datasource = { ...datasource, ...ctx.request.body }
65
99
 
66
100
  const response = await db.put(datasource)
@@ -0,0 +1,85 @@
1
+ import CouchDB from "../../../../db"
2
+ import { queryValidation } from "../validation"
3
+ import { generateQueryID } from "../../../../db/utils"
4
+ import { ImportInfo, ImportSource } from "./sources/base"
5
+ import { OpenAPI2 } from "./sources/openapi2"
6
+ import { Query } from "./../../../../definitions/common"
7
+ import { Curl } from "./sources/curl"
8
+ interface ImportResult {
9
+ errorQueries: Query[]
10
+ queries: Query[]
11
+ }
12
+
13
+ export class RestImporter {
14
+ data: string
15
+ sources: ImportSource[]
16
+ source!: ImportSource
17
+
18
+ constructor(data: string) {
19
+ this.data = data
20
+ this.sources = [new OpenAPI2(), new Curl()]
21
+ }
22
+
23
+ init = async () => {
24
+ for (let source of this.sources) {
25
+ if (await source.isSupported(this.data)) {
26
+ this.source = source
27
+ break
28
+ }
29
+ }
30
+ }
31
+
32
+ getInfo = async (): Promise<ImportInfo> => {
33
+ return this.source.getInfo()
34
+ }
35
+
36
+ importQueries = async (
37
+ appId: string,
38
+ datasourceId: string
39
+ ): Promise<ImportResult> => {
40
+ // constuct the queries
41
+ let queries = await this.source.getQueries(datasourceId)
42
+
43
+ // validate queries
44
+ const errorQueries: Query[] = []
45
+ const schema = queryValidation()
46
+ queries = queries
47
+ .filter(query => {
48
+ const validation = schema.validate(query)
49
+ if (validation.error) {
50
+ errorQueries.push(query)
51
+ return false
52
+ }
53
+ return true
54
+ })
55
+ .map(query => {
56
+ query._id = generateQueryID(query.datasourceId)
57
+ return query
58
+ })
59
+
60
+ // persist queries
61
+ const db = new CouchDB(appId)
62
+ const response = await db.bulkDocs(queries)
63
+
64
+ // create index to seperate queries and errors
65
+ const queryIndex = queries.reduce((acc, query) => {
66
+ if (query._id) {
67
+ acc[query._id] = query
68
+ }
69
+ return acc
70
+ }, {} as { [key: string]: Query })
71
+
72
+ // check for failed writes
73
+ response.forEach((query: any) => {
74
+ if (!query.ok) {
75
+ errorQueries.push(queryIndex[query.id])
76
+ delete queryIndex[query.id]
77
+ }
78
+ })
79
+
80
+ return {
81
+ errorQueries,
82
+ queries: Object.values(queryIndex),
83
+ }
84
+ }
85
+ }
@@ -0,0 +1,87 @@
1
+ import { Query, QueryParameter } from "../../../../../../definitions/datasource"
2
+ import { URL } from "url"
3
+
4
+ export interface ImportInfo {
5
+ name: string
6
+ }
7
+
8
+ enum MethodToVerb {
9
+ get = "read",
10
+ post = "create",
11
+ put = "update",
12
+ patch = "patch",
13
+ delete = "delete",
14
+ }
15
+
16
+ export abstract class ImportSource {
17
+ abstract isSupported(data: string): Promise<boolean>
18
+ abstract getInfo(): Promise<ImportInfo>
19
+ abstract getQueries(datasourceId: string): Promise<Query[]>
20
+
21
+ constructQuery = (
22
+ datasourceId: string,
23
+ name: string,
24
+ method: string,
25
+ path: string,
26
+ url: URL,
27
+ queryString: string,
28
+ headers: object = {},
29
+ parameters: QueryParameter[] = [],
30
+ body: object | undefined = undefined
31
+ ): Query => {
32
+ const readable = true
33
+ const queryVerb = this.verbFromMethod(method)
34
+ const transformer = "return data"
35
+ const schema = {}
36
+ path = this.processPath(path)
37
+ path = `${url.origin}/${path}`
38
+ queryString = this.processQuery(queryString)
39
+ const requestBody = JSON.stringify(body, null, 2)
40
+
41
+ const query: Query = {
42
+ datasourceId,
43
+ name,
44
+ parameters,
45
+ fields: {
46
+ headers,
47
+ queryString,
48
+ path,
49
+ requestBody,
50
+ },
51
+ transformer,
52
+ schema,
53
+ readable,
54
+ queryVerb,
55
+ }
56
+
57
+ return query
58
+ }
59
+
60
+ verbFromMethod = (method: string) => {
61
+ const verb = (<any>MethodToVerb)[method]
62
+ if (!verb) {
63
+ throw new Error(`Unsupported method: ${method}`)
64
+ }
65
+ return verb
66
+ }
67
+
68
+ processPath = (path: string): string => {
69
+ if (path?.startsWith("/")) {
70
+ path = path.substring(1)
71
+ }
72
+
73
+ // add extra braces around params for binding
74
+ path = path.replace(/[{]/g, "{{")
75
+ path = path.replace(/[}]/g, "}}")
76
+
77
+ return path
78
+ }
79
+
80
+ processQuery = (queryString: string): string => {
81
+ if (queryString?.startsWith("?")) {
82
+ return queryString.substring(1)
83
+ }
84
+
85
+ return queryString
86
+ }
87
+ }
@@ -0,0 +1,24 @@
1
+ import { ImportSource } from "."
2
+ import SwaggerParser from "@apidevtools/swagger-parser"
3
+ import { OpenAPI } from "openapi-types"
4
+ const yaml = require("js-yaml")
5
+
6
+ export abstract class OpenAPISource extends ImportSource {
7
+ parseData = async (data: string): Promise<OpenAPI.Document> => {
8
+ let json: OpenAPI.Document
9
+ try {
10
+ json = JSON.parse(data)
11
+ } catch (jsonErr) {
12
+ // couldn't parse json
13
+ // try to convert yaml -> json
14
+ try {
15
+ json = yaml.load(data)
16
+ } catch (yamlErr) {
17
+ // couldn't parse yaml
18
+ throw new Error("Could not parse JSON or YAML")
19
+ }
20
+ }
21
+
22
+ return SwaggerParser.validate(json, {})
23
+ }
24
+ }
@@ -0,0 +1,102 @@
1
+ import { ImportSource, ImportInfo } from "./base"
2
+ import { Query } from "../../../../../definitions/common"
3
+ import { URL } from "url"
4
+ const curlconverter = require("curlconverter")
5
+
6
+ const parseCurl = (data: string): any => {
7
+ const curlJson = curlconverter.toJsonString(data)
8
+ return JSON.parse(curlJson)
9
+ }
10
+
11
+ /**
12
+ * The curl converter parses the request body into the key field of an object
13
+ * e.g. --d '{"key":"val"}' produces an object { "{"key":"val"}" : "" }
14
+ * This is not what we want, so we need to parse out the key from the object
15
+ */
16
+ const parseBody = (curl: any) => {
17
+ if (curl.data) {
18
+ const keys = Object.keys(curl.data)
19
+ if (keys.length) {
20
+ let key = keys[0]
21
+ try {
22
+ // filter out the dollar syntax used by curl for shell support
23
+ if (key.startsWith("$")) {
24
+ key = key.substring(1)
25
+ }
26
+ return JSON.parse(key)
27
+ } catch (e) {
28
+ // do nothing
29
+ }
30
+ }
31
+ }
32
+ return undefined
33
+ }
34
+
35
+ const parseCookie = (curl: any) => {
36
+ if (curl.cookies) {
37
+ return Object.entries(curl.cookies).reduce((acc, entry) => {
38
+ const [key, value] = entry
39
+ return acc + `${key}=${value}; `
40
+ }, "")
41
+ }
42
+
43
+ return null
44
+ }
45
+
46
+ /**
47
+ * Curl
48
+ * https://curl.se/docs/manpage.html
49
+ */
50
+ export class Curl extends ImportSource {
51
+ curl: any
52
+
53
+ isSupported = async (data: string): Promise<boolean> => {
54
+ try {
55
+ const curl = parseCurl(data)
56
+ this.curl = curl
57
+ } catch (err) {
58
+ return false
59
+ }
60
+ return true
61
+ }
62
+
63
+ getUrl = (): URL => {
64
+ return new URL(this.curl.raw_url)
65
+ }
66
+
67
+ getInfo = async (): Promise<ImportInfo> => {
68
+ const url = this.getUrl()
69
+ return {
70
+ name: url.hostname,
71
+ }
72
+ }
73
+
74
+ getQueries = async (datasourceId: string): Promise<Query[]> => {
75
+ const url = this.getUrl()
76
+ const name = url.pathname
77
+ const path = url.pathname
78
+ const method = this.curl.method
79
+ const queryString = url.search
80
+ const headers = this.curl.headers
81
+ const requestBody = parseBody(this.curl)
82
+
83
+ const cookieHeader = parseCookie(this.curl)
84
+ if (cookieHeader) {
85
+ headers["Cookie"] = cookieHeader
86
+ }
87
+
88
+ const query = this.constructQuery(
89
+ datasourceId,
90
+ name,
91
+ method,
92
+ path,
93
+ url,
94
+ queryString,
95
+ headers,
96
+ [],
97
+ requestBody
98
+ )
99
+
100
+ return [query]
101
+ }
102
+ }