@budibase/server 1.3.20 → 1.3.21-alpha.1

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 (308) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/builder/assets/index.c9d3f9e8.js +1005 -0
  3. package/builder/assets/index.f1b70f52.css +6 -0
  4. package/builder/index.html +2 -4
  5. package/coverage/clover.xml +451 -390
  6. package/coverage/coverage-final.json +21 -21
  7. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/auth.js.html +41 -8
  9. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/component.js.html +68 -11
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +73 -34
  14. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/index.html +46 -46
  16. package/coverage/lcov-report/api/controllers/integration.js.html +6 -6
  17. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  22. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/external.js.html +2 -2
  26. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/screen.js.html +207 -12
  32. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  45. package/coverage/lcov-report/api/index.html +1 -1
  46. package/coverage/lcov-report/api/index.js.html +13 -13
  47. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/index.html +1 -1
  58. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/table.js.html +2 -2
  69. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/index.html +9 -9
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +75 -12
  73. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  75. package/coverage/lcov-report/automations/actions.js.html +1 -1
  76. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  77. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  78. package/coverage/lcov-report/automations/index.html +1 -1
  79. package/coverage/lcov-report/automations/index.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/index.html +1 -1
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  106. package/coverage/lcov-report/constants/index.html +1 -1
  107. package/coverage/lcov-report/constants/index.js.html +1 -1
  108. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  109. package/coverage/lcov-report/constants/screens.js.html +1 -1
  110. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  111. package/coverage/lcov-report/db/index.html +18 -18
  112. package/coverage/lcov-report/db/index.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  117. package/coverage/lcov-report/db/newid.js.html +2 -2
  118. package/coverage/lcov-report/db/utils.js.html +56 -20
  119. package/coverage/lcov-report/events/AutomationEmitter.js.html +3 -3
  120. package/coverage/lcov-report/events/index.html +1 -1
  121. package/coverage/lcov-report/events/index.js.html +1 -1
  122. package/coverage/lcov-report/events/utils.js.html +1 -1
  123. package/coverage/lcov-report/index.html +46 -46
  124. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  125. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  126. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  127. package/coverage/lcov-report/middleware/builder.js.html +12 -12
  128. package/coverage/lcov-report/middleware/currentapp.js.html +46 -40
  129. package/coverage/lcov-report/middleware/index.html +15 -15
  130. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  131. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  132. package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
  133. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  134. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  135. package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
  136. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  137. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  138. package/coverage/lcov-report/utilities/global.js.html +16 -16
  139. package/coverage/lcov-report/utilities/index.html +15 -15
  140. package/coverage/lcov-report/utilities/index.js.html +24 -24
  141. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  142. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  143. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  144. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  145. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  146. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  147. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  148. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  149. package/coverage/lcov-report/utilities/security.js.html +2 -2
  150. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  151. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  152. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  153. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  154. package/coverage/lcov-report/utilities/users.js.html +1 -1
  155. package/coverage/lcov-report/utilities/workerRequests.js.html +32 -8
  156. package/coverage/lcov.info +798 -672
  157. package/dist/api/controllers/application.js +5 -5
  158. package/dist/api/controllers/auth.js +9 -0
  159. package/dist/api/controllers/component.js +14 -1
  160. package/dist/api/controllers/datasource.js +21 -8
  161. package/dist/api/controllers/deploy/index.js +1 -8
  162. package/dist/api/controllers/integration.js +4 -4
  163. package/dist/{migrations/functions/usageQuotas/syncDevelopers.js → api/controllers/plugin/file.js} +13 -13
  164. package/dist/api/controllers/plugin/github.js +69 -0
  165. package/dist/api/controllers/plugin/index.js +200 -0
  166. package/dist/api/controllers/plugin/npm.js +58 -0
  167. package/dist/api/controllers/plugin/uploaders.js +11 -0
  168. package/dist/{migrations/functions/usageQuotas/syncPublishedApps.js → api/controllers/plugin/url.js} +13 -15
  169. package/dist/api/controllers/plugin/utils.js +26 -0
  170. package/dist/api/controllers/row/external.js +1 -1
  171. package/dist/api/controllers/screen.js +52 -2
  172. package/dist/api/controllers/static/index.js +1 -0
  173. package/dist/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  174. package/dist/api/controllers/static/templates/preview.hbs +5 -1
  175. package/dist/api/index.js +1 -1
  176. package/dist/api/routes/application.js +3 -2
  177. package/dist/api/routes/index.js +2 -0
  178. package/dist/{migrations/functions/publishedAppsQuota.js → api/routes/plugin.js} +13 -21
  179. package/dist/api/routes/public/rows.js +1 -82
  180. package/dist/api/routes/public/tables.js +1 -1
  181. package/dist/api/routes/table.js +1 -1
  182. package/dist/api/routes/utils/validators.js +20 -2
  183. package/dist/app.js +16 -1
  184. package/dist/db/utils.js +10 -1
  185. package/dist/environment.js +1 -0
  186. package/dist/integrations/airtable.js +126 -129
  187. package/dist/integrations/arangodb.js +86 -89
  188. package/dist/integrations/base/query.js +2 -2
  189. package/dist/integrations/base/sqlTable.js +3 -1
  190. package/dist/integrations/couchdb.js +80 -83
  191. package/dist/integrations/dynamodb.js +161 -164
  192. package/dist/integrations/elasticsearch.js +135 -138
  193. package/dist/integrations/firebase.js +154 -157
  194. package/dist/integrations/googlesheets.js +323 -327
  195. package/dist/integrations/index.js +99 -51
  196. package/dist/integrations/microsoftSqlServer.js +240 -243
  197. package/dist/integrations/mongodb.js +239 -242
  198. package/dist/integrations/mysql.js +215 -219
  199. package/dist/integrations/oracle.js +318 -322
  200. package/dist/integrations/postgres.js +262 -265
  201. package/dist/integrations/redis.js +134 -139
  202. package/dist/integrations/rest.js +289 -292
  203. package/dist/integrations/s3.js +61 -64
  204. package/dist/integrations/snowflake.js +83 -86
  205. package/dist/middleware/currentapp.js +2 -0
  206. package/dist/migrations/functions/backfill/global.js +0 -3
  207. package/dist/migrations/index.js +0 -10
  208. package/dist/package.json +9 -6
  209. package/dist/tests/utilities/TestConfiguration.js +1 -1
  210. package/dist/threads/query.js +2 -2
  211. package/dist/tsconfig.build.tsbuildinfo +1 -1
  212. package/dist/utilities/fileSystem/index.js +111 -1
  213. package/dist/utilities/workerRequests.js +4 -0
  214. package/dist/watch.js +77 -0
  215. package/dist/websocket.js +22 -0
  216. package/package.json +10 -7
  217. package/scripts/dev/manage.js +4 -0
  218. package/scripts/localdomain.js +3 -1
  219. package/specs/openapi.json +115 -112
  220. package/specs/openapi.yaml +96 -94
  221. package/specs/resources/misc.js +116 -0
  222. package/specs/resources/query.js +1 -1
  223. package/src/api/controllers/application.ts +1 -2
  224. package/src/api/controllers/auth.js +11 -0
  225. package/src/api/controllers/component.js +21 -2
  226. package/src/api/controllers/datasource.js +21 -8
  227. package/src/api/controllers/deploy/index.ts +1 -6
  228. package/src/api/controllers/integration.js +4 -4
  229. package/src/api/controllers/plugin/file.ts +15 -0
  230. package/src/api/controllers/plugin/github.ts +75 -0
  231. package/src/api/controllers/plugin/index.ts +215 -0
  232. package/src/api/controllers/plugin/npm.ts +56 -0
  233. package/src/api/controllers/plugin/uploaders.ts +4 -0
  234. package/src/api/controllers/plugin/url.ts +12 -0
  235. package/src/api/controllers/plugin/utils.ts +19 -0
  236. package/src/api/controllers/public/mapping/types.ts +8 -0
  237. package/src/api/controllers/row/external.js +1 -1
  238. package/src/api/controllers/screen.js +66 -1
  239. package/src/api/controllers/static/index.ts +1 -1
  240. package/src/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  241. package/src/api/controllers/static/templates/preview.hbs +5 -1
  242. package/src/api/index.js +1 -1
  243. package/src/api/routes/application.ts +13 -2
  244. package/src/api/routes/index.ts +2 -0
  245. package/src/api/routes/plugin.ts +14 -0
  246. package/src/api/routes/public/rows.ts +1 -82
  247. package/src/api/routes/public/tables.ts +1 -1
  248. package/src/api/routes/table.js +1 -1
  249. package/src/api/routes/tests/query.spec.js +8 -25
  250. package/src/api/routes/tests/user.spec.js +0 -2
  251. package/src/api/routes/utils/validators.js +26 -5
  252. package/src/app.ts +25 -2
  253. package/src/db/utils.js +12 -0
  254. package/src/definitions/openapi.ts +56 -55
  255. package/src/environment.js +1 -0
  256. package/src/integrations/airtable.ts +116 -118
  257. package/src/integrations/arangodb.ts +87 -89
  258. package/src/integrations/base/query.ts +2 -2
  259. package/src/integrations/base/sqlTable.ts +3 -1
  260. package/src/integrations/couchdb.ts +83 -89
  261. package/src/integrations/dynamodb.ts +173 -175
  262. package/src/integrations/elasticsearch.ts +120 -122
  263. package/src/integrations/firebase.ts +157 -159
  264. package/src/integrations/googlesheets.ts +328 -338
  265. package/src/integrations/index.ts +64 -21
  266. package/src/integrations/microsoftSqlServer.ts +249 -251
  267. package/src/integrations/mongodb.ts +261 -258
  268. package/src/integrations/mysql.ts +229 -234
  269. package/src/integrations/oracle.ts +373 -380
  270. package/src/integrations/postgres.ts +264 -268
  271. package/src/integrations/redis.ts +128 -132
  272. package/src/integrations/rest.ts +324 -329
  273. package/src/integrations/s3.ts +68 -71
  274. package/src/integrations/snowflake.ts +80 -82
  275. package/src/integrations/tests/{airtable.spec.js → airtable.spec.ts} +21 -18
  276. package/src/integrations/tests/{arangodb.spec.js → arangodb.spec.ts} +12 -9
  277. package/src/integrations/tests/{couchdb.spec.js → couchdb.spec.ts} +33 -27
  278. package/src/integrations/tests/{dynamodb.spec.js → dynamodb.spec.ts} +45 -41
  279. package/src/integrations/tests/{elasticsearch.spec.js → elasticsearch.spec.ts} +22 -21
  280. package/src/integrations/tests/{firebase.spec.js → firebase.spec.ts} +33 -28
  281. package/src/integrations/tests/{microsoftSqlServer.spec.js → microsoftSqlServer.spec.ts} +12 -11
  282. package/src/integrations/tests/{mongo.spec.js → mongo.spec.ts} +46 -35
  283. package/src/integrations/tests/{mysql.spec.js → mysql.spec.ts} +17 -15
  284. package/src/integrations/tests/{oracle.spec.js → oracle.spec.ts} +19 -17
  285. package/src/integrations/tests/{postgres.spec.js → postgres.spec.ts} +19 -17
  286. package/src/integrations/tests/{redis.spec.js → redis.spec.ts} +27 -18
  287. package/src/integrations/tests/{rest.spec.js → rest.spec.ts} +22 -14
  288. package/src/integrations/tests/{s3.spec.js → s3.spec.ts} +10 -8
  289. package/src/integrations/tests/{sql.spec.js → sql.spec.ts} +228 -177
  290. package/src/middleware/currentapp.js +2 -0
  291. package/src/migrations/functions/backfill/global.ts +0 -3
  292. package/src/migrations/index.ts +0 -16
  293. package/src/module.d.ts +2 -0
  294. package/src/tests/utilities/TestConfiguration.js +1 -1
  295. package/src/threads/query.ts +2 -2
  296. package/src/utilities/fileSystem/index.js +130 -0
  297. package/src/utilities/workerRequests.js +8 -0
  298. package/src/watch.ts +38 -0
  299. package/src/websocket.ts +26 -0
  300. package/builder/assets/index.79165a2a.js +0 -876
  301. package/builder/assets/index.fbe5f97c.css +0 -6
  302. package/builder/assets/vendor.5e1fe644.css +0 -1
  303. package/builder/assets/vendor.67dbd8fa.js +0 -248
  304. package/dist/migrations/functions/developerQuota.js +0 -49
  305. package/src/migrations/functions/developerQuota.ts +0 -15
  306. package/src/migrations/functions/publishedAppsQuota.ts +0 -13
  307. package/src/migrations/functions/usageQuotas/syncDevelopers.ts +0 -19
  308. package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +0 -21
