@usebruno/js 0.14.0 → 0.16.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usebruno/js",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "license": "MIT",
5
5
  "main": "src/index.js",
6
6
  "files": [
@@ -11,10 +11,11 @@
11
11
  "@usebruno/vm2": "^3.9.13"
12
12
  },
13
13
  "scripts": {
14
- "test": "jest --testPathIgnorePatterns test.js"
14
+ "test": "node --experimental-vm-modules $(npx which jest) --testPathIgnorePatterns test.js",
15
+ "sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js"
15
16
  },
16
17
  "dependencies": {
17
- "@usebruno/common": "0.2.0",
18
+ "@usebruno/common": "0.3.0",
18
19
  "@usebruno/query": "0.1.0",
19
20
  "ajv": "^8.12.0",
20
21
  "ajv-formats": "^2.1.1",
@@ -24,12 +25,29 @@
24
25
  "chai": "^4.3.7",
25
26
  "chai-string": "^1.5.0",
26
27
  "crypto-js": "^4.1.1",
28
+ "crypto-js-3.1.9-1": "npm:crypto-js@^3.1.9-1",
27
29
  "json-query": "^2.2.2",
28
30
  "lodash": "^4.17.21",
29
31
  "moment": "^2.29.4",
30
32
  "nanoid": "3.3.4",
31
- "node-fetch": "2.*",
33
+ "node-fetch": "^2.7.0",
32
34
  "node-vault": "^0.10.2",
35
+ "path": "^0.12.7",
36
+ "quickjs-emscripten": "^0.29.2",
33
37
  "uuid": "^9.0.0"
38
+ },
39
+ "devDependencies": {
40
+ "@rollup/plugin-commonjs": "^23.0.2",
41
+ "@rollup/plugin-json": "^6.1.0",
42
+ "@rollup/plugin-node-resolve": "^15.0.1",
43
+ "rollup": "3.2.5",
44
+ "rollup-plugin-node-builtins": "^2.1.2",
45
+ "rollup-plugin-node-globals": "^1.4.0",
46
+ "rollup-plugin-polyfill-node": "^0.13.0",
47
+ "rollup-plugin-terser": "^7.0.2",
48
+ "stream": "^0.0.2",
49
+ "terser": "^5.31.1",
50
+ "uglify-js": "^3.18.0",
51
+ "util": "^0.12.5"
34
52
  }
35
53
  }
package/src/bru.js CHANGED
@@ -5,24 +5,17 @@ const { interpolate } = require('@usebruno/common');
5
5
  const variableNameRegex = /^[\w-.]*$/;
6
6
 
