@budibase/server 1.3.17 → 1.3.19-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 (282) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/builder/assets/{index.a70e216a.css → index.3850883f.css} +2 -2
  3. package/builder/assets/index.fdade753.js +995 -0
  4. package/builder/index.html +2 -4
  5. package/coverage/clover.xml +409 -361
  6. package/coverage/coverage-final.json +18 -18
  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 +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 +38 -38
  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 +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 +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 +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 +30 -30
  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 +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 +725 -623
  157. package/dist/api/controllers/application.js +5 -4
  158. package/dist/api/controllers/component.js +14 -1
  159. package/dist/api/controllers/datasource.js +21 -8
  160. package/dist/api/controllers/integration.js +4 -4
  161. package/dist/api/controllers/plugin/file.js +24 -0
  162. package/dist/api/controllers/plugin/github.js +69 -0
  163. package/dist/api/controllers/plugin/index.js +197 -0
  164. package/dist/api/controllers/plugin/npm.js +58 -0
  165. package/dist/api/controllers/plugin/uploaders.js +11 -0
  166. package/dist/api/controllers/plugin/url.js +24 -0
  167. package/dist/api/controllers/plugin/utils.js +26 -0
  168. package/dist/api/controllers/row/external.js +1 -1
  169. package/dist/api/controllers/screen.js +52 -2
  170. package/dist/api/controllers/static/index.js +1 -0
  171. package/dist/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  172. package/dist/api/controllers/static/templates/preview.hbs +5 -1
  173. package/dist/api/routes/application.js +3 -2
  174. package/dist/api/routes/index.js +2 -0
  175. package/dist/api/routes/plugin.js +39 -0
  176. package/dist/api/routes/public/tables.js +1 -1
  177. package/dist/api/routes/table.js +1 -1
  178. package/dist/api/routes/utils/validators.js +2 -1
  179. package/dist/app.js +11 -0
  180. package/dist/db/utils.js +10 -1
  181. package/dist/environment.js +1 -0
  182. package/dist/integrations/airtable.js +126 -129
  183. package/dist/integrations/arangodb.js +86 -89
  184. package/dist/integrations/base/query.js +2 -2
  185. package/dist/integrations/base/sqlTable.js +3 -1
  186. package/dist/integrations/couchdb.js +80 -83
  187. package/dist/integrations/dynamodb.js +161 -164
  188. package/dist/integrations/elasticsearch.js +135 -138
  189. package/dist/integrations/firebase.js +154 -157
  190. package/dist/integrations/googlesheets.js +323 -327
  191. package/dist/integrations/index.js +99 -51
  192. package/dist/integrations/microsoftSqlServer.js +240 -243
  193. package/dist/integrations/mongodb.js +239 -242
  194. package/dist/integrations/mysql.js +215 -219
  195. package/dist/integrations/oracle.js +318 -322
  196. package/dist/integrations/postgres.js +262 -265
  197. package/dist/integrations/redis.js +134 -139
  198. package/dist/integrations/rest.js +289 -292
  199. package/dist/integrations/s3.js +61 -64
  200. package/dist/integrations/snowflake.js +83 -86
  201. package/dist/package.json +9 -6
  202. package/dist/tests/utilities/TestConfiguration.js +1 -1
  203. package/dist/threads/query.js +2 -2
  204. package/dist/tsconfig.build.tsbuildinfo +1 -1
  205. package/dist/utilities/fileSystem/index.js +110 -1
  206. package/dist/watch.js +77 -0
  207. package/dist/websocket.js +22 -0
  208. package/package.json +10 -7
  209. package/scripts/dev/manage.js +1 -0
  210. package/specs/openapi.json +3 -3
  211. package/specs/openapi.yaml +3 -3
  212. package/specs/resources/query.js +1 -1
  213. package/src/api/controllers/application.ts +1 -1
  214. package/src/api/controllers/component.js +21 -2
  215. package/src/api/controllers/datasource.js +21 -8
  216. package/src/api/controllers/integration.js +4 -4
  217. package/src/api/controllers/plugin/file.ts +15 -0
  218. package/src/api/controllers/plugin/github.ts +75 -0
  219. package/src/api/controllers/plugin/index.ts +212 -0
  220. package/src/api/controllers/plugin/npm.ts +56 -0
  221. package/src/api/controllers/plugin/uploaders.ts +4 -0
  222. package/src/api/controllers/plugin/url.ts +12 -0
  223. package/src/api/controllers/plugin/utils.ts +19 -0
  224. package/src/api/controllers/row/external.js +1 -1
  225. package/src/api/controllers/screen.js +66 -1
  226. package/src/api/controllers/static/index.ts +1 -0
  227. package/src/api/controllers/static/templates/BudibaseApp.svelte +10 -0
  228. package/src/api/controllers/static/templates/preview.hbs +5 -1
  229. package/src/api/routes/application.ts +13 -2
  230. package/src/api/routes/index.ts +2 -0
  231. package/src/api/routes/plugin.ts +14 -0
  232. package/src/api/routes/public/tables.ts +1 -1
  233. package/src/api/routes/table.js +1 -1
  234. package/src/api/routes/tests/query.spec.js +8 -25
  235. package/src/api/routes/utils/validators.js +2 -1
  236. package/src/app.ts +14 -0
  237. package/src/db/utils.js +12 -0
  238. package/src/definitions/openapi.ts +3 -3
  239. package/src/environment.js +1 -0
  240. package/src/integrations/airtable.ts +116 -118
  241. package/src/integrations/arangodb.ts +87 -89
  242. package/src/integrations/base/query.ts +2 -2
  243. package/src/integrations/base/sqlTable.ts +3 -1
  244. package/src/integrations/couchdb.ts +83 -89
  245. package/src/integrations/dynamodb.ts +173 -175
  246. package/src/integrations/elasticsearch.ts +120 -122
  247. package/src/integrations/firebase.ts +157 -159
  248. package/src/integrations/googlesheets.ts +328 -338
  249. package/src/integrations/index.ts +64 -21
  250. package/src/integrations/microsoftSqlServer.ts +249 -251
  251. package/src/integrations/mongodb.ts +261 -258
  252. package/src/integrations/mysql.ts +229 -234
  253. package/src/integrations/oracle.ts +373 -380
  254. package/src/integrations/postgres.ts +264 -268
  255. package/src/integrations/redis.ts +128 -132
  256. package/src/integrations/rest.ts +324 -329
  257. package/src/integrations/s3.ts +68 -71
  258. package/src/integrations/snowflake.ts +80 -82
  259. package/src/integrations/tests/{airtable.spec.js → airtable.spec.ts} +21 -18
  260. package/src/integrations/tests/{arangodb.spec.js → arangodb.spec.ts} +12 -9
  261. package/src/integrations/tests/{couchdb.spec.js → couchdb.spec.ts} +33 -27
  262. package/src/integrations/tests/{dynamodb.spec.js → dynamodb.spec.ts} +45 -41
  263. package/src/integrations/tests/{elasticsearch.spec.js → elasticsearch.spec.ts} +22 -21
  264. package/src/integrations/tests/{firebase.spec.js → firebase.spec.ts} +33 -28
  265. package/src/integrations/tests/{microsoftSqlServer.spec.js → microsoftSqlServer.spec.ts} +12 -11
  266. package/src/integrations/tests/{mongo.spec.js → mongo.spec.ts} +46 -35
  267. package/src/integrations/tests/{mysql.spec.js → mysql.spec.ts} +17 -15
  268. package/src/integrations/tests/{oracle.spec.js → oracle.spec.ts} +19 -17
  269. package/src/integrations/tests/{postgres.spec.js → postgres.spec.ts} +19 -17
  270. package/src/integrations/tests/{redis.spec.js → redis.spec.ts} +27 -18
  271. package/src/integrations/tests/{rest.spec.js → rest.spec.ts} +22 -14
  272. package/src/integrations/tests/{s3.spec.js → s3.spec.ts} +10 -8
  273. package/src/integrations/tests/{sql.spec.js → sql.spec.ts} +228 -177
  274. package/src/module.d.ts +2 -0
  275. package/src/tests/utilities/TestConfiguration.js +1 -1
  276. package/src/threads/query.ts +2 -2
  277. package/src/utilities/fileSystem/index.js +129 -0
  278. package/src/watch.ts +38 -0
  279. package/src/websocket.ts +26 -0
  280. package/builder/assets/index.8f5f192a.js +0 -876
  281. package/builder/assets/vendor.5e1fe644.css +0 -1
  282. package/builder/assets/vendor.67dbd8fa.js +0 -248
