@budibase/server 1.0.27-alpha.0 → 1.0.27-alpha.4

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 (199) hide show
  1. package/__mocks__/node-fetch.ts +18 -0
  2. package/builder/assets/{index.4a13c4cb.css → index.431d69df.css} +1 -1
  3. package/builder/assets/index.d849c3ee.js +1348 -0
  4. package/builder/index.html +2 -2
  5. package/coverage/clover.xml +576 -476
  6. package/coverage/coverage-final.json +26 -26
  7. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/application.js.html +54 -54
  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 +4 -4
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +49 -49
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/index.html +20 -20
  19. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/metadata.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 +19 -19
  24. package/coverage/lcov-report/api/controllers/query/index.js.html +66 -150
  25. package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -3
  26. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/index.html +16 -16
  30. package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +7 -4
  33. package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -20
  34. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/script.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/table/internal.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  46. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  48. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  49. package/coverage/lcov-report/api/index.html +1 -1
  50. package/coverage/lcov-report/api/index.js.html +5 -5
  51. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/index.html +1 -1
  64. package/coverage/lcov-report/api/routes/index.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/query.js.html +24 -3
  70. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/static.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  81. package/coverage/lcov-report/automations/actions.js.html +1 -1
  82. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  83. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  84. package/coverage/lcov-report/automations/index.html +1 -1
  85. package/coverage/lcov-report/automations/index.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  87. package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/executeQuery.js.html +31 -7
  92. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/index.html +11 -11
  95. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  98. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  99. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  100. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  101. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  102. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  103. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  108. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  110. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  111. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  112. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  113. package/coverage/lcov-report/automations/utils.js.html +5 -5
  114. package/coverage/lcov-report/constants/index.html +1 -1
  115. package/coverage/lcov-report/constants/index.js.html +1 -1
  116. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  117. package/coverage/lcov-report/constants/screens.js.html +1 -1
  118. package/coverage/lcov-report/db/client.js.html +1 -1
  119. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  120. package/coverage/lcov-report/db/index.html +1 -1
  121. package/coverage/lcov-report/db/index.js.html +1 -1
  122. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  123. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  124. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  125. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  126. package/coverage/lcov-report/db/newid.js.html +2 -2
  127. package/coverage/lcov-report/db/utils.js.html +18 -18
  128. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  129. package/coverage/lcov-report/events/index.html +1 -1
  130. package/coverage/lcov-report/events/index.js.html +1 -1
  131. package/coverage/lcov-report/events/utils.js.html +1 -1
  132. package/coverage/lcov-report/index.html +63 -63
  133. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  134. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  135. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  136. package/coverage/lcov-report/middleware/authorized.js.html +10 -10
  137. package/coverage/lcov-report/middleware/builder.js.html +8 -8
  138. package/coverage/lcov-report/middleware/currentapp.js.html +28 -28
  139. package/coverage/lcov-report/middleware/index.html +1 -1
  140. package/coverage/lcov-report/middleware/joi-validator.js.html +9 -9
  141. package/coverage/lcov-report/middleware/resourceId.js.html +17 -17
  142. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  143. package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
  144. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  145. package/coverage/lcov-report/threads/automation.js.html +1 -1
  146. package/coverage/lcov-report/threads/index.html +30 -30
  147. package/coverage/lcov-report/threads/index.js.html +11 -11
  148. package/coverage/lcov-report/threads/query.js.html +358 -91
  149. package/coverage/lcov-report/threads/utils.js.html +352 -10
  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 +13 -13
  155. package/coverage/lcov-report/utilities/index.html +1 -1
  156. package/coverage/lcov-report/utilities/index.js.html +9 -9
  157. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  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 +19 -19
  162. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +46 -10
  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 +1 -1
  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 +1001 -826
  170. package/dist/api/controllers/query/import/sources/curl.js +5 -1
  171. package/dist/api/controllers/query/index.js +29 -47
  172. package/dist/api/controllers/query/validation.js +2 -1
  173. package/dist/api/controllers/row/internalSearch.js +2 -1
  174. package/dist/api/controllers/row/utils.js +13 -6
  175. package/dist/api/routes/query.js +3 -1
  176. package/dist/automations/steps/executeQuery.js +8 -1
  177. package/dist/integrations/rest.js +2 -2
  178. package/dist/package.json +5 -4
  179. package/dist/tests/utilities/TestConfiguration.js +7 -0
  180. package/dist/threads/query.js +145 -52
  181. package/dist/threads/utils.js +104 -0
  182. package/dist/tsconfig.tsbuildinfo +1 -1
  183. package/dist/utilities/rowProcessor/index.js +13 -0
  184. package/package.json +6 -5
  185. package/src/api/controllers/query/import/sources/curl.ts +5 -1
  186. package/src/api/controllers/query/index.js +27 -55
  187. package/src/api/controllers/query/validation.js +2 -1
  188. package/src/api/controllers/row/internalSearch.js +2 -1
  189. package/src/api/controllers/row/utils.js +11 -8
  190. package/src/api/routes/query.js +8 -1
  191. package/src/api/routes/tests/query.spec.js +88 -0
  192. package/src/automations/steps/executeQuery.js +9 -1
  193. package/src/definitions/datasource.ts +10 -0
  194. package/src/integrations/rest.ts +5 -2
  195. package/src/tests/utilities/TestConfiguration.js +10 -0
  196. package/src/threads/query.js +145 -56
  197. package/src/threads/utils.js +114 -0
  198. package/src/utilities/rowProcessor/index.js +12 -0
  199. package/builder/assets/index.e2f56628.js +0 -1320