7
7
  class Bru {
8
- constructor(
9
- envVariables,
10
- collectionVariables,
11
- processEnvVars,
12
- collectionPath,
13
- historyLogger,
14
- setHtmlVisualizationString,
15
- secretVariables,
16
- requestVariables
17
- ) {
8
+ constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables) {
18
9
  this.envVariables = envVariables || {};
19
- this.collectionVariables = collectionVariables || {};
10
+ this.runtimeVariables = runtimeVariables || {};
20
11
  this.processEnvVars = cloneDeep(processEnvVars || {});
21
12
  this.secretVariables = cloneDeep(secretVariables || {});
13
+ this.collectionVariables = collectionVariables || {};
14
+ this.folderVariables = folderVariables || {};
22
15
  this.requestVariables = requestVariables || {};
23
16
  this.collectionPath = collectionPath;
24
17
  this.historyLogger = historyLogger;
25
- this.setHtmlVisualizationString = setHtmlVisualizationString;
18
+ this.setVisualizations = setVisualizations;
26
19
  }
27
20
 
28
21
  _interpolate = (str) => {
@@ -31,9 +24,11 @@ class Bru {
31
24
  }
32
25
 
33
26
  const combinedVars = {
27
+ ...this.collectionVariables,
34
28
  ...this.envVariables,
29
+ ...this.folderVariables,
35
30
  ...this.requestVariables,
36
- ...this.collectionVariables,
31
+ ...this.runtimeVariables,
37
32
  process: {
38
33
  env: {
39
34
  ...this.processEnvVars
@@ -82,7 +77,7 @@ class Bru {
82
77
  }
83
78
 
84
79
  hasVar(key) {
85
- return Object.hasOwn(this.collectionVariables, key);
80
+ return Object.hasOwn(this.runtimeVariables, key);
86
81
  }
87
82
 
88
83
  setVar(key, value) {
@@ -93,7 +88,7 @@ class Bru {
93
88
  if (variableNameRegex.test(key) === false) {
94
89
  throw new Error(
95
90
  `Variable name: "${key}" contains invalid characters!` +
96
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
91
+ ' Names must only contain alpha-numeric characters, "-", "_", "."'
97
92
  );
98
93
  }
99
94
 
@@ -106,22 +101,30 @@ class Bru {
106
101
  });
107
102
  }
108
103
 
109
- this.collectionVariables[key] = value;
104
+ this.runtimeVariables[key] = value;
110
105
  }
111
106
 
112
107
  getVar(key) {
113
108
  if (variableNameRegex.test(key) === false) {
114
109
  throw new Error(
115
110
  `Variable name: "${key}" contains invalid characters!` +
116
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
111
+ ' Names must only contain alpha-numeric characters, "-", "_", "."'
117
112
  );
118
113
  }
119
114
 
120
- return this._interpolate(this.collectionVariables[key]);
115
+ return this._interpolate(this.runtimeVariables[key]);
121
116
  }
122
117
 
123
118
  deleteVar(key) {
124
- delete this.collectionVariables[key];
119
+ delete this.runtimeVariables[key];
120
+ }
121
+
122
+ getCollectionVar(key) {
123
+ return this._interpolate(this.collectionVariables[key]);
124
+ }
125
+
126
+ getFolderVar(key) {
127
+ return this._interpolate(this.folderVariables[key]);
125
128
  }
126
129
 
127
130
  getRequestVar(key) {
@@ -132,13 +135,36 @@ class Bru {
132
135
  this.nextRequest = nextRequest;
133
136
  }
134
137
 
135
- visualize(htmlString) {
136
- this.setHtmlVisualizationString(htmlString);
137
- }
138
138
 
139
139
  getSecretVar(key) {
140
140
  return this.secretVariables?.[`$secrets.${key}`];
141
141
  }
142
+
143
+
144
+ visualize(type, data) {
145
+ if (type == 'table') {
146
+ if (data?.provider == 'ag-grid') {
147
+ if (!data?.props?.columnDefinitions) {
148
+ throw new Error(`columns definitions are required`);
149
+ }
150
+ if (!data?.props?.rowData) {
151
+ throw new Error(`row data is required`);
152
+ }
153
+ this.setVisualizations({ uid: uuid(), type, data });
154
+ } else if (data?.provider == 'react-table') {
155
+ this.setVisualizations({ uid: uuid(), type, data });
156
+ }
157
+ } else if (type == 'html') {
158
+ if (!data?.content) {
159
+ throw new Error(`html content is required`);
160
+ }
161
+ this.setVisualizations({ uid: uuid(), type, data });
162
+ }
163
+ }
164
+
165
+ sleep(ms) {
166
+ return new Promise((resolve) => setTimeout(resolve, ms));
167
+ }
142
168
  }
143
169
 
144
170
  module.exports = Bru;
@@ -1,14 +1,37 @@
1
1
  const { uuid } = require('./utils');
2
2
 
3
3
  class BrunoRequest {
4
+ /**
5
+ * The following properties are available as shorthand:
6
+ * - req.url
7
+ * - req.method
8
+ * - req.headers
9
+ * - req.timeout
10
+ * - req.body
11
+ *
12
+ * Above shorthands are useful for accessing the request properties directly in the scripts
13
+ * It must be noted that the user cannot set these properties directly.
14
+ * They should use the respective setter methods to set these properties.
15
+ */
4
16
  constructor(req, historyLogger) {
5
17
  this.req = req;
6
18
  this.url = req.url;
7
19
  this.method = req.method;
8
20
  this.headers = req.headers;
9
- this.body = req.data;
10
21
  this.timeout = req.timeout;
11
22
  this.historyLogger = historyLogger;
23
+
24
+ /**
25
+ * We automatically parse the JSON body if the content type is JSON
26
+ * This is to make it easier for the user to access the body directly
27
+ *
28
+ * It must be noted that the request data is always a string and is what gets sent over the network
29
+ * If the user wants to access the raw data, they can use getBody({raw: true}) method
30
+ */
31
+ const isJson = this.hasJSONContentType(this.req.headers);
32
+ if (isJson) {
33
+ this.body = this.__safeParseJSON(req.data);
34
+ }
12
35
  }
13
36
 
14
37
  getUrl() {
@@ -16,6 +39,7 @@ class BrunoRequest {
16
39
  }
17
40
 
18
41
  setUrl(url) {
42
+ this.url = url;
19
43
  this.req.url = url;
20
44
  }
21
45
 
@@ -40,6 +64,7 @@ class BrunoRequest {
40
64
  }
41
65
 
42
66
  setMethod(method) {
67
+ this.method = method;
43
68
  this.req.method = method;
44
69
  }
45
70
 
@@ -48,6 +73,7 @@ class BrunoRequest {
48
73
  }
49
74
 
50
75
  setHeaders(headers) {
76
+ this.headers = headers;
51
77
  this.req.headers = headers;
52
78
  }
53
79
 
@@ -64,14 +90,45 @@ class BrunoRequest {
64
90
  createdAt: new Date().toISOString()
65
91
  });
66
92
  }
93
+ this.headers[name] = value;
67
94
  this.req.headers[name] = value;
68
95
  }
69
96
 
70
- getBody() {
97
+ hasJSONContentType(headers) {
98
+ const contentType = headers?.['Content-Type'] || headers?.['content-type'] || '';
99
+ return contentType.includes('json');
100
+ }
101
+
102
+ /**
103
+ * Get the body of the request
104
+ *
105
+ * We automatically parse and return the JSON body if the content type is JSON
106
+ * If the user wants the raw body, they can pass the raw option as true
107
+ */
108
+ getBody(options = {}) {
109
+ if (options.raw) {
110
+ return this.req.data;
111
+ }
112
+
113
+ const isJson = this.hasJSONContentType(this.req.headers);
114
+ if (isJson) {
115
+ return this.__safeParseJSON(this.req.data);
116
+ }
117
+
71
118
  return this.req.data;
72
119
  }
73
120
 
74
- setBody(data) {
121
+ /**
122
+ * If the content type is JSON and if the data is an object
123
+ * - We set the body property as the object itself
124
+ * - We set the request data as the stringified JSON as it is what gets sent over the network
125
+ * Otherwise
126
+ * - We set the request data as the data itself
127
+ * - We set the body property as the data itself
128
+ *
129
+ * If the user wants to override this behavior, they can pass the raw option as true
130
+ */
131
+ setBody(data, options = {}) {
75
132
  if (this.historyLogger) {
76
133
  this.historyLogger({
77
134
  uid: uuid(),
@@ -80,7 +137,22 @@ class BrunoRequest {
80
137
  createdAt: new Date().toISOString()
81
138
  });
82
139
  }
140
+
141
+ if (options.raw) {
142
+ this.req.data = data;
143
+ this.body = data;
144
+ return;
145
+ }
146
+
147
+ const isJson = this.hasJSONContentType(this.req.headers);
148
+ if (isJson && this.__isObject(data)) {
149
+ this.body = data;
150
+ this.req.data = this.__safeStringifyJSON(data);
151
+ return;
152
+ }
153
+
83
154
  this.req.data = data;
155
+ this.body = data;
84
156
  }
85
157
 
86
158
  setMaxRedirects(maxRedirects) {
@@ -92,8 +164,34 @@ class BrunoRequest {
92
164
  }
93
165
 
94
166
  setTimeout(timeout) {
167
+ this.timeout = timeout;
95
168
  this.req.timeout = timeout;
96
169
  }
170
+
171
+ __safeParseJSON(str) {
172
+ try {
173
+ return JSON.parse(str);
174
+ } catch (e) {
175
+ return str;
176
+ }
177
+ }
178
+
179
+ __safeStringifyJSON(obj) {
180
+ try {
181
+ return JSON.stringify(obj);
182
+ } catch (e) {
183
+ return obj;
184
+ }
185
+ }
186
+
187
+ __isObject(obj) {
188
+ return obj !== null && typeof obj === 'object';
189
+ }
190
+
191
+
192
+ disableParsingResponseJson() {
193
+ this.req.__brunoDisableParsingResponseJson = true;
194
+ }
97
195
  }
98
196
 
99
197
  module.exports = BrunoRequest;
@@ -2,16 +2,18 @@ const { interpolate } = require('@usebruno/common');
2
2
 
3
3
  const interpolateString = (
4
4
  str,
5
- { envVariables = {}, collectionVariables = {}, processEnvVars = {}, requestVariables = {} }
5
+ { envVariables = {}, runtimeVariables = {}, processEnvVars = {}, collectionVariables = {}, folderVariables = {}, requestVariables = {} }
6
6
  ) => {
7
7
  if (!str || !str.length || typeof str !== 'string') {
8
8
  return str;
9
9
  }
10
10
 
11
11
  const combinedVars = {
12
+ ...collectionVariables,
12
13
  ...envVariables,
14
+ ...folderVariables,
13
15
  ...requestVariables,
14
- ...collectionVariables,
16
+ ...runtimeVariables,
15
17
  process: {
16
18
  env: {
17
19
  ...processEnvVars
@@ -5,6 +5,7 @@ const Bru = require('../bru');
5
5
  const BrunoRequest = require('../bruno-request');
6
6
  const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser, uuid } = require('../utils');
7
7
  const { interpolateString } = require('../interpolate-string');
8
+ const { executeQuickJsVm } = require('../sandbox/quickjs');
8
9
 
9
10
  const { expect } = chai;
10
11
  chai.use(require('chai-string'));
@@ -161,14 +162,40 @@ const isUnaryOperator = (operator) => {
161
162
  return unaryOperators.includes(operator);
162
163
  };
163
164
 
164
- const evaluateRhsOperand = (rhsOperand, operator, context) => {
165
+ const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
166
+ if (runtime === 'quickjs') {
167
+ return executeQuickJsVm({
168
+ script: literal,
169
+ context,
170
+ scriptType: 'template-literal'
171
+ });
172
+ }
173
+
174
+ return evaluateJsTemplateLiteral(literal, context);
175
+ };
176
+
177
+ const evaluateJsExpressionBasedOnRuntime = (expr, context, runtime) => {
178
+ if (runtime === 'quickjs') {
179
+ return executeQuickJsVm({
180
+ script: expr,
181
+ context,
182
+ scriptType: 'expression'
183
+ });
184
+ }
185
+
186
+ return evaluateJsExpression(expr, context);
187
+ };
188
+
189
+ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
165
190
  if (isUnaryOperator(operator)) {
166
191
  return;
167
192
  }
168
193
 
169
194
  const interpolationContext = {
170
- requestVariables: context.bru.requestVariables,
171
195
  collectionVariables: context.bru.collectionVariables,
196
+ folderVariables: context.bru.folderVariables,
197
+ requestVariables: context.bru.requestVariables,
198
+ runtimeVariables: context.bru.runtimeVariables,
172
199
  envVariables: context.bru.envVariables,
173
200
  processEnvVars: context.bru.processEnvVars
174
201
  };
@@ -181,13 +208,17 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
181
208
 
182
209
  return rhsOperand
183
210
  .split(',')
184
- .map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), interpolationContext), context));
211
+ .map((v) =>
212
+ evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
213
+ );
185
214
  }
186
215
 
187
216
  if (operator === 'between') {
188
217
  const [lhs, rhs] = rhsOperand
189
218
  .split(',')
190
- .map((v) => evaluateJsTemplateLiteral(interpolateString(v.trim(), interpolationContext), context));
219
+ .map((v) =>
220
+ evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
221
+ );
191
222
  return [lhs, rhs];
192
223
  }
193
224
 
@@ -200,20 +231,17 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
200
231
  return interpolateString(rhsOperand, interpolationContext);
201
232
  }
202
233
 
203
- return evaluateJsTemplateLiteral(interpolateString(rhsOperand, interpolationContext), context);
234
+ return evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(rhsOperand, interpolationContext), context, runtime);
204
235
  };
205
236
 
206
237
  class AssertRuntime {
207
- runAssertions(
208
- assertions,
209
- request,
210
- response,
211
- envVariables,
212
- collectionVariables,
213
- processEnvVars,
214
- historyLogger,
215
- secretVariables
216
- ) {
238
+ constructor(props) {
239
+ this.runtime = props?.runtime || 'vm2';
240
+ }
241
+
242
+ runAssertions(assertions, request, response, envVariables, runtimeVariables, processEnvVars, historyLogger, secretVariables) {
243
+ const collectionVariables = request?.collectionVariables || {};
244
+ const folderVariables = request?.folderVariables || {};
217
245
  const requestVariables = request?.requestVariables || {};
218
246
  const enabledAssertions = _.filter(assertions, (a) => a.enabled);
219
247
  if (!enabledAssertions.length) {
@@ -222,12 +250,14 @@ class AssertRuntime {
222
250
 
223
251
  const bru = new Bru(
224
252
  envVariables,
225
- collectionVariables,
253
+ runtimeVariables,
226
254
  processEnvVars,
227
255
  undefined, // collectionPath,
228
256
  undefined, // historyLogger,
229
- undefined, // setHtmlVisualizationString,
257
+ undefined, // setVisualizations,
230
258
  secretVariables,
259
+ collectionVariables,
260
+ folderVariables,
231
261
  requestVariables
232
262
  );
233
263
  const req = new BrunoRequest(request, historyLogger);
@@ -240,9 +270,11 @@ class AssertRuntime {
240
270
  };
241
271
 
242
272
  const context = {
273
+ ...collectionVariables,
243
274
  ...envVariables,
275
+ ...folderVariables,
244
276
  ...requestVariables,
245
- ...collectionVariables,
277
+ ...runtimeVariables,
246
278
  ...processEnvVars,
247
279
  ...bruContext
248
280
  };
@@ -256,8 +288,8 @@ class AssertRuntime {
256
288
  const { operator, value: rhsOperand } = parseAssertionOperator(rhsExpr);
257
289
 
258
290
  try {
259
- const lhs = evaluateJsExpression(lhsExpr, context);
260
- const rhs = evaluateRhsOperand(rhsOperand, operator, context);
291
+ const lhs = evaluateJsExpressionBasedOnRuntime(lhsExpr, context, this.runtime);
292
+ const rhs = evaluateRhsOperand(rhsOperand, operator, context, this.runtime);
261
293
 
262
294
  switch (operator) {
263
295
  case 'eq':
@@ -27,10 +27,13 @@ const axios = require('axios');
27
27
  const fetch = require('node-fetch');
28
28
  const chai = require('chai');
29
29
  const CryptoJS = require('crypto-js');
30
- const NodeSecrets = require('node-vault');
30
+ const NodeVault = require('node-vault');
31
+ const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
31
32
 
32
33
  class ScriptRuntime {
33
- constructor() {}
34
+ constructor(props) {
35
+ this.runtime = props?.runtime || 'vm2';
36
+ }
34
37
 
35
38
  // This approach is getting out of hand
36
39
  // Need to refactor this to use a single arg (object) instead of 7
@@ -38,7 +41,7 @@ class ScriptRuntime {
38
41
  script,
39
42
  request,
40
43
  envVariables,
41
- collectionVariables,
44
+ runtimeVariables,
42
45
  collectionPath,
43
46
  onConsoleLog,
44
47
  processEnvVars,
@@ -46,21 +49,14 @@ class ScriptRuntime {
46
49
  historyLogger,
47
50
  secretVariables
48
51
  ) {
49
- let htmlVisualizationString;
50
- let setHtmlVisualizationString = (htmlString) => {
51
- htmlVisualizationString = htmlString;
52
- };
52
+ let visualizations = [];
53
+ let setVisualizations = (data) => {
54
+ visualizations.push(data);
55
+ }
56
+ const collectionVariables = request?.collectionVariables || {};
57
+ const folderVariables = request?.folderVariables || {};
53
58
  const requestVariables = request?.requestVariables || {};
54
- const bru = new Bru(
55
- envVariables,
56
- collectionVariables,
57
- processEnvVars,
58
- collectionPath,
59
- historyLogger,
60
- setHtmlVisualizationString,
61
- secretVariables,
62
- requestVariables
63
- );
59
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables);
64
60
  const req = new BrunoRequest(request, historyLogger);
65
61
  const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
66
62
  const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
@@ -101,6 +97,23 @@ class ScriptRuntime {
101
97
  };
102
98
  }
103
99
 
100
+ if (this.runtime === 'quickjs') {
101
+ await executeQuickJsVmAsync({
102
+ script: script,
103
+ context: context,
104
+ collectionPath
105
+ });
106
+
107
+ return {
108
+ request,
109
+ envVariables: cleanJson(envVariables),
110
+ runtimeVariables: cleanJson(runtimeVariables),
111
+ visualizations,
112
+ nextRequestName: bru.nextRequest
113
+ };
114
+ }
115
+
116
+ // default runtime is vm2
104
117
  const vm = new NodeVM({
105
118
  sandbox: context,
106
119
  require: {
@@ -132,17 +145,18 @@ class ScriptRuntime {
132
145
  'crypto-js': CryptoJS,
133
146
  ...whitelistedModules,
134
147
  fs: allowScriptFilesystemAccess ? fs : undefined,
135
- 'node-vault': NodeSecrets
148
+ 'node-vault': NodeVault
136
149
  }
137
150
  }
138
151
  });
139
152
  const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
140
153
  await asyncVM();
154
+
141
155
  return {
142
156
  request,
143
157
  envVariables: cleanJson(envVariables),
144
- collectionVariables: cleanJson(collectionVariables),
145
- htmlVisualizationString,
158
+ runtimeVariables: cleanJson(runtimeVariables),
159
+ visualizations,
146
160
  nextRequestName: bru.nextRequest
147
161
  };
148
162
  }
@@ -152,7 +166,7 @@ class ScriptRuntime {
152
166
  request,
153
167
  response,
154
168
  envVariables,
155
- collectionVariables,
169
+ runtimeVariables,
156
170
  collectionPath,
157
171
  onConsoleLog,
158
172
  processEnvVars,
@@ -160,21 +174,14 @@ class ScriptRuntime {
160
174
  historyLogger,
161
175
  secretVariables
162
176
  ) {
163
- let htmlVisualizationString;
164
- let setHtmlVisualizationString = (htmlString) => {
165
- htmlVisualizationString = htmlString;
166
- };
177
+ let visualizations = [];
178
+ let setVisualizations = (data) => {
179
+ visualizations.push(data);
180
+ }
181
+ const collectionVariables = request?.collectionVariables || {};
182
+ const folderVariables = request?.folderVariables || {};
167
183
  const requestVariables = request?.requestVariables || {};
168
- const bru = new Bru(
169
- envVariables,
170
- collectionVariables,
171
- processEnvVars,
172
- collectionPath,
173
- historyLogger,
174
- setHtmlVisualizationString,
175
- secretVariables,
176
- requestVariables
177
- );
184
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables);
178
185
  const req = new BrunoRequest(request, historyLogger);
179
186
  const res = new BrunoResponse(response);
180
187
  const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
@@ -207,10 +214,28 @@ class ScriptRuntime {
207
214
  log: customLogger('log'),
208
215
  info: customLogger('info'),
209
216
  warn: customLogger('warn'),
210
- error: customLogger('error')
217
+ error: customLogger('error'),
218
+ debug: customLogger('debug')
219
+ };
220
+ }
221
+
222
+ if (this.runtime === 'quickjs') {
223
+ await executeQuickJsVmAsync({
224
+ script: script,
225
+ context: context,
226
+ collectionPath
227
+ });
228
+
229
+ return {
230
+ response,
231
+ envVariables: cleanJson(envVariables),
232
+ runtimeVariables: cleanJson(runtimeVariables),
233
+ visualizations,
234
+ nextRequestName: bru.nextRequest
211
235
  };
212
236
  }
213
237
 
238
+ // default runtime is vm2
214
239
  const vm = new NodeVM({
215
240
  sandbox: context,
216
241
  require: {
@@ -241,7 +266,7 @@ class ScriptRuntime {
241
266
  'crypto-js': CryptoJS,
242
267
  ...whitelistedModules,
243
268
  fs: allowScriptFilesystemAccess ? fs : undefined,
244
- 'node-vault': NodeSecrets
269
+ 'node-vault': NodeVault
245
270
  }
246
271
  }
247
272
  });
@@ -252,8 +277,8 @@ class ScriptRuntime {
252
277
  return {
253
278
  response,
254
279
  envVariables: cleanJson(envVariables),
255
- collectionVariables: cleanJson(collectionVariables),
256
- htmlVisualizationString,
280
+ runtimeVariables: cleanJson(runtimeVariables),
281
+ visualizations,
257
282
  nextRequestName: bru.nextRequest
258
283
  };
259
284
  }