@budibase/server 1.3.12 → 1.3.15-alpha.0

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 (271) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/builder/assets/index.b266d29f.js +995 -0
  3. package/builder/assets/{index.e50bda9f.css → index.f5c54dd2.css} +2 -2
  4. package/builder/index.html +2 -4
  5. package/coverage/clover.xml +377 -313
  6. package/coverage/coverage-final.json +22 -22
  7. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/backup.js.html +8 -5
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/component.js.html +82 -13
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +20 -20
  14. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/index.html +32 -32
  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 +1 -1
  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 +204 -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 +12 -12
  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 +1 -1
  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 +1 -1
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  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 +24 -24
  79. package/coverage/lcov-report/automations/index.js.html +18 -9
  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 +126 -24
  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 +1 -1
  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 +48 -48
  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 +33 -33
  129. package/coverage/lcov-report/middleware/index.html +1 -1
  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 +19 -19
  140. package/coverage/lcov-report/utilities/index.js.html +66 -42
  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 +5 -5
  146. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  147. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +4 -4
  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 +6 -3
  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 +1 -1
  156. package/coverage/lcov.info +692 -564
  157. package/dist/api/controllers/application.js +6 -9
  158. package/dist/api/controllers/backup.js +2 -1
  159. package/dist/api/controllers/component.js +18 -1
  160. package/dist/api/controllers/datasource.js +4 -4
  161. package/dist/api/controllers/deploy/index.js +17 -2
  162. package/dist/api/controllers/integration.js +4 -4
  163. package/dist/api/controllers/plugin.js +119 -0
  164. package/dist/api/controllers/row/ExternalRequest.js +1 -1
  165. package/dist/api/controllers/screen.js +51 -2
  166. package/dist/api/controllers/static/index.js +1 -0
  167. package/dist/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  168. package/dist/api/controllers/static/templates/preview.hbs +3 -1
  169. package/dist/api/routes/index.js +2 -0
  170. package/dist/api/routes/plugin.js +38 -0
  171. package/dist/app.js +9 -0
  172. package/dist/automations/index.js +10 -5
  173. package/dist/automations/triggers.js +39 -5
  174. package/dist/automations/utils.js +16 -7
  175. package/dist/db/utils.js +10 -1
  176. package/dist/environment.js +1 -0
  177. package/dist/integrations/airtable.js +126 -129
  178. package/dist/integrations/arangodb.js +86 -89
  179. package/dist/integrations/base/query.js +2 -2
  180. package/dist/integrations/couchdb.js +80 -83
  181. package/dist/integrations/dynamodb.js +161 -164
  182. package/dist/integrations/elasticsearch.js +135 -138
  183. package/dist/integrations/firebase.js +154 -157
  184. package/dist/integrations/googlesheets.js +323 -327
  185. package/dist/integrations/index.js +93 -51
  186. package/dist/integrations/microsoftSqlServer.js +240 -243
  187. package/dist/integrations/mongodb.js +239 -242
  188. package/dist/integrations/mysql.js +215 -219
  189. package/dist/integrations/oracle.js +318 -322
  190. package/dist/integrations/postgres.js +262 -265
  191. package/dist/integrations/redis.js +134 -139
  192. package/dist/integrations/rest.js +293 -281
  193. package/dist/integrations/s3.js +61 -64
  194. package/dist/integrations/snowflake.js +83 -86
  195. package/dist/package.json +8 -6
  196. package/dist/threads/automation.js +6 -0
  197. package/dist/threads/query.js +2 -2
  198. package/dist/tsconfig.build.tsbuildinfo +1 -1
  199. package/dist/utilities/fileSystem/index.js +71 -6
  200. package/dist/utilities/index.js +8 -0
  201. package/dist/utilities/rowProcessor/utils.js +1 -1
  202. package/dist/utilities/usageQuota/rows.js +2 -1
  203. package/dist/watch.js +77 -0
  204. package/package.json +9 -7
  205. package/scripts/dev/manage.js +1 -0
  206. package/src/api/controllers/application.ts +2 -6
  207. package/src/api/controllers/backup.js +2 -1
  208. package/src/api/controllers/component.js +25 -2
  209. package/src/api/controllers/datasource.js +4 -4
  210. package/src/api/controllers/deploy/index.ts +17 -4
  211. package/src/api/controllers/integration.js +4 -4
  212. package/src/api/controllers/plugin.ts +110 -0
  213. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  214. package/src/api/controllers/screen.js +65 -1
  215. package/src/api/controllers/static/index.ts +1 -0
  216. package/src/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  217. package/src/api/controllers/static/templates/preview.hbs +3 -1
  218. package/src/api/routes/index.ts +2 -0
  219. package/src/api/routes/plugin.ts +13 -0
  220. package/src/api/routes/tests/query.spec.js +11 -28
  221. package/src/app.ts +12 -0
  222. package/src/automations/index.js +6 -3
  223. package/src/automations/triggers.js +44 -10
  224. package/src/automations/utils.ts +21 -9
  225. package/src/db/utils.js +12 -0
  226. package/src/definitions/datasource.ts +1 -0
  227. package/src/environment.js +1 -0
  228. package/src/integrations/airtable.ts +116 -118
  229. package/src/integrations/arangodb.ts +87 -89
  230. package/src/integrations/base/query.ts +2 -2
  231. package/src/integrations/couchdb.ts +83 -89
  232. package/src/integrations/dynamodb.ts +173 -175
  233. package/src/integrations/elasticsearch.ts +120 -122
  234. package/src/integrations/firebase.ts +157 -159
  235. package/src/integrations/googlesheets.ts +328 -338
  236. package/src/integrations/index.ts +59 -21
  237. package/src/integrations/microsoftSqlServer.ts +249 -251
  238. package/src/integrations/mongodb.ts +261 -258
  239. package/src/integrations/mysql.ts +229 -234
  240. package/src/integrations/oracle.ts +373 -380
  241. package/src/integrations/postgres.ts +264 -268
  242. package/src/integrations/redis.ts +128 -132
  243. package/src/integrations/rest.ts +325 -317
  244. package/src/integrations/s3.ts +68 -71
  245. package/src/integrations/snowflake.ts +80 -82
  246. package/src/integrations/tests/{airtable.spec.js → airtable.spec.ts} +21 -18
  247. package/src/integrations/tests/{arangodb.spec.js → arangodb.spec.ts} +12 -9
  248. package/src/integrations/tests/{couchdb.spec.js → couchdb.spec.ts} +33 -27
  249. package/src/integrations/tests/{dynamodb.spec.js → dynamodb.spec.ts} +45 -41
  250. package/src/integrations/tests/{elasticsearch.spec.js → elasticsearch.spec.ts} +22 -21
  251. package/src/integrations/tests/{firebase.spec.js → firebase.spec.ts} +33 -28
  252. package/src/integrations/tests/{microsoftSqlServer.spec.js → microsoftSqlServer.spec.ts} +12 -11
  253. package/src/integrations/tests/{mongo.spec.js → mongo.spec.ts} +46 -35
  254. package/src/integrations/tests/{mysql.spec.js → mysql.spec.ts} +17 -15
  255. package/src/integrations/tests/{oracle.spec.js → oracle.spec.ts} +19 -17
  256. package/src/integrations/tests/{postgres.spec.js → postgres.spec.ts} +19 -17
  257. package/src/integrations/tests/{redis.spec.js → redis.spec.ts} +27 -18
  258. package/src/integrations/tests/{rest.spec.js → rest.spec.ts} +57 -14
  259. package/src/integrations/tests/{s3.spec.js → s3.spec.ts} +10 -8
  260. package/src/integrations/tests/{sql.spec.js → sql.spec.ts} +228 -177
  261. package/src/module.d.ts +1 -0
  262. package/src/threads/automation.ts +6 -0
  263. package/src/threads/query.ts +2 -2
  264. package/src/utilities/fileSystem/index.js +75 -6
  265. package/src/utilities/index.js +8 -0
  266. package/src/utilities/rowProcessor/utils.js +1 -1
  267. package/src/utilities/usageQuota/rows.js +2 -1
  268. package/src/watch.ts +38 -0
  269. package/builder/assets/index.a4ba55ba.js +0 -875
  270. package/builder/assets/vendor.5e1fe644.css +0 -1
  271. package/builder/assets/vendor.67dbd8fa.js +0 -248
