@budibase/server 1.3.12-alpha.2 → 1.3.13

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 (253) hide show
  1. package/__mocks__/mongodb.ts +1 -1
  2. package/builder/assets/{index.7886c551.css → index.e50bda9f.css} +2 -2
  3. package/builder/assets/index.fb22f106.js +875 -0
  4. package/builder/assets/vendor.5e1fe644.css +1 -0
  5. package/builder/assets/vendor.67dbd8fa.js +248 -0
  6. package/builder/index.html +4 -2
  7. package/coverage/clover.xml +253 -295
  8. package/coverage/coverage-final.json +17 -17
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +13 -82
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +20 -20
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/index.html +30 -30
  18. package/coverage/lcov-report/api/controllers/integration.js.html +6 -6
  19. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  24. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/screen.js.html +12 -204
  34. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  47. package/coverage/lcov-report/api/index.html +1 -1
  48. package/coverage/lcov-report/api/index.js.html +12 -12
  49. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/index.html +1 -1
  60. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  74. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  77. package/coverage/lcov-report/automations/actions.js.html +1 -1
  78. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  79. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  80. package/coverage/lcov-report/automations/index.html +1 -1
  81. package/coverage/lcov-report/automations/index.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/index.html +1 -1
  89. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  108. package/coverage/lcov-report/constants/index.html +1 -1
  109. package/coverage/lcov-report/constants/index.js.html +1 -1
  110. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  111. package/coverage/lcov-report/constants/screens.js.html +1 -1
  112. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  113. package/coverage/lcov-report/db/index.html +18 -18
  114. package/coverage/lcov-report/db/index.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  119. package/coverage/lcov-report/db/newid.js.html +2 -2
  120. package/coverage/lcov-report/db/utils.js.html +20 -56
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  122. package/coverage/lcov-report/events/index.html +1 -1
  123. package/coverage/lcov-report/events/index.js.html +1 -1
  124. package/coverage/lcov-report/events/utils.js.html +1 -1
  125. package/coverage/lcov-report/index.html +28 -28
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  127. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  128. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  129. package/coverage/lcov-report/middleware/builder.js.html +12 -12
  130. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  131. package/coverage/lcov-report/middleware/index.html +1 -1
  132. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  133. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  134. package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
  135. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  136. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  137. package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
  138. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  139. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  140. package/coverage/lcov-report/utilities/global.js.html +16 -16
  141. package/coverage/lcov-report/utilities/index.html +1 -1
  142. package/coverage/lcov-report/utilities/index.js.html +23 -23
  143. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  144. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  145. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  146. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  147. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  148. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  150. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  151. package/coverage/lcov-report/utilities/security.js.html +2 -2
  152. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  153. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  156. package/coverage/lcov-report/utilities/users.js.html +1 -1
  157. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  158. package/coverage/lcov.info +444 -532
  159. package/dist/api/controllers/application.js +4 -5
  160. package/dist/api/controllers/component.js +1 -18
  161. package/dist/api/controllers/datasource.js +4 -4
  162. package/dist/api/controllers/integration.js +4 -4
  163. package/dist/api/controllers/screen.js +2 -51
  164. package/dist/api/controllers/static/index.js +0 -1
  165. package/dist/api/controllers/static/templates/BudibaseApp.svelte +0 -10
  166. package/dist/api/controllers/static/templates/preview.hbs +1 -3
  167. package/dist/api/routes/index.js +0 -2
  168. package/dist/api/routes/static.js +1 -1
  169. package/dist/app.js +0 -9
  170. package/dist/db/utils.js +1 -10
  171. package/dist/environment.js +0 -1
  172. package/dist/integrations/airtable.js +129 -126
  173. package/dist/integrations/arangodb.js +89 -86
  174. package/dist/integrations/base/query.js +2 -2
  175. package/dist/integrations/couchdb.js +83 -80
  176. package/dist/integrations/dynamodb.js +164 -161
  177. package/dist/integrations/elasticsearch.js +138 -135
  178. package/dist/integrations/firebase.js +157 -154
  179. package/dist/integrations/googlesheets.js +327 -323
  180. package/dist/integrations/index.js +51 -93
  181. package/dist/integrations/microsoftSqlServer.js +243 -240
  182. package/dist/integrations/mongodb.js +242 -239
  183. package/dist/integrations/mysql.js +219 -215
  184. package/dist/integrations/oracle.js +322 -318
  185. package/dist/integrations/postgres.js +265 -262
  186. package/dist/integrations/redis.js +139 -134
  187. package/dist/integrations/rest.js +281 -278
  188. package/dist/integrations/s3.js +64 -61
  189. package/dist/integrations/snowflake.js +86 -83
  190. package/dist/package.json +6 -8
  191. package/dist/threads/query.js +2 -2
  192. package/dist/tsconfig.build.tsbuildinfo +1 -1
  193. package/dist/utilities/fileSystem/index.js +0 -65
  194. package/package.json +7 -9
  195. package/scripts/dev/manage.js +0 -1
  196. package/src/api/controllers/application.ts +1 -1
  197. package/src/api/controllers/component.js +2 -25
  198. package/src/api/controllers/datasource.js +4 -4
  199. package/src/api/controllers/integration.js +4 -4
  200. package/src/api/controllers/screen.js +1 -65
  201. package/src/api/controllers/static/index.ts +0 -1
  202. package/src/api/controllers/static/templates/BudibaseApp.svelte +0 -10
  203. package/src/api/controllers/static/templates/preview.hbs +1 -3
  204. package/src/api/routes/index.ts +0 -2
  205. package/src/api/routes/static.ts +1 -1
  206. package/src/api/routes/tests/query.spec.js +25 -8
  207. package/src/api/routes/tests/static.spec.js +2 -2
  208. package/src/app.ts +0 -12
  209. package/src/db/utils.js +0 -12
  210. package/src/environment.js +0 -1
  211. package/src/integrations/airtable.ts +118 -116
  212. package/src/integrations/arangodb.ts +89 -87
  213. package/src/integrations/base/query.ts +2 -2
  214. package/src/integrations/couchdb.ts +89 -83
  215. package/src/integrations/dynamodb.ts +175 -173
  216. package/src/integrations/elasticsearch.ts +122 -120
  217. package/src/integrations/firebase.ts +159 -157
  218. package/src/integrations/googlesheets.ts +338 -328
  219. package/src/integrations/index.ts +21 -59
  220. package/src/integrations/microsoftSqlServer.ts +251 -249
  221. package/src/integrations/mongodb.ts +258 -261
  222. package/src/integrations/mysql.ts +234 -229
  223. package/src/integrations/oracle.ts +380 -373
  224. package/src/integrations/postgres.ts +268 -264
  225. package/src/integrations/redis.ts +132 -128
  226. package/src/integrations/rest.ts +315 -310
  227. package/src/integrations/s3.ts +71 -68
  228. package/src/integrations/snowflake.ts +82 -80
  229. package/src/integrations/tests/{airtable.spec.ts → airtable.spec.js} +18 -21
  230. package/src/integrations/tests/{arangodb.spec.ts → arangodb.spec.js} +9 -12
  231. package/src/integrations/tests/{couchdb.spec.ts → couchdb.spec.js} +27 -33
  232. package/src/integrations/tests/{dynamodb.spec.ts → dynamodb.spec.js} +41 -45
  233. package/src/integrations/tests/{elasticsearch.spec.ts → elasticsearch.spec.js} +21 -22
  234. package/src/integrations/tests/{firebase.spec.ts → firebase.spec.js} +28 -33
  235. package/src/integrations/tests/{microsoftSqlServer.spec.ts → microsoftSqlServer.spec.js} +11 -12
  236. package/src/integrations/tests/{mongo.spec.ts → mongo.spec.js} +35 -46
  237. package/src/integrations/tests/{mysql.spec.ts → mysql.spec.js} +15 -17
  238. package/src/integrations/tests/{oracle.spec.ts → oracle.spec.js} +17 -19
  239. package/src/integrations/tests/{postgres.spec.ts → postgres.spec.js} +17 -19
  240. package/src/integrations/tests/{redis.spec.ts → redis.spec.js} +18 -27
  241. package/src/integrations/tests/{rest.spec.ts → rest.spec.js} +11 -19
  242. package/src/integrations/tests/{s3.spec.ts → s3.spec.js} +8 -10
  243. package/src/integrations/tests/{sql.spec.ts → sql.spec.js} +177 -228
  244. package/src/module.d.ts +0 -1
  245. package/src/threads/query.ts +2 -2
  246. package/src/utilities/fileSystem/index.js +0 -69
  247. package/builder/assets/index.a0a1e7ff.js +0 -994
  248. package/dist/api/controllers/plugin.js +0 -119
  249. package/dist/api/routes/plugin.js +0 -38
  250. package/dist/watch.js +0 -77
  251. package/src/api/controllers/plugin.ts +0 -110
  252. package/src/api/routes/plugin.ts +0 -13
  253. package/src/watch.ts +0 -38