@@ -231,20 +231,6 @@ describe("/queries", () => {
231
231
  url: `/api/queries/preview`,
232
232
  })
233
233
  })
234
-
235
- it("should fail with invalid integration type", async () => {
236
- const { datasource } = await createInvalidIntegration()
237
- await request
238
- .post(`/api/queries/preview`)
239
- .send({
240
- datasourceId: datasource._id,
241
- parameters: {},
242
- fields: {},
243
- queryVerb: "read",
244
- })
245
- .set(config.defaultHeaders())
246
- .expect(400)
247
- })
248
234
  })
249
235
 
250
236
  describe("execute", () => {
@@ -261,17 +247,14 @@ describe("/queries", () => {
261
247
  })
262
248
 
263
249
  it("should fail with invalid integration type", async () => {
264
- const { query, datasource } = await createInvalidIntegration()
265
- await request
266
- .post(`/api/queries/${query._id}`)
267
- .send({
268
- datasourceId: datasource._id,
269
- parameters: {},
270
- fields: {},
271
- queryVerb: "read",
272
- })
273
- .set(config.defaultHeaders())
274
- .expect(400)
250
+ let error
251
+ try {
252
+ await createInvalidIntegration()
253
+ } catch (err) {
254
+ error = err
255
+ }
256
+ expect(error).toBeDefined()
257
+ expect(error.message).toBe("No datasource implementation found.")
275
258
  })
276
259
  })
