@budibase/server 2.5.9 → 2.5.10-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 (198) hide show
  1. package/builder/assets/index.24635afb.js +1794 -0
  2. package/builder/assets/index.4eae16b2.css +6 -0
  3. package/builder/index.html +2 -2
  4. package/dist/api/controllers/application.js +3 -4
  5. package/dist/api/controllers/automation.js +13 -7
  6. package/dist/api/controllers/datasource.js +1 -1
  7. package/dist/api/controllers/dev.js +1 -1
  8. package/dist/api/controllers/ops.js +40 -0
  9. package/dist/api/controllers/plugin/index.js +6 -37
  10. package/dist/api/controllers/query/index.js +2 -2
  11. package/dist/api/controllers/row/ExternalRequest.js +21 -14
  12. package/dist/api/controllers/row/internal.js +5 -2
  13. package/dist/api/controllers/row/utils.js +2 -2
  14. package/dist/api/controllers/table/index.js +2 -2
  15. package/dist/api/controllers/table/utils.js +9 -3
  16. package/dist/api/controllers/user.js +1 -83
  17. package/dist/api/controllers/view/exporters.js +3 -1
  18. package/dist/api/index.js +1 -2
  19. package/dist/api/routes/index.js +2 -2
  20. package/dist/api/routes/{cloud.js → ops.js} +19 -6
  21. package/dist/api/routes/user.js +0 -1
  22. package/dist/app.js +4 -13
  23. package/dist/automations/actions.js +32 -6
  24. package/dist/automations/index.js +3 -2
  25. package/dist/automations/steps/bash.js +6 -6
  26. package/dist/automations/steps/createRow.js +11 -11
  27. package/dist/automations/steps/delay.js +3 -3
  28. package/dist/automations/steps/deleteRow.js +8 -8
  29. package/dist/automations/steps/discord.js +8 -8
  30. package/dist/automations/steps/executeQuery.js +9 -9
  31. package/dist/automations/steps/executeScript.js +6 -6
  32. package/dist/automations/steps/filter.js +6 -6
  33. package/dist/automations/steps/integromat.js +10 -10
  34. package/dist/automations/steps/loop.js +9 -9
  35. package/dist/automations/steps/outgoingWebhook.js +10 -10
  36. package/dist/automations/steps/queryRows.js +14 -14
  37. package/dist/automations/steps/sendSmtpEmail.js +9 -9
  38. package/dist/automations/steps/serverLog.js +4 -4
  39. package/dist/automations/steps/slack.js +6 -6
  40. package/dist/automations/steps/updateRow.js +11 -11
  41. package/dist/automations/steps/zapier.js +9 -9
  42. package/dist/automations/triggerInfo/app.js +5 -5
  43. package/dist/automations/triggerInfo/cron.js +4 -4
  44. package/dist/automations/triggerInfo/rowDeleted.js +5 -5
  45. package/dist/automations/triggerInfo/rowSaved.js +7 -7
  46. package/dist/automations/triggerInfo/rowUpdated.js +7 -7
  47. package/dist/automations/triggerInfo/webhook.js +6 -6
  48. package/dist/db/utils.js +3 -2
  49. package/dist/environment.js +0 -1
  50. package/dist/events/docUpdates/index.js +17 -0
  51. package/dist/events/docUpdates/processors.js +18 -0
  52. package/dist/events/docUpdates/syncUsers.js +49 -0
  53. package/dist/events/index.js +3 -0
  54. package/dist/integrations/base/sqlTable.js +9 -2
  55. package/dist/integrations/index.js +3 -3
  56. package/dist/integrations/microsoftSqlServer.js +5 -2
  57. package/dist/integrations/mysql.js +5 -3
  58. package/dist/integrations/postgres.js +7 -5
  59. package/dist/integrations/redis.js +7 -0
  60. package/dist/integrations/rest.js +4 -0
  61. package/dist/migrations/functions/syncQuotas.js +2 -0
  62. package/dist/migrations/functions/usageQuotas/syncApps.js +1 -2
  63. package/dist/migrations/functions/usageQuotas/syncRows.js +1 -2
  64. package/dist/migrations/functions/usageQuotas/syncUsers.js +21 -0
  65. package/dist/sdk/app/applications/sync.js +117 -23
  66. package/dist/sdk/app/backups/exports.js +14 -38
  67. package/dist/sdk/index.js +2 -0
  68. package/dist/sdk/plugins/index.js +27 -0
  69. package/dist/sdk/plugins/plugins.js +53 -0
  70. package/dist/sdk/users/utils.js +21 -4
  71. package/dist/startup.js +31 -28
  72. package/dist/threads/automation.js +16 -5
  73. package/dist/tsconfig.build.tsbuildinfo +1 -1
  74. package/dist/utilities/csv.js +33 -0
  75. package/dist/utilities/fileSystem/plugin.js +33 -23
  76. package/dist/utilities/global.js +17 -12
  77. package/dist/utilities/rowProcessor/utils.js +4 -5
  78. package/dist/utilities/schema.js +5 -1
  79. package/dist/watch.js +2 -2
  80. package/dist/websockets/client.js +14 -0
  81. package/dist/websockets/grid.js +60 -0
  82. package/dist/websockets/index.js +17 -0
  83. package/dist/websockets/websocket.js +78 -0
  84. package/package.json +16 -16
  85. package/scripts/dev/manage.js +2 -0
  86. package/scripts/integrations/mssql/data/entrypoint.sh +1 -0
  87. package/scripts/integrations/mssql/data/setup.sql +17 -17
  88. package/scripts/integrations/mysql/init.sql +1 -1
  89. package/scripts/integrations/postgres/init.sql +1 -0
  90. package/src/api/controllers/application.ts +4 -4
  91. package/src/api/controllers/automation.ts +12 -6
  92. package/src/api/controllers/datasource.ts +15 -5
  93. package/src/api/controllers/dev.ts +2 -2
  94. package/src/api/controllers/ops.ts +32 -0
  95. package/src/api/controllers/plugin/index.ts +8 -45
  96. package/src/api/controllers/query/index.ts +2 -2
  97. package/src/api/controllers/row/ExternalRequest.ts +21 -12
  98. package/src/api/controllers/row/internal.ts +13 -11
  99. package/src/api/controllers/row/utils.ts +4 -4
  100. package/src/api/controllers/table/index.ts +2 -2
  101. package/src/api/controllers/table/utils.ts +10 -3
  102. package/src/api/controllers/user.ts +10 -96
  103. package/src/api/controllers/view/exporters.ts +3 -1
  104. package/src/api/index.ts +2 -4
  105. package/src/api/routes/index.ts +2 -2
  106. package/src/api/routes/ops.ts +30 -0
  107. package/src/api/routes/tests/automation.spec.js +7 -4
  108. package/src/api/routes/tests/user.spec.js +48 -37
  109. package/src/api/routes/user.ts +0 -5
  110. package/src/app.ts +4 -15
  111. package/src/automations/actions.ts +56 -24
  112. package/src/automations/index.ts +1 -1
  113. package/src/automations/steps/bash.ts +10 -7
  114. package/src/automations/steps/createRow.ts +15 -12
  115. package/src/automations/steps/delay.ts +6 -4
  116. package/src/automations/steps/deleteRow.ts +12 -9
  117. package/src/automations/steps/discord.ts +10 -8
  118. package/src/automations/steps/executeQuery.ts +13 -10
  119. package/src/automations/steps/executeScript.ts +10 -7
  120. package/src/automations/steps/filter.ts +8 -6
  121. package/src/automations/steps/integromat.ts +12 -10
  122. package/src/automations/steps/loop.ts +16 -10
  123. package/src/automations/steps/outgoingWebhook.ts +14 -11
  124. package/src/automations/steps/queryRows.ts +18 -15
  125. package/src/automations/steps/sendSmtpEmail.ts +11 -9
  126. package/src/automations/steps/serverLog.ts +6 -4
  127. package/src/automations/steps/slack.ts +8 -6
  128. package/src/automations/steps/updateRow.ts +15 -12
  129. package/src/automations/steps/zapier.ts +11 -9
  130. package/src/automations/tests/utilities/index.ts +2 -2
  131. package/src/automations/triggerInfo/app.ts +8 -5
  132. package/src/automations/triggerInfo/cron.ts +7 -4
  133. package/src/automations/triggerInfo/rowDeleted.ts +8 -5
  134. package/src/automations/triggerInfo/rowSaved.ts +10 -7
  135. package/src/automations/triggerInfo/rowUpdated.ts +10 -7
  136. package/src/automations/triggerInfo/webhook.ts +9 -6
  137. package/src/db/utils.ts +1 -0
  138. package/src/environment.ts +0 -1
  139. package/src/events/docUpdates/index.ts +1 -0
  140. package/src/events/docUpdates/processors.ts +14 -0
  141. package/src/events/docUpdates/syncUsers.ts +35 -0
  142. package/src/events/index.ts +1 -0
  143. package/src/integration-test/postgres.spec.ts +3 -1
  144. package/src/integrations/base/sqlTable.ts +9 -2
  145. package/src/integrations/index.ts +3 -3
  146. package/src/integrations/microsoftSqlServer.ts +5 -2
  147. package/src/integrations/mysql.ts +5 -3
  148. package/src/integrations/postgres.ts +7 -5
  149. package/src/integrations/redis.ts +8 -0
  150. package/src/integrations/rest.ts +3 -0
  151. package/src/migrations/functions/syncQuotas.ts +2 -0
  152. package/src/migrations/functions/usageQuotas/syncApps.ts +2 -3
  153. package/src/migrations/functions/usageQuotas/syncRows.ts +2 -3
  154. package/src/migrations/functions/usageQuotas/syncUsers.ts +9 -0
  155. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +2 -2
  156. package/src/migrations/functions/usageQuotas/tests/syncUsers.spec.ts +26 -0
  157. package/src/migrations/index.ts +1 -0
  158. package/src/sdk/app/applications/sync.ts +129 -22
  159. package/src/sdk/app/applications/tests/sync.spec.ts +137 -0
  160. package/src/sdk/app/backups/exports.ts +17 -41
  161. package/src/sdk/index.ts +2 -0
  162. package/src/sdk/plugins/index.ts +5 -0
  163. package/src/sdk/plugins/plugins.ts +41 -0
  164. package/src/sdk/users/tests/utils.spec.ts +1 -32
  165. package/src/sdk/users/utils.ts +23 -5
  166. package/src/startup.ts +36 -34
  167. package/src/tests/jestEnv.ts +0 -1
  168. package/src/tests/jestSetup.ts +0 -1
  169. package/src/tests/utilities/TestConfiguration.ts +28 -0
  170. package/src/tests/utilities/structures.ts +25 -17
  171. package/src/threads/automation.ts +18 -6
  172. package/src/utilities/csv.ts +22 -0
  173. package/src/utilities/fileSystem/plugin.ts +13 -4
  174. package/src/utilities/global.ts +21 -16
  175. package/src/utilities/rowProcessor/utils.ts +9 -10
  176. package/src/utilities/schema.ts +8 -0
  177. package/src/utilities/tests/csv.spec.ts +33 -0
  178. package/src/watch.ts +2 -2
  179. package/src/websockets/client.ts +11 -0
  180. package/src/websockets/grid.ts +55 -0
  181. package/src/websockets/index.ts +14 -0
  182. package/src/websockets/websocket.ts +83 -0
  183. package/tsconfig.build.json +3 -5
  184. package/tsconfig.json +2 -1
  185. package/builder/assets/index.0b358332.js +0 -1817
  186. package/builder/assets/index.7f9a008b.css +0 -6
  187. package/dist/api/controllers/cloud.js +0 -130
  188. package/dist/elasticApm.js +0 -14
  189. package/dist/package.json +0 -180
  190. package/dist/websocket.js +0 -22
  191. package/scripts/likeCypress.ts +0 -35
  192. package/src/api/controllers/cloud.ts +0 -119
  193. package/src/api/routes/cloud.ts +0 -18
  194. package/src/api/routes/tests/cloud.spec.ts +0 -54
  195. package/src/elasticApm.ts +0 -10
  196. package/src/migrations/functions/tests/syncQuotas.spec.js +0 -26
  197. package/src/tests/logging.ts +0 -34
  198. package/src/websocket.ts +0 -26
