@budibase/server 0.9.188 → 0.9.190-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 (307) hide show
  1. package/Dockerfile +7 -1
  2. package/__mocks__/mssql.ts +1 -1
  3. package/__mocks__/oracledb.ts +31 -0
  4. package/__mocks__/pg.ts +3 -0
  5. package/builder/assets/bb-space-man.5be51a45.svg +290 -0
  6. package/builder/assets/index.7d405e74.css +1 -0
  7. package/builder/assets/index.edea4fa5.js +1316 -0
  8. package/builder/assets/oracle.66592424.png +0 -0
  9. package/builder/assets/vendor.470042a4.js +152 -0
  10. package/builder/assets/vendor.5e1fe644.css +1 -0
  11. package/builder/index.html +4 -4
  12. package/coverage/clover.xml +1507 -1081
  13. package/coverage/coverage-final.json +93 -89
  14. package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
  15. package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
  16. package/coverage/lcov-report/api/controllers/application.js.html +64 -13
  17. package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
  18. package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
  19. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  22. package/coverage/lcov-report/api/controllers/datasource.js.html +232 -28
  23. package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
  24. package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
  25. package/coverage/lcov-report/api/controllers/index.html +91 -91
  26. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
  28. package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
  29. package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
  30. package/coverage/lcov-report/api/controllers/query.js.html +53 -209
  31. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  32. package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
  33. package/coverage/lcov-report/api/controllers/row/external.js.html +17 -8
  34. package/coverage/lcov-report/api/controllers/row/index.html +26 -26
  35. package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
  36. package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
  37. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
  38. package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
  39. package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
  40. package/coverage/lcov-report/api/controllers/script.js.html +3 -3
  41. package/coverage/lcov-report/api/controllers/table/external.js.html +1001 -0
  42. package/coverage/lcov-report/api/controllers/table/index.html +56 -26
  43. package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
  44. package/coverage/lcov-report/api/controllers/table/internal.js.html +545 -0
  45. package/coverage/lcov-report/api/controllers/table/utils.js.html +175 -52
  46. package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
  47. package/coverage/lcov-report/api/controllers/user.js.html +390 -33
  48. package/coverage/lcov-report/api/controllers/view/exporters.js.html +19 -4
  49. package/coverage/lcov-report/api/controllers/view/index.html +22 -22
  50. package/coverage/lcov-report/api/controllers/view/index.js.html +52 -13
  51. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  52. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
  53. package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
  54. package/coverage/lcov-report/api/index.html +1 -1
  55. package/coverage/lcov-report/api/index.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/dev.js.html +2 -2
  67. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/index.html +4 -4
  69. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/query.js.html +5 -2
  75. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/static.js.html +2 -2
  81. package/coverage/lcov-report/api/routes/table.js.html +35 -2
  82. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/user.js.html +17 -2
  84. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  85. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  86. package/coverage/lcov-report/automations/actions.js.html +2 -2
  87. package/coverage/lcov-report/automations/automationUtils.js.html +4 -4
  88. package/coverage/lcov-report/automations/bullboard.js.html +71 -20
  89. package/coverage/lcov-report/automations/index.html +35 -50
  90. package/coverage/lcov-report/automations/index.js.html +2 -2
  91. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
  96. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
  98. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/index.html +14 -14
  100. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
  102. package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
  103. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  106. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  107. package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
  108. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  110. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  113. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  115. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  116. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggers.js.html +22 -10
  118. package/coverage/lcov-report/automations/utils.js.html +42 -12
  119. package/coverage/lcov-report/constants/index.html +5 -5
  120. package/coverage/lcov-report/constants/index.js.html +87 -21
  121. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  122. package/coverage/lcov-report/constants/screens.js.html +1 -1
  123. package/coverage/lcov-report/db/client.js.html +2 -2
  124. package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
  125. package/coverage/lcov-report/db/index.html +2 -2
  126. package/coverage/lcov-report/db/index.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
  128. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  129. package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
  130. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
  131. package/coverage/lcov-report/db/newid.js.html +3 -3
  132. package/coverage/lcov-report/db/utils.js.html +57 -57
  133. package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
  134. package/coverage/lcov-report/events/index.html +6 -6
  135. package/coverage/lcov-report/events/index.js.html +1 -1
  136. package/coverage/lcov-report/events/utils.js.html +5 -5
  137. package/coverage/lcov-report/index.html +106 -91
  138. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  139. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  140. package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
  141. package/coverage/lcov-report/middleware/authorized.js.html +11 -8
  142. package/coverage/lcov-report/middleware/builder.js.html +16 -7
  143. package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
  144. package/coverage/lcov-report/middleware/index.html +23 -23
  145. package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
  146. package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
  147. package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
  148. package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
  149. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  150. package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +90 -33
  151. package/coverage/lcov-report/threads/index.html +141 -0
  152. package/coverage/lcov-report/threads/index.js.html +278 -0
  153. package/coverage/lcov-report/threads/query.js.html +278 -0
  154. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  155. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  156. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  157. package/coverage/lcov-report/utilities/csvParser.js.html +144 -15
  158. package/coverage/lcov-report/utilities/global.js.html +26 -11
  159. package/coverage/lcov-report/utilities/index.html +48 -48
  160. package/coverage/lcov-report/utilities/index.js.html +47 -14
  161. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
  162. package/coverage/lcov-report/utilities/queue/index.html +14 -14
  163. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  164. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  165. package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
  166. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
  167. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
  168. package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
  169. package/coverage/lcov-report/utilities/security.js.html +3 -3
  170. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  171. package/coverage/lcov-report/utilities/users.js.html +1 -1
  172. package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
  173. package/coverage/lcov.info +2495 -1737
  174. package/dist/api/controllers/application.js +15 -1
  175. package/dist/api/controllers/auth.js +3 -3
  176. package/dist/api/controllers/datasource.js +67 -16
  177. package/dist/api/controllers/deploy/index.js +2 -0
  178. package/dist/api/controllers/dev.js +4 -1
  179. package/dist/api/controllers/query.js +30 -58
  180. package/dist/api/controllers/row/ExternalRequest.js +78 -34
  181. package/dist/api/controllers/row/external.js +3 -1
  182. package/dist/api/controllers/row/utils.js +6 -12
  183. package/dist/api/controllers/table/external.js +249 -0
  184. package/dist/api/controllers/table/index.js +49 -123
  185. package/dist/api/controllers/table/internal.js +150 -0
  186. package/dist/api/controllers/table/utils.js +62 -28
  187. package/dist/api/controllers/user.js +123 -11
  188. package/dist/api/controllers/view/exporters.js +4 -0
  189. package/dist/api/controllers/view/index.js +14 -2
  190. package/dist/api/routes/query.js +1 -1
  191. package/dist/api/routes/table.js +7 -1
  192. package/dist/api/routes/user.js +2 -1
  193. package/dist/app.js +2 -11
  194. package/dist/automations/bullboard.js +37 -10
  195. package/dist/automations/triggers.js +7 -3
  196. package/dist/automations/utils.js +11 -2
  197. package/dist/constants/index.js +19 -0
  198. package/dist/definitions/datasource.js +5 -0
  199. package/dist/environment.js +13 -0
  200. package/dist/integrations/base/IntegrationBase.js +2 -0
  201. package/dist/integrations/base/datasourcePlus.js +2 -0
  202. package/dist/integrations/base/sql.js +353 -177
  203. package/dist/integrations/base/sqlTable.js +143 -0
  204. package/dist/integrations/base/utils.js +30 -0
  205. package/dist/integrations/index.js +6 -0
  206. package/dist/integrations/microsoftSqlServer.js +117 -9
  207. package/dist/integrations/mysql.js +16 -85
  208. package/dist/integrations/oracle.js +347 -0
  209. package/dist/integrations/postgres.js +35 -28
  210. package/dist/integrations/utils.js +71 -9
  211. package/dist/middleware/authorized.js +2 -1
  212. package/dist/middleware/builder.js +4 -1
  213. package/dist/package.json +12 -7
  214. package/dist/tests/utilities/TestConfiguration.js +2 -1
  215. package/dist/{automations/thread.js → threads/automation.js} +26 -8
  216. package/dist/threads/index.js +64 -0
  217. package/dist/threads/query.js +64 -0
  218. package/dist/tsconfig.tsbuildinfo +1 -1
  219. package/dist/utilities/csvParser.js +46 -5
  220. package/dist/utilities/global.js +6 -2
  221. package/dist/utilities/index.js +11 -0
  222. package/dist/utilities/queue/inMemoryQueue.js +8 -0
  223. package/dist/utilities/scriptRunner.js +4 -1
  224. package/package.json +13 -8
  225. package/scripts/dev/manage.js +1 -0
  226. package/scripts/integrations/mssql/data/Dockerfile +9 -0
  227. package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
  228. package/scripts/integrations/mssql/data/setup.sql +54 -0
  229. package/scripts/integrations/mssql/docker-compose.yaml +12 -0
  230. package/scripts/integrations/mssql/reset.sh +3 -0
  231. package/scripts/integrations/oracle/docker-compose.yml +19 -0
  232. package/scripts/integrations/oracle/instantclient/linux/x86-64/basiclite-21.4.zip +0 -0
  233. package/scripts/integrations/oracle/instantclient/linux/x86-64/install.sh +23 -0
  234. package/scripts/integrations/oracle/oracle.md +90 -0
  235. package/scripts/integrations/postgres/docker-compose.yml +3 -3
  236. package/scripts/likeCypress.ts +33 -0
  237. package/src/api/controllers/application.js +18 -1
  238. package/src/api/controllers/auth.js +3 -0
  239. package/src/api/controllers/datasource.js +84 -16
  240. package/src/api/controllers/deploy/index.js +2 -0
  241. package/src/api/controllers/dev.js +4 -1
  242. package/src/api/controllers/query.js +29 -81
  243. package/src/api/controllers/row/ExternalRequest.ts +91 -36
  244. package/src/api/controllers/row/external.js +4 -1
  245. package/src/api/controllers/row/utils.js +8 -11
  246. package/src/api/controllers/table/external.js +307 -0
  247. package/src/api/controllers/table/index.js +47 -137
  248. package/src/api/controllers/table/internal.js +155 -0
  249. package/src/api/controllers/table/utils.js +74 -33
  250. package/src/api/controllers/user.js +132 -13
  251. package/src/api/controllers/view/exporters.js +5 -0
  252. package/src/api/controllers/view/index.js +15 -2
  253. package/src/api/routes/query.js +1 -0
  254. package/src/api/routes/table.js +11 -0
  255. package/src/api/routes/tests/datasource.spec.js +2 -2
  256. package/src/api/routes/tests/misc.spec.js +5 -1
  257. package/src/api/routes/tests/query.spec.js +0 -1
  258. package/src/api/routes/user.js +5 -0
  259. package/src/app.ts +2 -10
  260. package/src/automations/bullboard.js +28 -11
  261. package/src/automations/tests/automation.spec.js +3 -4
  262. package/src/automations/triggers.js +7 -3
  263. package/src/automations/utils.js +12 -2
  264. package/src/constants/index.js +22 -0
  265. package/src/definitions/common.ts +7 -1
  266. package/src/definitions/datasource.ts +10 -3
  267. package/src/environment.js +15 -0
  268. package/src/integrations/airtable.ts +2 -1
  269. package/src/integrations/arangodb.ts +2 -1
  270. package/src/integrations/base/IntegrationBase.ts +6 -0
  271. package/src/integrations/base/datasourcePlus.ts +9 -0
  272. package/src/integrations/base/sql.ts +377 -218
  273. package/src/integrations/base/sqlTable.ts +180 -0
  274. package/src/integrations/base/utils.ts +22 -0
  275. package/src/integrations/couchdb.ts +2 -1
  276. package/src/integrations/dynamodb.ts +2 -1
  277. package/src/integrations/elasticsearch.ts +2 -1
  278. package/src/integrations/index.ts +7 -0
  279. package/src/integrations/microsoftSqlServer.ts +145 -13
  280. package/src/integrations/mongodb.ts +2 -1
  281. package/src/integrations/mysql.ts +23 -95
  282. package/src/integrations/oracle.ts +458 -0
  283. package/src/integrations/postgres.ts +45 -35
  284. package/src/integrations/rest.ts +2 -1
  285. package/src/integrations/s3.ts +2 -1
  286. package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
  287. package/src/integrations/tests/oracle.spec.js +94 -0
  288. package/src/integrations/tests/postgres.spec.js +4 -0
  289. package/src/integrations/utils.ts +78 -8
  290. package/src/middleware/authorized.js +2 -1
  291. package/src/middleware/builder.js +4 -1
  292. package/src/tests/utilities/TestConfiguration.js +2 -1
  293. package/src/{automations/thread.js → threads/automation.js} +27 -8
  294. package/src/threads/index.js +66 -0
  295. package/src/threads/query.js +66 -0
  296. package/src/utilities/csvParser.js +48 -5
  297. package/src/utilities/global.js +7 -2
  298. package/src/utilities/index.js +11 -0
  299. package/src/utilities/queue/inMemoryQueue.js +7 -0
  300. package/src/utilities/scriptRunner.js +4 -1
  301. package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
  302. package/src/utilities/tests/csvParser.spec.js +3 -0
  303. package/tsconfig.json +1 -1
  304. package/builder/assets/index.550fdba7.js +0 -201
  305. package/builder/assets/index.7469e1e4.css +0 -29
  306. package/builder/assets/vendor.278a305c.js +0 -9
  307. package/builder/assets/vendor.d75d5eb7.css +0 -1
