@budibase/server 1.0.211 → 1.0.212-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 (238) hide show
  1. package/builder/assets/index.44dea5cc.js +1312 -0
  2. package/builder/assets/index.c6912819.css +6 -0
  3. package/builder/index.html +2 -2
  4. package/coverage/clover.xml +296 -263
  5. package/coverage/coverage-final.json +10 -10
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/backup.js.html +9 -6
  10. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/dev.js.html +111 -12
  14. package/coverage/lcov-report/api/controllers/index.html +21 -21
  15. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +47 -17
  25. package/coverage/lcov-report/api/controllers/row/index.html +22 -22
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
  30. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  44. package/coverage/lcov-report/api/index.html +1 -1
  45. package/coverage/lcov-report/api/index.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/dev.js.html +5 -2
  56. package/coverage/lcov-report/api/routes/index.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  74. package/coverage/lcov-report/automations/actions.js.html +1 -1
  75. package/coverage/lcov-report/automations/automationUtils.js.html +57 -12
  76. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  77. package/coverage/lcov-report/automations/index.html +17 -17
  78. package/coverage/lcov-report/automations/index.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/index.html +1 -1
  86. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggers.js.html +4 -4
  105. package/coverage/lcov-report/constants/index.html +1 -1
  106. package/coverage/lcov-report/constants/index.js.html +1 -1
  107. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  108. package/coverage/lcov-report/constants/screens.js.html +1 -1
  109. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  110. package/coverage/lcov-report/db/index.html +10 -10
  111. package/coverage/lcov-report/db/index.js.html +1 -1
  112. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  116. package/coverage/lcov-report/db/newid.js.html +1 -1
  117. package/coverage/lcov-report/db/utils.js.html +9 -6
  118. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  119. package/coverage/lcov-report/events/index.html +1 -1
  120. package/coverage/lcov-report/events/index.js.html +1 -1
  121. package/coverage/lcov-report/events/utils.js.html +1 -1
  122. package/coverage/lcov-report/index.html +48 -48
  123. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  124. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  125. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  126. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  127. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  128. package/coverage/lcov-report/middleware/index.html +1 -1
  129. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  130. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  131. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  132. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  133. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  134. package/coverage/lcov-report/threads/automation.js.html +2 -2
  135. package/coverage/lcov-report/threads/index.html +1 -1
  136. package/coverage/lcov-report/threads/query.js.html +1 -1
  137. package/coverage/lcov-report/threads/utils.js.html +1 -1
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  139. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  140. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  141. package/coverage/lcov-report/utilities/global.js.html +1 -1
  142. package/coverage/lcov-report/utilities/index.html +15 -15
  143. package/coverage/lcov-report/utilities/index.js.html +27 -9
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  151. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  152. package/coverage/lcov-report/utilities/security.js.html +1 -1
  153. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  157. package/coverage/lcov-report/utilities/users.js.html +1 -1
  158. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  159. package/coverage/lcov.info +504 -449
  160. package/dist/api/controllers/application.js +1 -1
  161. package/dist/api/controllers/backup.js +3 -2
  162. package/dist/api/controllers/dev.js +25 -2
  163. package/dist/api/controllers/row/external.js +19 -7
  164. package/dist/api/controllers/row/utils.js +3 -0
  165. package/dist/api/controllers/static/index.js +31 -2
  166. package/dist/api/routes/dev.js +2 -1
  167. package/dist/api/routes/static.js +1 -0
  168. package/dist/automations/automationUtils.js +16 -4
  169. package/dist/automations/triggers.js +1 -1
  170. package/dist/db/utils.js +1 -0
  171. package/dist/definitions/datasource.js +1 -0
  172. package/dist/environment.js +1 -1
  173. package/dist/integrations/airtable.js +1 -0
  174. package/dist/integrations/arangodb.js +1 -0
  175. package/dist/integrations/base/sql.js +20 -3
  176. package/dist/integrations/couchdb.js +1 -0
  177. package/dist/integrations/dynamodb.js +1 -0
  178. package/dist/integrations/elasticsearch.js +1 -0
  179. package/dist/integrations/firebase.js +1 -0
  180. package/dist/integrations/googlesheets.js +1 -0
  181. package/dist/integrations/index.js +4 -0
  182. package/dist/integrations/microsoftSqlServer.js +2 -1
  183. package/dist/integrations/mongodb.js +1 -0
  184. package/dist/integrations/mysql.js +2 -1
  185. package/dist/integrations/oracle.js +1 -0
  186. package/dist/integrations/postgres.js +2 -1
  187. package/dist/integrations/redis.js +1 -0
  188. package/dist/integrations/rest.js +1 -0
  189. package/dist/integrations/s3.js +1 -0
  190. package/dist/integrations/snowflake.js +102 -0
  191. package/dist/package.json +7 -6
  192. package/dist/threads/automation.js +1 -1
  193. package/dist/tsconfig.build.tsbuildinfo +1 -1
  194. package/dist/utilities/fileSystem/index.js +16 -6
  195. package/dist/utilities/fileSystem/utilities.js +2 -1
  196. package/dist/utilities/index.js +5 -1
  197. package/package.json +8 -7
  198. package/scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip +0 -0
  199. package/scripts/integrations/oracle/instantclient/linux/arm64/install.sh +23 -0
  200. package/scripts/integrations/oracle/instantclient/linux/install.sh +10 -0
  201. package/src/api/controllers/application.ts +5 -1
  202. package/src/api/controllers/backup.js +3 -2
  203. package/src/api/controllers/dev.js +35 -2
  204. package/src/api/controllers/row/external.js +19 -9
  205. package/src/api/controllers/row/utils.js +3 -0
  206. package/src/api/controllers/static/index.js +41 -2
  207. package/src/api/routes/dev.js +1 -0
  208. package/src/api/routes/static.ts +1 -0
  209. package/src/automations/automationUtils.js +19 -4
  210. package/src/automations/triggers.js +1 -1
  211. package/src/db/utils.js +1 -0
  212. package/src/definitions/common.ts +1 -0
  213. package/src/definitions/datasource.ts +2 -0
  214. package/src/environment.js +2 -1
  215. package/src/integrations/airtable.ts +1 -0
  216. package/src/integrations/arangodb.ts +1 -0
  217. package/src/integrations/base/sql.ts +25 -11
  218. package/src/integrations/couchdb.ts +1 -0
  219. package/src/integrations/dynamodb.ts +1 -0
  220. package/src/integrations/elasticsearch.ts +1 -0
  221. package/src/integrations/firebase.ts +1 -0
  222. package/src/integrations/googlesheets.ts +1 -0
  223. package/src/integrations/index.ts +4 -0
  224. package/src/integrations/microsoftSqlServer.ts +2 -0
  225. package/src/integrations/mongodb.ts +1 -0
  226. package/src/integrations/mysql.ts +2 -0
  227. package/src/integrations/oracle.ts +1 -0
  228. package/src/integrations/postgres.ts +2 -0
  229. package/src/integrations/redis.ts +1 -0
  230. package/src/integrations/rest.ts +1 -0
  231. package/src/integrations/s3.ts +1 -0
  232. package/src/integrations/snowflake.ts +99 -0
  233. package/src/threads/automation.js +1 -1
  234. package/src/utilities/fileSystem/index.js +22 -8
  235. package/src/utilities/fileSystem/utilities.js +2 -0
  236. package/src/utilities/index.js +7 -1
  237. package/builder/assets/index.24307ca0.css +0 -6
  238. package/builder/assets/index.4c5e5a40.js +0 -1315
