@budibase/server 1.0.19-alpha.0 → 1.0.19-alpha.1

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 (194) 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.9337c392.css → index.2fc6da87.css} +1 -1
  4. package/builder/assets/{index.f0651cb7.js → index.b0718f41.js} +190 -186
  5. package/builder/index.html +2 -2
  6. package/coverage/clover.xml +313 -275
  7. package/coverage/coverage-final.json +13 -13
  8. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/application.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/index.html +18 -18
  20. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  23. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/query/index.html +11 -11
  25. package/coverage/lcov-report/api/controllers/query/index.js.html +15 -9
  26. package/coverage/lcov-report/api/controllers/query/validation.js.html +5 -2
  27. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  39. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/user.js.html +108 -9
  44. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  46. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  49. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  50. package/coverage/lcov-report/api/index.html +1 -1
  51. package/coverage/lcov-report/api/index.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/index.html +1 -1
  65. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/user.js.html +32 -2
  80. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  82. package/coverage/lcov-report/automations/actions.js.html +1 -1
  83. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  84. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  85. package/coverage/lcov-report/automations/index.html +1 -1
  86. package/coverage/lcov-report/automations/index.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/index.html +1 -1
  96. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  104. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  113. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  114. package/coverage/lcov-report/automations/utils.js.html +1 -1
  115. package/coverage/lcov-report/constants/index.html +1 -1
  116. package/coverage/lcov-report/constants/index.js.html +22 -22
  117. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  118. package/coverage/lcov-report/constants/screens.js.html +1 -1
  119. package/coverage/lcov-report/db/client.js.html +18 -18
  120. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  121. package/coverage/lcov-report/db/index.html +15 -15
  122. package/coverage/lcov-report/db/index.js.html +3 -3
  123. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  124. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  126. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  127. package/coverage/lcov-report/db/newid.js.html +3 -3
  128. package/coverage/lcov-report/db/utils.js.html +90 -63
  129. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  130. package/coverage/lcov-report/events/index.html +1 -1
  131. package/coverage/lcov-report/events/index.js.html +1 -1
  132. package/coverage/lcov-report/events/utils.js.html +1 -1
  133. package/coverage/lcov-report/index.html +51 -51
  134. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  135. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  136. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  137. package/coverage/lcov-report/middleware/authorized.js.html +2 -2
  138. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  139. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  140. package/coverage/lcov-report/middleware/index.html +1 -1
  141. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  142. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  143. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  144. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  145. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  146. package/coverage/lcov-report/threads/automation.js.html +1 -1
  147. package/coverage/lcov-report/threads/index.html +20 -20
  148. package/coverage/lcov-report/threads/index.js.html +1 -1
  149. package/coverage/lcov-report/threads/query.js.html +63 -12
  150. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  151. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  152. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  153. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  154. package/coverage/lcov-report/utilities/global.js.html +1 -1
  155. package/coverage/lcov-report/utilities/index.html +19 -19
  156. package/coverage/lcov-report/utilities/index.js.html +66 -33
  157. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  158. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  159. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  160. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  161. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  162. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  164. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  165. package/coverage/lcov-report/utilities/security.js.html +2 -2
  166. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  167. package/coverage/lcov-report/utilities/users.js.html +1 -1
  168. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  169. package/coverage/lcov.info +490 -424
  170. package/dist/api/controllers/query/index.js +4 -2
  171. package/dist/api/controllers/query/validation.js +1 -0
  172. package/dist/api/controllers/user.js +37 -1
  173. package/dist/api/routes/user.js +3 -1
  174. package/dist/db/utils.js +8 -0
  175. package/dist/integrations/rest.js +110 -113
  176. package/dist/package.json +4 -4
  177. package/dist/threads/query.js +14 -2
  178. package/dist/tsconfig.tsbuildinfo +1 -1
  179. package/dist/utilities/index.js +10 -0
  180. package/package.json +5 -5
  181. package/src/api/controllers/query/import/sources/base/index.ts +1 -2
  182. package/src/api/controllers/query/import/sources/openapi2.ts +1 -1
  183. package/src/api/controllers/query/index.js +4 -2
  184. package/src/api/controllers/query/validation.js +1 -0
  185. package/src/api/controllers/user.js +33 -0
  186. package/src/api/routes/user.js +10 -0
  187. package/src/db/utils.js +9 -0
  188. package/src/definitions/common.ts +2 -38
  189. package/src/definitions/datasource.ts +50 -1
  190. package/src/integrations/base/IntegrationBase.ts +4 -4
  191. package/src/integrations/rest.ts +111 -137
  192. package/src/integrations/tests/rest.spec.js +16 -7
  193. package/src/threads/query.js +19 -2
  194. package/src/utilities/index.js +11 -0
