@budibase/server 1.0.17 → 1.0.19-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 (227) hide show
  1. package/__mocks__/node-fetch.ts +3 -0
  2. package/builder/assets/bb-spaceship.8f6e81e1.svg +227 -0
  3. package/builder/assets/{index.4fb3f887.css → index.2fc6da87.css} +1 -1
  4. package/builder/assets/index.86b28e1c.js +1320 -0
  5. package/builder/assets/{vendor.470042a4.js → vendor.a9288856.js} +1 -1
  6. package/builder/index.html +3 -3
  7. package/coverage/clover.xml +440 -372
  8. package/coverage/coverage-final.json +17 -16
  9. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/datasource.js.html +14 -14
  18. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/index.html +23 -38
  21. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/query/index.html +126 -0
  26. package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +159 -27
  27. package/coverage/lcov-report/api/controllers/query/validation.js.html +203 -0
  28. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/user.js.html +108 -9
  45. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  49. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/webhook.js.html +18 -6
  51. package/coverage/lcov-report/api/index.html +1 -1
  52. package/coverage/lcov-report/api/index.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/index.html +9 -9
  66. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/query.js.html +11 -98
  72. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/user.js.html +32 -2
  81. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  83. package/coverage/lcov-report/automations/actions.js.html +1 -1
  84. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  85. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  86. package/coverage/lcov-report/automations/index.html +1 -1
  87. package/coverage/lcov-report/automations/index.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/index.html +1 -1
  97. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  105. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  113. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  114. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  115. package/coverage/lcov-report/automations/utils.js.html +1 -1
  116. package/coverage/lcov-report/constants/index.html +1 -1
  117. package/coverage/lcov-report/constants/index.js.html +22 -22
  118. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  119. package/coverage/lcov-report/constants/screens.js.html +1 -1
  120. package/coverage/lcov-report/db/client.js.html +18 -18
  121. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  122. package/coverage/lcov-report/db/index.html +15 -15
  123. package/coverage/lcov-report/db/index.js.html +3 -3
  124. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  126. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  127. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  128. package/coverage/lcov-report/db/newid.js.html +4 -4
  129. package/coverage/lcov-report/db/utils.js.html +91 -64
  130. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  131. package/coverage/lcov-report/events/index.html +1 -1
  132. package/coverage/lcov-report/events/index.js.html +1 -1
  133. package/coverage/lcov-report/events/utils.js.html +1 -1
  134. package/coverage/lcov-report/index.html +67 -52
  135. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  136. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  137. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  138. package/coverage/lcov-report/middleware/authorized.js.html +2 -2
  139. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  140. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  141. package/coverage/lcov-report/middleware/index.html +1 -1
  142. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  143. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  144. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  145. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  146. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  147. package/coverage/lcov-report/threads/automation.js.html +1 -1
  148. package/coverage/lcov-report/threads/index.html +20 -20
  149. package/coverage/lcov-report/threads/index.js.html +1 -1
  150. package/coverage/lcov-report/threads/query.js.html +63 -12
  151. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  152. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  153. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  154. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  155. package/coverage/lcov-report/utilities/global.js.html +1 -1
  156. package/coverage/lcov-report/utilities/index.html +19 -19
  157. package/coverage/lcov-report/utilities/index.js.html +66 -33
  158. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  159. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  160. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  161. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  162. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  164. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  165. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  166. package/coverage/lcov-report/utilities/security.js.html +2 -2
  167. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  168. package/coverage/lcov-report/utilities/users.js.html +1 -1
  169. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  170. package/coverage/lcov.info +688 -583
  171. package/dist/api/controllers/query/import/index.js +79 -0
  172. package/dist/api/controllers/query/import/sources/base/index.js +63 -0
  173. package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
  174. package/dist/api/controllers/query/import/sources/curl.js +90 -0
  175. package/dist/api/controllers/query/import/sources/openapi2.js +139 -0
  176. package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  177. package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  178. package/dist/api/controllers/{query.js → query/index.js} +42 -6
  179. package/dist/api/controllers/query/validation.js +37 -0
  180. package/dist/api/controllers/user.js +37 -1
  181. package/dist/api/controllers/webhook.js +4 -0
  182. package/dist/api/routes/query.js +2 -32
  183. package/dist/api/routes/user.js +3 -1
  184. package/dist/db/utils.js +8 -0
  185. package/dist/integrations/rest.js +110 -113
  186. package/dist/package.json +8 -4
  187. package/dist/threads/query.js +14 -2
  188. package/dist/tsconfig.tsbuildinfo +1 -1
  189. package/dist/utilities/index.js +10 -0
  190. package/package.json +9 -5
  191. package/src/api/controllers/query/import/index.ts +85 -0
  192. package/src/api/controllers/query/import/sources/base/index.ts +85 -0
  193. package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
  194. package/src/api/controllers/query/import/sources/curl.ts +94 -0
  195. package/src/api/controllers/query/import/sources/openapi2.ts +159 -0
  196. package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +104 -0
  197. package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
  198. package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
  199. package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
  200. package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
  201. package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
  202. package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
  203. package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
  204. package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
  205. package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
  206. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
  207. package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
  208. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
  209. package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
  210. package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +239 -0
  211. package/src/api/controllers/query/import/tests/index.spec.js +115 -0
  212. package/src/api/controllers/{query.js → query/index.js} +50 -6
  213. package/src/api/controllers/query/validation.js +41 -0
  214. package/src/api/controllers/user.js +33 -0
  215. package/src/api/controllers/webhook.js +4 -0
  216. package/src/api/routes/query.js +5 -34
  217. package/src/api/routes/user.js +10 -0
  218. package/src/db/utils.js +9 -0
  219. package/src/definitions/common.ts +2 -16
  220. package/src/definitions/datasource.ts +50 -1
  221. package/src/integrations/base/IntegrationBase.ts +4 -4
  222. package/src/integrations/oracle.ts +1 -1
  223. package/src/integrations/rest.ts +111 -137
  224. package/src/integrations/tests/rest.spec.js +16 -7
  225. package/src/threads/query.js +19 -2
  226. package/src/utilities/index.js +11 -0
  227. package/builder/assets/index.3ba0b30e.js +0 -1316
