@budibase/server 2.5.6-alpha.1 → 2.5.6-alpha.10

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 (121) hide show
  1. package/builder/assets/{index.1fe52b59.js → index.5c1a6913.js} +361 -361
  2. package/builder/assets/index.c0265b74.css +6 -0
  3. package/builder/index.html +2 -2
  4. package/dist/api/controllers/automation.js +13 -7
  5. package/dist/api/controllers/plugin/index.js +6 -37
  6. package/dist/api/controllers/table/utils.js +2 -1
  7. package/dist/api/controllers/user.js +1 -83
  8. package/dist/api/routes/user.js +0 -1
  9. package/dist/app.js +2 -2
  10. package/dist/automations/actions.js +32 -6
  11. package/dist/automations/index.js +3 -2
  12. package/dist/automations/steps/bash.js +6 -6
  13. package/dist/automations/steps/createRow.js +11 -11
  14. package/dist/automations/steps/delay.js +3 -3
  15. package/dist/automations/steps/deleteRow.js +8 -8
  16. package/dist/automations/steps/discord.js +8 -8
  17. package/dist/automations/steps/executeQuery.js +9 -9
  18. package/dist/automations/steps/executeScript.js +6 -6
  19. package/dist/automations/steps/filter.js +6 -6
  20. package/dist/automations/steps/integromat.js +10 -10
  21. package/dist/automations/steps/loop.js +9 -9
  22. package/dist/automations/steps/outgoingWebhook.js +10 -10
  23. package/dist/automations/steps/queryRows.js +14 -14
  24. package/dist/automations/steps/sendSmtpEmail.js +9 -9
  25. package/dist/automations/steps/serverLog.js +4 -4
  26. package/dist/automations/steps/slack.js +6 -6
  27. package/dist/automations/steps/updateRow.js +11 -11
  28. package/dist/automations/steps/zapier.js +9 -9
  29. package/dist/automations/triggerInfo/app.js +5 -5
  30. package/dist/automations/triggerInfo/cron.js +4 -4
  31. package/dist/automations/triggerInfo/rowDeleted.js +5 -5
  32. package/dist/automations/triggerInfo/rowSaved.js +7 -7
  33. package/dist/automations/triggerInfo/rowUpdated.js +7 -7
  34. package/dist/automations/triggerInfo/webhook.js +6 -6
  35. package/dist/events/docUpdates/index.js +17 -0
  36. package/dist/events/docUpdates/processors.js +18 -0
  37. package/dist/events/docUpdates/syncUsers.js +49 -0
  38. package/dist/events/index.js +3 -0
  39. package/dist/integrations/index.js +3 -3
  40. package/dist/package.json +9 -8
  41. package/dist/sdk/app/applications/sync.js +117 -23
  42. package/dist/sdk/index.js +2 -0
  43. package/dist/sdk/plugins/index.js +27 -0
  44. package/dist/sdk/plugins/plugins.js +53 -0
  45. package/dist/sdk/users/utils.js +21 -4
  46. package/dist/startup.js +2 -1
  47. package/dist/threads/automation.js +2 -2
  48. package/dist/tsconfig.build.tsbuildinfo +1 -1
  49. package/dist/utilities/fileSystem/plugin.js +33 -23
  50. package/dist/utilities/global.js +17 -12
  51. package/dist/watch.js +2 -2
  52. package/dist/websockets/client.js +14 -0
  53. package/dist/websockets/grid.js +60 -0
  54. package/dist/websockets/index.js +17 -0
  55. package/dist/websockets/websocket.js +78 -0
  56. package/jest.config.ts +3 -3
  57. package/nodemon.json +7 -3
  58. package/package.json +10 -9
  59. package/src/api/controllers/automation.ts +12 -6
  60. package/src/api/controllers/plugin/index.ts +8 -45
  61. package/src/api/controllers/row/internal.ts +9 -10
  62. package/src/api/controllers/row/utils.ts +2 -2
  63. package/src/api/controllers/table/utils.ts +2 -1
  64. package/src/api/controllers/user.ts +10 -96
  65. package/src/api/routes/tests/automation.spec.js +2 -2
  66. package/src/api/routes/tests/user.spec.js +0 -37
  67. package/src/api/routes/user.ts +0 -5
  68. package/src/app.ts +2 -2
  69. package/src/automations/actions.ts +56 -24
  70. package/src/automations/index.ts +1 -1
  71. package/src/automations/steps/bash.ts +10 -7
  72. package/src/automations/steps/createRow.ts +15 -12
  73. package/src/automations/steps/delay.ts +6 -4
  74. package/src/automations/steps/deleteRow.ts +12 -9
  75. package/src/automations/steps/discord.ts +10 -8
  76. package/src/automations/steps/executeQuery.ts +13 -10
  77. package/src/automations/steps/executeScript.ts +10 -7
  78. package/src/automations/steps/filter.ts +8 -6
  79. package/src/automations/steps/integromat.ts +12 -10
  80. package/src/automations/steps/loop.ts +16 -10
  81. package/src/automations/steps/outgoingWebhook.ts +14 -11
  82. package/src/automations/steps/queryRows.ts +18 -15
  83. package/src/automations/steps/sendSmtpEmail.ts +11 -9
  84. package/src/automations/steps/serverLog.ts +6 -4
  85. package/src/automations/steps/slack.ts +8 -6
  86. package/src/automations/steps/updateRow.ts +15 -12
  87. package/src/automations/steps/zapier.ts +11 -9
  88. package/src/automations/tests/utilities/index.ts +2 -2
  89. package/src/automations/triggerInfo/app.ts +8 -5
  90. package/src/automations/triggerInfo/cron.ts +7 -4
  91. package/src/automations/triggerInfo/rowDeleted.ts +8 -5
  92. package/src/automations/triggerInfo/rowSaved.ts +10 -7
  93. package/src/automations/triggerInfo/rowUpdated.ts +10 -7
  94. package/src/automations/triggerInfo/webhook.ts +9 -6
  95. package/src/events/docUpdates/index.ts +1 -0
  96. package/src/events/docUpdates/processors.ts +14 -0
  97. package/src/events/docUpdates/syncUsers.ts +35 -0
  98. package/src/events/index.ts +1 -0
  99. package/src/integrations/index.ts +3 -3
  100. package/src/sdk/app/applications/sync.ts +129 -22
  101. package/src/sdk/app/applications/tests/sync.spec.ts +137 -0
  102. package/src/sdk/index.ts +2 -0
  103. package/src/sdk/plugins/index.ts +5 -0
  104. package/src/sdk/plugins/plugins.ts +41 -0
  105. package/src/sdk/users/tests/utils.spec.ts +1 -32
  106. package/src/sdk/users/utils.ts +23 -5
  107. package/src/startup.ts +2 -1
  108. package/src/tests/utilities/TestConfiguration.ts +28 -0
  109. package/src/tests/utilities/structures.ts +25 -17
  110. package/src/threads/automation.ts +2 -2
  111. package/src/utilities/fileSystem/plugin.ts +13 -4
  112. package/src/utilities/global.ts +21 -16
  113. package/src/watch.ts +2 -2
  114. package/src/websockets/client.ts +11 -0
  115. package/src/websockets/grid.ts +55 -0
  116. package/src/websockets/index.ts +14 -0
  117. package/src/websockets/websocket.ts +83 -0
  118. package/tsconfig.json +1 -7
  119. package/builder/assets/index.841e62d8.css +0 -6
  120. package/dist/websocket.js +0 -22
  121. package/src/websocket.ts +0 -26
