@budibase/server 1.3.18 → 1.3.19-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 (302) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/builder/assets/index.1709d1b3.js +1005 -0
  3. package/builder/assets/index.8f621053.css +6 -0
  4. package/builder/index.html +2 -4
  5. package/coverage/clover.xml +441 -388
  6. package/coverage/coverage-final.json +20 -20
  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 +5 -5
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +9 -6
  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 +37 -37
  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 +1 -1
  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 +1 -1
  156. package/coverage/lcov.info +780 -667
  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/tables.js +1 -1
  180. package/dist/api/routes/table.js +1 -1
  181. package/dist/api/routes/utils/validators.js +2 -1
  182. package/dist/app.js +11 -0
  183. package/dist/db/utils.js +10 -1
  184. package/dist/environment.js +1 -0
  185. package/dist/integrations/airtable.js +126 -129
  186. package/dist/integrations/arangodb.js +86 -89
  187. package/dist/integrations/base/query.js +2 -2
  188. package/dist/integrations/base/sqlTable.js +3 -1
  189. package/dist/integrations/couchdb.js +80 -83
  190. package/dist/integrations/dynamodb.js +161 -164
  191. package/dist/integrations/elasticsearch.js +135 -138
  192. package/dist/integrations/firebase.js +154 -157
  193. package/dist/integrations/googlesheets.js +323 -327
  194. package/dist/integrations/index.js +99 -51
  195. package/dist/integrations/microsoftSqlServer.js +240 -243
  196. package/dist/integrations/mongodb.js +239 -242
  197. package/dist/integrations/mysql.js +215 -219
  198. package/dist/integrations/oracle.js +318 -322
  199. package/dist/integrations/postgres.js +262 -265
  200. package/dist/integrations/redis.js +134 -139
  201. package/dist/integrations/rest.js +289 -292
  202. package/dist/integrations/s3.js +61 -64
  203. package/dist/integrations/snowflake.js +83 -86
  204. package/dist/middleware/currentapp.js +2 -0
  205. package/dist/migrations/functions/backfill/global.js +0 -3
  206. package/dist/migrations/index.js +0 -10
  207. package/dist/package.json +9 -6
  208. package/dist/tests/utilities/TestConfiguration.js +1 -1
  209. package/dist/threads/query.js +2 -2
  210. package/dist/tsconfig.build.tsbuildinfo +1 -1
  211. package/dist/utilities/fileSystem/index.js +110 -1
  212. package/dist/watch.js +77 -0
  213. package/dist/websocket.js +22 -0
  214. package/package.json +10 -7
  215. package/scripts/dev/manage.js +1 -0
  216. package/scripts/localdomain.js +3 -1
  217. package/specs/openapi.json +3 -3
  218. package/specs/openapi.yaml +3 -3
  219. package/specs/resources/query.js +1 -1
  220. package/src/api/controllers/application.ts +1 -2
  221. package/src/api/controllers/auth.js +11 -0
  222. package/src/api/controllers/component.js +21 -2
  223. package/src/api/controllers/datasource.js +21 -8
  224. package/src/api/controllers/deploy/index.ts +1 -6
  225. package/src/api/controllers/integration.js +4 -4
  226. package/src/api/controllers/plugin/file.ts +15 -0
  227. package/src/api/controllers/plugin/github.ts +75 -0
  228. package/src/api/controllers/plugin/index.ts +215 -0
  229. package/src/api/controllers/plugin/npm.ts +56 -0
  230. package/src/api/controllers/plugin/uploaders.ts +4 -0
  231. package/src/api/controllers/plugin/url.ts +12 -0
  232. package/src/api/controllers/plugin/utils.ts +19 -0
  233. package/src/api/controllers/row/external.js +1 -1
  234. package/src/api/controllers/screen.js +66 -1
  235. package/src/api/controllers/static/index.ts +1 -1
  236. package/src/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  237. package/src/api/controllers/static/templates/preview.hbs +5 -1
  238. package/src/api/index.js +1 -1
  239. package/src/api/routes/application.ts +13 -2
  240. package/src/api/routes/index.ts +2 -0
  241. package/src/api/routes/plugin.ts +14 -0
  242. package/src/api/routes/public/tables.ts +1 -1
  243. package/src/api/routes/table.js +1 -1
  244. package/src/api/routes/tests/query.spec.js +8 -25
  245. package/src/api/routes/tests/user.spec.js +0 -2
  246. package/src/api/routes/utils/validators.js +2 -1
  247. package/src/app.ts +14 -0
  248. package/src/db/utils.js +12 -0
  249. package/src/definitions/openapi.ts +3 -3
  250. package/src/environment.js +1 -0
  251. package/src/integrations/airtable.ts +116 -118
  252. package/src/integrations/arangodb.ts +87 -89
  253. package/src/integrations/base/query.ts +2 -2
  254. package/src/integrations/base/sqlTable.ts +3 -1
  255. package/src/integrations/couchdb.ts +83 -89
  256. package/src/integrations/dynamodb.ts +173 -175
  257. package/src/integrations/elasticsearch.ts +120 -122
  258. package/src/integrations/firebase.ts +157 -159
  259. package/src/integrations/googlesheets.ts +328 -338
  260. package/src/integrations/index.ts +64 -21
  261. package/src/integrations/microsoftSqlServer.ts +249 -251
  262. package/src/integrations/mongodb.ts +261 -258
  263. package/src/integrations/mysql.ts +229 -234
  264. package/src/integrations/oracle.ts +373 -380
  265. package/src/integrations/postgres.ts +264 -268
  266. package/src/integrations/redis.ts +128 -132
  267. package/src/integrations/rest.ts +324 -329
  268. package/src/integrations/s3.ts +68 -71
  269. package/src/integrations/snowflake.ts +80 -82
  270. package/src/integrations/tests/{airtable.spec.js → airtable.spec.ts} +21 -18
  271. package/src/integrations/tests/{arangodb.spec.js → arangodb.spec.ts} +12 -9
  272. package/src/integrations/tests/{couchdb.spec.js → couchdb.spec.ts} +33 -27
  273. package/src/integrations/tests/{dynamodb.spec.js → dynamodb.spec.ts} +45 -41
  274. package/src/integrations/tests/{elasticsearch.spec.js → elasticsearch.spec.ts} +22 -21
  275. package/src/integrations/tests/{firebase.spec.js → firebase.spec.ts} +33 -28
  276. package/src/integrations/tests/{microsoftSqlServer.spec.js → microsoftSqlServer.spec.ts} +12 -11
  277. package/src/integrations/tests/{mongo.spec.js → mongo.spec.ts} +46 -35
  278. package/src/integrations/tests/{mysql.spec.js → mysql.spec.ts} +17 -15
  279. package/src/integrations/tests/{oracle.spec.js → oracle.spec.ts} +19 -17
  280. package/src/integrations/tests/{postgres.spec.js → postgres.spec.ts} +19 -17
  281. package/src/integrations/tests/{redis.spec.js → redis.spec.ts} +27 -18
  282. package/src/integrations/tests/{rest.spec.js → rest.spec.ts} +22 -14
  283. package/src/integrations/tests/{s3.spec.js → s3.spec.ts} +10 -8
  284. package/src/integrations/tests/{sql.spec.js → sql.spec.ts} +228 -177
  285. package/src/middleware/currentapp.js +2 -0
  286. package/src/migrations/functions/backfill/global.ts +0 -3
  287. package/src/migrations/index.ts +0 -16
  288. package/src/module.d.ts +2 -0
  289. package/src/tests/utilities/TestConfiguration.js +1 -1
  290. package/src/threads/query.ts +2 -2
  291. package/src/utilities/fileSystem/index.js +129 -0
  292. package/src/watch.ts +38 -0
  293. package/src/websocket.ts +26 -0
  294. package/builder/assets/index.a70e216a.css +0 -6
  295. package/builder/assets/index.a934251d.js +0 -876
  296. package/builder/assets/vendor.5e1fe644.css +0 -1
  297. package/builder/assets/vendor.67dbd8fa.js +0 -248
  298. package/dist/migrations/functions/developerQuota.js +0 -49
  299. package/src/migrations/functions/developerQuota.ts +0 -15
  300. package/src/migrations/functions/publishedAppsQuota.ts +0 -13
  301. package/src/migrations/functions/usageQuotas/syncDevelopers.ts +0 -19
  302. package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +0 -21