@@ -14,11 +14,6 @@ import {
14
14
  BearerAuthConfig,
15
15
  } from "../definitions/datasource"
16
16
  import { get } from "lodash"
17
- const fetch = require("node-fetch")
18
- const { formatBytes } = require("../utilities")
19
- const { performance } = require("perf_hooks")
20
- const FormData = require("form-data")
21
- const { URLSearchParams } = require("url")
22
17
 
23
18
  const BodyTypes = {
24
19
  NONE: "none",
@@ -55,353 +50,363 @@ const coreFields = {
55
50
  },
56
51
  }
57
52
 
58
- const { parseStringPromise: xmlParser, Builder: XmlBuilder } = require("xml2js")
53
+ module RestModule {
54
+ const fetch = require("node-fetch")
55
+ const { formatBytes } = require("../utilities")
56
+ const { performance } = require("perf_hooks")
57
+ const FormData = require("form-data")
58
+ const { URLSearchParams } = require("url")
59
+ const {
60
+ parseStringPromise: xmlParser,
61
+ Builder: XmlBuilder,
62
+ } = require("xml2js")
59
63
 
60
- const SCHEMA: Integration = {
61
- docs: "https://github.com/node-fetch/node-fetch",
62
- description:
63
- "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.",
64
- friendlyName: "REST API",
65
- type: "API",
66
- datasource: {
67
- url: {
68
- type: DatasourceFieldType.STRING,
69
- default: "",
70
- required: false,
71
- deprecated: true,
72
- },
73
- defaultHeaders: {
74
- type: DatasourceFieldType.OBJECT,
75
- required: false,
76
- default: {},
77
- },
78
- },
79
- query: {
80
- create: {
81
- readable: true,
82
- displayName: "POST",
83
- type: QueryType.FIELDS,
84
- fields: coreFields,
85
- },
86
- read: {
87
- displayName: "GET",
88
- readable: true,
89
- type: QueryType.FIELDS,
90
- fields: coreFields,
91
- },
92
- update: {
93
- displayName: "PUT",
94
- readable: true,
95
- type: QueryType.FIELDS,
96
- fields: coreFields,
97
- },
98
- patch: {
99
- displayName: "PATCH",
100
- readable: true,
101
- type: QueryType.FIELDS,
102
- fields: coreFields,
103
- },
104
- delete: {
105
- displayName: "DELETE",
106
- type: QueryType.FIELDS,
107
- fields: coreFields,
64
+ const SCHEMA: Integration = {
65
+ docs: "https://github.com/node-fetch/node-fetch",
66
+ description:
67
+ "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.",
68
+ friendlyName: "REST API",
69
+ type: "API",
70
+ datasource: {
71
+ url: {
72
+ type: DatasourceFieldType.STRING,
73
+ default: "",
74
+ required: false,
75
+ deprecated: true,
76
+ },
77
+ defaultHeaders: {
78
+ type: DatasourceFieldType.OBJECT,
79
+ required: false,
80
+ default: {},
81
+ },
108
82
  },
109
- },
110
- }
111
-
112
- class RestIntegration implements IntegrationBase {
113
- private config: RestConfig
114
- private headers: {
115
- [key: string]: string
116
- } = {}
117
- private startTimeMs: number = performance.now()
118
-
119
- constructor(config: RestConfig) {
120
- this.config = config
121
- }
122
-
123
- async parseResponse(response: any, pagination: PaginationConfig | null) {
124
- let data, raw, headers
125
- const contentType = response.headers.get("content-type") || ""
126
- try {
127
- if (contentType.includes("application/json")) {
128
- data = await response.json()
129
- raw = JSON.stringify(data)
130
- } else if (
131
- contentType.includes("text/xml") ||
132
- contentType.includes("application/xml")
133
- ) {
134
- const rawXml = await response.text()
135
- data =
136
- (await xmlParser(rawXml, {
137
- explicitArray: false,
138
- trim: true,
139
- explicitRoot: false,
140
- })) || {}
141
- // there is only one structure, its an array, return the array so it appears as rows
142
- const keys = Object.keys(data)
143
- if (keys.length === 1 && Array.isArray(data[keys[0]])) {
144
- data = data[keys[0]]
145
- }
146
- raw = rawXml
147
- } else {
148
- data = await response.text()
149
- raw = data
150
- }
151
- } catch (err) {
152
- throw "Failed to parse response body."
153
- }
154
- const size = formatBytes(
155
- response.headers.get("content-length") || Buffer.byteLength(raw, "utf8")
156
- )
157
- const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
158
- headers = response.headers.raw()
159
- for (let [key, value] of Object.entries(headers)) {
160
- headers[key] = Array.isArray(value) ? value[0] : value
161
- }
162
-
163
- // Check if a pagination cursor exists in the response
164
- let nextCursor = null
165
- if (pagination?.responseParam) {
166
- nextCursor = get(data, pagination.responseParam)
167
- }
168
-
169
- return {
170
- data,
171
- info: {
172
- code: response.status,
173
- size,
174
- time,
83
+ query: {
84
+ create: {
85
+ readable: true,
86
+ displayName: "POST",
87
+ type: QueryType.FIELDS,
88
+ fields: coreFields,
175
89
  },
176
- extra: {
177
- raw,
178
- headers,
90
+ read: {
91
+ displayName: "GET",
92
+ readable: true,
93
+ type: QueryType.FIELDS,
94
+ fields: coreFields,
179
95
  },
180
- pagination: {
181
- cursor: nextCursor,
96
+ update: {
97
+ displayName: "PUT",
98
+ readable: true,
99
+ type: QueryType.FIELDS,
100
+ fields: coreFields,
182
101
  },
183
- }
102
+ patch: {
103
+ displayName: "PATCH",
104
+ readable: true,
105
+ type: QueryType.FIELDS,
106
+ fields: coreFields,
107
+ },
108
+ delete: {
109
+ displayName: "DELETE",
110
+ type: QueryType.FIELDS,
111
+ fields: coreFields,
112
+ },
113
+ },
184
114
  }
185
115
 
186
- getUrl(
187
- path: string,
188
- queryString: string,
189
- pagination: PaginationConfig | null,
190
- paginationValues: PaginationValues | null
191
- ): string {
192
- // Add pagination params to query string if required
193
- if (pagination?.location === "query" && paginationValues) {
194
- const { pageParam, sizeParam } = pagination
195
- const params = new URLSearchParams()
116
+ class RestIntegration implements IntegrationBase {
117
+ private config: RestConfig
118
+ private headers: {
119
+ [key: string]: string
120
+ } = {}
121
+ private startTimeMs: number = performance.now()
196
122
 
197
- // Append page number or cursor param if configured
198
- if (pageParam && paginationValues.page != null) {
199
- params.append(pageParam, paginationValues.page)
123
+ constructor(config: RestConfig) {
124
+ this.config = config
125
+ }
126
+
127
+ async parseResponse(response: any, pagination: PaginationConfig | null) {
128
+ let data, raw, headers
129
+ const contentType = response.headers.get("content-type") || ""
130
+ try {
131
+ if (contentType.includes("application/json")) {
132
+ data = await response.json()
133
+ raw = JSON.stringify(data)
134
+ } else if (
135
+ contentType.includes("text/xml") ||
136
+ contentType.includes("application/xml")
137
+ ) {
138
+ const rawXml = await response.text()
139
+ data =
140
+ (await xmlParser(rawXml, {
141
+ explicitArray: false,
142
+ trim: true,
143
+ explicitRoot: false,
144
+ })) || {}
145
+ // there is only one structure, its an array, return the array so it appears as rows
146
+ const keys = Object.keys(data)
147
+ if (keys.length === 1 && Array.isArray(data[keys[0]])) {
148
+ data = data[keys[0]]
149
+ }
150
+ raw = rawXml
151
+ } else {
152
+ data = await response.text()
153
+ raw = data
154
+ }
155
+ } catch (err) {
156
+ throw "Failed to parse response body."
157
+ }
158
+ const size = formatBytes(
159
+ response.headers.get("content-length") || Buffer.byteLength(raw, "utf8")
160
+ )
161
+ const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
162
+ headers = response.headers.raw()
163
+ for (let [key, value] of Object.entries(headers)) {
164
+ headers[key] = Array.isArray(value) ? value[0] : value
200
165
  }
201
166
 
202
- // Append page size param if configured
203
- if (sizeParam && paginationValues.limit != null) {
204
- params.append(sizeParam, paginationValues.limit)
167
+ // Check if a pagination cursor exists in the response
168
+ let nextCursor = null
169
+ if (pagination?.responseParam) {
170
+ nextCursor = get(data, pagination.responseParam)
205
171
  }
206
172
 
207
- // Prepend query string with pagination params
208
- let paginationString = params.toString()
209
- if (paginationString) {
210
- queryString = `${paginationString}&${queryString}`
173
+ return {
174
+ data,
175
+ info: {
176
+ code: response.status,
177
+ size,
178
+ time,
179
+ },
180
+ extra: {
181
+ raw,
182
+ headers,
183
+ },
184
+ pagination: {
185
+ cursor: nextCursor,
186
+ },
211
187
  }
212
188
  }
213
189
 
214
- const main = `${path}?${queryString}`
215
- let complete = main
216
- if (this.config.url && !main.startsWith("http")) {
217
- complete = !this.config.url ? main : `${this.config.url}/${main}`
218
- }
219
- if (!complete.startsWith("http")) {
220
- complete = `http://${complete}`
221
- }
222
- return complete
223
- }
190
+ getUrl(
191
+ path: string,
192
+ queryString: string,
193
+ pagination: PaginationConfig | null,
194
+ paginationValues: PaginationValues | null
195
+ ): string {
196
+ // Add pagination params to query string if required
197
+ if (pagination?.location === "query" && paginationValues) {
198
+ const { pageParam, sizeParam } = pagination
199
+ const params = new URLSearchParams()
224
200
 
225
- addBody(
226
- bodyType: string,
227
- body: string | any,
228
- input: any,
229
- pagination: PaginationConfig | null,
230
- paginationValues: PaginationValues | null
231
- ) {
232
- if (!input.headers) {
233
- input.headers = {}
234
- }
235
- if (bodyType === BodyTypes.NONE) {
236
- return input
237
- }
238
- let error,
239
- object: any = {},
240
- string = ""
241
- try {
242
- if (body) {
243
- string = typeof body !== "string" ? JSON.stringify(body) : body
244
- object = typeof body === "object" ? body : JSON.parse(body)
245
- }
246
- } catch (err) {
247
- error = err
248
- }
201
+ // Append page number or cursor param if configured
202
+ if (pageParam && paginationValues.page != null) {
203
+ params.append(pageParam, paginationValues.page)
204
+ }
249
205
 
250
- // Util to add pagination values to a certain body type
251
- const addPaginationToBody = (insertFn: Function) => {
252
- if (pagination?.location === "body") {
253
- if (pagination?.pageParam && paginationValues?.page != null) {
254
- insertFn(pagination.pageParam, paginationValues.page)
206
+ // Append page size param if configured
207
+ if (sizeParam && paginationValues.limit != null) {
208
+ params.append(sizeParam, paginationValues.limit)
255
209
  }
256
- if (pagination?.sizeParam && paginationValues?.limit != null) {
257
- insertFn(pagination.sizeParam, paginationValues.limit)
210
+
211
+ // Prepend query string with pagination params
212
+ let paginationString = params.toString()
213
+ if (paginationString) {
214
+ queryString = `${paginationString}&${queryString}`
258
215
  }
259
216
  }
217
+
218
+ const main = `${path}?${queryString}`
219
+ let complete = main
220
+ if (this.config.url && !main.startsWith("http")) {
221
+ complete = !this.config.url ? main : `${this.config.url}/${main}`
222
+ }
223
+ if (!complete.startsWith("http")) {
224
+ complete = `http://${complete}`
225
+ }
226
+ return complete
260
227
  }
261
228
 
262
- switch (bodyType) {
263
- case BodyTypes.TEXT:
264
- // content type defaults to plaintext
265
- input.body = string
266
- break
267
- case BodyTypes.ENCODED:
268
- const params = new URLSearchParams()
269
- for (let [key, value] of Object.entries(object)) {
270
- params.append(key, value)
271
- }
272
- addPaginationToBody((key: string, value: any) => {
273
- params.append(key, value)
274
- })
275
- input.body = params
276
- break
277
- case BodyTypes.FORM_DATA:
278
- const form = new FormData()
279
- for (let [key, value] of Object.entries(object)) {
280
- form.append(key, value)
281
- }
282
- addPaginationToBody((key: string, value: any) => {
283
- form.append(key, value)
284
- })
285
- input.body = form
286
- break
287
- case BodyTypes.XML:
288
- if (object != null && Object.keys(object).length) {
289
- string = new XmlBuilder().buildObject(object)
229
+ addBody(
230
+ bodyType: string,
231
+ body: string | any,
232
+ input: any,
233
+ pagination: PaginationConfig | null,
234
+ paginationValues: PaginationValues | null
235
+ ) {
236
+ if (!input.headers) {
237
+ input.headers = {}
238
+ }
239
+ if (bodyType === BodyTypes.NONE) {
240
+ return input
241
+ }
242
+ let error,
243
+ object: any = {},
244
+ string = ""
245
+ try {
246
+ if (body) {
247
+ string = typeof body !== "string" ? JSON.stringify(body) : body
248
+ object = typeof body === "object" ? body : JSON.parse(body)
290
249
  }
291
- input.body = string
292
- input.headers["Content-Type"] = "application/xml"
293
- break
294
- case BodyTypes.JSON:
295
- // if JSON error, throw it
296
- if (error) {
297
- throw "Invalid JSON for request body"
250
+ } catch (err) {
251
+ error = err
252
+ }
253
+
254
+ // Util to add pagination values to a certain body type
255
+ const addPaginationToBody = (insertFn: Function) => {
256
+ if (pagination?.location === "body") {
257
+ if (pagination?.pageParam && paginationValues?.page != null) {
258
+ insertFn(pagination.pageParam, paginationValues.page)
259
+ }
260
+ if (pagination?.sizeParam && paginationValues?.limit != null) {
261
+ insertFn(pagination.sizeParam, paginationValues.limit)
262
+ }
298
263
  }
299
- addPaginationToBody((key: string, value: any) => {
300
- object[key] = value
301
- })
302
- input.body = JSON.stringify(object)
303
- input.headers["Content-Type"] = "application/json"
304
- break
264
+ }
265
+
266
+ switch (bodyType) {
267
+ case BodyTypes.TEXT:
268
+ // content type defaults to plaintext
269
+ input.body = string
270
+ break
271
+ case BodyTypes.ENCODED:
272
+ const params = new URLSearchParams()
273
+ for (let [key, value] of Object.entries(object)) {
274
+ params.append(key, value)
275
+ }
276
+ addPaginationToBody((key: string, value: any) => {
277
+ params.append(key, value)
278
+ })
279
+ input.body = params
280
+ break
281
+ case BodyTypes.FORM_DATA:
282
+ const form = new FormData()
283
+ for (let [key, value] of Object.entries(object)) {
284
+ form.append(key, value)
285
+ }
286
+ addPaginationToBody((key: string, value: any) => {
287
+ form.append(key, value)
288
+ })
289
+ input.body = form
290
+ break
291
+ case BodyTypes.XML:
292
+ if (object != null && Object.keys(object).length) {
293
+ string = new XmlBuilder().buildObject(object)
294
+ }
295
+ input.body = string
296
+ input.headers["Content-Type"] = "application/xml"
297
+ break
298
+ case BodyTypes.JSON:
299
+ // if JSON error, throw it
300
+ if (error) {
301
+ throw "Invalid JSON for request body"
302
+ }
303
+ addPaginationToBody((key: string, value: any) => {
304
+ object[key] = value
305
+ })
306
+ input.body = JSON.stringify(object)
307
+ input.headers["Content-Type"] = "application/json"
308
+ break
309
+ }
310
+ return input
305
311
  }
306
- return input
307
- }
308
312
 
309
- getAuthHeaders(authConfigId: string): { [key: string]: any } {
310
- let headers: any = {}
313
+ getAuthHeaders(authConfigId: string): { [key: string]: any } {
314
+ let headers: any = {}
311
315
 
312
- if (this.config.authConfigs && authConfigId) {
313
- const authConfig = this.config.authConfigs.filter(
314
- c => c._id === authConfigId
315
- )[0]
316
- // check the config still exists before proceeding
317
- // if not - do nothing
318
- if (authConfig) {
319
- let config
320
- switch (authConfig.type) {
321
- case AuthType.BASIC:
322
- config = authConfig.config as BasicAuthConfig
323
- headers.Authorization = `Basic ${Buffer.from(
324
- `${config.username}:${config.password}`
325
- ).toString("base64")}`
326
- break
327
- case AuthType.BEARER:
328
- config = authConfig.config as BearerAuthConfig
329
- headers.Authorization = `Bearer ${config.token}`
330
- break
316
+ if (this.config.authConfigs && authConfigId) {
317
+ const authConfig = this.config.authConfigs.filter(
318
+ c => c._id === authConfigId
319
+ )[0]
320
+ // check the config still exists before proceeding
321
+ // if not - do nothing
322
+ if (authConfig) {
323
+ let config
324
+ switch (authConfig.type) {
325
+ case AuthType.BASIC:
326
+ config = authConfig.config as BasicAuthConfig
327
+ headers.Authorization = `Basic ${Buffer.from(
328
+ `${config.username}:${config.password}`
329
+ ).toString("base64")}`
330
+ break
331
+ case AuthType.BEARER:
332
+ config = authConfig.config as BearerAuthConfig
333
+ headers.Authorization = `Bearer ${config.token}`
334
+ break
335
+ }
331
336
  }
332
337
  }
333
- }
334
338
 
335
- return headers
336
- }
339
+ return headers
340
+ }
337
341
 
338
- async _req(query: RestQuery) {
339
- const {
340
- path = "",
341
- queryString = "",
342
- headers = {},
343
- method = "GET",
344
- disabledHeaders,
345
- bodyType,
346
- requestBody,
347
- authConfigId,
348
- pagination,
349
- paginationValues,
350
- } = query
351
- const authHeaders = this.getAuthHeaders(authConfigId)
342
+ async _req(query: RestQuery) {
343
+ const {
344
+ path = "",
345
+ queryString = "",
346
+ headers = {},
347
+ method = "GET",
348
+ disabledHeaders,
349
+ bodyType,
350
+ requestBody,
351
+ authConfigId,
352
+ pagination,
353
+ paginationValues,
354
+ } = query
355
+ const authHeaders = this.getAuthHeaders(authConfigId)
352
356
 
353
- this.headers = {
354
- ...this.config.defaultHeaders,
355
- ...headers,
356
- ...authHeaders,
357
- }
357
+ this.headers = {
358
+ ...this.config.defaultHeaders,
359
+ ...headers,
360
+ ...authHeaders,
361
+ }
358
362
 
359
- if (disabledHeaders) {
360
- for (let headerKey of Object.keys(this.headers)) {
361
- if (disabledHeaders[headerKey]) {
362
- delete this.headers[headerKey]
363
+ if (disabledHeaders) {
364
+ for (let headerKey of Object.keys(this.headers)) {
365
+ if (disabledHeaders[headerKey]) {
366
+ delete this.headers[headerKey]
367
+ }
363
368
  }
364
369
  }
365
- }
366
370
 
367
- let input: any = { method, headers: this.headers }
368
- input = this.addBody(
369
- bodyType,
370
- requestBody,
371
- input,
372
- pagination,
373
- paginationValues
374
- )
371
+ let input: any = { method, headers: this.headers }
372
+ input = this.addBody(
373
+ bodyType,
374
+ requestBody,
375
+ input,
376
+ pagination,
377
+ paginationValues
378
+ )
375
379
 
376
- this.startTimeMs = performance.now()
377
- const url = this.getUrl(path, queryString, pagination, paginationValues)
378
- const response = await fetch(url, input)
379
- return await this.parseResponse(response, pagination)
380
- }
380
+ this.startTimeMs = performance.now()
381
+ const url = this.getUrl(path, queryString, pagination, paginationValues)
382
+ const response = await fetch(url, input)
383
+ return await this.parseResponse(response, pagination)
384
+ }
381
385
 
382
- async create(opts: RestQuery) {
383
- return this._req({ ...opts, method: "POST" })
384
- }
386
+ async create(opts: RestQuery) {
387
+ return this._req({ ...opts, method: "POST" })
388
+ }
385
389
 
386
- async read(opts: RestQuery) {
387
- return this._req({ ...opts, method: "GET" })
388
- }
390
+ async read(opts: RestQuery) {
391
+ return this._req({ ...opts, method: "GET" })
392
+ }
389
393
 
390
- async update(opts: RestQuery) {
391
- return this._req({ ...opts, method: "PUT" })
392
- }
394
+ async update(opts: RestQuery) {
395
+ return this._req({ ...opts, method: "PUT" })
396
+ }
393
397
 
394
- async patch(opts: RestQuery) {
395
- return this._req({ ...opts, method: "PATCH" })
396
- }
398
+ async patch(opts: RestQuery) {
399
+ return this._req({ ...opts, method: "PATCH" })
400
+ }
397
401
 
398
- async delete(opts: RestQuery) {
399
- return this._req({ ...opts, method: "DELETE" })
402
+ async delete(opts: RestQuery) {
403
+ return this._req({ ...opts, method: "DELETE" })
404
+ }
400
405
  }
401
- }
402
406
 
403
- export default {
404
- schema: SCHEMA,
405
- integration: RestIntegration,
406
- AuthType,
407
+ module.exports = {
408
+ schema: SCHEMA,
409
+ integration: RestIntegration,
410
+ AuthType,
411
+ }
407
412
  }