@budibase/server 0.9.185-alpha.2 → 0.9.185-alpha.20

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 (251) hide show
  1. package/Dockerfile +7 -1
  2. package/__mocks__/oracledb.ts +31 -0
  3. package/builder/assets/bb-space-man.5be51a45.svg +290 -0
  4. package/builder/assets/index.7d405e74.css +1 -0
  5. package/builder/assets/index.83e08172.js +1316 -0
  6. package/builder/assets/oracle.66592424.png +0 -0
  7. package/builder/assets/vendor.470042a4.js +152 -0
  8. package/builder/assets/vendor.5e1fe644.css +1 -0
  9. package/builder/index.html +4 -4
  10. package/coverage/clover.xml +785 -687
  11. package/coverage/coverage-final.json +90 -88
  12. package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
  13. package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
  14. package/coverage/lcov-report/api/controllers/application.js.html +43 -13
  15. package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
  16. package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
  17. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  20. package/coverage/lcov-report/api/controllers/datasource.js.html +129 -21
  21. package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
  22. package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
  23. package/coverage/lcov-report/api/controllers/index.html +77 -77
  24. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
  26. package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
  27. package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
  28. package/coverage/lcov-report/api/controllers/query.js.html +48 -210
  29. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  30. package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
  31. package/coverage/lcov-report/api/controllers/row/external.js.html +2 -2
  32. package/coverage/lcov-report/api/controllers/row/index.html +10 -10
  33. package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
  34. package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
  35. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
  36. package/coverage/lcov-report/api/controllers/row/utils.js.html +2 -2
  37. package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
  38. package/coverage/lcov-report/api/controllers/script.js.html +3 -3
  39. package/coverage/lcov-report/api/controllers/table/external.js.html +29 -8
  40. package/coverage/lcov-report/api/controllers/table/index.html +20 -20
  41. package/coverage/lcov-report/api/controllers/table/index.js.html +3 -3
  42. package/coverage/lcov-report/api/controllers/table/internal.js.html +2 -2
  43. package/coverage/lcov-report/api/controllers/table/utils.js.html +8 -8
  44. package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
  45. package/coverage/lcov-report/api/controllers/user.js.html +2 -2
  46. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.html +9 -9
  48. package/coverage/lcov-report/api/controllers/view/index.js.html +5 -5
  49. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  50. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
  51. package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
  52. package/coverage/lcov-report/api/index.html +1 -1
  53. package/coverage/lcov-report/api/index.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/dev.js.html +2 -2
  65. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/index.html +4 -4
  67. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/query.js.html +5 -2
  73. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/static.js.html +2 -2
  79. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  84. package/coverage/lcov-report/automations/actions.js.html +2 -2
  85. package/coverage/lcov-report/automations/automationUtils.js.html +3 -3
  86. package/coverage/lcov-report/automations/bullboard.js.html +71 -20
  87. package/coverage/lcov-report/automations/index.html +33 -48
  88. package/coverage/lcov-report/automations/index.js.html +2 -2
  89. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
  94. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
  96. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/index.html +14 -14
  98. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
  100. package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
  101. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
  106. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  108. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  109. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  111. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  115. package/coverage/lcov-report/automations/triggers.js.html +22 -10
  116. package/coverage/lcov-report/automations/utils.js.html +42 -12
  117. package/coverage/lcov-report/constants/index.html +5 -5
  118. package/coverage/lcov-report/constants/index.js.html +44 -23
  119. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  120. package/coverage/lcov-report/constants/screens.js.html +1 -1
  121. package/coverage/lcov-report/db/client.js.html +2 -2
  122. package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
  123. package/coverage/lcov-report/db/index.html +2 -2
  124. package/coverage/lcov-report/db/index.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
  126. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  127. package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
  128. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
  129. package/coverage/lcov-report/db/newid.js.html +3 -3
  130. package/coverage/lcov-report/db/utils.js.html +57 -57
  131. package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
  132. package/coverage/lcov-report/events/index.html +6 -6
  133. package/coverage/lcov-report/events/index.js.html +1 -1
  134. package/coverage/lcov-report/events/utils.js.html +5 -5
  135. package/coverage/lcov-report/index.html +86 -71
  136. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  137. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  138. package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
  139. package/coverage/lcov-report/middleware/authorized.js.html +4 -4
  140. package/coverage/lcov-report/middleware/builder.js.html +16 -7
  141. package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
  142. package/coverage/lcov-report/middleware/index.html +21 -21
  143. package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
  144. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  145. package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
  146. package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
  147. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  148. package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +90 -33
  149. package/coverage/lcov-report/threads/index.html +141 -0
  150. package/coverage/lcov-report/threads/index.js.html +278 -0
  151. package/coverage/lcov-report/threads/query.js.html +278 -0
  152. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  153. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  154. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  155. package/coverage/lcov-report/utilities/csvParser.js.html +2 -2
  156. package/coverage/lcov-report/utilities/global.js.html +2 -2
  157. package/coverage/lcov-report/utilities/index.html +21 -21
  158. package/coverage/lcov-report/utilities/index.js.html +12 -9
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
  160. package/coverage/lcov-report/utilities/queue/index.html +14 -14
  161. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  162. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
  167. package/coverage/lcov-report/utilities/security.js.html +3 -3
  168. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  169. package/coverage/lcov-report/utilities/users.js.html +1 -1
  170. package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
  171. package/coverage/lcov.info +1247 -1070
  172. package/dist/api/controllers/application.js +11 -1
  173. package/dist/api/controllers/datasource.js +31 -7
  174. package/dist/api/controllers/deploy/index.js +2 -0
  175. package/dist/api/controllers/dev.js +4 -1
  176. package/dist/api/controllers/query.js +27 -57
  177. package/dist/api/controllers/table/external.js +8 -1
  178. package/dist/api/routes/query.js +1 -1
  179. package/dist/app.js +2 -11
  180. package/dist/automations/bullboard.js +37 -10
  181. package/dist/automations/triggers.js +7 -3
  182. package/dist/automations/utils.js +11 -2
  183. package/dist/constants/index.js +6 -0
  184. package/dist/definitions/datasource.js +1 -0
  185. package/dist/environment.js +13 -0
  186. package/dist/integrations/base/IntegrationBase.js +2 -0
  187. package/dist/integrations/base/sql.js +40 -8
  188. package/dist/integrations/index.js +6 -0
  189. package/dist/integrations/mysql.js +3 -1
  190. package/dist/integrations/oracle.js +345 -0
  191. package/dist/integrations/utils.js +17 -2
  192. package/dist/middleware/builder.js +4 -1
  193. package/dist/package.json +11 -6
  194. package/dist/{automations/thread.js → threads/automation.js} +26 -8
  195. package/dist/threads/index.js +64 -0
  196. package/dist/threads/query.js +64 -0
  197. package/dist/tsconfig.tsbuildinfo +1 -1
  198. package/dist/utilities/index.js +1 -0
  199. package/dist/utilities/queue/inMemoryQueue.js +8 -0
  200. package/dist/utilities/scriptRunner.js +4 -1
  201. package/package.json +12 -7
  202. package/scripts/dev/manage.js +1 -0
  203. package/scripts/integrations/oracle/docker-compose.yml +19 -0
  204. package/scripts/integrations/oracle/instantclient/linux/x86-64/basiclite-21.4.zip +0 -0
  205. package/scripts/integrations/oracle/instantclient/linux/x86-64/install.sh +23 -0
  206. package/scripts/integrations/oracle/oracle.md +90 -0
  207. package/scripts/integrations/postgres/docker-compose.yml +3 -3
  208. package/scripts/likeCypress.ts +33 -0
  209. package/src/api/controllers/application.js +11 -1
  210. package/src/api/controllers/datasource.js +45 -9
  211. package/src/api/controllers/deploy/index.js +2 -0
  212. package/src/api/controllers/dev.js +4 -1
  213. package/src/api/controllers/query.js +26 -80
  214. package/src/api/controllers/table/external.js +8 -1
  215. package/src/api/routes/query.js +1 -0
  216. package/src/app.ts +2 -10
  217. package/src/automations/bullboard.js +28 -11
  218. package/src/automations/tests/automation.spec.js +3 -4
  219. package/src/automations/triggers.js +7 -3
  220. package/src/automations/utils.js +12 -2
  221. package/src/constants/index.js +7 -0
  222. package/src/definitions/datasource.ts +1 -0
  223. package/src/environment.js +15 -0
  224. package/src/integrations/airtable.ts +2 -1
  225. package/src/integrations/arangodb.ts +2 -1
  226. package/src/integrations/base/IntegrationBase.ts +6 -0
  227. package/src/integrations/base/datasourcePlus.ts +2 -1
  228. package/src/integrations/base/sql.ts +41 -9
  229. package/src/integrations/couchdb.ts +2 -1
  230. package/src/integrations/dynamodb.ts +2 -1
  231. package/src/integrations/elasticsearch.ts +2 -1
  232. package/src/integrations/index.ts +7 -0
  233. package/src/integrations/mongodb.ts +2 -1
  234. package/src/integrations/mysql.ts +1 -1
  235. package/src/integrations/oracle.ts +445 -0
  236. package/src/integrations/rest.ts +2 -1
  237. package/src/integrations/s3.ts +2 -1
  238. package/src/integrations/tests/oracle.spec.js +94 -0
  239. package/src/integrations/utils.ts +16 -2
  240. package/src/middleware/builder.js +4 -1
  241. package/src/{automations/thread.js → threads/automation.js} +27 -8
  242. package/src/threads/index.js +66 -0
  243. package/src/threads/query.js +66 -0
  244. package/src/utilities/index.js +1 -0
  245. package/src/utilities/queue/inMemoryQueue.js +7 -0
  246. package/src/utilities/scriptRunner.js +4 -1
  247. package/tsconfig.json +1 -1
  248. package/builder/assets/index.0eadd2f5.js +0 -201
  249. package/builder/assets/index.a79ec0ef.css +0 -29
  250. package/builder/assets/vendor.278a305c.js +0 -9
  251. package/builder/assets/vendor.d75d5eb7.css +0 -1