@@ -1,4 +1,4 @@
1
- import { Row, Table } from "./common"
1
+ import { Row, Table, Base } from "./common"
2
2
 
3
3
  export enum Operation {
4
4
  CREATE = "CREATE",
@@ -181,3 +181,52 @@ export interface SqlQuery {
181
181
  export interface QueryOptions {
182
182
  disableReturning?: boolean
183
183
  }
184
+
185
+ export interface Datasource extends Base {
186
+ type: string
187
+ name: string
188
+ source: SourceNames
189
+ // the config is defined by the schema
190
+ config: {
191
+ [key: string]: string | number | boolean
192
+ }
193
+ plus: boolean
194
+ entities?: {
195
+ [key: string]: Table
196
+ }
197
+ }
198
+
199
+ export interface QueryParameter {
200
+ name: string
201
+ default: string
202
+ }
203
+
204
+ export interface RestQueryFields {
205
+ path: string
206
+ queryString?: string
207
+ headers: { [key: string]: any }
208
+ disabledHeaders: { [key: string]: any }
209
+ requestBody: any
210
+ bodyType: string
211
+ json: object
212
+ method: string
213
+ }
214
+
215
+ export interface RestConfig {
216
+ url: string
217
+ defaultHeaders: {
218
+ [key: string]: any
219
+ }
220
+ }
221
+
222
+ export interface Query {
223
+ _id?: string
224
+ datasourceId: string
225
+ name: string
226
+ parameters: QueryParameter[]
227
+ fields: RestQueryFields | any
228
+ transformer: string | null
229
+ schema: any
230
+ readable: boolean
231
+ queryVerb: string
232
+ }
@@ -1,6 +1,6 @@
1
1
  export interface IntegrationBase {
2
- create?(query: any): Promise<any[]>
3
- read?(query: any): Promise<any[]>
4
- update?(query: any): Promise<any[]>
5
- delete?(query: any): Promise<any[]>
2
+ create?(query: any): Promise<any[]|any>
3
+ read?(query: any): Promise<any[]|any>
4
+ update?(query: any): Promise<any[]|any>
5
+ delete?(query: any): Promise<any[]|any>
6
6
  }
@@ -450,7 +450,7 @@ module OracleModule {
450
450
  })
451
451
  return lastRow.rows
452
452
  } else {
453
- return [{ [ operation.toLowerCase() ]: true }]
453
+ return [{ [operation.toLowerCase()]: true }]
454
454
  }