@@ -1,7 +1,14 @@
1
- const { getScreenParams, generateScreenID } = require("../../db/utils")
1
+ const {
2
+ getScreenParams,
3
+ generateScreenID,
4
+ getPluginParams,
5
+ DocumentType,
6
+ } = require("../../db/utils")
2
7
  const { AccessController } = require("@budibase/backend-core/roles")
3
8
  const { getAppDB } = require("@budibase/backend-core/context")
4
9
  const { events } = require("@budibase/backend-core")
10
+ const { getGlobalDB } = require("@budibase/backend-core/tenancy")
11
+ const { updateAppPackage } = require("./application")
5
12
 
6
13
  exports.fetch = async ctx => {
7
14
  const db = getAppDB()
@@ -32,6 +39,47 @@ exports.save = async ctx => {
32
39
 
33
40
  const response = await db.put(screen)
34
41
 
42
+ // Find any custom components being used
43
+ let pluginNames = []
44
+ let pluginAdded = false
45
+ findPlugins(screen.props, pluginNames)
46
+ if (pluginNames.length) {
47
+ const globalDB = getGlobalDB()
48
+ const pluginsResponse = await globalDB.allDocs(
49
+ getPluginParams(null, {
50
+ include_docs: true,
51
+ })
52
+ )
53
+ const requiredPlugins = pluginsResponse.rows
54
+ .map(row => row.doc)
55
+ .filter(plugin => {
56
+ return (
57
+ plugin.schema.type === "component" &&
58
+ pluginNames.includes(`plugin/${plugin.name}`)
59
+ )
60
+ })
61
+
62
+ // Update the app metadata
63
+ const application = await db.get(DocumentType.APP_METADATA)
64
+ let usedPlugins = application.usedPlugins || []
65
+
66
+ requiredPlugins.forEach(plugin => {
67
+ if (!usedPlugins.find(x => x._id === plugin._id)) {
68
+ pluginAdded = true
69
+ usedPlugins.push({
70
+ _id: plugin._id,
71
+ name: plugin.name,
72
+ version: plugin.version,
73
+ jsUrl: plugin.jsUrl,
74
+ })
75
+ }
76
+ })
77
+
78
+ if (pluginAdded) {
79
+ await updateAppPackage({ usedPlugins }, ctx.appId)
80
+ }
81
+ }
82
+
35
83
  if (eventFn) {
36
84
  await eventFn(screen)
37
85
  }
@@ -40,6 +88,7 @@ exports.save = async ctx => {
40
88
  ...screen,
41
89
  _id: response.id,
42
90
  _rev: response.rev,
91
+ pluginAdded,
43
92
  }
44
93
  }
45
94
 
@@ -56,3 +105,18 @@ exports.destroy = async ctx => {
56
105
  }
57
106
  ctx.status = 200
58
107
  }