@@ -189,7 +189,7 @@ const fetchAppPackage = (ctx) => __awaiter(void 0, void 0, void 0, function* ()
189
189
  application,
190
190
  screens,
191
191
  layouts,
192
- clientLibPath: (0, utilities_1.clientLibraryPath)(ctx.params.appId, application.version),
192
+ clientLibPath: (0, utilities_1.clientLibraryPath)(ctx.params.appId, application.version, ctx),
193
193
  };
194
194
  });
195
195
  exports.fetchAppPackage = fetchAppPackage;
@@ -13,11 +13,12 @@ const { events, context } = require("@budibase/backend-core");
13
13
  const { DocumentTypes } = require("../../db/utils");
14
14
  exports.exportAppDump = function (ctx) {
15
15
  return __awaiter(this, void 0, void 0, function* () {
16
- const { appId } = ctx.query;
16
+ let { appId, excludeRows } = ctx.query;
17
17
  const appName = decodeURI(ctx.query.appname);
18
+ excludeRows = excludeRows === "true";
18
19
  const backupIdentifier = `${appName}-export-${new Date().getTime()}.txt`;
19
20
  ctx.attachment(backupIdentifier);
20
- ctx.body = yield streamBackup(appId);
21
+ ctx.body = yield streamBackup(appId, excludeRows);
21
22
  yield context.doInAppContext(appId, () => __awaiter(this, void 0, void 0, function* () {
22
23
  const appDb = context.getAppDB();
23
24
  const app = yield appDb.get(DocumentTypes.APP_METADATA);
@@ -13,8 +13,8 @@ const env = require("../../environment");
13
13
  const { checkSlashesInUrl } = require("../../utilities");
14
14
  const { request } = require("../../utilities/workerRequests");
15
15
  const { clearLock } = require("../../utilities/redis");
16
- const { Replication, getProdAppID } = require("@budibase/backend-core/db");
17
- const { DocumentTypes } = require("../../db/utils");
16
+ const { Replication, getProdAppID, dangerousGetDB, } = require("@budibase/backend-core/db");
17
+ const { DocumentTypes, getRowParams } = require("../../db/utils");
18
18
  const { app: appCache } = require("@budibase/backend-core/cache");
19
19
  const { getProdAppDB, getAppDB } = require("@budibase/backend-core/context");
20
20
  const { events } = require("@budibase/backend-core");
@@ -129,3 +129,26 @@ exports.getBudibaseVersion = (ctx) => __awaiter(void 0, void 0, void 0, function
129
129
  };
130
130
  yield events.installation.versionChecked(version);
131
131
  });
132
+ // TODO: remove as part of beta program
133
+ exports.checkBetaAccess = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
134
+ const userToCheck = ctx.query.email;
135
+ const BETA_USERS_DB = "app_bb_f9b77d06b9db4e3ca185476ab87a2364";
136
+ const BETA_USERS_TABLE = "ta_8c2c6df1c03f49cfb6340e85e066dd15";
137
+ try {
138
+ const db = dangerousGetDB(BETA_USERS_DB);
139
+ const betaUsers = (yield db.allDocs(getRowParams(BETA_USERS_TABLE, null, {
140
+ include_docs: true,
141
+ }))).rows.map(row => row.doc);
142
+ let access = false;
143
+ for (let betaUser of betaUsers) {
144
+ if (betaUser["Email address"].trim() === userToCheck) {
145
+ access = true;
146
+ break;
147
+ }
148
+ }
149
+ ctx.body = { access };
150
+ }
151
+ catch (err) {
152
+ ctx.body = { access: false };
153
+ }
154
+ });
@@ -155,29 +155,41 @@ exports.validate = () => __awaiter(void 0, void 0, void 0, function* () {
155
155
  return { valid: true };
156
156
  });
157
157
  exports.exportRows = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
158
- const { datasourceId, tableName } = breakExternalTableId(ctx.params.tableId);
158
+ const { datasourceId } = breakExternalTableId(ctx.params.tableId);
159
159
  const db = getAppDB();
160
- let format = ctx.query.format;
160
+ const format = ctx.query.format;
161
+ const { columns } = ctx.request.body;
161
162
  const datasource = yield db.get(datasourceId);
162
163
  if (!datasource || !datasource.entities) {
163
164
  ctx.throw(400, "Datasource has not been configured for plus API.");
164
165
  }
165
- const tables = datasource.entities;
166
- const table = tables[tableName];
167
166
  ctx.request.body = {
168
167
  query: {
169
168
  oneOf: {
170
- [table.primaryDisplay]: ctx.request.body.rows.map(id => breakRowIdField(id)[0]),
169
+ _id: ctx.request.body.rows.map(row => JSON.parse(decodeURI(row))[0]),
171
170
  },
172
171
  },
173
172
  };
174
173
  let result = yield exports.search(ctx);
175
- let headers = Object.keys(result.rows[0]);
174
+ let rows = [];
175
+ // Filter data to only specified columns if required
176
+ if (columns && columns.length) {
177
+ for (let i = 0; i < result.rows.length; i++) {
178
+ rows[i] = {};
179
+ for (let column of columns) {
180
+ rows[i][column] = result.rows[i][column];
181
+ }
182
+ }
183
+ }
184
+ else {
185
+ rows = result.rows;
186
+ }
187
+ let headers = Object.keys(rows[0]);
176
188
  const exporter = exporters[format];
177
189
  const filename = `export.${format}`;
178
190
  // send down the file
179
191
  ctx.attachment(filename);
180
- return apiFileReturn(exporter(headers, result.rows));
192
+ return apiFileReturn(exporter(headers, rows));
181
193
  });