@@ -142,3 +142,13 @@ exports.doesDatabaseExist = (dbName) => __awaiter(void 0, void 0, void 0, functi
142
142
  return false;
143
143
  }
144
144
  });
145
+ exports.formatBytes = bytes => {
146
+ const units = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
147
+ const byteIncrements = 1024;
148
+ let unit = 0;
149
+ let size = parseInt(bytes, 10) || 0;
150
+ while (size >= byteIncrements && ++unit) {
151
+ size /= byteIncrements;
152
+ }
153
+ return `${size.toFixed(size < 10 && unit > 0 ? 1 : 0)}${units[unit]}`;
154
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.0.19-alpha.0",
4
+ "version": "1.0.19-alpha.1",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -70,9 +70,9 @@
70
70
  "license": "GPL-3.0",
71
71
  "dependencies": {
72
72
  "@apidevtools/swagger-parser": "^10.0.3",
73
- "@budibase/auth": "^1.0.19-alpha.0",
74
- "@budibase/client": "^1.0.19-alpha.0",
75
- "@budibase/string-templates": "^1.0.19-alpha.0",
73
+ "@budibase/auth": "^1.0.19-alpha.1",
74
+ "@budibase/client": "^1.0.19-alpha.1",
75
+ "@budibase/string-templates": "^1.0.19-alpha.1",
76
76
  "@bull-board/api": "^3.7.0",
77
77
  "@bull-board/koa": "^3.7.0",
78
78
  "@elastic/elasticsearch": "7.10.0",
@@ -162,5 +162,5 @@
162
162
  "optionalDependencies": {
163
163
  "oracledb": "^5.3.0"
164
164
  },
165
- "gitHead": "78991939242ca4b1ac5209f2ddf5225f09d080fb"
165
+ "gitHead": "5623634c9caf89d0694e57e726b654fbf7ccb69a"
166
166
  }
@@ -1,5 +1,4 @@
1
-
2
- import { Query, QueryParameter } from "../../../../../../definitions/common"
1
+ import { Query, QueryParameter } from "../../../../../../definitions/datasource"
3
2
 
4
3
  export interface ImportInfo {
5
4
  url: string
@@ -1,5 +1,5 @@
1
1
  import { ImportInfo } from "./base"
2
- import { Query, QueryParameter } from "../../../../../definitions/common"
2
+ import { Query, QueryParameter } from "../../../../../definitions/datasource"
3
3
  import { OpenAPIV2 } from "openapi-types"
4
4
  import { OpenAPISource } from "./base/openapi"
5
5
 
@@ -123,7 +123,7 @@ async function enrichQueryFields(fields, parameters = {}) {
123
123
  enrichedQuery.requestBody
124
124
  )
125
125
  } catch (err) {
126
- throw { message: `JSON Invalid - error: ${err}` }
126
+ // no json found, ignore
127
127
  }
128
128
  delete enrichedQuery.customData
129
129
  }