@@ -14,14 +14,18 @@ const { join } = require("path");
14
14
  const uuid = require("uuid/v4");
15
15
  const { doWithDB, dangerousGetDB, closeDB, } = require("@budibase/backend-core/db");
16
16
  const { ObjectStoreBuckets } = require("../../constants");
17
- const { upload, retrieve, retrieveToTmp, streamUpload, deleteFolder, downloadTarball, deleteFiles, } = require("./utilities");
17
+ const { upload, retrieve, retrieveToTmp, streamUpload, deleteFolder, downloadTarball, downloadTarballDirect, deleteFiles, } = require("./utilities");
18
18
  const { updateClientLibrary } = require("./clientLibrary");
19
+ const { checkSlashesInUrl } = require("../");
19
20
  const env = require("../../environment");
20
21
  const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, TABLE_ROW_PREFIX, } = require("../../db/utils");
21
22
  const MemoryStream = require("memorystream");
22
23
  const { getAppId } = require("@budibase/backend-core/context");
24
+ const tar = require("tar");
25
+ const fetch = require("node-fetch");
23
26
  const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..");
24
27
  const NODE_MODULES_PATH = join(TOP_LEVEL_PATH, "node_modules");
28
+ const DATASOURCE_PATH = join(budibaseTempDir(), "datasource");
25
29
  /**
26
30
  * The single stack system (Cloud and Builder) should not make use of the file system where possible,
27
31
  * this file handles all of the file access for the system with the intention of limiting it all to one
@@ -96,6 +100,12 @@ exports.getTemplateStream = (template) => __awaiter(void 0, void 0, void 0, func
96
100
  exports.loadHandlebarsFile = path => {
97
101
  return fs.readFileSync(path, "utf8");
98
102
  };
103
+ /**
104
+ * Same as above just with a different name.
105
+ */
106
+ exports.loadJSFile = (directory, name) => {
107
+ return fs.readFileSync(join(directory, name), "utf8");
108
+ };
99
109
  /**
100
110
  * When return a file from the API need to write the file to the system temporarily so we
101
111
  * can create a read stream to send.
@@ -294,6 +304,104 @@ exports.cleanup = appIds => {
294
304
  }
295
305
  }
296
306
  };
307
+ const createTempFolder = item => {
308
+ const path = join(budibaseTempDir(), item);
309
+ try {
310
+ // remove old tmp directories automatically - don't combine
311
+ if (fs.existsSync(path)) {
312
+ fs.rmSync(path, { recursive: true, force: true });
313
+ }
314
+ fs.mkdirSync(path);
315
+ }
316
+ catch (err) {
317
+ throw new Error(`Path cannot be created: ${err.message}`);
318
+ }
319
+ return path;
320
+ };
321
+ exports.createTempFolder = createTempFolder;
322
+ const extractTarball = (fromFilePath, toPath) => __awaiter(void 0, void 0, void 0, function* () {
323
+ yield tar.extract({
324
+ file: fromFilePath,
325
+ C: toPath,
326
+ });
327
+ });
328
+ exports.extractTarball = extractTarball;
329
+ const getPluginMetadata = (path) => __awaiter(void 0, void 0, void 0, function* () {
330
+ let metadata = {};
331
+ try {
332
+ const pkg = fs.readFileSync(join(path, "package.json"), "utf8");
333
+ const schema = fs.readFileSync(join(path, "schema.json"), "utf8");
334
+ metadata.schema = JSON.parse(schema);
335
+ metadata.package = JSON.parse(pkg);
336
+ if (!metadata.package.name ||
337
+ !metadata.package.version ||
338
+ !metadata.package.description) {
339
+ throw new Error("package.json is missing one of 'name', 'version' or 'description'.");
340
+ }
341
+ }
342
+ catch (err) {
343
+ throw new Error(`Unable to process schema.json/package.json in plugin. ${err.message}`);
344
+ }
345
+ return { metadata, directory: path };
346
+ });
347
+ exports.getPluginMetadata = getPluginMetadata;
348
+ exports.getDatasourcePlugin = (name, url, hash) => __awaiter(void 0, void 0, void 0, function* () {
349
+ if (!fs.existsSync(DATASOURCE_PATH)) {
350
+ fs.mkdirSync(DATASOURCE_PATH);
351
+ }
352
+ const filename = join(DATASOURCE_PATH, name);
353
+ const metadataName = `${filename}.bbmetadata`;
354
+ if (fs.existsSync(filename)) {
355
+ const currentHash = fs.readFileSync(metadataName, "utf8");
356
+ // if hash is the same return the file, otherwise remove it and re-download
357
+ if (currentHash === hash) {
358
+ return require(filename);
359
+ }
360
+ else {
361
+ console.log(`Updating plugin: ${name}`);
362
+ fs.unlinkSync(filename);
363
+ }
364
+ }
365
+ const fullUrl = checkSlashesInUrl(`${env.MINIO_URL}/${ObjectStoreBuckets.PLUGINS}/${url}`);
366
+ const response = yield fetch(fullUrl);
367
+ if (response.status === 200) {
368
+ const content = yield response.text();
369
+ fs.writeFileSync(filename, content);
370
+ fs.writeFileSync(metadataName, hash);
371
+ return require(filename);
372
+ }
373
+ else {
374
+ throw new Error(`Unable to retrieve plugin - reason: ${yield response.text()}`);
375
+ }
376
+ });
377
+ /**
378
+ * Find for a file recursively from start path applying filter, return first match
379
+ */
380
+ exports.findFileRec = (startPath, filter) => {
381
+ if (!fs.existsSync(startPath)) {
382
+ return;
383
+ }
384
+ const files = fs.readdirSync(startPath);
385
+ for (let i = 0, len = files.length; i < len; i++) {
386
+ const filename = join(startPath, files[i]);
387
+ const stat = fs.lstatSync(filename);
388
+ if (stat.isDirectory()) {
389
+ return exports.findFileRec(filename, filter);
390
+ }
391
+ else if (filename.endsWith(filter)) {
392
+ return filename;
393
+ }
394
+ }
395
+ };
396
+ /**
397
+ * Remove a folder which is not empty from the file system
398
+ */
399
+ exports.deleteFolderFileSystem = path => {
400
+ if (!fs.existsSync(path)) {
401
+ return;
402
+ }
403
+ fs.rmSync(path, { recursive: true, force: true });
404
+ };
297
405
  /**
298
406
  * Full function definition for below can be found in the utilities.
299
407
  */