@@ -12,12 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getDatasourcePlugin = exports.getPluginMetadata = void 0;
15
+ exports.getAutomationPlugin = exports.getDatasourcePlugin = exports.getPluginMetadata = void 0;
16
16
  const budibaseDir_1 = require("../budibaseDir");
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const path_1 = require("path");
19
19
  const backend_core_1 = require("@budibase/backend-core");
20
20
  const DATASOURCE_PATH = (0, path_1.join)((0, budibaseDir_1.budibaseTempDir)(), "datasource");
21
+ const AUTOMATION_PATH = (0, path_1.join)((0, budibaseDir_1.budibaseTempDir)(), "automation");
21
22
  const getPluginMetadata = (path) => __awaiter(void 0, void 0, void 0, function* () {
22
23
  let metadata = {};
23
24
  try {
@@ -37,30 +38,39 @@ const getPluginMetadata = (path) => __awaiter(void 0, void 0, void 0, function*
37
38
  return { metadata, directory: path };
38
39
  });
39
40
  exports.getPluginMetadata = getPluginMetadata;
40
- const getDatasourcePlugin = (plugin) => __awaiter(void 0, void 0, void 0, function* () {
41
+ function getPluginImpl(path, plugin) {
41
42
  var _a;
42
- const hash = (_a = plugin.schema) === null || _a === void 0 ? void 0 : _a.hash;
43
- if (!fs_1.default.existsSync(DATASOURCE_PATH)) {
44
- fs_1.default.mkdirSync(DATASOURCE_PATH);
45
- }
46
- const filename = (0, path_1.join)(DATASOURCE_PATH, plugin.name);
47
- const metadataName = `${filename}.bbmetadata`;
48
- if (fs_1.default.existsSync(filename)) {
49
- const currentHash = fs_1.default.readFileSync(metadataName, "utf8");
50
- // if hash is the same return the file, otherwise remove it and re-download
51
- if (currentHash === hash) {
52
- return require(filename);
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ const hash = (_a = plugin.schema) === null || _a === void 0 ? void 0 : _a.hash;
45
+ if (!fs_1.default.existsSync(path)) {
46
+ fs_1.default.mkdirSync(path);
53
47
  }
54
- else {
55
- console.log(`Updating plugin: ${plugin.name}`);
56
- delete require.cache[require.resolve(filename)];
57
- fs_1.default.unlinkSync(filename);
48
+ const filename = (0, path_1.join)(path, plugin.name);
49
+ const metadataName = `${filename}.bbmetadata`;
50
+ if (fs_1.default.existsSync(filename)) {
51
+ const currentHash = fs_1.default.readFileSync(metadataName, "utf8");
52
+ // if hash is the same return the file, otherwise remove it and re-download
53
+ if (currentHash === hash) {
54
+ return require(filename);
55
+ }
56
+ else {
57
+ console.log(`Updating plugin: ${plugin.name}`);
58
+ delete require.cache[require.resolve(filename)];
59
+ fs_1.default.unlinkSync(filename);
60
+ }
58
61
  }
59
- }
60
- const pluginKey = backend_core_1.objectStore.getPluginJSKey(plugin);
61
- const pluginJs = yield backend_core_1.objectStore.retrieve(backend_core_1.objectStore.ObjectStoreBuckets.PLUGINS, pluginKey);
62
- fs_1.default.writeFileSync(filename, pluginJs);
63
- fs_1.default.writeFileSync(metadataName, hash);
64
- return require(filename);
62
+ const pluginKey = backend_core_1.objectStore.getPluginJSKey(plugin);
63
+ const pluginJs = yield backend_core_1.objectStore.retrieve(backend_core_1.objectStore.ObjectStoreBuckets.PLUGINS, pluginKey);
64
+ fs_1.default.writeFileSync(filename, pluginJs);
65
+ fs_1.default.writeFileSync(metadataName, hash);
66
+ return require(filename);
67
+ });
68
+ }
69
+ const getDatasourcePlugin = (plugin) => __awaiter(void 0, void 0, void 0, function* () {
70
+ return getPluginImpl(DATASOURCE_PATH, plugin);
65
71
  });
66
72
  exports.getDatasourcePlugin = getDatasourcePlugin;
73
+ const getAutomationPlugin = (plugin) => __awaiter(void 0, void 0, void 0, function* () {
74
+ return getPluginImpl(AUTOMATION_PATH, plugin);
75
+ });
76
+ exports.getAutomationPlugin = getAutomationPlugin;
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getGlobalUsersFromMetadata = exports.getGlobalUsers = exports.getGlobalUser = exports.getRawGlobalUser = exports.getCachedSelf = exports.updateAppRole = void 0;
15
+ exports.getGlobalUsersFromMetadata = exports.getGlobalUsers = exports.getGlobalUser = exports.getRawGlobalUser = exports.getCachedSelf = exports.processUser = exports.updateAppRole = void 0;
16
16
  const utils_1 = require("../db/utils");
17
17
  const backend_core_1 = require("@budibase/backend-core");
18
18
  const environment_1 = __importDefault(require("../environment"));
@@ -20,7 +20,7 @@ const pro_1 = require("@budibase/pro");
20
20
  function updateAppRole(user, { appId } = {}) {
21
21
  var _a;
22
22
  appId = appId || backend_core_1.context.getAppId();
23
- if (!user || !user.roles) {
23
+ if (!user || (!user.roles && !user.userGroups)) {
24
24
  return user;
25
25
  }
26
26
  // if in an multi-tenancy environment make sure roles are never updated
@@ -31,7 +31,7 @@ function updateAppRole(user, { appId } = {}) {
31
31
  return user;
32
32
  }
33
33
  // always use the deployed app
34
- if (appId) {
34
+ if (appId && user.roles) {
35
35
  user.roleId = user.roles[backend_core_1.db.getProdAppID(appId)];
36
36
  }
37
37
  // if a role wasn't found then either set as admin (builder) or public (everyone else)
@@ -76,6 +76,7 @@ function processUser(user, opts = {}) {
76
76
  return user;
77
77
  });
78
78
  }
79
+ exports.processUser = processUser;
79
80
  function getCachedSelf(ctx, appId) {
80
81
  var _a;
81
82
  return __awaiter(this, void 0, void 0, function* () {
@@ -101,15 +102,13 @@ function getGlobalUser(userId) {
101
102
  });
102
103
  }
103
104
  exports.getGlobalUser = getGlobalUser;
104
- function getGlobalUsers(users) {
105
+ function getGlobalUsers(userIds, opts) {
105
106
  return __awaiter(this, void 0, void 0, function* () {
106
107
  const appId = backend_core_1.context.getAppId();
107
108
  const db = backend_core_1.tenancy.getGlobalDB();
108
- const allGroups = yield pro_1.groups.fetch();
109
109
  let globalUsers;
110
- if (users) {
111
- const globalIds = users.map(user => (0, utils_1.getGlobalIDFromUserMetadataID)(user._id));
112
- globalUsers = (yield db.allDocs((0, utils_1.getMultiIDParams)(globalIds))).rows.map(row => row.doc);
110
+ if (userIds) {
111
+ globalUsers = (yield db.allDocs((0, utils_1.getMultiIDParams)(userIds))).rows.map(row => row.doc);
113
112
  }
114
113
  else {
115
114
  globalUsers = (yield db.allDocs(backend_core_1.db.getGlobalUserParams(null, {
@@ -126,15 +125,21 @@ function getGlobalUsers(users) {
126
125
  if (!appId) {
127
126
  return globalUsers;
128
127
  }
129
- // pass in the groups, meaning we don't actually need to retrieve them for
130
- // each user individually
131
- return Promise.all(globalUsers.map(user => processUser(user, { groups: allGroups })));
128
+ if (opts === null || opts === void 0 ? void 0 : opts.noProcessing) {
129
+ return globalUsers;
130
+ }
131
+ else {
132
+ // pass in the groups, meaning we don't actually need to retrieve them for
133
+ // each user individually
134
+ const allGroups = yield pro_1.groups.fetch();
135
+ return Promise.all(globalUsers.map(user => processUser(user, { groups: allGroups })));
136
+ }
132
137
  });
133
138
  }
134
139
  exports.getGlobalUsers = getGlobalUsers;
135
140
  function getGlobalUsersFromMetadata(users) {
136
141
  return __awaiter(this, void 0, void 0, function* () {
137
- const globalUsers = yield getGlobalUsers(users);
142
+ const globalUsers = yield getGlobalUsers(users.map(user => user._id));
138
143
  return users.map(user => {
139
144
  const globalUser = globalUsers.find(globalUser => { var _a; return globalUser && ((_a = user._id) === null || _a === void 0 ? void 0 : _a.includes(globalUser._id)); });
140
145
  return Object.assign(Object.assign({}, globalUser), user);
package/dist/watch.js CHANGED
@@ -18,7 +18,7 @@ const environment_1 = __importDefault(require("./environment"));
18
18
  const chokidar_1 = __importDefault(require("chokidar"));
19
19
  const fs_1 = __importDefault(require("fs"));
20
20
  const backend_core_1 = require("@budibase/backend-core");
21
- const plugin_1 = require("./api/controllers/plugin");
21
+ const plugins_1 = __importDefault(require("./sdk/plugins"));
22
22
  function watch() {
23
23
  const watchPath = path_1.default.join(environment_1.default.PLUGINS_DIR, "./**/*.tar.gz");
24
24
  chokidar_1.default
@@ -41,7 +41,7 @@ function watch() {
41
41
  const split = path.split("/");
42
42
  const name = split[split.length - 1];
43
43
  console.log("Importing plugin:", path);
44
- yield (0, plugin_1.processUploadedPlugin)({ name, path });
44
+ yield plugins_1.default.processUploaded({ name, path });
45
45
  }
46
46
  catch (err) {
47
47
  const message = (err === null || err === void 0 ? void 0 : err.message) ? err === null || err === void 0 ? void 0 : err.message : err;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const websocket_1 = __importDefault(require("./websocket"));
7
+ const authorized_1 = __importDefault(require("../middleware/authorized"));
8
+ const backend_core_1 = require("@budibase/backend-core");
9
+ class ClientAppWebsocket extends websocket_1.default {
10
+ constructor(app, server) {
11
+ super(app, server, "/socket/client", [(0, authorized_1.default)(backend_core_1.permissions.BUILDER)]);
12
+ }
13
+ }
14
+ exports.default = ClientAppWebsocket;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const authorized_1 = __importDefault(require("../middleware/authorized"));
16
+ const websocket_1 = __importDefault(require("./websocket"));
17
+ const backend_core_1 = require("@budibase/backend-core");
18
+ class GridSocket extends websocket_1.default {
19
+ constructor(app, server) {
20
+ super(app, server, "/socket/grid", [(0, authorized_1.default)(backend_core_1.permissions.BUILDER)]);
21
+ this.io.on("connection", socket => {
22
+ const user = socket.data.user;
23
+ console.log(`Spreadsheet user connected: ${user === null || user === void 0 ? void 0 : user.id}`);
24
+ // Socket state
25
+ let currentRoom;
26
+ // Initial identification of connected spreadsheet
27
+ socket.on("select-table", (tableId, callback) => __awaiter(this, void 0, void 0, function* () {
28
+ // Leave current room
29
+ if (currentRoom) {
30
+ socket.to(currentRoom).emit("user-disconnect", socket.data.user);
31
+ socket.leave(currentRoom);
32
+ }
33
+ // Join new room
34
+ currentRoom = tableId;
35
+ socket.join(currentRoom);
36
+ socket.to(currentRoom).emit("user-update", socket.data.user);
37
+ // Reply with all users in current room
38
+ const sockets = yield this.io.in(currentRoom).fetchSockets();
39
+ callback({
40
+ users: sockets.map(socket => socket.data.user),
41
+ id: user.id,
42
+ });
43
+ }));
44
+ // Handle users selecting a new cell
45
+ socket.on("select-cell", cellId => {
46
+ socket.data.user.selectedCellId = cellId;
47
+ if (currentRoom) {
48
+ socket.to(currentRoom).emit("user-update", socket.data.user);
49
+ }
50
+ });
51
+ // Disconnection cleanup
52
+ socket.on("disconnect", () => {
53
+ if (currentRoom) {
54
+ socket.to(currentRoom).emit("user-disconnect", socket.data.user);
55
+ }
56
+ });
57
+ });
58
+ }
59
+ }
60
+ exports.default = GridSocket;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.gridSocket = exports.clientAppSocket = exports.initialise = void 0;
7
+ const grid_1 = __importDefault(require("./grid"));
8
+ const client_1 = __importDefault(require("./client"));
9
+ let clientAppSocket;
10
+ exports.clientAppSocket = clientAppSocket;
11
+ let gridSocket;
12
+ exports.gridSocket = gridSocket;
13
+ const initialise = (app, server) => {
14
+ exports.clientAppSocket = clientAppSocket = new client_1.default(app, server);
15
+ exports.gridSocket = gridSocket = new grid_1.default(app, server);
16
+ };
17
+ exports.initialise = initialise;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const socket_io_1 = require("socket.io");
16
+ const http_1 = __importDefault(require("http"));
17
+ const cookies_1 = __importDefault(require("cookies"));
18
+ const koa_useragent_1 = require("koa-useragent");
19
+ const backend_core_1 = require("@budibase/backend-core");
20
+ const currentapp_1 = __importDefault(require("../middleware/currentapp"));
21
+ class Socket {
22
+ constructor(app, server, path, additionalMiddlewares) {
23
+ this.io = new socket_io_1.Server(server, {
24
+ path,
25
+ });
26
+ // Attach default middlewares
27
+ const authenticate = backend_core_1.auth.buildAuthMiddleware([], {
28
+ publicAllowed: true,
29
+ });
30
+ const middlewares = [
31
+ koa_useragent_1.userAgent,
32
+ authenticate,
33
+ currentapp_1.default,
34
+ ...(additionalMiddlewares || []),
35
+ ];
36
+ // Apply middlewares
37
+ this.io.use((socket, next) => __awaiter(this, void 0, void 0, function* () {
38
+ // Build fake koa context
39
+ const res = new http_1.default.ServerResponse(socket.request);
40
+ const ctx = Object.assign(Object.assign({}, app.createContext(socket.request, res)), {
41
+ // Additional overrides needed to make our middlewares work with this
42
+ // fake koa context
43
+ cookies: new cookies_1.default(socket.request, res), get: (field) => socket.request.headers[field], throw: (code, message) => {
44
+ throw new Error(message);
45
+ },
46
+ // Needed for koa-useragent middleware
47
+ headers: socket.request.headers, header: socket.request.headers,
48
+ // We don't really care about the path since it will never contain
49
+ // an app ID
50
+ path: "/socket" });
51
+ // Run all koa middlewares
52
+ try {
53
+ for (let [idx, middleware] of middlewares.entries()) {
54
+ yield middleware(ctx, () => {
55
+ if (idx === middlewares.length - 1) {
56
+ // Middlewares are finished.
57
+ // Extract some data from our enriched koa context to persist
58
+ // as metadata for the socket
59
+ socket.data.user = {
60
+ id: ctx.user._id,
61
+ email: ctx.user.email,
62
+ };
63
+ next();
64
+ }
65
+ });
66
+ }
67
+ }
68
+ catch (error) {
69
+ next(error);
70
+ }
71
+ }));
72
+ }
73
+ // Emit an event to all sockets
74
+ emit(event, payload) {
75
+ this.io.sockets.emit(event, payload);
76
+ }
77
+ }
78
+ exports.default = Socket;
package/jest.config.ts CHANGED
@@ -20,9 +20,9 @@ const baseConfig: Config.InitialProjectOptions = {
20
20
  }
21
21
 
22
22
  // add pro sources if they exist
23
- if (fs.existsSync("../../../budibase-pro")) {
24
- baseConfig.moduleNameMapper["@budibase/pro"] =
25
- "<rootDir>/../../../budibase-pro/packages/pro/src"
23
+ if (fs.existsSync("../pro/packages")) {
24
+ baseConfig.moduleNameMapper!["@budibase/pro"] =
25
+ "<rootDir>/../pro/packages/pro/src"
26
26
  }
27
27
 
28
28
  const config: Config.InitialOptions = {
package/nodemon.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
- "watch": ["src", "../backend-core", "../../../budibase-pro/packages/pro"],
2
+ "watch": ["src", "../backend-core", "../pro/packages/pro"],
3
3
  "ext": "js,ts,json",
4
- "ignore": ["src/**/*.spec.ts", "src/**/*.spec.js", "../backend-core/dist/**/*"],
4
+ "ignore": [
5
+ "src/**/*.spec.ts",
6
+ "src/**/*.spec.js",
7
+ "../backend-core/dist/**/*"
8
+ ],
5
9
  "exec": "ts-node src/index.ts"
6
- }
10
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.5.6-alpha.1",
4
+ "version": "2.5.6-alpha.10",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -45,12 +45,12 @@
45
45
  "license": "GPL-3.0",
46
46
  "dependencies": {
47
47
  "@apidevtools/swagger-parser": "10.0.3",
48
- "@budibase/backend-core": "2.5.6-alpha.1",
49
- "@budibase/client": "2.5.6-alpha.1",
50
- "@budibase/pro": "2.5.5-alpha.4",
51
- "@budibase/shared-core": "2.5.6-alpha.1",
52
- "@budibase/string-templates": "2.5.6-alpha.1",
53
- "@budibase/types": "2.5.6-alpha.1",
48
+ "@budibase/backend-core": "2.5.6-alpha.10",
49
+ "@budibase/client": "2.5.6-alpha.10",
50
+ "@budibase/pro": "2.5.6-alpha.6",
51
+ "@budibase/shared-core": "2.5.6-alpha.10",
52
+ "@budibase/string-templates": "2.5.6-alpha.10",
53
+ "@budibase/types": "2.5.6-alpha.10",
54
54
  "@bull-board/api": "3.7.0",
55
55
  "@bull-board/koa": "3.9.4",
56
56
  "@elastic/elasticsearch": "7.10.0",
@@ -65,6 +65,7 @@
65
65
  "bull": "4.10.1",
66
66
  "chmodr": "1.2.0",
67
67
  "chokidar": "3.5.3",
68
+ "cookies": "0.8.0",
68
69
  "csvtojson": "2.0.10",
69
70
  "curlconverter": "3.21.0",
70
71
  "dd-trace": "3.13.2",
@@ -108,7 +109,7 @@
108
109
  "redis": "4",
109
110
  "server-destroy": "1.0.1",
110
111
  "snowflake-promise": "^4.5.0",
111
- "socket.io": "^4.5.1",
112
+ "socket.io": "4.6.1",
112
113
  "svelte": "3.49.0",
113
114
  "swagger-parser": "10.0.3",
114
115
  "tar": "6.1.11",
@@ -175,5 +176,5 @@
175
176
  "optionalDependencies": {
176
177
  "oracledb": "5.3.0"
177
178
  },
178
- "gitHead": "fdc38d656252b7b81508245e20ca65ef2739a363"
179
+ "gitHead": "5cd18e57d5c371d2dc375e20469f123e81aaec13"
179
180
  }
@@ -16,9 +16,15 @@ import { setTestFlag, clearTestFlag } from "../../utilities/redis"
16
16
  import { context, cache, events } from "@budibase/backend-core"
17
17
  import { automations } from "@budibase/pro"
18
18
  import { Automation, BBContext } from "@budibase/types"
19
+ import { getActionDefinitions as actionDefs } from "../../automations/actions"
19
20
 
20
- const ACTION_DEFS = removeDeprecated(actions.ACTION_DEFINITIONS)
21
- const TRIGGER_DEFS = removeDeprecated(triggers.TRIGGER_DEFINITIONS)
21
+ async function getActionDefinitions() {
22
+ return removeDeprecated(await actionDefs())
23
+ }
24
+
25
+ function getTriggerDefinitions() {
26
+ return removeDeprecated(triggers.TRIGGER_DEFINITIONS)
27
+ }
22
28
 
23
29
  /*************************
24
30
  * *
@@ -228,17 +234,17 @@ export async function clearLogError(ctx: BBContext) {
228
234
  }
229
235
 
230
236
  export async function getActionList(ctx: BBContext) {
231
- ctx.body = ACTION_DEFS
237
+ ctx.body = await getActionDefinitions()
232
238
  }
233
239
 
234
240
  export async function getTriggerList(ctx: BBContext) {
235
- ctx.body = TRIGGER_DEFS
241
+ ctx.body = getTriggerDefinitions()
236
242
  }
237
243
 
238
244
  export async function getDefinitionList(ctx: BBContext) {
239
245
  ctx.body = {
240
- trigger: TRIGGER_DEFS,
241
- action: ACTION_DEFS,
246
+ trigger: getTriggerDefinitions(),
247
+ action: await getActionDefinitions(),
242
248
  }
243
249
  }
244
250
 
@@ -1,31 +1,11 @@
1
- import { npmUpload, urlUpload, githubUpload, fileUpload } from "./uploaders"
2
- import {
3
- plugins as pluginCore,
4
- db as dbCore,
5
- tenancy,
6
- objectStore,
7
- } from "@budibase/backend-core"
8
- import { PluginType, FileType, PluginSource, Plugin } from "@budibase/types"
1
+ import { npmUpload, urlUpload, githubUpload } from "./uploaders"
2
+ import { plugins as pluginCore } from "@budibase/backend-core"
3
+ import { PluginType, FileType, PluginSource } from "@budibase/types"
9
4
  import env from "../../../environment"
10
- import { ClientAppSocket } from "../../../websocket"
5
+ import { clientAppSocket } from "../../../websockets"
6
+ import sdk from "../../../sdk"
11
7
  import { sdk as pro } from "@budibase/pro"
12
8
 
13
- export async function getPlugins(type?: PluginType) {
14
- const db = tenancy.getGlobalDB()
15
- const response = await db.allDocs(
16
- dbCore.getPluginParams(null, {
17
- include_docs: true,
18
- })
19
- )
20
- let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
21
- plugins = objectStore.enrichPluginURLs(plugins)
22
- if (type) {
23
- return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
24
- } else {
25
- return plugins
26
- }
27
- }
28
-
29
9
  export async function upload(ctx: any) {
30
10
  const plugins: FileType[] =
31
11
  ctx.request.files.file.length > 1
@@ -35,7 +15,7 @@ export async function upload(ctx: any) {
35
15
  let docs = []
36
16
  // can do single or multiple plugins
37
17
  for (let plugin of plugins) {
38
- const doc = await processUploadedPlugin(plugin, PluginSource.FILE)
18
+ const doc = await sdk.plugins.processUploaded(plugin, PluginSource.FILE)
39
19
  docs.push(doc)
40
20
  }
41
21
  ctx.body = {
@@ -91,7 +71,7 @@ export async function create(ctx: any) {
91
71
 
92
72
  const doc = await pro.plugins.storePlugin(metadata, directory, source)
93
73
 
94
- ClientAppSocket.emit("plugins-update", { name, hash: doc.hash })
74
+ clientAppSocket.emit("plugins-update", { name, hash: doc.hash })
95
75
  ctx.body = {
96
76
  message: "Plugin uploaded successfully",
97
77
  plugins: [doc],
@@ -105,7 +85,7 @@ export async function create(ctx: any) {
105
85
  }
106
86
 
107
87
  export async function fetch(ctx: any) {
108
- ctx.body = await getPlugins()
88
+ ctx.body = await sdk.plugins.fetch()
109
89
  }
110
90
 
111
91
  export async function destroy(ctx: any) {
@@ -119,20 +99,3 @@ export async function destroy(ctx: any) {
119
99
  ctx.throw(400, err.message)
120
100
  }
121
101
  }
122
-
123
- export async function processUploadedPlugin(
124
- plugin: FileType,
125
- source?: PluginSource
126
- ) {
127
- const { metadata, directory } = await fileUpload(plugin)
128
- pluginCore.validate(metadata?.schema)
129
-
130
- // Only allow components in cloud
131
- if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
132
- throw new Error("Only component plugins are supported outside of self-host")
133
- }
134
-
135
- const doc = await pro.plugins.storePlugin(metadata, directory, source)
136
- ClientAppSocket.emit("plugin-update", { name: doc.name, hash: doc.hash })
137
- return doc
138
- }
@@ -30,7 +30,6 @@ import { finaliseRow, updateRelatedFormula } from "./staticFormula"
30
30
  import { csv, json, jsonWithSchema, Format } from "../view/exporters"
31
31
  import { apiFileReturn } from "../../../utilities/fileSystem"
32
32
  import {
33
- Ctx,
34
33
  UserCtx,
35
34
  Database,
36
35
  LinkDocumentValue,
@@ -72,7 +71,7 @@ async function getView(db: Database, viewName: string) {
72
71
  return viewInfo
73
72
  }
74
73
 
75
- async function getRawTableData(ctx: Ctx, db: Database, tableId: string) {
74
+ async function getRawTableData(ctx: UserCtx, db: Database, tableId: string) {
76
75
  let rows
77
76
  if (tableId === InternalTables.USER_METADATA) {
78
77
  await userController.fetchMetadata(ctx)
@@ -188,7 +187,7 @@ export async function save(ctx: UserCtx) {
188
187
  })
189
188
  }
190
189
 
191
- export async function fetchView(ctx: Ctx) {
190
+ export async function fetchView(ctx: UserCtx) {
192
191
  const viewName = decodeURIComponent(ctx.params.viewName)
193
192
 
194
193
  // if this is a table view being looked for just transfer to that
@@ -255,7 +254,7 @@ export async function fetchView(ctx: Ctx) {
255
254
  return rows
256
255
  }
257
256
 
258
- export async function fetch(ctx: Ctx) {
257
+ export async function fetch(ctx: UserCtx) {
259
258
  const db = context.getAppDB()
260
259
 
261
260
  const tableId = ctx.params.tableId
@@ -264,7 +263,7 @@ export async function fetch(ctx: Ctx) {
264
263
  return outputProcessing(table, rows)
265
264
  }
266
265
 
267
- export async function find(ctx: Ctx) {
266
+ export async function find(ctx: UserCtx) {
268
267
  const db = dbCore.getDB(ctx.appId)
269
268
  const table = await db.get(ctx.params.tableId)
270
269
  let row = await utils.findRow(ctx, ctx.params.tableId, ctx.params.rowId)
@@ -272,7 +271,7 @@ export async function find(ctx: Ctx) {
272
271
  return row
273
272
  }
274
273
 
275
- export async function destroy(ctx: Ctx) {
274
+ export async function destroy(ctx: UserCtx) {
276
275
  const db = context.getAppDB()
277
276
  const { _id } = ctx.request.body
278
277
  let row = await db.get(_id)
@@ -308,7 +307,7 @@ export async function destroy(ctx: Ctx) {
308
307
  return { response, row }
309
308
  }
310
309
 
311
- export async function bulkDestroy(ctx: Ctx) {
310
+ export async function bulkDestroy(ctx: UserCtx) {
312
311
  const db = context.getAppDB()
313
312
  const tableId = ctx.params.tableId
314
313
  const table = await db.get(tableId)
@@ -347,7 +346,7 @@ export async function bulkDestroy(ctx: Ctx) {
347
346
  return { response: { ok: true }, rows: processedRows }
348
347
  }
349
348
 
350
- export async function search(ctx: Ctx) {
349
+ export async function search(ctx: UserCtx) {
351
350
  // Fetch the whole table when running in cypress, as search doesn't work
352
351
  if (!env.COUCH_DB_URL && env.isCypress()) {
353
352
  return { rows: await fetch(ctx) }
@@ -387,7 +386,7 @@ export async function search(ctx: Ctx) {
387
386
  return response
388
387
  }
389
388
 
390
- export async function exportRows(ctx: Ctx) {
389
+ export async function exportRows(ctx: UserCtx) {
391
390
  const db = context.getAppDB()
392
391
  const table = await db.get(ctx.params.tableId)
393
392
  const rowIds = ctx.request.body.rows
@@ -439,7 +438,7 @@ export async function exportRows(ctx: Ctx) {
439
438
  }
440
439
  }
441
440
 
442
- export async function fetchEnrichedRow(ctx: Ctx) {
441
+ export async function fetchEnrichedRow(ctx: UserCtx) {
443
442
  const db = context.getAppDB()
444
443
  const tableId = ctx.params.tableId
445
444
  const rowId = ctx.params.rowId
@@ -5,7 +5,7 @@ import { context } from "@budibase/backend-core"
5
5
  import { makeExternalQuery } from "../../../integrations/base/query"
6
6
  import { Row, Table } from "@budibase/types"
7
7
  import { Format } from "../view/exporters"
8
- import { Ctx } from "@budibase/types"
8
+ import { UserCtx } from "@budibase/types"
9
9
  import sdk from "../../../sdk"
10
10
  const validateJs = require("validate.js")
11
11
  const { cloneDeep } = require("lodash/fp")
@@ -26,7 +26,7 @@ export async function getDatasourceAndQuery(json: any) {
26
26
  return makeExternalQuery(datasource, json)
27
27
  }
28
28
 
29
- export async function findRow(ctx: Ctx, tableId: string, rowId: string) {
29
+ export async function findRow(ctx: UserCtx, tableId: string, rowId: string) {
30
30
  const db = context.getAppDB()
31
31
  let row
32
32
  // TODO remove special user case in future