@budibase/server 1.0.27-alpha.3 → 1.0.27-alpha.7

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.2dc0d283.js → index.02c16fdb.js} +245 -240
  3. package/builder/assets/{index.5522fcd5.css → index.0dce895b.css} +1 -1
  4. package/builder/index.html +2 -2
  5. package/coverage/clover.xml +423 -319
  6. package/coverage/coverage-final.json +22 -22
  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 +1 -1
  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 +100 -121
  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 +1 -1
  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 +1 -1
  33. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  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 +46 -46
  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 +31 -31
  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 +356 -11
  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 +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 +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 +723 -545
  170. package/dist/api/controllers/query/import/sources/base/index.js +2 -1
  171. package/dist/api/controllers/query/import/sources/curl.js +11 -5
  172. package/dist/api/controllers/query/import/sources/openapi2.js +8 -5
  173. package/dist/api/controllers/query/index.js +45 -47
  174. package/dist/api/controllers/query/validation.js +2 -1
  175. package/dist/api/routes/query.js +3 -1
  176. package/dist/automations/steps/executeQuery.js +8 -1
  177. package/dist/integrations/rest.js +3 -3
  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 +105 -0
  182. package/dist/tsconfig.tsbuildinfo +1 -1
  183. package/package.json +6 -5
  184. package/src/api/controllers/query/import/sources/base/index.ts +3 -1
  185. package/src/api/controllers/query/import/sources/curl.ts +12 -4
  186. package/src/api/controllers/query/import/sources/openapi2.ts +9 -5
  187. package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +2 -3
  188. package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +6 -7
  189. package/src/api/controllers/query/import/tests/index.spec.js +0 -6
  190. package/src/api/controllers/query/index.js +48 -55
  191. package/src/api/controllers/query/validation.js +2 -1
  192. package/src/api/routes/query.js +8 -1
  193. package/src/api/routes/tests/query.spec.js +88 -0
  194. package/src/automations/steps/executeQuery.js +9 -1
  195. package/src/definitions/datasource.ts +10 -0
  196. package/src/integrations/rest.ts +6 -3
  197. package/src/tests/utilities/TestConfiguration.js +10 -0
  198. package/src/threads/query.js +145 -56
  199. package/src/threads/utils.js +115 -0
@@ -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,98 @@ 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
+ const cache = await getClient()
46
+ let promises = []
47
+ for (let variable of cachedVars) {
48
+ promises.push(
49
+ cache.delete(makeVariableKey(variable.queryId, variable.name))
50
+ )
51
+ }
52
+ await Promise.all(promises)
53
+ }
54
+
55
+ exports.storeDynamicVariable = async (queryId, variable, value) => {
56
+ const cache = await getClient()
57
+ await cache.store(
58
+ makeVariableKey(queryId, variable),
59
+ value,
60
+ VARIABLE_TTL_SECONDS
61
+ )
62
+ }
63
+
64
+ exports.formatResponse = resp => {
65
+ if (typeof resp === "string") {
66
+ try {
67
+ resp = JSON.parse(resp)
68
+ } catch (err) {
69
+ resp = { response: resp }
70
+ }
71
+ }
72
+ return resp
73
+ }
74
+
75
+ exports.hasExtraData = response => {
76
+ return (
77
+ typeof response === "object" &&
78
+ !Array.isArray(response) &&
79
+ response.data != null &&
80
+ response.info != null
81
+ )
82
+ }
83
+
84
+ exports.enrichQueryFields = (fields, parameters = {}) => {
85
+ const enrichedQuery = {}
86
+
87
+ // enrich the fields with dynamic parameters
88
+ for (let key of Object.keys(fields)) {
89
+ if (fields[key] == null) {
90
+ continue
91
+ }
92
+ if (typeof fields[key] === "object") {
93
+ // enrich nested fields object
94
+ enrichedQuery[key] = this.enrichQueryFields(fields[key], parameters)
95
+ } else if (typeof fields[key] === "string") {
96
+ // enrich string value as normal
97
+ let value = fields[key]
98
+ // add triple brace to avoid escaping e.g. '=' in cookie header
99
+ if (IS_HANDLEBARS.test(value) && !IS_TRIPLE_BRACE.test(value)) {
100
+ value = `{${value}}`
101
+ }
102
+ enrichedQuery[key] = processStringSync(value, parameters, {
103
+ noHelpers: true,
104
+ })
105
+ } else {
106
+ enrichedQuery[key] = fields[key]
107
+ }
108
+ }
109
+
110
+ if (
111
+ enrichedQuery.json ||
112
+ enrichedQuery.customData ||
113
+ enrichedQuery.requestBody
114
+ ) {
115
+ try {
116
+ enrichedQuery.json = JSON.parse(
117
+ enrichedQuery.json ||
118
+ enrichedQuery.customData ||
119
+ enrichedQuery.requestBody
120
+ )
121
+ } catch (err) {
122
+ // no json found, ignore
123
+ }
124
+ delete enrichedQuery.customData
125
+ }
126
+
127
+ return enrichedQuery
128
+ }