@@ -301,5 +409,6 @@ exports.upload = upload;
301
409
  exports.retrieve = retrieve;
302
410
  exports.retrieveToTmp = retrieveToTmp;
303
411
  exports.deleteFiles = deleteFiles;
412
+ exports.downloadTarballDirect = downloadTarballDirect;
304
413
  exports.TOP_LEVEL_PATH = TOP_LEVEL_PATH;
305
414
  exports.NODE_MODULES_PATH = NODE_MODULES_PATH;
package/dist/watch.js ADDED
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
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
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.watch = void 0;
39
+ const path_1 = __importDefault(require("path"));
40
+ const env = __importStar(require("./environment"));
41
+ const chokidar_1 = __importDefault(require("chokidar"));
42
+ const fs_1 = __importDefault(require("fs"));
43
+ const backend_core_1 = require("@budibase/backend-core");
44
+ const constants_1 = require("@budibase/backend-core/constants");
45
+ const plugin_1 = require("./api/controllers/plugin");
46
+ function watch() {
47
+ const watchPath = path_1.default.join(env.PLUGINS_DIR, "./**/*.tar.gz");
48
+ chokidar_1.default
49
+ .watch(watchPath, {
50
+ ignored: "**/node_modules",
51
+ awaitWriteFinish: {
52
+ pollInterval: 100,
53
+ stabilityThreshold: 250,
54
+ },
55
+ usePolling: true,
56
+ interval: 250,
57
+ })
58
+ .on("all", (event, path) => __awaiter(this, void 0, void 0, function* () {
59
+ // Sanity checks
60
+ if (!(path === null || path === void 0 ? void 0 : path.endsWith(".tar.gz")) || !fs_1.default.existsSync(path)) {
61
+ return;
62
+ }
63
+ yield backend_core_1.tenancy.doInTenant(constants_1.DEFAULT_TENANT_ID, () => __awaiter(this, void 0, void 0, function* () {
64
+ try {
65
+ const split = path.split("/");
66
+ const name = split[split.length - 1];
67
+ console.log("Importing plugin:", path);
68
+ yield (0, plugin_1.processPlugin)({ name, path });
69
+ }
70
+ catch (err) {
71
+ const message = (err === null || err === void 0 ? void 0 : err.message) ? err === null || err === void 0 ? void 0 : err.message : err;
72
+ console.error("Failed to import plugin:", message);
73
+ }
74
+ }));
75
+ }));
76
+ }
77
+ exports.watch = watch;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClientAppSocket = exports.initialise = void 0;
4
+ const socket_io_1 = require("socket.io");
5
+ class Websocket {
6
+ constructor(server, path) {
7
+ this.socketServer = new socket_io_1.Server(server, {
8
+ path,
9
+ });
10
+ }
11
+ // Emit an event to all sockets
12
+ emit(event, payload) {
13
+ this.socketServer.sockets.emit(event, payload);
14
+ }
15
+ }
16
+ // Likely to be more socket instances in future
17
+ let ClientAppSocket;
18
+ exports.ClientAppSocket = ClientAppSocket;
19
+ const initialise = (server) => {
20
+ exports.ClientAppSocket = ClientAppSocket = new Websocket(server, "/socket/client");
21
+ };
22
+ exports.initialise = initialise;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.3.17",
4
+ "version": "1.3.19-alpha.0",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -77,11 +77,11 @@
77
77
  "license": "GPL-3.0",