277
260
 
@@ -23,7 +23,6 @@ describe("/users", () => {
23
23
  })
24
24
 
25
25
  describe("fetch", () => {
26
-
27
26
  it("returns a list of users from an instance db", async () => {
28
27
  await config.createUser("uuidx")
29
28
  await config.createUser("uuidy")
@@ -38,7 +37,6 @@ describe("/users", () => {
38
37
  expect(res.body.find(u => u._id === `ro_ta_users_us_uuidy`)).toBeDefined()
39
38
  })
40
39
 
41
-
42
40
  it("should apply authorization to endpoint", async () => {
43
41
  await config.createUser()
44
42
  await checkPermissionsEndpoint({
@@ -10,6 +10,7 @@ const Joi = require("joi")
10
10
  const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("")
11
11
  const OPTIONAL_NUMBER = Joi.number().optional().allow(null)
12
12
  const OPTIONAL_BOOLEAN = Joi.boolean().optional().allow(null)
13
+ const APP_NAME_REGEX = /^[\w\s]+$/
13
14
 
14
15
  exports.tableValidator = () => {
15
16
  // prettier-ignore
@@ -209,15 +210,35 @@ exports.automationValidator = (existing = false) => {
209
210
  }).unknown(true))
210
211
  }
211
212
 
212
- exports.applicationValidator = () => {
213
+ exports.applicationValidator = (opts = { isCreate: true }) => {
213
214
  // prettier-ignore
214
- return joiValidator.body(Joi.object({
215
+ const base = {
215
216
  _id: OPTIONAL_STRING,
216
217
  _rev: OPTIONAL_STRING,
217
- name: Joi.string().required(),
218
218
  url: OPTIONAL_STRING,
219
219
  template: Joi.object({
220
220
  templateString: OPTIONAL_STRING,
221
- }).unknown(true),
222
- }).unknown(true))
221
+ })
222
+ }
223
+
224
+ const appNameValidator = Joi.string()
225
+ .pattern(new RegExp(APP_NAME_REGEX))
226
+ .error(new Error("App name must be letters, numbers and spaces only"))
227
+ if (opts.isCreate) {
228
+ base.name = appNameValidator.required()
229
+ } else {
230
+ base.name = appNameValidator.optional()
231
+ }
232
+
233
+ return joiValidator.body(
234
+ Joi.object({
235
+ _id: OPTIONAL_STRING,
236
+ _rev: OPTIONAL_STRING,
237
+ name: appNameValidator,
238
+ url: OPTIONAL_STRING,
239
+ template: Joi.object({
240
+ templateString: OPTIONAL_STRING,
241
+ }).unknown(true),
242
+ }).unknown(true)
243
+ )
223
244
  }
package/src/app.ts CHANGED
@@ -26,10 +26,17 @@ const bullboard = require("./automations/bullboard")
26
26
  const { logAlert } = require("@budibase/backend-core/logging")
27
27
  const { pinoSettings } = require("@budibase/backend-core")
28
28
  const { Thread } = require("./threads")
29
+ const fs = require("fs")
29
30
  import redis from "./utilities/redis"
30
31
  import * as migrations from "./migrations"
31
32
  import { events, installation, tenancy } from "@budibase/backend-core"
32
- import { createAdminUser, getChecklist } from "./utilities/workerRequests"
33
+ import {
34
+ createAdminUser,
35
+ generateApiKey,
36
+ getChecklist,
37
+ } from "./utilities/workerRequests"
38
+ import { watch } from "./watch"
39
+ import { initialise as initialiseWebsockets } from "./websocket"
33
40
 
34
41
  const app = new Koa()
35
42
 
@@ -74,6 +81,7 @@ if (env.isProd()) {
74
81
 
75
82
  const server = http.createServer(app.callback())
76
83
  destroyable(server)
84
+ initialiseWebsockets(server)
77
85
 
78
86
  let shuttingDown = false,
79
87
  errCode = 0
@@ -123,11 +131,16 @@ module.exports = server.listen(env.PORT || 0, async () => {
123
131
  if (!checklist?.adminUser?.checked) {
124
132
  try {
125
133
  const tenantId = tenancy.getTenantId()
126
- await createAdminUser(
134
+ const user = await createAdminUser(
127
135
  env.BB_ADMIN_USER_EMAIL,
128
136
  env.BB_ADMIN_USER_PASSWORD,
129
137
  tenantId
130
138
  )
139
+ // Need to set up an API key for automated integration tests
140
+ if (env.isTest()) {
141
+ await generateApiKey(user._id)
142
+ }
143
+
131
144
  console.log(
132
145
  "Admin account automatically created for",
133
146
  env.BB_ADMIN_USER_EMAIL
@@ -139,6 +152,16 @@ module.exports = server.listen(env.PORT || 0, async () => {
139
152
  }
140
153
  }
141
154
 
155
+ // monitor plugin directory if required
156
+ if (
157
+ env.SELF_HOSTED &&
158
+ !env.MULTI_TENANCY &&
159
+ env.PLUGINS_DIR &&
160
+ fs.existsSync(env.PLUGINS_DIR)
161
+ ) {
162
+ watch()
163
+ }
164
+
142
165
  // check for version updates
143
166
  await installation.checkInstallVersion()
144
167
 
package/src/db/utils.js CHANGED
@@ -42,6 +42,7 @@ const DocumentType = {
42
42
  MEM_VIEW: "view",
43
43
  USER_FLAG: "flag",
44
44
  AUTOMATION_METADATA: "meta_au",
45
+ PLUGIN: "plg",
45
46
  }
46
47
 
47
48
  const InternalTables = {
@@ -370,6 +371,10 @@ exports.getMemoryViewParams = (otherProps = {}) => {
370
371
  return getDocParams(DocumentType.MEM_VIEW, null, otherProps)
371
372
  }
372
373
 
374
+ exports.generatePluginID = name => {
375
+ return `${DocumentType.PLUGIN}${SEPARATOR}${name}`
376
+ }
377
+
373
378
  /**
374
379
  * This can be used with the db.allDocs to get a list of IDs
375
380
  */
@@ -379,3 +384,10 @@ exports.getMultiIDParams = ids => {
379
384
  include_docs: true,
380
385
  }
381
386
  }
387
+
388
+ /**
389
+ * Gets parameters for retrieving automations, this is a utility function for the getDocParams function.
390
+ */
391
+ exports.getPluginParams = (pluginId = null, otherProps = {}) => {
392
+ return getDocParams(DocumentType.PLUGIN, pluginId, otherProps)
393
+ }
@@ -278,58 +278,7 @@ export interface paths {
278
278
  };
279
279
  requestBody: {
280
280
  content: {
281
- "application/json": {
282
- query: {
283
- /** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */
284
- allOr?: boolean;
285
- /**
286
- * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value.
287
- * @example [object Object]
288
- */
289
- string?: { [key: string]: string };
290
- /** @description A fuzzy search, only supported by internal tables. */
291
- fuzzy?: { [key: string]: unknown };
292
- /**
293
- * @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.
294
- * @example [object Object]
295
- */
296
- range?: { [key: string]: unknown };
297
- /** @description Searches for rows that have a column value that is exactly the value set. */
298
- equal?: { [key: string]: unknown };
299
- /** @description Searches for any row which does not contain the specified column value. */
300
- notEqual?: { [key: string]: unknown };
301
- /**
302
- * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.
303
- * @example [object Object]
304
- */
305
- empty?: { [key: string]: unknown };
306
- /** @description Searches for rows which have the specified column. */
307
- notEmpty?: { [key: string]: unknown };
308
- /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */
309
- oneOf?: { [key: string]: unknown };
310
- };
311
- /** @description Enables pagination, by default this is disabled. */
312
- paginate?: boolean;
313
- /** @description If retrieving another page, the bookmark from the previous request must be supplied. */
314
- bookmark?: string | number;
315
- /** @description The maximum number of rows to return, useful when paginating, for internal tables this will be limited to 1000, for SQL tables it will be 5000. */
316
- limit?: number;
317
- /** @description A set of parameters describing the sort behaviour of the search. */
318
- sort?: {
319
- /**
320
- * @description The order of the sort, by default this is ascending.
321
- * @enum {string}
322
- */
323
- order?: "ascending" | "descending";
324
- /** @description The name of the column by which the rows will be sorted. */
325
- column?: string;
326
- /**
327
- * @description Defines whether the column should be treated as a string or as numbers when sorting.
328
- * @enum {string}
329
- */
330
- type?: "string" | "number";
331
- };
332
- };
281
+ "application/json": components["schemas"]["rowSearch"];
333
282
  };
334
283
  };
335
284
  };
@@ -344,7 +293,7 @@ export interface paths {
344
293
  };
345
294
  };
346
295
  responses: {
347
- /** Returns the created table, including the ID which has been generated for it. This can be internal or external data sources. */
296
+ /** Returns the created table, including the ID which has been generated for it. This can be internal or external datasources. */
348
297
  200: {
349
298
  content: {
350
299
  "application/json": components["schemas"]["tableOutput"];
@@ -965,7 +914,7 @@ export interface components {
965
914
  query: {
966
915
  /** @description The ID of the query. */
967
916
  _id: string;
968
- /** @description The ID of the data source the query belongs to. */
917
+ /** @description The ID of the datasource the query belongs to. */
969
918
  datasourceId?: string;
970
919
  /** @description The bindings which are required to perform this query. */
971
920
  parameters?: string[];
@@ -989,7 +938,7 @@ export interface components {
989
938
  data: {
990
939
  /** @description The ID of the query. */
991
940
  _id: string;
992
- /** @description The ID of the data source the query belongs to. */
941
+ /** @description The ID of the datasource the query belongs to. */
993
942
  datasourceId?: string;
994
943
  /** @description The bindings which are required to perform this query. */
995
944
  parameters?: string[];
@@ -1105,6 +1054,58 @@ export interface components {
1105
1054
  _id: string;
1106
1055
  }[];
1107
1056
  };
1057
+ rowSearch: {
1058
+ query: {
1059
+ /** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */
1060
+ allOr?: boolean;
1061
+ /**
1062
+ * @description A map of field name to the string to search for, this will look for rows that have a value starting with the string value.
1063
+ * @example [object Object]
1064
+ */
1065
+ string?: { [key: string]: string };
1066
+ /** @description A fuzzy search, only supported by internal tables. */
1067
+ fuzzy?: { [key: string]: unknown };
1068
+ /**
1069
+ * @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.
1070
+ * @example [object Object]
1071
+ */
1072
+ range?: { [key: string]: unknown };
1073
+ /** @description Searches for rows that have a column value that is exactly the value set. */
1074
+ equal?: { [key: string]: unknown };
1075
+ /** @description Searches for any row which does not contain the specified column value. */
1076
+ notEqual?: { [key: string]: unknown };
1077
+ /**
1078
+ * @description Searches for rows which do not contain the specified column. The object should simply contain keys of the column names, these can map to any value.
1079
+ * @example [object Object]
1080
+ */
1081
+ empty?: { [key: string]: unknown };
1082
+ /** @description Searches for rows which have the specified column. */
1083
+ notEmpty?: { [key: string]: unknown };
1084
+ /** @description Searches for rows which have a column value that is any of the specified values. The format of this must be columnName -> [value1, value2]. */
1085
+ oneOf?: { [key: string]: unknown };
1086
+ };
1087
+ /** @description Enables pagination, by default this is disabled. */
1088
+ paginate?: boolean;
1089
+ /** @description If retrieving another page, the bookmark from the previous request must be supplied. */
1090
+ bookmark?: string | number;
1091
+ /** @description The maximum number of rows to return, useful when paginating, for internal tables this will be limited to 1000, for SQL tables it will be 5000. */
1092
+ limit?: number;
1093
+ /** @description A set of parameters describing the sort behaviour of the search. */
1094
+ sort?: {
1095
+ /**
1096
+ * @description The order of the sort, by default this is ascending.
1097
+ * @enum {string}
1098
+ */
1099
+ order?: "ascending" | "descending";
1100
+ /** @description The name of the column by which the rows will be sorted. */
1101
+ column?: string;
1102
+ /**
1103
+ * @description Defines whether the column should be treated as a string or as numbers when sorting.
1104
+ * @enum {string}
1105
+ */
1106
+ type?: "string" | "number";
1107
+ };
1108
+ };
1108
1109
  nameSearch: {
1109
1110
  /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */
1110
1111
  name: string;
@@ -74,6 +74,7 @@ module.exports = {
74
74
  SQL_MAX_ROWS: process.env.SQL_MAX_ROWS,
75
75
  BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL,
76
76
  BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
77
+ PLUGINS_DIR: process.env.PLUGINS_DIR || "/plugins",
77
78
  // flags
78
79
  ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS,
79
80
  DISABLE_THREADING: process.env.DISABLE_THREADING,
@@ -5,146 +5,144 @@ import {
5
5
  IntegrationBase,
6
6
  } from "@budibase/types"
7
7
 
8
- module AirtableModule {
9
- const Airtable = require("airtable")
8
+ const Airtable = require("airtable")
10
9
 
11
- interface AirtableConfig {
12
- apiKey: string
13
- base: string
14
- }
10
+ interface AirtableConfig {
11
+ apiKey: string
12
+ base: string
13
+ }
15
14
 
16
- const SCHEMA: Integration = {
17
- docs: "https://airtable.com/api",
18
- description:
19
- "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
20
- friendlyName: "Airtable",
21
- type: "Spreadsheet",
22
- datasource: {
23
- apiKey: {
24
- type: DatasourceFieldType.PASSWORD,
25
- default: "enter api key",
26
- required: true,
27
- },
28
- base: {
29
- type: DatasourceFieldType.STRING,
30
- default: "mybase",
31
- required: true,
32
- },
15
+ const SCHEMA: Integration = {
16
+ docs: "https://airtable.com/api",
17
+ description:
18
+ "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
19
+ friendlyName: "Airtable",
20
+ type: "Spreadsheet",
21
+ datasource: {
22
+ apiKey: {
23
+ type: DatasourceFieldType.PASSWORD,
24
+ default: "enter api key",
25
+ required: true,
26
+ },
27
+ base: {
28
+ type: DatasourceFieldType.STRING,
29
+ default: "mybase",
30
+ required: true,
33
31
  },
34
- query: {
35
- create: {
36
- type: QueryType.FIELDS,
37
- customisable: true,
38
- fields: {
39
- table: {
40
- type: DatasourceFieldType.STRING,
41
- required: true,
42
- },
32
+ },
33
+ query: {
34
+ create: {
35
+ type: QueryType.FIELDS,
36
+ customisable: true,
37
+ fields: {
38
+ table: {
39
+ type: DatasourceFieldType.STRING,
40
+ required: true,
43
41
  },
44
42
  },
45
- read: {
46
- type: QueryType.FIELDS,
47
- fields: {
48
- table: {
49
- type: DatasourceFieldType.STRING,
50
- required: true,
51
- },
52
- view: {
53
- type: DatasourceFieldType.STRING,
54
- required: true,
55
- },
56
- numRecords: {
57
- type: DatasourceFieldType.NUMBER,
58
- default: 10,
59
- },
43
+ },
44
+ read: {
45
+ type: QueryType.FIELDS,
46
+ fields: {
47
+ table: {
48
+ type: DatasourceFieldType.STRING,
49
+ required: true,
60
50
  },
61
- },
62
- update: {
63
- type: QueryType.FIELDS,
64
- customisable: true,
65
- fields: {
66
- id: {
67
- display: "Record ID",
68
- type: DatasourceFieldType.STRING,
69
- required: true,
70
- },
71
- table: {
72
- type: DatasourceFieldType.STRING,
73
- required: true,
74
- },
51
+ view: {
52
+ type: DatasourceFieldType.STRING,
53
+ required: true,
54
+ },
55
+ numRecords: {
56
+ type: DatasourceFieldType.NUMBER,
57
+ default: 10,
75
58
  },
76
59
  },
77
- delete: {
78
- type: QueryType.JSON,
60
+ },
61
+ update: {
62
+ type: QueryType.FIELDS,
63
+ customisable: true,
64
+ fields: {
65
+ id: {
66
+ display: "Record ID",
67
+ type: DatasourceFieldType.STRING,
68
+ required: true,
69
+ },
70
+ table: {
71
+ type: DatasourceFieldType.STRING,
72
+ required: true,
73
+ },
79
74
  },
80
75
  },
81
- }
76
+ delete: {
77
+ type: QueryType.JSON,
78
+ },
79
+ },
80
+ }
82
81
 
83
- class AirtableIntegration implements IntegrationBase {
84
- private config: AirtableConfig
85
- private client: any
82
+ class AirtableIntegration implements IntegrationBase {
83
+ private config: AirtableConfig
84
+ private client: any
86
85
 
87
- constructor(config: AirtableConfig) {
88
- this.config = config
89
- this.client = new Airtable(config).base(config.base)
90
- }
86
+ constructor(config: AirtableConfig) {
87
+ this.config = config
88
+ this.client = new Airtable(config).base(config.base)
89
+ }
91
90
 
92
- async create(query: { table: any; json: any }) {
93
- const { table, json } = query
91
+ async create(query: { table: any; json: any }) {
92
+ const { table, json } = query
94
93
 
95
- try {
96
- return await this.client(table).create([
97
- {
98
- fields: json,
99
- },
100
- ])
101
- } catch (err) {
102
- console.error("Error writing to airtable", err)
103
- throw err
104
- }
94
+ try {
95
+ return await this.client(table).create([
96
+ {
97
+ fields: json,
98
+ },
99
+ ])
100
+ } catch (err) {
101
+ console.error("Error writing to airtable", err)
102
+ throw err
105
103
  }
104
+ }
106
105
 
107
- async read(query: { table: any; numRecords: any; view: any }) {
108
- try {
109
- const records = await this.client(query.table)
110
- .select({ maxRecords: query.numRecords || 10, view: query.view })
111
- .firstPage()
112
- // @ts-ignore
113
- return records.map(({ fields }) => fields)
114
- } catch (err) {
115
- console.error("Error writing to airtable", err)
116
- return []
117
- }
106
+ async read(query: { table: any; numRecords: any; view: any }) {
107
+ try {
108
+ const records = await this.client(query.table)
109
+ .select({ maxRecords: query.numRecords || 10, view: query.view })
110
+ .firstPage()
111
+ // @ts-ignore
112
+ return records.map(({ fields }) => fields)
113
+ } catch (err) {
114
+ console.error("Error writing to airtable", err)
115
+ return []
118
116
  }
117
+ }
119
118
 
120
- async update(query: { table: any; id: any; json: any }) {
121
- const { table, id, json } = query
119
+ async update(query: { table: any; id: any; json: any }) {
120
+ const { table, id, json } = query
122
121
 
123
- try {
124
- return await this.client(table).update([
125
- {
126
- id,
127
- fields: json,
128
- },
129
- ])
130
- } catch (err) {
131
- console.error("Error writing to airtable", err)
132
- throw err
133
- }
122
+ try {
123
+ return await this.client(table).update([
124
+ {
125
+ id,
126
+ fields: json,
127
+ },
128
+ ])
129
+ } catch (err) {
130
+ console.error("Error writing to airtable", err)
131
+ throw err
134
132
  }
133
+ }
135
134
 
136
- async delete(query: { table: any; ids: any }) {
137
- try {
138
- return await this.client(query.table).destroy(query.ids)
139
- } catch (err) {
140
- console.error("Error writing to airtable", err)
141
- throw err
142
- }
135
+ async delete(query: { table: any; ids: any }) {
136
+ try {
137
+ return await this.client(query.table).destroy(query.ids)
138
+ } catch (err) {
139
+ console.error("Error writing to airtable", err)
140
+ throw err
143
141
  }
144
142
  }
143
+ }
145
144
 
146
- module.exports = {
147
- schema: SCHEMA,
148
- integration: AirtableIntegration,
149
- }
145
+ export default {
146
+ schema: SCHEMA,
147
+ integration: AirtableIntegration,
150
148
  }