@@ -1,77 +1,166 @@
1
- require("./utils").threadSetup()
1
+ const threadUtils = require("./utils")
2
+ threadUtils.threadSetup()
2
3
  const ScriptRunner = require("../utilities/scriptRunner")
3
4
  const { integrations } = require("../integrations")
5
+ const { processStringSync } = require("@budibase/string-templates")
6
+ const CouchDB = require("../db")
4
7
 
5
- function formatResponse(resp) {
6
- if (typeof resp === "string") {
7
- try {
8
- resp = JSON.parse(resp)
9
- } catch (err) {
10
- resp = { response: resp }
11
- }
8
+ class QueryRunner {
9
+ constructor(input, flags = { noRecursiveQuery: false }) {
10
+ this.appId = input.appId
11
+ this.datasource = input.datasource
12
+ this.queryVerb = input.queryVerb
13
+ this.fields = input.fields
14
+ this.parameters = input.parameters
15
+ this.transformer = input.transformer
16
+ this.queryId = input.queryId
17
+ this.noRecursiveQuery = flags.noRecursiveQuery
18
+ this.cachedVariables = []
19
+ // allows the response from a query to be stored throughout this
20
+ // execution so that if it needs to be re-used for another variable
21
+ // it can be
22
+ this.queryResponse = {}
23
+ this.hasRerun = false
12
24
  }
13
- return resp
14
- }
15
25
 
16
- function hasExtraData(response) {
17
- return (
18
- typeof response === "object" &&
19
- !Array.isArray(response) &&
20
- response.data != null &&
21
- response.info != null
22
- )
23
- }
26
+ async execute() {
27
+ let { datasource, fields, queryVerb, transformer } = this
28
+ // pre-query, make sure datasource variables are added to parameters
29
+ const parameters = await this.addDatasourceVariables()
30
+ const query = threadUtils.enrichQueryFields(fields, parameters)
31
+ const Integration = integrations[datasource.source]
32
+ if (!Integration) {
33
+ throw "Integration type does not exist."
34
+ }
35
+ const integration = new Integration(datasource.config)
24
36
 
25
- async function runAndTransform(datasource, queryVerb, query, transformer) {
26
- const Integration = integrations[datasource.source]
27
- if (!Integration) {
28
- throw "Integration type does not exist."
29
- }
30
- const integration = new Integration(datasource.config)
37
+ let output = threadUtils.formatResponse(await integration[queryVerb](query))
38
+ let rows = output,
39
+ info = undefined,
40
+ extra = undefined
41
+ if (threadUtils.hasExtraData(output)) {
42
+ rows = output.data
43
+ info = output.info
44
+ extra = output.extra
45
+ }
31
46
 
32
- let output = formatResponse(await integration[queryVerb](query))
33
- let rows = output,
34
- info = undefined,
35
- extra = undefined
36
- if (hasExtraData(output)) {
37
- rows = output.data
38
- info = output.info
39
- extra = output.extra
40
- }
47
+ // transform as required
48
+ if (transformer) {
49
+ const runner = new ScriptRunner(transformer, { data: rows })
50
+ rows = runner.execute()
51
+ }
41
52
 
42
- // transform as required
43
- if (transformer) {
44
- const runner = new ScriptRunner(transformer, { data: rows })
45
- rows = runner.execute()
46
- }
53
+ // if the request fails we retry once, invalidating the cached value
54
+ if (
55
+ info &&
56
+ info.code >= 400 &&
57
+ this.cachedVariables.length > 0 &&
58
+ !this.hasRerun
59
+ ) {
60
+ this.hasRerun = true
61
+ // invalidate the cache value
62
+ await threadUtils.invalidateDynamicVariables(this.cachedVariables)
63
+ return this.execute()
64
+ }
47
65
 
48
- // needs to an array for next step
49
- if (!Array.isArray(rows)) {
50
- rows = [rows]
51
- }
66
+ // needs to an array for next step
67
+ if (!Array.isArray(rows)) {
68
+ rows = [rows]
69
+ }
52
70
 
53
- // map into JSON if just raw primitive here
54
- if (rows.find(row => typeof row !== "object")) {
55
- rows = rows.map(value => ({ value }))
71
+ // map into JSON if just raw primitive here
72
+ if (rows.find(row => typeof row !== "object")) {
73
+ rows = rows.map(value => ({ value }))
74
+ }
75
+
76
+ // get all the potential fields in the schema
77
+ let keys = rows.flatMap(Object.keys)
78
+
79
+ if (integration.end) {
80
+ integration.end()
81
+ }
82
+
83
+ return { rows, keys, info, extra }
56
84
  }
57
85
 
58
- // get all the potential fields in the schema
59
- let keys = rows.flatMap(Object.keys)
86
+ async runAnotherQuery(queryId, parameters) {
87
+ const db = new CouchDB(this.appId)
88
+ const query = await db.get(queryId)
89
+ const datasource = await db.get(query.datasourceId)
90
+ return new QueryRunner(
91
+ {
92
+ appId: this.appId,
93
+ datasource,
94
+ queryVerb: query.queryVerb,
95
+ fields: query.fields,
96
+ parameters,
97
+ transformer: query.transformer,
98
+ },
99
+ { noRecursiveQuery: true }
100
+ ).execute()
101
+ }
60
102
 
61
- if (integration.end) {
62
- integration.end()
103
+ async getDynamicVariable(variable) {
104
+ let { parameters } = this
105
+ const queryId = variable.queryId,
106
+ name = variable.name
107
+ let value = await threadUtils.checkCacheForDynamicVariable(queryId, name)
108
+ if (!value) {
109
+ value = this.queryResponse[queryId]
110
+ ? this.queryResponse[queryId]
111
+ : await this.runAnotherQuery(queryId, parameters)
112
+ // store incase this query is to be called again
113
+ this.queryResponse[queryId] = value
114
+ await threadUtils.storeDynamicVariable(queryId, name, value)
115
+ } else {
116
+ this.cachedVariables.push({ queryId, name })
117
+ }
118
+ return value
63
119
  }
64
120
 
65
- return { rows, keys, info, extra }
121
+ async addDatasourceVariables() {
122
+ let { datasource, parameters, fields } = this
123
+ if (!datasource || !datasource.config) {
124
+ return parameters
125
+ }
126
+ const staticVars = datasource.config.staticVariables || {}
127
+ const dynamicVars = datasource.config.dynamicVariables || []
128
+ for (let [key, value] of Object.entries(staticVars)) {
129
+ if (!parameters[key]) {
130
+ parameters[key] = value
131
+ }
132
+ }
133
+ if (!this.noRecursiveQuery) {
134
+ // need to see if this uses any variables
135
+ const stringFields = JSON.stringify(fields)
136
+ const foundVars = dynamicVars.filter(variable => {
137
+ // don't allow a query to use its own dynamic variable (loop)
138
+ if (variable.queryId === this.queryId) {
139
+ return false
140
+ }
141
+ // look for {{ variable }} but allow spaces between handlebars
142
+ const regex = new RegExp(`{{[ ]*${variable.name}[ ]*}}`)
143
+ return regex.test(stringFields)
144
+ })
145
+ const dynamics = foundVars.map(dynVar => this.getDynamicVariable(dynVar))
146
+ const responses = await Promise.all(dynamics)
147
+ for (let i = 0; i < foundVars.length; i++) {
148
+ const variable = foundVars[i]
149
+ parameters[variable.name] = processStringSync(variable.value, {
150
+ data: responses[i].rows,
151
+ info: responses[i].extra,
152
+ })
153
+ // make sure its known that this uses dynamic variables in case it fails
154
+ this.hasDynamicVariables = true
155
+ }
156
+ }
157
+ return parameters
158
+ }
66
159
  }
67
160
 
68
161
  module.exports = (input, callback) => {
69
- runAndTransform(
70
- input.datasource,
71
- input.queryVerb,
72
- input.query,
73
- input.transformer
74
- )
162
+ const Runner = new QueryRunner(input)
163
+ Runner.execute()
75
164
  .then(response => {
76
165
  callback(null, response)
77
166
  })
@@ -1,6 +1,26 @@
1
1
  const env = require("../environment")
2
2
  const CouchDB = require("../db")
3
3
  const { init } = require("@budibase/auth")
4
+ const redis = require("@budibase/auth/redis")
5
+ const { SEPARATOR } = require("@budibase/auth/db")
6
+ const { processStringSync } = require("@budibase/string-templates")
7
+
8
+ const VARIABLE_TTL_SECONDS = 3600
9
+ let client
10
+
11
+ const IS_TRIPLE_BRACE = new RegExp(/^{{3}.*}{3}$/)
12
+ const IS_HANDLEBARS = new RegExp(/^{{2}.*}{2}$/)
13
+
14
+ async function getClient() {
15
+ if (!client) {
16
+ client = await new redis.Client(redis.utils.Databases.QUERY_VARS).init()
17
+ }
18
+ return client
19
+ }
20
+
21
+ process.on("exit", async () => {
22
+ if (client) await client.finish()
23
+ })
4
24
 
5
25
  exports.threadSetup = () => {
6
26
  // don't run this if not threading
@@ -11,3 +31,97 @@ exports.threadSetup = () => {
11
31
  env.setInThread()
12
32
  init(CouchDB)
13
33
  }
34
+
35
+ function makeVariableKey(queryId, variable) {
36
+ return `${queryId}${SEPARATOR}${variable}`
37
+ }
38
+
39
+ exports.checkCacheForDynamicVariable = async (queryId, variable) => {
40
+ const cache = await getClient()
41
+ return cache.get(makeVariableKey(queryId, variable))
42
+ }
43
+
44
+ exports.invalidateDynamicVariables = async cachedVars => {
45
+ let promises = []
46
+ for (let variable of cachedVars) {
47
+ promises.push(
48
+ client.delete(makeVariableKey(variable.queryId, variable.name))
49
+ )
50
+ }
51
+ await Promise.all(promises)
52
+ }
53
+
54
+ exports.storeDynamicVariable = async (queryId, variable, value) => {
55
+ const cache = await getClient()
56
+ await cache.store(
57
+ makeVariableKey(queryId, variable),
58
+ value,
59
+ VARIABLE_TTL_SECONDS
60
+ )
61
+ }
62
+
63
+ exports.formatResponse = resp => {
64
+ if (typeof resp === "string") {
65
+ try {
66
+ resp = JSON.parse(resp)
67
+ } catch (err) {
68
+ resp = { response: resp }
69
+ }
70
+ }
71
+ return resp
72
+ }
73
+
74
+ exports.hasExtraData = response => {
75
+ return (
76
+ typeof response === "object" &&
77
+ !Array.isArray(response) &&
78
+ response.data != null &&
79
+ response.info != null
80
+ )
81
+ }
82
+
83
+ exports.enrichQueryFields = (fields, parameters = {}) => {
84
+ const enrichedQuery = {}
85
+
86
+ // enrich the fields with dynamic parameters
87
+ for (let key of Object.keys(fields)) {
88
+ if (fields[key] == null) {
89
+ continue
90
+ }
91
+ if (typeof fields[key] === "object") {
92
+ // enrich nested fields object
93
+ enrichedQuery[key] = this.enrichQueryFields(fields[key], parameters)
94
+ } else if (typeof fields[key] === "string") {
95
+ // enrich string value as normal
96
+ let value = fields[key]
97
+ // add triple brace to avoid escaping e.g. '=' in cookie header
98
+ if (IS_HANDLEBARS.test(value) && !IS_TRIPLE_BRACE.test(value)) {
99
+ value = `{${value}}`
100
+ }
101
+ enrichedQuery[key] = processStringSync(value, parameters, {
102
+ noHelpers: true,
103
+ })
104
+ } else {
105
+ enrichedQuery[key] = fields[key]
106
+ }
107
+ }
108
+
109
+ if (
110
+ enrichedQuery.json ||
111
+ enrichedQuery.customData ||
112
+ enrichedQuery.requestBody
113
+ ) {
114
+ try {
115
+ enrichedQuery.json = JSON.parse(
116
+ enrichedQuery.json ||
117
+ enrichedQuery.customData ||
118
+ enrichedQuery.requestBody
119
+ )
120
+ } catch (err) {
121
+ // no json found, ignore
122
+ }
123
+ delete enrichedQuery.customData
124
+ }
125
+
126
+ return enrichedQuery
127
+ }
@@ -81,6 +81,18 @@ const TYPE_TRANSFORM_MAP = {
81
81
  [FieldTypes.AUTO]: {
82
82
  parse: () => undefined,
83
83
  },
84
+ [FieldTypes.JSON]: {
85
+ parse: input => {
86
+ try {
87
+ if (input === "") {
88
+ return undefined
89
+ }
90
+ return JSON.parse(input)
91
+ } catch (err) {
92
+ return input
93
+ }
94
+ },
95
+ },
84
96
  }
85
97
 
86
98
  /**