455
455
  }
456
456
  }
@@ -2,29 +2,58 @@ import {
2
2
  Integration,
3
3
  DatasourceFieldTypes,
4
4
  QueryTypes,
5
+ RestConfig,
6
+ RestQueryFields as RestQuery,
5
7
  } from "../definitions/datasource"
6
8
  import { IntegrationBase } from "./base/IntegrationBase"
7
9
 
10
+ const BodyTypes = {
11
+ NONE: "none",
12
+ FORM_DATA: "form",
13
+ ENCODED: "encoded",
14
+ JSON: "json",
15
+ TEXT: "text",
16
+ }
17
+
18
+ const coreFields = {
19
+ path: {
20
+ type: DatasourceFieldTypes.STRING,
21
+ display: "URL",
22
+ },
23
+ queryString: {
24
+ type: DatasourceFieldTypes.STRING,
25
+ },
26
+ headers: {
27
+ type: DatasourceFieldTypes.OBJECT,
28
+ },
29
+ enabledHeaders: {
30
+ type: DatasourceFieldTypes.OBJECT,
31
+ },
32
+ requestBody: {
33
+ type: DatasourceFieldTypes.JSON,
34
+ },
35
+ bodyType: {
36
+ type: DatasourceFieldTypes.STRING,
37
+ enum: Object.values(BodyTypes),
38
+ },
39
+ }
40
+
8
41
  module RestModule {
9
42
  const fetch = require("node-fetch")
10
-
11
- interface RestConfig {
12
- url: string
13
- defaultHeaders: {
14
- [key: string]: any
15
- }
16
- }
43
+ const { formatBytes } = require("../utilities")
44
+ const { performance } = require("perf_hooks")
17
45
 
18
46
  const SCHEMA: Integration = {
19
47
  docs: "https://github.com/node-fetch/node-fetch",
20
48
  description:
21
- "Representational state transfer (REST) is a de-facto standard for a software architecture for interactive applications that typically use multiple Web services. ",
49
+ "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.",
22
50
  friendlyName: "REST API",
23
51
  datasource: {
24
52
  url: {
25
53
  type: DatasourceFieldTypes.STRING,
26
- default: "localhost",
27
- required: true,
54
+ default: "",
55
+ required: false,
56
+ deprecated: true,
28
57
  },
29
58
  defaultHeaders: {
30
59
  type: DatasourceFieldTypes.OBJECT,
@@ -37,97 +66,30 @@ module RestModule {
37
66
  readable: true,
38
67
  displayName: "POST",
39
68
  type: QueryTypes.FIELDS,
40
- urlDisplay: true,
41
- fields: {
42
- path: {
43
- type: DatasourceFieldTypes.STRING,
44
- },
45
- queryString: {
46
- type: DatasourceFieldTypes.STRING,
47
- },
48
- headers: {
49
- type: DatasourceFieldTypes.OBJECT,
50
- },
51
- requestBody: {
52
- type: DatasourceFieldTypes.JSON,
53
- },
54
- },
69
+ fields: coreFields,
55
70
  },
56
71
  read: {
57
72
  displayName: "GET",
58
73
  readable: true,
59
74
  type: QueryTypes.FIELDS,
60
- urlDisplay: true,
61
- fields: {
62
- path: {
63
- type: DatasourceFieldTypes.STRING,
64
- },
65
- queryString: {
66
- type: DatasourceFieldTypes.STRING,
67
- },
68
- headers: {
69
- type: DatasourceFieldTypes.OBJECT,
70
- },
71
- },
75
+ fields: coreFields,
72
76
  },
73
77
  update: {
74
78
  displayName: "PUT",
75
79
  readable: true,
76
80
  type: QueryTypes.FIELDS,
77
- urlDisplay: true,
78
- fields: {
79
- path: {
80
- type: DatasourceFieldTypes.STRING,
81
- },
82
- queryString: {
83
- type: DatasourceFieldTypes.STRING,
84
- },
85
- headers: {
86
- type: DatasourceFieldTypes.OBJECT,
87
- },
88
- requestBody: {
89
- type: DatasourceFieldTypes.JSON,
90
- },
91
- },
81
+ fields: coreFields,
92
82
  },
93
83
  patch: {
94
84
  displayName: "PATCH",
95
85
  readable: true,
96
86
  type: QueryTypes.FIELDS,
97
- urlDisplay: true,
98
- fields: {
99
- path: {
100
- type: DatasourceFieldTypes.STRING,
101
- },
102
- queryString: {
103
- type: DatasourceFieldTypes.STRING,
104
- },
105
- headers: {
106
- type: DatasourceFieldTypes.OBJECT,
107
- },
108
- requestBody: {
109
- type: DatasourceFieldTypes.JSON,
110
- },
111
- },
87
+ fields: coreFields,
112
88
  },
113
89
  delete: {
114
90
  displayName: "DELETE",
115
91
  type: QueryTypes.FIELDS,
116
- urlDisplay: true,
117
- fields: {
118
- path: {
119
- type: DatasourceFieldTypes.STRING,
120
- },
121
- queryString: {
122
- type: DatasourceFieldTypes.STRING,
123
- },
124
- headers: {
125
- type: DatasourceFieldTypes.OBJECT,
126
- },
127
- requestBody: {
128
- type: DatasourceFieldTypes.JSON,
129
- },
130
- },
92
+ fields: coreFields,
131
93
  },
132
94
  },
133
95
  }
@@ -137,94 +99,106 @@ module RestModule {
137
99
  private headers: {
138
100
  [key: string]: string
139
101
  } = {}
102
+ private startTimeMs: number = performance.now()
140
103
 
141
104
  constructor(config: RestConfig) {
142
105
  this.config = config
143
106
  }
144
107
 
145
108
  async parseResponse(response: any) {
109
+ let data, raw, headers
146
110
  const contentType = response.headers.get("content-type")
147
111
  if (contentType && contentType.indexOf("application/json") !== -1) {
148
- return await response.json()
112
+ data = await response.json()
113
+ raw = JSON.stringify(data)
149
114
  } else {
150
- return await response.text()
115
+ data = await response.text()
116
+ raw = data
117
+ }
118
+ const size = formatBytes(response.headers.get("content-length") || Buffer.byteLength(raw, "utf8"))
119
+ const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
120
+ headers = response.headers.raw()
121
+ for (let [key, value] of Object.entries(headers)) {
122
+ headers[key] = Array.isArray(value) ? value[0] : value
123
+ }
124
+ return {
125
+ data,
126
+ info: {
127
+ code: response.status,
128
+ size,
129
+ time,
130
+ },
131
+ extra: {
132
+ raw,
133
+ headers,
134
+ },
151
135
  }
152
136
  }
153
137
 
154
138
  getUrl(path: string, queryString: string): string {
155
- return `${this.config.url}/${path}?${queryString}`
156
- }
157
-
158
- async create({ path = "", queryString = "", headers = {}, json = {} }) {
159
- this.headers = {
160
- ...this.config.defaultHeaders,
161
- ...headers,
139
+ const main = `${path}?${queryString}`
140
+ let complete = main
141
+ if (this.config.url && !main.startsWith(this.config.url)) {
142
+ complete = !this.config.url ? main : `${this.config.url}/${main}`
162
143
  }
163
-
164
- const response = await fetch(this.getUrl(path, queryString), {
165
- method: "POST",
166
- headers: this.headers,
167
- body: JSON.stringify(json),
168
- })
169
-
170
- return await this.parseResponse(response)
144
+ if (!complete.startsWith("http")) {
145
+ complete = `http://${complete}`
146
+ }
147
+ return complete
171
148
  }
172
149
 
173
- async read({ path = "", queryString = "", headers = {} }) {
150
+ async _req(query: RestQuery) {
151
+ const { path = "", queryString = "", headers = {}, method = "GET", disabledHeaders, bodyType, requestBody } = query
174
152
  this.headers = {
175
153
  ...this.config.defaultHeaders,
176
154
  ...headers,
177
155
  }
178
156
 
179
- const response = await fetch(this.getUrl(path, queryString), {
180
- headers: this.headers,
181
- })
182
-
183
- return await this.parseResponse(response)
184
- }
157
+ if (disabledHeaders) {
158
+ for (let headerKey of Object.keys(this.headers)) {
159
+ if (disabledHeaders[headerKey]) {
160
+ delete this.headers[headerKey]
161
+ }
162
+ }
163
+ }
185
164
 
186
- async update({ path = "", queryString = "", headers = {}, json = {} }) {
187
- this.headers = {
188
- ...this.config.defaultHeaders,
189
- ...headers,
165
+ let json
166
+ if (bodyType === BodyTypes.JSON && requestBody) {
167
+ try {
168
+ json = JSON.parse(requestBody)
169
+ } catch (err) {
170
+ throw "Invalid JSON for request body"
171
+ }
190
172
  }
191
173
 
192
- const response = await fetch(this.getUrl(path, queryString), {
193
- method: "PUT",
194
- headers: this.headers,
195
- body: JSON.stringify(json),
196
- })
174
+ const input: any = { method, headers: this.headers }
175
+ if (json && typeof json === "object" && Object.keys(json).length > 0) {
176
+ input.body = JSON.stringify(json)
177
+ }
197
178
 
179
+ this.startTimeMs = performance.now()
180
+ const response = await fetch(this.getUrl(path, queryString), input)
198
181
  return await this.parseResponse(response)
199
182
  }
200
183
 
201
- async patch({ path = "", queryString = "", headers = {}, json = {} }) {
202
- this.headers = {
203
- ...this.config.defaultHeaders,
204
- ...headers,
205
- }
206
-
207
- const response = await fetch(this.getUrl(path, queryString), {
208
- method: "PATCH",
209
- headers: this.headers,
210
- body: JSON.stringify(json),
211
- })
184
+ async create(opts: RestQuery) {
185
+ return this._req({ ...opts, method: "POST" })
186
+ }
212
187
 
213
- return await this.parseResponse(response)
188
+ async read(opts: RestQuery) {
189
+ return this._req({ ...opts, method: "GET" })
214
190
  }
215
191
 
216
- async delete({ path = "", queryString = "", headers = {} }) {
217
- this.headers = {
218
- ...this.config.defaultHeaders,
219
- ...headers,
220
- }
192
+ async update(opts: RestQuery) {
193
+ return this._req({ ...opts, method: "PUT" })
194
+ }
221
195
 
222
- const response = await fetch(this.getUrl(path, queryString), {
223
- method: "DELETE",
224
- headers: this.headers,
225
- })
196
+ async patch(opts: RestQuery) {
197
+ return this._req({ ...opts, method: "PATCH" })
198
+ }
226
199
 
227
- return await this.parseResponse(response)
200
+ async delete(opts: RestQuery) {
201
+ return this._req({ ...opts, method: "DELETE" })
228
202
  }
229
203
  }
230
204
 
@@ -1,6 +1,9 @@
1
1
  jest.mock("node-fetch", () =>
2
2
  jest.fn(() => ({
3
3
  headers: {
4
+ raw: () => {
5
+ return { "content-type": ["application/json"] }
6
+ },
4
7
  get: () => ["application/json"]
5
8
  },
6
9
  json: jest.fn(),
@@ -24,6 +27,7 @@ describe("REST Integration", () => {
24
27
  config = new TestConfiguration({
25
28
  url: BASE_URL,
26
29
  })
30
+ jest.clearAllMocks()
27
31
  })
28
32
 
29
33
  it("calls the create method with the correct params", async () => {
@@ -33,9 +37,10 @@ describe("REST Integration", () => {
33
37
  headers: {
34
38
  Accept: "application/json",
35
39
  },
36
- json: {
40
+ bodyType: "json",
41
+ requestBody: JSON.stringify({
37
42
  name: "test",
38
- },
43
+ }),
39
44
  }
40
45
  const response = await config.integration.create(query)
41
46
  expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
@@ -60,6 +65,7 @@ describe("REST Integration", () => {
60
65
  headers: {
61
66
  Accept: "text/html",
62
67
  },
68
+ method: "GET",
63
69
  })
64
70
  })
65
71
 
@@ -70,13 +76,14 @@ describe("REST Integration", () => {
70
76
  headers: {
71
77
  Accept: "application/json",
72
78
  },
73
- json: {
79
+ bodyType: "json",
80
+ requestBody: JSON.stringify({
74
81
  name: "test",
75
- },
82
+ }),
76
83
  }
77
84
  const response = await config.integration.update(query)
78
85
  expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
79
- method: "POST",
86
+ method: "PUT",
80
87
  body: '{"name":"test"}',
81
88
  headers: {
82
89
  Accept: "application/json",
@@ -91,9 +98,10 @@ describe("REST Integration", () => {
91
98
  headers: {
92
99
  Accept: "application/json",
93
100
  },
94
- json: {
101
+ bodyType: "json",
102
+ requestBody: JSON.stringify({
95
103
  name: "test",
96
- },
104
+ }),
97
105
  }
98
106
  const response = await config.integration.delete(query)
99
107
  expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/api?test=1`, {
@@ -101,6 +109,7 @@ describe("REST Integration", () => {
101
109
  headers: {
102
110
  Accept: "application/json",
103
111
  },
112
+ body: '{"name":"test"}',
104
113
  })
105
114
  })
106
115
  })
@@ -15,6 +15,15 @@ function formatResponse(resp) {
15
15
  return resp
16
16
  }
17
17
 
18
+ function hasExtraData(response) {
19
+ return (
20
+ typeof response === "object" &&
21
+ !Array.isArray(response) &&
22
+ response.data != null &&
23
+ response.info != null
24
+ )
25
+ }
26
+
18
27
  async function runAndTransform(datasource, queryVerb, query, transformer) {
19
28
  const Integration = integrations[datasource.source]
20
29
  if (!Integration) {
@@ -22,7 +31,15 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
22
31
  }
23
32
  const integration = new Integration(datasource.config)
24
33
 
25
- let rows = formatResponse(await integration[queryVerb](query))
34
+ let output = formatResponse(await integration[queryVerb](query))
35
+ let rows = output,
36
+ info = undefined,
37
+ extra = undefined
38
+ if (hasExtraData(output)) {
39
+ rows = output.data
40
+ info = output.info
41
+ extra = output.extra
42
+ }
26
43
 
27
44
  // transform as required
28
45
  if (transformer) {
@@ -47,7 +64,7 @@ async function runAndTransform(datasource, queryVerb, query, transformer) {
47
64
  integration.end()
48
65
  }
49
66
 
50
- return { rows, keys }
67
+ return { rows, keys, info, extra }
51
68
  }
52
69
 
53
70
  module.exports = (input, callback) => {
@@ -150,3 +150,14 @@ exports.doesDatabaseExist = async dbName => {
150
150
  return false
151
151
  }
152
152
  }
153
+
154
+ exports.formatBytes = bytes => {
155
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
156
+ const byteIncrements = 1024
157
+ let unit = 0
158
+ let size = parseInt(bytes, 10) || 0
159
+ while (size >= byteIncrements && ++unit) {
160
+ size /= byteIncrements
161
+ }
162
+ return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`
163
+ }