@@ -151,7 +151,7 @@ exports.preview = async function (ctx) {
151
151
  const enrichedQuery = await enrichQueryFields(fields, parameters)
152
152
 
153
153
  try {
154
- const { rows, keys } = await Runner.run({
154
+ const { rows, keys, info, extra } = await Runner.run({
155
155
  datasource,
156
156
  queryVerb,
157
157
  query: enrichedQuery,
@@ -161,6 +161,8 @@ exports.preview = async function (ctx) {
161
161
  ctx.body = {
162
162
  rows,
163
163
  schemaFields: [...new Set(keys)],
164
+ info,
165
+ extra,
164
166
  }
165
167
  } catch (err) {
166
168
  ctx.throw(400, err)
@@ -19,6 +19,7 @@ exports.queryValidation = () => {
19
19
  extra: Joi.object().optional(),
20
20
  schema: Joi.object({}).required().unknown(true),
21
21
  transformer: Joi.string().optional(),
22
+ flags: Joi.object().optional(),
22
23
  })
23
24
  }
24
25
 
@@ -2,6 +2,7 @@ const CouchDB = require("../../db")
2
2
  const {
3
3
  generateUserMetadataID,
4
4
  getUserMetadataParams,
5
+ generateUserFlagID,
5
6
  } = require("../../db/utils")
6
7
  const { InternalTables } = require("../../db/utils")
7
8
  const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
@@ -195,3 +196,35 @@ exports.destroyMetadata = async function (ctx) {
195
196
  exports.findMetadata = async function (ctx) {
196
197
  ctx.body = await getFullUser(ctx, ctx.params.id)
197
198
  }
199
+
200
+ exports.setFlag = async function (ctx) {
201
+ const userId = ctx.user._id
202
+ const { flag, value } = ctx.request.body
203
+ if (!flag) {
204
+ ctx.throw(400, "Must supply a 'flag' field in request body.")
205
+ }
206
+ const flagDocId = generateUserFlagID(userId)
207
+ const db = new CouchDB(ctx.appId)
208
+ let doc
209
+ try {
210
+ doc = await db.get(flagDocId)
211
+ } catch (err) {
212
+ doc = { _id: flagDocId }
213
+ }
214
+ doc[flag] = value || true
215
+ await db.put(doc)
216
+ ctx.body = { message: "Flag set successfully" }
217
+ }
218
+
219
+ exports.getFlags = async function (ctx) {
220
+ const userId = ctx.user._id
221
+ const docId = generateUserFlagID(userId)
222
+ const db = new CouchDB(ctx.appId)
223
+ let doc
224
+ try {
225
+ doc = await db.get(docId)
226
+ } catch (err) {
227
+ doc = { _id: docId }
228
+ }
229
+ ctx.body = doc
230
+ }
@@ -39,5 +39,15 @@ router
39
39
  authorized(PermissionTypes.USER, PermissionLevels.WRITE),
40
40
  controller.syncUser
41
41
  )
42
+ .post(
43
+ "/api/users/flags",
44
+ authorized(PermissionTypes.USER, PermissionLevels.WRITE),
45
+ controller.setFlag
46
+ )
47
+ .get(
48
+ "/api/users/flags",
49
+ authorized(PermissionTypes.USER, PermissionLevels.READ),
50
+ controller.getFlags
51
+ )
42
52
 
43
53
  module.exports = router
package/src/db/utils.js CHANGED
@@ -40,6 +40,7 @@ const DocumentTypes = {
40
40
  DEPLOYMENTS: "deployments",
41
41
  METADATA: "metadata",
42
42
  MEM_VIEW: "view",
43
+ USER_FLAG: "flag",
43
44
  }
44
45
 
45
46
  const ViewNames = {
@@ -339,6 +340,14 @@ exports.getQueryParams = (datasourceId = null, otherProps = {}) => {
339
340
  )
340
341
  }
341
342
 
343
+ /**
344
+ * Generates a new flag document ID.
345
+ * @returns {string} The ID of the flag document that was generated.
346
+ */
347
+ exports.generateUserFlagID = userId => {
348
+ return `${DocumentTypes.USER_FLAG}${SEPARATOR}${userId}`
349
+ }
350
+
342
351
  exports.generateMetadataID = (type, entityId) => {
343
352
  return `${DocumentTypes.METADATA}${SEPARATOR}${type}${SEPARATOR}${entityId}`
344
353
  }
@@ -1,6 +1,6 @@
1
- import { SourceNames } from "./datasource"
1
+ export { Query, Datasource } from "./datasource"
2
2
 
3
- interface Base {
3
+ export interface Base {
4
4
  _id?: string
5
5
  _rev?: string
6
6
  }
@@ -93,39 +93,3 @@ export interface Automation extends Base {
93
93
  trigger?: AutomationStep
94
94
  }
95
95
  }
96
-
97
- export interface Datasource extends Base {
98
- type: string
99
- name: string
100
- source: SourceNames
101
- // the config is defined by the schema
102
- config: {
103
- [key: string]: string | number | boolean
104
- }
105
- plus: boolean
106
- entities?: {
107
- [key: string]: Table
108
- }
109
- }
110
-
111
- export interface QueryParameter {
112
- name: string
113
- default: string
114
- }
115
-
116
- export interface Query {
117
- _id?: string
118
- datasourceId: string
119
- name: string
120
- parameters: QueryParameter[]
121
- fields: {
122
- headers: object
123
- queryString: string | null
124
- path: string
125
- requestBody: string | undefined
126
- }
127
- transformer: string | null
128
- schema: any
129
- readable: boolean
130
- queryVerb: string
131
- }
@@ -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
  }
@@ -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