@@ -63,7 +63,7 @@ exports.save = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
63
63
  });
64
64
  });
65
65
  exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
66
- // there are no views in external data sources, shouldn't ever be called
66
+ // there are no views in external datasources, shouldn't ever be called
67
67
  // for now just fetch
68
68
  const split = ctx.params.viewName.split("all_");
69
69
  ctx.params.tableId = split[1] ? split[1] : split[0];
@@ -8,10 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- const { getScreenParams, generateScreenID } = require("../../db/utils");
11
+ const { getScreenParams, generateScreenID, getPluginParams, DocumentType, } = require("../../db/utils");
12
12
  const { AccessController } = require("@budibase/backend-core/roles");
13
13
  const { getAppDB } = require("@budibase/backend-core/context");
14
14
  const { events } = require("@budibase/backend-core");
15
+ const { getGlobalDB } = require("@budibase/backend-core/tenancy");
16
+ const { updateAppPackage } = require("./application");
15
17
  exports.fetch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
16
18
  const db = getAppDB();
17
19
  const screens = (yield db.allDocs(getScreenParams(null, {
@@ -28,11 +30,45 @@ exports.save = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
28
30
  eventFn = events.screen.created;
29
31
  }
30
32
  const response = yield db.put(screen);
33
+ // Find any custom components being used
34
+ let pluginNames = [];
35
+ let pluginAdded = false;
36
+ findPlugins(screen.props, pluginNames);
37
+ if (pluginNames.length) {
38
+ const globalDB = getGlobalDB();
39
+ const pluginsResponse = yield globalDB.allDocs(getPluginParams(null, {
40
+ include_docs: true,
41
+ }));
42
+ const requiredPlugins = pluginsResponse.rows
43
+ .map(row => row.doc)
44
+ .filter(plugin => {
45
+ return (plugin.schema.type === "component" &&
46
+ pluginNames.includes(`plugin/${plugin.name}`));
47
+ });
48
+ // Update the app metadata
49
+ const application = yield db.get(DocumentType.APP_METADATA);
50
+ let usedPlugins = application.usedPlugins || [];
51
+ requiredPlugins.forEach(plugin => {
52
+ if (!usedPlugins.find(x => x._id === plugin._id)) {
53
+ pluginAdded = true;
54
+ usedPlugins.push({
55
+ _id: plugin._id,
56
+ name: plugin.name,
57
+ version: plugin.version,
58
+ jsUrl: plugin.jsUrl,
59
+ hash: plugin.hash,
60
+ });
61
+ }
62
+ });
63
+ if (pluginAdded) {
64
+ yield updateAppPackage({ usedPlugins }, ctx.appId);
65
+ }
66
+ }
31
67
  if (eventFn) {
32
68
  yield eventFn(screen);
33
69
  }
34
70
  ctx.message = `Screen ${screen.name} saved.`;
35
- ctx.body = Object.assign(Object.assign({}, screen), { _id: response.id, _rev: response.rev });
71
+ ctx.body = Object.assign(Object.assign({}, screen), { _id: response.id, _rev: response.rev, pluginAdded });
36
72
  });
37
73
  exports.destroy = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
38
74
  const db = getAppDB();
@@ -45,3 +81,17 @@ exports.destroy = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
45
81
  };