182
194
  exports.fetchEnrichedRow = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
183
195
  const id = ctx.params.rowId;
@@ -70,6 +70,9 @@ exports.validate = ({ tableId, row, table }) => __awaiter(void 0, void 0, void 0
70
70
  // Validate.js doesn't seem to handle array
71
71
  if (type === FieldTypes.ARRAY && row[fieldName]) {
72
72
  if (row[fieldName].length) {
73
+ if (!Array.isArray(row[fieldName])) {
74
+ row[fieldName] = row[fieldName].split(",");
75
+ }
73
76
  row[fieldName].map(val => {
74
77
  if (!constraints.inclusion.includes(val) &&
75
78
  constraints.inclusion.length !== 0) {
@@ -21,8 +21,11 @@ const { upload } = require("../../../utilities/fileSystem");
21
21
  const { attachmentsRelativeURL } = require("../../../utilities");
22
22
  const { DocumentTypes, isDevAppID } = require("../../../db/utils");
23
23
  const { getAppDB, getAppId } = require("@budibase/backend-core/context");
24
+ const { setCookie, clearCookie } = require("@budibase/backend-core/utils");
24
25
  const AWS = require("aws-sdk");
25
26
  const { events } = require("@budibase/backend-core");
27
+ const fs = require("fs");
28
+ const { downloadTarballDirect, } = require("../../../utilities/fileSystem/utilities");
26
29
  function prepareUpload({ s3Key, bucket, metadata, file }) {
27
30
  return __awaiter(this, void 0, void 0, function* () {
28
31
  const response = yield upload({
@@ -42,9 +45,35 @@ function prepareUpload({ s3Key, bucket, metadata, file }) {
42
45
  };
43
46
  });
44
47
  }
48
+ exports.toggleBetaUiFeature = function (ctx) {
49
+ return __awaiter(this, void 0, void 0, function* () {
50
+ const cookieName = `beta:${ctx.params.feature}`;
51
+ if (ctx.cookies.get(cookieName)) {
52
+ clearCookie(ctx, cookieName);
53
+ ctx.body = {
54
+ message: `${ctx.params.feature} disabled`,
55
+ };
56
+ return;
57
+ }
58
+ let builderPath = resolve(TOP_LEVEL_PATH, "new_design_ui");
59
+ // // download it from S3
60
+ if (!fs.existsSync(builderPath)) {
61
+ fs.mkdirSync(builderPath);
62
+ }
63
+ yield downloadTarballDirect("https://cdn.budi.live/beta:design_ui/new_ui.tar.gz", builderPath);
64
+ setCookie(ctx, {}, cookieName);
65
+ ctx.body = {
66
+ message: `${ctx.params.feature} enabled`,
67
+ };
68
+ });
69
+ };
45
70
  exports.serveBuilder = function (ctx) {
46
71
  return __awaiter(this, void 0, void 0, function* () {
47
- let builderPath = resolve(TOP_LEVEL_PATH, "builder");
72
+ // Temporary: New Design UI
73
+ const designUiCookie = ctx.cookies.get("beta:design_ui");
74
+ // TODO: get this from the tmp Dir that we downloaded from MinIO
75
+ const uiPath = designUiCookie ? "new_design_ui" : "builder";
76
+ let builderPath = resolve(TOP_LEVEL_PATH, uiPath);
48
77
  yield send(ctx, ctx.file, { root: builderPath });
49
78
  if (!ctx.file.includes("assets/")) {
50
79
  yield events.serve.servedBuilder();
@@ -80,7 +109,7 @@ exports.serveApp = function (ctx) {
80
109
  title: appInfo.name,
81
110
  production: env.isProd(),
82
111
  appId,
83
- clientLibPath: clientLibraryPath(appId, appInfo.version),
112
+ clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
84
113
  });
85
114
  const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`);
86
115
  ctx.body = yield processString(appHbs, {
@@ -18,5 +18,6 @@ if (env.isDev() || env.isTest()) {
18
18
  router
19
19
  .get("/api/dev/version", authorized(BUILDER), controller.getBudibaseVersion)
20
20
  .delete("/api/dev/:appId/lock", authorized(BUILDER), controller.clearLock)
21
- .post("/api/dev/:appId/revert", authorized(BUILDER), controller.revert);
21
+ .post("/api/dev/:appId/revert", authorized(BUILDER), controller.revert)
22
+ .get("/api/beta/access", controller.checkBetaAccess);
22
23
  module.exports = router;
@@ -68,6 +68,7 @@ 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/beta/:feature", controller.toggleBetaUiFeature)
71
72
  .post("/api/attachments/:tableId/upload", (0, resourceId_1.paramResource)("tableId"), (0, authorized_1.default)(permissions_1.PermissionTypes.TABLE, permissions_1.PermissionLevels.WRITE), controller.uploadFile)
72
73
  .get("/:appId/:path*", controller.serveApp)
73
74
  .get("/app/:appUrl/:path*", controller.serveApp)
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  const { getTable } = require("../api/controllers/table/utils");
12
- const { findHBSBlocks } = require("@budibase/string-templates");
12
+ const { findHBSBlocks, decodeJSBinding, isJSBinding, encodeJSBinding, } = require("@budibase/string-templates");
13
13
  /**
14
14
  * When values are input to the system generally they will be of type string as this is required for template strings.
15
15
  * This can generate some odd scenarios as the Schema of the automation requires a number but the builder might supply
@@ -81,11 +81,23 @@ exports.getError = err => {
81
81
  return typeof err !== "string" ? err.toString() : err;
82
82
  };
83
83
  exports.substituteLoopStep = (hbsString, substitute) => {
84
- let blocks = findHBSBlocks(hbsString);
84
+ let blocks = [];
85
+ let checkForJS = isJSBinding(hbsString);
86
+ if (checkForJS) {
87
+ hbsString = decodeJSBinding(hbsString);
88
+ blocks.push(hbsString);
89
+ }
90
+ else {
91
+ blocks = findHBSBlocks(hbsString);
92
+ }
85
93
  for (let block of blocks) {
86
- let oldBlock = block;
87
94
  block = block.replace(/loop/, substitute);
88
- hbsString = hbsString.replace(new RegExp(oldBlock, "g"), block);
95
+ if (checkForJS) {
96
+ hbsString = encodeJSBinding(block);
97
+ }
98
+ else {
99
+ hbsString = block;
100
+ }
89
101
  }
90
102
  return hbsString;
91
103
  };
@@ -95,7 +95,7 @@ exports.externalTrigger = function (automation, params, { getResponses } = {}) {
95
95
  // values are likely to be submitted as strings, so we shall convert to correct type
96
96
  const coercedFields = {};
97
97
  const fields = automation.definition.trigger.inputs.fields;
98
- for (let key of Object.keys(fields)) {
98
+ for (let key of Object.keys(fields || {})) {
99
99
  coercedFields[key] = coerce(params.fields[key], fields[key]);
100
100
  }
101
101
  params.fields = coercedFields;
package/dist/db/utils.js CHANGED
@@ -54,6 +54,7 @@ exports.isDevAppID = isDevAppID;
54
54
  exports.isProdAppID = isProdAppID;
55
55
  exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`;
56
56
  exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`;
57
+ exports.TABLE_ROW_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${DocumentTypes.TABLE}`;
57
58
  exports.ViewNames = ViewNames;
58
59
  exports.InternalTables = InternalTables;
59
60
  exports.DocumentTypes = DocumentTypes;
@@ -52,6 +52,7 @@ var SourceNames;
52
52
  SourceNames["GOOGLE_SHEETS"] = "GOOGLE_SHEETS";
53
53
  SourceNames["FIRESTORE"] = "FIRESTORE";
54
54
  SourceNames["REDIS"] = "REDIS";
55
+ SourceNames["SNOWFLAKE"] = "SNOWFLAKE";
55
56
  })(SourceNames = exports.SourceNames || (exports.SourceNames = {}));
56
57
  var IncludeRelationships;
57
58
  (function (IncludeRelationships) {
@@ -56,7 +56,7 @@ module.exports = {
56
56
  SALT_ROUNDS: process.env.SALT_ROUNDS,
57
57
  LOGGER: process.env.LOGGER,
58
58
  LOG_LEVEL: process.env.LOG_LEVEL,
59
- AUTOMATION_MAX_ITERATIONS: process.env.AUTOMATION_MAX_ITERATIONS,
59
+ AUTOMATION_MAX_ITERATIONS: parseIntSafe(process.env.AUTOMATION_MAX_ITERATIONS) || 200,
60
60
  SENDGRID_API_KEY: process.env.SENDGRID_API_KEY,
61
61
  DYNAMO_ENDPOINT: process.env.DYNAMO_ENDPOINT,
62
62
  QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT),
@@ -17,6 +17,7 @@ var AirtableModule;
17
17
  docs: "https://airtable.com/api",
18
18
  description: "Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
19
19
  friendlyName: "Airtable",
20
+ type: "Spreadsheet",
20
21
  datasource: {
21
22
  apiKey: {
22
23
  type: datasource_1.DatasourceFieldTypes.PASSWORD,
@@ -16,6 +16,7 @@ var ArangoModule;
16
16
  const SCHEMA = {
17
17
  docs: "https://github.com/arangodb/arangojs",
18
18
  friendlyName: "ArangoDB",
19
+ type: "Non-relational",
19
20
  description: "ArangoDB is a scalable open-source multi-model database natively supporting graph, document and search. All supported data models & access patterns can be combined in queries allowing for maximal flexibility. ",
20
21
  datasource: {
21
22
  url: {
@@ -89,6 +89,23 @@ function parseFilters(filters) {
89
89
  }
90
90
  return filters;
91
91
  }
92
+ function generateSelectStatement(json, knex) {
93
+ var _a;
94
+ const { resource, meta } = json;
95
+ const schema = (_a = meta === null || meta === void 0 ? void 0 : meta.table) === null || _a === void 0 ? void 0 : _a.schema;
96
+ return resource.fields.map(field => {
97
+ const fieldNames = field.split(/\./g);
98
+ const tableName = fieldNames[0];
99
+ const columnName = fieldNames[1];
100
+ if (columnName && knex.client.config.client === utils_1.SqlClients.POSTGRES) {
101
+ const externalType = schema === null || schema === void 0 ? void 0 : schema[columnName].externalType;
102
+ if (externalType === null || externalType === void 0 ? void 0 : externalType.includes("money")) {
103
+ return knex.raw(`"${tableName}"."${columnName}"::money::numeric as "${field}"`);
104
+ }
105
+ }
106
+ return `${field} as ${field}`;
107
+ });
108
+ }
92
109
  class InternalBuilder {
93
110
  constructor(client) {
94
111
  this.client = client;
@@ -209,7 +226,7 @@ class InternalBuilder {
209
226
  }
210
227
  return query;
211
228
  }
212
- addRelationships(knex, query, fields, fromTable, relationships) {
229
+ addRelationships(query, fromTable, relationships) {
213
230
  if (!relationships) {
214
231
  return query;
215
232
  }
@@ -311,7 +328,7 @@ class InternalBuilder {
311
328
  if (resource.fields && resource.fields.length > 0) {
312
329
  // select the resources as the format "table.columnName" - this is what is provided
313
330
  // by the resource builder further up
314
- selectStatement = resource.fields.map(field => `${field} as ${field}`);
331
+ selectStatement = generateSelectStatement(json, knex);
315
332
  }
316
333
  let foundLimit = limit || BASE_LIMIT;
317
334
  // handle pagination
@@ -347,7 +364,7 @@ class InternalBuilder {
347
364
  preQuery = this.addSorting(preQuery, json);
348
365
  }
349
366
  // handle joins
350
- query = this.addRelationships(knex, preQuery, selectStatement, tableName, relationships);
367
+ query = this.addRelationships(preQuery, tableName, relationships);
351
368
  return this.addFilters(query, filters, { relationship: true });
352
369
  }
353
370
  update(knex, json, opts) {
@@ -16,6 +16,7 @@ var CouchDBModule;
16
16
  const SCHEMA = {
17
17
  docs: "https://docs.couchdb.org/en/stable/",
18
18
  friendlyName: "CouchDB",
19
+ type: "Non-relational",
19
20
  description: "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.",
20
21
  datasource: {
21
22
  url: {
@@ -18,6 +18,7 @@ var DynamoModule;
18
18
  docs: "https://github.com/dabit3/dynamodb-documentclient-cheat-sheet",
19
19
  description: "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.",
20
20
  friendlyName: "DynamoDB",
21
+ type: "Non-relational",
21
22
  datasource: {
22
23
  region: {
23
24
  type: datasource_1.DatasourceFieldTypes.STRING,
@@ -17,6 +17,7 @@ var ElasticsearchModule;
17
17
  docs: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html",
18
18
  description: "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.",
19
19
  friendlyName: "ElasticSearch",
20
+ type: "Non-relational",
20
21
  datasource: {
21
22
  url: {
22
23
  type: datasource_1.DatasourceFieldTypes.STRING,
@@ -16,6 +16,7 @@ var Firebase;
16
16
  const SCHEMA = {
17
17
  docs: "https://firebase.google.com/docs/firestore/quickstart",
18
18
  friendlyName: "Firestore",
19
+ type: "Non-relational",
19
20
  description: "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
20
21
  datasource: {
21
22
  email: {
@@ -33,6 +33,7 @@ var GoogleSheetsModule;
33
33
  docs: "https://developers.google.com/sheets/api/quickstart/nodejs",
34
34
  description: "Create and collaborate on online spreadsheets in real-time and from any device. ",
35
35
  friendlyName: "Google Sheets",
36
+ type: "Spreadsheet",
36
37
  datasource: {
37
38
  spreadsheetId: {
38
39
  display: "Google Sheet URL",
@@ -13,6 +13,7 @@ const rest = require("./rest");
13
13
  const googlesheets = require("./googlesheets");
14
14
  const firebase = require("./firebase");
15
15
  const redis = require("./redis");
16
+ const snowflake = require("./snowflake");
16
17
  const { SourceNames } = require("../definitions/datasource");
17
18
  const environment = require("../environment");
18
19
  const DEFINITIONS = {
@@ -29,6 +30,7 @@ const DEFINITIONS = {
29
30
  [SourceNames.REST]: rest.schema,
30
31
  [SourceNames.FIRESTORE]: firebase.schema,
31
32
  [SourceNames.REDIS]: redis.schema,
33
+ [SourceNames.SNOWFLAKE]: snowflake.schema,
32
34
  };
33
35
  const INTEGRATIONS = {
34
36
  [SourceNames.POSTGRES]: postgres.integration,
@@ -45,6 +47,8 @@ const INTEGRATIONS = {
45
47
  [SourceNames.FIRESTORE]: firebase.integration,
46
48
  [SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
47
49
  [SourceNames.REDIS]: redis.integration,
50
+ [SourceNames.FIREBASE]: firebase.integration,
51
+ [SourceNames.SNOWFLAKE]: snowflake.integration,
48
52
  };
49
53
  // optionally add oracle integration if the oracle binary can be installed
50
54
  if (!(process.arch === "arm64" && process.platform === "darwin")) {
@@ -21,6 +21,7 @@ var MSSQLModule;
21
21
  plus: true,
22
22
  description: "Microsoft SQL Server is a relational database management system developed by Microsoft. ",
23
23
  friendlyName: "MS SQL Server",
24
+ type: "Relational",
24
25
  datasource: {
25
26
  user: {
26
27
  type: datasource_1.DatasourceFieldTypes.STRING,
@@ -201,7 +202,7 @@ var MSSQLModule;
201
202
  if (typeof name !== "string") {
202
203
  continue;
203
204
  }
204
- schema[name] = Object.assign({ autocolumn: !!autoColumns.find((col) => col === name), name: name }, (0, utils_1.convertSqlType)(def.DATA_TYPE));
205
+ schema[name] = Object.assign(Object.assign({ autocolumn: !!autoColumns.find((col) => col === name), name: name }, (0, utils_1.convertSqlType)(def.DATA_TYPE)), { externalType: def.DATA_TYPE });
205
206
  }
206
207
  tables[tableName] = {
207
208
  _id: (0, utils_1.buildExternalTableId)(datasourceId, tableName),
@@ -16,6 +16,7 @@ var MongoDBModule;
16
16
  const SCHEMA = {
17
17
  docs: "https://github.com/mongodb/node-mongodb-native",
18
18
  friendlyName: "MongoDB",
19
+ type: "Non-relational",
19
20
  description: "MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.",
20
21
  datasource: {
21
22
  connectionString: {
@@ -24,6 +24,7 @@ var MySQLModule;
24
24
  docs: "https://github.com/sidorares/node-mysql2",
25
25
  plus: true,
26
26
  friendlyName: "MySQL",
27
+ type: "Relational",
27
28
  description: "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ",
28
29
  datasource: {
29
30
  host: {
@@ -187,7 +188,7 @@ var MySQLModule;
187
188
  const isAuto = typeof column.Extra === "string" &&
188
189
  (column.Extra === "auto_increment" ||
189
190
  column.Extra.toLowerCase().includes("generated"));
190
- schema[columnName] = Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type));
191
+ schema[columnName] = Object.assign(Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type)), { externalType: column.Type });
191
192
  }
192
193
  if (!tables[tableName]) {
193
194
  tables[tableName] = {
@@ -24,6 +24,7 @@ var OracleModule;
24
24
  docs: "https://github.com/oracle/node-oracledb",
25
25
  plus: true,
26
26
  friendlyName: "Oracle",
27
+ type: "Relational",
27
28
  description: "Oracle Database is an object-relational database management system developed by Oracle Corporation",
28
29
  datasource: {
29
30
  host: {
@@ -29,6 +29,7 @@ var PostgresModule;
29
29
  docs: "https://node-postgres.com",
30
30
  plus: true,
31
31
  friendlyName: "PostgreSQL",
32
+ type: "Relational",
32
33
  description: "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.",
33
34
  datasource: {
34
35
  host: {
@@ -229,7 +230,7 @@ var PostgresModule;
229
230
  column.column_default.startsWith("nextval");
230
231
  const isGenerated = column.is_generated && column.is_generated !== "NEVER";
231
232
  const isAuto = hasDefault || identity || isGenerated;
232
- tables[tableName].schema[columnName] = Object.assign({ autocolumn: isAuto, name: columnName }, (0, utils_1.convertSqlType)(column.data_type));
233
+ tables[tableName].schema[columnName] = Object.assign(Object.assign({ autocolumn: isAuto, name: columnName }, (0, utils_1.convertSqlType)(column.data_type)), { externalType: column.data_type });
233
234
  }
234
235
  const final = (0, utils_1.finaliseExternalTables)(tables, entities);
235
236
  this.tables = final.tables;
@@ -20,6 +20,7 @@ var RedisModule;
20
20
  docs: "https://redis.io/docs/",
21
21
  description: "",
22
22
  friendlyName: "Redis",
23
+ type: "Non-relational",
23
24
  datasource: {
24
25
  host: {
25
26
  type: "string",
@@ -56,6 +56,7 @@ var RestModule;
56
56
  docs: "https://github.com/node-fetch/node-fetch",
57
57
  description: "With the REST API datasource, you can connect, query and pull data from multiple REST APIs. You can then use the retrieved data to build apps.",
58
58
  friendlyName: "REST API",
59
+ type: "API",
59
60
  datasource: {
60
61
  url: {
61
62
  type: datasource_1.DatasourceFieldTypes.STRING,
@@ -17,6 +17,7 @@ var S3Module;
17
17
  docs: "https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
18
18
  description: "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.",
19
19
  friendlyName: "Amazon S3",
20
+ type: "Object store",
20
21
  datasource: {
21
22
  region: {
22
23
  type: "string",
@@ -0,0 +1,102 @@
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
+ const datasource_1 = require("../definitions/datasource");
13
+ const snowflake_promise_1 = require("snowflake-promise");
14
+ var SnowflakeModule;
15
+ (function (SnowflakeModule) {
16
+ const SCHEMA = {
17
+ docs: "https://developers.snowflake.com/",
18
+ description: "Snowflake is a solution for data warehousing, data lakes, data engineering, data science, data application development, and securely sharing and consuming shared data.",
19
+ friendlyName: "Snowflake",
20
+ type: "Relational",
21
+ datasource: {
22
+ account: {
23
+ type: "string",
24
+ required: true,
25
+ },
26
+ username: {
27
+ type: "string",
28
+ required: true,
29
+ },
30
+ password: {
31
+ type: "password",
32
+ required: true,
33
+ },
34
+ warehouse: {
35
+ type: "string",
36
+ required: true,
37
+ },
38
+ database: {
39
+ type: "string",
40
+ required: true,
41
+ },
42
+ schema: {
43
+ type: "string",
44
+ required: true,
45
+ },
46
+ },
47
+ query: {
48
+ create: {
49
+ type: datasource_1.QueryTypes.SQL,
50
+ },
51
+ read: {
52
+ type: datasource_1.QueryTypes.SQL,
53
+ },
54
+ update: {
55
+ type: datasource_1.QueryTypes.SQL,
56
+ },
57
+ delete: {
58
+ type: datasource_1.QueryTypes.SQL,
59
+ },
60
+ },
61
+ };
62
+ class SnowflakeIntegration {
63
+ constructor(config) {
64
+ this.client = new snowflake_promise_1.Snowflake(config);
65
+ }
66
+ internalQuery(query) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ yield this.client.connect();
69
+ try {
70
+ return yield this.client.execute(query.sql);
71
+ }
72
+ catch (err) {
73
+ throw (err === null || err === void 0 ? void 0 : err.message.split(":")[1]) || (err === null || err === void 0 ? void 0 : err.message);
74
+ }
75
+ });
76
+ }
77
+ create(query) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ return this.internalQuery(query);
80
+ });
81
+ }
82
+ read(query) {
83
+ return __awaiter(this, void 0, void 0, function* () {
84
+ return this.internalQuery(query);
85
+ });
86
+ }
87
+ update(query) {
88
+ return __awaiter(this, void 0, void 0, function* () {
89
+ return this.internalQuery(query);
90
+ });
91
+ }
92
+ delete(query) {
93
+ return __awaiter(this, void 0, void 0, function* () {
94
+ return this.internalQuery(query);
95
+ });
96
+ }
97
+ }
98
+ module.exports = {
99
+ schema: SCHEMA,
100
+ integration: SnowflakeIntegration,
101
+ };
102
+ })(SnowflakeModule || (SnowflakeModule = {}));