@@ -0,0 +1,33 @@
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
+ exports.jsonFromCsvString = void 0;
16
+ const csvtojson_1 = __importDefault(require("csvtojson"));
17
+ function jsonFromCsvString(csvString) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ const castedWithEmptyValues = yield (0, csvtojson_1.default)({ ignoreEmpty: true }).fromString(csvString);
20
+ // By default the csvtojson library casts empty values as empty strings. This is causing issues on conversion.
21
+ // ignoreEmpty will remove the key completly if empty, so creating this empty object will ensure we return the values with the keys but empty values
22
+ const result = yield (0, csvtojson_1.default)({ ignoreEmpty: false }).fromString(csvString);
23
+ result.forEach((r, i) => {
24
+ for (const [key] of Object.entries(r).filter(([key, value]) => value === "")) {
25
+ if (castedWithEmptyValues[i][key] === undefined) {
26
+ r[key] = null;
27
+ }
28
+ }
29
+ });
30
+ return result;
31
+ });
32
+ }
33
+ exports.jsonFromCsvString = jsonFromCsvString;
@@ -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);
@@ -46,17 +46,16 @@ function processFormulas(table, rows, { dynamic, contextRows } = { dynamic: true
46
46
  for (let [column, schema] of Object.entries(table.schema)) {
47
47
  const isStatic = schema.formulaType === constants_1.FormulaTypes.STATIC;
48
48
  if (schema.type !== constants_1.FieldTypes.FORMULA ||
49
+ schema.formula == null ||
49
50
  (dynamic && isStatic) ||
50
51
  (!dynamic && !isStatic)) {
51
52
  continue;
52
53
  }
53
54
  // iterate through rows and process formula
54
55
  for (let i = 0; i < rowArray.length; i++) {
55
- if (schema.formula) {
56
- let row = rowArray[i];
57
- let context = contextRows ? contextRows[i] : row;
58
- rowArray[i] = Object.assign(Object.assign({}, row), { [column]: (0, string_templates_1.processStringSync)(schema.formula, context) });
59
- }
56
+ let row = rowArray[i];
57
+ let context = contextRows ? contextRows[i] : row;
58
+ rowArray[i] = Object.assign(Object.assign({}, row), { [column]: (0, string_templates_1.processStringSync)(schema.formula, context) });
60
59
  }
61
60
  }
62
61
  return single ? rowArray[0] : rowArray;
@@ -39,13 +39,17 @@ function validate(rows, schema) {
39
39
  };
40
40
  rows.forEach(row => {
41
41
  Object.entries(row).forEach(([columnName, columnData]) => {
42
- var _a, _b;
42
+ var _a, _b, _c;
43
43
  const columnType = (_a = schema[columnName]) === null || _a === void 0 ? void 0 : _a.type;
44
44
  const isAutoColumn = (_b = schema[columnName]) === null || _b === void 0 ? void 0 : _b.autocolumn;
45
45
  // If the columnType is not a string, then it's not present in the schema, and should be added to the invalid columns array
46
46
  if (typeof columnType !== "string") {
47
47
  results.invalidColumns.push(columnName);
48
48
  }
49
+ else if (columnData == null &&
50
+ !((_c = schema[columnName].constraints) === null || _c === void 0 ? void 0 : _c.presence)) {
51
+ results.schemaValidation[columnName] = true;
52
+ }
49
53
  else if (
50
54
  // If there's no data for this field don't bother with further checks
51
55
  // If the field is already marked as invalid there's no need for further checks
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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.5.9",
4
+ "version": "2.5.10-alpha.1",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -26,6 +26,7 @@
26
26
  "dev:stack:down": "node scripts/dev/manage.js down",
27
27
  "dev:stack:nuke": "node scripts/dev/manage.js nuke",
28
28
  "dev:builder": "yarn run dev:stack:up && nodemon",
29
+ "dev:built": "yarn run dev:stack:up && yarn run run:docker",
29
30
  "specs": "ts-node specs/generate.ts && openapi-typescript specs/openapi.yaml --output src/definitions/openapi.ts",
30
31
  "initialise": "node scripts/initialise.js",
31
32
  "env:multi:enable": "node scripts/multiTenancy.js enable",
@@ -44,12 +45,12 @@
44
45
  "license": "GPL-3.0",
45
46
  "dependencies": {
46
47
  "@apidevtools/swagger-parser": "10.0.3",
47
- "@budibase/backend-core": "^2.5.9",
48
- "@budibase/client": "^2.5.9",
49
- "@budibase/pro": "2.5.8",
50
- "@budibase/shared-core": "^2.5.9",
51
- "@budibase/string-templates": "^2.5.9",
52
- "@budibase/types": "^2.5.9",
48
+ "@budibase/backend-core": "2.5.10-alpha.1",
49
+ "@budibase/client": "2.5.10-alpha.1",
50
+ "@budibase/pro": "2.5.10-alpha.0",
51
+ "@budibase/shared-core": "2.5.10-alpha.1",
52
+ "@budibase/string-templates": "2.5.10-alpha.1",
53
+ "@budibase/types": "2.5.10-alpha.1",
53
54
  "@bull-board/api": "3.7.0",
54
55
  "@bull-board/koa": "3.9.4",
55
56
  "@elastic/elasticsearch": "7.10.0",
@@ -64,6 +65,7 @@
64
65
  "bull": "4.10.1",
65
66
  "chmodr": "1.2.0",
66
67
  "chokidar": "3.5.3",
68
+ "cookies": "0.8.0",
67
69
  "csvtojson": "2.0.10",
68
70
  "curlconverter": "3.21.0",
69
71
  "dd-trace": "3.13.2",
@@ -85,7 +87,6 @@
85
87
  "koa-body": "4.2.0",
86
88
  "koa-compress": "4.0.1",
87
89
  "koa-connect": "2.1.0",
88
- "koa-pino-logger": "3.0.0",
89
90
  "koa-send": "5.0.0",
90
91
  "koa-session": "5.12.0",
91
92
  "koa-static": "5.0.0",
@@ -99,7 +100,6 @@
99
100
  "node-fetch": "2.6.7",
100
101
  "open": "8.4.0",
101
102
  "pg": "8.5.1",
102
- "pino-pretty": "4.0.0",
103
103
  "posthog-node": "1.3.0",
104
104
  "pouchdb": "7.3.0",
105
105
  "pouchdb-adapter-memory": "7.2.2",
@@ -109,18 +109,17 @@
109
109
  "redis": "4",
110
110
  "server-destroy": "1.0.1",
111
111
  "snowflake-promise": "^4.5.0",
112
- "socket.io": "^4.5.1",
112
+ "socket.io": "4.6.1",
113
113
  "svelte": "3.49.0",
114
114
  "swagger-parser": "10.0.3",
115
115
  "tar": "6.1.11",
116
116
  "to-json-schema": "0.2.5",
117
117
  "uuid": "3.3.2",
118
118
  "validate.js": "0.13.1",
119
- "vm2": "^3.9.15",
119
+ "vm2": "3.9.17",
120
120
  "worker-farm": "1.7.0",
121
- "xml2js": "0.4.23",
122
- "yargs": "13.2.4",
123
- "zlib": "1.0.5"
121
+ "xml2js": "0.5.0",
122
+ "yargs": "13.2.4"
124
123
  },
125
124
  "devDependencies": {
126
125
  "@babel/core": "7.17.4",
@@ -149,7 +148,7 @@
149
148
  "@types/tar": "6.1.3",
150
149
  "@typescript-eslint/parser": "5.45.0",
151
150
  "apidoc": "0.50.4",
152
- "babel-jest": "27.5.1",
151
+ "babel-jest": "29.5.0",
153
152
  "copyfiles": "2.4.1",
154
153
  "docker-compose": "0.23.17",
155
154
  "eslint": "6.8.0",
@@ -157,6 +156,7 @@
157
156
  "is-wsl": "2.2.0",
158
157
  "jest": "29.5.0",
159
158
  "jest-openapi": "0.14.2",
159
+ "jest-runner": "29.5.0",
160
160
  "jest-serial-runner": "^1.2.1",
161
161
  "nodemon": "2.0.15",
162
162
  "openapi-types": "9.3.1",
@@ -176,5 +176,5 @@
176
176
  "optionalDependencies": {
177
177
  "oracledb": "5.3.0"
178
178
  },
179
- "gitHead": "1a054856a4aa2b39142e7b7800f8ae39f5904ecc"
179
+ "gitHead": "9fcfb0a6cd4e4003f0e420b4b180b3b069e93191"
180
180
  }
@@ -45,6 +45,8 @@ async function init() {
45
45
  BB_ADMIN_USER_PASSWORD: "",
46
46
  PLUGINS_DIR: "",
47
47
  TENANT_FEATURE_FLAGS: "*:LICENSING,*:USER_GROUPS,*:ONBOARDING_TOUR",
48
+ HTTP_MIGRATIONS: "0",
49
+ HTTP_LOGGING: "0",
48
50
  }
49
51
  let envFile = ""
50
52
  Object.keys(envFileJson).forEach(key => {
@@ -11,6 +11,7 @@ if [ "$1" = '/opt/mssql/bin/sqlservr' ]; then
11
11
 
12
12
  echo "RUNNING BUDIBASE SETUP"
13
13
 
14
+ cat setup.sql
14
15
  #run the setup script to create the DB and the schema in the DB
15
16
  /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Passw0rd -i setup.sql
16
17
 
@@ -34,7 +34,7 @@ GO
34
34
  CREATE TABLE people
35
35
  (
36
36
  name varchar(30) NOT NULL,
37
- age varchar(20),
37
+ age int default 20 NOT NULL,
38
38
  CONSTRAINT pk_people PRIMARY KEY NONCLUSTERED (name, age)
39
39
  );
40
40
 
@@ -50,22 +50,22 @@ VALUES
50
50
  ('Processing', 1);
51
51
 
52
52
  INSERT INTO people (name, age)
53
- VALUES ('Bob', '30'),
54
- ('Bert', '10'),
55
- ('Jack', '12'),
56
- ('Mike', '31'),
57
- ('Dave', '44'),
58
- ('Jim', '43'),
59
- ('Kerry', '32'),
60
- ('Julie', '12'),
61
- ('Kim', '55'),
62
- ('Andy', '33'),
63
- ('John', '22'),
64
- ('Ruth', '66'),
65
- ('Robert', '88'),
66
- ('Bobert', '99'),
67
- ('Jan', '22'),
68
- ('Megan', '11');
53
+ VALUES ('Bob', 30),
54
+ ('Bert', 10),
55
+ ('Jack', 12),
56
+ ('Mike', 31),
57
+ ('Dave', 44),
58
+ ('Jim', 43),
59
+ ('Kerry', 32),
60
+ ('Julie', 12),
61
+ ('Kim', 55),
62
+ ('Andy', 33),
63
+ ('John', 22),
64
+ ('Ruth', 66),
65
+ ('Robert', 88),
66
+ ('Bobert', 99),
67
+ ('Jan', 22),
68
+ ('Megan', 11);
69
69
 
70
70
 
71
71
  IF OBJECT_ID ('Chains.sizes', 'U') IS NOT NULL
@@ -3,7 +3,7 @@ USE main;
3
3
  CREATE TABLE Persons (
4
4
  PersonID int NOT NULL AUTO_INCREMENT,
5
5
  CreatedAt datetime,
6
- Age float,
6
+ Age float DEFAULT 20 NOT NULL,
7
7
  LastName varchar(255),
8
8
  FirstName varchar(255),
9
9
  Address varchar(255),
@@ -8,6 +8,7 @@ CREATE TABLE Persons (
8
8
  FirstName varchar(255),
9
9
  Address varchar(255),
10
10
  City varchar(255) DEFAULT 'Belfast',
11
+ Age INTEGER DEFAULT 20 NOT NULL,
11
12
  Type person_job
12
13
  );
13
14
  CREATE TABLE Tasks (