46
82
  ctx.status = 200;
47
83
  });
84
+ const findPlugins = (component, foundPlugins) => {
85
+ if (!component) {
86
+ return;
87
+ }
88
+ if (component._component.startsWith("plugin")) {
89
+ if (!foundPlugins.includes(component._component)) {
90
+ foundPlugins.push(component._component);
91
+ }
92
+ }
93
+ if (!component._children || !component._children.length) {
94
+ return;
95
+ }
96
+ component._children.forEach(child => findPlugins(child, foundPlugins));
97
+ };
@@ -113,6 +113,7 @@ const serveApp = function (ctx) {
113
113
  production: env.isProd(),
114
114
  appId,
115
115
  clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
116
+ usedPlugins: appInfo.usedPlugins,
116
117
  });
117
118
  const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`);
118
119
  ctx.body = yield processString(appHbs, {
@@ -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,9 @@
66
66
  customTheme,
67
67
  previewDevice,
68
68
  navigation,
69
- hiddenComponentIds
69
+ hiddenComponentIds,
70
+ usedPlugins,
71
+ location
70
72
  } = parsed
71
73
 
72
74
  // Set some flags so the app knows we're in the builder
@@ -81,6 +83,8 @@
81
83
  window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
82
84
  window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
83
85
  window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
86
+ window["##BUDIBASE_USED_PLUGINS##"] = usedPlugins
87
+ window["##BUDIBASE_LOCATION##"] = location
84
88
 
85
89
  // Initialise app
86
90
  try {
package/dist/api/index.js CHANGED
@@ -51,8 +51,8 @@ router
51
51
  .use(buildTenancyMiddleware(null, null, {
52
52
  noTenancyRequired: true,
53
53
  }))
54
- .use(currentApp)
55
54
  .use(pro.licensing())
55
+ .use(currentApp)
56
56
  .use(auditLog);
57
57
  // error handling middleware
58
58
  router.use((ctx, next) => __awaiter(void 0, void 0, void 0, function* () {
@@ -30,14 +30,15 @@ const router_1 = __importDefault(require("@koa/router"));
30
30
  const controller = __importStar(require("../controllers/application"));
31
31
  const authorized_1 = __importDefault(require("../../middleware/authorized"));
32
32
  const permissions_1 = require("@budibase/backend-core/permissions");
33
+ const validators_1 = require("./utils/validators");
33
34
  const router = new router_1.default();
34
35
  router
35
36
  .post("/api/applications/:appId/sync", (0, authorized_1.default)(permissions_1.BUILDER), controller.sync)
36
- .post("/api/applications", (0, authorized_1.default)(permissions_1.BUILDER), controller.create)
37
+ .post("/api/applications", (0, authorized_1.default)(permissions_1.BUILDER), (0, validators_1.applicationValidator)(), controller.create)
37
38
  .get("/api/applications/:appId/definition", controller.fetchAppDefinition)
38
39
  .get("/api/applications", controller.fetch)
39
40
  .get("/api/applications/:appId/appPackage", controller.fetchAppPackage)
40
- .put("/api/applications/:appId", (0, authorized_1.default)(permissions_1.BUILDER), controller.update)
41
+ .put("/api/applications/:appId", (0, authorized_1.default)(permissions_1.BUILDER), (0, validators_1.applicationValidator)(), controller.update)
41
42
  .post("/api/applications/:appId/client/update", (0, authorized_1.default)(permissions_1.BUILDER), controller.updateClient)
42
43
  .post("/api/applications/:appId/client/revert", (0, authorized_1.default)(permissions_1.BUILDER), controller.revertClient)
43
44
  .delete("/api/applications/:appId", (0, authorized_1.default)(permissions_1.BUILDER), controller.destroy);
@@ -30,6 +30,7 @@ const metadata_1 = __importDefault(require("./metadata"));
30
30
  const dev_1 = __importDefault(require("./dev"));
31
31
  const cloud_1 = __importDefault(require("./cloud"));
32
32
  const migrations_1 = __importDefault(require("./migrations"));
33
+ const plugin_1 = __importDefault(require("./plugin"));
33
34
  var static_1 = require("./static");
34
35
  Object.defineProperty(exports, "staticRoutes", { enumerable: true, get: function () { return __importDefault(static_1).default; } });
35
36
  var public_1 = require("./public");
@@ -63,4 +64,5 @@ exports.mainRoutes = [
63
64
  table_1.default,
64
65
  row_1.default,
65
66
  migrations_1.default,
67
+ plugin_1.default,
66
68
  ];
@@ -22,26 +22,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
33
27
  };
34
28
  Object.defineProperty(exports, "__esModule", { value: true });
35
- exports.run = void 0;
36
- const syncPublishedApps = __importStar(require("./usageQuotas/syncPublishedApps"));
37
- /**
38
- * Date:
39
- * March 2022
40
- *
41
- * Description:
42
- * Sync the published apps count
43
- */
44
- const run = (db) => __awaiter(void 0, void 0, void 0, function* () {
45
- yield syncPublishedApps.run();
46
- });
47
- exports.run = run;
29
+ const router_1 = __importDefault(require("@koa/router"));
30
+ const controller = __importStar(require("../controllers/plugin"));
31
+ const authorized_1 = __importDefault(require("../../middleware/authorized"));
32
+ const permissions_1 = require("@budibase/backend-core/permissions");
33
+ const router = new router_1.default();
34
+ router
35
+ .post("/api/plugin/upload", (0, authorized_1.default)(permissions_1.BUILDER), controller.upload)
36
+ .post("/api/plugin", (0, authorized_1.default)(permissions_1.BUILDER), controller.create)
37
+ .get("/api/plugin", (0, authorized_1.default)(permissions_1.BUILDER), controller.fetch)
38
+ .delete("/api/plugin/:pluginId", (0, authorized_1.default)(permissions_1.BUILDER), controller.destroy);
39
+ exports.default = router;
@@ -28,7 +28,7 @@ const read = [], write = [];
28
28
  * responses:
29
29
  * 200:
30
30
  * description: Returns the created table, including the ID which has been generated for it. This can be
31
- * internal or external data sources.
31
+ * internal or external datasources.
32
32
  * content:
33
33
  * application/json:
34
34
  * schema:
@@ -45,7 +45,7 @@ router
45
45
  * @apiParam (Body) {string} [_rev] If updating an existing internal table then the revision must also be specified.
46
46
  * @apiParam (Body) {string} type] This should either be "internal" or "external" depending on the table type -
47
47
  * this will default to internal.
48
- * @apiParam (Body) {string} [sourceId] If creating an external table then this should be set to the data source ID. If
48
+ * @apiParam (Body) {string} [sourceId] If creating an external table then this should be set to the datasource ID. If
49
49
  * building an internal table this does not need to be set, although it will be returned as "bb_internal".
50
50
  * @apiParam (Body) {string} name The name of the table, this will be used in the UI. To rename the table simply
51
51
  * supply the table structure to this endpoint with the name changed.
@@ -7,6 +7,7 @@ const Joi = require("joi");
7
7
  const OPTIONAL_STRING = Joi.string().optional().allow(null).allow("");
8
8
  const OPTIONAL_NUMBER = Joi.number().optional().allow(null);
9
9
  const OPTIONAL_BOOLEAN = Joi.boolean().optional().allow(null);
10
+ const APP_NAME_REGEX = /^[\w\s]+$/;
10
11
  exports.tableValidator = () => {
11
12
  // prettier-ignore
12
13
  return joiValidator.body(Joi.object({
@@ -195,7 +196,7 @@ exports.applicationValidator = () => {
195
196
  return joiValidator.body(Joi.object({
196
197
  _id: OPTIONAL_STRING,
197
198
  _rev: OPTIONAL_STRING,
198
- name: Joi.string().required(),
199
+ name: Joi.string().pattern(new RegExp(APP_NAME_REGEX)).required().error(new Error('App name must be letters, numbers and spaces only')),
199
200
  url: OPTIONAL_STRING,
200
201
  template: Joi.object({
201
202
  templateString: OPTIONAL_STRING,
package/dist/app.js CHANGED
@@ -60,10 +60,13 @@ const bullboard = require("./automations/bullboard");
60
60
  const { logAlert } = require("@budibase/backend-core/logging");
61
61
  const { pinoSettings } = require("@budibase/backend-core");
62
62
  const { Thread } = require("./threads");
63
+ const fs = require("fs");
63
64
  const redis_1 = __importDefault(require("./utilities/redis"));
64
65
  const migrations = __importStar(require("./migrations"));
65
66
  const backend_core_1 = require("@budibase/backend-core");
66
67
  const workerRequests_1 = require("./utilities/workerRequests");
68
+ const watch_1 = require("./watch");
69
+ const websocket_1 = require("./websocket");
67
70
  const app = new Koa();
68
71
  // set up top level koa middleware
69
72
  app.use(koaBody({
@@ -97,6 +100,7 @@ if (env.isProd()) {
97
100
  }
98
101
  const server = http.createServer(app.callback());
99
102
  destroyable(server);
103
+ (0, websocket_1.initialise)(server);
100
104
  let shuttingDown = false, errCode = 0;
101
105
  server.on("close", () => __awaiter(void 0, void 0, void 0, function* () {
102
106
  // already in process
@@ -150,6 +154,13 @@ module.exports = server.listen(env.PORT || 0, () => __awaiter(void 0, void 0, vo
150
154
  }
151
155
  }
152
156
  }
157
+ // monitor plugin directory if required
158
+ if (env.SELF_HOSTED &&
159
+ !env.MULTI_TENANCY &&
160
+ env.PLUGINS_DIR &&
161
+ fs.existsSync(env.PLUGINS_DIR)) {
162
+ (0, watch_1.watch)();
163
+ }
153
164
  // check for version updates
154
165
  yield backend_core_1.installation.checkInstallVersion();
155
166
  // done last - this will never complete
package/dist/db/utils.js CHANGED
@@ -7,7 +7,7 @@ const AppStatus = {
7
7
  ALL: "all",
8
8
  DEPLOYED: "published",
9
9
  };
10
- const DocumentType = Object.assign(Object.assign({}, CoreDocTypes), { TABLE: "ta", ROW: "ro", USER: "us", AUTOMATION: "au", LINK: "li", WEBHOOK: "wh", INSTANCE: "inst", LAYOUT: "layout", SCREEN: "screen", DATASOURCE: "datasource", DATASOURCE_PLUS: "datasource_plus", QUERY: "query", DEPLOYMENTS: "deployments", METADATA: "metadata", MEM_VIEW: "view", USER_FLAG: "flag", AUTOMATION_METADATA: "meta_au" });
10
+ const DocumentType = Object.assign(Object.assign({}, CoreDocTypes), { TABLE: "ta", ROW: "ro", USER: "us", AUTOMATION: "au", LINK: "li", WEBHOOK: "wh", INSTANCE: "inst", LAYOUT: "layout", SCREEN: "screen", DATASOURCE: "datasource", DATASOURCE_PLUS: "datasource_plus", QUERY: "query", DEPLOYMENTS: "deployments", METADATA: "metadata", MEM_VIEW: "view", USER_FLAG: "flag", AUTOMATION_METADATA: "meta_au", PLUGIN: "plg" });
11
11
  const InternalTables = {
12
12
  USER_METADATA: "ta_users",
13
13
  };
@@ -274,6 +274,9 @@ exports.generateMemoryViewID = viewName => {
274
274
  exports.getMemoryViewParams = (otherProps = {}) => {
275
275
  return getDocParams(DocumentType.MEM_VIEW, null, otherProps);
276
276
  };
277
+ exports.generatePluginID = name => {
278
+ return `${DocumentType.PLUGIN}${SEPARATOR}${name}`;
279
+ };
277
280
  /**
278
281
  * This can be used with the db.allDocs to get a list of IDs
279
282
  */
@@ -283,3 +286,9 @@ exports.getMultiIDParams = ids => {
283
286
  include_docs: true,
284
287
  };
285
288
  };
289
+ /**
290
+ * Gets parameters for retrieving automations, this is a utility function for the getDocParams function.
291
+ */
292
+ exports.getPluginParams = (pluginId = null, otherProps = {}) => {
293
+ return getDocParams(DocumentType.PLUGIN, pluginId, otherProps);
294
+ };
@@ -64,6 +64,7 @@ module.exports = {
64
64
  SQL_MAX_ROWS: process.env.SQL_MAX_ROWS,
65
65
  BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL,
66
66
  BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
67
+ PLUGINS_DIR: process.env.PLUGINS_DIR || "/plugins",
67
68
  // flags
68
69
  ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS,
69
70
  DISABLE_THREADING: process.env.DISABLE_THREADING,
@@ -10,141 +10,138 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const types_1 = require("@budibase/types");
13
- var AirtableModule;
14
- (function (AirtableModule) {
15
- const Airtable = require("airtable");
16
- const SCHEMA = {
17
- docs: "https://airtable.com/api",
18
- description: "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: types_1.DatasourceFieldType.PASSWORD,
24
- default: "enter api key",
25
- required: true,
26
- },
27
- base: {
28
- type: types_1.DatasourceFieldType.STRING,
29
- default: "mybase",
30
- required: true,
31
- },
13
+ const Airtable = require("airtable");
14
+ const SCHEMA = {
15
+ docs: "https://airtable.com/api",
16
+ description: "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
17
+ friendlyName: "Airtable",
18
+ type: "Spreadsheet",
19
+ datasource: {
20
+ apiKey: {
21
+ type: types_1.DatasourceFieldType.PASSWORD,
22
+ default: "enter api key",
23
+ required: true,
32
24
  },
33
- query: {
34
- create: {
35
- type: types_1.QueryType.FIELDS,
36
- customisable: true,
37
- fields: {
38
- table: {
39
- type: types_1.DatasourceFieldType.STRING,
40
- required: true,
41
- },
25
+ base: {
26
+ type: types_1.DatasourceFieldType.STRING,
27
+ default: "mybase",
28
+ required: true,
29
+ },
30
+ },
31
+ query: {
32
+ create: {
33
+ type: types_1.QueryType.FIELDS,
34
+ customisable: true,
35
+ fields: {
36
+ table: {
37
+ type: types_1.DatasourceFieldType.STRING,
38
+ required: true,
42
39
  },
43
40
  },
44
- read: {
45
- type: types_1.QueryType.FIELDS,
46
- fields: {
47
- table: {
48
- type: types_1.DatasourceFieldType.STRING,
49
- required: true,
50
- },
51
- view: {
52
- type: types_1.DatasourceFieldType.STRING,
53
- required: true,
54
- },
55
- numRecords: {
56
- type: types_1.DatasourceFieldType.NUMBER,
57
- default: 10,
58
- },
41
+ },
42
+ read: {
43
+ type: types_1.QueryType.FIELDS,
44
+ fields: {
45
+ table: {
46
+ type: types_1.DatasourceFieldType.STRING,
47
+ required: true,
59
48
  },
60
- },
61
- update: {
62
- type: types_1.QueryType.FIELDS,
63
- customisable: true,
64
- fields: {
65
- id: {
66
- display: "Record ID",
67
- type: types_1.DatasourceFieldType.STRING,
68
- required: true,
69
- },
70
- table: {
71
- type: types_1.DatasourceFieldType.STRING,
72
- required: true,
73
- },
49
+ view: {
50
+ type: types_1.DatasourceFieldType.STRING,
51
+ required: true,
52
+ },
53
+ numRecords: {
54
+ type: types_1.DatasourceFieldType.NUMBER,
55
+ default: 10,
74
56
  },
75
57
  },
76
- delete: {
77
- type: types_1.QueryType.JSON,
58
+ },
59
+ update: {
60
+ type: types_1.QueryType.FIELDS,
61
+ customisable: true,
62
+ fields: {
63
+ id: {
64
+ display: "Record ID",
65
+ type: types_1.DatasourceFieldType.STRING,
66
+ required: true,
67
+ },
68
+ table: {
69
+ type: types_1.DatasourceFieldType.STRING,
70
+ required: true,
71
+ },
78
72
  },
79
73
  },
80
- };
81
- class AirtableIntegration {
82
- constructor(config) {
83
- this.config = config;
84
- this.client = new Airtable(config).base(config.base);
85
- }
86
- create(query) {
87
- return __awaiter(this, void 0, void 0, function* () {
88
- const { table, json } = query;
89
- try {
90
- return yield this.client(table).create([
91
- {
92
- fields: json,
93
- },
94
- ]);
95
- }
96
- catch (err) {
97
- console.error("Error writing to airtable", err);
98
- throw err;
99
- }
100
- });
101
- }
102
- read(query) {
103
- return __awaiter(this, void 0, void 0, function* () {
104
- try {
105
- const records = yield this.client(query.table)
106
- .select({ maxRecords: query.numRecords || 10, view: query.view })
107
- .firstPage();
108
- // @ts-ignore
109
- return records.map(({ fields }) => fields);
110
- }
111
- catch (err) {
112
- console.error("Error writing to airtable", err);
113
- return [];
114
- }
115
- });
116
- }
117
- update(query) {
118
- return __awaiter(this, void 0, void 0, function* () {
119
- const { table, id, json } = query;
120
- try {
121
- return yield this.client(table).update([
122
- {
123
- id,
124
- fields: json,
125
- },
126
- ]);
127
- }
128
- catch (err) {
129
- console.error("Error writing to airtable", err);
130
- throw err;
131
- }
132
- });
133
- }
134
- delete(query) {
135
- return __awaiter(this, void 0, void 0, function* () {
136
- try {
137
- return yield this.client(query.table).destroy(query.ids);
138
- }
139
- catch (err) {
140
- console.error("Error writing to airtable", err);
141
- throw err;
142
- }
143
- });
144
- }
74
+ delete: {
75
+ type: types_1.QueryType.JSON,
76
+ },
77
+ },
78
+ };
79
+ class AirtableIntegration {
80
+ constructor(config) {
81
+ this.config = config;
82
+ this.client = new Airtable(config).base(config.base);
83
+ }
84
+ create(query) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ const { table, json } = query;
87
+ try {
88
+ return yield this.client(table).create([
89
+ {
90
+ fields: json,
91
+ },
92
+ ]);
93
+ }
94
+ catch (err) {
95
+ console.error("Error writing to airtable", err);
96
+ throw err;
97
+ }
98
+ });
99
+ }
100
+ read(query) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ try {
103
+ const records = yield this.client(query.table)
104
+ .select({ maxRecords: query.numRecords || 10, view: query.view })
105
+ .firstPage();
106
+ // @ts-ignore
107
+ return records.map(({ fields }) => fields);
108
+ }
109
+ catch (err) {
110
+ console.error("Error writing to airtable", err);
111
+ return [];
112
+ }
113
+ });
114
+ }
115
+ update(query) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const { table, id, json } = query;
118
+ try {
119
+ return yield this.client(table).update([
120
+ {
121
+ id,
122
+ fields: json,
123
+ },
124
+ ]);
125
+ }
126
+ catch (err) {
127
+ console.error("Error writing to airtable", err);
128
+ throw err;
129
+ }
130
+ });
131
+ }
132
+ delete(query) {
133
+ return __awaiter(this, void 0, void 0, function* () {
134
+ try {
135
+ return yield this.client(query.table).destroy(query.ids);
136
+ }
137
+ catch (err) {
138
+ console.error("Error writing to airtable", err);
139
+ throw err;
140
+ }
141
+ });
145
142
  }
146
- module.exports = {
147
- schema: SCHEMA,
148
- integration: AirtableIntegration,
149
- };
150
- })(AirtableModule || (AirtableModule = {}));
143
+ }
144
+ exports.default = {
145
+ schema: SCHEMA,
146
+ integration: AirtableIntegration,
147
+ };