@@ -0,0 +1,345 @@
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 datasource_1 = require("../definitions/datasource");
16
+ const utils_1 = require("./utils");
17
+ const oracledb_1 = __importDefault(require("oracledb"));
18
+ const sql_1 = __importDefault(require("./base/sql"));
19
+ const constants_1 = require("../constants");
20
+ var OracleModule;
21
+ (function (OracleModule) {
22
+ oracledb_1.default.outFormat = oracledb_1.default.OUT_FORMAT_OBJECT;
23
+ const SCHEMA = {
24
+ docs: "https://github.com/oracle/node-oracledb",
25
+ plus: true,
26
+ friendlyName: "Oracle",
27
+ description: "Oracle Database is an object-relational database management system developed by Oracle Corporation",
28
+ datasource: {
29
+ host: {
30
+ type: datasource_1.DatasourceFieldTypes.STRING,
31
+ default: "localhost",
32
+ required: true,
33
+ },
34
+ port: {
35
+ type: datasource_1.DatasourceFieldTypes.NUMBER,
36
+ required: true,
37
+ default: 1521,
38
+ },
39
+ database: {
40
+ type: datasource_1.DatasourceFieldTypes.STRING,
41
+ required: true,
42
+ },
43
+ user: {
44
+ type: datasource_1.DatasourceFieldTypes.STRING,
45
+ required: true,
46
+ },
47
+ password: {
48
+ type: datasource_1.DatasourceFieldTypes.PASSWORD,
49
+ required: true,
50
+ },
51
+ },
52
+ query: {
53
+ create: {
54
+ type: datasource_1.QueryTypes.SQL,
55
+ },
56
+ read: {
57
+ type: datasource_1.QueryTypes.SQL,
58
+ },
59
+ update: {
60
+ type: datasource_1.QueryTypes.SQL,
61
+ },
62
+ delete: {
63
+ type: datasource_1.QueryTypes.SQL,
64
+ },
65
+ },
66
+ };
67
+ const UNSUPPORTED_TYPES = ["BLOB", "CLOB", "NCLOB"];
68
+ const OracleContraintTypes = {
69
+ PRIMARY: "P",
70
+ NOT_NULL_OR_CHECK: "C",
71
+ FOREIGN_KEY: "R",
72
+ UNIQUE: "U",
73
+ };
74
+ class OracleIntegration extends sql_1.default {
75
+ constructor(config) {
76
+ super(utils_1.SqlClients.ORACLE);
77
+ this.tables = {};
78
+ this.schemaErrors = {};
79
+ this.COLUMNS_SQL = `
80
+ SELECT
81
+ tabs.table_name,
82
+ cols.column_name,
83
+ cols.data_type,
84
+ cols.data_default,
85
+ cols.column_id,
86
+ cons.constraint_name,
87
+ cons.constraint_type,
88
+ cons.r_constraint_name,
89
+ cons.search_condition
90
+ FROM
91
+ user_tables tabs
92
+ JOIN
93
+ user_tab_columns cols
94
+ ON tabs.table_name = cols.table_name
95
+ LEFT JOIN
96
+ user_cons_columns col_cons
97
+ ON cols.column_name = col_cons.column_name
98
+ AND cols.table_name = col_cons.table_name
99
+ LEFT JOIN
100
+ user_constraints cons
101
+ ON col_cons.constraint_name = cons.constraint_name
102
+ AND cons.table_name = cols.table_name
103
+ WHERE
104
+ (cons.status = 'ENABLED'
105
+ OR cons.status IS NULL)
106
+ `;
107
+ this.getConnection = () => __awaiter(this, void 0, void 0, function* () {
108
+ //connectString : "(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))(CONNECT_DATA =(SID= ORCL)))"
109
+ const connectString = `${this.config.host}:${this.config.port || 1521}/${this.config.database}`;
110
+ const attributes = {
111
+ user: this.config.user,
112
+ password: this.config.user,
113
+ connectString,
114
+ };
115
+ return oracledb_1.default.getConnection(attributes);
116
+ });
117
+ this.config = config;
118
+ }
119
+ /**
120
+ * Map the flat tabular columns and constraints data into a nested object
121
+ */
122
+ mapColumns(result) {
123
+ const oracleTables = {};
124
+ if (result.rows) {
125
+ result.rows.forEach(row => {
126
+ const tableName = row.TABLE_NAME;
127
+ const columnName = row.COLUMN_NAME;
128
+ const dataType = row.DATA_TYPE;
129
+ const dataDefault = row.DATA_DEFAULT;
130
+ const columnId = row.COLUMN_ID;
131
+ const constraintName = row.CONSTRAINT_NAME;
132
+ const constraintType = row.CONSTRAINT_TYPE;
133
+ const relatedConstraintName = row.R_CONSTRAINT_NAME;
134
+ const searchCondition = row.SEARCH_CONDITION;
135
+ let table = oracleTables[tableName];
136
+ if (!table) {
137
+ table = {
138
+ name: tableName,
139
+ columns: {},
140
+ };
141
+ oracleTables[tableName] = table;
142
+ }
143
+ let column = table.columns[columnName];
144
+ if (!column) {
145
+ column = {
146
+ name: columnName,
147
+ type: dataType,
148
+ default: dataDefault,
149
+ id: columnId,
150
+ constraints: {},
151
+ };
152
+ table.columns[columnName] = column;
153
+ }
154
+ if (constraintName && constraintType) {
155
+ let constraint = column.constraints[constraintName];
156
+ if (!constraint) {
157
+ constraint = {
158
+ name: constraintName,
159
+ type: constraintType,
160
+ relatedConstraintName: relatedConstraintName,
161
+ searchCondition: searchCondition,
162
+ };
163
+ }
164
+ column.constraints[constraintName] = constraint;
165
+ }
166
+ });
167
+ }
168
+ return oracleTables;
169
+ }
170
+ isSupportedColumn(column) {
171
+ if (UNSUPPORTED_TYPES.includes(column.type)) {
172
+ return false;
173
+ }
174
+ return true;
175
+ }
176
+ isAutoColumn(column) {
177
+ if (column.default && column.default.toLowerCase().includes("nextval")) {
178
+ return true;
179
+ }
180
+ return false;
181
+ }
182
+ /**
183
+ * No native boolean in oracle. Best we can do is to check if a manual 1 or 0 number constraint has been set up
184
+ * This matches the default behaviour for generating DDL used in knex.
185
+ */
186
+ isBooleanType(column) {
187
+ if (column.type.toLowerCase() === "number" &&
188
+ Object.values(column.constraints).filter(c => {
189
+ if (c.type === OracleContraintTypes.NOT_NULL_OR_CHECK &&
190
+ c.searchCondition) {
191
+ const condition = c.searchCondition
192
+ .replace(/\s/g, "") // remove spaces
193
+ .replace(/[']+/g, ""); // remove quotes
194
+ if (condition.includes("in(0,1)") ||
195
+ condition.includes("in(1,0)")) {
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }).length > 0) {
201
+ return true;
202
+ }
203
+ return false;
204
+ }
205
+ internalConvertType(column) {
206
+ if (this.isBooleanType(column)) {
207
+ return constants_1.FieldTypes.BOOLEAN;
208
+ }
209
+ return utils_1.convertSqlType(column.type);
210
+ }
211
+ /**
212
+ * Fetches the tables from the oracle table and assigns them to the datasource.
213
+ * @param {*} datasourceId - datasourceId to fetch
214
+ * @param entities - the tables that are to be built
215
+ */
216
+ buildSchema(datasourceId, entities) {
217
+ return __awaiter(this, void 0, void 0, function* () {
218
+ const columnsResponse = yield this.internalQuery({
219
+ sql: this.COLUMNS_SQL,
220
+ });
221
+ const oracleTables = this.mapColumns(columnsResponse);
222
+ const tables = {};
223
+ // iterate each table
224
+ Object.values(oracleTables).forEach(oracleTable => {
225
+ let table = tables[oracleTable.name];
226
+ if (!table) {
227
+ table = {
228
+ _id: utils_1.buildExternalTableId(datasourceId, oracleTable.name),
229
+ primary: [],
230
+ name: oracleTable.name,
231
+ schema: {},
232
+ };
233
+ tables[oracleTable.name] = table;
234
+ }
235
+ // iterate each column on the table
236
+ Object.values(oracleTable.columns)
237
+ // remove columns that we can't read / save
238
+ .filter(oracleColumn => this.isSupportedColumn(oracleColumn))
239
+ // match the order of the columns in the db
240
+ .sort((c1, c2) => c1.id - c2.id)
241
+ .forEach(oracleColumn => {
242
+ const columnName = oracleColumn.name;
243
+ let fieldSchema = table.schema[columnName];
244
+ if (!fieldSchema) {
245
+ fieldSchema = {
246
+ autocolumn: this.isAutoColumn(oracleColumn),
247
+ name: columnName,
248
+ type: this.internalConvertType(oracleColumn),
249
+ };
250
+ table.schema[columnName] = fieldSchema;
251
+ }
252
+ // iterate each constraint on the column
253
+ Object.values(oracleColumn.constraints).forEach(oracleConstraint => {
254
+ if (oracleConstraint.type === OracleContraintTypes.PRIMARY) {
255
+ table.primary.push(columnName);
256
+ }
257
+ });
258
+ });
259
+ });
260
+ const final = utils_1.finaliseExternalTables(tables, entities);
261
+ this.tables = final.tables;
262
+ this.schemaErrors = final.errors;
263
+ });
264
+ }
265
+ /**
266
+ * Knex default returning behaviour does not work with oracle
267
+ * Manually add the behaviour for the return column
268
+ */
269
+ addReturning(query, bindings, returnColumn) {
270
+ if (bindings instanceof Array) {
271
+ bindings.push({ dir: oracledb_1.default.BIND_OUT });
272
+ query.sql = query.sql + ` returning \"${returnColumn}\" into :${bindings.length}`;
273
+ }
274
+ }
275
+ internalQuery(query, returnColum, operation) {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ let connection;
278
+ try {
279
+ connection = yield this.getConnection();
280
+ const options = { autoCommit: true };
281
+ const bindings = query.bindings || [];
282
+ if (returnColum && (operation === datasource_1.Operation.CREATE || operation === datasource_1.Operation.UPDATE)) {
283
+ this.addReturning(query, bindings, returnColum);
284
+ }
285
+ const result = yield connection.execute(query.sql, bindings, options);
286
+ return result;
287
+ }
288
+ finally {
289
+ if (connection) {
290
+ try {
291
+ yield connection.close();
292
+ }
293
+ catch (err) {
294
+ console.error(err);
295
+ }
296
+ }
297
+ }
298
+ });
299
+ }
300
+ create(query) {
301
+ return __awaiter(this, void 0, void 0, function* () {
302
+ const response = yield this.internalQuery(utils_1.getSqlQuery(query));
303
+ return response.rows && response.rows.length
304
+ ? response.rows
305
+ : [{ created: true }];
306
+ });
307
+ }
308
+ read(query) {
309
+ return __awaiter(this, void 0, void 0, function* () {
310
+ const response = yield this.internalQuery(utils_1.getSqlQuery(query));
311
+ return response.rows ? response.rows : [];
312
+ });
313
+ }
314
+ update(query) {
315
+ return __awaiter(this, void 0, void 0, function* () {
316
+ const response = yield this.internalQuery(utils_1.getSqlQuery(query));
317
+ return response.rows && response.rows.length
318
+ ? response.rows
319
+ : [{ updated: true }];
320
+ });
321
+ }
322
+ delete(query) {
323
+ return __awaiter(this, void 0, void 0, function* () {
324
+ const response = yield this.internalQuery(utils_1.getSqlQuery(query));
325
+ return response.rows && response.rows.length
326
+ ? response.rows
327
+ : [{ deleted: true }];
328
+ });
329
+ }
330
+ query(json) {
331
+ return __awaiter(this, void 0, void 0, function* () {
332
+ const primaryKeys = json.meta.table.primary;
333
+ const primaryKey = primaryKeys ? primaryKeys[0] : undefined;
334
+ const queryFn = (query, operation) => this.internalQuery(query, primaryKey, operation);
335
+ const processFn = (response) => response.rows ? response.rows : [];
336
+ const output = yield this.queryWithReturning(json, queryFn, processFn);
337
+ return output;
338
+ });
339
+ }
340
+ }
341
+ module.exports = {
342
+ schema: SCHEMA,
343
+ integration: OracleIntegration,
344
+ };
345
+ })(OracleModule || (OracleModule = {}));
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.finaliseExternalTables = exports.isIsoDateString = exports.isSQL = exports.getSqlQuery = exports.convertSqlType = exports.breakRowIdField = exports.convertRowId = exports.isRowId = exports.generateRowIdField = exports.breakExternalTableId = exports.buildExternalTableId = exports.isExternalTable = exports.SqlClients = void 0;
4
4
  const datasource_1 = require("../definitions/datasource");
5
5
  const { DocumentTypes, SEPARATOR } = require("../db/utils");
6
- const { FieldTypes, BuildSchemaErrors } = require("../constants");
6
+ const { FieldTypes, BuildSchemaErrors, InvalidColumns } = require("../constants");
7
7
  const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`;
8
8
  const ROW_ID_REGEX = /^\[.*]$/g;
9
9
  const SQL_TYPE_MAP = {
@@ -31,12 +31,17 @@ const SQL_TYPE_MAP = {
31
31
  fixed: FieldTypes.NUMBER,
32
32
  datetime: FieldTypes.DATETIME,
33
33
  tinyint: FieldTypes.BOOLEAN,
34
+ long: FieldTypes.LONGFORM,
35
+ number: FieldTypes.NUMBER,
36
+ binary_float: FieldTypes.NUMBER,
37
+ binary_double: FieldTypes.NUMBER,
34
38
  };
35
39
  var SqlClients;
36
40
  (function (SqlClients) {
37
41
  SqlClients["MS_SQL"] = "mssql";
38
42
  SqlClients["POSTGRES"] = "pg";
39
43
  SqlClients["MY_SQL"] = "mysql";
44
+ SqlClients["ORACLE"] = "oracledb";
40
45
  })(SqlClients = exports.SqlClients || (exports.SqlClients = {}));
41
46
  function isExternalTable(tableId) {
42
47
  return tableId.includes(DocumentTypes.DATASOURCE);
@@ -151,17 +156,27 @@ function copyExistingPropsOver(tableName, table, entities) {
151
156
  return table;
152
157
  }
153
158
  function finaliseExternalTables(tables, entities) {
154
- const finalTables = {};
159
+ const invalidColumns = Object.values(InvalidColumns);
160
+ let finalTables = {};
155
161
  const errors = {};
156
162
  for (let [name, table] of Object.entries(tables)) {
163
+ const schemaFields = Object.keys(table.schema);
157
164
  // make sure every table has a key
158
165
  if (table.primary == null || table.primary.length === 0) {
159
166
  errors[name] = BuildSchemaErrors.NO_KEY;
160
167
  continue;
161
168
  }
169
+ else if (schemaFields.find(field => invalidColumns.includes(field))) {
170
+ errors[name] = BuildSchemaErrors.INVALID_COLUMN;
171
+ continue;
172
+ }
162
173
  // make sure all previous props have been added back
163
174
  finalTables[name] = copyExistingPropsOver(name, table, entities);
164
175
  }
176
+ // sort the tables by name
177
+ finalTables = Object.entries(finalTables)
178
+ .sort(([a], [b]) => a.localeCompare(b))
179
+ .reduce((r, [k, v]) => (Object.assign(Object.assign({}, r), { [k]: v })), {});
165
180
  return { tables: finalTables, errors };
166
181
  }
167
182
  exports.finaliseExternalTables = finaliseExternalTables;
@@ -13,6 +13,7 @@ const { doesUserHaveLock, updateLock, checkDebounce, setDebounce, } = require(".
13
13
  const CouchDB = require("../db");
14
14
  const { DocumentTypes } = require("../db/utils");
15
15
  const { PermissionTypes } = require("@budibase/auth/permissions");
16
+ const { app: appCache } = require("@budibase/auth/cache");
16
17
  const DEBOUNCE_TIME_SEC = 30;
17
18
  /************************************************** *
18
19
  * This middleware has been broken out of the *
@@ -51,7 +52,9 @@ function updateAppUpdatedAt(ctx) {
51
52
  const db = new CouchDB(appId);
52
53
  const metadata = yield db.get(DocumentTypes.APP_METADATA);
53
54
  metadata.updatedAt = new Date().toISOString();
54
- yield db.put(metadata);
55
+ const response = yield db.put(metadata);
56
+ metadata._rev = response.rev;
57
+ yield appCache.invalidateAppMetadata(appId, metadata);
55
58
  // set a new debounce record with a short TTL
56
59
  yield setDebounce(appId, DEBOUNCE_TIME_SEC);
57
60
  });
package/dist/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "0.9.185-alpha.1",
4
+ "version": "0.9.185-alpha.19",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.js",
7
7
  "repository": {
@@ -68,9 +68,11 @@
68
68
  "author": "Budibase",
69
69
  "license": "AGPL-3.0-or-later",
70
70
  "dependencies": {
71
- "@budibase/auth": "^0.9.185-alpha.1",
72
- "@budibase/client": "^0.9.185-alpha.1",
73
- "@budibase/string-templates": "^0.9.185-alpha.1",
71
+ "@budibase/auth": "^0.9.185-alpha.19",
72
+ "@budibase/client": "^0.9.185-alpha.19",
73
+ "@budibase/string-templates": "^0.9.185-alpha.19",
74
+ "@bull-board/api": "^3.7.0",
75
+ "@bull-board/koa": "^3.7.0",
74
76
  "@elastic/elasticsearch": "7.10.0",
75
77
  "@koa/router": "8.0.0",
76
78
  "@sendgrid/mail": "7.1.1",
@@ -80,7 +82,6 @@
80
82
  "aws-sdk": "^2.767.0",
81
83
  "bcryptjs": "2.4.3",
82
84
  "bull": "^3.22.4",
83
- "bull-board": "^2.0.1",
84
85
  "chmodr": "1.2.0",
85
86
  "csvtojson": "2.0.10",
86
87
  "dotenv": "8.2.0",
@@ -120,6 +121,7 @@
120
121
  "uuid": "3.3.2",
121
122
  "validate.js": "0.13.1",
122
123
  "vm2": "^3.9.3",
124
+ "worker-farm": "^1.7.0",
123
125
  "yargs": "13.2.4",
124
126
  "zlib": "1.0.5"
125
127
  },
@@ -133,12 +135,12 @@
133
135
  "@types/koa": "^2.13.3",
134
136
  "@types/koa-router": "^7.4.2",
135
137
  "@types/node": "^15.12.4",
138
+ "@types/oracledb": "^5.2.1",
136
139
  "@typescript-eslint/parser": "4.28.0",
137
140
  "babel-jest": "^27.0.2",
138
141
  "copyfiles": "^2.4.1",
139
142
  "docker-compose": "^0.23.6",
140
143
  "eslint": "^6.8.0",
141
- "express": "^4.17.1",
142
144
  "jest": "^27.0.5",
143
145
  "nodemon": "^2.0.4",
144
146
  "prettier": "^2.3.1",
@@ -149,5 +151,8 @@
149
151
  "typescript": "^4.3.5",
150
152
  "update-dotenv": "^1.1.1"
151
153
  },
154
+ "optionalDependencies": {
155
+ "oracledb": "^5.3.0"
156
+ },
152
157
  "gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc"
153
158
  }
@@ -8,17 +8,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- const actions = require("./actions");
12
- const automationUtils = require("./automationUtils");
11
+ // when thread starts, make sure it is recorded
12
+ const env = require("../environment");
13
+ env.setInThread();
14
+ const actions = require("../automations/actions");
15
+ const automationUtils = require("../automations/automationUtils");
13
16
  const AutomationEmitter = require("../events/AutomationEmitter");
14
17
  const { processObject } = require("@budibase/string-templates");
15
18
  const { DEFAULT_TENANT_ID } = require("@budibase/auth").constants;
16
19
  const CouchDB = require("../db");
17
20
  const { DocumentTypes, isDevAppID } = require("../db/utils");
18
21
  const { doInTenant } = require("@budibase/auth/tenancy");
19
- const env = require("../environment");
20
22
  const usage = require("../utilities/usageQuota");
23
+ const { definitions: triggerDefs } = require("../automations/triggerInfo");
21
24
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId;
25
+ const CRON_STEP_ID = triggerDefs.CRON.stepId;
22
26
  const STOPPED_STATUS = { success: false, status: "STOPPED" };
23
27
  /**
24
28
  * The automation orchestrator is a class responsible for executing automations.
@@ -31,6 +35,8 @@ class Orchestrator {
31
35
  this._chainCount = this._metadata ? this._metadata.automationChainCount : 0;
32
36
  this._appId = triggerOutput.appId;
33
37
  this._app = null;
38
+ const triggerStepId = automation.definition.trigger.stepId;
39
+ triggerOutput = this.cleanupTriggerOutputs(triggerStepId, triggerOutput);
34
40
  // remove from context
35
41
  delete triggerOutput.appId;
36
42
  delete triggerOutput.metadata;
@@ -42,10 +48,15 @@ class Orchestrator {
42
48
  this._emitter = new AutomationEmitter(this._chainCount + 1);
43
49
  this.executionOutput = { trigger: {}, steps: [] };
44
50
  // setup the execution output
45
- const triggerStepId = automation.definition.trigger.stepId;
46
51
  const triggerId = automation.definition.trigger.id;
47
52
  this.updateExecutionOutput(triggerId, triggerStepId, null, triggerOutput);
48
53
  }
54
+ cleanupTriggerOutputs(stepId, triggerOutput) {
55
+ if (stepId === CRON_STEP_ID) {
56
+ triggerOutput.timestamp = Date.now();
57
+ }
58
+ return triggerOutput;
59
+ }
49
60
  getStepFunctionality(stepId) {
50
61
  return __awaiter(this, void 0, void 0, function* () {
51
62
  let step = yield actions.getAction(stepId);
@@ -122,7 +133,14 @@ class Orchestrator {
122
133
  });
123
134
  }
124
135
  }
125
- module.exports = (job) => __awaiter(void 0, void 0, void 0, function* () {
126
- const automationOrchestrator = new Orchestrator(job.data.automation, job.data.event);
127
- return automationOrchestrator.execute();
128
- });
136
+ module.exports = (input, callback) => {
137
+ const automationOrchestrator = new Orchestrator(input.data.automation, input.data.event);
138
+ automationOrchestrator
139
+ .execute()
140
+ .then(response => {
141
+ callback(null, response);
142
+ })
143
+ .catch(err => {
144
+ callback(err);
145
+ });
146
+ };
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ const workerFarm = require("worker-farm");
3
+ const env = require("../environment");
4
+ const ThreadType = {
5
+ QUERY: "query",
6
+ AUTOMATION: "automation",
7
+ };
8
+ function typeToFile(type) {
9
+ let filename = null;
10
+ switch (type) {
11
+ case ThreadType.QUERY:
12
+ filename = "./query";
13
+ break;
14
+ case ThreadType.AUTOMATION:
15
+ filename = "./automation";
16
+ break;
17
+ default:
18
+ throw "Unknown thread type";
19
+ }
20
+ return require.resolve(filename);
21
+ }
22
+ class Thread {
23
+ constructor(type, opts = { timeoutMs: null, count: 1 }) {
24
+ this.type = type;
25
+ this.count = opts.count ? opts.count : 1;
26
+ this.disableThreading =
27
+ env.isTest() ||
28
+ env.DISABLE_THREADING ||
29
+ this.count === 0 ||
30
+ env.isInThread();
31
+ if (!this.disableThreading) {
32
+ const workerOpts = {
33
+ autoStart: true,
34
+ maxConcurrentWorkers: this.count,
35
+ };
36
+ if (opts.timeoutMs) {
37
+ workerOpts.maxCallTime = opts.timeoutMs;
38
+ }
39
+ this.workers = workerFarm(workerOpts, typeToFile(type));
40
+ }
41
+ }
42
+ run(data) {
43
+ return new Promise((resolve, reject) => {
44
+ let fncToCall;
45
+ // if in test then don't use threading
46
+ if (this.disableThreading) {
47
+ fncToCall = require(typeToFile(this.type));
48
+ }
49
+ else {
50
+ fncToCall = this.workers;
51
+ }
52
+ fncToCall(data, (err, response) => {
53
+ if (err) {
54
+ reject(err);
55
+ }
56
+ else {
57
+ resolve(response);
58
+ }
59
+ });
60
+ });
61
+ }
62
+ }
63
+ module.exports.Thread = Thread;
64
+ module.exports.ThreadType = ThreadType;
@@ -0,0 +1,64 @@
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
+ // when thread starts, make sure it is recorded
12
+ const env = require("../environment");
13
+ env.setInThread();
14
+ const ScriptRunner = require("../utilities/scriptRunner");
15
+ const { integrations } = require("../integrations");
16
+ function formatResponse(resp) {
17
+ if (typeof resp === "string") {
18
+ try {
19
+ resp = JSON.parse(resp);
20
+ }
21
+ catch (err) {
22
+ resp = { response: resp };
23
+ }
24
+ }
25
+ return resp;
26
+ }
27
+ function runAndTransform(datasource, queryVerb, query, transformer) {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ const Integration = integrations[datasource.source];
30
+ if (!Integration) {
31
+ throw "Integration type does not exist.";
32
+ }
33
+ const integration = new Integration(datasource.config);
34
+ let rows = formatResponse(yield integration[queryVerb](query));
35
+ // transform as required
36
+ if (transformer) {
37
+ const runner = new ScriptRunner(transformer, { data: rows });
38
+ rows = runner.execute();
39
+ }
40
+ // needs to an array for next step
41
+ if (!Array.isArray(rows)) {
42
+ rows = [rows];
43
+ }
44
+ // map into JSON if just raw primitive here
45
+ if (rows.find(row => typeof row !== "object")) {
46
+ rows = rows.map(value => ({ value }));
47
+ }
48
+ // get all the potential fields in the schema
49
+ let keys = rows.flatMap(Object.keys);
50
+ if (integration.end) {
51
+ integration.end();
52
+ }
53
+ return { rows, keys };
54
+ });
55
+ }
56
+ module.exports = (input, callback) => {
57
+ runAndTransform(input.datasource, input.queryVerb, input.query, input.transformer)
58
+ .then(response => {
59
+ callback(null, response);
60
+ })
61
+ .catch(err => {
62
+ callback(err);
63
+ });
64
+ };