@budibase/server 1.2.57 → 1.2.58-alpha.2

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 (207) hide show
  1. package/__mocks__/mongodb.ts +4 -0
  2. package/__mocks__/node-fetch.ts +8 -1
  3. package/builder/assets/index.d7a7633b.js +875 -0
  4. package/builder/assets/index.fdb1647e.css +6 -0
  5. package/builder/assets/{vendor.6bcafa60.js → vendor.67dbd8fa.js} +1 -1
  6. package/builder/index.html +3 -3
  7. package/coverage/clover.xml +510 -485
  8. package/coverage/coverage-final.json +18 -18
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/index.html +1 -1
  18. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  24. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/index.html +25 -25
  29. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +317 -191
  31. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/utils.js.html +27 -18
  33. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +2 -2
  37. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/user.js.html +19 -19
  41. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  47. package/coverage/lcov-report/api/index.html +1 -1
  48. package/coverage/lcov-report/api/index.js.html +5 -5
  49. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/index.html +1 -1
  60. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  74. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  77. package/coverage/lcov-report/automations/actions.js.html +1 -1
  78. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  79. package/coverage/lcov-report/automations/bullboard.js.html +9 -6
  80. package/coverage/lcov-report/automations/index.html +11 -11
  81. package/coverage/lcov-report/automations/index.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/index.html +1 -1
  89. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  108. package/coverage/lcov-report/constants/index.html +1 -1
  109. package/coverage/lcov-report/constants/index.js.html +30 -30
  110. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  111. package/coverage/lcov-report/constants/screens.js.html +1 -1
  112. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  113. package/coverage/lcov-report/db/index.html +1 -1
  114. package/coverage/lcov-report/db/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  119. package/coverage/lcov-report/db/newid.js.html +4 -4
  120. package/coverage/lcov-report/db/utils.js.html +69 -69
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  122. package/coverage/lcov-report/events/index.html +1 -1
  123. package/coverage/lcov-report/events/index.js.html +1 -1
  124. package/coverage/lcov-report/events/utils.js.html +1 -1
  125. package/coverage/lcov-report/index.html +33 -33
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  127. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  128. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  129. package/coverage/lcov-report/middleware/builder.js.html +11 -11
  130. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  131. package/coverage/lcov-report/middleware/index.html +10 -10
  132. package/coverage/lcov-report/middleware/joi-validator.js.html +18 -9
  133. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  134. package/coverage/lcov-report/middleware/resourceId.js.html +12 -12
  135. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  136. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  137. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  138. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  139. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  140. package/coverage/lcov-report/utilities/global.js.html +31 -31
  141. package/coverage/lcov-report/utilities/index.html +1 -1
  142. package/coverage/lcov-report/utilities/index.js.html +23 -23
  143. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  144. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  145. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  147. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  150. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  151. package/coverage/lcov-report/utilities/security.js.html +2 -2
  152. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  153. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  156. package/coverage/lcov-report/utilities/users.js.html +7 -7
  157. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  158. package/coverage/lcov.info +824 -780
  159. package/dist/api/controllers/row/internalSearch.js +39 -4
  160. package/dist/api/controllers/row/utils.js +3 -1
  161. package/dist/api/controllers/static/index.js +26 -2
  162. package/dist/api/controllers/static/templates/preview.hbs +103 -0
  163. package/dist/api/controllers/table/external.js +1 -1
  164. package/dist/api/routes/static.js +3 -0
  165. package/dist/app.js +4 -3
  166. package/dist/automations/bullboard.js +1 -0
  167. package/dist/automations/logging/index.js +3 -0
  168. package/dist/integrations/base/query.js +27 -0
  169. package/dist/integrations/base/sql.js +62 -30
  170. package/dist/integrations/base/utils.js +13 -27
  171. package/dist/integrations/microsoftSqlServer.js +5 -2
  172. package/dist/integrations/mongodb.js +35 -8
  173. package/dist/integrations/mysql.js +2 -2
  174. package/dist/integrations/postgres.js +5 -2
  175. package/dist/middleware/joi-validator.js +7 -4
  176. package/dist/package.json +7 -7
  177. package/dist/threads/index.js +1 -0
  178. package/dist/tsconfig.build.tsbuildinfo +1 -1
  179. package/dist/utilities/fileSystem/index.js +2 -1
  180. package/dist/utilities/redis.js +1 -0
  181. package/package.json +8 -8
  182. package/src/api/controllers/row/internalSearch.js +45 -3
  183. package/src/api/controllers/row/utils.js +4 -1
  184. package/src/api/controllers/static/index.ts +21 -1
  185. package/src/api/controllers/static/templates/preview.hbs +103 -0
  186. package/src/api/controllers/table/external.js +1 -1
  187. package/src/api/routes/static.ts +12 -0
  188. package/src/api/routes/tests/internalSearch.spec.js +176 -0
  189. package/src/api/routes/tests/static.spec.js +19 -7
  190. package/src/app.ts +5 -3
  191. package/src/automations/bullboard.js +1 -0
  192. package/src/automations/logging/index.ts +3 -0
  193. package/src/integrations/base/query.ts +16 -0
  194. package/src/integrations/base/sql.ts +67 -30
  195. package/src/integrations/base/utils.ts +9 -18
  196. package/src/integrations/microsoftSqlServer.ts +3 -2
  197. package/src/integrations/mongodb.ts +35 -8
  198. package/src/integrations/mysql.ts +1 -1
  199. package/src/integrations/postgres.ts +2 -1
  200. package/src/integrations/tests/mongo.spec.js +218 -0
  201. package/src/integrations/tests/sql.spec.js +101 -11
  202. package/src/middleware/joi-validator.js +7 -4
  203. package/src/threads/index.ts +1 -0
  204. package/src/utilities/fileSystem/index.js +2 -0
  205. package/src/utilities/redis.js +1 -0
  206. package/builder/assets/index.08dd0c5e.css +0 -6
  207. package/builder/assets/index.b6eebfec.js +0 -975
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  const { SearchIndexes } = require("../../../db/utils");
12
+ const { removeKeyNumbering } = require("./utils");
12
13
  const fetch = require("node-fetch");