78
78
  "dependencies": {
79
79
  "@apidevtools/swagger-parser": "10.0.3",
80
- "@budibase/backend-core": "^1.3.17",
81
- "@budibase/client": "^1.3.17",
82
- "@budibase/pro": "1.3.16",
83
- "@budibase/string-templates": "^1.3.17",
84
- "@budibase/types": "^1.3.17",
80
+ "@budibase/backend-core": "1.3.19-alpha.0",
81
+ "@budibase/client": "1.3.19-alpha.0",
82
+ "@budibase/pro": "1.3.18",
83
+ "@budibase/string-templates": "1.3.19-alpha.0",
84
+ "@budibase/types": "1.3.19-alpha.0",
85
85
  "@bull-board/api": "3.7.0",
86
86
  "@bull-board/koa": "3.9.4",
87
87
  "@elastic/elasticsearch": "7.10.0",
@@ -95,6 +95,7 @@
95
95
  "bcryptjs": "2.4.3",
96
96
  "bull": "4.8.5",
97
97
  "chmodr": "1.2.0",
98
+ "chokidar": "3.5.3",
98
99
  "csvtojson": "2.0.10",
99
100
  "curlconverter": "3.21.0",
100
101
  "dotenv": "8.2.0",
@@ -138,8 +139,10 @@
138
139
  "redis": "4",
139
140
  "server-destroy": "1.0.1",
140
141
  "snowflake-promise": "^4.5.0",
142
+ "socket.io": "^4.5.1",
141
143
  "svelte": "3.49.0",
142
144
  "swagger-parser": "10.0.3",
145
+ "tar": "6.1.11",
143
146
  "to-json-schema": "0.2.5",
144
147
  "uuid": "3.3.2",
145
148
  "validate.js": "0.13.1",
@@ -196,5 +199,5 @@
196
199
  "optionalDependencies": {
197
200
  "oracledb": "5.3.0"
198
201
  },
199
- "gitHead": "01d7c9d994aa66a1d08ab71acc9e6c8eab825a47"
202
+ "gitHead": "04749bf93a17516f8f71d44b49995b2d50b080bb"
200
203
  }