@@ -1,210 +1,300 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
2
14
  Object.defineProperty(exports, "__esModule", { value: true });
3
15
  const knex_1 = require("knex");
4
- const BASE_LIMIT = 5000;
5
16
  const datasource_1 = require("../../definitions/datasource");
6
17
  const utils_1 = require("../utils");
7
- function parseBody(body) {
8
- for (let [key, value] of Object.entries(body)) {
9
- if (typeof value !== "string") {
10
- continue;
11
- }
12
- if (utils_1.isIsoDateString(value)) {
13
- body[key] = new Date(value);
14
- }
15
- }
16
- return body;
17
- }
18
- // right now we only do filters on the specific table being queried
19
- function addFilters(tableName, query, filters) {
20
- function iterate(structure, fn) {
21
- for (let [key, value] of Object.entries(structure)) {
22
- fn(`${tableName}.${key}`, value);
23
- }
24
- }
25
- if (!filters) {
26
- return query;
27
- }
28
- // if all or specified in filters, then everything is an or
29
- const allOr = filters.allOr;
30
- if (filters.oneOf) {
31
- iterate(filters.oneOf, (key, array) => {
32
- const fnc = allOr ? "orWhereIn" : "whereIn";
33
- query = query[fnc](key, array);
34
- });
35
- }
36
- if (filters.string) {
37
- iterate(filters.string, (key, value) => {
38
- const fnc = allOr ? "orWhere" : "where";
39
- query = query[fnc](key, "ilike", `${value}%`);
40
- });
18
+ const sqlTable_1 = __importDefault(require("./sqlTable"));
19
+ const BASE_LIMIT = 5000;
20
+ // these are invalid dates sent by the client, need to convert them to a real max date
21
+ const MIN_ISO_DATE = "0000-00-00T00:00:00.000Z";
22
+ const MAX_ISO_DATE = "9999-00-00T00:00:00.000Z";
23
+ function parse(input) {
24
+ if (Array.isArray(input)) {
25
+ return JSON.stringify(input);
41
26
  }
42
- if (filters.fuzzy) {
43
- iterate(filters.fuzzy, (key, value) => {
44
- const fnc = allOr ? "orWhere" : "where";
45
- query = query[fnc](key, "ilike", `%${value}%`);
46
- });
27
+ if (input == undefined) {
28
+ return null;
47
29
  }
48
- if (filters.range) {
49
- iterate(filters.range, (key, value) => {
50
- if (!value.high || !value.low) {
51
- return;
52
- }
53
- const fnc = allOr ? "orWhereBetween" : "whereBetween";
54
- query = query[fnc](key, [value.low, value.high]);
55
- });
30
+ if (typeof input !== "string") {
31
+ return input;
56
32
  }
57
- if (filters.equal) {
58
- iterate(filters.equal, (key, value) => {
59
- const fnc = allOr ? "orWhere" : "where";
60
- query = query[fnc]({ [key]: value });
61
- });
33
+ if (input === MAX_ISO_DATE) {
34
+ return new Date(8640000000000000);
62
35
  }
63
- if (filters.notEqual) {
64
- iterate(filters.notEqual, (key, value) => {
65
- const fnc = allOr ? "orWhereNot" : "whereNot";
66
- query = query[fnc]({ [key]: value });
67
- });
36
+ if (input === MIN_ISO_DATE) {
37
+ return new Date(-8640000000000000);
68
38
  }
69
- if (filters.empty) {
70
- iterate(filters.empty, key => {
71
- const fnc = allOr ? "orWhereNull" : "whereNull";
72
- query = query[fnc](key);
73
- });
39
+ if (utils_1.isIsoDateString(input)) {
40
+ return new Date(input);
74
41
  }
75
- if (filters.notEmpty) {
76
- iterate(filters.notEmpty, key => {
77
- const fnc = allOr ? "orWhereNotNull" : "whereNotNull";
78
- query = query[fnc](key);
79
- });
42
+ return input;
43
+ }
44
+ function parseBody(body) {
45
+ for (let [key, value] of Object.entries(body)) {
46
+ body[key] = parse(value);
80
47
  }
81
- return query;
48
+ return body;
82
49
  }
83
- function addRelationships(knex, query, fields, fromTable, relationships) {
84
- if (!relationships) {
85
- return query;
50
+ function parseFilters(filters) {
51
+ if (!filters) {
52
+ return {};
86
53
  }
87
- for (let relationship of relationships) {
88
- const from = relationship.from, to = relationship.to, toTable = relationship.tableName;
89
- if (!relationship.through) {
90
- // @ts-ignore
91
- query = query.leftJoin(toTable, `${fromTable}.${from}`, `${toTable}.${to}`);
54
+ for (let [key, value] of Object.entries(filters)) {
55
+ let parsed;
56
+ if (typeof value === "object") {
57
+ parsed = parseFilters(value);
92
58
  }
93
59
  else {
94
- const throughTable = relationship.through;
95
- const fromPrimary = relationship.fromPrimary;
96
- const toPrimary = relationship.toPrimary;
97
- query = query
98
- // @ts-ignore
99
- .leftJoin(throughTable, `${fromTable}.${fromPrimary}`, `${throughTable}.${from}`)
100
- .leftJoin(toTable, `${toTable}.${toPrimary}`, `${throughTable}.${to}`);
60
+ parsed = parse(value);
101
61
  }
62
+ // @ts-ignore
63
+ filters[key] = parsed;
102
64
  }
103
- return query.limit(BASE_LIMIT);
65
+ return filters;
104
66
  }
105
- function buildCreate(knex, json, opts) {
106
- const { endpoint, body } = json;
107
- let query = knex(endpoint.entityId);
108
- const parsedBody = parseBody(body);
109
- // make sure no null values in body for creation
110
- for (let [key, value] of Object.entries(parsedBody)) {
111
- if (value == null) {
112
- delete parsedBody[key];
113
- }
114
- }
115
- // mysql can't use returning
116
- if (opts.disableReturning) {
117
- return query.insert(parsedBody);
67
+ class InternalBuilder {
68
+ constructor(client) {
69
+ this.client = client;
118
70
  }
119
- else {
120
- return query.insert(parsedBody).returning("*");
71
+ // right now we only do filters on the specific table being queried
72
+ addFilters(tableName, query, filters) {
73
+ function iterate(structure, fn) {
74
+ for (let [key, value] of Object.entries(structure)) {
75
+ fn(`${tableName}.${key}`, value);
76
+ }
77
+ }
78
+ if (!filters) {
79
+ return query;
80
+ }
81
+ filters = parseFilters(filters);
82
+ // if all or specified in filters, then everything is an or
83
+ const allOr = filters.allOr;
84
+ if (filters.oneOf) {
85
+ iterate(filters.oneOf, (key, array) => {
86
+ const fnc = allOr ? "orWhereIn" : "whereIn";
87
+ query = query[fnc](key, array);
88
+ });
89
+ }
90
+ if (filters.string) {
91
+ iterate(filters.string, (key, value) => {
92
+ const fnc = allOr ? "orWhere" : "where";
93
+ // postgres supports ilike, nothing else does
94
+ if (this.client === utils_1.SqlClients.POSTGRES) {
95
+ query = query[fnc](key, "ilike", `${value}%`);
96
+ }
97
+ else {
98
+ const rawFnc = `${fnc}Raw`;
99
+ // @ts-ignore
100
+ query = query[rawFnc](`LOWER(${key}) LIKE ?`, [`${value}%`]);
101
+ }
102
+ });
103
+ }
104
+ if (filters.fuzzy) {
105
+ iterate(filters.fuzzy, (key, value) => {
106
+ const fnc = allOr ? "orWhere" : "where";
107
+ // postgres supports ilike, nothing else does
108
+ if (this.client === utils_1.SqlClients.POSTGRES) {
109
+ query = query[fnc](key, "ilike", `%${value}%`);
110
+ }
111
+ else {
112
+ const rawFnc = `${fnc}Raw`;
113
+ // @ts-ignore
114
+ query = query[rawFnc](`LOWER(${key}) LIKE ?`, [`%${value}%`]);
115
+ }
116
+ });
117
+ }
118
+ if (filters.range) {
119
+ iterate(filters.range, (key, value) => {
120
+ if (!value.high || !value.low) {
121
+ return;
122
+ }
123
+ const fnc = allOr ? "orWhereBetween" : "whereBetween";
124
+ query = query[fnc](key, [value.low, value.high]);
125
+ });
126
+ }
127
+ if (filters.equal) {
128
+ iterate(filters.equal, (key, value) => {
129
+ const fnc = allOr ? "orWhere" : "where";
130
+ query = query[fnc]({ [key]: value });
131
+ });
132
+ }
133
+ if (filters.notEqual) {
134
+ iterate(filters.notEqual, (key, value) => {
135
+ const fnc = allOr ? "orWhereNot" : "whereNot";
136
+ query = query[fnc]({ [key]: value });
137
+ });
138
+ }
139
+ if (filters.empty) {
140
+ iterate(filters.empty, key => {
141
+ const fnc = allOr ? "orWhereNull" : "whereNull";
142
+ query = query[fnc](key);
143
+ });
144
+ }
145
+ if (filters.notEmpty) {
146
+ iterate(filters.notEmpty, key => {
147
+ const fnc = allOr ? "orWhereNotNull" : "whereNotNull";
148
+ query = query[fnc](key);
149
+ });
150
+ }
151
+ return query;
121
152
  }
122
- }
123
- function buildRead(knex, json, limit) {
124
- let { endpoint, resource, filters, sort, paginate, relationships } = json;
125
- const tableName = endpoint.entityId;
126
- // select all if not specified
127
- if (!resource) {
128
- resource = { fields: [] };
129
- }
130
- let selectStatement = "*";
131
- // handle select
132
- if (resource.fields && resource.fields.length > 0) {
133
- // select the resources as the format "table.columnName" - this is what is provided
134
- // by the resource builder further up
135
- selectStatement = resource.fields.map(field => `${field} as ${field}`);
136
- }
137
- let foundLimit = limit || BASE_LIMIT;
138
- // handle pagination
139
- let foundOffset = null;
140
- if (paginate && paginate.page && paginate.limit) {
141
- // @ts-ignore
142
- const page = paginate.page <= 1 ? 0 : paginate.page - 1;
143
- const offset = page * paginate.limit;
144
- foundLimit = paginate.limit;
145
- foundOffset = offset;
153
+ addSorting(query, json) {
154
+ var _a;
155
+ let { sort, paginate } = json;
156
+ if (!sort) {
157
+ return query;
158
+ }
159
+ const table = (_a = json.meta) === null || _a === void 0 ? void 0 : _a.table;
160
+ for (let [key, value] of Object.entries(sort)) {
161
+ const direction = value === datasource_1.SortDirection.ASCENDING ? "asc" : "desc";
162
+ query = query.orderBy(`${table === null || table === void 0 ? void 0 : table.name}.${key}`, direction);
163
+ }
164
+ if (this.client === utils_1.SqlClients.MS_SQL && !sort && (paginate === null || paginate === void 0 ? void 0 : paginate.limit)) {
165
+ // @ts-ignore
166
+ query = query.orderBy(`${table === null || table === void 0 ? void 0 : table.name}.${table === null || table === void 0 ? void 0 : table.primary[0]}`);
167
+ }
168
+ return query;
146
169
  }
147
- else if (paginate && paginate.limit) {
148
- foundLimit = paginate.limit;
170
+ addRelationships(knex, query, fields, fromTable, relationships) {
171
+ if (!relationships) {
172
+ return query;
173
+ }
174
+ for (let relationship of relationships) {
175
+ const from = relationship.from, to = relationship.to, toTable = relationship.tableName;
176
+ if (!relationship.through) {
177
+ // @ts-ignore
178
+ query = query.leftJoin(toTable, `${fromTable}.${from}`, `${toTable}.${to}`);
179
+ }
180
+ else {
181
+ const throughTable = relationship.through;
182
+ const fromPrimary = relationship.fromPrimary;
183
+ const toPrimary = relationship.toPrimary;
184
+ query = query
185
+ // @ts-ignore
186
+ .leftJoin(throughTable, `${fromTable}.${fromPrimary}`, `${throughTable}.${from}`)
187
+ .leftJoin(toTable, `${toTable}.${toPrimary}`, `${throughTable}.${to}`);
188
+ }
189
+ }
190
+ return query.limit(BASE_LIMIT);
149
191
  }
150
- // start building the query
151
- let query = knex(tableName).limit(foundLimit);
152
- if (foundOffset) {
153
- query = query.offset(foundOffset);
192
+ create(knex, json, opts) {
193
+ const { endpoint, body } = json;
194
+ let query = knex(endpoint.entityId);
195
+ const parsedBody = parseBody(body);
196
+ // make sure no null values in body for creation
197
+ for (let [key, value] of Object.entries(parsedBody)) {
198
+ if (value == null) {
199
+ delete parsedBody[key];
200
+ }
201
+ }
202
+ // mysql can't use returning
203
+ if (opts.disableReturning) {
204
+ return query.insert(parsedBody);
205
+ }
206
+ else {
207
+ return query.insert(parsedBody).returning("*");
208
+ }
154
209
  }
155
- if (sort) {
156
- for (let [key, value] of Object.entries(sort)) {
157
- const direction = value === datasource_1.SortDirection.ASCENDING ? "asc" : "desc";
158
- query = query.orderBy(key, direction);
210
+ bulkCreate(knex, json) {
211
+ const { endpoint, body } = json;
212
+ let query = knex(endpoint.entityId);
213
+ if (!Array.isArray(body)) {
214
+ return query;
159
215
  }
216
+ const parsedBody = body.map(row => parseBody(row));
217
+ return query.insert(parsedBody);
160
218
  }
161
- query = addFilters(tableName, query, filters);
162
- // @ts-ignore
163
- let preQuery = knex({
219
+ read(knex, json, limit) {
220
+ let { endpoint, resource, filters, sort, paginate, relationships } = json;
221
+ const tableName = endpoint.entityId;
222
+ // select all if not specified
223
+ if (!resource) {
224
+ resource = { fields: [] };
225
+ }
226
+ let selectStatement = "*";
227
+ // handle select
228
+ if (resource.fields && resource.fields.length > 0) {
229
+ // select the resources as the format "table.columnName" - this is what is provided
230
+ // by the resource builder further up
231
+ selectStatement = resource.fields.map(field => `${field} as ${field}`);
232
+ }
233
+ let foundLimit = limit || BASE_LIMIT;
234
+ // handle pagination
235
+ let foundOffset = null;
236
+ if (paginate && paginate.page && paginate.limit) {
237
+ // @ts-ignore
238
+ const page = paginate.page <= 1 ? 0 : paginate.page - 1;
239
+ const offset = page * paginate.limit;
240
+ foundLimit = paginate.limit;
241
+ foundOffset = offset;
242
+ }
243
+ else if (paginate && paginate.limit) {
244
+ foundLimit = paginate.limit;
245
+ }
246
+ // start building the query
247
+ let query = knex(tableName).limit(foundLimit);
248
+ if (foundOffset) {
249
+ query = query.offset(foundOffset);
250
+ }
251
+ query = this.addFilters(tableName, query, filters);
252
+ // add sorting to pre-query
253
+ query = this.addSorting(query, json);
164
254
  // @ts-ignore
165
- [tableName]: query,
166
- }).select(selectStatement);
167
- // handle joins
168
- return addRelationships(knex, preQuery, selectStatement, tableName, relationships);
169
- }
170
- function buildUpdate(knex, json, opts) {
171
- const { endpoint, body, filters } = json;
172
- let query = knex(endpoint.entityId);
173
- const parsedBody = parseBody(body);
174
- query = addFilters(endpoint.entityId, query, filters);
175
- // mysql can't use returning
176
- if (opts.disableReturning) {
177
- return query.update(parsedBody);
178
- }
179
- else {
180
- return query.update(parsedBody).returning("*");
255
+ let preQuery = knex({
256
+ // @ts-ignore
257
+ [tableName]: query,
258
+ }).select(selectStatement);
259
+ // have to add after as well (this breaks MS-SQL)
260
+ if (this.client !== utils_1.SqlClients.MS_SQL) {
261
+ preQuery = this.addSorting(preQuery, json);
262
+ }
263
+ // handle joins
264
+ return this.addRelationships(knex, preQuery, selectStatement, tableName, relationships);
181
265
  }
182
- }
183
- function buildDelete(knex, json, opts) {
184
- const { endpoint, filters } = json;
185
- let query = knex(endpoint.entityId);
186
- query = addFilters(endpoint.entityId, query, filters);
187
- // mysql can't use returning
188
- if (opts.disableReturning) {
189
- return query.delete();
266
+ update(knex, json, opts) {
267
+ const { endpoint, body, filters } = json;
268
+ let query = knex(endpoint.entityId);
269
+ const parsedBody = parseBody(body);
270
+ query = this.addFilters(endpoint.entityId, query, filters);
271
+ // mysql can't use returning
272
+ if (opts.disableReturning) {
273
+ return query.update(parsedBody);
274
+ }
275
+ else {
276
+ return query.update(parsedBody).returning("*");
277
+ }
190
278
  }
191
- else {
192
- return query.delete().returning("*");
279
+ delete(knex, json, opts) {
280
+ const { endpoint, filters } = json;
281
+ let query = knex(endpoint.entityId);
282
+ query = this.addFilters(endpoint.entityId, query, filters);
283
+ // mysql can't use returning
284
+ if (opts.disableReturning) {
285
+ return query.delete();
286
+ }
287
+ else {
288
+ return query.delete().returning("*");
289
+ }
193
290
  }
194
291
  }
195
- class SqlQueryBuilder {
292
+ class SqlQueryBuilder extends sqlTable_1.default {
196
293
  // pass through client to get flavour of SQL
197
294
  constructor(client, limit = BASE_LIMIT) {
198
- this.sqlClient = client;
295
+ super(client);
199
296
  this.limit = limit;
200
297
  }
201
- /**
202
- * @param json the input JSON structure from which an SQL query will be built.
203
- * @return {string} the operation that was found in the JSON.
204
- */
205
- _operation(json) {
206
- return json.endpoint.operation;
207
- }
208
298
  /**
209
299
  * @param json The JSON query DSL which is to be converted to SQL.
210
300
  * @param opts extra options which are to be passed into the query builder, e.g. disableReturning
@@ -212,26 +302,112 @@ class SqlQueryBuilder {
212
302
  * @return {{ sql: string, bindings: object }} the query ready to be passed to the driver.
213
303
  */
214
304
  _query(json, opts = {}) {
215
- const client = knex_1.knex({ client: this.sqlClient });
305
+ const sqlClient = this.getSqlClient();
306
+ const client = knex_1.knex({ client: sqlClient });
216
307
  let query;
308
+ const builder = new InternalBuilder(sqlClient);
217
309
  switch (this._operation(json)) {
218
310
  case datasource_1.Operation.CREATE:
219
- query = buildCreate(client, json, opts);
311
+ query = builder.create(client, json, opts);
220
312
  break;
221
313
  case datasource_1.Operation.READ:
222
- query = buildRead(client, json, this.limit);
314
+ query = builder.read(client, json, this.limit);
223
315
  break;
224
316
  case datasource_1.Operation.UPDATE:
225
- query = buildUpdate(client, json, opts);
317
+ query = builder.update(client, json, opts);
226
318
  break;
227
319
  case datasource_1.Operation.DELETE:
228
- query = buildDelete(client, json, opts);
320
+ query = builder.delete(client, json, opts);
229
321
  break;
322
+ case datasource_1.Operation.BULK_CREATE:
323
+ query = builder.bulkCreate(client, json);
324
+ break;
325
+ case datasource_1.Operation.CREATE_TABLE:
326
+ case datasource_1.Operation.UPDATE_TABLE:
327
+ case datasource_1.Operation.DELETE_TABLE:
328
+ return this._tableQuery(json);
230
329
  default:
231
330
  throw `Operation type is not supported by SQL query builder`;
232
331
  }
233
332
  // @ts-ignore
234
333
  return query.toSQL().toNative();
235
334
  }
335
+ getReturningRow(queryFn, json) {
336
+ return __awaiter(this, void 0, void 0, function* () {
337
+ if (!json.extra || !json.extra.idFilter) {
338
+ return {};
339
+ }
340
+ const input = this._query({
341
+ endpoint: Object.assign(Object.assign({}, json.endpoint), { operation: datasource_1.Operation.READ }),
342
+ resource: {
343
+ fields: [],
344
+ },
345
+ filters: json.extra.idFilter,
346
+ paginate: {
347
+ limit: 1,
348
+ },
349
+ meta: json.meta,
350
+ });
351
+ return queryFn(input, datasource_1.Operation.READ);
352
+ });
353
+ }
354
+ // when creating if an ID has been inserted need to make sure
355
+ // the id filter is enriched with it before trying to retrieve the row
356
+ checkLookupKeys(id, json) {
357
+ var _a, _b;
358
+ if (!id || !((_a = json.meta) === null || _a === void 0 ? void 0 : _a.table) || !json.meta.table.primary) {
359
+ return json;
360
+ }
361
+ const primaryKey = (_b = json.meta.table.primary) === null || _b === void 0 ? void 0 : _b[0];
362
+ json.extra = {
363
+ idFilter: {
364
+ equal: {
365
+ [primaryKey]: id,
366
+ },
367
+ },
368
+ };
369
+ return json;
370
+ }
371
+ // this function recreates the returning functionality of postgres
372
+ queryWithReturning(json, queryFn, processFn = (result) => result) {
373
+ return __awaiter(this, void 0, void 0, function* () {
374
+ const sqlClient = this.getSqlClient();
375
+ const operation = this._operation(json);
376
+ const input = this._query(json, { disableReturning: true });
377
+ if (Array.isArray(input)) {
378
+ const responses = [];
379
+ for (let query of input) {
380
+ responses.push(yield queryFn(query, operation));
381
+ }
382
+ return responses;
383
+ }
384
+ let row;
385
+ // need to manage returning, a feature mySQL can't do
386
+ if (operation === datasource_1.Operation.DELETE) {
387
+ row = processFn(yield this.getReturningRow(queryFn, json));
388
+ }
389
+ const response = yield queryFn(input, operation);
390
+ const results = processFn(response);
391
+ // same as delete, manage returning
392
+ if (operation === datasource_1.Operation.CREATE || operation === datasource_1.Operation.UPDATE) {
393
+ let id;
394
+ if (sqlClient === utils_1.SqlClients.MS_SQL) {
395
+ id = results === null || results === void 0 ? void 0 : results[0].id;
396
+ }
397
+ else if (sqlClient === utils_1.SqlClients.MY_SQL) {
398
+ id = results === null || results === void 0 ? void 0 : results.insertId;
399
+ }
400
+ else if (sqlClient === utils_1.SqlClients.ORACLE) {
401
+ id = response.outBinds[0][0];
402
+ }
403
+ row = processFn(yield this.getReturningRow(queryFn, this.checkLookupKeys(id, json)));
404
+ }
405
+ if (operation !== datasource_1.Operation.READ) {
406
+ return row;
407
+ }
408
+ return results.length ? results : [{ [operation.toLowerCase()]: true }];
409
+ });
410
+ }
236
411
  }
412
+ exports.default = SqlQueryBuilder;
237
413
  module.exports = SqlQueryBuilder;