13
14
  const { getCouchInfo } = require("@budibase/backend-core/db");
14
15
  const { getAppId } = require("@budibase/backend-core/context");
@@ -18,7 +19,7 @@ const { getAppId } = require("@budibase/backend-core/context");
18
19
  */
19
20
  class QueryBuilder {
20
21
  constructor(base) {
21
- this.query = Object.assign({ allOr: false, string: {}, fuzzy: {}, range: {}, equal: {}, notEqual: {}, empty: {}, notEmpty: {}, oneOf: {}, contains: {} }, base);
22
+ this.query = Object.assign({ allOr: false, string: {}, fuzzy: {}, range: {}, equal: {}, notEqual: {}, empty: {}, notEmpty: {}, oneOf: {}, contains: {}, notContains: {}, containsAny: {} }, base);
22
23
  this.limit = 50;
23
24
  this.sortOrder = "ascending";
24
25
  this.sortType = "string";
@@ -104,6 +105,14 @@ class QueryBuilder {
104
105
  this.query.contains[key] = value;
105
106
  return this;
106
107
  }
108
+ addNotContains(key, value) {
109
+ this.query.notContains[key] = value;
110
+ return this;
111
+ }
112
+ addContainsAny(key, value) {
113
+ this.query.containsAny[key] = value;
114
+ return this;
115
+ }
107
116
  /**
108
117
  * Preprocesses a value before going into a lucene search.
109
118
  * Transforms strings to lowercase and wraps strings and bools in quotes.
@@ -146,11 +155,27 @@ class QueryBuilder {
146
155
  }
147
156
  return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`;
148
157
  };
149
- const contains = (key, value) => {
150
- if (!value && value !== 0) {
158
+ const contains = (key, value, mode = "AND") => {
159
+ if (Array.isArray(value) && value.length === 0) {
151
160
  return null;
152
161
  }
153
- return `${key}:${builder.preprocess(value, { escape: true })}`;
162
+ if (!Array.isArray(value)) {
163
+ return `${key}:${value}`;
164
+ }
165
+ let statement = `${builder.preprocess(value[0], { escape: true })}`;
166
+ for (let i = 1; i < value.length; i++) {
167
+ statement += ` ${mode} ${builder.preprocess(value[i], {
168
+ escape: true,
169
+ })}`;
170
+ }
171
+ return `${key}:(${statement})`;
172
+ };
173
+ const notContains = (key, value) => {
174
+ const allPrefix = allOr === "" ? "*:* AND" : "";
175
+ return allPrefix + "NOT " + contains(key, value);
176
+ };
177
+ const containsAny = (key, value) => {
178
+ return contains(key, value, "OR");
154
179
  };
155
180
  const oneOf = (key, value) => {
156
181
  if (!Array.isArray(value)) {
@@ -169,6 +194,8 @@ class QueryBuilder {
169
194
  };
170
195
  function build(structure, queryFn) {
171
196
  for (let [key, value] of Object.entries(structure)) {
197
+ // check for new format - remove numbering if needed
198
+ key = removeKeyNumbering(key);
172
199
  key = builder.preprocess(key.replace(/ /g, "_"), {
173
200
  escape: true,
174
201
  });
@@ -246,6 +273,12 @@ class QueryBuilder {
246
273
  if (this.query.contains) {
247
274
  build(this.query.contains, contains);
248
275
  }
276
+ if (this.query.notContains) {
277
+ build(this.query.notContains, notContains);
278
+ }
279
+ if (this.query.containsAny) {
280
+ build(this.query.containsAny, containsAny);
281
+ }
249
282
  // make sure table ID is always added as an AND
250
283
  if (tableId) {
251
284
  query = `(${query})`;
@@ -280,6 +313,8 @@ class QueryBuilder {
280
313
  });
281
314
  }
282
315
  }
316
+ // exported for unit testing
317
+ exports.QueryBuilder = QueryBuilder;
283
318
  /**
284
319
  * Executes a lucene search query.
285
320
  * @param url The query URL
@@ -13,8 +13,9 @@ const { cloneDeep } = require("lodash/fp");
13
13
  const { InternalTables } = require("../../../db/utils");
14
14
  const userController = require("../user");
15
15
  const { FieldTypes } = require("../../../constants");
16
- const { makeExternalQuery } = require("../../../integrations/base/utils");
17
16
  const { getAppDB } = require("@budibase/backend-core/context");
17
+ const { makeExternalQuery } = require("../../../integrations/base/query");
18
+ const { removeKeyNumbering } = require("../../../integrations/base/utils");
18
19
  validateJs.extend(validateJs.validators.datetime, {
19
20
  parse: function (value) {
20
21
  return new Date(value).getTime();
@@ -24,6 +25,7 @@ validateJs.extend(validateJs.validators.datetime, {
24
25
  return new Date(value).toISOString();
25
26
  },
26
27
  });
28
+ exports.removeKeyNumbering = removeKeyNumbering;
27
29
  exports.getDatasourceAndQuery = (json) => __awaiter(void 0, void 0, void 0, function* () {
28
30
  const datasourceId = json.endpoint.datasourceId;
29
31
  const db = getAppDB();
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getSignedUploadURL = exports.serveClientLibrary = exports.serveApp = exports.uploadFile = exports.serveBuilder = exports.toggleBetaUiFeature = void 0;
12
+ exports.getSignedUploadURL = exports.serveClientLibrary = exports.serveBuilderPreview = exports.serveApp = exports.deleteObjects = exports.uploadFile = exports.serveBuilder = exports.toggleBetaUiFeature = void 0;
13
13
  require("svelte/register");
14
14
  const send = require("koa-send");
15
15
  const { resolve, join } = require("../../../utilities/centralPath");
@@ -19,7 +19,7 @@ const { processString } = require("@budibase/string-templates");
19
19
  const { loadHandlebarsFile, NODE_MODULES_PATH, TOP_LEVEL_PATH, } = require("../../../utilities/fileSystem");
20
20
  const env = require("../../../environment");
21
21
  const { clientLibraryPath } = require("../../../utilities");
22
- const { upload } = require("../../../utilities/fileSystem");
22
+ const { upload, deleteFiles } = require("../../../utilities/fileSystem");
23
23
  const { attachmentsRelativeURL } = require("../../../utilities");
24
24
  const { DocumentType } = require("../../../db/utils");
25
25
  const { getAppDB, getAppId } = require("@budibase/backend-core/context");
@@ -95,6 +95,12 @@ const uploadFile = function (ctx) {
95
95
  });
96
96
  };
97
97
  exports.uploadFile = uploadFile;
98
+ const deleteObjects = function (ctx) {
99
+ return __awaiter(this, void 0, void 0, function* () {
100
+ ctx.body = yield deleteFiles(ObjectStoreBuckets.APPS, ctx.request.body.keys);
101
+ });
102
+ };
103
+ exports.deleteObjects = deleteObjects;
98
104
  const serveApp = function (ctx) {
99
105
  return __awaiter(this, void 0, void 0, function* () {
100
106
  const db = getAppDB({ skip_setup: true });
@@ -123,6 +129,24 @@ const serveApp = function (ctx) {
123
129
  });
124
130
  };
125
131
  exports.serveApp = serveApp;
132
+ const serveBuilderPreview = function (ctx) {
133
+ return __awaiter(this, void 0, void 0, function* () {
134
+ const db = getAppDB({ skip_setup: true });
135
+ const appInfo = yield db.get(DocumentType.APP_METADATA);
136
+ if (!env.isJest()) {
137
+ let appId = getAppId();
138
+ const previewHbs = loadHandlebarsFile(`${__dirname}/templates/preview.hbs`);
139
+ ctx.body = yield processString(previewHbs, {
140
+ clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
141
+ });
142
+ }
143
+ else {
144
+ // just return the app info for jest to assert on
145
+ ctx.body = Object.assign(Object.assign({}, appInfo), { builderPreview: true });
146
+ }
147
+ });
148
+ };
149
+ exports.serveBuilderPreview = serveBuilderPreview;
126
150
  const serveClientLibrary = function (ctx) {
127
151
  return __awaiter(this, void 0, void 0, function* () {
128
152
  return send(ctx, "budibase-client.js", {
@@ -0,0 +1,103 @@
1
+ <html lang="en">
2
+ <head>
3
+ <title>Budibase Builder Preview</title>
4
+ <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
5
+ <link rel="preconnect" href="https://fonts.gstatic.com" />
6
+ <link
7
+ href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
8
+ rel="stylesheet"
9
+ />
10
+ <link
11
+ href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
12
+ rel="stylesheet"
13
+ />
14
+ <style>
15
+ html, body {
16
+ padding: 0;
17
+ margin: 0;
18
+ }
19
+ html {
20
+ height: 100%;
21
+ width: 100%;
22
+ overflow: hidden;
23
+ display: flex;
24
+ flex-direction: column;
25
+ justify-content: flex-start;
26
+ align-items: stretch;
27
+ }
28
+ body {
29
+ flex: 1 1 auto;
30
+ overflow: hidden;
31
+ }
32
+
33
+ *,
34
+ *:before,
35
+ *:after {
36
+ box-sizing: border-box;
37
+ }
38
+ </style>
39
+ <script src='{{ clientLibPath }}'></script>
40
+ <script>
41
+ function receiveMessage(event) {
42
+ if (!event.data) {
43
+ return
44
+ }
45
+
46
+ // Parse received message
47
+ // If parsing fails, just ignore and wait for the next message
48
+ let parsed
49
+ try {
50
+ parsed = JSON.parse(event.data)
51
+ } catch (error) {
52
+ console.error("Client received invalid JSON")
53
+ // Ignore
54
+ }
55
+ if (!parsed || !parsed.isBudibaseEvent) {
56
+ return
57
+ }
58
+
59
+ // Extract data from message
60
+ const {
61
+ selectedComponentId,
62
+ layout,
63
+ screen,
64
+ appId,
65
+ theme,
66
+ customTheme,
67
+ previewDevice,
68
+ navigation,
69
+ hiddenComponentIds
70
+ } = parsed
71
+
72
+ // Set some flags so the app knows we're in the builder
73
+ window["##BUDIBASE_IN_BUILDER##"] = true
74
+ window["##BUDIBASE_APP_ID##"] = appId
75
+ window["##BUDIBASE_PREVIEW_LAYOUT##"] = layout
76
+ window["##BUDIBASE_PREVIEW_SCREEN##"] = screen
77
+ window["##BUDIBASE_SELECTED_COMPONENT_ID##"] = selectedComponentId
78
+ window["##BUDIBASE_PREVIEW_ID##"] = Math.random()
79
+ window["##BUDIBASE_PREVIEW_THEME##"] = theme
80
+ window["##BUDIBASE_PREVIEW_CUSTOM_THEME##"] = customTheme
81
+ window["##BUDIBASE_PREVIEW_DEVICE##"] = previewDevice
82
+ window["##BUDIBASE_PREVIEW_NAVIGATION##"] = navigation
83
+ window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"] = hiddenComponentIds
84
+
85
+ // Initialise app
86
+ try {
87
+ if (window.loadBudibase) {
88
+ window.loadBudibase()
89
+ document.documentElement.classList.add("loaded")
90
+ } else {
91
+ throw "The client library couldn't be loaded"
92
+ }
93
+ } catch (error) {
94
+ window.parent.postMessage({ type: "error", error })
95
+ }
96
+ }
97
+
98
+ window.addEventListener("message", receiveMessage)
99
+ window.parent.postMessage({ type: "ready" })
100
+ </script>
101
+ </head>
102
+ <body></body>
103
+ </html>
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  const { buildExternalTableId, breakExternalTableId, } = require("../../../integrations/utils");
12
12
  const { getTable, generateForeignKey, generateJunctionTableName, foreignKeyStructure, hasTypeChanged, } = require("./utils");
13
13
  const { DataSourceOperation, FieldTypes, RelationshipTypes, } = require("../../../constants");
14
- const { makeExternalQuery } = require("../../../integrations/base/utils");
14
+ const { makeExternalQuery } = require("../../../integrations/base/query");
15
15
  const { cloneDeep } = require("lodash/fp");
16
16
  const csvParser = require("../../../utilities/csvParser");
17
17
  const { handleRequest } = require("../row/external");
@@ -68,8 +68,11 @@ router
68
68
  // TODO: for now this builder endpoint is not authorized/secured, will need to be
69
69
  .get("/builder/:file*", controller.serveBuilder)
70
70
  .post("/api/attachments/process", (0, authorized_1.default)(permissions_1.BUILDER), controller.uploadFile)
71
+ .post("/api/attachments/delete", (0, authorized_1.default)(permissions_1.BUILDER), controller.deleteObjects)
71
72
  .post("/api/beta/:feature", controller.toggleBetaUiFeature)
72
73
  .post("/api/attachments/:tableId/upload", (0, resourceId_1.paramResource)("tableId"), (0, authorized_1.default)(permissions_1.PermissionTypes.TABLE, permissions_1.PermissionLevels.WRITE), controller.uploadFile)
74
+ .post("/api/attachments/:tableId/delete", (0, resourceId_1.paramResource)("tableId"), (0, authorized_1.default)(permissions_1.PermissionTypes.TABLE, permissions_1.PermissionLevels.WRITE), controller.deleteObjects)
75
+ .get("/preview", (0, authorized_1.default)(permissions_1.BUILDER), controller.serveBuilderPreview)
73
76
  .get("/:appId/:path*", controller.serveApp)
74
77
  .get("/app/:appUrl/:path*", controller.serveApp)
75
78
  .post("/api/attachments/:datasourceId/url", (0, authorized_1.default)(permissions_1.PermissionTypes.TABLE, permissions_1.PermissionLevels.READ), controller.getSignedUploadURL);
package/dist/app.js CHANGED
@@ -104,9 +104,7 @@ server.on("close", () => __awaiter(void 0, void 0, void 0, function* () {
104
104
  return;
105
105
  }
106
106
  shuttingDown = true;
107
- if (!env.isTest()) {
108
- console.log("Server Closed");
109
- }
107
+ console.log("Server Closed");
110
108
  yield automations.shutdown();
111
109
  yield redis_1.default.shutdown();
112
110
  yield backend_core_1.events.shutdown();
@@ -174,3 +172,6 @@ process.on("uncaughtException", err => {
174
172
  process.on("SIGTERM", () => {
175
173
  shutdown();
176
174
  });
175
+ process.on("SIGINT", () => {
176
+ shutdown();
177
+ });
@@ -59,5 +59,6 @@ exports.shutdown = () => __awaiter(void 0, void 0, void 0, function* () {
59
59
  yield automationQueue.close();
60
60
  automationQueue = null;
61
61
  }
62
+ console.log("Bull shutdown");
62
63
  });
63
64
  exports.queue = automationQueue;
@@ -56,6 +56,9 @@ function checkAppMetadata(apps) {
56
56
  for (let [key, errors] of Object.entries(metadata.automationErrors)) {
57
57
  const updated = [];
58
58
  for (let error of errors) {
59
+ if (!error) {
60
+ continue;
61
+ }
59
62
  const startDate = error.split(backend_core_1.db.SEPARATOR)[2];
60
63
  if (startDate > maxStartDate) {
61
64
  updated.push(error);
@@ -0,0 +1,27 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.makeExternalQuery = void 0;
13
+ const { integrations } = require("../index");
14
+ function makeExternalQuery(datasource, json) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const Integration = integrations[datasource.source];
17
+ // query is the opinionated function
18
+ if (Integration.prototype.query) {
19
+ const integration = new Integration(datasource.config);
20
+ return integration.query(json);
21
+ }
22
+ else {
23
+ throw "Datasource does not support query.";
24
+ }
25
+ });
26
+ }
27
+ exports.makeExternalQuery = makeExternalQuery;
@@ -17,6 +17,7 @@ const types_1 = require("@budibase/types");
17
17
  const utils_1 = require("../utils");
18
18
  const sqlTable_1 = __importDefault(require("./sqlTable"));
19
19
  const environment_1 = __importDefault(require("../../environment"));
20
+ const utils_2 = require("./utils");
20
21
  const envLimit = environment_1.default.SQL_MAX_ROWS
21
22
  ? parseInt(environment_1.default.SQL_MAX_ROWS)
22
23
  : null;
@@ -116,12 +117,13 @@ class InternalBuilder {
116
117
  addFilters(query, filters, opts) {
117
118
  function iterate(structure, fn) {
118
119
  for (let [key, value] of Object.entries(structure)) {
119
- const isRelationshipField = key.includes(".");
120
+ const updatedKey = (0, utils_2.removeKeyNumbering)(key);
121
+ const isRelationshipField = updatedKey.includes(".");
120
122
  if (!opts.relationship && !isRelationshipField) {
121
- fn(`${opts.tableName}.${key}`, value);
123
+ fn(`${opts.tableName}.${updatedKey}`, value);
122
124
  }
123
125
  if (opts.relationship && isRelationshipField) {
124
- fn(key, value);
126
+ fn(updatedKey, value);
125
127
  }
126
128
  }
127
129
  }
@@ -139,6 +141,56 @@ class InternalBuilder {
139
141
  ]);
140
142
  }
141
143
  };
144
+ const contains = (mode, any = false) => {
145
+ const fnc = allOr ? "orWhere" : "where";
146
+ const rawFnc = `${fnc}Raw`;
147
+ const not = mode === (filters === null || filters === void 0 ? void 0 : filters.notContains) ? "NOT " : "";
148
+ function stringifyArray(value, quoteStyle = '"') {
149
+ for (let i in value) {
150
+ if (typeof value[i] === "string") {
151
+ value[i] = `${quoteStyle}${value[i]}${quoteStyle}`;
152
+ }
153
+ }
154
+ return `[${value.join(",")}]`;
155
+ }
156
+ if (this.client === utils_1.SqlClient.POSTGRES) {
157
+ iterate(mode, (key, value) => {
158
+ const wrap = any ? "" : "'";
159
+ const containsOp = any ? "\\?| array" : "@>";
160
+ const fieldNames = key.split(/\./g);
161
+ const tableName = fieldNames[0];
162
+ const columnName = fieldNames[1];
163
+ // @ts-ignore
164
+ query = query[rawFnc](`${not}"${tableName}"."${columnName}"::jsonb ${containsOp} ${wrap}${stringifyArray(value, any ? "'" : '"')}${wrap}`);
165
+ });
166
+ }
167
+ else if (this.client === utils_1.SqlClient.MY_SQL) {
168
+ const jsonFnc = any ? "JSON_OVERLAPS" : "JSON_CONTAINS";
169
+ iterate(mode, (key, value) => {
170
+ // @ts-ignore
171
+ query = query[rawFnc](`${not}${jsonFnc}(${key}, '${stringifyArray(value)}')`);
172
+ });
173
+ }
174
+ else {
175
+ const andOr = mode === (filters === null || filters === void 0 ? void 0 : filters.containsAny) ? " OR " : " AND ";
176
+ iterate(mode, (key, value) => {
177
+ let statement = "";
178
+ for (let i in value) {
179
+ if (typeof value[i] === "string") {
180
+ value[i] = `%"${value[i]}"%`;
181
+ }
182
+ else {
183
+ value[i] = `%${value[i]}%`;
184
+ }
185
+ statement +=
186
+ (statement ? andOr : "") +
187
+ `LOWER(${likeKey(this.client, key)}) LIKE ?`;
188
+ }
189
+ // @ts-ignore
190
+ query = query[rawFnc](`${not}(${statement})`, value);
191
+ });
192
+ }
193
+ };
142
194
  if (!filters) {
143
195
  return query;
144
196
  }
@@ -212,32 +264,13 @@ class InternalBuilder {
212
264
  });
213
265
  }
214
266
  if (filters.contains) {
215
- const fnc = allOr ? "orWhere" : "where";
216
- const rawFnc = `${fnc}Raw`;
217
- if (this.client === utils_1.SqlClient.POSTGRES) {
218
- iterate(filters.contains, (key, value) => {
219
- const fieldNames = key.split(/\./g);
220
- const tableName = fieldNames[0];
221
- const columnName = fieldNames[1];
222
- if (typeof value === "string") {
223
- value = `"${value}"`;
224
- }
225
- // @ts-ignore
226
- query = query[rawFnc](`"${tableName}"."${columnName}"::jsonb @> '[${value}]'`);
227
- });
228
- }
229
- else if (this.client === utils_1.SqlClient.MY_SQL) {
230
- iterate(filters.contains, (key, value) => {
231
- if (typeof value === "string") {
232
- value = `"${value}"`;
233
- }
234
- // @ts-ignore
235
- query = query[rawFnc](`JSON_CONTAINS(${key}, '${value}')`);
236
- });
237
- }
238
- else {
239
- iterate(filters.contains, like);
240
- }
267
+ contains(filters.contains);
268
+ }
269
+ if (filters.notContains) {
270
+ contains(filters.notContains);
271
+ }
272
+ if (filters.containsAny) {
273
+ contains(filters.containsAny, true);
241
274
  }
242
275
  return query;
243
276
  }
@@ -548,4 +581,3 @@ class SqlQueryBuilder extends sqlTable_1.default {
548
581
  }
549
582
  }
550
583
  exports.default = SqlQueryBuilder;
551
- module.exports = SqlQueryBuilder;
@@ -1,30 +1,16 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- var DatasourceUtils;
13
- (function (DatasourceUtils) {
14
- const { integrations } = require("../index");
15
- function makeExternalQuery(datasource, json) {
16
- return __awaiter(this, void 0, void 0, function* () {
17
- const Integration = integrations[datasource.source];
18
- // query is the opinionated function
19
- if (Integration.prototype.query) {
20
- const integration = new Integration(datasource.config);
21
- return integration.query(json);
22
- }
23
- else {
24
- throw "Datasource does not support query.";
25
- }
26
- });
3
+ exports.removeKeyNumbering = void 0;
4
+ const QUERY_START_REGEX = /\d[0-9]*:/g;
5
+ function removeKeyNumbering(key) {
6
+ if (typeof key === "string" && key.match(QUERY_START_REGEX) != null) {
7
+ const parts = key.split(":");
8
+ // remove the number
9
+ parts.shift();
10
+ return parts.join(":");
27
11
  }
28
- DatasourceUtils.makeExternalQuery = makeExternalQuery;
29
- module.exports.makeExternalQuery = makeExternalQuery;
30
- })(DatasourceUtils || (DatasourceUtils = {}));
12
+ else {
13
+ return key;
14
+ }
15
+ }
16
+ exports.removeKeyNumbering = removeKeyNumbering;
@@ -8,13 +8,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  const types_1 = require("@budibase/types");
13
16
  const utils_1 = require("./utils");
17
+ const sql_1 = __importDefault(require("./base/sql"));
14
18
  var MSSQLModule;
15
19
  (function (MSSQLModule) {
16
20
  const sqlServer = require("mssql");
17
- const Sql = require("./base/sql");
18
21
  const DEFAULT_SCHEMA = "dbo";
19
22
  const SCHEMA = {
20
23
  docs: "https://github.com/tediousjs/node-mssql",
@@ -69,7 +72,7 @@ var MSSQLModule;
69
72
  },
70
73
  },
71
74
  };
72
- class SqlServerIntegration extends Sql {
75
+ class SqlServerIntegration extends sql_1.default {
73
76
  constructor(config) {
74
77
  super(utils_1.SqlClient.MS_SQL);
75
78
  this.index = 0;
@@ -80,10 +80,11 @@ var MongoDBModule;
80
80
  if (json[field] instanceof Object) {
81
81
  json[field] = self.createObjectIds(json[field]);
82
82
  }
83
- if (field === "_id" && typeof json[field] === "string") {
84
- const id = (_a = json["_id"].match(/(?<=objectid\(['"]).*(?=['"]\))/gi)) === null || _a === void 0 ? void 0 : _a[0];
83
+ if (typeof json[field] === "string" &&
84
+ json[field].toLowerCase().startsWith("objectid")) {
85
+ const id = (_a = json[field].match(/(?<=objectid\(['"]).*(?=['"]\))/gi)) === null || _a === void 0 ? void 0 : _a[0];
85
86
  if (id) {
86
- json["_id"] = mongodb_1.ObjectID.createFromHexString(id);
87
+ json[field] = mongodb_1.ObjectID.createFromHexString(id);
87
88
  }
88
89
  }
89
90
  }
@@ -98,10 +99,33 @@ var MongoDBModule;
98
99
  return interpolateObjectIds(json);
99
100
  }
100
101
  parseQueryParams(params, mode) {
101
- let queryParams = params.split(/(?<=}),[\n\s]*(?={)/g);
102
- let group1 = queryParams[0] ? JSON.parse(queryParams[0]) : {};
103
- let group2 = queryParams[1] ? JSON.parse(queryParams[1]) : {};
104
- let group3 = queryParams[2] ? JSON.parse(queryParams[2]) : {};
102
+ var _a, _b, _c;
103
+ let queryParams = [];
104
+ let openCount = 0;
105
+ let inQuotes = false;
106
+ let i = 0;
107
+ let startIndex = 0;
108
+ for (let c of params) {
109
+ if (c === '"' && i > 0 && params[i - 1] !== "\\") {
110
+ inQuotes = !inQuotes;
111
+ }
112
+ if (c === "{" && !inQuotes) {
113
+ openCount++;
114
+ if (openCount === 1) {
115
+ startIndex = i;
116
+ }
117
+ }
118
+ else if (c === "}" && !inQuotes) {
119
+ if (openCount === 1) {
120
+ queryParams.push(JSON.parse(params.substring(startIndex, i + 1)));
121
+ }
122
+ openCount--;
123
+ }
124
+ i++;
125
+ }
126
+ let group1 = (_a = queryParams[0]) !== null && _a !== void 0 ? _a : {};
127
+ let group2 = (_b = queryParams[1]) !== null && _b !== void 0 ? _b : {};
128
+ let group3 = (_c = queryParams[2]) !== null && _c !== void 0 ? _c : {};
105
129
  if (mode === "update") {
106
130
  return {
107
131
  filter: group1,
@@ -159,7 +183,10 @@ var MongoDBModule;
159
183
  return yield collection.findOne(json);
160
184
  }
161
185
  case "findOneAndUpdate": {
162
- let findAndUpdateJson = json;
186
+ if (typeof query.json === "string") {
187
+ json = this.parseQueryParams(query.json, "update");
188
+ }
189
+ let findAndUpdateJson = this.createObjectIds(json);
163
190
  return yield collection.findOneAndUpdate(findAndUpdateJson.filter, findAndUpdateJson.update, findAndUpdateJson.options);
164
191
  }
165
192
  case "count": {
@@ -16,10 +16,10 @@ const types_1 = require("@budibase/types");
16
16
  const utils_1 = require("./utils");
17
17
  const dayjs_1 = __importDefault(require("dayjs"));
18
18
  const { NUMBER_REGEX } = require("../utilities");
19
+ const sql_1 = __importDefault(require("./base/sql"));
19
20
  var MySQLModule;
20
21
  (function (MySQLModule) {
21
22
  const mysql = require("mysql2/promise");
22
- const Sql = require("./base/sql");
23
23
  const SCHEMA = {
24
24
  docs: "https://github.com/sidorares/node-mysql2",
25
25
  plus: true,
@@ -96,7 +96,7 @@ var MySQLModule;
96
96
  }
97
97
  return bindings;
98
98
  }
99
- class MySQLIntegration extends Sql {
99
+ class MySQLIntegration extends sql_1.default {
100
100
  constructor(config) {
101
101
  super(utils_1.SqlClient.MY_SQL);
102
102
  this.tables = {};