@@ -58,6 +58,7 @@ async function init() {
58
58
  DEPLOYMENT_ENVIRONMENT: "development",
59
59
  BB_ADMIN_USER_EMAIL: "",
60
60
  BB_ADMIN_USER_PASSWORD: "",
61
+ PLUGINS_DIR: "",
61
62
  }
62
63
  let envFile = ""
63
64
  Object.keys(envFileJson).forEach(key => {
@@ -1327,7 +1327,7 @@
1327
1327
  "type": "string"
1328
1328
  },
1329
1329
  "datasourceId": {
1330
- "description": "The ID of the data source the query belongs to.",
1330
+ "description": "The ID of the datasource the query belongs to.",
1331
1331
  "type": "string"
1332
1332
  },
1333
1333
  "parameters": {
@@ -1386,7 +1386,7 @@
1386
1386
  "type": "string"
1387
1387
  },
1388
1388
  "datasourceId": {
1389
- "description": "The ID of the data source the query belongs to.",
1389
+ "description": "The ID of the datasource the query belongs to.",
1390
1390
  "type": "string"
1391
1391
  },
1392
1392
  "parameters": {
@@ -2289,7 +2289,7 @@
2289
2289
  },
2290
2290
  "responses": {
2291
2291
  "200": {
2292
- "description": "Returns the created table, including the ID which has been generated for it. This can be internal or external data sources.",
2292
+ "description": "Returns the created table, including the ID which has been generated for it. This can be internal or external datasources.",
2293
2293
  "content": {
2294
2294
  "application/json": {
2295
2295
  "schema": {
@@ -1004,7 +1004,7 @@ components:
1004
1004
  description: The ID of the query.
1005
1005
  type: string
1006
1006
  datasourceId:
1007
- description: The ID of the data source the query belongs to.
1007
+ description: The ID of the datasource the query belongs to.
1008
1008
  type: string
1009
1009
  parameters:
1010
1010
  description: The bindings which are required to perform this query.
@@ -1051,7 +1051,7 @@ components:
1051
1051
  description: The ID of the query.
1052
1052
  type: string
1053
1053
  datasourceId:
1054
- description: The ID of the data source the query belongs to.
1054
+ description: The ID of the datasource the query belongs to.
1055
1055
  type: string
1056
1056
  parameters:
1057
1057
  description: The bindings which are required to perform this query.
@@ -1665,7 +1665,7 @@ paths:
1665
1665
  responses:
1666
1666
  "200":
1667
1667
  description: Returns the created table, including the ID which has been
1668
- generated for it. This can be internal or external data sources.
1668
+ generated for it. This can be internal or external datasources.
1669
1669
  content:
1670
1670
  application/json:
1671
1671
  schema:
@@ -82,7 +82,7 @@ const querySchema = object(
82
82
  type: "string",
83
83
  },
84
84
  datasourceId: {
85
- description: "The ID of the data source the query belongs to.",
85
+ description: "The ID of the datasource the query belongs to.",
86
86
  type: "string",
87
87
  },
88
88
  parameters: {
@@ -572,7 +572,7 @@ export const sync = async (ctx: any, next: any) => {
572
572
  }
573
573
  }
574
574
 
575
- const updateAppPackage = async (appPackage: any, appId: any) => {
575
+ export const updateAppPackage = async (appPackage: any, appId: any) => {
576
576
  return context.doInAppContext(appId, async () => {
577
577
  const db = context.getAppDB()
578
578
  const application = await db.get(DocumentType.APP_METADATA)
@@ -1,6 +1,7 @@
1
- const { DocumentType } = require("../../db/utils")
1
+ const { DocumentType, getPluginParams } = require("../../db/utils")
2
2
  const { getComponentLibraryManifest } = require("../../utilities/fileSystem")
3
3
  const { getAppDB } = require("@budibase/backend-core/context")
4
+ const { getGlobalDB } = require("@budibase/backend-core/tenancy")
4
5
 
5
6
  exports.fetchAppComponentDefinitions = async function (ctx) {
6
7
  try {
@@ -10,7 +11,6 @@ exports.fetchAppComponentDefinitions = async function (ctx) {
10
11
  let componentManifests = await Promise.all(
11
12
  app.componentLibraries.map(async library => {
12
13
  let manifest = await getComponentLibraryManifest(library)
13
-
14
14
  return {
15
15
  manifest,
16
16
  library,
@@ -31,6 +31,25 @@ exports.fetchAppComponentDefinitions = async function (ctx) {
31
31
  }
32
32
  }
33
33
  }
34
+
35
+ // Add custom components
36
+ const globalDB = getGlobalDB()
37
+ const response = await globalDB.allDocs(
38
+ getPluginParams(null, {
39
+ include_docs: true,
40
+ })
41
+ )
42
+ response.rows
43
+ .map(row => row.doc)
44
+ .filter(plugin => plugin.schema.type === "component")
45
+ .forEach(plugin => {
46
+ const fullComponentName = `plugin/${plugin.name}`
47
+ definitions[fullComponentName] = {
48
+ component: fullComponentName,
49
+ ...plugin.schema.schema,
50
+ }
51
+ })
52
+
34
53
  ctx.body = definitions
35
54
  } catch (err) {
36
55
  console.error(`component-definitions=failed`, err)
@@ -7,7 +7,7 @@ const {
7
7
  getTableParams,
8
8
  } = require("../../db/utils")
9
9
  const { BuildSchemaErrors, InvalidColumns } = require("../../constants")
10
- const { integrations } = require("../../integrations")
10
+ const { getIntegration } = require("../../integrations")
11
11
  const { getDatasourceAndQuery } = require("./row/utils")
12
12
  const { invalidateDynamicVariables } = require("../../threads/utils")
13
13
  const { getAppDB } = require("@budibase/backend-core/context")
@@ -50,9 +50,23 @@ exports.fetch = async function (ctx) {
50
50
  exports.buildSchemaFromDb = async function (ctx) {
51
51
  const db = getAppDB()
52
52
  const datasource = await db.get(ctx.params.datasourceId)
53
+ const tablesFilter = ctx.request.body.tablesFilter
53
54
 
54
- const { tables, error } = await buildSchemaHelper(datasource)
55
- datasource.entities = tables
55
+ let { tables, error } = await buildSchemaHelper(datasource)
56
+ if (tablesFilter) {
57
+ if (!datasource.entities) {
58
+ datasource.entities = {}
59
+ }
60
+ for (let key in tables) {
61
+ if (
62
+ tablesFilter.some(filter => filter.toLowerCase() === key.toLowerCase())
63
+ ) {
64
+ datasource.entities[key] = tables[key]
65
+ }
66
+ }
67
+ } else {
68
+ datasource.entities = tables
69
+ }
56
70
 
57
71
  const dbResp = await db.put(datasource)
58
72
  datasource._rev = dbResp.rev
@@ -114,7 +128,7 @@ exports.update = async function (ctx) {
114
128
 
115
129
  // Drain connection pools when configuration is changed
116
130
  if (datasource.source) {
117
- const source = integrations[datasource.source]
131
+ const source = await getIntegration(datasource.source)
118
132
  if (source && source.pool) {
119
133
  await source.pool.end()
120
134
  }
@@ -149,7 +163,7 @@ exports.save = async function (ctx) {
149
163
 
150
164
  // Drain connection pools when configuration is changed
151
165
  if (datasource.source) {
152
- const source = integrations[datasource.source]
166
+ const source = await getIntegration(datasource.source)
153
167
  if (source && source.pool) {
154
168
  await source.pool.end()
155
169
  }
@@ -218,15 +232,14 @@ function updateError(error, newError, tables) {
218
232
  }
219
233
 
220
234
  const buildSchemaHelper = async datasource => {
221
- const Connector = integrations[datasource.source]
235
+ const Connector = await getIntegration(datasource.source)
222
236
 
223
237
  // Connect to the DB and build the schema
224
238
  const connector = new Connector(datasource.config)
225
239
  await connector.buildSchema(datasource._id, datasource.entities)
226
- datasource.entities = connector.tables
227
240
 
228
241
  // make sure they all have a display name selected
229
- for (let entity of Object.values(datasource.entities)) {
242
+ for (let entity of Object.values(datasource.entities ?? {})) {
230
243
  if (entity.primaryDisplay) {
231
244
  continue
232
245
  }
@@ -1,12 +1,11 @@
1
- const { cloneDeep } = require("lodash")
2
- const { definitions } = require("../../integrations")
1
+ const { getDefinitions } = require("../../integrations")
3
2
  const { SourceName } = require("@budibase/types")
4
3
  const googlesheets = require("../../integrations/googlesheets")
5
4
  const { featureFlags } = require("@budibase/backend-core")
6
5
 
7
6
  exports.fetch = async function (ctx) {
8
7
  ctx.status = 200
9
- const defs = cloneDeep(definitions)
8
+ const defs = await getDefinitions()
10
9
 
11
10
  // for google sheets integration google verification
12
11
  if (featureFlags.isEnabled(featureFlags.FeatureFlag.GOOGLE_SHEETS)) {
@@ -17,6 +16,7 @@ exports.fetch = async function (ctx) {
17
16
  }
18
17
 
19
18
  exports.find = async function (ctx) {
19
+ const defs = await getDefinitions()
20
20
  ctx.status = 200
21
- ctx.body = definitions[ctx.params.type]
21
+ ctx.body = defs[ctx.params.type]
22
22
  }
@@ -0,0 +1,15 @@
1
+ import {
2
+ createTempFolder,
3
+ getPluginMetadata,
4
+ extractTarball,
5
+ } from "../../../utilities/fileSystem"
6
+
7
+ export async function fileUpload(file: { name: string; path: string }) {
8
+ if (!file.name.endsWith(".tar.gz")) {
9
+ throw new Error("Plugin must be compressed into a gzipped tarball.")
10
+ }
11
+ const path = createTempFolder(file.name.split(".tar.gz")[0])
12
+ await extractTarball(file.path, path)
13
+
14
+ return await getPluginMetadata(path)
15
+ }
@@ -0,0 +1,75 @@
1
+ import { getPluginMetadata } from "../../../utilities/fileSystem"
2
+ import fetch from "node-fetch"
3
+ import { downloadUnzipTarball } from "./utils"
4
+
5
+ export async function request(
6
+ url: string,
7
+ headers: { [key: string]: string },
8
+ err: string
9
+ ) {
10
+ const response = await fetch(url, { headers })
11
+ if (response.status >= 300) {
12
+ const respErr = await response.text()
13
+ throw new Error(`Error: ${err} - ${respErr}`)
14
+ }
15
+ return response.json()
16
+ }
17
+
18
+ export async function githubUpload(url: string, name = "", token = "") {
19
+ let githubUrl = url
20
+
21
+ if (!githubUrl.includes("https://github.com/")) {
22
+ throw new Error("The plugin origin must be from Github")
23
+ }
24
+
25
+ if (url.includes(".git")) {
26
+ githubUrl = url.replace(".git", "")
27
+ }
28
+
29
+ const githubApiUrl = githubUrl.replace(
30
+ "https://github.com/",
31
+ "https://api.github.com/repos/"
32
+ )
33
+ const headers: any = token ? { Authorization: `Bearer ${token}` } : {}
34
+ const pluginDetails = await request(
35
+ githubApiUrl,
36
+ headers,
37
+ "Repository not found"
38
+ )
39
+ const pluginName = pluginDetails.name || name
40
+ const pluginLatestReleaseUrl = pluginDetails?.["releases_url"]
41
+ ? pluginDetails?.["releases_url"].replace("{/id}", "/latest")
42
+ : undefined
43
+ if (!pluginLatestReleaseUrl) {
44
+ throw new Error("Github release not found")
45
+ }
46
+
47
+ const pluginReleaseDetails = await request(
48
+ pluginLatestReleaseUrl,
49
+ headers,
50
+ "Github latest release not found"
51
+ )
52
+ const pluginReleaseTarballAsset = pluginReleaseDetails?.assets?.find(
53
+ (x: any) => x?.["content_type"] === "application/gzip"
54
+ )
55
+ const pluginLastReleaseTarballUrl =
56
+ pluginReleaseTarballAsset?.["browser_download_url"]
57
+ if (!pluginLastReleaseTarballUrl) {
58
+ throw new Error("Github latest release url not found")
59
+ }
60
+
61
+ try {
62
+ const path = await downloadUnzipTarball(
63
+ pluginLastReleaseTarballUrl,
64
+ pluginName,
65
+ headers
66
+ )
67
+ return await getPluginMetadata(path)
68
+ } catch (err: any) {
69
+ let errMsg = err?.message || err
70
+ if (errMsg === "unexpected response Not Found") {
71
+ errMsg = "Github release tarball not found"
72
+ }
73
+ throw new Error(errMsg)
74
+ }
75
+ }