108
+
109
+ const findPlugins = (component, foundPlugins) => {
110
+ if (!component) {
111
+ return
112
+ }
113
+ if (component._component.startsWith("plugin")) {
114
+ if (!foundPlugins.includes(component._component)) {
115
+ foundPlugins.push(component._component)
116
+ }
117
+ }
118
+ if (!component._children || !component._children.length) {
119
+ return
120
+ }
121
+ component._children.forEach(child => findPlugins(child, foundPlugins))
122
+ }
@@ -113,6 +113,7 @@ export const serveApp = async function (ctx: any) {
113
113
  production: env.isProd(),
114
114
  appId,
115
115
  clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
116
+ usedPlugins: appInfo.usedPlugins,
116
117
  })
117
118
 
118
119
  const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
@@ -3,6 +3,7 @@
3
3
  export let favicon = ""
4
4
 
5
5
  export let clientLibPath
6
+ export let usedPlugins
6
7
  </script>
7
8
 
8
9
  <svelte:head>
@@ -83,6 +84,15 @@
83
84
  </script>
84
85
  <script type="application/javascript" src={clientLibPath}>
85
86
  </script>
87
+ <!-- Custom components need inserted after the core client library -->
88
+ <!-- But before loadBudibase is called -->
89
+ {#if usedPlugins?.length}
90
+ {#each usedPlugins as plugin}
91
+ <script
92
+ type="application/javascript"
93
+ src={`/plugins/${plugin.jsUrl}`}></script>
94
+ {/each}
95
+ {/if}
86
96
  <script type="application/javascript">
87
97
  if (window.loadBudibase) {
88
98
  window.loadBudibase()
@@ -66,7 +66,8 @@
66
66
  customTheme,
67
67
  previewDevice,
68
68
  navigation,
69
- hiddenComponentIds
69
+ hiddenComponentIds,
70
+ usedPlugins
70
71
  } = parsed
71
72
 
72
73
  // Set some flags so the app knows we're in the builder
@@ -81,6 +82,7 @@
81
82
  window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
82
83
  window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
83
84
  window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
85
+ window["##BUDIBASE_USED_PLUGINS##"] = usedPlugins
84
86
 
85
87
  // Initialise app
86
88
  try {
@@ -24,6 +24,7 @@ import metadataRoutes from "./metadata"
24
24
  import devRoutes from "./dev"
25
25
  import cloudRoutes from "./cloud"
26
26
  import migrationRoutes from "./migrations"
27
+ import pluginRoutes from "./plugin"
27
28
 
28
29
  export { default as staticRoutes } from "./static"
29
30
  export { default as publicRoutes } from "./public"
@@ -57,4 +58,5 @@ export const mainRoutes = [
57
58
  tableRoutes,
58
59
  rowRoutes,
59
60
  migrationRoutes,
61
+ pluginRoutes,
60
62
  ]
@@ -0,0 +1,13 @@
1
+ import Router from "@koa/router"
2
+ import * as controller from "../controllers/plugin"
3
+ import authorized from "../../middleware/authorized"
4
+ import { BUILDER } from "@budibase/backend-core/permissions"
5
+
6
+ const router = new Router()
7
+
8
+ router
9
+ .post("/api/plugin/upload", authorized(BUILDER), controller.upload)
10
+ .get("/api/plugin", authorized(BUILDER), controller.fetch)
11
+ .delete("/api/plugin/:pluginId", authorized(BUILDER), controller.destroy)
12
+
13
+ export default router
@@ -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
 
@@ -311,7 +294,7 @@ describe("/queries", () => {
311
294
  "url": "string",
312
295
  "value": "string"
313
296
  })
314
- expect(res.body.rows[0].url).toContain("doctype html")
297
+ expect(res.body.rows[0].url).toContain("doctype%20html")
315
298
  })
316
299
 
317
300
  it("check that it automatically retries on fail with cached dynamics", async () => {
@@ -396,7 +379,7 @@ describe("/queries", () => {
396
379
  "queryHdr": userDetails.firstName,
397
380
  "secondHdr" : "1234"
398
381
  })
399
- expect(res.body.rows[0].url).toEqual("http://www.google.com?email=" + userDetails.email)
382
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?email=" + userDetails.email.replace("@", "%40"))
400
383
  })
401
384
 
402
385
  it("should bind the current user to query parameters", async () => {
@@ -413,7 +396,7 @@ describe("/queries", () => {
413
396
  "testParam" : "1234"
414
397
  })
415
398
 
416
- expect(res.body.rows[0].url).toEqual("http://www.google.com?test=" + userDetails.email +
399
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?test=" + userDetails.email.replace("@", "%40") +
417
400
  "&testName=" + userDetails.firstName + "&testParam=1234")
418
401
  })
419
402
 
package/src/app.ts CHANGED
@@ -26,10 +26,12 @@ 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
33
  import { createAdminUser, getChecklist } from "./utilities/workerRequests"
34
+ import { watch } from "./watch"
33
35
 
34
36
  const app = new Koa()
35
37
 
@@ -139,6 +141,16 @@ module.exports = server.listen(env.PORT || 0, async () => {
139
141
  }
140
142
  }
141
143
 
144
+ // monitor plugin directory if required
145
+ if (
146
+ env.SELF_HOSTED &&
147
+ !env.MULTI_TENANCY &&
148
+ env.PLUGINS_DIR &&
149
+ fs.existsSync(env.PLUGINS_DIR)
150
+ ) {
151
+ watch()
152
+ }
153
+
142
154
  // check for version updates
143
155
  await installation.checkInstallVersion()
144
156
 
@@ -1,16 +1,19 @@
1
1
  const { processEvent } = require("./utils")
2
2
  const { queue, shutdown } = require("./bullboard")
3
- const { TRIGGER_DEFINITIONS } = require("./triggers")
3
+ const { TRIGGER_DEFINITIONS, rebootTrigger } = require("./triggers")
4
4
  const { ACTION_DEFINITIONS } = require("./actions")
5
5
 
6
6
  /**
7
7
  * This module is built purely to kick off the worker farm and manage the inputs/outputs
8
8
  */
9
- exports.init = function () {
9
+ exports.init = async function () {
10
10
  // this promise will not complete
11
- return queue.process(async job => {
11
+ const promise = queue.process(async job => {
12
12
  await processEvent(job)
13
13
  })
14
+ // on init we need to trigger any reboot automations
15
+ await rebootTrigger()
16
+ return promise
14
17
  }
15
18
 
16
19
  exports.getQueues = () => {
@@ -9,6 +9,7 @@ const { checkTestFlag } = require("../utilities/redis")
9
9
  const utils = require("./utils")
10
10
  const env = require("../environment")
11
11
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
12
+ const { getAllApps } = require("@budibase/backend-core/db")
12
13
 
13
14
  const TRIGGER_DEFINITIONS = definitions
14
15
  const JOB_OPTS = {
@@ -16,24 +17,27 @@ const JOB_OPTS = {
16
17
  removeOnFail: true,
17
18
  }
18
19
 
20
+ async function getAllAutomations() {
21
+ const db = getAppDB()
22
+ let automations = await db.allDocs(
23
+ getAutomationParams(null, { include_docs: true })
24
+ )
25
+ return automations.rows.map(row => row.doc)
26
+ }
27
+
19
28
  async function queueRelevantRowAutomations(event, eventType) {
20
29
  if (event.appId == null) {
21
30
  throw `No appId specified for ${eventType} - check event emitters.`
22
31
  }
23
32
 
24
33
  doInAppContext(event.appId, async () => {
25
- const db = getAppDB()
26
- let automations = await db.allDocs(
27
- getAutomationParams(null, { include_docs: true })
28
- )
34
+ let automations = await getAllAutomations()
29
35
 
30
36
  // filter down to the correct event type
31
- automations = automations.rows
32
- .map(automation => automation.doc)
33
- .filter(automation => {
34
- const trigger = automation.definition.trigger
35
- return trigger && trigger.event === eventType
36
- })
37
+ automations = automations.filter(automation => {
38
+ const trigger = automation.definition.trigger
39
+ return trigger && trigger.event === eventType
40
+ })
37
41
 
38
42
  for (let automation of automations) {
39
43
  let automationDef = automation.definition
@@ -110,4 +114,34 @@ exports.externalTrigger = async function (
110
114
  }
111
115
  }
112
116
 
117
+ exports.rebootTrigger = async () => {
118
+ // reboot cron option is only available on the main thread at
119
+ // startup and only usable in self host
120
+ if (env.isInThread() || !env.SELF_HOSTED) {
121
+ return
122
+ }
123
+ // iterate through all production apps, find the reboot crons
124
+ // and trigger events for them
125
+ const appIds = await getAllApps({ dev: false, idsOnly: true })
126
+ for (let prodAppId of appIds) {
127
+ await doInAppContext(prodAppId, async () => {
128
+ let automations = await getAllAutomations()
129
+ let rebootEvents = []
130
+ for (let automation of automations) {
131
+ if (utils.isRebootTrigger(automation)) {
132
+ const job = {
133
+ automation,
134
+ event: {
135
+ appId: prodAppId,
136
+ timestamp: Date.now(),
137
+ },
138
+ }
139
+ rebootEvents.push(queue.add(job, JOB_OPTS))
140
+ }
141
+ }
142
+ await Promise.all(rebootEvents)
143
+ })
144
+ }
145
+ }
146
+
113
147
  exports.TRIGGER_DEFINITIONS = TRIGGER_DEFINITIONS
@@ -17,6 +17,7 @@ import { tenancy } from "@budibase/backend-core"
17
17
  import { quotas } from "@budibase/pro"
18
18
  import { Automation } from "@budibase/types"
19
19
 
20
+ const REBOOT_CRON = "@reboot"
20
21
  const WH_STEP_ID = definitions.WEBHOOK.stepId
21
22
  const CRON_STEP_ID = definitions.CRON.stepId
22
23
  const Runner = new Thread(ThreadType.AUTOMATION)
@@ -109,22 +110,33 @@ export async function clearMetadata() {
109
110
  await db.bulkDocs(automationMetadata)
110
111
  }
111
112
 
113
+ export function isCronTrigger(auto: Automation) {
114
+ return (
115
+ auto &&
116
+ auto.definition.trigger &&
117
+ auto.definition.trigger.stepId === CRON_STEP_ID
118
+ )
119
+ }
120
+
121
+ export function isRebootTrigger(auto: Automation) {
122
+ const trigger = auto ? auto.definition.trigger : null
123
+ return isCronTrigger(auto) && trigger?.inputs.cron === REBOOT_CRON
124
+ }
125
+
112
126
  /**
113
127
  * This function handles checking of any cron jobs that need to be enabled/updated.
114
128
  * @param {string} appId The ID of the app in which we are checking for webhooks
115
129
  * @param {object|undefined} automation The automation object to be updated.
116
130
  */
117
- export async function enableCronTrigger(appId: any, automation: any) {
131
+ export async function enableCronTrigger(appId: any, automation: Automation) {
118
132
  const trigger = automation ? automation.definition.trigger : null
119
- function isCronTrigger(auto: any) {
120
- return (
121
- auto &&
122
- auto.definition.trigger &&
123
- auto.definition.trigger.stepId === CRON_STEP_ID
124
- )
125
- }
133
+
126
134
  // need to create cron job
127
- if (isCronTrigger(automation) && trigger?.inputs.cron) {
135
+ if (
136
+ isCronTrigger(automation) &&
137
+ !isRebootTrigger(automation) &&
138
+ trigger?.inputs.cron
139
+ ) {
128
140
  // make a job id rather than letting Bull decide, makes it easier to handle on way out
129
141
  const jobId = `${appId}_cron_${newid()}`
130
142
  const job: any = await queue.add(
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
+ }
@@ -34,6 +34,7 @@ export interface RestConfig {
34
34
  defaultHeaders: {
35
35
  [key: string]: any
36
36
  }
37
+ legacyHttpParser: boolean
37
38
  authConfigs: AuthConfig[]
38
39
  staticVariables: {
39
40
  [key: string]: 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,